[Midnightbsd-cvs] src [10219] trunk/sys/arm: add arm
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sat Jun 2 11:44:29 EDT 2018
Revision: 10219
http://svnweb.midnightbsd.org/src/?rev=10219
Author: laffer1
Date: 2018-06-02 11:44:28 -0400 (Sat, 02 Jun 2018)
Log Message:
-----------
add arm
Added Paths:
-----------
trunk/sys/arm/
trunk/sys/arm/allwinner/
trunk/sys/arm/allwinner/a10_clk.c
trunk/sys/arm/allwinner/a10_clk.h
trunk/sys/arm/allwinner/a10_common.c
trunk/sys/arm/allwinner/a10_ehci.c
trunk/sys/arm/allwinner/a10_gpio.c
trunk/sys/arm/allwinner/a10_gpio.h
trunk/sys/arm/allwinner/a10_machdep.c
trunk/sys/arm/allwinner/a10_sramc.c
trunk/sys/arm/allwinner/a10_sramc.h
trunk/sys/arm/allwinner/a10_wdog.c
trunk/sys/arm/allwinner/a10_wdog.h
trunk/sys/arm/allwinner/a20/
trunk/sys/arm/allwinner/a20/a20_cpu_cfg.c
trunk/sys/arm/allwinner/a20/a20_cpu_cfg.h
trunk/sys/arm/allwinner/a20/a20_mp.c
trunk/sys/arm/allwinner/a20/files.a20
trunk/sys/arm/allwinner/a20/std.a20
trunk/sys/arm/allwinner/aintc.c
trunk/sys/arm/allwinner/console.c
trunk/sys/arm/allwinner/files.a10
trunk/sys/arm/allwinner/if_emac.c
trunk/sys/arm/allwinner/if_emacreg.h
trunk/sys/arm/allwinner/std.a10
trunk/sys/arm/allwinner/timer.c
trunk/sys/arm/arm/
trunk/sys/arm/arm/autoconf.c
trunk/sys/arm/arm/bcopy_page.S
trunk/sys/arm/arm/bcopyinout.S
trunk/sys/arm/arm/bcopyinout_xscale.S
trunk/sys/arm/arm/blockio.S
trunk/sys/arm/arm/bootconfig.c
trunk/sys/arm/arm/bus_space_asm_generic.S
trunk/sys/arm/arm/bus_space_base.c
trunk/sys/arm/arm/bus_space_generic.c
trunk/sys/arm/arm/busdma_machdep-v6.c
trunk/sys/arm/arm/busdma_machdep.c
trunk/sys/arm/arm/copystr.S
trunk/sys/arm/arm/cpu_asm-v6.S
trunk/sys/arm/arm/cpufunc.c
trunk/sys/arm/arm/cpufunc_asm.S
trunk/sys/arm/arm/cpufunc_asm_arm10.S
trunk/sys/arm/arm/cpufunc_asm_arm11.S
trunk/sys/arm/arm/cpufunc_asm_arm11x6.S
trunk/sys/arm/arm/cpufunc_asm_arm9.S
trunk/sys/arm/arm/cpufunc_asm_armv4.S
trunk/sys/arm/arm/cpufunc_asm_armv5.S
trunk/sys/arm/arm/cpufunc_asm_armv5_ec.S
trunk/sys/arm/arm/cpufunc_asm_armv6.S
trunk/sys/arm/arm/cpufunc_asm_armv7.S
trunk/sys/arm/arm/cpufunc_asm_fa526.S
trunk/sys/arm/arm/cpufunc_asm_pj4b.S
trunk/sys/arm/arm/cpufunc_asm_sheeva.S
trunk/sys/arm/arm/cpufunc_asm_xscale.S
trunk/sys/arm/arm/cpufunc_asm_xscale_c3.S
trunk/sys/arm/arm/cpuinfo.c
trunk/sys/arm/arm/db_disasm.c
trunk/sys/arm/arm/db_interface.c
trunk/sys/arm/arm/db_trace.c
trunk/sys/arm/arm/devmap.c
trunk/sys/arm/arm/disassem.c
trunk/sys/arm/arm/dump_machdep.c
trunk/sys/arm/arm/elf_machdep.c
trunk/sys/arm/arm/elf_trampoline.c
trunk/sys/arm/arm/exception.S
trunk/sys/arm/arm/fiq.c
trunk/sys/arm/arm/fiq_subr.S
trunk/sys/arm/arm/fusu.S
trunk/sys/arm/arm/gdb_machdep.c
trunk/sys/arm/arm/genassym.c
trunk/sys/arm/arm/generic_timer.c
trunk/sys/arm/arm/gic.c
trunk/sys/arm/arm/identcpu.c
trunk/sys/arm/arm/in_cksum.c
trunk/sys/arm/arm/in_cksum_arm.S
trunk/sys/arm/arm/inckern.S
trunk/sys/arm/arm/intr.c
trunk/sys/arm/arm/locore-v4.S
trunk/sys/arm/arm/locore-v6.S
trunk/sys/arm/arm/locore.S
trunk/sys/arm/arm/machdep.c
trunk/sys/arm/arm/mem.c
trunk/sys/arm/arm/minidump_machdep.c
trunk/sys/arm/arm/mp_machdep.c
trunk/sys/arm/arm/mpcore_timer.c
trunk/sys/arm/arm/mpcore_timervar.h
trunk/sys/arm/arm/nexus.c
trunk/sys/arm/arm/physmem.c
trunk/sys/arm/arm/pl190.c
trunk/sys/arm/arm/pl310.c
trunk/sys/arm/arm/pmap-v6.c
trunk/sys/arm/arm/pmap.c
trunk/sys/arm/arm/sc_machdep.c
trunk/sys/arm/arm/setcpsr.S
trunk/sys/arm/arm/setstack.s
trunk/sys/arm/arm/stack_machdep.c
trunk/sys/arm/arm/stdatomic.c
trunk/sys/arm/arm/support.S
trunk/sys/arm/arm/swtch.S
trunk/sys/arm/arm/sys_machdep.c
trunk/sys/arm/arm/syscall.c
trunk/sys/arm/arm/trap-v6.c
trunk/sys/arm/arm/trap.c
trunk/sys/arm/arm/uio_machdep.c
trunk/sys/arm/arm/undefined.c
trunk/sys/arm/arm/vfp.c
trunk/sys/arm/arm/vm_machdep.c
trunk/sys/arm/at91/
trunk/sys/arm/at91/at91.c
trunk/sys/arm/at91/at91_aic.c
trunk/sys/arm/at91/at91_aicreg.h
trunk/sys/arm/at91/at91_cfata.c
trunk/sys/arm/at91/at91_gpio.h
trunk/sys/arm/at91/at91_machdep.c
trunk/sys/arm/at91/at91_mci.c
trunk/sys/arm/at91/at91_mcireg.h
trunk/sys/arm/at91/at91_pdcreg.h
trunk/sys/arm/at91/at91_pinctrl.c
trunk/sys/arm/at91/at91_pio.c
trunk/sys/arm/at91/at91_pio_sam9g20.h
trunk/sys/arm/at91/at91_pio_sam9g45.h
trunk/sys/arm/at91/at91_pioreg.h
trunk/sys/arm/at91/at91_piovar.h
trunk/sys/arm/at91/at91_pit.c
trunk/sys/arm/at91/at91_pitreg.h
trunk/sys/arm/at91/at91_pmc.c
trunk/sys/arm/at91/at91_pmcreg.h
trunk/sys/arm/at91/at91_pmcvar.h
trunk/sys/arm/at91/at91_reset.S
trunk/sys/arm/at91/at91_rst.c
trunk/sys/arm/at91/at91_rstreg.h
trunk/sys/arm/at91/at91_rtc.c
trunk/sys/arm/at91/at91_rtcreg.h
trunk/sys/arm/at91/at91_sdramc.c
trunk/sys/arm/at91/at91_shdwc.c
trunk/sys/arm/at91/at91_smc.c
trunk/sys/arm/at91/at91_smc.h
trunk/sys/arm/at91/at91_spi.c
trunk/sys/arm/at91/at91_spireg.h
trunk/sys/arm/at91/at91_ssc.c
trunk/sys/arm/at91/at91_sscreg.h
trunk/sys/arm/at91/at91_st.c
trunk/sys/arm/at91/at91_streg.h
trunk/sys/arm/at91/at91_tcb.c
trunk/sys/arm/at91/at91_twi.c
trunk/sys/arm/at91/at91_twiio.h
trunk/sys/arm/at91/at91_twireg.h
trunk/sys/arm/at91/at91_usartreg.h
trunk/sys/arm/at91/at91_wdt.c
trunk/sys/arm/at91/at91_wdtreg.h
trunk/sys/arm/at91/at91board.h
trunk/sys/arm/at91/at91reg.h
trunk/sys/arm/at91/at91rm9200.c
trunk/sys/arm/at91/at91rm9200_devices.c
trunk/sys/arm/at91/at91rm9200var.h
trunk/sys/arm/at91/at91rm92reg.h
trunk/sys/arm/at91/at91sam9260.c
trunk/sys/arm/at91/at91sam9260reg.h
trunk/sys/arm/at91/at91sam9g20.c
trunk/sys/arm/at91/at91sam9g20reg.h
trunk/sys/arm/at91/at91sam9g45.c
trunk/sys/arm/at91/at91sam9g45reg.h
trunk/sys/arm/at91/at91sam9x5.c
trunk/sys/arm/at91/at91sam9x5reg.h
trunk/sys/arm/at91/at91soc.c
trunk/sys/arm/at91/at91soc.h
trunk/sys/arm/at91/at91var.h
trunk/sys/arm/at91/board_bwct.c
trunk/sys/arm/at91/board_eb9200.c
trunk/sys/arm/at91/board_ethernut5.c
trunk/sys/arm/at91/board_hl200.c
trunk/sys/arm/at91/board_hl201.c
trunk/sys/arm/at91/board_kb920x.c
trunk/sys/arm/at91/board_qila9g20.c
trunk/sys/arm/at91/board_sam9260ek.c
trunk/sys/arm/at91/board_sam9g20ek.c
trunk/sys/arm/at91/board_sam9x25ek.c
trunk/sys/arm/at91/board_sn9g45.c
trunk/sys/arm/at91/board_tsc4370.c
trunk/sys/arm/at91/files.at91
trunk/sys/arm/at91/if_ate.c
trunk/sys/arm/at91/if_atereg.h
trunk/sys/arm/at91/if_macb.c
trunk/sys/arm/at91/if_macbreg.h
trunk/sys/arm/at91/if_macbvar.h
trunk/sys/arm/at91/std.at91
trunk/sys/arm/at91/std.at91sam9
trunk/sys/arm/at91/std.at91sam9g45
trunk/sys/arm/at91/std.atmel
trunk/sys/arm/at91/std.bwct
trunk/sys/arm/at91/std.eb9200
trunk/sys/arm/at91/std.ethernut5
trunk/sys/arm/at91/std.hl200
trunk/sys/arm/at91/std.hl201
trunk/sys/arm/at91/std.kb920x
trunk/sys/arm/at91/std.qila9g20
trunk/sys/arm/at91/std.sam9260ek
trunk/sys/arm/at91/std.sam9g20ek
trunk/sys/arm/at91/std.sam9x25ek
trunk/sys/arm/at91/std.sn9g45
trunk/sys/arm/at91/std.tsc4370
trunk/sys/arm/at91/uart_bus_at91usart.c
trunk/sys/arm/at91/uart_cpu_at91usart.c
trunk/sys/arm/at91/uart_dev_at91usart.c
trunk/sys/arm/broadcom/
trunk/sys/arm/broadcom/bcm2835/
trunk/sys/arm/broadcom/bcm2835/bcm2835_bsc.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_bscreg.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_common.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_fb.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_intr.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_spi.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_spireg.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_spivar.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.c
trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.h
trunk/sys/arm/broadcom/bcm2835/bcm2836.c
trunk/sys/arm/broadcom/bcm2835/bcm2836.h
trunk/sys/arm/broadcom/bcm2835/bcm283x_dwc_fdt.c
trunk/sys/arm/broadcom/bcm2835/files.bcm2835
trunk/sys/arm/broadcom/bcm2835/files.bcm2836
trunk/sys/arm/broadcom/bcm2835/std.bcm2835
trunk/sys/arm/broadcom/bcm2835/std.bcm2836
trunk/sys/arm/broadcom/bcm2835/std.rpi
trunk/sys/arm/cavium/
trunk/sys/arm/cavium/cns11xx/
trunk/sys/arm/cavium/cns11xx/cfi_bus_econa.c
trunk/sys/arm/cavium/cns11xx/econa.c
trunk/sys/arm/cavium/cns11xx/econa_machdep.c
trunk/sys/arm/cavium/cns11xx/econa_reg.h
trunk/sys/arm/cavium/cns11xx/econa_var.h
trunk/sys/arm/cavium/cns11xx/ehci_ebus.c
trunk/sys/arm/cavium/cns11xx/files.econa
trunk/sys/arm/cavium/cns11xx/if_ece.c
trunk/sys/arm/cavium/cns11xx/if_ecereg.h
trunk/sys/arm/cavium/cns11xx/if_ecevar.h
trunk/sys/arm/cavium/cns11xx/ohci_ec.c
trunk/sys/arm/cavium/cns11xx/std.econa
trunk/sys/arm/cavium/cns11xx/timer.c
trunk/sys/arm/cavium/cns11xx/uart_bus_ec.c
trunk/sys/arm/cavium/cns11xx/uart_cpu_ec.c
trunk/sys/arm/compile/
trunk/sys/arm/conf/
trunk/sys/arm/conf/APALIS-IMX6
trunk/sys/arm/conf/ARMADAXP
trunk/sys/arm/conf/ARNDALE
trunk/sys/arm/conf/ARNDALE-OCTA
trunk/sys/arm/conf/ATMEL
trunk/sys/arm/conf/AVILA
trunk/sys/arm/conf/AVILA.hints
trunk/sys/arm/conf/BEAGLEBONE
trunk/sys/arm/conf/BWCT
trunk/sys/arm/conf/BWCT.hints
trunk/sys/arm/conf/CAMBRIA
trunk/sys/arm/conf/CAMBRIA.hints
trunk/sys/arm/conf/CHROMEBOOK
trunk/sys/arm/conf/CHROMEBOOK.hints
trunk/sys/arm/conf/CNS11XXNAS
trunk/sys/arm/conf/COLIBRI-VF50
trunk/sys/arm/conf/COSMIC
trunk/sys/arm/conf/CRB
trunk/sys/arm/conf/CUBIEBOARD
trunk/sys/arm/conf/CUBIEBOARD2
trunk/sys/arm/conf/DB-78XXX
trunk/sys/arm/conf/DB-88F5XXX
trunk/sys/arm/conf/DB-88F6XXX
trunk/sys/arm/conf/DEFAULTS
trunk/sys/arm/conf/DIGI-CCWMX53
trunk/sys/arm/conf/DOCKSTAR
trunk/sys/arm/conf/DREAMPLUG-1001
trunk/sys/arm/conf/EA3250
trunk/sys/arm/conf/EA3250.hints
trunk/sys/arm/conf/EB9200
trunk/sys/arm/conf/EB9200.hints
trunk/sys/arm/conf/EFIKA_MX
trunk/sys/arm/conf/EP80219
trunk/sys/arm/conf/ETHERNUT5
trunk/sys/arm/conf/ETHERNUT5.hints
trunk/sys/arm/conf/EXYNOS5.common
trunk/sys/arm/conf/EXYNOS5250
trunk/sys/arm/conf/EXYNOS5250.common
trunk/sys/arm/conf/EXYNOS5420
trunk/sys/arm/conf/GUMSTIX
trunk/sys/arm/conf/GUMSTIX-QEMU
trunk/sys/arm/conf/GUMSTIX.hints
trunk/sys/arm/conf/HL200
trunk/sys/arm/conf/HL201
trunk/sys/arm/conf/HL201.hints
trunk/sys/arm/conf/IMX53
trunk/sys/arm/conf/IMX53-QSB
trunk/sys/arm/conf/IMX6
trunk/sys/arm/conf/IQ31244
trunk/sys/arm/conf/KB920X
trunk/sys/arm/conf/KB920X.hints
trunk/sys/arm/conf/LN2410SBC
trunk/sys/arm/conf/Makefile
trunk/sys/arm/conf/NOTES
trunk/sys/arm/conf/NSLU
trunk/sys/arm/conf/NSLU.hints
trunk/sys/arm/conf/PANDABOARD
trunk/sys/arm/conf/PANDABOARD.hints
trunk/sys/arm/conf/QILA9G20
trunk/sys/arm/conf/QILA9G20.hints
trunk/sys/arm/conf/QUARTZ
trunk/sys/arm/conf/RADXA
trunk/sys/arm/conf/RPI-B
trunk/sys/arm/conf/SAM9260EK
trunk/sys/arm/conf/SAM9260EK.hints
trunk/sys/arm/conf/SAM9G20EK
trunk/sys/arm/conf/SAM9G20EK.hints
trunk/sys/arm/conf/SAM9X25EK
trunk/sys/arm/conf/SAM9X25EK.hints
trunk/sys/arm/conf/SHEEVAPLUG
trunk/sys/arm/conf/SN9G45
trunk/sys/arm/conf/TS7800
trunk/sys/arm/conf/VERSATILEPB
trunk/sys/arm/conf/VYBRID
trunk/sys/arm/conf/ZEDBOARD
trunk/sys/arm/conf/genboardid.awk
trunk/sys/arm/conf/mach-types
trunk/sys/arm/freescale/
trunk/sys/arm/freescale/fsl_ocotp.c
trunk/sys/arm/freescale/fsl_ocotpreg.h
trunk/sys/arm/freescale/fsl_ocotpvar.h
trunk/sys/arm/freescale/imx/
trunk/sys/arm/freescale/imx/console.c
trunk/sys/arm/freescale/imx/files.imx51
trunk/sys/arm/freescale/imx/files.imx53
trunk/sys/arm/freescale/imx/files.imx6
trunk/sys/arm/freescale/imx/imx51_ccm.c
trunk/sys/arm/freescale/imx/imx51_ccmreg.h
trunk/sys/arm/freescale/imx/imx51_ccmvar.h
trunk/sys/arm/freescale/imx/imx51_dpllreg.h
trunk/sys/arm/freescale/imx/imx51_ipuv3.c
trunk/sys/arm/freescale/imx/imx51_ipuv3_fbd.c
trunk/sys/arm/freescale/imx/imx51_ipuv3reg.h
trunk/sys/arm/freescale/imx/imx51_machdep.c
trunk/sys/arm/freescale/imx/imx51_sdmareg.h
trunk/sys/arm/freescale/imx/imx51_ssireg.h
trunk/sys/arm/freescale/imx/imx51_tzicreg.h
trunk/sys/arm/freescale/imx/imx53_machdep.c
trunk/sys/arm/freescale/imx/imx6_anatop.c
trunk/sys/arm/freescale/imx/imx6_anatopreg.h
trunk/sys/arm/freescale/imx/imx6_anatopvar.h
trunk/sys/arm/freescale/imx/imx6_audmux.c
trunk/sys/arm/freescale/imx/imx6_ccm.c
trunk/sys/arm/freescale/imx/imx6_ccmreg.h
trunk/sys/arm/freescale/imx/imx6_machdep.c
trunk/sys/arm/freescale/imx/imx6_mp.c
trunk/sys/arm/freescale/imx/imx6_pl310.c
trunk/sys/arm/freescale/imx/imx6_sdma.c
trunk/sys/arm/freescale/imx/imx6_sdma.h
trunk/sys/arm/freescale/imx/imx6_ssi.c
trunk/sys/arm/freescale/imx/imx6_usbphy.c
trunk/sys/arm/freescale/imx/imx_ccmvar.h
trunk/sys/arm/freescale/imx/imx_common.c
trunk/sys/arm/freescale/imx/imx_gpio.c
trunk/sys/arm/freescale/imx/imx_gpt.c
trunk/sys/arm/freescale/imx/imx_gptreg.h
trunk/sys/arm/freescale/imx/imx_gptvar.h
trunk/sys/arm/freescale/imx/imx_i2c.c
trunk/sys/arm/freescale/imx/imx_iomux.c
trunk/sys/arm/freescale/imx/imx_iomuxvar.h
trunk/sys/arm/freescale/imx/imx_machdep.c
trunk/sys/arm/freescale/imx/imx_machdep.h
trunk/sys/arm/freescale/imx/imx_nop_usbphy.c
trunk/sys/arm/freescale/imx/imx_sdhci.c
trunk/sys/arm/freescale/imx/imx_wdog.c
trunk/sys/arm/freescale/imx/imx_wdogreg.h
trunk/sys/arm/freescale/imx/std.imx51
trunk/sys/arm/freescale/imx/std.imx53
trunk/sys/arm/freescale/imx/std.imx6
trunk/sys/arm/freescale/imx/tzic.c
trunk/sys/arm/freescale/vybrid/
trunk/sys/arm/freescale/vybrid/files.vybrid
trunk/sys/arm/freescale/vybrid/std.vybrid
trunk/sys/arm/freescale/vybrid/vf_anadig.c
trunk/sys/arm/freescale/vybrid/vf_ccm.c
trunk/sys/arm/freescale/vybrid/vf_common.c
trunk/sys/arm/freescale/vybrid/vf_common.h
trunk/sys/arm/freescale/vybrid/vf_dcu4.c
trunk/sys/arm/freescale/vybrid/vf_dmamux.c
trunk/sys/arm/freescale/vybrid/vf_dmamux.h
trunk/sys/arm/freescale/vybrid/vf_edma.c
trunk/sys/arm/freescale/vybrid/vf_edma.h
trunk/sys/arm/freescale/vybrid/vf_ehci.c
trunk/sys/arm/freescale/vybrid/vf_gpio.c
trunk/sys/arm/freescale/vybrid/vf_i2c.c
trunk/sys/arm/freescale/vybrid/vf_iomuxc.c
trunk/sys/arm/freescale/vybrid/vf_iomuxc.h
trunk/sys/arm/freescale/vybrid/vf_machdep.c
trunk/sys/arm/freescale/vybrid/vf_mscm.c
trunk/sys/arm/freescale/vybrid/vf_nfc.c
trunk/sys/arm/freescale/vybrid/vf_port.c
trunk/sys/arm/freescale/vybrid/vf_port.h
trunk/sys/arm/freescale/vybrid/vf_sai.c
trunk/sys/arm/freescale/vybrid/vf_src.c
trunk/sys/arm/freescale/vybrid/vf_src.h
trunk/sys/arm/freescale/vybrid/vf_tcon.c
trunk/sys/arm/freescale/vybrid/vf_uart.c
trunk/sys/arm/include/
trunk/sys/arm/include/_align.h
trunk/sys/arm/include/_bus.h
trunk/sys/arm/include/_inttypes.h
trunk/sys/arm/include/_limits.h
trunk/sys/arm/include/_stdint.h
trunk/sys/arm/include/_types.h
trunk/sys/arm/include/acle-compat.h
trunk/sys/arm/include/armreg.h
trunk/sys/arm/include/asm.h
trunk/sys/arm/include/asmacros.h
trunk/sys/arm/include/at91_gpio.h
trunk/sys/arm/include/atags.h
trunk/sys/arm/include/atomic.h
trunk/sys/arm/include/blockio.h
trunk/sys/arm/include/board.h
trunk/sys/arm/include/bootconfig.h
trunk/sys/arm/include/bus.h
trunk/sys/arm/include/bus_dma.h
trunk/sys/arm/include/clock.h
trunk/sys/arm/include/counter.h
trunk/sys/arm/include/cpu-v6.h
trunk/sys/arm/include/cpu.h
trunk/sys/arm/include/cpuconf.h
trunk/sys/arm/include/cpufunc.h
trunk/sys/arm/include/cpuinfo.h
trunk/sys/arm/include/db_machdep.h
trunk/sys/arm/include/devmap.h
trunk/sys/arm/include/disassem.h
trunk/sys/arm/include/elf.h
trunk/sys/arm/include/endian.h
trunk/sys/arm/include/exec.h
trunk/sys/arm/include/fdt.h
trunk/sys/arm/include/fiq.h
trunk/sys/arm/include/float.h
trunk/sys/arm/include/floatingpoint.h
trunk/sys/arm/include/fp.h
trunk/sys/arm/include/frame.h
trunk/sys/arm/include/gdb_machdep.h
trunk/sys/arm/include/ieee.h
trunk/sys/arm/include/ieeefp.h
trunk/sys/arm/include/in_cksum.h
trunk/sys/arm/include/intr.h
trunk/sys/arm/include/katelib.h
trunk/sys/arm/include/kdb.h
trunk/sys/arm/include/limits.h
trunk/sys/arm/include/machdep.h
trunk/sys/arm/include/md_var.h
trunk/sys/arm/include/memdev.h
trunk/sys/arm/include/metadata.h
trunk/sys/arm/include/minidump.h
trunk/sys/arm/include/ofw_machdep.h
trunk/sys/arm/include/param.h
trunk/sys/arm/include/pcb.h
trunk/sys/arm/include/pcpu.h
trunk/sys/arm/include/physmem.h
trunk/sys/arm/include/pl310.h
trunk/sys/arm/include/pmap.h
trunk/sys/arm/include/pmc_mdep.h
trunk/sys/arm/include/proc.h
trunk/sys/arm/include/profile.h
trunk/sys/arm/include/psl.h
trunk/sys/arm/include/pte.h
trunk/sys/arm/include/ptrace.h
trunk/sys/arm/include/reg.h
trunk/sys/arm/include/reloc.h
trunk/sys/arm/include/resource.h
trunk/sys/arm/include/runq.h
trunk/sys/arm/include/sc_machdep.h
trunk/sys/arm/include/setjmp.h
trunk/sys/arm/include/sf_buf.h
trunk/sys/arm/include/sigframe.h
trunk/sys/arm/include/signal.h
trunk/sys/arm/include/smp.h
trunk/sys/arm/include/stack.h
trunk/sys/arm/include/stdarg.h
trunk/sys/arm/include/swi.h
trunk/sys/arm/include/sysarch.h
trunk/sys/arm/include/sysreg.h
trunk/sys/arm/include/trap.h
trunk/sys/arm/include/ucontext.h
trunk/sys/arm/include/undefined.h
trunk/sys/arm/include/utrap.h
trunk/sys/arm/include/vdso.h
trunk/sys/arm/include/vfp.h
trunk/sys/arm/include/vm.h
trunk/sys/arm/include/vmparam.h
trunk/sys/arm/lpc/
trunk/sys/arm/lpc/files.lpc
trunk/sys/arm/lpc/if_lpe.c
trunk/sys/arm/lpc/if_lpereg.h
trunk/sys/arm/lpc/lpc_dmac.c
trunk/sys/arm/lpc/lpc_fb.c
trunk/sys/arm/lpc/lpc_gpio.c
trunk/sys/arm/lpc/lpc_intc.c
trunk/sys/arm/lpc/lpc_machdep.c
trunk/sys/arm/lpc/lpc_mmc.c
trunk/sys/arm/lpc/lpc_ohci.c
trunk/sys/arm/lpc/lpc_pll.c
trunk/sys/arm/lpc/lpc_pwr.c
trunk/sys/arm/lpc/lpc_rtc.c
trunk/sys/arm/lpc/lpc_spi.c
trunk/sys/arm/lpc/lpc_timer.c
trunk/sys/arm/lpc/lpcreg.h
trunk/sys/arm/lpc/lpcvar.h
trunk/sys/arm/lpc/ssd1289.c
trunk/sys/arm/lpc/std.lpc
trunk/sys/arm/mv/
trunk/sys/arm/mv/armadaxp/
trunk/sys/arm/mv/armadaxp/armadaxp.c
trunk/sys/arm/mv/armadaxp/armadaxp_mp.c
trunk/sys/arm/mv/armadaxp/files.armadaxp
trunk/sys/arm/mv/armadaxp/mptramp.S
trunk/sys/arm/mv/armadaxp/std.armadaxp
trunk/sys/arm/mv/armadaxp/std.mv78x60
trunk/sys/arm/mv/discovery/
trunk/sys/arm/mv/discovery/discovery.c
trunk/sys/arm/mv/discovery/files.db78xxx
trunk/sys/arm/mv/discovery/std.db78xxx
trunk/sys/arm/mv/files.mv
trunk/sys/arm/mv/gpio.c
trunk/sys/arm/mv/ic.c
trunk/sys/arm/mv/kirkwood/
trunk/sys/arm/mv/kirkwood/files.kirkwood
trunk/sys/arm/mv/kirkwood/kirkwood.c
trunk/sys/arm/mv/kirkwood/std.db88f6xxx
trunk/sys/arm/mv/kirkwood/std.kirkwood
trunk/sys/arm/mv/mpic.c
trunk/sys/arm/mv/mv_common.c
trunk/sys/arm/mv/mv_localbus.c
trunk/sys/arm/mv/mv_machdep.c
trunk/sys/arm/mv/mv_pci.c
trunk/sys/arm/mv/mv_ts.c
trunk/sys/arm/mv/mvreg.h
trunk/sys/arm/mv/mvvar.h
trunk/sys/arm/mv/mvwin.h
trunk/sys/arm/mv/orion/
trunk/sys/arm/mv/orion/db88f5xxx.c
trunk/sys/arm/mv/orion/files.db88f5xxx
trunk/sys/arm/mv/orion/files.ts7800
trunk/sys/arm/mv/orion/orion.c
trunk/sys/arm/mv/orion/std.db88f5xxx
trunk/sys/arm/mv/orion/std.ts7800
trunk/sys/arm/mv/rtc.c
trunk/sys/arm/mv/std-pj4b.mv
trunk/sys/arm/mv/std.mv
trunk/sys/arm/mv/timer.c
trunk/sys/arm/mv/twsi.c
trunk/sys/arm/rockchip/
trunk/sys/arm/rockchip/files.rk30xx
trunk/sys/arm/rockchip/rk30xx_common.c
trunk/sys/arm/rockchip/rk30xx_gpio.c
trunk/sys/arm/rockchip/rk30xx_grf.c
trunk/sys/arm/rockchip/rk30xx_grf.h
trunk/sys/arm/rockchip/rk30xx_machdep.c
trunk/sys/arm/rockchip/rk30xx_mp.c
trunk/sys/arm/rockchip/rk30xx_pmu.c
trunk/sys/arm/rockchip/rk30xx_pmu.h
trunk/sys/arm/rockchip/rk30xx_wdog.c
trunk/sys/arm/rockchip/rk30xx_wdog.h
trunk/sys/arm/rockchip/std.rk30xx
trunk/sys/arm/samsung/
trunk/sys/arm/samsung/exynos/
trunk/sys/arm/samsung/exynos/chrome_ec.c
trunk/sys/arm/samsung/exynos/chrome_ec.h
trunk/sys/arm/samsung/exynos/chrome_kb.c
trunk/sys/arm/samsung/exynos/chrome_kb.h
trunk/sys/arm/samsung/exynos/exynos5_combiner.c
trunk/sys/arm/samsung/exynos/exynos5_combiner.h
trunk/sys/arm/samsung/exynos/exynos5_common.c
trunk/sys/arm/samsung/exynos/exynos5_common.h
trunk/sys/arm/samsung/exynos/exynos5_ehci.c
trunk/sys/arm/samsung/exynos/exynos5_fimd.c
trunk/sys/arm/samsung/exynos/exynos5_i2c.c
trunk/sys/arm/samsung/exynos/exynos5_machdep.c
trunk/sys/arm/samsung/exynos/exynos5_mct.c
trunk/sys/arm/samsung/exynos/exynos5_mp.c
trunk/sys/arm/samsung/exynos/exynos5_pad.c
trunk/sys/arm/samsung/exynos/exynos5_pad.h
trunk/sys/arm/samsung/exynos/exynos_uart.c
trunk/sys/arm/samsung/exynos/exynos_uart.h
trunk/sys/arm/samsung/exynos/files.exynos5
trunk/sys/arm/samsung/exynos/std.exynos5250
trunk/sys/arm/samsung/exynos/std.exynos5420
trunk/sys/arm/samsung/s3c2xx0/
trunk/sys/arm/samsung/s3c2xx0/board_ln2410sbc.c
trunk/sys/arm/samsung/s3c2xx0/files.s3c2xx0
trunk/sys/arm/samsung/s3c2xx0/s3c2410reg.h
trunk/sys/arm/samsung/s3c2xx0/s3c2410var.h
trunk/sys/arm/samsung/s3c2xx0/s3c2440reg.h
trunk/sys/arm/samsung/s3c2xx0/s3c24x0.c
trunk/sys/arm/samsung/s3c2xx0/s3c24x0_clk.c
trunk/sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c
trunk/sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c
trunk/sys/arm/samsung/s3c2xx0/s3c24x0reg.h
trunk/sys/arm/samsung/s3c2xx0/s3c24x0var.h
trunk/sys/arm/samsung/s3c2xx0/s3c2xx0board.h
trunk/sys/arm/samsung/s3c2xx0/s3c2xx0reg.h
trunk/sys/arm/samsung/s3c2xx0/s3c2xx0var.h
trunk/sys/arm/samsung/s3c2xx0/std.ln2410sbc
trunk/sys/arm/samsung/s3c2xx0/std.s3c2410
trunk/sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c
trunk/sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c
trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c
trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h
trunk/sys/arm/ti/
trunk/sys/arm/ti/aintc.c
trunk/sys/arm/ti/am335x/
trunk/sys/arm/ti/am335x/am335x_dmtimer.c
trunk/sys/arm/ti/am335x/am335x_lcd.c
trunk/sys/arm/ti/am335x/am335x_lcd.h
trunk/sys/arm/ti/am335x/am335x_lcd_syscons.c
trunk/sys/arm/ti/am335x/am335x_pmic.c
trunk/sys/arm/ti/am335x/am335x_prcm.c
trunk/sys/arm/ti/am335x/am335x_pwm.c
trunk/sys/arm/ti/am335x/am335x_pwm.h
trunk/sys/arm/ti/am335x/am335x_reg.h
trunk/sys/arm/ti/am335x/am335x_rtc.c
trunk/sys/arm/ti/am335x/am335x_rtcreg.h
trunk/sys/arm/ti/am335x/am335x_rtcvar.h
trunk/sys/arm/ti/am335x/am335x_scm.h
trunk/sys/arm/ti/am335x/am335x_scm_padconf.c
trunk/sys/arm/ti/am335x/am335x_usbss.c
trunk/sys/arm/ti/am335x/files.am335x
trunk/sys/arm/ti/am335x/std.am335x
trunk/sys/arm/ti/cpsw/
trunk/sys/arm/ti/cpsw/if_cpsw.c
trunk/sys/arm/ti/cpsw/if_cpswreg.h
trunk/sys/arm/ti/cpsw/if_cpswvar.h
trunk/sys/arm/ti/files.ti
trunk/sys/arm/ti/omap3/
trunk/sys/arm/ti/omap3/omap3_reg.h
trunk/sys/arm/ti/omap4/
trunk/sys/arm/ti/omap4/files.omap4
trunk/sys/arm/ti/omap4/omap4_l2cache.c
trunk/sys/arm/ti/omap4/omap4_mp.c
trunk/sys/arm/ti/omap4/omap4_prcm_clks.c
trunk/sys/arm/ti/omap4/omap4_reg.h
trunk/sys/arm/ti/omap4/omap4_scm_padconf.c
trunk/sys/arm/ti/omap4/omap4_smc.h
trunk/sys/arm/ti/omap4/omap4var.h
trunk/sys/arm/ti/omap4/pandaboard/
trunk/sys/arm/ti/omap4/pandaboard/files.pandaboard
trunk/sys/arm/ti/omap4/pandaboard/pandaboard.c
trunk/sys/arm/ti/omap4/pandaboard/std.pandaboard
trunk/sys/arm/ti/omap4/std.omap4
trunk/sys/arm/ti/std.ti
trunk/sys/arm/ti/ti_adc.c
trunk/sys/arm/ti/ti_adcreg.h
trunk/sys/arm/ti/ti_adcvar.h
trunk/sys/arm/ti/ti_common.c
trunk/sys/arm/ti/ti_cpuid.c
trunk/sys/arm/ti/ti_cpuid.h
trunk/sys/arm/ti/ti_edma3.c
trunk/sys/arm/ti/ti_edma3.h
trunk/sys/arm/ti/ti_gpio.c
trunk/sys/arm/ti/ti_i2c.c
trunk/sys/arm/ti/ti_i2c.h
trunk/sys/arm/ti/ti_machdep.c
trunk/sys/arm/ti/ti_mbox.c
trunk/sys/arm/ti/ti_mbox.h
trunk/sys/arm/ti/ti_mmchs.c
trunk/sys/arm/ti/ti_mmchs.h
trunk/sys/arm/ti/ti_prcm.c
trunk/sys/arm/ti/ti_prcm.h
trunk/sys/arm/ti/ti_pruss.c
trunk/sys/arm/ti/ti_pruss.h
trunk/sys/arm/ti/ti_scm.c
trunk/sys/arm/ti/ti_scm.h
trunk/sys/arm/ti/ti_sdhci.c
trunk/sys/arm/ti/ti_sdma.c
trunk/sys/arm/ti/ti_sdma.h
trunk/sys/arm/ti/ti_sdmareg.h
trunk/sys/arm/ti/ti_smc.S
trunk/sys/arm/ti/ti_smc.h
trunk/sys/arm/ti/ti_wdt.c
trunk/sys/arm/ti/ti_wdt.h
trunk/sys/arm/ti/tivar.h
trunk/sys/arm/ti/twl/
trunk/sys/arm/ti/twl/twl.c
trunk/sys/arm/ti/twl/twl.h
trunk/sys/arm/ti/twl/twl_clks.c
trunk/sys/arm/ti/twl/twl_clks.h
trunk/sys/arm/ti/twl/twl_vreg.c
trunk/sys/arm/ti/twl/twl_vreg.h
trunk/sys/arm/ti/usb/
trunk/sys/arm/ti/usb/omap_ehci.c
trunk/sys/arm/ti/usb/omap_usb.h
trunk/sys/arm/versatile/
trunk/sys/arm/versatile/files.versatile
trunk/sys/arm/versatile/if_smc_fdt.c
trunk/sys/arm/versatile/pl050.c
trunk/sys/arm/versatile/sp804.c
trunk/sys/arm/versatile/versatile_clcd.c
trunk/sys/arm/versatile/versatile_common.c
trunk/sys/arm/versatile/versatile_machdep.c
trunk/sys/arm/versatile/versatile_pci.c
trunk/sys/arm/versatile/versatile_sic.c
trunk/sys/arm/versatile/versatile_timer.c
trunk/sys/arm/xilinx/
trunk/sys/arm/xilinx/files.zynq7
trunk/sys/arm/xilinx/std.zynq7
trunk/sys/arm/xilinx/uart_dev_cdnc.c
trunk/sys/arm/xilinx/zedboard/
trunk/sys/arm/xilinx/zedboard/files.zedboard
trunk/sys/arm/xilinx/zedboard/std.zedboard
trunk/sys/arm/xilinx/zy7_devcfg.c
trunk/sys/arm/xilinx/zy7_ehci.c
trunk/sys/arm/xilinx/zy7_gpio.c
trunk/sys/arm/xilinx/zy7_l2cache.c
trunk/sys/arm/xilinx/zy7_machdep.c
trunk/sys/arm/xilinx/zy7_mp.c
trunk/sys/arm/xilinx/zy7_reg.h
trunk/sys/arm/xilinx/zy7_slcr.c
trunk/sys/arm/xilinx/zy7_slcr.h
trunk/sys/arm/xscale/
trunk/sys/arm/xscale/i80321/
trunk/sys/arm/xscale/i80321/ep80219_machdep.c
trunk/sys/arm/xscale/i80321/files.ep80219
trunk/sys/arm/xscale/i80321/files.i80219
trunk/sys/arm/xscale/i80321/files.i80321
trunk/sys/arm/xscale/i80321/files.iq31244
trunk/sys/arm/xscale/i80321/i80321.c
trunk/sys/arm/xscale/i80321/i80321_aau.c
trunk/sys/arm/xscale/i80321/i80321_dma.c
trunk/sys/arm/xscale/i80321/i80321_intr.h
trunk/sys/arm/xscale/i80321/i80321_mcu.c
trunk/sys/arm/xscale/i80321/i80321_pci.c
trunk/sys/arm/xscale/i80321/i80321_space.c
trunk/sys/arm/xscale/i80321/i80321_timer.c
trunk/sys/arm/xscale/i80321/i80321_wdog.c
trunk/sys/arm/xscale/i80321/i80321reg.h
trunk/sys/arm/xscale/i80321/i80321var.h
trunk/sys/arm/xscale/i80321/iq31244_7seg.c
trunk/sys/arm/xscale/i80321/iq31244_machdep.c
trunk/sys/arm/xscale/i80321/iq80321.c
trunk/sys/arm/xscale/i80321/iq80321reg.h
trunk/sys/arm/xscale/i80321/iq80321var.h
trunk/sys/arm/xscale/i80321/obio.c
trunk/sys/arm/xscale/i80321/obiovar.h
trunk/sys/arm/xscale/i80321/std.ep80219
trunk/sys/arm/xscale/i80321/std.i80219
trunk/sys/arm/xscale/i80321/std.i80321
trunk/sys/arm/xscale/i80321/std.iq31244
trunk/sys/arm/xscale/i80321/uart_bus_i80321.c
trunk/sys/arm/xscale/i80321/uart_cpu_i80321.c
trunk/sys/arm/xscale/i8134x/
trunk/sys/arm/xscale/i8134x/crb_machdep.c
trunk/sys/arm/xscale/i8134x/files.crb
trunk/sys/arm/xscale/i8134x/files.i81342
trunk/sys/arm/xscale/i8134x/i81342.c
trunk/sys/arm/xscale/i8134x/i81342_mcu.c
trunk/sys/arm/xscale/i8134x/i81342_pci.c
trunk/sys/arm/xscale/i8134x/i81342_space.c
trunk/sys/arm/xscale/i8134x/i81342reg.h
trunk/sys/arm/xscale/i8134x/i81342var.h
trunk/sys/arm/xscale/i8134x/iq81342_7seg.c
trunk/sys/arm/xscale/i8134x/iq81342reg.h
trunk/sys/arm/xscale/i8134x/iq81342var.h
trunk/sys/arm/xscale/i8134x/obio.c
trunk/sys/arm/xscale/i8134x/obiovar.h
trunk/sys/arm/xscale/i8134x/std.crb
trunk/sys/arm/xscale/i8134x/std.i81342
trunk/sys/arm/xscale/i8134x/uart_bus_i81342.c
trunk/sys/arm/xscale/i8134x/uart_cpu_i81342.c
trunk/sys/arm/xscale/ixp425/
trunk/sys/arm/xscale/ixp425/avila_ata.c
trunk/sys/arm/xscale/ixp425/avila_gpio.c
trunk/sys/arm/xscale/ixp425/avila_led.c
trunk/sys/arm/xscale/ixp425/avila_machdep.c
trunk/sys/arm/xscale/ixp425/cambria_exp_space.c
trunk/sys/arm/xscale/ixp425/cambria_fled.c
trunk/sys/arm/xscale/ixp425/cambria_gpio.c
trunk/sys/arm/xscale/ixp425/cambria_led.c
trunk/sys/arm/xscale/ixp425/files.avila
trunk/sys/arm/xscale/ixp425/files.ixp425
trunk/sys/arm/xscale/ixp425/if_npe.c
trunk/sys/arm/xscale/ixp425/if_npereg.h
trunk/sys/arm/xscale/ixp425/ixdp425_pci.c
trunk/sys/arm/xscale/ixp425/ixdp425reg.h
trunk/sys/arm/xscale/ixp425/ixp425.c
trunk/sys/arm/xscale/ixp425/ixp425_a4x_io.S
trunk/sys/arm/xscale/ixp425/ixp425_a4x_space.c
trunk/sys/arm/xscale/ixp425/ixp425_iic.c
trunk/sys/arm/xscale/ixp425/ixp425_intr.h
trunk/sys/arm/xscale/ixp425/ixp425_mem.c
trunk/sys/arm/xscale/ixp425/ixp425_npe.c
trunk/sys/arm/xscale/ixp425/ixp425_npereg.h
trunk/sys/arm/xscale/ixp425/ixp425_npevar.h
trunk/sys/arm/xscale/ixp425/ixp425_pci.c
trunk/sys/arm/xscale/ixp425/ixp425_pci_asm.S
trunk/sys/arm/xscale/ixp425/ixp425_pci_space.c
trunk/sys/arm/xscale/ixp425/ixp425_qmgr.c
trunk/sys/arm/xscale/ixp425/ixp425_qmgr.h
trunk/sys/arm/xscale/ixp425/ixp425_space.c
trunk/sys/arm/xscale/ixp425/ixp425_timer.c
trunk/sys/arm/xscale/ixp425/ixp425_wdog.c
trunk/sys/arm/xscale/ixp425/ixp425reg.h
trunk/sys/arm/xscale/ixp425/ixp425var.h
trunk/sys/arm/xscale/ixp425/std.avila
trunk/sys/arm/xscale/ixp425/std.ixp425
trunk/sys/arm/xscale/ixp425/std.ixp435
trunk/sys/arm/xscale/ixp425/uart_bus_ixp425.c
trunk/sys/arm/xscale/ixp425/uart_cpu_ixp425.c
trunk/sys/arm/xscale/pxa/
trunk/sys/arm/xscale/pxa/files.pxa
trunk/sys/arm/xscale/pxa/if_smc_smi.c
trunk/sys/arm/xscale/pxa/pxa_gpio.c
trunk/sys/arm/xscale/pxa/pxa_icu.c
trunk/sys/arm/xscale/pxa/pxa_machdep.c
trunk/sys/arm/xscale/pxa/pxa_obio.c
trunk/sys/arm/xscale/pxa/pxa_smi.c
trunk/sys/arm/xscale/pxa/pxa_space.c
trunk/sys/arm/xscale/pxa/pxa_timer.c
trunk/sys/arm/xscale/pxa/pxareg.h
trunk/sys/arm/xscale/pxa/pxavar.h
trunk/sys/arm/xscale/pxa/std.pxa
trunk/sys/arm/xscale/pxa/uart_bus_pxa.c
trunk/sys/arm/xscale/pxa/uart_cpu_pxa.c
trunk/sys/arm/xscale/std.xscale
trunk/sys/arm/xscale/std.xscale-be
Added: trunk/sys/arm/allwinner/a10_clk.c
===================================================================
--- trunk/sys/arm/allwinner/a10_clk.c (rev 0)
+++ trunk/sys/arm/allwinner/a10_clk.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,192 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Simple clock driver for Allwinner A10 */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a10_clk.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include "a10_clk.h"
+
+struct a10_ccm_softc {
+ struct resource *res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct a10_ccm_softc *a10_ccm_sc = NULL;
+
+#define ccm_read_4(sc, reg) \
+ bus_space_read_4((sc)->bst, (sc)->bsh, (reg))
+#define ccm_write_4(sc, reg, val) \
+ bus_space_write_4((sc)->bst, (sc)->bsh, (reg), (val))
+
+static int
+a10_ccm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "allwinner,sun4i-ccm")) {
+ device_set_desc(dev, "Allwinner Clock Control Module");
+ return(BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+a10_ccm_attach(device_t dev)
+{
+ struct a10_ccm_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ if (a10_ccm_sc)
+ return (ENXIO);
+
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res);
+ sc->bsh = rman_get_bushandle(sc->res);
+
+ a10_ccm_sc = sc;
+
+ return (0);
+}
+
+static device_method_t a10_ccm_methods[] = {
+ DEVMETHOD(device_probe, a10_ccm_probe),
+ DEVMETHOD(device_attach, a10_ccm_attach),
+ { 0, 0 }
+};
+
+static driver_t a10_ccm_driver = {
+ "a10_ccm",
+ a10_ccm_methods,
+ sizeof(struct a10_ccm_softc),
+};
+
+static devclass_t a10_ccm_devclass;
+
+DRIVER_MODULE(a10_ccm, simplebus, a10_ccm_driver, a10_ccm_devclass, 0, 0);
+
+int
+a10_clk_usb_activate(void)
+{
+ struct a10_ccm_softc *sc = a10_ccm_sc;
+ uint32_t reg_value;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ /* Gating AHB clock for USB */
+ reg_value = ccm_read_4(sc, CCM_AHB_GATING0);
+ reg_value |= CCM_AHB_GATING_USB0; /* AHB clock gate usb0 */
+ reg_value |= CCM_AHB_GATING_EHCI0; /* AHB clock gate ehci1 */
+ reg_value |= CCM_AHB_GATING_EHCI1; /* AHB clock gate ehci1 */
+ ccm_write_4(sc, CCM_AHB_GATING0, reg_value);
+
+ /* Enable clock for USB */
+ reg_value = ccm_read_4(sc, CCM_USB_CLK);
+ reg_value |= CCM_USB_PHY; /* USBPHY */
+ reg_value |= CCM_USB0_RESET; /* disable reset for USB0 */
+ reg_value |= CCM_USB1_RESET; /* disable reset for USB1 */
+ reg_value |= CCM_USB2_RESET; /* disable reset for USB2 */
+ ccm_write_4(sc, CCM_USB_CLK, reg_value);
+
+ return (0);
+}
+
+int
+a10_clk_usb_deactivate(void)
+{
+ struct a10_ccm_softc *sc = a10_ccm_sc;
+ uint32_t reg_value;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ /* Disable clock for USB */
+ reg_value = ccm_read_4(sc, CCM_USB_CLK);
+ reg_value &= ~CCM_USB_PHY; /* USBPHY */
+ reg_value &= ~CCM_USB0_RESET; /* reset for USB0 */
+ reg_value &= ~CCM_USB1_RESET; /* reset for USB1 */
+ reg_value &= ~CCM_USB2_RESET; /* reset for USB2 */
+ ccm_write_4(sc, CCM_USB_CLK, reg_value);
+
+ /* Disable gating AHB clock for USB */
+ reg_value = ccm_read_4(sc, CCM_AHB_GATING0);
+ reg_value &= ~CCM_AHB_GATING_USB0; /* disable AHB clock gate usb0 */
+ reg_value &= ~CCM_AHB_GATING_EHCI1; /* disable AHB clock gate ehci1 */
+ ccm_write_4(sc, CCM_AHB_GATING0, reg_value);
+
+ return (0);
+}
+
+int
+a10_clk_emac_activate(void) {
+ struct a10_ccm_softc *sc = a10_ccm_sc;
+ uint32_t reg_value;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ /* Gating AHB clock for EMAC */
+ reg_value = ccm_read_4(sc, CCM_AHB_GATING0);
+ reg_value |= CCM_AHB_GATING_EMAC;
+ ccm_write_4(sc, CCM_AHB_GATING0, reg_value);
+
+ return (0);
+}
+
Property changes on: trunk/sys/arm/allwinner/a10_clk.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_clk.h
===================================================================
--- trunk/sys/arm/allwinner/a10_clk.h (rev 0)
+++ trunk/sys/arm/allwinner/a10_clk.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,118 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/allwinner/a10_clk.h 266337 2014-05-17 18:53:36Z ian $
+ */
+
+#ifndef _A10_CLK_H_
+#define _A10_CLK_H_
+
+#define CCMU_BASE 0xe1c20000
+
+#define CCM_PLL1_CFG 0x0000
+#define CCM_PLL1_TUN 0x0004
+#define CCM_PLL2_CFG 0x0008
+#define CCM_PLL2_TUN 0x000c
+#define CCM_PLL3_CFG 0x0010
+#define CCM_PLL3_TUN 0x0014
+#define CCM_PLL4_CFG 0x0018
+#define CCM_PLL4_TUN 0x001c
+#define CCM_PLL5_CFG 0x0020
+#define CCM_PLL5_TUN 0x0024
+#define CCM_PLL6_CFG 0x0028
+#define CCM_PLL6_TUN 0x002c
+#define CCM_PLL7_CFG 0x0030
+#define CCM_PLL7_TUN 0x0034
+#define CCM_PLL1_TUN2 0x0038
+#define CCM_PLL5_TUN2 0x003c
+#define CCM_PLL_LOCK_DBG 0x004c
+#define CCM_OSC24M_CFG 0x0050
+#define CCM_CPU_AHB_APB0_CFG 0x0054
+#define CCM_APB1_CLK_DIV 0x0058
+#define CCM_AXI_GATING 0x005c
+#define CCM_AHB_GATING0 0x0060
+#define CCM_AHB_GATING1 0x0064
+#define CCM_APB0_GATING 0x0068
+#define CCM_APB1_GATING 0x006c
+#define CCM_NAND_SCLK_CFG 0x0080
+#define CCM_MS_SCLK_CFG 0x0084
+#define CCM_MMC0_SCLK_CFG 0x0088
+#define CCM_MMC1_SCLK_CFG 0x008c
+#define CCM_MMC2_SCLK_CFG 0x0090
+#define CCM_MMC3_SCLK_CFG 0x0094
+#define CCM_TS_CLK 0x0098
+#define CCM_SS_CLK 0x009c
+#define CCM_SPI0_CLK 0x00a0
+#define CCM_SPI1_CLK 0x00a4
+#define CCM_SPI2_CLK 0x00a8
+#define CCM_PATA_CLK 0x00ac
+#define CCM_IR0_CLK 0x00b0
+#define CCM_IR1_CLK 0x00b4
+#define CCM_IIS_CLK 0x00b8
+#define CCM_AC97_CLK 0x00bc
+#define CCM_SPDIF_CLK 0x00c0
+#define CCM_KEYPAD_CLK 0x00c4
+#define CCM_SATA_CLK 0x00c8
+#define CCM_USB_CLK 0x00cc
+#define CCM_GPS_CLK 0x00d0
+#define CCM_SPI3_CLK 0x00d4
+#define CCM_DRAM_CLK 0x0100
+#define CCM_BE0_SCLK 0x0104
+#define CCM_BE1_SCLK 0x0108
+#define CCM_FE0_CLK 0x010c
+#define CCM_FE1_CLK 0x0110
+#define CCM_MP_CLK 0x0114
+#define CCM_LCD0_CH0_CLK 0x0118
+#define CCM_LCD1_CH0_CLK 0x011c
+#define CCM_CSI_ISP_CLK 0x0120
+#define CCM_TVD_CLK 0x0128
+#define CCM_LCD0_CH1_CLK 0x012c
+#define CCM_LCD1_CH1_CLK 0x0130
+#define CCM_CS0_CLK 0x0134
+#define CCM_CS1_CLK 0x0138
+#define CCM_VE_CLK 0x013c
+#define CCM_AUDIO_CODEC_CLK 0x0140
+#define CCM_AVS_CLK 0x0144
+#define CCM_ACE_CLK 0x0148
+#define CCM_LVDS_CLK 0x014c
+#define CCM_HDMI_CLK 0x0150
+#define CCM_MALI400_CLK 0x0154
+
+#define CCM_AHB_GATING_USB0 (1 << 0)
+#define CCM_AHB_GATING_EHCI0 (1 << 1)
+#define CCM_AHB_GATING_EHCI1 (1 << 3)
+#define CCM_AHB_GATING_EMAC (1 << 17)
+
+#define CCM_USB_PHY (1 << 8)
+#define CCM_USB0_RESET (1 << 0)
+#define CCM_USB1_RESET (1 << 1)
+#define CCM_USB2_RESET (1 << 2)
+
+int a10_clk_usb_activate(void);
+int a10_clk_usb_deactivate(void);
+int a10_clk_emac_activate(void);
+
+#endif /* _A10_CLK_H_ */
Property changes on: trunk/sys/arm/allwinner/a10_clk.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_common.c
===================================================================
--- trunk/sys/arm/allwinner/a10_common.c (rev 0)
+++ trunk/sys/arm/allwinner/a10_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a10_common.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+ int offset;
+
+ if (fdt_is_compatible(node, "allwinner,sun4i-ic"))
+ offset = 0;
+ else if (fdt_is_compatible(node, "arm,gic"))
+ offset = 32;
+ else
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]) + offset;
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_aintc_decode_ic,
+ NULL
+};
Property changes on: trunk/sys/arm/allwinner/a10_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_ehci.c
===================================================================
--- trunk/sys/arm/allwinner/a10_ehci.c (rev 0)
+++ trunk/sys/arm/allwinner/a10_ehci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,300 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Allwinner A10 attachment driver for the USB Enhanced Host Controller.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a10_ehci.c 308402 2016-11-07 09:19:04Z hselasky $");
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include "gpio_if.h"
+
+#include "a10_clk.h"
+
+#define EHCI_HC_DEVSTR "Allwinner Integrated USB 2.0 controller"
+
+#define SW_USB_PMU_IRQ_ENABLE 0x800
+
+#define SW_SDRAM_REG_HPCR_USB1 (0x250 + ((1 << 2) * 4))
+#define SW_SDRAM_REG_HPCR_USB2 (0x250 + ((1 << 2) * 5))
+#define SW_SDRAM_BP_HPCR_ACCESS (1 << 0)
+
+#define SW_ULPI_BYPASS (1 << 0)
+#define SW_AHB_INCRX_ALIGN (1 << 8)
+#define SW_AHB_INCR4 (1 << 9)
+#define SW_AHB_INCR8 (1 << 10)
+#define GPIO_USB1_PWR 230
+#define GPIO_USB2_PWR 227
+
+#define A10_READ_4(sc, reg) \
+ bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
+
+#define A10_WRITE_4(sc, reg, data) \
+ bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
+
+static device_attach_t a10_ehci_attach;
+static device_detach_t a10_ehci_detach;
+
+bs_r_1_proto(reversed);
+bs_w_1_proto(reversed);
+
+static int
+a10_ehci_probe(device_t self)
+{
+
+ if (!ofw_bus_status_okay(self))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(self, "allwinner,usb-ehci"))
+ return (ENXIO);
+
+ device_set_desc(self, EHCI_HC_DEVSTR);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_ehci_attach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ bus_space_handle_t bsh;
+ device_t sc_gpio_dev;
+ int err;
+ int rid;
+ uint32_t reg_value = 0;
+
+ /* initialise some bus fields */
+ sc->sc_bus.parent = self;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus,
+ USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
+ return (ENOMEM);
+ }
+
+ sc->sc_bus.usbrev = USB_REV_2_0;
+
+ rid = 0;
+ sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->sc_io_res) {
+ device_printf(self, "Could not map memory\n");
+ goto error;
+ }
+
+ sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+ sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+ bsh = rman_get_bushandle(sc->sc_io_res);
+
+ sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+ if (bus_space_subregion(sc->sc_io_tag, bsh, 0x00,
+ sc->sc_io_size, &sc->sc_io_hdl) != 0)
+ panic("%s: unable to subregion USB host registers",
+ device_get_name(self));
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(self, "Could not allocate irq\n");
+ goto error;
+ }
+ sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(self, "Could not add USB device\n");
+ goto error;
+ }
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+ device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);
+
+ sprintf(sc->sc_vendor, "Allwinner");
+
+ /* Get the GPIO device, we need this to give power to USB */
+ sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (sc_gpio_dev == NULL) {
+ device_printf(self, "Error: failed to get the GPIO device\n");
+ goto error;
+ }
+
+ err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+ if (err) {
+ device_printf(self, "Could not setup irq, %d\n", err);
+ sc->sc_intr_hdl = NULL;
+ goto error;
+ }
+
+ sc->sc_flags |= EHCI_SCFLG_DONTRESET;
+
+ /* Enable clock for USB */
+ a10_clk_usb_activate();
+
+ /* Give power to USB */
+ GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_OUTPUT);
+ GPIO_PIN_SET(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_HIGH);
+
+ /* Give power to USB */
+ GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB1_PWR, GPIO_PIN_OUTPUT);
+ GPIO_PIN_SET(sc_gpio_dev, GPIO_USB1_PWR, GPIO_PIN_HIGH);
+
+ /* Enable passby */
+ reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE);
+ reg_value |= SW_AHB_INCR8; /* AHB INCR8 enable */
+ reg_value |= SW_AHB_INCR4; /* AHB burst type INCR4 enable */
+ reg_value |= SW_AHB_INCRX_ALIGN; /* AHB INCRX align enable */
+ reg_value |= SW_ULPI_BYPASS; /* ULPI bypass enable */
+ A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);
+
+ /* Configure port */
+ reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2);
+ reg_value |= SW_SDRAM_BP_HPCR_ACCESS;
+ A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value);
+
+ err = ehci_init(sc);
+ if (!err) {
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ }
+ if (err) {
+ device_printf(self, "USB init failed err=%d\n", err);
+ goto error;
+ }
+ return (0);
+
+error:
+ a10_ehci_detach(self);
+ return (ENXIO);
+}
+
+static int
+a10_ehci_detach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ int err;
+ uint32_t reg_value = 0;
+
+ /* during module unload there are lots of children leftover */
+ device_delete_children(self);
+
+ if (sc->sc_irq_res && sc->sc_intr_hdl) {
+ /*
+ * only call ehci_detach() after ehci_init()
+ */
+ ehci_detach(sc);
+
+ err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
+
+ if (err)
+ /* XXX or should we panic? */
+ device_printf(self, "Could not tear down irq, %d\n",
+ err);
+ sc->sc_intr_hdl = NULL;
+ }
+
+ if (sc->sc_irq_res) {
+ bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+ if (sc->sc_io_res) {
+ bus_release_resource(self, SYS_RES_MEMORY, 0,
+ sc->sc_io_res);
+ sc->sc_io_res = NULL;
+ }
+ usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
+
+ /* Disable configure port */
+ reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2);
+ reg_value &= ~SW_SDRAM_BP_HPCR_ACCESS;
+ A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value);
+
+ /* Disable passby */
+ reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE);
+ reg_value &= ~SW_AHB_INCR8; /* AHB INCR8 disable */
+ reg_value &= ~SW_AHB_INCR4; /* AHB burst type INCR4 disable */
+ reg_value &= ~SW_AHB_INCRX_ALIGN; /* AHB INCRX align disable */
+ reg_value &= ~SW_ULPI_BYPASS; /* ULPI bypass disable */
+ A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);
+
+ /* Disable clock for USB */
+ a10_clk_usb_deactivate();
+
+ return (0);
+}
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, a10_ehci_probe),
+ DEVMETHOD(device_attach, a10_ehci_attach),
+ DEVMETHOD(device_detach, a10_ehci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD_END
+};
+
+static driver_t ehci_driver = {
+ .name = "ehci",
+ .methods = ehci_methods,
+ .size = sizeof(ehci_softc_t),
+};
+
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
+MODULE_DEPEND(ehci, usb, 1, 1, 1);
Property changes on: trunk/sys/arm/allwinner/a10_ehci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_gpio.c
===================================================================
--- trunk/sys/arm/allwinner/a10_gpio.c (rev 0)
+++ trunk/sys/arm/allwinner/a10_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,529 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012 Luiz Otavio O Souza.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a10_gpio.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "gpio_if.h"
+#include "a10_gpio.h"
+
+/*
+ * A10 have 9 banks of gpio.
+ * 32 pins per bank:
+ * PA0 - PA17 | PB0 - PB23 | PC0 - PC24
+ * PD0 - PD27 | PE0 - PE31 | PF0 - PF5
+ * PG0 - PG9 | PH0 - PH27 | PI0 - PI12
+ */
+
+#define A10_GPIO_PINS 288
+#define A10_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+ GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
+
+#define A10_GPIO_NONE 0
+#define A10_GPIO_PULLUP 1
+#define A10_GPIO_PULLDOWN 2
+
+#define A10_GPIO_INPUT 0
+#define A10_GPIO_OUTPUT 1
+
+struct a10_gpio_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ struct resource * sc_mem_res;
+ struct resource * sc_irq_res;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ void * sc_intrhand;
+ int sc_gpio_npins;
+ struct gpio_pin sc_gpio_pins[A10_GPIO_PINS];
+};
+
+#define A10_GPIO_LOCK(_sc) mtx_lock(&_sc->sc_mtx)
+#define A10_GPIO_UNLOCK(_sc) mtx_unlock(&_sc->sc_mtx)
+#define A10_GPIO_LOCK_ASSERT(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
+
+#define A10_GPIO_GP_CFG(_bank, _pin) 0x00 + ((_bank) * 0x24) + ((_pin)<<2)
+#define A10_GPIO_GP_DAT(_bank) 0x10 + ((_bank) * 0x24)
+#define A10_GPIO_GP_DRV(_bank, _pin) 0x14 + ((_bank) * 0x24) + ((_pin)<<2)
+#define A10_GPIO_GP_PUL(_bank, _pin) 0x1c + ((_bank) * 0x24) + ((_pin)<<2)
+
+#define A10_GPIO_GP_INT_CFG0 0x200
+#define A10_GPIO_GP_INT_CFG1 0x204
+#define A10_GPIO_GP_INT_CFG2 0x208
+#define A10_GPIO_GP_INT_CFG3 0x20c
+
+#define A10_GPIO_GP_INT_CTL 0x210
+#define A10_GPIO_GP_INT_STA 0x214
+#define A10_GPIO_GP_INT_DEB 0x218
+
+static struct a10_gpio_softc *a10_gpio_sc;
+
+#define A10_GPIO_WRITE(_sc, _off, _val) \
+ bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
+#define A10_GPIO_READ(_sc, _off) \
+ bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
+
+static uint32_t
+a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin)
+{
+ uint32_t bank, func, offset;
+
+ bank = pin / 32;
+ pin = pin - 32 * bank;
+ func = pin >> 3;
+ offset = ((pin & 0x07) << 2);
+
+ A10_GPIO_LOCK(sc);
+ func = (A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, func)) >> offset) & 7;
+ A10_GPIO_UNLOCK(sc);
+
+ return (func);
+}
+
+static uint32_t
+a10_gpio_func_flag(uint32_t nfunc)
+{
+
+ switch (nfunc) {
+ case A10_GPIO_INPUT:
+ return (GPIO_PIN_INPUT);
+ case A10_GPIO_OUTPUT:
+ return (GPIO_PIN_OUTPUT);
+ }
+ return (0);
+}
+
+static void
+a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f)
+{
+ uint32_t bank, func, data, offset;
+
+ /* Must be called with lock held. */
+ A10_GPIO_LOCK_ASSERT(sc);
+
+ bank = pin / 32;
+ pin = pin - 32 * bank;
+ func = pin >> 3;
+ offset = ((pin & 0x07) << 2);
+
+ data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, func));
+ data &= ~(7 << offset);
+ data |= (f << offset);
+ A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, func), data);
+}
+
+static void
+a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state)
+{
+ uint32_t bank, offset, pull, val;
+
+ /* Must be called with lock held. */
+ A10_GPIO_LOCK_ASSERT(sc);
+
+ bank = pin / 32;
+ pin = pin - 32 * bank;
+ pull = pin >> 4;
+ offset = ((pin & 0x0f) << 1);
+
+ val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pull));
+ val &= ~(0x03 << offset);
+ val |= (state << offset);
+ A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pull), val);
+}
+
+static void
+a10_gpio_pin_configure(struct a10_gpio_softc *sc, struct gpio_pin *pin,
+ unsigned int flags)
+{
+
+ A10_GPIO_LOCK(sc);
+
+ /*
+ * Manage input/output.
+ */
+ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
+ pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
+ if (flags & GPIO_PIN_OUTPUT) {
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+ a10_gpio_set_function(sc, pin->gp_pin,
+ A10_GPIO_OUTPUT);
+ } else {
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ a10_gpio_set_function(sc, pin->gp_pin,
+ A10_GPIO_INPUT);
+ }
+ }
+
+ /* Manage Pull-up/pull-down. */
+ pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
+ if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
+ if (flags & GPIO_PIN_PULLUP) {
+ pin->gp_flags |= GPIO_PIN_PULLUP;
+ a10_gpio_set_pud(sc, pin->gp_pin, A10_GPIO_PULLUP);
+ } else {
+ pin->gp_flags |= GPIO_PIN_PULLDOWN;
+ a10_gpio_set_pud(sc, pin->gp_pin, A10_GPIO_PULLDOWN);
+ }
+ } else
+ a10_gpio_set_pud(sc, pin->gp_pin, A10_GPIO_NONE);
+
+ A10_GPIO_UNLOCK(sc);
+}
+
+static int
+a10_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = A10_GPIO_PINS - 1;
+ return (0);
+}
+
+static int
+a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct a10_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ A10_GPIO_LOCK(sc);
+ *caps = sc->sc_gpio_pins[i].gp_caps;
+ A10_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct a10_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ A10_GPIO_LOCK(sc);
+ *flags = sc->sc_gpio_pins[i].gp_flags;
+ A10_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct a10_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ A10_GPIO_LOCK(sc);
+ memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME);
+ A10_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct a10_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ a10_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
+
+ return (0);
+}
+
+static int
+a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct a10_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, offset, data;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ bank = pin / 32;
+ pin = pin - 32 * bank;
+ offset = pin & 0x1f;
+
+ A10_GPIO_LOCK(sc);
+ data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
+ if (value)
+ data |= (1 << offset);
+ else
+ data &= ~(1 << offset);
+ A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
+ A10_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct a10_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, offset, reg_data;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ bank = pin / 32;
+ pin = pin - 32 * bank;
+ offset = pin & 0x1f;
+
+ A10_GPIO_LOCK(sc);
+ reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
+ A10_GPIO_UNLOCK(sc);
+ *val = (reg_data & (1 << offset)) ? 1 : 0;
+
+ return (0);
+}
+
+static int
+a10_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct a10_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, data, offset;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ bank = pin / 32;
+ pin = pin - 32 * bank;
+ offset = pin & 0x1f;
+
+ A10_GPIO_LOCK(sc);
+ data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
+ if (data & (1 << offset))
+ data &= ~(1 << offset);
+ else
+ data |= (1 << offset);
+ A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
+ A10_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+a10_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-gpio"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Allwinner GPIO controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_gpio_attach(device_t dev)
+{
+ struct a10_gpio_softc *sc = device_get_softc(dev);
+ uint32_t func;
+ int i, rid;
+ phandle_t gpio;
+
+ sc->sc_dev = dev;
+
+ mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_DEF);
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ /* Find our node. */
+ gpio = ofw_bus_get_node(sc->sc_dev);
+
+ if (!OF_hasprop(gpio, "gpio-controller"))
+ /* Node is not a GPIO controller. */
+ goto fail;
+
+ /* Initialize the software controlled pins. */
+ for (i = 0; i < A10_GPIO_PINS; i++) {
+ snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
+ "pin %d", i);
+ func = a10_gpio_get_function(sc, i);
+ sc->sc_gpio_pins[i].gp_pin = i;
+ sc->sc_gpio_pins[i].gp_caps = A10_GPIO_DEFAULT_CAPS;
+ sc->sc_gpio_pins[i].gp_flags = a10_gpio_func_flag(func);
+ }
+ sc->sc_gpio_npins = i;
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ a10_gpio_sc = sc;
+
+ return (bus_generic_attach(dev));
+
+fail:
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ return (ENXIO);
+}
+
+static int
+a10_gpio_detach(device_t dev)
+{
+
+ return (EBUSY);
+}
+
+static device_method_t a10_gpio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, a10_gpio_probe),
+ DEVMETHOD(device_attach, a10_gpio_attach),
+ DEVMETHOD(device_detach, a10_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, a10_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, a10_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, a10_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, a10_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, a10_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, a10_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, a10_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, a10_gpio_pin_toggle),
+
+ DEVMETHOD_END
+};
+
+static devclass_t a10_gpio_devclass;
+
+static driver_t a10_gpio_driver = {
+ "gpio",
+ a10_gpio_methods,
+ sizeof(struct a10_gpio_softc),
+};
+
+DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0);
+
+int
+a10_emac_gpio_config(uint32_t pin)
+{
+ struct a10_gpio_softc *sc = a10_gpio_sc;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ /* Configure pin mux settings for MII. */
+ A10_GPIO_LOCK(sc);
+ a10_gpio_set_function(sc, pin, A10_GPIO_PULLDOWN);
+ A10_GPIO_UNLOCK(sc);
+
+ return (0);
+}
Property changes on: trunk/sys/arm/allwinner/a10_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_gpio.h
===================================================================
--- trunk/sys/arm/allwinner/a10_gpio.h (rev 0)
+++ trunk/sys/arm/allwinner/a10_gpio.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,35 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/allwinner/a10_gpio.h 266337 2014-05-17 18:53:36Z ian $
+ */
+
+#ifndef _A10_GPIO_H_
+#define _A10_GPIO_H_
+
+int a10_emac_gpio_config(uint32_t pin);
+
+#endif
Property changes on: trunk/sys/arm/allwinner/a10_gpio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_machdep.c
===================================================================
--- trunk/sys/arm/allwinner/a10_machdep.c (rev 0)
+++ trunk/sys/arm/allwinner/a10_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,113 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/ti/ti_machdep.c
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a10_machdep.c 266337 2014-05-17 18:53:36Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <arm/allwinner/a10_wdog.h>
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+}
+
+void
+initarm_gpio_init(void)
+{
+}
+
+void
+initarm_late_init(void)
+{
+}
+
+/*
+ * Set up static device mappings.
+ *
+ * This covers all the on-chip device with 1MB section mappings, which is good
+ * for performance (uses fewer TLB entries for device access).
+ *
+ * XXX It also covers a block of SRAM and some GPU (mali400) stuff that maybe
+ * shouldn't be device-mapped. The original code mapped a 4MB block, but
+ * perhaps a 1MB block would be more appropriate.
+ */
+int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(0x01C00000, 0x00400000); /* 4MB */
+
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+ return (0);
+}
+
+void
+cpu_reset()
+{
+ a10wd_watchdog_reset();
+ printf("Reset failed!\n");
+ while (1);
+}
Property changes on: trunk/sys/arm/allwinner/a10_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_sramc.c
===================================================================
--- trunk/sys/arm/allwinner/a10_sramc.c (rev 0)
+++ trunk/sys/arm/allwinner/a10_sramc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,135 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/allwinner/a10_sramc.c 266337 2014-05-17 18:53:36Z ian $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a10_sramc.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+#include <machine/fdt.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "a10_sramc.h"
+
+#define SRAM_CTL1_CFG 0x04
+
+struct a10_sramc_softc {
+ struct resource *res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct a10_sramc_softc *a10_sramc_sc;
+
+#define sramc_read_4(sc, reg) \
+ bus_space_read_4((sc)->bst, (sc)->bsh, (reg))
+#define sramc_write_4(sc, reg, val) \
+ bus_space_write_4((sc)->bst, (sc)->bsh, (reg), (val))
+
+
+static int
+a10_sramc_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "allwinner,sun4i-sramc")) {
+ device_set_desc(dev, "Allwinner sramc module");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+a10_sramc_attach(device_t dev)
+{
+ struct a10_sramc_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res);
+ sc->bsh = rman_get_bushandle(sc->res);
+
+ a10_sramc_sc = sc;
+
+ return (0);
+}
+
+static device_method_t a10_sramc_methods[] = {
+ DEVMETHOD(device_probe, a10_sramc_probe),
+ DEVMETHOD(device_attach, a10_sramc_attach),
+ { 0, 0 }
+};
+
+static driver_t a10_sramc_driver = {
+ "a10_sramc",
+ a10_sramc_methods,
+ sizeof(struct a10_sramc_softc),
+};
+
+static devclass_t a10_sramc_devclass;
+
+DRIVER_MODULE(a10_sramc, simplebus, a10_sramc_driver, a10_sramc_devclass, 0, 0);
+
+int
+a10_map_to_emac(void)
+{
+ struct a10_sramc_softc *sc = a10_sramc_sc;
+ uint32_t reg_value;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ /* Map SRAM to EMAC, set bit 2 and 4. */
+ reg_value = sramc_read_4(sc, SRAM_CTL1_CFG);
+ reg_value |= 0x5 << 2;
+ sramc_write_4(sc, SRAM_CTL1_CFG, reg_value);
+
+ return (0);
+}
Property changes on: trunk/sys/arm/allwinner/a10_sramc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_sramc.h
===================================================================
--- trunk/sys/arm/allwinner/a10_sramc.h (rev 0)
+++ trunk/sys/arm/allwinner/a10_sramc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,35 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/allwinner/a10_sramc.h 266337 2014-05-17 18:53:36Z ian $
+ */
+
+#ifndef _A10_SRAMC_H_
+#define _A10_SRAMC_H_
+
+int a10_map_to_emac(void);
+
+#endif
Property changes on: trunk/sys/arm/allwinner/a10_sramc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_wdog.c
===================================================================
--- trunk/sys/arm/allwinner/a10_wdog.c (rev 0)
+++ trunk/sys/arm/allwinner/a10_wdog.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,209 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a10_wdog.c 266405 2014-05-18 16:03:34Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/watchdog.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <machine/machdep.h>
+#include <machine/fdt.h>
+
+#include <arm/allwinner/a10_wdog.h>
+
+#define READ(_sc, _r) bus_read_4((_sc)->res, (_r))
+#define WRITE(_sc, _r, _v) bus_write_4((_sc)->res, (_r), (_v))
+
+#define WDOG_CTRL 0x00
+#define WDOG_CTRL_RESTART (1 << 0)
+#define WDOG_MODE 0x04
+#define WDOG_MODE_INTVL_SHIFT 3
+#define WDOG_MODE_RST_EN (1 << 1)
+#define WDOG_MODE_EN (1 << 0)
+
+struct a10wd_interval {
+ uint64_t milliseconds;
+ unsigned int value;
+};
+
+struct a10wd_interval wd_intervals[] = {
+ { 500, 0 },
+ { 1000, 1 },
+ { 2000, 2 },
+ { 3000, 3 },
+ { 4000, 4 },
+ { 5000, 5 },
+ { 6000, 6 },
+ { 8000, 7 },
+ { 10000, 8 },
+ { 12000, 9 },
+ { 14000, 10 },
+ { 16000, 11 },
+ { 0, 0 } /* sentinel */
+};
+
+static struct a10wd_softc *a10wd_sc = NULL;
+
+struct a10wd_softc {
+ device_t dev;
+ struct resource * res;
+ struct mtx mtx;
+};
+
+static void a10wd_watchdog_fn(void *private, u_int cmd, int *error);
+
+static int
+a10wd_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "allwinner,sun4i-wdt")) {
+ device_set_desc(dev, "Allwinner A10 Watchdog");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+a10wd_attach(device_t dev)
+{
+ struct a10wd_softc *sc;
+ int rid;
+
+ if (a10wd_sc != NULL)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ rid = 0;
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ a10wd_sc = sc;
+ mtx_init(&sc->mtx, "A10 Watchdog", "a10wd", MTX_DEF);
+ EVENTHANDLER_REGISTER(watchdog_list, a10wd_watchdog_fn, sc, 0);
+
+ return (0);
+}
+
+static void
+a10wd_watchdog_fn(void *private, u_int cmd, int *error)
+{
+ struct a10wd_softc *sc;
+ uint64_t ms;
+ int i;
+
+ sc = private;
+ mtx_lock(&sc->mtx);
+
+ cmd &= WD_INTERVAL;
+
+ if (cmd > 0) {
+ ms = ((uint64_t)1 << (cmd & WD_INTERVAL)) / 1000000;
+ i = 0;
+ while (wd_intervals[i].milliseconds &&
+ (ms > wd_intervals[i].milliseconds))
+ i++;
+ if (wd_intervals[i].milliseconds) {
+ WRITE(sc, WDOG_MODE,
+ (wd_intervals[i].value << WDOG_MODE_INTVL_SHIFT) |
+ WDOG_MODE_EN | WDOG_MODE_RST_EN);
+ WRITE(sc, WDOG_CTRL, WDOG_CTRL_RESTART);
+ *error = 0;
+ }
+ else {
+ /*
+ * Can't arm
+ * disable watchdog as watchdog(9) requires
+ */
+ device_printf(sc->dev,
+ "Can't arm, timeout is more than 16 sec\n");
+ mtx_unlock(&sc->mtx);
+ WRITE(sc, WDOG_MODE, 0);
+ return;
+ }
+ }
+ else
+ WRITE(sc, WDOG_MODE, 0);
+
+ mtx_unlock(&sc->mtx);
+}
+
+void
+a10wd_watchdog_reset()
+{
+
+ if (a10wd_sc == NULL) {
+ printf("Reset: watchdog device has not been initialized\n");
+ return;
+ }
+
+ WRITE(a10wd_sc, WDOG_MODE,
+ (wd_intervals[0].value << WDOG_MODE_INTVL_SHIFT) |
+ WDOG_MODE_EN | WDOG_MODE_RST_EN);
+
+ while(1)
+ ;
+
+}
+
+static device_method_t a10wd_methods[] = {
+ DEVMETHOD(device_probe, a10wd_probe),
+ DEVMETHOD(device_attach, a10wd_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t a10wd_driver = {
+ "a10wd",
+ a10wd_methods,
+ sizeof(struct a10wd_softc),
+};
+static devclass_t a10wd_devclass;
+
+DRIVER_MODULE(a10wd, simplebus, a10wd_driver, a10wd_devclass, 0, 0);
Property changes on: trunk/sys/arm/allwinner/a10_wdog.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a10_wdog.h
===================================================================
--- trunk/sys/arm/allwinner/a10_wdog.h (rev 0)
+++ trunk/sys/arm/allwinner/a10_wdog.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,36 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/allwinner/a10_wdog.h 246660 2013-02-11 11:31:23Z gonzo $
+ *
+ */
+#ifndef __A10_WDOG_H__
+#define __A10_WDOG_H__
+
+void a10wd_watchdog_reset(void);
+
+#endif /*__A10_WDOG_H__*/
+
Property changes on: trunk/sys/arm/allwinner/a10_wdog.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a20/a20_cpu_cfg.c
===================================================================
--- trunk/sys/arm/allwinner/a20/a20_cpu_cfg.c (rev 0)
+++ trunk/sys/arm/allwinner/a20/a20_cpu_cfg.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,139 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* CPU configuration module for Allwinner A20 */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a20/a20_cpu_cfg.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include "a20_cpu_cfg.h"
+
+struct a20_cpu_cfg_softc {
+ struct resource *res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct a20_cpu_cfg_softc *a20_cpu_cfg_sc = NULL;
+
+#define cpu_cfg_read_4(sc, reg) \
+ bus_space_read_4((sc)->bst, (sc)->bsh, (reg))
+#define cpu_cfg_write_4(sc, reg, val) \
+ bus_space_write_4((sc)->bst, (sc)->bsh, (reg), (val))
+
+static int
+a20_cpu_cfg_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "allwinner,sun7i-cpu-cfg")) {
+ device_set_desc(dev, "A20 CPU Configuration Module");
+ return(BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+a20_cpu_cfg_attach(device_t dev)
+{
+ struct a20_cpu_cfg_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ if (a20_cpu_cfg_sc)
+ return (ENXIO);
+
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res);
+ sc->bsh = rman_get_bushandle(sc->res);
+
+ a20_cpu_cfg_sc = sc;
+
+ return (0);
+}
+
+static device_method_t a20_cpu_cfg_methods[] = {
+ DEVMETHOD(device_probe, a20_cpu_cfg_probe),
+ DEVMETHOD(device_attach, a20_cpu_cfg_attach),
+ { 0, 0 }
+};
+
+static driver_t a20_cpu_cfg_driver = {
+ "a20_cpu_cfg",
+ a20_cpu_cfg_methods,
+ sizeof(struct a20_cpu_cfg_softc),
+};
+
+static devclass_t a20_cpu_cfg_devclass;
+
+DRIVER_MODULE(a20_cpu_cfg, simplebus, a20_cpu_cfg_driver, a20_cpu_cfg_devclass, 0, 0);
+
+uint64_t
+a20_read_counter64(void)
+{
+ uint32_t lo, hi;
+
+ /* Latch counter, wait for it to be ready to read. */
+ cpu_cfg_write_4(a20_cpu_cfg_sc, OSC24M_CNT64_CTRL_REG, CNT64_RL_EN);
+ while (cpu_cfg_read_4(a20_cpu_cfg_sc, OSC24M_CNT64_CTRL_REG) & CNT64_RL_EN)
+ continue;
+
+ hi = cpu_cfg_read_4(a20_cpu_cfg_sc, OSC24M_CNT64_HIGH_REG);
+ lo = cpu_cfg_read_4(a20_cpu_cfg_sc, OSC24M_CNT64_LOW_REG);
+
+ return (((uint64_t)hi << 32) | lo);
+}
+
Property changes on: trunk/sys/arm/allwinner/a20/a20_cpu_cfg.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a20/a20_cpu_cfg.h
===================================================================
--- trunk/sys/arm/allwinner/a20/a20_cpu_cfg.h (rev 0)
+++ trunk/sys/arm/allwinner/a20/a20_cpu_cfg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,68 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/allwinner/a20/a20_cpu_cfg.h 266337 2014-05-17 18:53:36Z ian $
+ */
+
+#ifndef _A20_CPU_CFG_H_
+#define _A20_CPU_CFG_H_
+
+#define CPU_CFG_BASE 0xe1c25c00
+
+#define CPU0_RST_CTRL 0x0040
+#define CPU0_CTRL_REG 0x0044
+#define CPU0_STATUS_REG 0x0048
+
+#define CPU1_RST_CTRL 0x0080
+#define CPU1_CTRL_REG 0x0084
+#define CPU1_STATUS_REG 0x0088
+
+#define GENER_CTRL_REG 0x0184
+
+#define EVENT_IN_REG 0x0190
+#define PRIVATE_REG 0x01a4
+
+#define IDLE_CNT0_LOW_REG 0x0200
+#define IDLE_CNT0_HIGH_REG 0x0204
+#define IDLE_CNT0_CTRL_REG 0x0208
+
+#define IDLE_CNT1_LOW_REG 0x0210
+#define IDLE_CNT1_HIGH_REG 0x0214
+#define IDLE_CNT1_CTRL_REG 0x0218
+
+#define OSC24M_CNT64_CTRL_REG 0x0280
+#define OSC24M_CNT64_LOW_REG 0x0284
+#define OSC24M_CNT64_HIGH_REG 0x0288
+
+#define LOSC_CNT64_CTRL_REG 0x0290
+#define LOSC_CNT64_LOW_REG 0x0294
+#define LOSC_CNT64_HIGH_REG 0x0298
+
+#define CNT64_RL_EN 0x02 /* read latch enable */
+
+uint64_t a20_read_counter64(void);
+
+#endif /* _A20_CPU_CFG_H_ */
Property changes on: trunk/sys/arm/allwinner/a20/a20_cpu_cfg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a20/a20_mp.c
===================================================================
--- trunk/sys/arm/allwinner/a20/a20_mp.c (rev 0)
+++ trunk/sys/arm/allwinner/a20/a20_mp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,160 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/a20/a20_mp.c 286052 2015-07-30 00:24:21Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#define CPUCFG_BASE 0x01c25c00
+#define CPUCFG_SIZE 0x400
+
+#define CPU0_RST_CTL 0x40
+#define CPU0_CTL 0x44
+#define CPU0_STATUS 0x48
+#define CPU1_RST_CTL 0x80
+#define CPU1_CTL 0x84
+#define CPU1_STATUS 0x88
+#define CPUCFG_GENCTL 0x184
+#define CPUCFG_P_REG0 0x1a4
+#define CPU1_PWR_CLAMP 0x1b0
+#define CPU1_PWROFF_REG 0x1b4
+#define CPUCFG_DBGCTL0 0x1e0
+#define CPUCFG_DBGCTL1 0x1e4
+
+void
+platform_mp_init_secondary(void)
+{
+
+ gic_init_secondary();
+}
+
+void
+platform_mp_setmaxid(void)
+{
+ int ncpu;
+
+ if (mp_ncpus != 0)
+ return;
+
+ /* Read the number of cores from the CP15 L2 Control Register. */
+ __asm __volatile("mrc p15, 1, %0, c9, c0, 2" : "=r" (ncpu));
+ ncpu = ((ncpu >> 24) & 0x3) + 1;
+
+ mp_ncpus = ncpu;
+ mp_maxid = ncpu - 1;
+}
+
+int
+platform_mp_probe(void)
+{
+
+ if (mp_ncpus == 0)
+ platform_mp_setmaxid();
+
+ return (mp_ncpus > 1);
+}
+
+void
+platform_mp_start_ap(void)
+{
+ bus_space_handle_t cpucfg;
+
+ uint32_t val;
+
+ if (bus_space_map(fdtbus_bs_tag, CPUCFG_BASE, CPUCFG_SIZE, 0,
+ &cpucfg) != 0)
+ panic("Couldn't map the CPUCFG\n");
+
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_P_REG0,
+ pmap_kextract((vm_offset_t)mpentry));
+
+ /*
+ * Assert nCOREPORESET low and set L1RSTDISABLE low.
+ * Ensure DBGPWRDUP is set to LOW to prevent any external
+ * debug access to the processor.
+ */
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 0);
+
+ /* Set L1RSTDISABLE low */
+ val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL);
+ val &= ~(1 << 1);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL, val);
+
+ /* Set DBGPWRDUP low */
+ val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1);
+ val &= ~(1 << 1);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val);
+
+ /* Release power clamp */
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0xff);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x7f);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x3f);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x1f);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x0f);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x07);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x03);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x01);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x00);
+ DELAY(10000);
+
+ /* Clear power-off gating */
+ val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG);
+ val &= ~(1 << 0);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG, val);
+ DELAY(1000);
+
+ /* De-assert cpu core reset */
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 3);
+
+ /* Assert DBGPWRDUP signal */
+ val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1);
+ val |= (1 << 1);
+ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val);
+
+ armv7_sev();
+ bus_space_unmap(fdtbus_bs_tag, cpucfg, CPUCFG_SIZE);
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+
+ pic_ipi_send(cpus, ipi);
+}
Property changes on: trunk/sys/arm/allwinner/a20/a20_mp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a20/files.a20
===================================================================
--- trunk/sys/arm/allwinner/a20/files.a20 (rev 0)
+++ trunk/sys/arm/allwinner/a20/files.a20 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,23 @@
+# $FreeBSD: stable/10/sys/arm/allwinner/a20/files.a20 278727 2015-02-13 22:32:02Z ian $
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+arm/arm/gic.c standard
+
+arm/allwinner/a20/a20_cpu_cfg.c standard
+arm/allwinner/a10_clk.c standard
+arm/allwinner/a10_sramc.c standard
+arm/allwinner/a10_gpio.c optional gpio
+arm/allwinner/a10_ehci.c optional ehci
+arm/allwinner/if_emac.c optional emac
+arm/allwinner/a10_wdog.c standard
+arm/allwinner/timer.c standard
+arm/arm/bus_space_base.c standard
+arm/allwinner/a10_common.c standard
+arm/allwinner/a10_machdep.c standard
+arm/allwinner/a20/a20_mp.c optional smp
Property changes on: trunk/sys/arm/allwinner/a20/files.a20
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/allwinner/a20/std.a20
===================================================================
--- trunk/sys/arm/allwinner/a20/std.a20 (rev 0)
+++ trunk/sys/arm/allwinner/a20/std.a20 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,25 @@
+# Allwinner A20 common options
+#$FreeBSD: stable/10/sys/arm/allwinner/a20/std.a20 278601 2015-02-11 22:47:48Z ian $
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+makeoption ARM_LITTLE_ENDIAN
+
+# Physical memory starts at 0x40200000. We assume images are loaded at
+# 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel'
+#
+#
+options PHYSADDR=0x40000000
+
+makeoptions KERNPHYSADDR=0x40200000
+options KERNPHYSADDR=0x40200000
+makeoptions KERNVIRTADDR=0xc0200000
+options KERNVIRTADDR=0xc0200000
+
+options ARM_L2_PIPT
+
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
+
+files "../allwinner/a20/files.a20"
Property changes on: trunk/sys/arm/allwinner/a20/std.a20
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/allwinner/aintc.c
===================================================================
--- trunk/sys/arm/allwinner/aintc.c (rev 0)
+++ trunk/sys/arm/allwinner/aintc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,216 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/aintc.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/**
+ * Interrupt controller registers
+ *
+ */
+#define SW_INT_VECTOR_REG 0x00
+#define SW_INT_BASE_ADR_REG 0x04
+#define SW_INT_PROTECTION_REG 0x08
+#define SW_INT_NMI_CTRL_REG 0x0c
+
+#define SW_INT_IRQ_PENDING_REG0 0x10
+#define SW_INT_IRQ_PENDING_REG1 0x14
+#define SW_INT_IRQ_PENDING_REG2 0x18
+
+#define SW_INT_FIQ_PENDING_REG0 0x20
+#define SW_INT_FIQ_PENDING_REG1 0x24
+#define SW_INT_FIQ_PENDING_REG2 0x28
+
+#define SW_INT_SELECT_REG0 0x30
+#define SW_INT_SELECT_REG1 0x34
+#define SW_INT_SELECT_REG2 0x38
+
+#define SW_INT_ENABLE_REG0 0x40
+#define SW_INT_ENABLE_REG1 0x44
+#define SW_INT_ENABLE_REG2 0x48
+
+#define SW_INT_MASK_REG0 0x50
+#define SW_INT_MASK_REG1 0x54
+#define SW_INT_MASK_REG2 0x58
+
+#define SW_INT_IRQNO_ENMI 0
+
+#define SW_INT_IRQ_PENDING_REG(_b) (0x10 + ((_b) * 4))
+#define SW_INT_FIQ_PENDING_REG(_b) (0x20 + ((_b) * 4))
+#define SW_INT_SELECT_REG(_b) (0x30 + ((_b) * 4))
+#define SW_INT_ENABLE_REG(_b) (0x40 + ((_b) * 4))
+#define SW_INT_MASK_REG(_b) (0x50 + ((_b) * 4))
+
+struct a10_aintc_softc {
+ device_t sc_dev;
+ struct resource * aintc_res;
+ bus_space_tag_t aintc_bst;
+ bus_space_handle_t aintc_bsh;
+ uint8_t ver;
+};
+
+static struct a10_aintc_softc *a10_aintc_sc = NULL;
+
+#define aintc_read_4(reg) \
+ bus_space_read_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg)
+#define aintc_write_4(reg, val) \
+ bus_space_write_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg, val)
+
+static int
+a10_aintc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-ic"))
+ return (ENXIO);
+ device_set_desc(dev, "A10 AINTC Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_aintc_attach(device_t dev)
+{
+ struct a10_aintc_softc *sc = device_get_softc(dev);
+ int rid = 0;
+ int i;
+
+ sc->sc_dev = dev;
+
+ if (a10_aintc_sc)
+ return (ENXIO);
+
+ sc->aintc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->aintc_res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->aintc_bst = rman_get_bustag(sc->aintc_res);
+ sc->aintc_bsh = rman_get_bushandle(sc->aintc_res);
+
+ a10_aintc_sc = sc;
+
+ /* Disable & clear all interrupts */
+ for (i = 0; i < 3; i++) {
+ aintc_write_4(SW_INT_ENABLE_REG(i), 0);
+ aintc_write_4(SW_INT_MASK_REG(i), 0xffffffff);
+ }
+ /* enable protection mode*/
+ aintc_write_4(SW_INT_PROTECTION_REG, 0x01);
+
+ /* config the external interrupt source type*/
+ aintc_write_4(SW_INT_NMI_CTRL_REG, 0x00);
+
+ return (0);
+}
+
+static device_method_t a10_aintc_methods[] = {
+ DEVMETHOD(device_probe, a10_aintc_probe),
+ DEVMETHOD(device_attach, a10_aintc_attach),
+ { 0, 0 }
+};
+
+static driver_t a10_aintc_driver = {
+ "aintc",
+ a10_aintc_methods,
+ sizeof(struct a10_aintc_softc),
+};
+
+static devclass_t a10_aintc_devclass;
+
+DRIVER_MODULE(aintc, simplebus, a10_aintc_driver, a10_aintc_devclass, 0, 0);
+
+int
+arm_get_next_irq(int last_irq)
+{
+ uint32_t value;
+ int i, b;
+
+ for (i = 0; i < 3; i++) {
+ value = aintc_read_4(SW_INT_IRQ_PENDING_REG(i));
+ for (b = 0; b < 32; b++)
+ if (value & (1 << b)) {
+ return (i * 32 + b);
+ }
+ }
+
+ return (-1);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ uint32_t bit, block, value;
+
+ bit = (nb % 32);
+ block = (nb / 32);
+
+ value = aintc_read_4(SW_INT_ENABLE_REG(block));
+ value &= ~(1 << bit);
+ aintc_write_4(SW_INT_ENABLE_REG(block), value);
+
+ value = aintc_read_4(SW_INT_MASK_REG(block));
+ value |= (1 << bit);
+ aintc_write_4(SW_INT_MASK_REG(block), value);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ uint32_t bit, block, value;
+
+ bit = (nb % 32);
+ block = (nb / 32);
+
+ value = aintc_read_4(SW_INT_ENABLE_REG(block));
+ value |= (1 << bit);
+ aintc_write_4(SW_INT_ENABLE_REG(block), value);
+
+ value = aintc_read_4(SW_INT_MASK_REG(block));
+ value &= ~(1 << bit);
+ aintc_write_4(SW_INT_MASK_REG(block), value);
+
+ if(nb == SW_INT_IRQNO_ENMI) /* must clear pending bit when enabled */
+ aintc_write_4(SW_INT_IRQ_PENDING_REG(0), (1 << SW_INT_IRQNO_ENMI));
+}
Property changes on: trunk/sys/arm/allwinner/aintc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/console.c
===================================================================
--- trunk/sys/arm/allwinner/console.c (rev 0)
+++ trunk/sys/arm/allwinner/console.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,143 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Simple UART console driver for Allwinner A10 */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/console.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cons.h>
+#include <sys/consio.h>
+#include <sys/kernel.h>
+
+#ifndef A10_UART_BASE
+#define A10_UART_BASE 0xe1c28000 /* UART0 */
+#endif
+
+#define REG_SHIFT 2
+
+#define UART_DLL 0 /* Out: Divisor Latch Low */
+#define UART_DLM 1 /* Out: Divisor Latch High */
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+
+static uint32_t
+uart_getreg(uint32_t *bas)
+{
+ return *((volatile uint32_t *)(bas)) & 0xff;
+}
+
+static void
+uart_setreg(uint32_t *bas, uint32_t val)
+{
+ *((volatile uint32_t *)(bas)) = val;
+}
+
+static int
+ub_getc(void)
+{
+ while ((uart_getreg((uint32_t *)(A10_UART_BASE +
+ (UART_LSR << REG_SHIFT))) & UART_LSR_DR) == 0);
+ __asm __volatile("nop");
+
+ return (uart_getreg((uint32_t *)A10_UART_BASE) & 0xff);
+}
+
+static void
+ub_putc(unsigned char c)
+{
+ if (c == '\n')
+ ub_putc('\r');
+
+ while ((uart_getreg((uint32_t *)(A10_UART_BASE +
+ (UART_LSR << REG_SHIFT))) & UART_LSR_THRE) == 0)
+ __asm __volatile("nop");
+
+ uart_setreg((uint32_t *)A10_UART_BASE, c);
+}
+
+static cn_probe_t uart_cnprobe;
+static cn_init_t uart_cninit;
+static cn_term_t uart_cnterm;
+static cn_getc_t uart_cngetc;
+static cn_putc_t uart_cnputc;
+static cn_grab_t uart_cngrab;
+static cn_ungrab_t uart_cnungrab;
+
+static void
+uart_cngrab(struct consdev *cp)
+{
+}
+
+static void
+uart_cnungrab(struct consdev *cp)
+{
+}
+
+
+static void
+uart_cnprobe(struct consdev *cp)
+{
+ sprintf(cp->cn_name, "uart");
+ cp->cn_pri = CN_NORMAL;
+}
+
+static void
+uart_cninit(struct consdev *cp)
+{
+ uart_setreg((uint32_t *)(A10_UART_BASE +
+ (UART_FCR << REG_SHIFT)), 0x06);
+}
+
+void
+uart_cnputc(struct consdev *cp, int c)
+{
+ ub_putc(c);
+}
+
+int
+uart_cngetc(struct consdev * cp)
+{
+ return ub_getc();
+}
+
+static void
+uart_cnterm(struct consdev * cp)
+{
+}
+
+CONSOLE_DRIVER(uart);
+
Property changes on: trunk/sys/arm/allwinner/console.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/files.a10
===================================================================
--- trunk/sys/arm/allwinner/files.a10 (rev 0)
+++ trunk/sys/arm/allwinner/files.a10 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,23 @@
+# $FreeBSD: stable/10/sys/arm/allwinner/files.a10 278727 2015-02-13 22:32:02Z ian $
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+
+arm/allwinner/a10_clk.c standard
+arm/allwinner/a10_common.c standard
+arm/allwinner/a10_gpio.c optional gpio
+arm/allwinner/a10_ehci.c optional ehci
+arm/allwinner/a10_machdep.c standard
+arm/allwinner/a10_sramc.c standard
+arm/allwinner/a10_wdog.c standard
+arm/allwinner/a20/a20_cpu_cfg.c standard
+arm/allwinner/aintc.c standard
+arm/allwinner/if_emac.c optional emac
+arm/allwinner/timer.c standard
+arm/arm/bus_space_base.c standard
+#arm/allwinner/console.c standard
Property changes on: trunk/sys/arm/allwinner/files.a10
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/allwinner/if_emac.c
===================================================================
--- trunk/sys/arm/allwinner/if_emac.c (rev 0)
+++ trunk/sys/arm/allwinner/if_emac.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1153 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/allwinner/if_emac.c 266337 2014-05-17 18:53:36Z ian $
+ */
+
+/* A10/A20 EMAC driver */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/if_emac.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_mib.h>
+#include <net/ethernet.h>
+#include <net/if_vlan_var.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <arm/allwinner/if_emacreg.h>
+
+#include "miibus_if.h"
+
+#include "gpio_if.h"
+
+#include "a10_clk.h"
+#include "a10_sramc.h"
+#include "a10_gpio.h"
+
+struct emac_softc {
+ struct ifnet *emac_ifp;
+ device_t emac_dev;
+ device_t emac_miibus;
+ bus_space_handle_t emac_handle;
+ bus_space_tag_t emac_tag;
+ struct resource *emac_res;
+ struct resource *emac_irq;
+ void *emac_intrhand;
+ int emac_if_flags;
+ struct mtx emac_mtx;
+ struct callout emac_tick_ch;
+ int emac_watchdog_timer;
+ int emac_rx_process_limit;
+ int emac_link;
+};
+
+static int emac_probe(device_t);
+static int emac_attach(device_t);
+static int emac_detach(device_t);
+static int emac_shutdown(device_t);
+static int emac_suspend(device_t);
+static int emac_resume(device_t);
+
+static void emac_sys_setup(void);
+static void emac_reset(struct emac_softc *);
+
+static void emac_init_locked(struct emac_softc *);
+static void emac_start_locked(struct ifnet *);
+static void emac_init(void *);
+static void emac_stop_locked(struct emac_softc *);
+static void emac_intr(void *);
+static int emac_ioctl(struct ifnet *, u_long, caddr_t);
+
+static void emac_rxeof(struct emac_softc *, int);
+static void emac_txeof(struct emac_softc *);
+
+static int emac_miibus_readreg(device_t, int, int);
+static int emac_miibus_writereg(device_t, int, int, int);
+static void emac_miibus_statchg(device_t);
+
+static int emac_ifmedia_upd(struct ifnet *);
+static void emac_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
+static int sysctl_hw_emac_proc_limit(SYSCTL_HANDLER_ARGS);
+
+#define EMAC_READ_REG(sc, reg) \
+ bus_space_read_4(sc->emac_tag, sc->emac_handle, reg)
+#define EMAC_WRITE_REG(sc, reg, val) \
+ bus_space_write_4(sc->emac_tag, sc->emac_handle, reg, val)
+
+static void
+emac_sys_setup(void)
+{
+ int i;
+
+ a10_clk_emac_activate();
+
+ /*
+ * Configure pin mux settings for MII.
+ * Pins PA0 from PA17.
+ */
+ for (i = 0; i <= 17; i++)
+ a10_emac_gpio_config(i);
+ /* Map sram */
+ a10_map_to_emac();
+}
+
+static void
+emac_get_hwaddr(struct emac_softc *sc, uint8_t *hwaddr)
+{
+ uint32_t val0, val1, rnd;
+
+ /*
+ * Try to get MAC address from running hardware.
+ * If there is something non-zero there just use it.
+ *
+ * Otherwise set the address to a convenient locally assigned address,
+ * 'bsd' + random 24 low-order bits. 'b' is 0x62, which has the locally
+ * assigned bit set, and the broadcast/multicast bit clear.
+ */
+ val0 = EMAC_READ_REG(sc, EMAC_MAC_A0);
+ val1 = EMAC_READ_REG(sc, EMAC_MAC_A1);
+ if ((val0 | val1) != 0 && (val0 | val1) != 0xffffff) {
+ hwaddr[0] = (val1 >> 16) & 0xff;
+ hwaddr[1] = (val1 >> 8) & 0xff;
+ hwaddr[2] = (val1 >> 0) & 0xff;
+ hwaddr[3] = (val0 >> 16) & 0xff;
+ hwaddr[4] = (val0 >> 8) & 0xff;
+ hwaddr[5] = (val0 >> 0) & 0xff;
+ } else {
+ rnd = arc4random() & 0x00ffffff;
+ hwaddr[0] = 'b';
+ hwaddr[1] = 's';
+ hwaddr[2] = 'd';
+ hwaddr[3] = (rnd >> 16) & 0xff;
+ hwaddr[4] = (rnd >> 8) & 0xff;
+ hwaddr[5] = (rnd >> 0) & 0xff;
+ }
+ if (bootverbose)
+ printf("MAC address: %s\n", ether_sprintf(hwaddr));
+}
+
+static void
+emac_set_rx_mode(struct emac_softc *sc)
+{
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ uint32_t h, hashes[2];
+ uint32_t rcr = 0;
+
+ EMAC_ASSERT_LOCKED(sc);
+
+ ifp = sc->emac_ifp;
+
+ rcr = EMAC_READ_REG(sc, EMAC_RX_CTL);
+
+ /* Unicast packet and DA filtering */
+ rcr |= EMAC_RX_UCAD;
+ rcr |= EMAC_RX_DAF;
+
+ hashes[0] = 0;
+ hashes[1] = 0;
+ if (ifp->if_flags & IFF_ALLMULTI) {
+ hashes[0] = 0xffffffff;
+ hashes[1] = 0xffffffff;
+ } else {
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &sc->emac_ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
+ hashes[h >> 5] |= 1 << (h & 0x1f);
+ }
+ if_maddr_runlock(ifp);
+ }
+ rcr |= EMAC_RX_MCO;
+ rcr |= EMAC_RX_MHF;
+ EMAC_WRITE_REG(sc, EMAC_RX_HASH0, hashes[0]);
+ EMAC_WRITE_REG(sc, EMAC_RX_HASH1, hashes[1]);
+
+ if (ifp->if_flags & IFF_BROADCAST) {
+ rcr |= EMAC_RX_BCO;
+ rcr |= EMAC_RX_MCO;
+ }
+
+ if (ifp->if_flags & IFF_PROMISC)
+ rcr |= EMAC_RX_PA;
+ else
+ rcr |= EMAC_RX_UCAD;
+
+ EMAC_WRITE_REG(sc, EMAC_RX_CTL, rcr);
+}
+
+static void
+emac_reset(struct emac_softc *sc)
+{
+
+ EMAC_WRITE_REG(sc, EMAC_CTL, 0);
+ DELAY(200);
+ EMAC_WRITE_REG(sc, EMAC_CTL, 1);
+ DELAY(200);
+}
+
+static void
+emac_txeof(struct emac_softc *sc)
+{
+ struct ifnet *ifp;
+
+ EMAC_ASSERT_LOCKED(sc);
+
+ ifp = sc->emac_ifp;
+ ifp->if_opackets++;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ /* Unarm watchdog timer if no TX */
+ sc->emac_watchdog_timer = 0;
+}
+
+static void
+emac_rxeof(struct emac_softc *sc, int count)
+{
+ struct ifnet *ifp;
+ struct mbuf *m, *m0;
+ uint32_t reg_val, rxcount;
+ int16_t len;
+ uint16_t status;
+ int good_packet, i;
+
+ ifp = sc->emac_ifp;
+ for (; count > 0 &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; count--) {
+ /*
+ * Race warning: The first packet might arrive with
+ * the interrupts disabled, but the second will fix
+ */
+ rxcount = EMAC_READ_REG(sc, EMAC_RX_FBC);
+ if (!rxcount) {
+ /* Had one stuck? */
+ rxcount = EMAC_READ_REG(sc, EMAC_RX_FBC);
+ if (!rxcount)
+ return;
+ }
+ /* Check packet header */
+ reg_val = EMAC_READ_REG(sc, EMAC_RX_IO_DATA);
+ if (reg_val != EMAC_PACKET_HEADER) {
+ /* Packet header is wrong */
+ if (bootverbose)
+ if_printf(ifp, "wrong packet header\n");
+ /* Disable RX */
+ reg_val = EMAC_READ_REG(sc, EMAC_CTL);
+ reg_val &= ~EMAC_CTL_RX_EN;
+ EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
+
+ /* Flush RX FIFO */
+ reg_val = EMAC_READ_REG(sc, EMAC_RX_CTL);
+ reg_val |= EMAC_RX_FLUSH_FIFO;
+ EMAC_WRITE_REG(sc, EMAC_RX_CTL, reg_val);
+ for (i = 100; i > 0; i--) {
+ DELAY(100);
+ if ((EMAC_READ_REG(sc, EMAC_RX_CTL) &
+ EMAC_RX_FLUSH_FIFO) == 0)
+ break;
+ }
+ if (i == 0) {
+ device_printf(sc->emac_dev,
+ "flush FIFO timeout\n");
+ /* Reinitialize controller */
+ emac_init_locked(sc);
+ return;
+ }
+ /* Enable RX */
+ reg_val = EMAC_READ_REG(sc, EMAC_CTL);
+ reg_val |= EMAC_CTL_RX_EN;
+ EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
+
+ return;
+ }
+
+ good_packet = 1;
+
+ /* Get packet size and status */
+ reg_val = EMAC_READ_REG(sc, EMAC_RX_IO_DATA);
+ len = reg_val & 0xffff;
+ status = (reg_val >> 16) & 0xffff;
+
+ if (len < 64) {
+ good_packet = 0;
+ if (bootverbose)
+ if_printf(ifp,
+ "bad packet: len = %i status = %i\n",
+ len, status);
+ ifp->if_ierrors++;
+ }
+#if 0
+ if (status & (EMAC_CRCERR | EMAC_LENERR)) {
+ good_packet = 0;
+ ifp->if_ierrors++;
+ if (status & EMAC_CRCERR)
+ if_printf(ifp, "crc error\n");
+ if (status & EMAC_LENERR)
+ if_printf(ifp, "length error\n");
+ }
+#endif
+ if (good_packet) {
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL)
+ return;
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
+
+ len -= ETHER_CRC_LEN;
+
+ /* Copy entire frame to mbuf first. */
+ bus_space_read_multi_4(sc->emac_tag, sc->emac_handle,
+ EMAC_RX_IO_DATA, mtod(m, uint32_t *),
+ roundup2(len, 4) / 4);
+
+ m->m_pkthdr.rcvif = ifp;
+ m->m_len = m->m_pkthdr.len = len;
+
+ /*
+ * Emac controller needs strict aligment, so to avoid
+ * copying over an entire frame to align, we allocate
+ * a new mbuf and copy ethernet header + IP header to
+ * the new mbuf. The new mbuf is prepended into the
+ * existing mbuf chain.
+ */
+ if (m->m_len <= (MHLEN - ETHER_HDR_LEN)) {
+ bcopy(m->m_data, m->m_data + ETHER_HDR_LEN,
+ m->m_len);
+ m->m_data += ETHER_HDR_LEN;
+ } else if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN) &&
+ m->m_len > (MHLEN - ETHER_HDR_LEN)) {
+ MGETHDR(m0, M_NOWAIT, MT_DATA);
+ if (m0 != NULL) {
+ len = ETHER_HDR_LEN +
+ m->m_pkthdr.l2hlen;
+ bcopy(m->m_data, m0->m_data, len);
+ m->m_data += len;
+ m->m_len -= len;
+ m0->m_len = len;
+ M_MOVE_PKTHDR(m0, m);
+ m0->m_next = m;
+ m = m0;
+ } else {
+ ifp->if_ierrors++;
+ m_freem(m);
+ m = NULL;
+ continue;
+ }
+ } else if (m->m_len > EMAC_MAC_MAXF) {
+ ifp->if_ierrors++;
+ m_freem(m);
+ m = NULL;
+ continue;
+ }
+ ifp->if_ipackets++;
+ EMAC_UNLOCK(sc);
+ (*ifp->if_input)(ifp, m);
+ EMAC_LOCK(sc);
+ }
+ }
+}
+
+static void
+emac_watchdog(struct emac_softc *sc)
+{
+ struct ifnet *ifp;
+
+ EMAC_ASSERT_LOCKED(sc);
+
+ if (sc->emac_watchdog_timer == 0 || --sc->emac_watchdog_timer)
+ return;
+
+ ifp = sc->emac_ifp;
+
+ if (sc->emac_link == 0) {
+ if (bootverbose)
+ if_printf(sc->emac_ifp, "watchdog timeout "
+ "(missed link)\n");
+ } else
+ if_printf(sc->emac_ifp, "watchdog timeout -- resetting\n");
+
+ ifp->if_oerrors++;
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ emac_init_locked(sc);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ emac_start_locked(ifp);
+}
+
+static void
+emac_tick(void *arg)
+{
+ struct emac_softc *sc;
+ struct mii_data *mii;
+
+ sc = (struct emac_softc *)arg;
+ mii = device_get_softc(sc->emac_miibus);
+ mii_tick(mii);
+
+ emac_watchdog(sc);
+ callout_reset(&sc->emac_tick_ch, hz, emac_tick, sc);
+}
+
+static void
+emac_init(void *xcs)
+{
+ struct emac_softc *sc;
+
+ sc = (struct emac_softc *)xcs;
+ EMAC_LOCK(sc);
+ emac_init_locked(sc);
+ EMAC_UNLOCK(sc);
+}
+
+static void
+emac_init_locked(struct emac_softc *sc)
+{
+ struct ifnet *ifp;
+ struct mii_data *mii;
+ uint32_t reg_val;
+ uint8_t *eaddr;
+
+ EMAC_ASSERT_LOCKED(sc);
+
+ ifp = sc->emac_ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
+ /* Flush RX FIFO */
+ reg_val = EMAC_READ_REG(sc, EMAC_RX_CTL);
+ reg_val |= EMAC_RX_FLUSH_FIFO;
+ EMAC_WRITE_REG(sc, EMAC_RX_CTL, reg_val);
+ DELAY(1);
+
+ /* Soft reset MAC */
+ reg_val = EMAC_READ_REG(sc, EMAC_MAC_CTL0);
+ reg_val &= (~EMAC_MAC_CTL0_SOFT_RST);
+ EMAC_WRITE_REG(sc, EMAC_MAC_CTL0, reg_val);
+
+ /* Set MII clock */
+ reg_val = EMAC_READ_REG(sc, EMAC_MAC_MCFG);
+ reg_val &= (~(0xf << 2));
+ reg_val |= (0xd << 2);
+ EMAC_WRITE_REG(sc, EMAC_MAC_MCFG, reg_val);
+
+ /* Clear RX counter */
+ EMAC_WRITE_REG(sc, EMAC_RX_FBC, 0);
+
+ /* Disable all interrupt and clear interrupt status */
+ EMAC_WRITE_REG(sc, EMAC_INT_CTL, 0);
+ reg_val = EMAC_READ_REG(sc, EMAC_INT_STA);
+ EMAC_WRITE_REG(sc, EMAC_INT_STA, reg_val);
+ DELAY(1);
+
+ /* Set up TX */
+ reg_val = EMAC_READ_REG(sc, EMAC_TX_MODE);
+ reg_val |= EMAC_TX_AB_M;
+ reg_val &= EMAC_TX_TM;
+ EMAC_WRITE_REG(sc, EMAC_TX_MODE, reg_val);
+
+ /* Set up RX */
+ reg_val = EMAC_READ_REG(sc, EMAC_RX_CTL);
+ reg_val |= EMAC_RX_SETUP;
+ reg_val &= EMAC_RX_TM;
+ EMAC_WRITE_REG(sc, EMAC_RX_CTL, reg_val);
+
+ /* Set up MAC CTL0. */
+ reg_val = EMAC_READ_REG(sc, EMAC_MAC_CTL0);
+ reg_val |= EMAC_MAC_CTL0_SETUP;
+ EMAC_WRITE_REG(sc, EMAC_MAC_CTL0, reg_val);
+
+ /* Set up MAC CTL1. */
+ reg_val = EMAC_READ_REG(sc, EMAC_MAC_CTL1);
+ reg_val |= EMAC_MAC_CTL1_SETUP;
+ EMAC_WRITE_REG(sc, EMAC_MAC_CTL1, reg_val);
+
+ /* Set up IPGT */
+ EMAC_WRITE_REG(sc, EMAC_MAC_IPGT, EMAC_MAC_IPGT_FD);
+
+ /* Set up IPGR */
+ EMAC_WRITE_REG(sc, EMAC_MAC_IPGR, EMAC_MAC_NBTB_IPG2 |
+ (EMAC_MAC_NBTB_IPG1 << 8));
+
+ /* Set up Collison window */
+ EMAC_WRITE_REG(sc, EMAC_MAC_CLRT, EMAC_MAC_RM | (EMAC_MAC_CW << 8));
+
+ /* Set up Max Frame Length */
+ EMAC_WRITE_REG(sc, EMAC_MAC_MAXF, EMAC_MAC_MFL);
+
+ /* Setup ethernet address */
+ eaddr = IF_LLADDR(ifp);
+ EMAC_WRITE_REG(sc, EMAC_MAC_A1, eaddr[0] << 16 |
+ eaddr[1] << 8 | eaddr[2]);
+ EMAC_WRITE_REG(sc, EMAC_MAC_A0, eaddr[3] << 16 |
+ eaddr[4] << 8 | eaddr[5]);
+
+ /* Setup rx filter */
+ emac_set_rx_mode(sc);
+
+ /* Enable RX/TX0/RX Hlevel interrupt */
+ reg_val = EMAC_READ_REG(sc, EMAC_INT_CTL);
+ reg_val |= EMAC_INT_EN;
+ EMAC_WRITE_REG(sc, EMAC_INT_CTL, reg_val);
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ sc->emac_link = 0;
+
+ /* Switch to the current media. */
+ mii = device_get_softc(sc->emac_miibus);
+ mii_mediachg(mii);
+
+ callout_reset(&sc->emac_tick_ch, hz, emac_tick, sc);
+}
+
+
+static void
+emac_start(struct ifnet *ifp)
+{
+ struct emac_softc *sc;
+
+ sc = ifp->if_softc;
+ EMAC_LOCK(sc);
+ emac_start_locked(ifp);
+ EMAC_UNLOCK(sc);
+}
+
+static void
+emac_start_locked(struct ifnet *ifp)
+{
+ struct emac_softc *sc;
+ struct mbuf *m, *m0;
+ uint32_t reg_val;
+
+ sc = ifp->if_softc;
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
+ return;
+ if (sc->emac_link == 0)
+ return;
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ return;
+
+ /* Select channel */
+ EMAC_WRITE_REG(sc, EMAC_TX_INS, 0);
+
+ /*
+ * Emac controller wants 4 byte aligned TX buffers.
+ * We have to copy pretty much all the time.
+ */
+ if (m->m_next != NULL || (mtod(m, uintptr_t) & 3) != 0) {
+ m0 = m_defrag(m, M_NOWAIT);
+ if (m0 == NULL) {
+ m_freem(m);
+ m = NULL;
+ return;
+ }
+ m = m0;
+ }
+ /* Write data */
+ bus_space_write_multi_4(sc->emac_tag, sc->emac_handle,
+ EMAC_TX_IO_DATA, mtod(m, uint32_t *),
+ roundup2(m->m_len, 4) / 4);
+
+ /* Send the data lengh. */
+ EMAC_WRITE_REG(sc, EMAC_TX_PL0, m->m_len);
+
+ /* Start translate from fifo to phy. */
+ reg_val = EMAC_READ_REG(sc, EMAC_TX_CTL0);
+ reg_val |= 1;
+ EMAC_WRITE_REG(sc, EMAC_TX_CTL0, reg_val);
+
+ /* Set timeout */
+ sc->emac_watchdog_timer = 5;
+
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ BPF_MTAP(ifp, m);
+ m_freem(m);
+}
+
+static void
+emac_stop_locked(struct emac_softc *sc)
+{
+ struct ifnet *ifp;
+ uint32_t reg_val;
+
+ EMAC_ASSERT_LOCKED(sc);
+
+ ifp = sc->emac_ifp;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->emac_link = 0;
+
+ /* Disable all interrupt and clear interrupt status */
+ EMAC_WRITE_REG(sc, EMAC_INT_CTL, 0);
+ reg_val = EMAC_READ_REG(sc, EMAC_INT_STA);
+ EMAC_WRITE_REG(sc, EMAC_INT_STA, reg_val);
+
+ /* Disable RX/TX */
+ reg_val = EMAC_READ_REG(sc, EMAC_CTL);
+ reg_val &= ~(EMAC_CTL_RST | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN);
+ EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
+
+ callout_stop(&sc->emac_tick_ch);
+}
+
+static void
+emac_intr(void *arg)
+{
+ struct emac_softc *sc;
+ struct ifnet *ifp;
+ uint32_t reg_val;
+
+ sc = (struct emac_softc *)arg;
+ EMAC_LOCK(sc);
+ ifp = sc->emac_ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
+ /* Disable all interrupts */
+ EMAC_WRITE_REG(sc, EMAC_INT_CTL, 0);
+ /* Get EMAC interrupt status */
+ reg_val = EMAC_READ_REG(sc, EMAC_INT_STA);
+ /* Clear ISR status */
+ EMAC_WRITE_REG(sc, EMAC_INT_STA, reg_val);
+
+ /* Received incoming packet */
+ if (reg_val & EMAC_INT_STA_RX)
+ emac_rxeof(sc, sc->emac_rx_process_limit);
+
+ /* Transmit Interrupt check */
+ if (reg_val & EMAC_INT_STA_TX){
+ emac_txeof(sc);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ emac_start_locked(ifp);
+ }
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ /* Re-enable interrupt mask */
+ reg_val = EMAC_READ_REG(sc, EMAC_INT_CTL);
+ reg_val |= EMAC_INT_EN;
+ EMAC_WRITE_REG(sc, EMAC_INT_CTL, reg_val);
+ }
+ EMAC_UNLOCK(sc);
+}
+
+static int
+emac_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct emac_softc *sc;
+ struct mii_data *mii;
+ struct ifreq *ifr;
+ int error = 0;
+
+ sc = ifp->if_softc;
+ ifr = (struct ifreq *)data;
+
+ switch (command) {
+ case SIOCSIFFLAGS:
+ EMAC_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ if ((ifp->if_flags ^ sc->emac_if_flags) &
+ (IFF_PROMISC | IFF_ALLMULTI))
+ emac_set_rx_mode(sc);
+ } else
+ emac_init_locked(sc);
+ } else {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ emac_stop_locked(sc);
+ }
+ sc->emac_if_flags = ifp->if_flags;
+ EMAC_UNLOCK(sc);
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ EMAC_LOCK(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ emac_set_rx_mode(sc);
+ }
+ EMAC_UNLOCK(sc);
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ mii = device_get_softc(sc->emac_miibus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+ break;
+ default:
+ error = ether_ioctl(ifp, command, data);
+ break;
+ }
+ return (error);
+}
+
+static int
+emac_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-emac"))
+ return (ENXIO);
+
+ device_set_desc(dev, "A10/A20 EMAC ethernet controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+emac_detach(device_t dev)
+{
+ struct emac_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->emac_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ if (device_is_attached(dev)) {
+ ether_ifdetach(sc->emac_ifp);
+ EMAC_LOCK(sc);
+ emac_stop_locked(sc);
+ EMAC_UNLOCK(sc);
+ callout_drain(&sc->emac_tick_ch);
+ }
+
+ if (sc->emac_intrhand != NULL)
+ bus_teardown_intr(sc->emac_dev, sc->emac_irq,
+ sc->emac_intrhand);
+
+ if (sc->emac_miibus != NULL) {
+ device_delete_child(sc->emac_dev, sc->emac_miibus);
+ bus_generic_detach(sc->emac_dev);
+ }
+
+ if (sc->emac_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->emac_res);
+
+ if (sc->emac_irq != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->emac_irq);
+
+ if (sc->emac_ifp != NULL)
+ if_free(sc->emac_ifp);
+
+ if (mtx_initialized(&sc->emac_mtx))
+ mtx_destroy(&sc->emac_mtx);
+
+ return (0);
+}
+
+static int
+emac_shutdown(device_t dev)
+{
+
+ return (emac_suspend(dev));
+}
+
+static int
+emac_suspend(device_t dev)
+{
+ struct emac_softc *sc;
+ struct ifnet *ifp;
+
+ sc = device_get_softc(dev);
+
+ EMAC_LOCK(sc);
+ ifp = sc->emac_ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ emac_stop_locked(sc);
+ EMAC_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+emac_resume(device_t dev)
+{
+ struct emac_softc *sc;
+ struct ifnet *ifp;
+
+ sc = device_get_softc(dev);
+
+ EMAC_LOCK(sc);
+ ifp = sc->emac_ifp;
+ if ((ifp->if_flags & IFF_UP) != 0) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ emac_init_locked(sc);
+ }
+ EMAC_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+emac_attach(device_t dev)
+{
+ struct emac_softc *sc;
+ struct ifnet *ifp;
+ int error, rid;
+ uint8_t eaddr[ETHER_ADDR_LEN];
+
+ sc = device_get_softc(dev);
+ sc->emac_dev = dev;
+
+ error = 0;
+ mtx_init(&sc->emac_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+ MTX_DEF);
+ callout_init_mtx(&sc->emac_tick_ch, &sc->emac_mtx, 0);
+
+ rid = 0;
+ sc->emac_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->emac_res == NULL) {
+ device_printf(dev, "unable to map memory\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ sc->emac_tag = rman_get_bustag(sc->emac_res);
+ sc->emac_handle = rman_get_bushandle(sc->emac_res);
+
+ rid = 0;
+ sc->emac_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->emac_irq == NULL) {
+ device_printf(dev, "cannot allocate IRQ resources.\n");
+ error = ENXIO;
+ goto fail;
+ }
+ /* Create device sysctl node. */
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "process_limit", CTLTYPE_INT | CTLFLAG_RW,
+ &sc->emac_rx_process_limit, 0, sysctl_hw_emac_proc_limit, "I",
+ "max number of Rx events to process");
+
+ sc->emac_rx_process_limit = EMAC_PROC_DEFAULT;
+ error = resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "process_limit", &sc->emac_rx_process_limit);
+ if (error == 0) {
+ if (sc->emac_rx_process_limit < EMAC_PROC_MIN ||
+ sc->emac_rx_process_limit > EMAC_PROC_MAX) {
+ device_printf(dev, "process_limit value out of range; "
+ "using default: %d\n", EMAC_PROC_DEFAULT);
+ sc->emac_rx_process_limit = EMAC_PROC_DEFAULT;
+ }
+ }
+ /* Setup EMAC */
+ emac_sys_setup();
+ emac_reset(sc);
+
+ ifp = sc->emac_ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "unable to allocate ifp\n");
+ error = ENOSPC;
+ goto fail;
+ }
+ ifp->if_softc = sc;
+
+ /* Setup MII */
+ error = mii_attach(dev, &sc->emac_miibus, ifp, emac_ifmedia_upd,
+ emac_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ if (error != 0) {
+ device_printf(dev, "PHY probe failed\n");
+ goto fail;
+ }
+
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = emac_start;
+ ifp->if_ioctl = emac_ioctl;
+ ifp->if_init = emac_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+
+ /* Get MAC address */
+ emac_get_hwaddr(sc, eaddr);
+ ether_ifattach(ifp, eaddr);
+
+ /* VLAN capability setup. */
+ ifp->if_capabilities |= IFCAP_VLAN_MTU;
+ ifp->if_capenable = ifp->if_capabilities;
+ /* Tell the upper layer we support VLAN over-sized frames. */
+ ifp->if_hdrlen = sizeof(struct ether_vlan_header);
+
+ error = bus_setup_intr(dev, sc->emac_irq, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, emac_intr, sc, &sc->emac_intrhand);
+ if (error != 0) {
+ device_printf(dev, "could not set up interrupt handler.\n");
+ ether_ifdetach(ifp);
+ goto fail;
+ }
+
+fail:
+ if (error != 0)
+ emac_detach(dev);
+ return (error);
+}
+
+static boolean_t
+emac_miibus_iowait(struct emac_softc *sc)
+{
+ uint32_t timeout;
+
+ for (timeout = 100; timeout != 0; --timeout) {
+ DELAY(100);
+ if ((EMAC_READ_REG(sc, EMAC_MAC_MIND) & 0x1) == 0)
+ return (true);
+ }
+
+ return (false);
+}
+
+/*
+ * The MII bus interface
+ */
+static int
+emac_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct emac_softc *sc;
+ int rval;
+
+ sc = device_get_softc(dev);
+
+ /* Issue phy address and reg */
+ EMAC_WRITE_REG(sc, EMAC_MAC_MADR, (phy << 8) | reg);
+ /* Pull up the phy io line */
+ EMAC_WRITE_REG(sc, EMAC_MAC_MCMD, 0x1);
+ if (!emac_miibus_iowait(sc)) {
+ device_printf(dev, "timeout waiting for mii read\n");
+ return (0);
+ }
+ /* Push down the phy io line */
+ EMAC_WRITE_REG(sc, EMAC_MAC_MCMD, 0x0);
+ /* Read data */
+ rval = EMAC_READ_REG(sc, EMAC_MAC_MRDD);
+
+ return (rval);
+}
+
+static int
+emac_miibus_writereg(device_t dev, int phy, int reg, int data)
+{
+ struct emac_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Issue phy address and reg */
+ EMAC_WRITE_REG(sc, EMAC_MAC_MADR, (phy << 8) | reg);
+ /* Write data */
+ EMAC_WRITE_REG(sc, EMAC_MAC_MWTD, data);
+ /* Pull up the phy io line */
+ EMAC_WRITE_REG(sc, EMAC_MAC_MCMD, 0x1);
+ if (!emac_miibus_iowait(sc)) {
+ device_printf(dev, "timeout waiting for mii write\n");
+ return (0);
+ }
+ /* Push down the phy io line */
+ EMAC_WRITE_REG(sc, EMAC_MAC_MCMD, 0x0);
+
+ return (0);
+}
+
+static void
+emac_miibus_statchg(device_t dev)
+{
+ struct emac_softc *sc;
+ struct mii_data *mii;
+ struct ifnet *ifp;
+ uint32_t reg_val;
+
+ sc = device_get_softc(dev);
+
+ mii = device_get_softc(sc->emac_miibus);
+ ifp = sc->emac_ifp;
+ if (mii == NULL || ifp == NULL ||
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
+ sc->emac_link = 0;
+ if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
+ (IFM_ACTIVE | IFM_AVALID)) {
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_10_T:
+ case IFM_100_TX:
+ sc->emac_link = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ /* Program MACs with resolved speed/duplex. */
+ if (sc->emac_link != 0) {
+ reg_val = EMAC_READ_REG(sc, EMAC_MAC_IPGT);
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+ reg_val &= ~EMAC_MAC_IPGT_HD;
+ reg_val |= EMAC_MAC_IPGT_FD;
+ } else {
+ reg_val &= ~EMAC_MAC_IPGT_FD;
+ reg_val |= EMAC_MAC_IPGT_HD;
+ }
+ EMAC_WRITE_REG(sc, EMAC_MAC_IPGT, reg_val);
+ /* Enable RX/TX */
+ reg_val = EMAC_READ_REG(sc, EMAC_CTL);
+ reg_val |= EMAC_CTL_RST | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN;
+ EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
+ } else {
+ /* Disable RX/TX */
+ reg_val = EMAC_READ_REG(sc, EMAC_CTL);
+ reg_val &= ~(EMAC_CTL_RST | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN);
+ EMAC_WRITE_REG(sc, EMAC_CTL, reg_val);
+ }
+}
+
+static int
+emac_ifmedia_upd(struct ifnet *ifp)
+{
+ struct emac_softc *sc;
+ struct mii_data *mii;
+ struct mii_softc *miisc;
+ int error;
+
+ sc = ifp->if_softc;
+ mii = device_get_softc(sc->emac_miibus);
+ EMAC_LOCK(sc);
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ PHY_RESET(miisc);
+ error = mii_mediachg(mii);
+ EMAC_UNLOCK(sc);
+
+ return (error);
+}
+
+static void
+emac_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct emac_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = device_get_softc(sc->emac_miibus);
+
+ EMAC_LOCK(sc);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ EMAC_UNLOCK(sc);
+}
+
+static device_method_t emac_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, emac_probe),
+ DEVMETHOD(device_attach, emac_attach),
+ DEVMETHOD(device_detach, emac_detach),
+ DEVMETHOD(device_shutdown, emac_shutdown),
+ DEVMETHOD(device_suspend, emac_suspend),
+ DEVMETHOD(device_resume, emac_resume),
+
+ /* bus interface, for miibus */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, emac_miibus_readreg),
+ DEVMETHOD(miibus_writereg, emac_miibus_writereg),
+ DEVMETHOD(miibus_statchg, emac_miibus_statchg),
+
+ DEVMETHOD_END
+};
+
+static driver_t emac_driver = {
+ "emac",
+ emac_methods,
+ sizeof(struct emac_softc)
+};
+
+static devclass_t emac_devclass;
+
+DRIVER_MODULE(emac, simplebus, emac_driver, emac_devclass, 0, 0);
+DRIVER_MODULE(miibus, emac, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(emac, miibus, 1, 1, 1);
+MODULE_DEPEND(emac, ether, 1, 1, 1);
+
+static int
+sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
+{
+ int error, value;
+
+ if (arg1 == NULL)
+ return (EINVAL);
+ value = *(int *)arg1;
+ error = sysctl_handle_int(oidp, &value, 0, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ if (value < low || value > high)
+ return (EINVAL);
+ *(int *)arg1 = value;
+
+ return (0);
+}
+
+static int
+sysctl_hw_emac_proc_limit(SYSCTL_HANDLER_ARGS)
+{
+
+ return (sysctl_int_range(oidp, arg1, arg2, req,
+ EMAC_PROC_MIN, EMAC_PROC_MAX));
+}
Property changes on: trunk/sys/arm/allwinner/if_emac.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/if_emacreg.h
===================================================================
--- trunk/sys/arm/allwinner/if_emacreg.h (rev 0)
+++ trunk/sys/arm/allwinner/if_emacreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,240 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (C) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/allwinner/if_emacreg.h 266337 2014-05-17 18:53:36Z ian $
+ */
+
+#ifndef __IF_EMACREG_H__
+#define __IF_EMACREG_H__
+
+/*
+ * EMAC register definitions
+ */
+#define EMAC_CTL 0x00
+#define EMAC_CTL_RST (1 << 0)
+#define EMAC_CTL_TX_EN (1 << 1)
+#define EMAC_CTL_RX_EN (1 << 2)
+
+#define EMAC_TX_MODE 0x04
+#define EMAC_TX_FLOW 0x08
+#define EMAC_TX_CTL0 0x0C
+#define EMAC_TX_CTL1 0x10
+#define EMAC_TX_INS 0x14
+#define EMAC_TX_PL0 0x18
+#define EMAC_TX_PL1 0x1C
+#define EMAC_TX_STA 0x20
+#define EMAC_TX_IO_DATA 0x24
+#define EMAC_TX_IO_DATA1 0x28
+#define EMAC_TX_TSVL0 0x2C
+#define EMAC_TX_TSVH0 0x30
+#define EMAC_TX_TSVL1 0x34
+#define EMAC_TX_TSVH1 0x38
+
+#define EMAC_RX_CTL 0x3C
+#define EMAC_RX_HASH0 0x40
+#define EMAC_RX_HASH1 0x44
+#define EMAC_RX_STA 0x48
+#define EMAC_RX_IO_DATA 0x4C
+#define EMAC_RX_FBC 0x50
+
+#define EMAC_INT_CTL 0x54
+#define EMAC_INT_STA 0x58
+#define EMAC_INT_STA_TX (0x01 | 0x02)
+#define EMAC_INT_STA_RX 0x100
+#define EMAC_INT_EN (0xf << 0) | (1 << 8)
+
+#define EMAC_MAC_CTL0 0x5C
+#define EMAC_MAC_CTL1 0x60
+#define EMAC_MAC_IPGT 0x64
+#define EMAC_MAC_IPGR 0x68
+#define EMAC_MAC_CLRT 0x6C
+#define EMAC_MAC_MAXF 0x70
+#define EMAC_MAC_SUPP 0x74
+#define EMAC_MAC_TEST 0x78
+#define EMAC_MAC_MCFG 0x7C
+#define EMAC_MAC_MCMD 0x80
+#define EMAC_MAC_MADR 0x84
+#define EMAC_MAC_MWTD 0x88
+#define EMAC_MAC_MRDD 0x8C
+#define EMAC_MAC_MIND 0x90
+#define EMAC_MAC_SSRR 0x94
+#define EMAC_MAC_A0 0x98
+#define EMAC_MAC_A1 0x9C
+#define EMAC_MAC_A2 0xA0
+
+#define EMAC_SAFX_L0 0xA4
+#define EMAC_SAFX_H0 0xA8
+#define EMAC_SAFX_L1 0xAC
+#define EMAC_SAFX_H1 0xB0
+#define EMAC_SAFX_L2 0xB4
+#define EMAC_SAFX_H2 0xB8
+#define EMAC_SAFX_L3 0xBC
+#define EMAC_SAFX_H3 0xC0
+
+#define EMAC_PHY_DUPLEX (1 << 8)
+
+/*
+ * Each received packet has 8 bytes header:
+ * Byte 0: Packet valid flag: 0x01 valid, 0x00 not valid
+ * Byte 1: 0x43 -> Ascii code 'C'
+ * Byte 2: 0x41 -> Ascii code 'A'
+ * Byte 3: 0x4d -> Ascii code 'M'
+ * Byte 4: High byte of received packet's status
+ * Byte 5: Low byte of received packet's status
+ * Byte 6: High byte of packet size
+ * Byte 7: Low byte of packet size
+ */
+#define EMAC_PACKET_HEADER (0x0143414d)
+
+/* Aborted frame enable */
+#define EMAC_TX_AB_M (1 << 0)
+
+/* 0: Enable CPU mode for TX, 1: DMA */
+#define EMAC_TX_TM ~(1 << 1)
+
+/* 0: DRQ asserted, 1: DRQ automatically */
+#define EMAC_RX_DRQ_MODE (1 << 1)
+
+/* 0: Enable CPU mode for RX, 1: DMA */
+#define EMAC_RX_TM ~(1 << 2)
+
+/* Pass all Frames */
+#define EMAC_RX_PA (1 << 4)
+
+/* Pass Control Frames */
+#define EMAC_RX_PCF (1 << 5)
+
+/* Pass Frames with CRC Error */
+#define EMAC_RX_PCRCE (1 << 6)
+
+/* Pass Frames with Length Error */
+#define EMAC_RX_PLE (1 << 7)
+
+/* Pass Frames length out of range */
+#define EMAC_RX_POR (1 << 8)
+
+/* Accept unicast Packets */
+#define EMAC_RX_UCAD (1 << 16)
+
+/* Enable DA Filtering */
+#define EMAC_RX_DAF (1 << 17)
+
+/* Accept multicast Packets */
+#define EMAC_RX_MCO (1 << 20)
+
+/* Enable Hash filter */
+#define EMAC_RX_MHF (1 << 21)
+
+/* Accept Broadcast Packets */
+#define EMAC_RX_BCO (1 << 22)
+
+/* Enable SA Filtering */
+#define EMAC_RX_SAF (1 << 24)
+
+/* Inverse Filtering */
+#define EMAC_RX_SAIF (1 << 25)
+
+#define EMAC_RX_SETUP (EMAC_RX_POR | EMAC_RX_UCAD | \
+ EMAC_RX_DAF | EMAC_RX_MCO | EMAC_RX_BCO)
+
+/* Enable Receive Flow Control */
+#define EMAC_MAC_CTL0_RFC (1 << 2)
+
+/* Enable Transmit Flow Control */
+#define EMAC_MAC_CTL0_TFC (1 << 3)
+
+/* Enable soft reset */
+#define EMAC_MAC_CTL0_SOFT_RST (1 << 15)
+
+#define EMAC_MAC_CTL0_SETUP (EMAC_MAC_CTL0_RFC | EMAC_MAC_CTL0_TFC)
+
+/* Enable duplex */
+#define EMAC_MAC_CTL1_DUP (1 << 0)
+
+/* Enable MAC Frame Length Checking */
+#define EMAC_MAC_CTL1_FLC (1 << 1)
+
+/* Enable Huge Frame */
+#define EMAC_MAC_CTL1_HF (1 << 2)
+
+/* Enable MAC Delayed CRC */
+#define EMAC_MAC_CTL1_DCRC (1 << 3)
+
+/* Enable MAC CRC */
+#define EMAC_MAC_CTL1_CRC (1 << 4)
+
+/* Enable MAC PAD Short frames */
+#define EMAC_MAC_CTL1_PC (1 << 5)
+
+/* Enable MAC PAD Short frames and append CRC */
+#define EMAC_MAC_CTL1_VC (1 << 6)
+
+/* Enable MAC auto detect Short frames */
+#define EMAC_MAC_CTL1_ADP (1 << 7)
+
+#define EMAC_MAC_CTL1_PRE (1 << 8)
+#define EMAC_MAC_CTL1_LPE (1 << 9)
+
+/* Enable no back off */
+#define EMAC_MAC_CTL1_NB (1 << 12)
+
+#define EMAC_MAC_CTL1_BNB (1 << 13)
+#define EMAC_MAC_CTL1_ED (1 << 14)
+
+#define EMAC_MAC_CTL1_SETUP (EMAC_MAC_CTL1_FLC | EMAC_MAC_CTL1_CRC | \
+ EMAC_MAC_CTL1_PC)
+
+/* half duplex */
+#define EMAC_MAC_IPGT_HD 0x12
+
+/* full duplex */
+#define EMAC_MAC_IPGT_FD 0x15
+
+#define EMAC_MAC_NBTB_IPG1 0xC
+#define EMAC_MAC_NBTB_IPG2 0x12
+
+#define EMAC_MAC_CW 0x37
+#define EMAC_MAC_RM 0xF
+
+#define EMAC_MAC_MFL 0x0600
+
+/* Receive status */
+#define EMAC_CRCERR (1 << 4)
+#define EMAC_LENERR (3 << 5)
+
+#define EMAC_RX_FLUSH_FIFO (1 << 3)
+#define EMAC_PHY_RESET (1 << 15)
+#define EMAC_PHY_PWRDOWN (1 << 11)
+
+#define EMAC_PROC_MIN 16
+#define EMAC_PROC_MAX 255
+#define EMAC_PROC_DEFAULT 64
+
+#define EMAC_LOCK(cs) mtx_lock(&(sc)->emac_mtx)
+#define EMAC_UNLOCK(cs) mtx_unlock(&(sc)->emac_mtx)
+#define EMAC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->emac_mtx, MA_OWNED);
+
+#endif /* __IF_EMACREG_H__ */
Property changes on: trunk/sys/arm/allwinner/if_emacreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/allwinner/std.a10
===================================================================
--- trunk/sys/arm/allwinner/std.a10 (rev 0)
+++ trunk/sys/arm/allwinner/std.a10 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,20 @@
+# Allwinner A10 common options
+#$FreeBSD: stable/10/sys/arm/allwinner/std.a10 278601 2015-02-11 22:47:48Z ian $
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+makeoption ARM_LITTLE_ENDIAN
+
+# Physical memory starts at 0x40200000. We assume images are loaded at
+# 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel'
+#
+#
+options PHYSADDR=0x40000000
+
+makeoptions KERNPHYSADDR=0x40200000
+options KERNPHYSADDR=0x40200000
+makeoptions KERNVIRTADDR=0xc0200000
+options KERNVIRTADDR=0xc0200000
+
+files "../allwinner/files.a10"
Property changes on: trunk/sys/arm/allwinner/std.a10
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/allwinner/timer.c
===================================================================
--- trunk/sys/arm/allwinner/timer.c (rev 0)
+++ trunk/sys/arm/allwinner/timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,378 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/allwinner/timer.c 277113 2015-01-13 07:45:16Z ganbold $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <sys/kdb.h>
+
+#include "a20/a20_cpu_cfg.h"
+
+/**
+ * Timer registers addr
+ *
+ */
+#define SW_TIMER_IRQ_EN_REG 0x00
+#define SW_TIMER_IRQ_STA_REG 0x04
+#define SW_TIMER0_CTRL_REG 0x10
+#define SW_TIMER0_INT_VALUE_REG 0x14
+#define SW_TIMER0_CUR_VALUE_REG 0x18
+
+#define SW_COUNTER64LO_REG 0xa4
+#define SW_COUNTER64HI_REG 0xa8
+#define CNT64_CTRL_REG 0xa0
+
+#define CNT64_RL_EN 0x02 /* read latch enable */
+
+#define TIMER_ENABLE (1<<0)
+#define TIMER_AUTORELOAD (1<<1)
+#define TIMER_OSC24M (1<<2) /* oscillator = 24mhz */
+#define TIMER_PRESCALAR (0<<4) /* prescalar = 1 */
+
+#define SYS_TIMER_CLKSRC 24000000 /* clock source */
+
+struct a10_timer_softc {
+ device_t sc_dev;
+ struct resource *res[2];
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ void *sc_ih; /* interrupt handler */
+ uint32_t sc_period;
+ uint32_t timer0_freq;
+ struct eventtimer et;
+ uint8_t sc_timer_type; /* 0 for A10, 1 for A20 */
+};
+
+int a10_timer_get_timerfreq(struct a10_timer_softc *);
+
+#define timer_read_4(sc, reg) \
+ bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg)
+#define timer_write_4(sc, reg, val) \
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val)
+
+static u_int a10_timer_get_timecount(struct timecounter *);
+static int a10_timer_timer_start(struct eventtimer *,
+ sbintime_t first, sbintime_t period);
+static int a10_timer_timer_stop(struct eventtimer *);
+
+static uint64_t timer_read_counter64(void);
+
+static int a10_timer_initialized = 0;
+static int a10_timer_hardclock(void *);
+static int a10_timer_probe(device_t);
+static int a10_timer_attach(device_t);
+
+static struct timecounter a10_timer_timecounter = {
+ .tc_name = "a10_timer timer0",
+ .tc_get_timecount = a10_timer_get_timecount,
+ .tc_counter_mask = ~0u,
+ .tc_frequency = 0,
+ .tc_quality = 1000,
+};
+
+struct a10_timer_softc *a10_timer_sc = NULL;
+
+static struct resource_spec a10_timer_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static uint64_t
+timer_read_counter64(void)
+{
+ uint32_t lo, hi;
+
+ /* In case of A20 get appropriate counter info */
+ if (a10_timer_sc->sc_timer_type)
+ return (a20_read_counter64());
+
+ /* Latch counter, wait for it to be ready to read. */
+ timer_write_4(a10_timer_sc, CNT64_CTRL_REG, CNT64_RL_EN);
+ while (timer_read_4(a10_timer_sc, CNT64_CTRL_REG) & CNT64_RL_EN)
+ continue;
+
+ hi = timer_read_4(a10_timer_sc, SW_COUNTER64HI_REG);
+ lo = timer_read_4(a10_timer_sc, SW_COUNTER64LO_REG);
+
+ return (((uint64_t)hi << 32) | lo);
+}
+
+static int
+a10_timer_probe(device_t dev)
+{
+ struct a10_timer_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (ofw_bus_is_compatible(dev, "allwinner,sun4i-timer"))
+ sc->sc_timer_type = 0;
+ else if (ofw_bus_is_compatible(dev, "allwinner,sun7i-timer"))
+ sc->sc_timer_type = 1;
+ else
+ return (ENXIO);
+
+ device_set_desc(dev, "Allwinner A10/A20 timer");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_timer_attach(device_t dev)
+{
+ struct a10_timer_softc *sc;
+ int err;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, a10_timer_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->sc_dev = dev;
+ sc->sc_bst = rman_get_bustag(sc->res[0]);
+ sc->sc_bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Setup and enable the timer interrupt */
+ err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, a10_timer_hardclock,
+ NULL, sc, &sc->sc_ih);
+ if (err != 0) {
+ bus_release_resources(dev, a10_timer_spec, sc->res);
+ device_printf(dev, "Unable to setup the clock irq handler, "
+ "err = %d\n", err);
+ return (ENXIO);
+ }
+
+ /* Set clock source to OSC24M, 16 pre-division */
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ val |= TIMER_PRESCALAR | TIMER_OSC24M;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ /* Enable timer0 */
+ val = timer_read_4(sc, SW_TIMER_IRQ_EN_REG);
+ val |= TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER_IRQ_EN_REG, val);
+
+ sc->timer0_freq = SYS_TIMER_CLKSRC;
+
+ /* Set desired frequency in event timer and timecounter */
+ sc->et.et_frequency = sc->timer0_freq;
+ sc->et.et_name = "a10_timer Eventtimer";
+ sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
+ sc->et.et_quality = 1000;
+ sc->et.et_min_period = (0x00000005LLU << 32) / sc->et.et_frequency;
+ sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
+ sc->et.et_start = a10_timer_timer_start;
+ sc->et.et_stop = a10_timer_timer_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ if (device_get_unit(dev) == 0)
+ a10_timer_sc = sc;
+
+ a10_timer_timecounter.tc_frequency = sc->timer0_freq;
+ tc_init(&a10_timer_timecounter);
+
+ if (bootverbose) {
+ device_printf(sc->sc_dev, "clock: hz=%d stathz = %d\n", hz, stathz);
+
+ device_printf(sc->sc_dev, "event timer clock frequency %u\n",
+ sc->timer0_freq);
+ device_printf(sc->sc_dev, "timecounter clock frequency %lld\n",
+ a10_timer_timecounter.tc_frequency);
+ }
+
+ a10_timer_initialized = 1;
+
+ return (0);
+}
+
+static int
+a10_timer_timer_start(struct eventtimer *et, sbintime_t first,
+ sbintime_t period)
+{
+ struct a10_timer_softc *sc;
+ uint32_t count;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)et->et_priv;
+
+ if (period != 0)
+ sc->sc_period = ((uint32_t)et->et_frequency * period) >> 32;
+ else
+ sc->sc_period = 0;
+ if (first != 0)
+ count = ((uint32_t)et->et_frequency * first) >> 32;
+ else
+ count = sc->sc_period;
+
+ /* Update timer values */
+ timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, sc->sc_period);
+ timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, count);
+
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ if (period != 0) {
+ /* periodic */
+ val |= TIMER_AUTORELOAD;
+ } else {
+ /* oneshot */
+ val &= ~TIMER_AUTORELOAD;
+ }
+ /* Enable timer0 */
+ val |= TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ return (0);
+}
+
+static int
+a10_timer_timer_stop(struct eventtimer *et)
+{
+ struct a10_timer_softc *sc;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)et->et_priv;
+
+ /* Disable timer0 */
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ val &= ~TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ sc->sc_period = 0;
+
+ return (0);
+}
+
+int
+a10_timer_get_timerfreq(struct a10_timer_softc *sc)
+{
+ return (sc->timer0_freq);
+}
+
+static int
+a10_timer_hardclock(void *arg)
+{
+ struct a10_timer_softc *sc;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)arg;
+
+ /* Clear interrupt pending bit. */
+ timer_write_4(sc, SW_TIMER_IRQ_STA_REG, 0x1);
+
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ /*
+ * Disabled autoreload and sc_period > 0 means
+ * timer_start was called with non NULL first value.
+ * Now we will set periodic timer with the given period
+ * value.
+ */
+ if ((val & (1<<1)) == 0 && sc->sc_period > 0) {
+ /* Update timer */
+ timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, sc->sc_period);
+
+ /* Make periodic and enable */
+ val |= TIMER_AUTORELOAD | TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+ }
+
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+
+ return (FILTER_HANDLED);
+}
+
+u_int
+a10_timer_get_timecount(struct timecounter *tc)
+{
+
+ if (a10_timer_sc == NULL)
+ return (0);
+
+ return ((u_int)timer_read_counter64());
+}
+
+static device_method_t a10_timer_methods[] = {
+ DEVMETHOD(device_probe, a10_timer_probe),
+ DEVMETHOD(device_attach, a10_timer_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t a10_timer_driver = {
+ "a10_timer",
+ a10_timer_methods,
+ sizeof(struct a10_timer_softc),
+};
+
+static devclass_t a10_timer_devclass;
+
+DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0);
+
+void
+DELAY(int usec)
+{
+ uint32_t counter;
+ uint64_t end, now;
+
+ if (!a10_timer_initialized) {
+ for (; usec > 0; usec--)
+ for (counter = 50; counter > 0; counter--)
+ cpufunc_nullop();
+ return;
+ }
+
+ now = timer_read_counter64();
+ end = now + (a10_timer_sc->timer0_freq / 1000000) * (usec + 1);
+
+ while (now < end)
+ now = timer_read_counter64();
+}
+
Property changes on: trunk/sys/arm/allwinner/timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/autoconf.c
===================================================================
--- trunk/sys/arm/arm/autoconf.c (rev 0)
+++ trunk/sys/arm/arm/autoconf.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,100 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
+ * from: FreeBSD: src/sys/i386/i386/autoconf.c,v 1.156
+ */
+
+/*
+ * Setup the system to run on the current machine.
+ *
+ * Configure() is called at boot time and initializes the vba
+ * device tables and the memory controller monitoring. Available
+ * devices are determined (from possibilities mentioned in ioconf.c),
+ * and the drivers are initialized.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/autoconf.c 146794 2005-05-29 23:44:22Z marcel $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/disklabel.h>
+#include <sys/reboot.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/cons.h>
+
+static void configure_first (void *);
+static void configure (void *);
+static void configure_final (void *);
+
+SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL);
+/* SI_ORDER_SECOND is hookable */
+SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL);
+/* SI_ORDER_MIDDLE is hookable */
+SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL);
+
+device_t nexus_dev;
+
+
+/*
+ * Determine i/o configuration for a machine.
+ */
+static void
+configure_first(void *dummy)
+{
+
+ device_add_child(root_bus, "nexus", 0);
+}
+
+static void
+configure(void *dummy)
+{
+
+ root_bus_configure();
+}
+
+static void
+configure_final(void *dummy)
+{
+
+ cninit_finish();
+ cold = 0;
+}
Property changes on: trunk/sys/arm/arm/autoconf.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/bcopy_page.S
===================================================================
--- trunk/sys/arm/arm/bcopy_page.S (rev 0)
+++ trunk/sys/arm/arm/bcopy_page.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,281 @@
+/* $MidnightBSD$ */
+/* $NetBSD: bcopy_page.S,v 1.7 2003/10/13 21:03:13 scw Exp $ */
+
+/*-
+ * Copyright (c) 1995 Scott Stevens
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Scott Stevens.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * bcopy_page.S
+ *
+ * page optimised bcopy and bzero routines
+ *
+ * Created : 08/04/95
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/bcopy_page.S 248361 2013-03-16 02:48:49Z andrew $");
+
+#include "assym.s"
+
+#ifndef _ARM_ARCH_5E
+
+/* #define BIG_LOOPS */
+
+/*
+ * bcopy_page(src, dest)
+ *
+ * Optimised copy page routine.
+ *
+ * On entry:
+ * r0 - src address
+ * r1 - dest address
+ *
+ * Requires:
+ * number of bytes per page (PAGE_SIZE) is a multiple of 512 (BIG_LOOPS), 128
+ * otherwise.
+ */
+
+#define CHUNK_SIZE 32
+
+#define PREFETCH_FIRST_CHUNK /* nothing */
+#define PREFETCH_NEXT_CHUNK /* nothing */
+
+#ifndef COPY_CHUNK
+#define COPY_CHUNK \
+ PREFETCH_NEXT_CHUNK ; \
+ ldmia r0!, {r3-r8,ip,lr} ; \
+ stmia r1!, {r3-r8,ip,lr}
+#endif /* ! COPY_CHUNK */
+
+#ifndef SAVE_REGS
+#define SAVE_REGS stmfd sp!, {r4-r8, lr}
+#define RESTORE_REGS ldmfd sp!, {r4-r8, pc}
+#endif
+
+ENTRY(bcopy_page)
+ PREFETCH_FIRST_CHUNK
+ SAVE_REGS
+#ifdef BIG_LOOPS
+ mov r2, #(PAGE_SIZE >> 9)
+#else
+ mov r2, #(PAGE_SIZE >> 7)
+#endif
+
+1:
+ COPY_CHUNK
+ COPY_CHUNK
+ COPY_CHUNK
+ COPY_CHUNK
+
+#ifdef BIG_LOOPS
+ /* There is little point making the loop any larger; unless we are
+ running with the cache off, the load/store overheads will
+ completely dominate this loop. */
+ COPY_CHUNK
+ COPY_CHUNK
+ COPY_CHUNK
+ COPY_CHUNK
+
+ COPY_CHUNK
+ COPY_CHUNK
+ COPY_CHUNK
+ COPY_CHUNK
+
+ COPY_CHUNK
+ COPY_CHUNK
+ COPY_CHUNK
+ COPY_CHUNK
+#endif
+ subs r2, r2, #1
+ bne 1b
+
+ RESTORE_REGS /* ...and return. */
+END(bcopy_page)
+
+/*
+ * bzero_page(dest)
+ *
+ * Optimised zero page routine.
+ *
+ * On entry:
+ * r0 - dest address
+ *
+ * Requires:
+ * number of bytes per page (PAGE_SIZE) is a multiple of 512 (BIG_LOOPS), 128
+ * otherwise
+ */
+
+ENTRY(bzero_page)
+ stmfd sp!, {r4-r8, lr}
+#ifdef BIG_LOOPS
+ mov r2, #(PAGE_SIZE >> 9)
+#else
+ mov r2, #(PAGE_SIZE >> 7)
+#endif
+ mov r3, #0
+ mov r4, #0
+ mov r5, #0
+ mov r6, #0
+ mov r7, #0
+ mov r8, #0
+ mov ip, #0
+ mov lr, #0
+
+1:
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+
+#ifdef BIG_LOOPS
+ /* There is little point making the loop any larger; unless we are
+ running with the cache off, the load/store overheads will
+ completely dominate this loop. */
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+ stmia r0!, {r3-r8,ip,lr}
+
+#endif
+
+ subs r2, r2, #1
+ bne 1b
+
+ ldmfd sp!, {r4-r8, pc}
+END(bzero_page)
+
+#else /* _ARM_ARCH_5E */
+
+/*
+ * armv5e version of bcopy_page
+ */
+ENTRY(bcopy_page)
+ pld [r0]
+ stmfd sp!, {r4, r5}
+ mov ip, #32
+ ldr r2, [r0], #0x04 /* 0x00 */
+ ldr r3, [r0], #0x04 /* 0x04 */
+1: pld [r0, #0x18] /* Prefetch 0x20 */
+ ldr r4, [r0], #0x04 /* 0x08 */
+ ldr r5, [r0], #0x04 /* 0x0c */
+ strd r2, [r1], #0x08
+ ldr r2, [r0], #0x04 /* 0x10 */
+ ldr r3, [r0], #0x04 /* 0x14 */
+ strd r4, [r1], #0x08
+ ldr r4, [r0], #0x04 /* 0x18 */
+ ldr r5, [r0], #0x04 /* 0x1c */
+ strd r2, [r1], #0x08
+ ldr r2, [r0], #0x04 /* 0x20 */
+ ldr r3, [r0], #0x04 /* 0x24 */
+ pld [r0, #0x18] /* Prefetch 0x40 */
+ strd r4, [r1], #0x08
+ ldr r4, [r0], #0x04 /* 0x28 */
+ ldr r5, [r0], #0x04 /* 0x2c */
+ strd r2, [r1], #0x08
+ ldr r2, [r0], #0x04 /* 0x30 */
+ ldr r3, [r0], #0x04 /* 0x34 */
+ strd r4, [r1], #0x08
+ ldr r4, [r0], #0x04 /* 0x38 */
+ ldr r5, [r0], #0x04 /* 0x3c */
+ strd r2, [r1], #0x08
+ ldr r2, [r0], #0x04 /* 0x40 */
+ ldr r3, [r0], #0x04 /* 0x44 */
+ pld [r0, #0x18] /* Prefetch 0x60 */
+ strd r4, [r1], #0x08
+ ldr r4, [r0], #0x04 /* 0x48 */
+ ldr r5, [r0], #0x04 /* 0x4c */
+ strd r2, [r1], #0x08
+ ldr r2, [r0], #0x04 /* 0x50 */
+ ldr r3, [r0], #0x04 /* 0x54 */
+ strd r4, [r1], #0x08
+ ldr r4, [r0], #0x04 /* 0x58 */
+ ldr r5, [r0], #0x04 /* 0x5c */
+ strd r2, [r1], #0x08
+ ldr r2, [r0], #0x04 /* 0x60 */
+ ldr r3, [r0], #0x04 /* 0x64 */
+ pld [r0, #0x18] /* Prefetch 0x80 */
+ strd r4, [r1], #0x08
+ ldr r4, [r0], #0x04 /* 0x68 */
+ ldr r5, [r0], #0x04 /* 0x6c */
+ strd r2, [r1], #0x08
+ ldr r2, [r0], #0x04 /* 0x70 */
+ ldr r3, [r0], #0x04 /* 0x74 */
+ strd r4, [r1], #0x08
+ ldr r4, [r0], #0x04 /* 0x78 */
+ ldr r5, [r0], #0x04 /* 0x7c */
+ strd r2, [r1], #0x08
+ subs ip, ip, #0x01
+ ldrgt r2, [r0], #0x04 /* 0x80 */
+ ldrgt r3, [r0], #0x04 /* 0x84 */
+ strd r4, [r1], #0x08
+ bgt 1b
+ ldmfd sp!, {r4, r5}
+ RET
+END(bcopy_page)
+
+/*
+ * armv5e version of bzero_page
+ */
+ENTRY(bzero_page)
+ mov r1, #PAGE_SIZE
+ mov r2, #0
+ mov r3, #0
+1: strd r2, [r0], #8 /* 32 */
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8 /* 64 */
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8 /* 96 */
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8 /* 128 */
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ subs r1, r1, #128
+ bne 1b
+ RET
+END(bzero_page)
+#endif /* _ARM_ARCH_5E */
Property changes on: trunk/sys/arm/arm/bcopy_page.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/bcopyinout.S
===================================================================
--- trunk/sys/arm/arm/bcopyinout.S (rev 0)
+++ trunk/sys/arm/arm/bcopyinout.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,624 @@
+/* $MidnightBSD$ */
+/* $NetBSD: bcopyinout.S,v 1.11 2003/10/13 21:22:40 scw Exp $ */
+
+/*-
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Allen Briggs for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "assym.s"
+
+#include <machine/acle-compat.h>
+#include <machine/asm.h>
+#include <sys/errno.h>
+
+.L_arm_memcpy:
+ .word _C_LABEL(_arm_memcpy)
+.L_min_memcpy_size:
+ .word _C_LABEL(_min_memcpy_size)
+
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/bcopyinout.S 294681 2016-01-24 19:58:58Z ian $");
+#ifdef _ARM_ARCH_5E
+#include <arm/arm/bcopyinout_xscale.S>
+#else
+
+ .text
+ .align 2
+
+#if __ARM_ARCH >= 6
+#define GET_PCB(tmp) \
+ mrc p15, 0, tmp, c13, c0, 4; \
+ add tmp, tmp, #(TD_PCB)
+#else
+.Lcurpcb:
+ .word _C_LABEL(__pcpu) + PC_CURPCB
+
+#define GET_PCB(tmp) \
+ ldr tmp, .Lcurpcb
+#endif
+
+
+#define SAVE_REGS stmfd sp!, {r4-r11}
+#define RESTORE_REGS ldmfd sp!, {r4-r11}
+
+#if defined(_ARM_ARCH_5E)
+#define HELLOCPP #
+#define PREFETCH(rx,o) pld [ rx , HELLOCPP (o) ]
+#else
+#define PREFETCH(rx,o)
+#endif
+
+/*
+ * r0 = user space address
+ * r1 = kernel space address
+ * r2 = length
+ *
+ * Copies bytes from user space to kernel space
+ *
+ * We save/restore r4-r11:
+ * r4-r11 are scratch
+ */
+ENTRY(copyin)
+ /* Quick exit if length is zero */
+ teq r2, #0
+ moveq r0, #0
+ RETeq
+
+ ldr r3, .L_arm_memcpy
+ ldr r3, [r3]
+ cmp r3, #0
+ beq .Lnormal
+ ldr r3, .L_min_memcpy_size
+ ldr r3, [r3]
+ cmp r2, r3
+ blt .Lnormal
+ stmfd sp!, {r0-r2, r4, lr}
+ mov r3, r0
+ mov r0, r1
+ mov r1, r3
+ mov r3, #2 /* SRC_IS_USER */
+ ldr r4, .L_arm_memcpy
+ mov lr, pc
+ ldr pc, [r4]
+ cmp r0, #0
+ ldmfd sp!, {r0-r2, r4, lr}
+ moveq r0, #0
+ RETeq
+
+.Lnormal:
+ SAVE_REGS
+ GET_PCB(r4)
+ ldr r4, [r4]
+
+
+ ldr r5, [r4, #PCB_ONFAULT]
+ adr r3, .Lcopyfault
+ str r3, [r4, #PCB_ONFAULT]
+
+ PREFETCH(r0, 0)
+ PREFETCH(r1, 0)
+
+ /*
+ * If not too many bytes, take the slow path.
+ */
+ cmp r2, #0x08
+ blt .Licleanup
+
+ /*
+ * Align destination to word boundary.
+ */
+ and r6, r1, #0x3
+ ldr pc, [pc, r6, lsl #2]
+ b .Lialend
+ .word .Lialend
+ .word .Lial3
+ .word .Lial2
+ .word .Lial1
+.Lial3: ldrbt r6, [r0], #1
+ sub r2, r2, #1
+ strb r6, [r1], #1
+.Lial2: ldrbt r7, [r0], #1
+ sub r2, r2, #1
+ strb r7, [r1], #1
+.Lial1: ldrbt r6, [r0], #1
+ sub r2, r2, #1
+ strb r6, [r1], #1
+.Lialend:
+
+ /*
+ * If few bytes left, finish slow.
+ */
+ cmp r2, #0x08
+ blt .Licleanup
+
+ /*
+ * If source is not aligned, finish slow.
+ */
+ ands r3, r0, #0x03
+ bne .Licleanup
+
+ cmp r2, #0x60 /* Must be > 0x5f for unrolled cacheline */
+ blt .Licleanup8
+
+ /*
+ * Align destination to cacheline boundary.
+ * If source and destination are nicely aligned, this can be a big
+ * win. If not, it's still cheaper to copy in groups of 32 even if
+ * we don't get the nice cacheline alignment.
+ */
+ and r6, r1, #0x1f
+ ldr pc, [pc, r6]
+ b .Licaligned
+ .word .Licaligned
+ .word .Lical28
+ .word .Lical24
+ .word .Lical20
+ .word .Lical16
+ .word .Lical12
+ .word .Lical8
+ .word .Lical4
+.Lical28:ldrt r6, [r0], #4
+ sub r2, r2, #4
+ str r6, [r1], #4
+.Lical24:ldrt r7, [r0], #4
+ sub r2, r2, #4
+ str r7, [r1], #4
+.Lical20:ldrt r6, [r0], #4
+ sub r2, r2, #4
+ str r6, [r1], #4
+.Lical16:ldrt r7, [r0], #4
+ sub r2, r2, #4
+ str r7, [r1], #4
+.Lical12:ldrt r6, [r0], #4
+ sub r2, r2, #4
+ str r6, [r1], #4
+.Lical8:ldrt r7, [r0], #4
+ sub r2, r2, #4
+ str r7, [r1], #4
+.Lical4:ldrt r6, [r0], #4
+ sub r2, r2, #4
+ str r6, [r1], #4
+
+ /*
+ * We start with > 0x40 bytes to copy (>= 0x60 got us into this
+ * part of the code, and we may have knocked that down by as much
+ * as 0x1c getting aligned).
+ *
+ * This loop basically works out to:
+ * do {
+ * prefetch-next-cacheline(s)
+ * bytes -= 0x20;
+ * copy cacheline
+ * } while (bytes >= 0x40);
+ * bytes -= 0x20;
+ * copy cacheline
+ */
+.Licaligned:
+ PREFETCH(r0, 32)
+ PREFETCH(r1, 32)
+
+ sub r2, r2, #0x20
+
+ /* Copy a cacheline */
+ ldrt r10, [r0], #4
+ ldrt r11, [r0], #4
+ ldrt r6, [r0], #4
+ ldrt r7, [r0], #4
+ ldrt r8, [r0], #4
+ ldrt r9, [r0], #4
+ stmia r1!, {r10-r11}
+ ldrt r10, [r0], #4
+ ldrt r11, [r0], #4
+ stmia r1!, {r6-r11}
+
+ cmp r2, #0x40
+ bge .Licaligned
+
+ sub r2, r2, #0x20
+
+ /* Copy a cacheline */
+ ldrt r10, [r0], #4
+ ldrt r11, [r0], #4
+ ldrt r6, [r0], #4
+ ldrt r7, [r0], #4
+ ldrt r8, [r0], #4
+ ldrt r9, [r0], #4
+ stmia r1!, {r10-r11}
+ ldrt r10, [r0], #4
+ ldrt r11, [r0], #4
+ stmia r1!, {r6-r11}
+
+ cmp r2, #0x08
+ blt .Liprecleanup
+
+.Licleanup8:
+ ldrt r8, [r0], #4
+ ldrt r9, [r0], #4
+ sub r2, r2, #8
+ stmia r1!, {r8, r9}
+ cmp r2, #8
+ bge .Licleanup8
+
+.Liprecleanup:
+ /*
+ * If we're done, bail.
+ */
+ cmp r2, #0
+ beq .Lout
+
+.Licleanup:
+ and r6, r2, #0x3
+ ldr pc, [pc, r6, lsl #2]
+ b .Licend
+ .word .Lic4
+ .word .Lic1
+ .word .Lic2
+ .word .Lic3
+.Lic4: ldrbt r6, [r0], #1
+ sub r2, r2, #1
+ strb r6, [r1], #1
+.Lic3: ldrbt r7, [r0], #1
+ sub r2, r2, #1
+ strb r7, [r1], #1
+.Lic2: ldrbt r6, [r0], #1
+ sub r2, r2, #1
+ strb r6, [r1], #1
+.Lic1: ldrbt r7, [r0], #1
+ subs r2, r2, #1
+ strb r7, [r1], #1
+.Licend:
+ bne .Licleanup
+
+.Liout:
+ mov r0, #0
+
+ str r5, [r4, #PCB_ONFAULT]
+ RESTORE_REGS
+
+ RET
+
+.Lcopyfault:
+ ldr r0, =EFAULT
+ str r5, [r4, #PCB_ONFAULT]
+ RESTORE_REGS
+
+ RET
+END(copyin)
+
+/*
+ * r0 = kernel space address
+ * r1 = user space address
+ * r2 = length
+ *
+ * Copies bytes from kernel space to user space
+ *
+ * We save/restore r4-r11:
+ * r4-r11 are scratch
+ */
+
+ENTRY(copyout)
+ /* Quick exit if length is zero */
+ teq r2, #0
+ moveq r0, #0
+ RETeq
+
+ ldr r3, .L_arm_memcpy
+ ldr r3, [r3]
+ cmp r3, #0
+ beq .Lnormale
+ ldr r3, .L_min_memcpy_size
+ ldr r3, [r3]
+ cmp r2, r3
+ blt .Lnormale
+ stmfd sp!, {r0-r2, r4, lr}
+ mov r3, r0
+ mov r0, r1
+ mov r1, r3
+ mov r3, #1 /* DST_IS_USER */
+ ldr r4, .L_arm_memcpy
+ mov lr, pc
+ ldr pc, [r4]
+ cmp r0, #0
+ ldmfd sp!, {r0-r2, r4, lr}
+ moveq r0, #0
+ RETeq
+
+.Lnormale:
+ SAVE_REGS
+ GET_PCB(r4)
+ ldr r4, [r4]
+
+ ldr r5, [r4, #PCB_ONFAULT]
+ adr r3, .Lcopyfault
+ str r3, [r4, #PCB_ONFAULT]
+
+ PREFETCH(r0, 0)
+ PREFETCH(r1, 0)
+
+ /*
+ * If not too many bytes, take the slow path.
+ */
+ cmp r2, #0x08
+ blt .Lcleanup
+
+ /*
+ * Align destination to word boundary.
+ */
+ and r6, r1, #0x3
+ ldr pc, [pc, r6, lsl #2]
+ b .Lalend
+ .word .Lalend
+ .word .Lal3
+ .word .Lal2
+ .word .Lal1
+.Lal3: ldrb r6, [r0], #1
+ sub r2, r2, #1
+ strbt r6, [r1], #1
+.Lal2: ldrb r7, [r0], #1
+ sub r2, r2, #1
+ strbt r7, [r1], #1
+.Lal1: ldrb r6, [r0], #1
+ sub r2, r2, #1
+ strbt r6, [r1], #1
+.Lalend:
+
+ /*
+ * If few bytes left, finish slow.
+ */
+ cmp r2, #0x08
+ blt .Lcleanup
+
+ /*
+ * If source is not aligned, finish slow.
+ */
+ ands r3, r0, #0x03
+ bne .Lcleanup
+
+ cmp r2, #0x60 /* Must be > 0x5f for unrolled cacheline */
+ blt .Lcleanup8
+
+ /*
+ * Align source & destination to cacheline boundary.
+ */
+ and r6, r1, #0x1f
+ ldr pc, [pc, r6]
+ b .Lcaligned
+ .word .Lcaligned
+ .word .Lcal28
+ .word .Lcal24
+ .word .Lcal20
+ .word .Lcal16
+ .word .Lcal12
+ .word .Lcal8
+ .word .Lcal4
+.Lcal28:ldr r6, [r0], #4
+ sub r2, r2, #4
+ strt r6, [r1], #4
+.Lcal24:ldr r7, [r0], #4
+ sub r2, r2, #4
+ strt r7, [r1], #4
+.Lcal20:ldr r6, [r0], #4
+ sub r2, r2, #4
+ strt r6, [r1], #4
+.Lcal16:ldr r7, [r0], #4
+ sub r2, r2, #4
+ strt r7, [r1], #4
+.Lcal12:ldr r6, [r0], #4
+ sub r2, r2, #4
+ strt r6, [r1], #4
+.Lcal8: ldr r7, [r0], #4
+ sub r2, r2, #4
+ strt r7, [r1], #4
+.Lcal4: ldr r6, [r0], #4
+ sub r2, r2, #4
+ strt r6, [r1], #4
+
+ /*
+ * We start with > 0x40 bytes to copy (>= 0x60 got us into this
+ * part of the code, and we may have knocked that down by as much
+ * as 0x1c getting aligned).
+ *
+ * This loop basically works out to:
+ * do {
+ * prefetch-next-cacheline(s)
+ * bytes -= 0x20;
+ * copy cacheline
+ * } while (bytes >= 0x40);
+ * bytes -= 0x20;
+ * copy cacheline
+ */
+.Lcaligned:
+ PREFETCH(r0, 32)
+ PREFETCH(r1, 32)
+
+ sub r2, r2, #0x20
+
+ /* Copy a cacheline */
+ ldmia r0!, {r6-r11}
+ strt r6, [r1], #4
+ strt r7, [r1], #4
+ ldmia r0!, {r6-r7}
+ strt r8, [r1], #4
+ strt r9, [r1], #4
+ strt r10, [r1], #4
+ strt r11, [r1], #4
+ strt r6, [r1], #4
+ strt r7, [r1], #4
+
+ cmp r2, #0x40
+ bge .Lcaligned
+
+ sub r2, r2, #0x20
+
+ /* Copy a cacheline */
+ ldmia r0!, {r6-r11}
+ strt r6, [r1], #4
+ strt r7, [r1], #4
+ ldmia r0!, {r6-r7}
+ strt r8, [r1], #4
+ strt r9, [r1], #4
+ strt r10, [r1], #4
+ strt r11, [r1], #4
+ strt r6, [r1], #4
+ strt r7, [r1], #4
+
+ cmp r2, #0x08
+ blt .Lprecleanup
+
+.Lcleanup8:
+ ldmia r0!, {r8-r9}
+ sub r2, r2, #8
+ strt r8, [r1], #4
+ strt r9, [r1], #4
+ cmp r2, #8
+ bge .Lcleanup8
+
+.Lprecleanup:
+ /*
+ * If we're done, bail.
+ */
+ cmp r2, #0
+ beq .Lout
+
+.Lcleanup:
+ and r6, r2, #0x3
+ ldr pc, [pc, r6, lsl #2]
+ b .Lcend
+ .word .Lc4
+ .word .Lc1
+ .word .Lc2
+ .word .Lc3
+.Lc4: ldrb r6, [r0], #1
+ sub r2, r2, #1
+ strbt r6, [r1], #1
+.Lc3: ldrb r7, [r0], #1
+ sub r2, r2, #1
+ strbt r7, [r1], #1
+.Lc2: ldrb r6, [r0], #1
+ sub r2, r2, #1
+ strbt r6, [r1], #1
+.Lc1: ldrb r7, [r0], #1
+ subs r2, r2, #1
+ strbt r7, [r1], #1
+.Lcend:
+ bne .Lcleanup
+
+.Lout:
+ mov r0, #0
+
+ str r5, [r4, #PCB_ONFAULT]
+ RESTORE_REGS
+
+ RET
+END(copyout)
+#endif
+
+/*
+ * int badaddr_read_1(const uint8_t *src, uint8_t *dest)
+ *
+ * Copies a single 8-bit value from src to dest, returning 0 on success,
+ * else EFAULT if a page fault occurred.
+ */
+ENTRY(badaddr_read_1)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+ ldr ip, [r2, #PCB_ONFAULT]
+ adr r3, 1f
+ str r3, [r2, #PCB_ONFAULT]
+ nop
+ nop
+ nop
+ ldrb r3, [r0]
+ nop
+ nop
+ nop
+ strb r3, [r1]
+ mov r0, #0 /* No fault */
+1: str ip, [r2, #PCB_ONFAULT]
+ RET
+END(badaddr_read_1)
+
+/*
+ * int badaddr_read_2(const uint16_t *src, uint16_t *dest)
+ *
+ * Copies a single 16-bit value from src to dest, returning 0 on success,
+ * else EFAULT if a page fault occurred.
+ */
+ENTRY(badaddr_read_2)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+ ldr ip, [r2, #PCB_ONFAULT]
+ adr r3, 1f
+ str r3, [r2, #PCB_ONFAULT]
+ nop
+ nop
+ nop
+ ldrh r3, [r0]
+ nop
+ nop
+ nop
+ strh r3, [r1]
+ mov r0, #0 /* No fault */
+1: str ip, [r2, #PCB_ONFAULT]
+ RET
+END(badaddr_read_2)
+
+/*
+ * int badaddr_read_4(const uint32_t *src, uint32_t *dest)
+ *
+ * Copies a single 32-bit value from src to dest, returning 0 on success,
+ * else EFAULT if a page fault occurred.
+ */
+ENTRY(badaddr_read_4)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+ ldr ip, [r2, #PCB_ONFAULT]
+ adr r3, 1f
+ str r3, [r2, #PCB_ONFAULT]
+ nop
+ nop
+ nop
+ ldr r3, [r0]
+ nop
+ nop
+ nop
+ str r3, [r1]
+ mov r0, #0 /* No fault */
+1: str ip, [r2, #PCB_ONFAULT]
+ RET
+END(badaddr_read_4)
+
Property changes on: trunk/sys/arm/arm/bcopyinout.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/bcopyinout_xscale.S
===================================================================
--- trunk/sys/arm/arm/bcopyinout_xscale.S (rev 0)
+++ trunk/sys/arm/arm/bcopyinout_xscale.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,943 @@
+/* $MidnightBSD$ */
+/* $NetBSD: bcopyinout_xscale.S,v 1.3 2003/12/15 09:27:18 scw Exp $ */
+
+/*-
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/bcopyinout_xscale.S 294681 2016-01-24 19:58:58Z ian $");
+
+#include <machine/acle-compat.h>
+
+ .syntax unified
+ .text
+ .align 2
+
+#if __ARM_ARCH >= 6
+#define GET_PCB(tmp) \
+ mrc p15, 0, tmp, c13, c0, 4; \
+ add tmp, tmp, #(TD_PCB)
+#else
+.Lcurpcb:
+ .word _C_LABEL(__pcpu) + PC_CURPCB
+#define GET_PCB(tmp) \
+ ldr tmp, .Lcurpcb
+#endif
+
+/*
+ * r0 = user space address
+ * r1 = kernel space address
+ * r2 = length
+ *
+ * Copies bytes from user space to kernel space
+ */
+ENTRY(copyin)
+ cmp r2, #0x00
+ movle r0, #0x00
+ movle pc, lr /* Bail early if length is <= 0 */
+
+ ldr r3, .L_arm_memcpy
+ ldr r3, [r3]
+ cmp r3, #0
+ beq .Lnormal
+ ldr r3, .L_min_memcpy_size
+ ldr r3, [r3]
+ cmp r2, r3
+ blt .Lnormal
+ stmfd sp!, {r0-r2, r4, lr}
+ mov r3, r0
+ mov r0, r1
+ mov r1, r3
+ mov r3, #2 /* SRC_IS_USER */
+ ldr r4, .L_arm_memcpy
+ mov lr, pc
+ ldr pc, [r4]
+ cmp r0, #0
+ ldmfd sp!, {r0-r2, r4, lr}
+ moveq r0, #0
+ RETeq
+
+.Lnormal:
+ stmfd sp!, {r10-r11, lr}
+
+ GET_PCB(r10)
+ ldr r10, [r10]
+
+ mov r3, #0x00
+ adr ip, .Lcopyin_fault
+ ldr r11, [r10, #PCB_ONFAULT]
+ str ip, [r10, #PCB_ONFAULT]
+ bl .Lcopyin_guts
+ str r11, [r10, #PCB_ONFAULT]
+ mov r0, #0x00
+ ldmfd sp!, {r10-r11, pc}
+
+.Lcopyin_fault:
+ ldr r0, =EFAULT
+ str r11, [r10, #PCB_ONFAULT]
+ cmp r3, #0x00
+ ldmfdgt sp!, {r4-r7} /* r3 > 0 Restore r4-r7 */
+ ldmfdlt sp!, {r4-r9} /* r3 < 0 Restore r4-r9 */
+ ldmfd sp!, {r10-r11, pc}
+
+.Lcopyin_guts:
+ pld [r0]
+ /* Word-align the destination buffer */
+ ands ip, r1, #0x03 /* Already word aligned? */
+ beq .Lcopyin_wordaligned /* Yup */
+ rsb ip, ip, #0x04
+ cmp r2, ip /* Enough bytes left to align it? */
+ blt .Lcopyin_l4_2 /* Nope. Just copy bytewise */
+ sub r2, r2, ip
+ rsbs ip, ip, #0x03
+ addne pc, pc, ip, lsl #3
+ nop
+ ldrbt ip, [r0], #0x01
+ strb ip, [r1], #0x01
+ ldrbt ip, [r0], #0x01
+ strb ip, [r1], #0x01
+ ldrbt ip, [r0], #0x01
+ strb ip, [r1], #0x01
+ cmp r2, #0x00 /* All done? */
+ RETeq
+
+ /* Destination buffer is now word aligned */
+.Lcopyin_wordaligned:
+ ands ip, r0, #0x03 /* Is src also word-aligned? */
+ bne .Lcopyin_bad_align /* Nope. Things just got bad */
+ cmp r2, #0x08 /* Less than 8 bytes remaining? */
+ blt .Lcopyin_w_less_than8
+
+ /* Quad-align the destination buffer */
+ tst r1, #0x07 /* Already quad aligned? */
+ ldrtne ip, [r0], #0x04
+ strne ip, [r1], #0x04
+ subne r2, r2, #0x04
+ stmfd sp!, {r4-r9} /* Free up some registers */
+ mov r3, #-1 /* Signal restore r4-r9 */
+
+ /* Destination buffer quad aligned, source is word aligned */
+ subs r2, r2, #0x80
+ blt .Lcopyin_w_lessthan128
+
+ /* Copy 128 bytes at a time */
+.Lcopyin_w_loop128:
+ ldrt r4, [r0], #0x04 /* LD:00-03 */
+ ldrt r5, [r0], #0x04 /* LD:04-07 */
+ pld [r0, #0x18] /* Prefetch 0x20 */
+ ldrt r6, [r0], #0x04 /* LD:08-0b */
+ ldrt r7, [r0], #0x04 /* LD:0c-0f */
+ ldrt r8, [r0], #0x04 /* LD:10-13 */
+ ldrt r9, [r0], #0x04 /* LD:14-17 */
+ strd r4, [r1], #0x08 /* ST:00-07 */
+ ldrt r4, [r0], #0x04 /* LD:18-1b */
+ ldrt r5, [r0], #0x04 /* LD:1c-1f */
+ strd r6, [r1], #0x08 /* ST:08-0f */
+ ldrt r6, [r0], #0x04 /* LD:20-23 */
+ ldrt r7, [r0], #0x04 /* LD:24-27 */
+ pld [r0, #0x18] /* Prefetch 0x40 */
+ strd r8, [r1], #0x08 /* ST:10-17 */
+ ldrt r8, [r0], #0x04 /* LD:28-2b */
+ ldrt r9, [r0], #0x04 /* LD:2c-2f */
+ strd r4, [r1], #0x08 /* ST:18-1f */
+ ldrt r4, [r0], #0x04 /* LD:30-33 */
+ ldrt r5, [r0], #0x04 /* LD:34-37 */
+ strd r6, [r1], #0x08 /* ST:20-27 */
+ ldrt r6, [r0], #0x04 /* LD:38-3b */
+ ldrt r7, [r0], #0x04 /* LD:3c-3f */
+ strd r8, [r1], #0x08 /* ST:28-2f */
+ ldrt r8, [r0], #0x04 /* LD:40-43 */
+ ldrt r9, [r0], #0x04 /* LD:44-47 */
+ pld [r0, #0x18] /* Prefetch 0x60 */
+ strd r4, [r1], #0x08 /* ST:30-37 */
+ ldrt r4, [r0], #0x04 /* LD:48-4b */
+ ldrt r5, [r0], #0x04 /* LD:4c-4f */
+ strd r6, [r1], #0x08 /* ST:38-3f */
+ ldrt r6, [r0], #0x04 /* LD:50-53 */
+ ldrt r7, [r0], #0x04 /* LD:54-57 */
+ strd r8, [r1], #0x08 /* ST:40-47 */
+ ldrt r8, [r0], #0x04 /* LD:58-5b */
+ ldrt r9, [r0], #0x04 /* LD:5c-5f */
+ strd r4, [r1], #0x08 /* ST:48-4f */
+ ldrt r4, [r0], #0x04 /* LD:60-63 */
+ ldrt r5, [r0], #0x04 /* LD:64-67 */
+ pld [r0, #0x18] /* Prefetch 0x80 */
+ strd r6, [r1], #0x08 /* ST:50-57 */
+ ldrt r6, [r0], #0x04 /* LD:68-6b */
+ ldrt r7, [r0], #0x04 /* LD:6c-6f */
+ strd r8, [r1], #0x08 /* ST:58-5f */
+ ldrt r8, [r0], #0x04 /* LD:70-73 */
+ ldrt r9, [r0], #0x04 /* LD:74-77 */
+ strd r4, [r1], #0x08 /* ST:60-67 */
+ ldrt r4, [r0], #0x04 /* LD:78-7b */
+ ldrt r5, [r0], #0x04 /* LD:7c-7f */
+ strd r6, [r1], #0x08 /* ST:68-6f */
+ strd r8, [r1], #0x08 /* ST:70-77 */
+ subs r2, r2, #0x80
+ strd r4, [r1], #0x08 /* ST:78-7f */
+ bge .Lcopyin_w_loop128
+
+.Lcopyin_w_lessthan128:
+ adds r2, r2, #0x80 /* Adjust for extra sub */
+ ldmfdeq sp!, {r4-r9}
+ RETeq
+ subs r2, r2, #0x20
+ blt .Lcopyin_w_lessthan32
+
+ /* Copy 32 bytes at a time */
+.Lcopyin_w_loop32:
+ ldrt r4, [r0], #0x04
+ ldrt r5, [r0], #0x04
+ pld [r0, #0x18]
+ ldrt r6, [r0], #0x04
+ ldrt r7, [r0], #0x04
+ ldrt r8, [r0], #0x04
+ ldrt r9, [r0], #0x04
+ strd r4, [r1], #0x08
+ ldrt r4, [r0], #0x04
+ ldrt r5, [r0], #0x04
+ strd r6, [r1], #0x08
+ strd r8, [r1], #0x08
+ subs r2, r2, #0x20
+ strd r4, [r1], #0x08
+ bge .Lcopyin_w_loop32
+
+.Lcopyin_w_lessthan32:
+ adds r2, r2, #0x20 /* Adjust for extra sub */
+ ldmfdeq sp!, {r4-r9}
+ RETeq /* Return now if done */
+
+ and r4, r2, #0x18
+ rsb r5, r4, #0x18
+ subs r2, r2, r4
+ add pc, pc, r5, lsl #1
+ nop
+
+ /* At least 24 bytes remaining */
+ ldrt r4, [r0], #0x04
+ ldrt r5, [r0], #0x04
+ nop
+ strd r4, [r1], #0x08
+
+ /* At least 16 bytes remaining */
+ ldrt r4, [r0], #0x04
+ ldrt r5, [r0], #0x04
+ nop
+ strd r4, [r1], #0x08
+
+ /* At least 8 bytes remaining */
+ ldrt r4, [r0], #0x04
+ ldrt r5, [r0], #0x04
+ nop
+ strd r4, [r1], #0x08
+
+ /* Less than 8 bytes remaining */
+ ldmfd sp!, {r4-r9}
+ RETeq /* Return now if done */
+ mov r3, #0x00
+
+.Lcopyin_w_less_than8:
+ subs r2, r2, #0x04
+ ldrtge ip, [r0], #0x04
+ strge ip, [r1], #0x04
+ RETeq /* Return now if done */
+ addlt r2, r2, #0x04
+ ldrbt ip, [r0], #0x01
+ cmp r2, #0x02
+ ldrbtge r2, [r0], #0x01
+ strb ip, [r1], #0x01
+ ldrbtgt ip, [r0]
+ strbge r2, [r1], #0x01
+ strbgt ip, [r1]
+ RET
+
+/*
+ * At this point, it has not been possible to word align both buffers.
+ * The destination buffer (r1) is word aligned, but the source buffer
+ * (r0) is not.
+ */
+.Lcopyin_bad_align:
+ stmfd sp!, {r4-r7}
+ mov r3, #0x01
+ bic r0, r0, #0x03
+ cmp ip, #2
+ ldrt ip, [r0], #0x04
+ bgt .Lcopyin_bad3
+ beq .Lcopyin_bad2
+ b .Lcopyin_bad1
+
+.Lcopyin_bad1_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #8
+#else
+ mov r4, ip, lsr #8
+#endif
+ ldrt r5, [r0], #0x04
+ pld [r0, #0x018]
+ ldrt r6, [r0], #0x04
+ ldrt r7, [r0], #0x04
+ ldrt ip, [r0], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r6, lsr #24
+ mov r6, r6, lsl #8
+ orr r6, r6, r7, lsr #24
+ mov r7, r7, lsl #8
+ orr r7, r7, ip, lsr #24
+#else
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ mov r6, r6, lsr #8
+ orr r6, r6, r7, lsl #24
+ mov r7, r7, lsr #8
+ orr r7, r7, ip, lsl #24
+#endif
+ str r4, [r1], #0x04
+ str r5, [r1], #0x04
+ str r6, [r1], #0x04
+ str r7, [r1], #0x04
+.Lcopyin_bad1:
+ subs r2, r2, #0x10
+ bge .Lcopyin_bad1_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r0, r0, #0x03
+ blt .Lcopyin_l4
+
+.Lcopyin_bad1_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #8
+#else
+ mov r4, ip, lsr #8
+#endif
+ ldrt ip, [r0], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #24
+#else
+ orr r4, r4, ip, lsl #24
+#endif
+ str r4, [r1], #0x04
+ bge .Lcopyin_bad1_loop4
+ sub r0, r0, #0x03
+ b .Lcopyin_l4
+
+.Lcopyin_bad2_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #16
+#else
+ mov r4, ip, lsr #16
+#endif
+ ldrt r5, [r0], #0x04
+ pld [r0, #0x018]
+ ldrt r6, [r0], #0x04
+ ldrt r7, [r0], #0x04
+ ldrt ip, [r0], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r6, lsr #16
+ mov r6, r6, lsl #16
+ orr r6, r6, r7, lsr #16
+ mov r7, r7, lsl #16
+ orr r7, r7, ip, lsr #16
+#else
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ mov r6, r6, lsr #16
+ orr r6, r6, r7, lsl #16
+ mov r7, r7, lsr #16
+ orr r7, r7, ip, lsl #16
+#endif
+ str r4, [r1], #0x04
+ str r5, [r1], #0x04
+ str r6, [r1], #0x04
+ str r7, [r1], #0x04
+.Lcopyin_bad2:
+ subs r2, r2, #0x10
+ bge .Lcopyin_bad2_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r0, r0, #0x02
+ blt .Lcopyin_l4
+
+.Lcopyin_bad2_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #16
+#else
+ mov r4, ip, lsr #16
+#endif
+ ldrt ip, [r0], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #16
+#else
+ orr r4, r4, ip, lsl #16
+#endif
+ str r4, [r1], #0x04
+ bge .Lcopyin_bad2_loop4
+ sub r0, r0, #0x02
+ b .Lcopyin_l4
+
+.Lcopyin_bad3_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #24
+#else
+ mov r4, ip, lsr #24
+#endif
+ ldrt r5, [r0], #0x04
+ pld [r0, #0x018]
+ ldrt r6, [r0], #0x04
+ ldrt r7, [r0], #0x04
+ ldrt ip, [r0], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r6, lsr #8
+ mov r6, r6, lsl #24
+ orr r6, r6, r7, lsr #8
+ mov r7, r7, lsl #24
+ orr r7, r7, ip, lsr #8
+#else
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ mov r6, r6, lsr #24
+ orr r6, r6, r7, lsl #8
+ mov r7, r7, lsr #24
+ orr r7, r7, ip, lsl #8
+#endif
+ str r4, [r1], #0x04
+ str r5, [r1], #0x04
+ str r6, [r1], #0x04
+ str r7, [r1], #0x04
+.Lcopyin_bad3:
+ subs r2, r2, #0x10
+ bge .Lcopyin_bad3_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r0, r0, #0x01
+ blt .Lcopyin_l4
+
+.Lcopyin_bad3_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #24
+#else
+ mov r4, ip, lsr #24
+#endif
+ ldrt ip, [r0], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #8
+#else
+ orr r4, r4, ip, lsl #8
+#endif
+ str r4, [r1], #0x04
+ bge .Lcopyin_bad3_loop4
+ sub r0, r0, #0x01
+
+.Lcopyin_l4:
+ ldmfd sp!, {r4-r7}
+ mov r3, #0x00
+ adds r2, r2, #0x04
+ RETeq
+.Lcopyin_l4_2:
+ rsbs r2, r2, #0x03
+ addne pc, pc, r2, lsl #3
+ nop
+ ldrbt ip, [r0], #0x01
+ strb ip, [r1], #0x01
+ ldrbt ip, [r0], #0x01
+ strb ip, [r1], #0x01
+ ldrbt ip, [r0]
+ strb ip, [r1]
+ RET
+END(copyin)
+
+/*
+ * r0 = kernel space address
+ * r1 = user space address
+ * r2 = length
+ *
+ * Copies bytes from kernel space to user space
+ */
+ENTRY(copyout)
+ cmp r2, #0x00
+ movle r0, #0x00
+ movle pc, lr /* Bail early if length is <= 0 */
+
+ ldr r3, .L_arm_memcpy
+ ldr r3, [r3]
+ cmp r3, #0
+ beq .Lnormale
+ ldr r3, .L_min_memcpy_size
+ ldr r3, [r3]
+ cmp r2, r3
+ blt .Lnormale
+ stmfd sp!, {r0-r2, r4, lr}
+ mov r3, r0
+ mov r0, r1
+ mov r1, r3
+ mov r3, #1 /* DST_IS_USER */
+ ldr r4, .L_arm_memcpy
+ mov lr, pc
+ ldr pc, [r4]
+ cmp r0, #0
+ ldmfd sp!, {r0-r2, r4, lr}
+ moveq r0, #0
+ RETeq
+
+.Lnormale:
+ stmfd sp!, {r10-r11, lr}
+
+ GET_PCB(r10)
+ ldr r10, [r10]
+
+ mov r3, #0x00
+ adr ip, .Lcopyout_fault
+ ldr r11, [r10, #PCB_ONFAULT]
+ str ip, [r10, #PCB_ONFAULT]
+ bl .Lcopyout_guts
+ str r11, [r10, #PCB_ONFAULT]
+ mov r0, #0x00
+ ldmfd sp!, {r10-r11, pc}
+
+.Lcopyout_fault:
+ ldr r0, =EFAULT
+ str r11, [r10, #PCB_ONFAULT]
+ cmp r3, #0x00
+ ldmfdgt sp!, {r4-r7} /* r3 > 0 Restore r4-r7 */
+ ldmfdlt sp!, {r4-r9} /* r3 < 0 Restore r4-r9 */
+ ldmfd sp!, {r10-r11, pc}
+
+.Lcopyout_guts:
+ pld [r0]
+ /* Word-align the destination buffer */
+ ands ip, r1, #0x03 /* Already word aligned? */
+ beq .Lcopyout_wordaligned /* Yup */
+ rsb ip, ip, #0x04
+ cmp r2, ip /* Enough bytes left to align it? */
+ blt .Lcopyout_l4_2 /* Nope. Just copy bytewise */
+ sub r2, r2, ip
+ rsbs ip, ip, #0x03
+ addne pc, pc, ip, lsl #3
+ nop
+ ldrb ip, [r0], #0x01
+ strbt ip, [r1], #0x01
+ ldrb ip, [r0], #0x01
+ strbt ip, [r1], #0x01
+ ldrb ip, [r0], #0x01
+ strbt ip, [r1], #0x01
+ cmp r2, #0x00 /* All done? */
+ RETeq
+
+ /* Destination buffer is now word aligned */
+.Lcopyout_wordaligned:
+ ands ip, r0, #0x03 /* Is src also word-aligned? */
+ bne .Lcopyout_bad_align /* Nope. Things just got bad */
+ cmp r2, #0x08 /* Less than 8 bytes remaining? */
+ blt .Lcopyout_w_less_than8
+
+ /* Quad-align the destination buffer */
+ tst r0, #0x07 /* Already quad aligned? */
+ ldrne ip, [r0], #0x04
+ subne r2, r2, #0x04
+ strtne ip, [r1], #0x04
+
+ stmfd sp!, {r4-r9} /* Free up some registers */
+ mov r3, #-1 /* Signal restore r4-r9 */
+
+ /* Destination buffer word aligned, source is quad aligned */
+ subs r2, r2, #0x80
+ blt .Lcopyout_w_lessthan128
+
+ /* Copy 128 bytes at a time */
+.Lcopyout_w_loop128:
+ ldrd r4, [r0], #0x08 /* LD:00-07 */
+ pld [r0, #0x18] /* Prefetch 0x20 */
+ ldrd r6, [r0], #0x08 /* LD:08-0f */
+ ldrd r8, [r0], #0x08 /* LD:10-17 */
+ strt r4, [r1], #0x04 /* ST:00-03 */
+ strt r5, [r1], #0x04 /* ST:04-07 */
+ ldrd r4, [r0], #0x08 /* LD:18-1f */
+ strt r6, [r1], #0x04 /* ST:08-0b */
+ strt r7, [r1], #0x04 /* ST:0c-0f */
+ ldrd r6, [r0], #0x08 /* LD:20-27 */
+ pld [r0, #0x18] /* Prefetch 0x40 */
+ strt r8, [r1], #0x04 /* ST:10-13 */
+ strt r9, [r1], #0x04 /* ST:14-17 */
+ ldrd r8, [r0], #0x08 /* LD:28-2f */
+ strt r4, [r1], #0x04 /* ST:18-1b */
+ strt r5, [r1], #0x04 /* ST:1c-1f */
+ ldrd r4, [r0], #0x08 /* LD:30-37 */
+ strt r6, [r1], #0x04 /* ST:20-23 */
+ strt r7, [r1], #0x04 /* ST:24-27 */
+ ldrd r6, [r0], #0x08 /* LD:38-3f */
+ strt r8, [r1], #0x04 /* ST:28-2b */
+ strt r9, [r1], #0x04 /* ST:2c-2f */
+ ldrd r8, [r0], #0x08 /* LD:40-47 */
+ pld [r0, #0x18] /* Prefetch 0x60 */
+ strt r4, [r1], #0x04 /* ST:30-33 */
+ strt r5, [r1], #0x04 /* ST:34-37 */
+ ldrd r4, [r0], #0x08 /* LD:48-4f */
+ strt r6, [r1], #0x04 /* ST:38-3b */
+ strt r7, [r1], #0x04 /* ST:3c-3f */
+ ldrd r6, [r0], #0x08 /* LD:50-57 */
+ strt r8, [r1], #0x04 /* ST:40-43 */
+ strt r9, [r1], #0x04 /* ST:44-47 */
+ ldrd r8, [r0], #0x08 /* LD:58-4f */
+ strt r4, [r1], #0x04 /* ST:48-4b */
+ strt r5, [r1], #0x04 /* ST:4c-4f */
+ ldrd r4, [r0], #0x08 /* LD:60-67 */
+ pld [r0, #0x18] /* Prefetch 0x80 */
+ strt r6, [r1], #0x04 /* ST:50-53 */
+ strt r7, [r1], #0x04 /* ST:54-57 */
+ ldrd r6, [r0], #0x08 /* LD:68-6f */
+ strt r8, [r1], #0x04 /* ST:58-5b */
+ strt r9, [r1], #0x04 /* ST:5c-5f */
+ ldrd r8, [r0], #0x08 /* LD:70-77 */
+ strt r4, [r1], #0x04 /* ST:60-63 */
+ strt r5, [r1], #0x04 /* ST:64-67 */
+ ldrd r4, [r0], #0x08 /* LD:78-7f */
+ strt r6, [r1], #0x04 /* ST:68-6b */
+ strt r7, [r1], #0x04 /* ST:6c-6f */
+ strt r8, [r1], #0x04 /* ST:70-73 */
+ strt r9, [r1], #0x04 /* ST:74-77 */
+ subs r2, r2, #0x80
+ strt r4, [r1], #0x04 /* ST:78-7b */
+ strt r5, [r1], #0x04 /* ST:7c-7f */
+ bge .Lcopyout_w_loop128
+
+.Lcopyout_w_lessthan128:
+ adds r2, r2, #0x80 /* Adjust for extra sub */
+ ldmfdeq sp!, {r4-r9}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x20
+ blt .Lcopyout_w_lessthan32
+
+ /* Copy 32 bytes at a time */
+.Lcopyout_w_loop32:
+ ldrd r4, [r0], #0x08
+ pld [r0, #0x18]
+ ldrd r6, [r0], #0x08
+ ldrd r8, [r0], #0x08
+ strt r4, [r1], #0x04
+ strt r5, [r1], #0x04
+ ldrd r4, [r0], #0x08
+ strt r6, [r1], #0x04
+ strt r7, [r1], #0x04
+ strt r8, [r1], #0x04
+ strt r9, [r1], #0x04
+ subs r2, r2, #0x20
+ strt r4, [r1], #0x04
+ strt r5, [r1], #0x04
+ bge .Lcopyout_w_loop32
+
+.Lcopyout_w_lessthan32:
+ adds r2, r2, #0x20 /* Adjust for extra sub */
+ ldmfdeq sp!, {r4-r9}
+ RETeq /* Return now if done */
+
+ and r4, r2, #0x18
+ rsb r5, r4, #0x18
+ subs r2, r2, r4
+ add pc, pc, r5, lsl #1
+ nop
+
+ /* At least 24 bytes remaining */
+ ldrd r4, [r0], #0x08
+ strt r4, [r1], #0x04
+ strt r5, [r1], #0x04
+ nop
+
+ /* At least 16 bytes remaining */
+ ldrd r4, [r0], #0x08
+ strt r4, [r1], #0x04
+ strt r5, [r1], #0x04
+ nop
+
+ /* At least 8 bytes remaining */
+ ldrd r4, [r0], #0x08
+ strt r4, [r1], #0x04
+ strt r5, [r1], #0x04
+ nop
+
+ /* Less than 8 bytes remaining */
+ ldmfd sp!, {r4-r9}
+ RETeq /* Return now if done */
+ mov r3, #0x00
+
+.Lcopyout_w_less_than8:
+ subs r2, r2, #0x04
+ ldrge ip, [r0], #0x04
+ strtge ip, [r1], #0x04
+ RETeq /* Return now if done */
+ addlt r2, r2, #0x04
+ ldrb ip, [r0], #0x01
+ cmp r2, #0x02
+ ldrbge r2, [r0], #0x01
+ strbt ip, [r1], #0x01
+ ldrbgt ip, [r0]
+ strbtge r2, [r1], #0x01
+ strbtgt ip, [r1]
+ RET
+
+/*
+ * At this point, it has not been possible to word align both buffers.
+ * The destination buffer (r1) is word aligned, but the source buffer
+ * (r0) is not.
+ */
+.Lcopyout_bad_align:
+ stmfd sp!, {r4-r7}
+ mov r3, #0x01
+ bic r0, r0, #0x03
+ cmp ip, #2
+ ldr ip, [r0], #0x04
+ bgt .Lcopyout_bad3
+ beq .Lcopyout_bad2
+ b .Lcopyout_bad1
+
+.Lcopyout_bad1_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #8
+#else
+ mov r4, ip, lsr #8
+#endif
+ ldr r5, [r0], #0x04
+ pld [r0, #0x018]
+ ldr r6, [r0], #0x04
+ ldr r7, [r0], #0x04
+ ldr ip, [r0], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r6, lsr #24
+ mov r6, r6, lsl #8
+ orr r6, r6, r7, lsr #24
+ mov r7, r7, lsl #8
+ orr r7, r7, ip, lsr #24
+#else
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ mov r6, r6, lsr #8
+ orr r6, r6, r7, lsl #24
+ mov r7, r7, lsr #8
+ orr r7, r7, ip, lsl #24
+#endif
+ strt r4, [r1], #0x04
+ strt r5, [r1], #0x04
+ strt r6, [r1], #0x04
+ strt r7, [r1], #0x04
+.Lcopyout_bad1:
+ subs r2, r2, #0x10
+ bge .Lcopyout_bad1_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r0, r0, #0x03
+ blt .Lcopyout_l4
+
+.Lcopyout_bad1_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #8
+#else
+ mov r4, ip, lsr #8
+#endif
+ ldr ip, [r0], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #24
+#else
+ orr r4, r4, ip, lsl #24
+#endif
+ strt r4, [r1], #0x04
+ bge .Lcopyout_bad1_loop4
+ sub r0, r0, #0x03
+ b .Lcopyout_l4
+
+.Lcopyout_bad2_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #16
+#else
+ mov r4, ip, lsr #16
+#endif
+ ldr r5, [r0], #0x04
+ pld [r0, #0x018]
+ ldr r6, [r0], #0x04
+ ldr r7, [r0], #0x04
+ ldr ip, [r0], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r6, lsr #16
+ mov r6, r6, lsl #16
+ orr r6, r6, r7, lsr #16
+ mov r7, r7, lsl #16
+ orr r7, r7, ip, lsr #16
+#else
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ mov r6, r6, lsr #16
+ orr r6, r6, r7, lsl #16
+ mov r7, r7, lsr #16
+ orr r7, r7, ip, lsl #16
+#endif
+ strt r4, [r1], #0x04
+ strt r5, [r1], #0x04
+ strt r6, [r1], #0x04
+ strt r7, [r1], #0x04
+.Lcopyout_bad2:
+ subs r2, r2, #0x10
+ bge .Lcopyout_bad2_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r0, r0, #0x02
+ blt .Lcopyout_l4
+
+.Lcopyout_bad2_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #16
+#else
+ mov r4, ip, lsr #16
+#endif
+ ldr ip, [r0], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #16
+#else
+ orr r4, r4, ip, lsl #16
+#endif
+ strt r4, [r1], #0x04
+ bge .Lcopyout_bad2_loop4
+ sub r0, r0, #0x02
+ b .Lcopyout_l4
+
+.Lcopyout_bad3_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #24
+#else
+ mov r4, ip, lsr #24
+#endif
+ ldr r5, [r0], #0x04
+ pld [r0, #0x018]
+ ldr r6, [r0], #0x04
+ ldr r7, [r0], #0x04
+ ldr ip, [r0], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r6, lsr #8
+ mov r6, r6, lsl #24
+ orr r6, r6, r7, lsr #8
+ mov r7, r7, lsl #24
+ orr r7, r7, ip, lsr #8
+#else
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ mov r6, r6, lsr #24
+ orr r6, r6, r7, lsl #8
+ mov r7, r7, lsr #24
+ orr r7, r7, ip, lsl #8
+#endif
+ strt r4, [r1], #0x04
+ strt r5, [r1], #0x04
+ strt r6, [r1], #0x04
+ strt r7, [r1], #0x04
+.Lcopyout_bad3:
+ subs r2, r2, #0x10
+ bge .Lcopyout_bad3_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r0, r0, #0x01
+ blt .Lcopyout_l4
+
+.Lcopyout_bad3_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #24
+#else
+ mov r4, ip, lsr #24
+#endif
+ ldr ip, [r0], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #8
+#else
+ orr r4, r4, ip, lsl #8
+#endif
+ strt r4, [r1], #0x04
+ bge .Lcopyout_bad3_loop4
+ sub r0, r0, #0x01
+
+.Lcopyout_l4:
+ ldmfd sp!, {r4-r7}
+ mov r3, #0x00
+ adds r2, r2, #0x04
+ RETeq
+.Lcopyout_l4_2:
+ rsbs r2, r2, #0x03
+ addne pc, pc, r2, lsl #3
+ nop
+ ldrb ip, [r0], #0x01
+ strbt ip, [r1], #0x01
+ ldrb ip, [r0], #0x01
+ strbt ip, [r1], #0x01
+ ldrb ip, [r0]
+ strbt ip, [r1]
+ RET
+END(copyout)
+
Property changes on: trunk/sys/arm/arm/bcopyinout_xscale.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/blockio.S
===================================================================
--- trunk/sys/arm/arm/blockio.S (rev 0)
+++ trunk/sys/arm/arm/blockio.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,597 @@
+/* $MidnightBSD$ */
+/* $NetBSD: blockio.S,v 1.5 2002/08/15 01:38:16 briggs Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ben Harris.
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * blockio.S
+ *
+ * optimised block read/write from/to IO routines.
+ *
+ * Created : 08/10/94
+ * Modified : 22/01/99 -- R.Earnshaw
+ * Faster, and small tweaks for StrongARM
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/blockio.S 275767 2014-12-14 16:28:53Z andrew $");
+
+ .syntax unified
+
+/*
+ * Read bytes from an I/O address into a block of memory
+ *
+ * r0 = address to read from (IO)
+ * r1 = address to write to (memory)
+ * r2 = length
+ */
+
+/* This code will look very familiar if you've read _memcpy(). */
+ENTRY(read_multi_1)
+ mov ip, sp
+ stmfd sp!, {fp, ip, lr, pc}
+ sub fp, ip, #4
+ subs r2, r2, #4 /* r2 = length - 4 */
+ blt .Lrm1_l4 /* less than 4 bytes */
+ ands r12, r1, #3
+ beq .Lrm1_main /* aligned destination */
+ rsb r12, r12, #4
+ cmp r12, #2
+ ldrb r3, [r0]
+ strb r3, [r1], #1
+ ldrbge r3, [r0]
+ strbge r3, [r1], #1
+ ldrbgt r3, [r0]
+ strbgt r3, [r1], #1
+ subs r2, r2, r12
+ blt .Lrm1_l4
+.Lrm1_main:
+.Lrm1loop:
+ ldrb r3, [r0]
+ ldrb r12, [r0]
+ orr r3, r3, r12, lsl #8
+ ldrb r12, [r0]
+ orr r3, r3, r12, lsl #16
+ ldrb r12, [r0]
+ orr r3, r3, r12, lsl #24
+ str r3, [r1], #4
+ subs r2, r2, #4
+ bge .Lrm1loop
+.Lrm1_l4:
+ adds r2, r2, #4 /* r2 = length again */
+ ldmdbeq fp, {fp, sp, pc}
+ RETeq
+ cmp r2, #2
+ ldrb r3, [r0]
+ strb r3, [r1], #1
+ ldrbge r3, [r0]
+ strbge r3, [r1], #1
+ ldrbgt r3, [r0]
+ strbgt r3, [r1], #1
+ ldmdb fp, {fp, sp, pc}
+END(read_multi_1)
+
+/*
+ * Write bytes to an I/O address from a block of memory
+ *
+ * r0 = address to write to (IO)
+ * r1 = address to read from (memory)
+ * r2 = length
+ */
+
+/* This code will look very familiar if you've read _memcpy(). */
+ENTRY(write_multi_1)
+ mov ip, sp
+ stmfd sp!, {fp, ip, lr, pc}
+ sub fp, ip, #4
+ subs r2, r2, #4 /* r2 = length - 4 */
+ blt .Lwm1_l4 /* less than 4 bytes */
+ ands r12, r1, #3
+ beq .Lwm1_main /* aligned source */
+ rsb r12, r12, #4
+ cmp r12, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0]
+ ldrbge r3, [r1], #1
+ strbge r3, [r0]
+ ldrbgt r3, [r1], #1
+ strbgt r3, [r0]
+ subs r2, r2, r12
+ blt .Lwm1_l4
+.Lwm1_main:
+.Lwm1loop:
+ ldr r3, [r1], #4
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ subs r2, r2, #4
+ bge .Lwm1loop
+.Lwm1_l4:
+ adds r2, r2, #4 /* r2 = length again */
+ ldmdbeq fp, {fp, sp, pc}
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0]
+ ldrbge r3, [r1], #1
+ strbge r3, [r0]
+ ldrbgt r3, [r1], #1
+ strbgt r3, [r0]
+ ldmdb fp, {fp, sp, pc}
+END(write_multi_1)
+
+/*
+ * Reads short ints (16 bits) from an I/O address into a block of memory
+ *
+ * r0 = address to read from (IO)
+ * r1 = address to write to (memory)
+ * r2 = length
+ */
+
+ENTRY(insw)
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address and the size is word aligned, do it fast */
+
+ tst r2, #0x00000001
+ tsteq r1, #0x00000003
+ beq .Lfastinsw
+
+/* Non aligned insw */
+
+.Linswloop:
+ ldr r3, [r0]
+ subs r2, r2, #0x00000001 /* Loop test in load delay slot */
+ strb r3, [r1], #0x0001
+ mov r3, r3, lsr #8
+ strb r3, [r1], #0x0001
+ bgt .Linswloop
+
+ RET
+
+/* Word aligned insw */
+
+.Lfastinsw:
+
+.Lfastinswloop:
+ ldr r3, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr ip, [r0]
+ mov r3, r3, lsr #16 /* Put the two shorts together */
+ orr r3, r3, ip, lsl #16
+ str r3, [r1], #0x0004 /* Store */
+ subs r2, r2, #0x00000002 /* Next */
+ bgt .Lfastinswloop
+
+ RET
+END(insw)
+
+/*
+ * Writes short ints (16 bits) from a block of memory to an I/O address
+ *
+ * r0 = address to write to (IO)
+ * r1 = address to read from (memory)
+ * r2 = length
+ */
+
+ENTRY(outsw)
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address and the size is word aligned, do it fast */
+
+ tst r2, #0x00000001
+ tsteq r1, #0x00000003
+ beq .Lfastoutsw
+
+/* Non aligned outsw */
+
+.Loutswloop:
+ ldrb r3, [r1], #0x0001
+ ldrb ip, [r1], #0x0001
+ subs r2, r2, #0x00000001 /* Loop test in load delay slot */
+ orr r3, r3, ip, lsl #8
+ orr r3, r3, r3, lsl #16
+ str r3, [r0]
+ bgt .Loutswloop
+
+ RET
+
+/* Word aligned outsw */
+
+.Lfastoutsw:
+
+.Lfastoutswloop:
+ ldr r3, [r1], #0x0004 /* r3 = (H)(L) */
+ subs r2, r2, #0x00000002 /* Loop test in load delay slot */
+
+ eor ip, r3, r3, lsr #16 /* ip = (H)(H^L) */
+ eor r3, r3, ip, lsl #16 /* r3 = (H^H^L)(L) = (L)(L) */
+ eor ip, ip, r3, lsr #16 /* ip = (H)(H^L^L) = (H)(H) */
+
+ str r3, [r0]
+ str ip, [r0]
+
+/* mov ip, r3, lsl #16
+ * orr ip, ip, ip, lsr #16
+ * str ip, [r0]
+ *
+ * mov ip, r3, lsr #16
+ * orr ip, ip, ip, lsl #16
+ * str ip, [r0]
+ */
+
+ bgt .Lfastoutswloop
+
+ RET
+END(outsw)
+
+/*
+ * reads short ints (16 bits) from an I/O address into a block of memory
+ * with a length garenteed to be a multiple of 16 bytes
+ * with a word aligned destination address
+ *
+ * r0 = address to read from (IO)
+ * r1 = address to write to (memory)
+ * r2 = length
+ */
+
+ENTRY(insw16)
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address is word aligned and the size suitably
+ aligned, do it fast */
+
+ tst r2, #0x00000007
+ tsteq r1, #0x00000003
+
+ bne _C_LABEL(insw)
+
+/* Word aligned insw */
+
+ stmfd sp!, {r4,r5,lr}
+
+.Linsw16loop:
+ ldr r3, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr lr, [r0]
+ mov r3, r3, lsr #16 /* Put the two shorts together */
+ orr r3, r3, lr, lsl #16
+
+ ldr r4, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr lr, [r0]
+ mov r4, r4, lsr #16 /* Put the two shorts together */
+ orr r4, r4, lr, lsl #16
+
+ ldr r5, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr lr, [r0]
+ mov r5, r5, lsr #16 /* Put the two shorts together */
+ orr r5, r5, lr, lsl #16
+
+ ldr ip, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr lr, [r0]
+ mov ip, ip, lsr #16 /* Put the two shorts together */
+ orr ip, ip, lr, lsl #16
+
+ stmia r1!, {r3-r5,ip}
+ subs r2, r2, #0x00000008 /* Next */
+ bgt .Linsw16loop
+
+ ldmfd sp!, {r4,r5,pc} /* Restore regs and go home */
+END(insw16)
+
+/*
+ * Writes short ints (16 bits) from a block of memory to an I/O address
+ *
+ * r0 = address to write to (IO)
+ * r1 = address to read from (memory)
+ * r2 = length
+ */
+
+ENTRY(outsw16)
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address is word aligned and the size suitably
+ aligned, do it fast */
+
+ tst r2, #0x00000007
+ tsteq r1, #0x00000003
+
+ bne _C_LABEL(outsw)
+
+/* Word aligned outsw */
+
+ stmfd sp!, {r4,r5,lr}
+
+.Loutsw16loop:
+ ldmia r1!, {r4,r5,ip,lr}
+
+ eor r3, r4, r4, lsl #16 /* r3 = (A^B)(B) */
+ eor r4, r4, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
+ eor r3, r3, r4, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
+ str r3, [r0]
+ str r4, [r0]
+
+/* mov r3, r4, lsl #16
+ * orr r3, r3, r3, lsr #16
+ * str r3, [r0]
+ *
+ * mov r3, r4, lsr #16
+ * orr r3, r3, r3, lsl #16
+ * str r3, [r0]
+ */
+
+ eor r3, r5, r5, lsl #16 /* r3 = (A^B)(B) */
+ eor r5, r5, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
+ eor r3, r3, r5, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
+ str r3, [r0]
+ str r5, [r0]
+
+ eor r3, ip, ip, lsl #16 /* r3 = (A^B)(B) */
+ eor ip, ip, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
+ eor r3, r3, ip, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
+ str r3, [r0]
+ str ip, [r0]
+
+ eor r3, lr, lr, lsl #16 /* r3 = (A^B)(B) */
+ eor lr, lr, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
+ eor r3, r3, lr, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
+ str r3, [r0]
+ str lr, [r0]
+
+ subs r2, r2, #0x00000008
+ bgt .Loutsw16loop
+
+ ldmfd sp!, {r4,r5,pc} /* and go home */
+END(outsw16)
+
+/*
+ * reads short ints (16 bits) from an I/O address into a block of memory
+ * The I/O address is assumed to be mapped multiple times in a block of
+ * 8 words.
+ * The destination address should be word aligned.
+ *
+ * r0 = address to read from (IO)
+ * r1 = address to write to (memory)
+ * r2 = length
+ */
+
+ENTRY(inswm8)
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address is word aligned and the size suitably
+ aligned, do it fast */
+
+ tst r1, #0x00000003
+
+ bne _C_LABEL(insw)
+
+/* Word aligned insw */
+
+ stmfd sp!, {r4-r9,lr}
+
+ mov lr, #0xff000000
+ orr lr, lr, #0x00ff0000
+
+.Linswm8_loop8:
+ cmp r2, #8
+ bcc .Linswm8_l8
+
+ ldmia r0, {r3-r9,ip}
+
+ bic r3, r3, lr
+ orr r3, r3, r4, lsl #16
+ bic r5, r5, lr
+ orr r4, r5, r6, lsl #16
+ bic r7, r7, lr
+ orr r5, r7, r8, lsl #16
+ bic r9, r9, lr
+ orr r6, r9, ip, lsl #16
+
+ stmia r1!, {r3-r6}
+
+ subs r2, r2, #0x00000008 /* Next */
+ bne .Linswm8_loop8
+ beq .Linswm8_l1
+
+.Linswm8_l8:
+ cmp r2, #4
+ bcc .Linswm8_l4
+
+ ldmia r0, {r3-r6}
+
+ bic r3, r3, lr
+ orr r3, r3, r4, lsl #16
+ bic r5, r5, lr
+ orr r4, r5, r6, lsl #16
+
+ stmia r1!, {r3-r4}
+
+ subs r2, r2, #0x00000004
+ beq .Linswm8_l1
+
+.Linswm8_l4:
+ cmp r2, #2
+ bcc .Linswm8_l2
+
+ ldmia r0, {r3-r4}
+
+ bic r3, r3, lr
+ orr r3, r3, r4, lsl #16
+ str r3, [r1], #0x0004
+
+ subs r2, r2, #0x00000002
+ beq .Linswm8_l1
+
+.Linswm8_l2:
+ cmp r2, #1
+ bcc .Linswm8_l1
+
+ ldr r3, [r0]
+ subs r2, r2, #0x00000001 /* Test in load delay slot */
+ /* XXX, why don't we use result? */
+
+ strb r3, [r1], #0x0001
+ mov r3, r3, lsr #8
+ strb r3, [r1], #0x0001
+
+
+.Linswm8_l1:
+ ldmfd sp!, {r4-r9,pc} /* And go home */
+END(inswm8)
+
+/*
+ * write short ints (16 bits) to an I/O address from a block of memory
+ * The I/O address is assumed to be mapped multiple times in a block of
+ * 8 words.
+ * The source address should be word aligned.
+ *
+ * r0 = address to read to (IO)
+ * r1 = address to write from (memory)
+ * r2 = length
+ */
+
+ENTRY(outswm8)
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address is word aligned and the size suitably
+ aligned, do it fast */
+
+ tst r1, #0x00000003
+
+ bne _C_LABEL(outsw)
+
+/* Word aligned outsw */
+
+ stmfd sp!, {r4-r8,lr}
+
+.Loutswm8_loop8:
+ cmp r2, #8
+ bcc .Loutswm8_l8
+
+ ldmia r1!, {r3,r5,r7,ip}
+
+ eor r4, r3, r3, lsr #16 /* r4 = (A)(A^B) */
+ eor r3, r3, r4, lsl #16 /* r3 = (A^A^B)(B) = (B)(B) */
+ eor r4, r4, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
+
+ eor r6, r5, r5, lsr #16 /* r6 = (A)(A^B) */
+ eor r5, r5, r6, lsl #16 /* r5 = (A^A^B)(B) = (B)(B) */
+ eor r6, r6, r5, lsr #16 /* r6 = (A)(B^A^B) = (A)(A) */
+
+ eor r8, r7, r7, lsr #16 /* r8 = (A)(A^B) */
+ eor r7, r7, r8, lsl #16 /* r7 = (A^A^B)(B) = (B)(B) */
+ eor r8, r8, r7, lsr #16 /* r8 = (A)(B^A^B) = (A)(A) */
+
+ eor lr, ip, ip, lsr #16 /* lr = (A)(A^B) */
+ eor ip, ip, lr, lsl #16 /* ip = (A^A^B)(B) = (B)(B) */
+ eor lr, lr, ip, lsr #16 /* lr = (A)(B^A^B) = (A)(A) */
+
+ stmia r0, {r3-r8,ip,lr}
+
+ subs r2, r2, #0x00000008 /* Next */
+ bne .Loutswm8_loop8
+ beq .Loutswm8_l1
+
+.Loutswm8_l8:
+ cmp r2, #4
+ bcc .Loutswm8_l4
+
+ ldmia r1!, {r3-r4}
+
+ eor r6, r3, r3, lsr #16 /* r6 = (A)(A^B) */
+ eor r5, r3, r6, lsl #16 /* r5 = (A^A^B)(B) = (B)(B) */
+ eor r6, r6, r5, lsr #16 /* r6 = (A)(B^A^B) = (A)(A) */
+
+ eor r8, r4, r4, lsr #16 /* r8 = (A)(A^B) */
+ eor r7, r4, r8, lsl #16 /* r7 = (A^A^B)(B) = (B)(B) */
+ eor r8, r8, r7, lsr #16 /* r8 = (A)(B^A^B) = (A)(A) */
+
+ stmia r0, {r5-r8}
+
+ subs r2, r2, #0x00000004
+ beq .Loutswm8_l1
+
+.Loutswm8_l4:
+ cmp r2, #2
+ bcc .Loutswm8_l2
+
+ ldr r3, [r1], #0x0004 /* r3 = (A)(B) */
+ subs r2, r2, #0x00000002 /* Done test in Load delay slot */
+
+ eor r5, r3, r3, lsr #16 /* r5 = (A)(A^B)*/
+ eor r4, r3, r5, lsl #16 /* r4 = (A^A^B)(B) = (B)(B) */
+ eor r5, r5, r4, lsr #16 /* r5 = (A)(B^A^B) = (A)(A) */
+
+ stmia r0, {r4, r5}
+
+ beq .Loutswm8_l1
+
+.Loutswm8_l2:
+ cmp r2, #1
+ bcc .Loutswm8_l1
+
+ ldrb r3, [r1], #0x0001
+ ldrb r4, [r1], #0x0001
+ subs r2, r2, #0x00000001 /* Done test in load delay slot */
+ /* XXX This test isn't used? */
+ orr r3, r3, r4, lsl #8
+ orr r3, r3, r3, lsl #16
+ str r3, [r0]
+
+.Loutswm8_l1:
+ ldmfd sp!, {r4-r8,pc} /* And go home */
+END(outswm8)
+
Property changes on: trunk/sys/arm/arm/blockio.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/bootconfig.c
===================================================================
--- trunk/sys/arm/arm/bootconfig.c (rev 0)
+++ trunk/sys/arm/arm/bootconfig.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,127 @@
+/* $MidnightBSD$ */
+/* $NetBSD: bootconfig.c,v 1.2 2002/03/10 19:56:39 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/bootconfig.c 236991 2012-06-13 04:59:55Z imp $");
+
+#include <sys/param.h>
+
+#include <sys/systm.h>
+
+#include <machine/bootconfig.h>
+
+
+/*
+ * Function to identify and process different types of boot argument
+ */
+
+int
+get_bootconf_option(opts, opt, type, result)
+ char *opts;
+ char *opt;
+ int type;
+ void *result;
+{
+ char *ptr;
+ char *optstart;
+ int not;
+
+ ptr = opts;
+
+ while (*ptr) {
+ /* Find start of option */
+ while (*ptr == ' ' || *ptr == '\t')
+ ++ptr;
+
+ if (*ptr == 0)
+ break;
+
+ not = 0;
+
+ /* Is it a negate option */
+ if ((type & BOOTOPT_TYPE_MASK) == BOOTOPT_TYPE_BOOLEAN && *ptr == '!') {
+ not = 1;
+ ++ptr;
+ }
+
+ /* Find the end of option */
+ optstart = ptr;
+ while (*ptr != 0 && *ptr != ' ' && *ptr != '\t' && *ptr != '=')
+ ++ptr;
+
+ if ((*ptr == '=')
+ || (*ptr != '=' && ((type & BOOTOPT_TYPE_MASK) == BOOTOPT_TYPE_BOOLEAN))) {
+ /* compare the option */
+ if (strncmp(optstart, opt, (ptr - optstart)) == 0) {
+ /* found */
+
+ if (*ptr == '=')
+ ++ptr;
+
+ switch(type & BOOTOPT_TYPE_MASK) {
+ case BOOTOPT_TYPE_BOOLEAN :
+ if (*(ptr - 1) == '=')
+ *((int *)result) = ((u_int)strtoul(ptr, NULL, 10) != 0);
+ else
+ *((int *)result) = !not;
+ break;
+ case BOOTOPT_TYPE_STRING :
+ *((char **)result) = ptr;
+ break;
+ case BOOTOPT_TYPE_INT :
+ *((int *)result) = (u_int)strtoul(ptr, NULL, 10);
+ break;
+ case BOOTOPT_TYPE_BININT :
+ *((int *)result) = (u_int)strtoul(ptr, NULL, 2);
+ break;
+ case BOOTOPT_TYPE_HEXINT :
+ *((int *)result) = (u_int)strtoul(ptr, NULL, 16);
+ break;
+ default:
+ return(0);
+ }
+ return(1);
+ }
+ }
+ /* skip to next option */
+ while (*ptr != ' ' && *ptr != '\t' && *ptr != 0)
+ ++ptr;
+ }
+ return(0);
+}
Property changes on: trunk/sys/arm/arm/bootconfig.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/bus_space_asm_generic.S
===================================================================
--- trunk/sys/arm/arm/bus_space_asm_generic.S (rev 0)
+++ trunk/sys/arm/arm/bus_space_asm_generic.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,361 @@
+/* $MidnightBSD$ */
+/* $NetBSD: bus_space_asm_generic.S,v 1.3 2003/03/27 19:46:14 mycroft Exp $ */
+
+/*-
+ * Copyright (c) 1997 Causality Limited.
+ * Copyright (c) 1997 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+#include <machine/cpuconf.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/bus_space_asm_generic.S 278727 2015-02-13 22:32:02Z ian $");
+
+/*
+ * Generic bus_space functions.
+ */
+
+/*
+ * read single
+ */
+
+ENTRY(generic_bs_r_1)
+ ldrb r0, [r1, r2]
+ RET
+END(generic_bs_r_1)
+
+ENTRY(generic_bs_r_2)
+ ldrh r0, [r1, r2]
+ RET
+END(generic_bs_r_2)
+
+ENTRY(generic_bs_r_4)
+ ldr r0, [r1, r2]
+ RET
+END(generic_bs_r_4)
+
+/*
+ * write single
+ */
+
+ENTRY(generic_bs_w_1)
+ strb r3, [r1, r2]
+ RET
+END(generic_bs_w_1)
+
+ENTRY(generic_bs_w_2)
+ strh r3, [r1, r2]
+ RET
+END(generic_bs_w_2)
+
+ENTRY(generic_bs_w_4)
+ str r3, [r1, r2]
+ RET
+END(generic_bs_w_4)
+
+/*
+ * read multiple
+ */
+
+ENTRY(generic_bs_rm_1)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldrb r3, [r0]
+ strb r3, [r1], #1
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_rm_1)
+
+ENTRY(generic_bs_rm_2)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldrh r3, [r0]
+ strh r3, [r1], #2
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_rm_2)
+
+ENTRY(generic_bs_rm_4)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldr r3, [r0]
+ str r3, [r1], #4
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_rm_4)
+
+/*
+ * write multiple
+ */
+
+ENTRY(generic_bs_wm_1)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldrb r3, [r1], #1
+ strb r3, [r0]
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_wm_1)
+
+ENTRY(generic_bs_wm_2)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldrh r3, [r1], #2
+ strh r3, [r0]
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_wm_2)
+
+ENTRY(generic_bs_wm_4)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldr r3, [r1], #4
+ str r3, [r0]
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_wm_4)
+
+/*
+ * read region
+ */
+
+ENTRY(generic_bs_rr_1)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldrb r3, [r0], #1
+ strb r3, [r1], #1
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_rr_1)
+
+ENTRY(generic_bs_rr_2)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldrh r3, [r0], #2
+ strh r3, [r1], #2
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_rr_2)
+
+ENTRY(generic_bs_rr_4)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldr r3, [r0], #4
+ str r3, [r1], #4
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_rr_4)
+
+/*
+ * write region.
+ */
+
+ENTRY(generic_bs_wr_1)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_wr_1)
+
+ENTRY(generic_bs_wr_2)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldrh r3, [r1], #2
+ strh r3, [r0], #2
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_wr_2)
+
+ENTRY(generic_bs_wr_4)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: ldr r3, [r1], #4
+ str r3, [r0], #4
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_wr_4)
+
+/*
+ * set region
+ */
+
+ENTRY(generic_bs_sr_1)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: strb r1, [r0], #1
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_sr_1)
+
+ENTRY(generic_bs_sr_2)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: strh r1, [r0], #2
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_sr_2)
+
+ENTRY(generic_bs_sr_4)
+ add r0, r1, r2
+ mov r1, r3
+ ldr r2, [sp, #0]
+ teq r2, #0
+ RETeq
+
+1: str r1, [r0], #4
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+END(generic_bs_sr_4)
+
+/*
+ * copy region
+ */
+
+ENTRY(generic_bs_c_2)
+ add r0, r1, r2
+ ldr r2, [sp, #0]
+ add r1, r2, r3
+ ldr r2, [sp, #4]
+ teq r2, #0
+ RETeq
+
+ cmp r0, r1
+ blt 2f
+
+1: ldrh r3, [r0], #2
+ strh r3, [r1], #2
+ subs r2, r2, #1
+ bne 1b
+
+ RET
+
+2: add r0, r0, r2, lsl #1
+ add r1, r1, r2, lsl #1
+ sub r0, r0, #2
+ sub r1, r1, #2
+
+3: ldrh r3, [r0], #-2
+ strh r3, [r1], #-2
+ subs r2, r2, #1
+ bne 3b
+
+ RET
+END(generic_bs_c_2)
+
Property changes on: trunk/sys/arm/arm/bus_space_asm_generic.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/bus_space_base.c
===================================================================
--- trunk/sys/arm/arm/bus_space_base.c (rev 0)
+++ trunk/sys/arm/arm/bus_space_base.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,160 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/bus_space_base.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <machine/bus.h>
+
+#include "opt_platform.h"
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(generic);
+
+/*
+ * The bus space tag. This is constant for all instances, so
+ * we never have to explicitly "create" it.
+ */
+static struct bus_space arm_base_bus_space __aligned(CACHE_LINE_SIZE) = {
+ /* privdata is whatever the implementer wants; unused in base tag */
+ .bs_privdata = NULL,
+
+ /* mapping/unmapping */
+ .bs_map = generic_bs_map,
+ .bs_unmap = generic_bs_unmap,
+ .bs_subregion = generic_bs_subregion,
+
+ /* allocation/deallocation */
+ .bs_alloc = generic_bs_alloc,
+ .bs_free = generic_bs_free,
+
+ /* barrier */
+ .bs_barrier = generic_bs_barrier,
+
+ /* read (single) */
+ .bs_r_1 = NULL, /* Use inline code in bus.h */
+ .bs_r_2 = NULL, /* Use inline code in bus.h */
+ .bs_r_4 = NULL, /* Use inline code in bus.h */
+ .bs_r_8 = NULL, /* Use inline code in bus.h */
+
+ /* read multiple */
+ .bs_rm_1 = generic_bs_rm_1,
+ .bs_rm_2 = generic_bs_rm_2,
+ .bs_rm_4 = generic_bs_rm_4,
+ .bs_rm_8 = BS_UNIMPLEMENTED,
+
+ /* read region */
+ .bs_rr_1 = generic_bs_rr_1,
+ .bs_rr_2 = generic_bs_rr_2,
+ .bs_rr_4 = generic_bs_rr_4,
+ .bs_rr_8 = BS_UNIMPLEMENTED,
+
+ /* write (single) */
+ .bs_w_1 = NULL, /* Use inline code in bus.h */
+ .bs_w_2 = NULL, /* Use inline code in bus.h */
+ .bs_w_4 = NULL, /* Use inline code in bus.h */
+ .bs_w_8 = NULL, /* Use inline code in bus.h */
+
+ /* write multiple */
+ .bs_wm_1 = generic_bs_wm_1,
+ .bs_wm_2 = generic_bs_wm_2,
+ .bs_wm_4 = generic_bs_wm_4,
+ .bs_wm_8 = BS_UNIMPLEMENTED,
+
+ /* write region */
+ .bs_wr_1 = generic_bs_wr_1,
+ .bs_wr_2 = generic_bs_wr_2,
+ .bs_wr_4 = generic_bs_wr_4,
+ .bs_wr_8 = BS_UNIMPLEMENTED,
+
+ /* set multiple */
+ .bs_sm_1 = BS_UNIMPLEMENTED,
+ .bs_sm_2 = BS_UNIMPLEMENTED,
+ .bs_sm_4 = BS_UNIMPLEMENTED,
+ .bs_sm_8 = BS_UNIMPLEMENTED,
+
+ /* set region */
+ .bs_sr_1 = generic_bs_sr_1,
+ .bs_sr_2 = generic_bs_sr_2,
+ .bs_sr_4 = generic_bs_sr_4,
+ .bs_sr_8 = BS_UNIMPLEMENTED,
+
+ /* copy */
+ .bs_c_1 = BS_UNIMPLEMENTED,
+ .bs_c_2 = generic_bs_c_2,
+ .bs_c_4 = BS_UNIMPLEMENTED,
+ .bs_c_8 = BS_UNIMPLEMENTED,
+
+ /* read stream (single) */
+ .bs_r_1_s = NULL, /* Use inline code in bus.h */
+ .bs_r_2_s = NULL, /* Use inline code in bus.h */
+ .bs_r_4_s = NULL, /* Use inline code in bus.h */
+ .bs_r_8_s = NULL, /* Use inline code in bus.h */
+
+ /* read multiple stream */
+ .bs_rm_1_s = generic_bs_rm_1,
+ .bs_rm_2_s = generic_bs_rm_2,
+ .bs_rm_4_s = generic_bs_rm_4,
+ .bs_rm_8_s = BS_UNIMPLEMENTED,
+
+ /* read region stream */
+ .bs_rr_1_s = generic_bs_rr_1,
+ .bs_rr_2_s = generic_bs_rr_2,
+ .bs_rr_4_s = generic_bs_rr_4,
+ .bs_rr_8_s = BS_UNIMPLEMENTED,
+
+ /* write stream (single) */
+ .bs_w_1_s = NULL, /* Use inline code in bus.h */
+ .bs_w_2_s = NULL, /* Use inline code in bus.h */
+ .bs_w_4_s = NULL, /* Use inline code in bus.h */
+ .bs_w_8_s = NULL, /* Use inline code in bus.h */
+
+ /* write multiple stream */
+ .bs_wm_1_s = generic_bs_wm_1,
+ .bs_wm_2_s = generic_bs_wm_2,
+ .bs_wm_4_s = generic_bs_wm_4,
+ .bs_wm_8_s = BS_UNIMPLEMENTED,
+
+ /* write region stream */
+ .bs_wr_1_s = generic_bs_wr_1,
+ .bs_wr_2_s = generic_bs_wr_2,
+ .bs_wr_4_s = generic_bs_wr_4,
+ .bs_wr_8_s = BS_UNIMPLEMENTED,
+};
+
+#ifdef FDT
+bus_space_tag_t fdtbus_bs_tag = &arm_base_bus_space;
+#endif
+
+bus_space_tag_t arm_base_bs_tag = &arm_base_bus_space;
Property changes on: trunk/sys/arm/arm/bus_space_base.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/bus_space_generic.c
===================================================================
--- trunk/sys/arm/arm/bus_space_generic.c (rev 0)
+++ trunk/sys/arm/arm/bus_space_generic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,134 @@
+/* $MidnightBSD$ */
+/* $NetBSD: obio_space.c,v 1.6 2003/07/15 00:25:05 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/bus_space_generic.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <machine/devmap.h>
+
+void
+generic_bs_unimplemented(void)
+{
+
+ panic("unimplemented bus_space function called");
+}
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(generic);
+
+int
+generic_bs_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ void *va;
+
+ /*
+ * We don't even examine the passed-in flags. For ARM, the CACHEABLE
+ * flag doesn't make sense (we create PTE_DEVICE mappings), and the
+ * LINEAR flag is just implied because we use kva_alloc(size).
+ */
+ if ((va = pmap_mapdev(bpa, size)) == NULL)
+ return (ENOMEM);
+ *bshp = (bus_space_handle_t)va;
+ return (0);
+}
+
+int
+generic_bs_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
+ bus_size_t alignment, bus_size_t boundary, int flags, bus_addr_t *bpap,
+ bus_space_handle_t *bshp)
+{
+
+ panic("generic_bs_alloc(): not implemented");
+}
+
+
+void
+generic_bs_unmap(bus_space_tag_t t, bus_space_handle_t h, bus_size_t size)
+{
+
+ pmap_unmapdev((vm_offset_t)h, size);
+}
+
+void
+generic_bs_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
+{
+
+ panic("generic_bs_free(): not implemented");
+}
+
+int
+generic_bs_subregion(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t size, bus_space_handle_t *nbshp)
+{
+
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+void
+generic_bs_barrier(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t len, int flags)
+{
+
+ /*
+ * dsb() will drain the L1 write buffer and establish a memory access
+ * barrier point on platforms where that has meaning. On a write we
+ * also need to drain the L2 write buffer, because most on-chip memory
+ * mapped devices are downstream of the L2 cache. Note that this needs
+ * to be done even for memory mapped as Device type, because while
+ * Device memory is not cached, writes to it are still buffered.
+ */
+ dsb();
+ if (flags & BUS_SPACE_BARRIER_WRITE) {
+ cpu_l2cache_drain_writebuf();
+ }
+}
Property changes on: trunk/sys/arm/arm/bus_space_generic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/busdma_machdep-v6.c
===================================================================
--- trunk/sys/arm/arm/busdma_machdep-v6.c (rev 0)
+++ trunk/sys/arm/arm/busdma_machdep-v6.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1734 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012-2014 Ian Lepore
+ * Copyright (c) 2010 Mark Tinguely
+ * Copyright (c) 2004 Olivier Houchard
+ * Copyright (c) 2002 Peter Grehan
+ * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From i386/busdma_machdep.c 191438 2009-04-23 20:24:19Z jhb
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/busdma_machdep-v6.c 318977 2017-05-27 08:17:59Z hselasky $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/kdb.h>
+#include <ddb/ddb.h>
+#include <ddb/db_output.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/busdma_bufalloc.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/memdesc.h>
+#include <sys/proc.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+
+#include <machine/atomic.h>
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+
+#define MAX_BPAGES 64
+#define MAX_DMA_SEGMENTS 4096
+#define BUS_DMA_EXCL_BOUNCE BUS_DMA_BUS2
+#define BUS_DMA_ALIGN_BOUNCE BUS_DMA_BUS3
+#define BUS_DMA_COULD_BOUNCE (BUS_DMA_EXCL_BOUNCE | BUS_DMA_ALIGN_BOUNCE)
+#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4
+
+struct bounce_zone;
+
+struct bus_dma_tag {
+ bus_dma_tag_t parent;
+ bus_size_t alignment;
+ bus_size_t boundary;
+ bus_addr_t lowaddr;
+ bus_addr_t highaddr;
+ bus_dma_filter_t *filter;
+ void *filterarg;
+ bus_size_t maxsize;
+ u_int nsegments;
+ bus_size_t maxsegsz;
+ int flags;
+ int ref_count;
+ int map_count;
+ bus_dma_lock_t *lockfunc;
+ void *lockfuncarg;
+ struct bounce_zone *bounce_zone;
+ /*
+ * DMA range for this tag. If the page doesn't fall within
+ * one of these ranges, an error is returned. The caller
+ * may then decide what to do with the transfer. If the
+ * range pointer is NULL, it is ignored.
+ */
+ struct arm32_dma_range *ranges;
+ int _nranges;
+};
+
+struct bounce_page {
+ vm_offset_t vaddr; /* kva of bounce buffer */
+ bus_addr_t busaddr; /* Physical address */
+ vm_offset_t datavaddr; /* kva of client data */
+ bus_addr_t dataaddr; /* client physical address */
+ bus_size_t datacount; /* client data count */
+ STAILQ_ENTRY(bounce_page) links;
+};
+
+struct sync_list {
+ vm_offset_t vaddr; /* kva of bounce buffer */
+ bus_addr_t busaddr; /* Physical address */
+ bus_size_t datacount; /* client data count */
+};
+
+int busdma_swi_pending;
+
+struct bounce_zone {
+ STAILQ_ENTRY(bounce_zone) links;
+ STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
+ int total_bpages;
+ int free_bpages;
+ int reserved_bpages;
+ int active_bpages;
+ int total_bounced;
+ int total_deferred;
+ int map_count;
+ bus_size_t alignment;
+ bus_addr_t lowaddr;
+ char zoneid[8];
+ char lowaddrid[20];
+ struct sysctl_ctx_list sysctl_tree;
+ struct sysctl_oid *sysctl_tree_top;
+};
+
+static struct mtx bounce_lock;
+static int total_bpages;
+static int busdma_zonecount;
+static uint32_t tags_total;
+static uint32_t maps_total;
+static uint32_t maps_dmamem;
+static uint32_t maps_coherent;
+static uint64_t maploads_total;
+static uint64_t maploads_bounced;
+static uint64_t maploads_coherent;
+static uint64_t maploads_dmamem;
+static uint64_t maploads_mbuf;
+static uint64_t maploads_physmem;
+
+static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+
+SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters");
+SYSCTL_UINT(_hw_busdma, OID_AUTO, tags_total, CTLFLAG_RD, &tags_total, 0,
+ "Number of active tags");
+SYSCTL_UINT(_hw_busdma, OID_AUTO, maps_total, CTLFLAG_RD, &maps_total, 0,
+ "Number of active maps");
+SYSCTL_UINT(_hw_busdma, OID_AUTO, maps_dmamem, CTLFLAG_RD, &maps_dmamem, 0,
+ "Number of active maps for bus_dmamem_alloc buffers");
+SYSCTL_UINT(_hw_busdma, OID_AUTO, maps_coherent, CTLFLAG_RD, &maps_coherent, 0,
+ "Number of active maps with BUS_DMA_COHERENT flag set");
+SYSCTL_UQUAD(_hw_busdma, OID_AUTO, maploads_total, CTLFLAG_RD, &maploads_total, 0,
+ "Number of load operations performed");
+SYSCTL_UQUAD(_hw_busdma, OID_AUTO, maploads_bounced, CTLFLAG_RD, &maploads_bounced, 0,
+ "Number of load operations that used bounce buffers");
+SYSCTL_UQUAD(_hw_busdma, OID_AUTO, maploads_coherent, CTLFLAG_RD, &maploads_dmamem, 0,
+ "Number of load operations on BUS_DMA_COHERENT memory");
+SYSCTL_UQUAD(_hw_busdma, OID_AUTO, maploads_dmamem, CTLFLAG_RD, &maploads_dmamem, 0,
+ "Number of load operations on bus_dmamem_alloc buffers");
+SYSCTL_UQUAD(_hw_busdma, OID_AUTO, maploads_mbuf, CTLFLAG_RD, &maploads_mbuf, 0,
+ "Number of load operations for mbufs");
+SYSCTL_UQUAD(_hw_busdma, OID_AUTO, maploads_physmem, CTLFLAG_RD, &maploads_physmem, 0,
+ "Number of load operations on physical buffers");
+SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0,
+ "Total bounce pages");
+
+struct bus_dmamap {
+ struct bp_list bpages;
+ int pagesneeded;
+ int pagesreserved;
+ bus_dma_tag_t dmat;
+ struct memdesc mem;
+ pmap_t pmap;
+ bus_dmamap_callback_t *callback;
+ void *callback_arg;
+ int flags;
+#define DMAMAP_COHERENT (1 << 0)
+#define DMAMAP_DMAMEM_ALLOC (1 << 1)
+#define DMAMAP_MBUF (1 << 2)
+ STAILQ_ENTRY(bus_dmamap) links;
+ bus_dma_segment_t *segments;
+ int sync_count;
+ struct sync_list slist[];
+};
+
+static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
+static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
+
+static void init_bounce_pages(void *dummy);
+static int alloc_bounce_zone(bus_dma_tag_t dmat);
+static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages);
+static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
+ int commit);
+static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
+ vm_offset_t vaddr, bus_addr_t addr,
+ bus_size_t size);
+static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
+static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
+ void *buf, bus_size_t buflen, int flags);
+static void _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map,
+ vm_paddr_t buf, bus_size_t buflen, int flags);
+static int _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
+ int flags);
+
+static busdma_bufalloc_t coherent_allocator; /* Cache of coherent buffers */
+static busdma_bufalloc_t standard_allocator; /* Cache of standard buffers */
+static void
+busdma_init(void *dummy)
+{
+ int uma_flags;
+
+ uma_flags = 0;
+
+ /* Create a cache of buffers in standard (cacheable) memory. */
+ standard_allocator = busdma_bufalloc_create("buffer",
+ arm_dcache_align, /* minimum_alignment */
+ NULL, /* uma_alloc func */
+ NULL, /* uma_free func */
+ uma_flags); /* uma_zcreate_flags */
+
+#ifdef INVARIANTS
+ /*
+ * Force UMA zone to allocate service structures like
+ * slabs using own allocator. uma_debug code performs
+ * atomic ops on uma_slab_t fields and safety of this
+ * operation is not guaranteed for write-back caches
+ */
+ uma_flags = UMA_ZONE_OFFPAGE;
+#endif
+ /*
+ * Create a cache of buffers in uncacheable memory, to implement the
+ * BUS_DMA_COHERENT (and potentially BUS_DMA_NOCACHE) flag.
+ */
+ coherent_allocator = busdma_bufalloc_create("coherent",
+ arm_dcache_align, /* minimum_alignment */
+ busdma_bufalloc_alloc_uncacheable,
+ busdma_bufalloc_free_uncacheable,
+ uma_flags); /* uma_zcreate_flags */
+}
+
+/*
+ * This init historically used SI_SUB_VM, but now the init code requires
+ * malloc(9) using M_DEVBUF memory, which is set up later than SI_SUB_VM, by
+ * SI_SUB_KMEM and SI_ORDER_SECOND, so we'll go right after that by using
+ * SI_SUB_KMEM and SI_ORDER_THIRD.
+ */
+SYSINIT(busdma, SI_SUB_KMEM, SI_ORDER_THIRD, busdma_init, NULL);
+
+static int
+exclusion_bounce_check(vm_offset_t lowaddr, vm_offset_t highaddr)
+{
+ int i;
+ for (i = 0; phys_avail[i] && phys_avail[i + 1]; i += 2) {
+ if ((lowaddr >= phys_avail[i] && lowaddr < phys_avail[i + 1]) ||
+ (lowaddr < phys_avail[i] && highaddr >= phys_avail[i]))
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Return true if the tag has an exclusion zone that could lead to bouncing.
+ */
+static __inline int
+exclusion_bounce(bus_dma_tag_t dmat)
+{
+
+ return (dmat->flags & BUS_DMA_EXCL_BOUNCE);
+}
+
+/*
+ * Return true if the given address does not fall on the alignment boundary.
+ */
+static __inline int
+alignment_bounce(bus_dma_tag_t dmat, bus_addr_t addr)
+{
+
+ return (addr & (dmat->alignment - 1));
+}
+
+/*
+ * Return true if the DMA should bounce because the start or end does not fall
+ * on a cacheline boundary (which would require a partial cacheline flush).
+ * COHERENT memory doesn't trigger cacheline flushes. Memory allocated by
+ * bus_dmamem_alloc() is always aligned to cacheline boundaries, and there's a
+ * strict rule that such memory cannot be accessed by the CPU while DMA is in
+ * progress (or by multiple DMA engines at once), so that it's always safe to do
+ * full cacheline flushes even if that affects memory outside the range of a
+ * given DMA operation that doesn't involve the full allocated buffer. If we're
+ * mapping an mbuf, that follows the same rules as a buffer we allocated.
+ */
+static __inline int
+cacheline_bounce(bus_dmamap_t map, bus_addr_t addr, bus_size_t size)
+{
+
+ if (map->flags & (DMAMAP_DMAMEM_ALLOC | DMAMAP_COHERENT | DMAMAP_MBUF))
+ return (0);
+ return ((addr | size) & arm_dcache_align_mask);
+}
+
+/*
+ * Return true if we might need to bounce the DMA described by addr and size.
+ *
+ * This is used to quick-check whether we need to do the more expensive work of
+ * checking the DMA page-by-page looking for alignment and exclusion bounces.
+ *
+ * Note that the addr argument might be either virtual or physical. It doesn't
+ * matter because we only look at the low-order bits, which are the same in both
+ * address spaces.
+ */
+static __inline int
+might_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t addr,
+ bus_size_t size)
+{
+
+ return ((dmat->flags & BUS_DMA_EXCL_BOUNCE) ||
+ alignment_bounce(dmat, addr) ||
+ cacheline_bounce(map, addr, size));
+}
+
+/*
+ * Return true if we must bounce the DMA described by paddr and size.
+ *
+ * Bouncing can be triggered by DMA that doesn't begin and end on cacheline
+ * boundaries, or doesn't begin on an alignment boundary, or falls within the
+ * exclusion zone of any tag in the ancestry chain.
+ *
+ * For exclusions, walk the chain of tags comparing paddr to the exclusion zone
+ * within each tag. If the tag has a filter function, use it to decide whether
+ * the DMA needs to bounce, otherwise any DMA within the zone bounces.
+ */
+static int
+must_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr,
+ bus_size_t size)
+{
+
+ if (cacheline_bounce(map, paddr, size))
+ return (1);
+
+ /*
+ * The tag already contains ancestors' alignment restrictions so this
+ * check doesn't need to be inside the loop.
+ */
+ if (alignment_bounce(dmat, paddr))
+ return (1);
+
+ /*
+ * Even though each tag has an exclusion zone that is a superset of its
+ * own and all its ancestors' exclusions, the exclusion zone of each tag
+ * up the chain must be checked within the loop, because the busdma
+ * rules say the filter function is called only when the address lies
+ * within the low-highaddr range of the tag that filterfunc belongs to.
+ */
+ while (dmat != NULL && exclusion_bounce(dmat)) {
+ if ((paddr >= dmat->lowaddr && paddr <= dmat->highaddr) &&
+ (dmat->filter == NULL ||
+ dmat->filter(dmat->filterarg, paddr) != 0))
+ return (1);
+ dmat = dmat->parent;
+ }
+
+ return (0);
+}
+
+static __inline struct arm32_dma_range *
+_bus_dma_inrange(struct arm32_dma_range *ranges, int nranges,
+ bus_addr_t curaddr)
+{
+ struct arm32_dma_range *dr;
+ int i;
+
+ for (i = 0, dr = ranges; i < nranges; i++, dr++) {
+ if (curaddr >= dr->dr_sysbase &&
+ round_page(curaddr) <= (dr->dr_sysbase + dr->dr_len))
+ return (dr);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Convenience function for manipulating driver locks from busdma (during
+ * busdma_swi, for example). Drivers that don't provide their own locks
+ * should specify &Giant to dmat->lockfuncarg. Drivers that use their own
+ * non-mutex locking scheme don't have to use this at all.
+ */
+void
+busdma_lock_mutex(void *arg, bus_dma_lock_op_t op)
+{
+ struct mtx *dmtx;
+
+ dmtx = (struct mtx *)arg;
+ switch (op) {
+ case BUS_DMA_LOCK:
+ mtx_lock(dmtx);
+ break;
+ case BUS_DMA_UNLOCK:
+ mtx_unlock(dmtx);
+ break;
+ default:
+ panic("Unknown operation 0x%x for busdma_lock_mutex!", op);
+ }
+}
+
+/*
+ * dflt_lock should never get called. It gets put into the dma tag when
+ * lockfunc == NULL, which is only valid if the maps that are associated
+ * with the tag are meant to never be defered.
+ * XXX Should have a way to identify which driver is responsible here.
+ */
+static void
+dflt_lock(void *arg, bus_dma_lock_op_t op)
+{
+
+ panic("driver error: busdma dflt_lock called");
+}
+
+/*
+ * Allocate a device specific dma_tag.
+ */
+int
+bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
+ bus_size_t boundary, bus_addr_t lowaddr,
+ bus_addr_t highaddr, bus_dma_filter_t *filter,
+ void *filterarg, bus_size_t maxsize, int nsegments,
+ bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
+ void *lockfuncarg, bus_dma_tag_t *dmat)
+{
+ bus_dma_tag_t newtag;
+ int error = 0;
+
+#if 0
+ if (!parent)
+ parent = arm_root_dma_tag;
+#endif
+
+ /* Basic sanity checking */
+ if (boundary != 0 && boundary < maxsegsz)
+ maxsegsz = boundary;
+
+ /* Return a NULL tag on failure */
+ *dmat = NULL;
+
+ if (maxsegsz == 0) {
+ return (EINVAL);
+ }
+
+ newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
+ M_ZERO | M_NOWAIT);
+ if (newtag == NULL) {
+ CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
+ __func__, newtag, 0, error);
+ return (ENOMEM);
+ }
+
+ newtag->parent = parent;
+ newtag->alignment = alignment;
+ newtag->boundary = boundary;
+ newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
+ newtag->highaddr = trunc_page((vm_paddr_t)highaddr) +
+ (PAGE_SIZE - 1);
+ newtag->filter = filter;
+ newtag->filterarg = filterarg;
+ newtag->maxsize = maxsize;
+ newtag->nsegments = nsegments;
+ newtag->maxsegsz = maxsegsz;
+ newtag->flags = flags;
+ newtag->ref_count = 1; /* Count ourself */
+ newtag->map_count = 0;
+ newtag->ranges = bus_dma_get_range();
+ newtag->_nranges = bus_dma_get_range_nb();
+ if (lockfunc != NULL) {
+ newtag->lockfunc = lockfunc;
+ newtag->lockfuncarg = lockfuncarg;
+ } else {
+ newtag->lockfunc = dflt_lock;
+ newtag->lockfuncarg = NULL;
+ }
+
+ /* Take into account any restrictions imposed by our parent tag */
+ if (parent != NULL) {
+ newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr);
+ newtag->highaddr = MAX(parent->highaddr, newtag->highaddr);
+ newtag->alignment = MAX(parent->alignment, newtag->alignment);
+ newtag->flags |= parent->flags & BUS_DMA_COULD_BOUNCE;
+ if (newtag->boundary == 0)
+ newtag->boundary = parent->boundary;
+ else if (parent->boundary != 0)
+ newtag->boundary = MIN(parent->boundary,
+ newtag->boundary);
+ if (newtag->filter == NULL) {
+ /*
+ * Short circuit to looking at our parent directly
+ * since we have encapsulated all of its information
+ */
+ newtag->filter = parent->filter;
+ newtag->filterarg = parent->filterarg;
+ newtag->parent = parent->parent;
+ }
+ if (newtag->parent != NULL)
+ atomic_add_int(&parent->ref_count, 1);
+ }
+
+ if (exclusion_bounce_check(newtag->lowaddr, newtag->highaddr))
+ newtag->flags |= BUS_DMA_EXCL_BOUNCE;
+ if (alignment_bounce(newtag, 1))
+ newtag->flags |= BUS_DMA_ALIGN_BOUNCE;
+
+ /*
+ * Any request can auto-bounce due to cacheline alignment, in addition
+ * to any alignment or boundary specifications in the tag, so if the
+ * ALLOCNOW flag is set, there's always work to do.
+ */
+ if ((flags & BUS_DMA_ALLOCNOW) != 0) {
+ struct bounce_zone *bz;
+ /*
+ * Round size up to a full page, and add one more page because
+ * there can always be one more boundary crossing than the
+ * number of pages in a transfer.
+ */
+ maxsize = roundup2(maxsize, PAGE_SIZE) + PAGE_SIZE;
+
+ if ((error = alloc_bounce_zone(newtag)) != 0) {
+ free(newtag, M_DEVBUF);
+ return (error);
+ }
+ bz = newtag->bounce_zone;
+
+ if (ptoa(bz->total_bpages) < maxsize) {
+ int pages;
+
+ pages = atop(maxsize) - bz->total_bpages;
+
+ /* Add pages to our bounce pool */
+ if (alloc_bounce_pages(newtag, pages) < pages)
+ error = ENOMEM;
+ }
+ /* Performed initial allocation */
+ newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ } else
+ newtag->bounce_zone = NULL;
+
+ if (error != 0) {
+ free(newtag, M_DEVBUF);
+ } else {
+ atomic_add_32(&tags_total, 1);
+ *dmat = newtag;
+ }
+ CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
+ __func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
+ return (error);
+}
+
+int
+bus_dma_tag_destroy(bus_dma_tag_t dmat)
+{
+ bus_dma_tag_t dmat_copy;
+ int error;
+
+ error = 0;
+ dmat_copy = dmat;
+
+ if (dmat != NULL) {
+
+ if (dmat->map_count != 0) {
+ error = EBUSY;
+ goto out;
+ }
+
+ while (dmat != NULL) {
+ bus_dma_tag_t parent;
+
+ parent = dmat->parent;
+ atomic_subtract_int(&dmat->ref_count, 1);
+ if (dmat->ref_count == 0) {
+ atomic_subtract_32(&tags_total, 1);
+ free(dmat, M_DEVBUF);
+ /*
+ * Last reference count, so
+ * release our reference
+ * count on our parent.
+ */
+ dmat = parent;
+ } else
+ dmat = NULL;
+ }
+ }
+out:
+ CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
+ return (error);
+}
+
+static int allocate_bz_and_pages(bus_dma_tag_t dmat, bus_dmamap_t mapp)
+{
+ struct bounce_zone *bz;
+ int maxpages;
+ int error;
+
+ if (dmat->bounce_zone == NULL)
+ if ((error = alloc_bounce_zone(dmat)) != 0)
+ return (error);
+ bz = dmat->bounce_zone;
+ /* Initialize the new map */
+ STAILQ_INIT(&(mapp->bpages));
+
+ /*
+ * Attempt to add pages to our pool on a per-instance basis up to a sane
+ * limit. Even if the tag isn't flagged as COULD_BOUNCE due to
+ * alignment and boundary constraints, it could still auto-bounce due to
+ * cacheline alignment, which requires at most two bounce pages.
+ */
+ if (dmat->flags & BUS_DMA_COULD_BOUNCE)
+ maxpages = MAX_BPAGES;
+ else
+ maxpages = 2 * bz->map_count;
+ if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 ||
+ (bz->map_count > 0 && bz->total_bpages < maxpages)) {
+ int pages;
+
+ pages = atop(roundup2(dmat->maxsize, PAGE_SIZE)) + 1;
+ pages = MIN(maxpages - bz->total_bpages, pages);
+ pages = MAX(pages, 2);
+ if (alloc_bounce_pages(dmat, pages) < pages)
+ return (ENOMEM);
+
+ if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0)
+ dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ }
+ bz->map_count++;
+ return (0);
+}
+
+static bus_dmamap_t
+allocate_map(bus_dma_tag_t dmat, int mflags)
+{
+ int mapsize, segsize;
+ bus_dmamap_t map;
+
+ /*
+ * Allocate the map. The map structure ends with an embedded
+ * variable-sized array of sync_list structures. Following that
+ * we allocate enough extra space to hold the array of bus_dma_segments.
+ */
+ KASSERT(dmat->nsegments <= MAX_DMA_SEGMENTS,
+ ("cannot allocate %u dma segments (max is %u)",
+ dmat->nsegments, MAX_DMA_SEGMENTS));
+ segsize = sizeof(struct bus_dma_segment) * dmat->nsegments;
+ mapsize = sizeof(*map) + sizeof(struct sync_list) * dmat->nsegments;
+ map = malloc(mapsize + segsize, M_DEVBUF, mflags | M_ZERO);
+ if (map == NULL) {
+ CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM);
+ return (NULL);
+ }
+ map->segments = (bus_dma_segment_t *)((uintptr_t)map + mapsize);
+ return (map);
+}
+
+/*
+ * Allocate a handle for mapping from kva/uva/physical
+ * address space into bus device space.
+ */
+int
+bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
+{
+ bus_dmamap_t map;
+ int error = 0;
+
+ *mapp = map = allocate_map(dmat, M_NOWAIT);
+ if (map == NULL) {
+ CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM);
+ return (ENOMEM);
+ }
+
+ /*
+ * Bouncing might be required if the driver asks for an exclusion
+ * region, a data alignment that is stricter than 1, or DMA that begins
+ * or ends with a partial cacheline. Whether bouncing will actually
+ * happen can't be known until mapping time, but we need to pre-allocate
+ * resources now because we might not be allowed to at mapping time.
+ */
+ error = allocate_bz_and_pages(dmat, map);
+ if (error != 0) {
+ free(map, M_DEVBUF);
+ *mapp = NULL;
+ return (error);
+ }
+ if (map->flags & DMAMAP_COHERENT)
+ atomic_add_32(&maps_coherent, 1);
+ atomic_add_32(&maps_total, 1);
+ dmat->map_count++;
+
+ return (0);
+}
+
+/*
+ * Destroy a handle for mapping from kva/uva/physical
+ * address space into bus device space.
+ */
+int
+bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+ if (STAILQ_FIRST(&map->bpages) != NULL || map->sync_count != 0) {
+ CTR3(KTR_BUSDMA, "%s: tag %p error %d",
+ __func__, dmat, EBUSY);
+ return (EBUSY);
+ }
+ if (dmat->bounce_zone)
+ dmat->bounce_zone->map_count--;
+ if (map->flags & DMAMAP_COHERENT)
+ atomic_subtract_32(&maps_coherent, 1);
+ atomic_subtract_32(&maps_total, 1);
+ free(map, M_DEVBUF);
+ dmat->map_count--;
+ CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
+ return (0);
+}
+
+
+/*
+ * Allocate a piece of memory that can be efficiently mapped into
+ * bus device space based on the constraints lited in the dma tag.
+ * A dmamap to for use with dmamap_load is also allocated.
+ */
+int
+bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
+ bus_dmamap_t *mapp)
+{
+ busdma_bufalloc_t ba;
+ struct busdma_bufzone *bufzone;
+ bus_dmamap_t map;
+ vm_memattr_t memattr;
+ int mflags;
+
+ if (flags & BUS_DMA_NOWAIT)
+ mflags = M_NOWAIT;
+ else
+ mflags = M_WAITOK;
+ if (flags & BUS_DMA_ZERO)
+ mflags |= M_ZERO;
+
+ *mapp = map = allocate_map(dmat, mflags);
+ if (map == NULL) {
+ CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+ __func__, dmat, dmat->flags, ENOMEM);
+ return (ENOMEM);
+ }
+ map->flags = DMAMAP_DMAMEM_ALLOC;
+
+ /* Choose a busdma buffer allocator based on memory type flags. */
+ if (flags & BUS_DMA_COHERENT) {
+ memattr = VM_MEMATTR_UNCACHEABLE;
+ ba = coherent_allocator;
+ map->flags |= DMAMAP_COHERENT;
+ } else {
+ memattr = VM_MEMATTR_DEFAULT;
+ ba = standard_allocator;
+ }
+
+ /*
+ * Try to find a bufzone in the allocator that holds a cache of buffers
+ * of the right size for this request. If the buffer is too big to be
+ * held in the allocator cache, this returns NULL.
+ */
+ bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
+
+ /*
+ * Allocate the buffer from the uma(9) allocator if...
+ * - It's small enough to be in the allocator (bufzone not NULL).
+ * - The alignment constraint isn't larger than the allocation size
+ * (the allocator aligns buffers to their size boundaries).
+ * - There's no need to handle lowaddr/highaddr exclusion zones.
+ * else allocate non-contiguous pages if...
+ * - The page count that could get allocated doesn't exceed
+ * nsegments also when the maximum segment size is less
+ * than PAGE_SIZE.
+ * - The alignment constraint isn't larger than a page boundary.
+ * - There are no boundary-crossing constraints.
+ * else allocate a block of contiguous pages because one or more of the
+ * constraints is something that only the contig allocator can fulfill.
+ */
+ if (bufzone != NULL && dmat->alignment <= bufzone->size &&
+ !exclusion_bounce(dmat)) {
+ *vaddr = uma_zalloc(bufzone->umazone, mflags);
+ } else if (dmat->nsegments >=
+ howmany(dmat->maxsize, MIN(dmat->maxsegsz, PAGE_SIZE)) &&
+ dmat->alignment <= PAGE_SIZE &&
+ (dmat->boundary % PAGE_SIZE) == 0) {
+ *vaddr = (void *)kmem_alloc_attr(kernel_arena, dmat->maxsize,
+ mflags, 0, dmat->lowaddr, memattr);
+ } else {
+ *vaddr = (void *)kmem_alloc_contig(kernel_arena, dmat->maxsize,
+ mflags, 0, dmat->lowaddr, dmat->alignment, dmat->boundary,
+ memattr);
+ }
+
+
+ if (*vaddr == NULL) {
+ CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+ __func__, dmat, dmat->flags, ENOMEM);
+ free(map, M_DEVBUF);
+ *mapp = NULL;
+ return (ENOMEM);
+ } else if ((uintptr_t)*vaddr & (dmat->alignment - 1)) {
+ printf("bus_dmamem_alloc failed to align memory properly.\n");
+ }
+ if (map->flags & DMAMAP_COHERENT)
+ atomic_add_32(&maps_coherent, 1);
+ atomic_add_32(&maps_dmamem, 1);
+ atomic_add_32(&maps_total, 1);
+ dmat->map_count++;
+
+ CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+ __func__, dmat, dmat->flags, 0);
+ return (0);
+}
+
+/*
+ * Free a piece of memory and it's allociated dmamap, that was allocated
+ * via bus_dmamem_alloc. Make the same choice for free/contigfree.
+ */
+void
+bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
+{
+ struct busdma_bufzone *bufzone;
+ busdma_bufalloc_t ba;
+
+ if (map->flags & DMAMAP_COHERENT)
+ ba = coherent_allocator;
+ else
+ ba = standard_allocator;
+
+ bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
+
+ if (bufzone != NULL && dmat->alignment <= bufzone->size &&
+ !exclusion_bounce(dmat))
+ uma_zfree(bufzone->umazone, vaddr);
+ else
+ kmem_free(kernel_arena, (vm_offset_t)vaddr, dmat->maxsize);
+
+ dmat->map_count--;
+ if (map->flags & DMAMAP_COHERENT)
+ atomic_subtract_32(&maps_coherent, 1);
+ atomic_subtract_32(&maps_total, 1);
+ atomic_subtract_32(&maps_dmamem, 1);
+ free(map, M_DEVBUF);
+ CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
+}
+
+static void
+_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
+ bus_size_t buflen, int flags)
+{
+ bus_addr_t curaddr;
+ bus_size_t sgsize;
+
+ if (map->pagesneeded == 0) {
+ CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d"
+ " map= %p, pagesneeded= %d",
+ dmat->lowaddr, dmat->boundary, dmat->alignment,
+ map, map->pagesneeded);
+ /*
+ * Count the number of bounce pages
+ * needed in order to complete this transfer
+ */
+ curaddr = buf;
+ while (buflen != 0) {
+ sgsize = MIN(buflen, dmat->maxsegsz);
+ if (must_bounce(dmat, map, curaddr, sgsize) != 0) {
+ sgsize = MIN(sgsize, PAGE_SIZE);
+ map->pagesneeded++;
+ }
+ curaddr += sgsize;
+ buflen -= sgsize;
+ }
+ CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded);
+ }
+}
+
+static void
+_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
+ void *buf, bus_size_t buflen, int flags)
+{
+ vm_offset_t vaddr;
+ vm_offset_t vendaddr;
+ bus_addr_t paddr;
+
+ if (map->pagesneeded == 0) {
+ CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d"
+ " map= %p, pagesneeded= %d",
+ dmat->lowaddr, dmat->boundary, dmat->alignment,
+ map, map->pagesneeded);
+ /*
+ * Count the number of bounce pages
+ * needed in order to complete this transfer
+ */
+ vaddr = (vm_offset_t)buf;
+ vendaddr = (vm_offset_t)buf + buflen;
+
+ while (vaddr < vendaddr) {
+ if (__predict_true(map->pmap == kernel_pmap))
+ paddr = pmap_kextract(vaddr);
+ else
+ paddr = pmap_extract(map->pmap, vaddr);
+ if (must_bounce(dmat, map, paddr,
+ min(vendaddr - vaddr, (PAGE_SIZE - ((vm_offset_t)vaddr &
+ PAGE_MASK)))) != 0) {
+ map->pagesneeded++;
+ }
+ vaddr += (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK));
+
+ }
+ CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded);
+ }
+}
+
+static int
+_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
+{
+
+ /* Reserve Necessary Bounce Pages */
+ mtx_lock(&bounce_lock);
+ if (flags & BUS_DMA_NOWAIT) {
+ if (reserve_bounce_pages(dmat, map, 0) != 0) {
+ map->pagesneeded = 0;
+ mtx_unlock(&bounce_lock);
+ return (ENOMEM);
+ }
+ } else {
+ if (reserve_bounce_pages(dmat, map, 1) != 0) {
+ /* Queue us for resources */
+ STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links);
+ mtx_unlock(&bounce_lock);
+ return (EINPROGRESS);
+ }
+ }
+ mtx_unlock(&bounce_lock);
+
+ return (0);
+}
+
+/*
+ * Add a single contiguous physical range to the segment list.
+ */
+static int
+_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr,
+ bus_size_t sgsize, bus_dma_segment_t *segs, int *segp)
+{
+ bus_addr_t baddr, bmask;
+ int seg;
+
+ /*
+ * Make sure we don't cross any boundaries.
+ */
+ bmask = ~(dmat->boundary - 1);
+ if (dmat->boundary > 0) {
+ baddr = (curaddr + dmat->boundary) & bmask;
+ if (sgsize > (baddr - curaddr))
+ sgsize = (baddr - curaddr);
+ }
+
+ if (dmat->ranges) {
+ struct arm32_dma_range *dr;
+
+ dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges,
+ curaddr);
+ if (dr == NULL) {
+ _bus_dmamap_unload(dmat, map);
+ return (0);
+ }
+ /*
+ * In a valid DMA range. Translate the physical
+ * memory address to an address in the DMA window.
+ */
+ curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase;
+ }
+
+ /*
+ * Insert chunk into a segment, coalescing with
+ * previous segment if possible.
+ */
+ seg = *segp;
+ if (seg == -1) {
+ seg = 0;
+ segs[seg].ds_addr = curaddr;
+ segs[seg].ds_len = sgsize;
+ } else {
+ if (curaddr == segs[seg].ds_addr + segs[seg].ds_len &&
+ (segs[seg].ds_len + sgsize) <= dmat->maxsegsz &&
+ (dmat->boundary == 0 ||
+ (segs[seg].ds_addr & bmask) == (curaddr & bmask)))
+ segs[seg].ds_len += sgsize;
+ else {
+ if (++seg >= dmat->nsegments)
+ return (0);
+ segs[seg].ds_addr = curaddr;
+ segs[seg].ds_len = sgsize;
+ }
+ }
+ *segp = seg;
+ return (sgsize);
+}
+
+/*
+ * Utility function to load a physical buffer. segp contains
+ * the starting segment on entrace, and the ending segment on exit.
+ */
+int
+_bus_dmamap_load_phys(bus_dma_tag_t dmat,
+ bus_dmamap_t map,
+ vm_paddr_t buf, bus_size_t buflen,
+ int flags,
+ bus_dma_segment_t *segs,
+ int *segp)
+{
+ bus_addr_t curaddr;
+ bus_size_t sgsize;
+ int error;
+
+ if (segs == NULL)
+ segs = map->segments;
+
+ maploads_total++;
+ maploads_physmem++;
+
+ if (might_bounce(dmat, map, buflen, buflen)) {
+ _bus_dmamap_count_phys(dmat, map, buf, buflen, flags);
+ if (map->pagesneeded != 0) {
+ maploads_bounced++;
+ error = _bus_dmamap_reserve_pages(dmat, map, flags);
+ if (error)
+ return (error);
+ }
+ }
+
+ while (buflen > 0) {
+ curaddr = buf;
+ sgsize = MIN(buflen, dmat->maxsegsz);
+ if (map->pagesneeded != 0 && must_bounce(dmat, map, curaddr,
+ sgsize)) {
+ sgsize = MIN(sgsize, PAGE_SIZE);
+ curaddr = add_bounce_page(dmat, map, 0, curaddr,
+ sgsize);
+ }
+ sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
+ segp);
+ if (sgsize == 0)
+ break;
+ buf += sgsize;
+ buflen -= sgsize;
+ }
+
+ /*
+ * Did we fit?
+ */
+ if (buflen != 0) {
+ _bus_dmamap_unload(dmat, map);
+ return (EFBIG); /* XXX better return value here? */
+ }
+ return (0);
+}
+
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+
+ return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+ segs, segp));
+}
+
+/*
+ * Utility function to load a linear buffer. segp contains
+ * the starting segment on entrace, and the ending segment on exit.
+ */
+int
+_bus_dmamap_load_buffer(bus_dma_tag_t dmat,
+ bus_dmamap_t map,
+ void *buf, bus_size_t buflen,
+ pmap_t pmap,
+ int flags,
+ bus_dma_segment_t *segs,
+ int *segp)
+{
+ bus_size_t sgsize;
+ bus_addr_t curaddr;
+ vm_offset_t vaddr;
+ struct sync_list *sl;
+ int error;
+
+ maploads_total++;
+ if (map->flags & DMAMAP_COHERENT)
+ maploads_coherent++;
+ if (map->flags & DMAMAP_DMAMEM_ALLOC)
+ maploads_dmamem++;
+
+ if (segs == NULL)
+ segs = map->segments;
+
+ if (flags & BUS_DMA_LOAD_MBUF) {
+ maploads_mbuf++;
+ map->flags |= DMAMAP_MBUF;
+ }
+
+ map->pmap = pmap;
+
+ if (might_bounce(dmat, map, (bus_addr_t)buf, buflen)) {
+ _bus_dmamap_count_pages(dmat, map, buf, buflen, flags);
+ if (map->pagesneeded != 0) {
+ maploads_bounced++;
+ error = _bus_dmamap_reserve_pages(dmat, map, flags);
+ if (error)
+ return (error);
+ }
+ }
+
+ sl = NULL;
+ vaddr = (vm_offset_t)buf;
+
+ while (buflen > 0) {
+ /*
+ * Get the physical address for this segment.
+ */
+ if (__predict_true(map->pmap == kernel_pmap))
+ curaddr = pmap_kextract(vaddr);
+ else
+ curaddr = pmap_extract(map->pmap, vaddr);
+
+ /*
+ * Compute the segment size, and adjust counts.
+ */
+ sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK);
+ if (sgsize > dmat->maxsegsz)
+ sgsize = dmat->maxsegsz;
+ if (buflen < sgsize)
+ sgsize = buflen;
+
+ if (map->pagesneeded != 0 && must_bounce(dmat, map, curaddr,
+ sgsize)) {
+ curaddr = add_bounce_page(dmat, map, vaddr, curaddr,
+ sgsize);
+ } else {
+ sl = &map->slist[map->sync_count - 1];
+ if (map->sync_count == 0 ||
+#ifdef ARM_L2_PIPT
+ curaddr != sl->busaddr + sl->datacount ||
+#endif
+ vaddr != sl->vaddr + sl->datacount) {
+ if (++map->sync_count > dmat->nsegments)
+ goto cleanup;
+ sl++;
+ sl->vaddr = vaddr;
+ sl->datacount = sgsize;
+ sl->busaddr = curaddr;
+ } else
+ sl->datacount += sgsize;
+ }
+ sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
+ segp);
+ if (sgsize == 0)
+ break;
+ vaddr += sgsize;
+ buflen -= sgsize;
+ }
+
+cleanup:
+ /*
+ * Did we fit?
+ */
+ if (buflen != 0) {
+ _bus_dmamap_unload(dmat, map);
+ return (EFBIG); /* XXX better return value here? */
+ }
+ return (0);
+}
+
+
+void
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct memdesc *mem, bus_dmamap_callback_t *callback,
+ void *callback_arg)
+{
+
+ map->mem = *mem;
+ map->dmat = dmat;
+ map->callback = callback;
+ map->callback_arg = callback_arg;
+}
+
+bus_dma_segment_t *
+_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+ if (segs == NULL)
+ segs = map->segments;
+ return (segs);
+}
+
+/*
+ * Release the mapping held by map.
+ */
+void
+_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+ struct bounce_page *bpage;
+ struct bounce_zone *bz;
+
+ if ((bz = dmat->bounce_zone) != NULL) {
+ while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
+ STAILQ_REMOVE_HEAD(&map->bpages, links);
+ free_bounce_page(dmat, bpage);
+ }
+
+ bz = dmat->bounce_zone;
+ bz->free_bpages += map->pagesreserved;
+ bz->reserved_bpages -= map->pagesreserved;
+ map->pagesreserved = 0;
+ map->pagesneeded = 0;
+ }
+ map->sync_count = 0;
+ map->flags &= ~DMAMAP_MBUF;
+}
+
+#ifdef notyetbounceuser
+/* If busdma uses user pages, then the interrupt handler could
+ * be use the kernel vm mapping. Both bounce pages and sync list
+ * do not cross page boundaries.
+ * Below is a rough sequence that a person would do to fix the
+ * user page reference in the kernel vmspace. This would be
+ * done in the dma post routine.
+ */
+void
+_bus_dmamap_fix_user(vm_offset_t buf, bus_size_t len,
+ pmap_t pmap, int op)
+{
+ bus_size_t sgsize;
+ bus_addr_t curaddr;
+ vm_offset_t va;
+
+ /*
+ * each synclist entry is contained within a single page.
+ * this would be needed if BUS_DMASYNC_POSTxxxx was implemented
+ */
+ curaddr = pmap_extract(pmap, buf);
+ va = pmap_dma_map(curaddr);
+ switch (op) {
+ case SYNC_USER_INV:
+ cpu_dcache_wb_range(va, sgsize);
+ break;
+
+ case SYNC_USER_COPYTO:
+ bcopy((void *)va, (void *)bounce, sgsize);
+ break;
+
+ case SYNC_USER_COPYFROM:
+ bcopy((void *) bounce, (void *)va, sgsize);
+ break;
+
+ default:
+ break;
+ }
+
+ pmap_dma_unmap(va);
+}
+#endif
+
+#ifdef ARM_L2_PIPT
+#define l2cache_wb_range(va, pa, size) cpu_l2cache_wb_range(pa, size)
+#define l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range(pa, size)
+#define l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range(pa, size)
+#else
+#define l2cache_wb_range(va, pa, size) cpu_l2cache_wb_range(va, size)
+#define l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range(va, size)
+#define l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range(va, size)
+#endif
+
+void
+_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
+{
+ struct bounce_page *bpage;
+ struct sync_list *sl, *end;
+ /*
+ * If the buffer was from user space, it is possible that this is not
+ * the same vm map, especially on a POST operation. It's not clear that
+ * dma on userland buffers can work at all right now. To be safe, until
+ * we're able to test direct userland dma, panic on a map mismatch.
+ */
+ if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
+ if (!pmap_dmap_iscurrent(map->pmap))
+ panic("_bus_dmamap_sync: wrong user map for bounce sync.");
+
+ CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
+ "performing bounce", __func__, dmat, dmat->flags, op);
+
+ /*
+ * For PREWRITE do a writeback. Clean the caches from the
+ * innermost to the outermost levels.
+ */
+ if (op & BUS_DMASYNC_PREWRITE) {
+ while (bpage != NULL) {
+ if (bpage->datavaddr != 0)
+ bcopy((void *)bpage->datavaddr,
+ (void *)bpage->vaddr,
+ bpage->datacount);
+ else
+ physcopyout(bpage->dataaddr,
+ (void *)bpage->vaddr,
+ bpage->datacount);
+ cpu_dcache_wb_range((vm_offset_t)bpage->vaddr,
+ bpage->datacount);
+ l2cache_wb_range((vm_offset_t)bpage->vaddr,
+ (vm_offset_t)bpage->busaddr,
+ bpage->datacount);
+ bpage = STAILQ_NEXT(bpage, links);
+ }
+ dmat->bounce_zone->total_bounced++;
+ }
+
+ /*
+ * Do an invalidate for PREREAD unless a writeback was already
+ * done above due to PREWRITE also being set. The reason for a
+ * PREREAD invalidate is to prevent dirty lines currently in the
+ * cache from being evicted during the DMA. If a writeback was
+ * done due to PREWRITE also being set there will be no dirty
+ * lines and the POSTREAD invalidate handles the rest. The
+ * invalidate is done from the innermost to outermost level. If
+ * L2 were done first, a dirty cacheline could be automatically
+ * evicted from L1 before we invalidated it, re-dirtying the L2.
+ */
+ if ((op & BUS_DMASYNC_PREREAD) && !(op & BUS_DMASYNC_PREWRITE)) {
+ bpage = STAILQ_FIRST(&map->bpages);
+ while (bpage != NULL) {
+ cpu_dcache_inv_range((vm_offset_t)bpage->vaddr,
+ bpage->datacount);
+ l2cache_inv_range((vm_offset_t)bpage->vaddr,
+ (vm_offset_t)bpage->busaddr,
+ bpage->datacount);
+ bpage = STAILQ_NEXT(bpage, links);
+ }
+ }
+
+ /*
+ * Re-invalidate the caches on a POSTREAD, even though they were
+ * already invalidated at PREREAD time. Aggressive prefetching
+ * due to accesses to other data near the dma buffer could have
+ * brought buffer data into the caches which is now stale. The
+ * caches are invalidated from the outermost to innermost; the
+ * prefetches could be happening right now, and if L1 were
+ * invalidated first, stale L2 data could be prefetched into L1.
+ */
+ if (op & BUS_DMASYNC_POSTREAD) {
+ while (bpage != NULL) {
+ vm_offset_t startv;
+ vm_paddr_t startp;
+ int len;
+
+ startv = bpage->vaddr &~ arm_dcache_align_mask;
+ startp = bpage->busaddr &~ arm_dcache_align_mask;
+ len = bpage->datacount;
+
+ if (startv != bpage->vaddr)
+ len += bpage->vaddr & arm_dcache_align_mask;
+ if (len & arm_dcache_align_mask)
+ len = (len -
+ (len & arm_dcache_align_mask)) +
+ arm_dcache_align;
+ l2cache_inv_range(startv, startp, len);
+ cpu_dcache_inv_range(startv, len);
+ if (bpage->datavaddr != 0)
+ bcopy((void *)bpage->vaddr,
+ (void *)bpage->datavaddr,
+ bpage->datacount);
+ else
+ physcopyin((void *)bpage->vaddr,
+ bpage->dataaddr,
+ bpage->datacount);
+ bpage = STAILQ_NEXT(bpage, links);
+ }
+ dmat->bounce_zone->total_bounced++;
+ }
+ }
+
+ /*
+ * For COHERENT memory no cache maintenance is necessary, but ensure all
+ * writes have reached memory for the PREWRITE case. No action is
+ * needed for a PREREAD without PREWRITE also set, because that would
+ * imply that the cpu had written to the COHERENT buffer and expected
+ * the dma device to see that change, and by definition a PREWRITE sync
+ * is required to make that happen.
+ */
+ if (map->flags & DMAMAP_COHERENT) {
+ if (op & BUS_DMASYNC_PREWRITE) {
+ dsb();
+ cpu_l2cache_drain_writebuf();
+ }
+ return;
+ }
+
+ /*
+ * Cache maintenance for normal (non-COHERENT non-bounce) buffers. All
+ * the comments about the sequences for flushing cache levels in the
+ * bounce buffer code above apply here as well. In particular, the fact
+ * that the sequence is inner-to-outer for PREREAD invalidation and
+ * outer-to-inner for POSTREAD invalidation is not a mistake.
+ */
+ if (map->sync_count != 0) {
+ if (!pmap_dmap_iscurrent(map->pmap))
+ panic("_bus_dmamap_sync: wrong user map for sync.");
+
+ sl = &map->slist[0];
+ end = &map->slist[map->sync_count];
+ CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
+ "performing sync", __func__, dmat, dmat->flags, op);
+
+ switch (op) {
+ case BUS_DMASYNC_PREWRITE:
+ case BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD:
+ while (sl != end) {
+ cpu_dcache_wb_range(sl->vaddr, sl->datacount);
+ l2cache_wb_range(sl->vaddr, sl->busaddr,
+ sl->datacount);
+ sl++;
+ }
+ break;
+
+ case BUS_DMASYNC_PREREAD:
+ /*
+ * An mbuf may start in the middle of a cacheline. There
+ * will be no cpu writes to the beginning of that line
+ * (which contains the mbuf header) while dma is in
+ * progress. Handle that case by doing a writeback of
+ * just the first cacheline before invalidating the
+ * overall buffer. Any mbuf in a chain may have this
+ * misalignment. Buffers which are not mbufs bounce if
+ * they are not aligned to a cacheline.
+ */
+ while (sl != end) {
+ if (sl->vaddr & arm_dcache_align_mask) {
+ KASSERT(map->flags & DMAMAP_MBUF,
+ ("unaligned buffer is not an mbuf"));
+ cpu_dcache_wb_range(sl->vaddr, 1);
+ l2cache_wb_range(sl->vaddr,
+ sl->busaddr, 1);
+ }
+ cpu_dcache_inv_range(sl->vaddr, sl->datacount);
+ l2cache_inv_range(sl->vaddr, sl->busaddr,
+ sl->datacount);
+ sl++;
+ }
+ break;
+
+ case BUS_DMASYNC_POSTWRITE:
+ break;
+
+ case BUS_DMASYNC_POSTREAD:
+ case BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE:
+ while (sl != end) {
+ l2cache_inv_range(sl->vaddr, sl->busaddr,
+ sl->datacount);
+ cpu_dcache_inv_range(sl->vaddr, sl->datacount);
+ sl++;
+ }
+ break;
+
+ default:
+ panic("unsupported combination of sync operations: 0x%08x\n", op);
+ break;
+ }
+ }
+}
+
+static void
+init_bounce_pages(void *dummy __unused)
+{
+
+ total_bpages = 0;
+ STAILQ_INIT(&bounce_zone_list);
+ STAILQ_INIT(&bounce_map_waitinglist);
+ STAILQ_INIT(&bounce_map_callbacklist);
+ mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
+}
+SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
+
+static struct sysctl_ctx_list *
+busdma_sysctl_tree(struct bounce_zone *bz)
+{
+
+ return (&bz->sysctl_tree);
+}
+
+static struct sysctl_oid *
+busdma_sysctl_tree_top(struct bounce_zone *bz)
+{
+
+ return (bz->sysctl_tree_top);
+}
+
+static int
+alloc_bounce_zone(bus_dma_tag_t dmat)
+{
+ struct bounce_zone *bz;
+
+ /* Check to see if we already have a suitable zone */
+ STAILQ_FOREACH(bz, &bounce_zone_list, links) {
+ if ((dmat->alignment <= bz->alignment) &&
+ (dmat->lowaddr >= bz->lowaddr)) {
+ dmat->bounce_zone = bz;
+ return (0);
+ }
+ }
+
+ if ((bz = (struct bounce_zone *)malloc(sizeof(*bz), M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL)
+ return (ENOMEM);
+
+ STAILQ_INIT(&bz->bounce_page_list);
+ bz->free_bpages = 0;
+ bz->reserved_bpages = 0;
+ bz->active_bpages = 0;
+ bz->lowaddr = dmat->lowaddr;
+ bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
+ bz->map_count = 0;
+ snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
+ busdma_zonecount++;
+ snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
+ STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links);
+ dmat->bounce_zone = bz;
+
+ sysctl_ctx_init(&bz->sysctl_tree);
+ bz->sysctl_tree_top = SYSCTL_ADD_NODE(&bz->sysctl_tree,
+ SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid,
+ CTLFLAG_RD, 0, "");
+ if (bz->sysctl_tree_top == NULL) {
+ sysctl_ctx_free(&bz->sysctl_tree);
+ return (0); /* XXX error code? */
+ }
+
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0,
+ "Total bounce pages");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0,
+ "Free bounce pages");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0,
+ "Reserved bounce pages");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0,
+ "Active bounce pages");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0,
+ "Total bounce requests (pages bounced)");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0,
+ "Total bounce requests that were deferred");
+ SYSCTL_ADD_STRING(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, "");
+ SYSCTL_ADD_ULONG(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "alignment", CTLFLAG_RD, &bz->alignment, "");
+
+ return (0);
+}
+
+static int
+alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
+{
+ struct bounce_zone *bz;
+ int count;
+
+ bz = dmat->bounce_zone;
+ count = 0;
+ while (numpages > 0) {
+ struct bounce_page *bpage;
+
+ bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+
+ if (bpage == NULL)
+ break;
+ bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
+ M_NOWAIT, 0ul, bz->lowaddr, PAGE_SIZE, 0);
+ if (bpage->vaddr == 0) {
+ free(bpage, M_DEVBUF);
+ break;
+ }
+ bpage->busaddr = pmap_kextract(bpage->vaddr);
+ mtx_lock(&bounce_lock);
+ STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links);
+ total_bpages++;
+ bz->total_bpages++;
+ bz->free_bpages++;
+ mtx_unlock(&bounce_lock);
+ count++;
+ numpages--;
+ }
+ return (count);
+}
+
+static int
+reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit)
+{
+ struct bounce_zone *bz;
+ int pages;
+
+ mtx_assert(&bounce_lock, MA_OWNED);
+ bz = dmat->bounce_zone;
+ pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved);
+ if (commit == 0 && map->pagesneeded > (map->pagesreserved + pages))
+ return (map->pagesneeded - (map->pagesreserved + pages));
+ bz->free_bpages -= pages;
+ bz->reserved_bpages += pages;
+ map->pagesreserved += pages;
+ pages = map->pagesneeded - map->pagesreserved;
+
+ return (pages);
+}
+
+static bus_addr_t
+add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
+ bus_addr_t addr, bus_size_t size)
+{
+ struct bounce_zone *bz;
+ struct bounce_page *bpage;
+
+ KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
+ KASSERT(map != NULL,
+ ("add_bounce_page: bad map %p", map));
+
+ bz = dmat->bounce_zone;
+ if (map->pagesneeded == 0)
+ panic("add_bounce_page: map doesn't need any pages");
+ map->pagesneeded--;
+
+ if (map->pagesreserved == 0)
+ panic("add_bounce_page: map doesn't need any pages");
+ map->pagesreserved--;
+
+ mtx_lock(&bounce_lock);
+ bpage = STAILQ_FIRST(&bz->bounce_page_list);
+ if (bpage == NULL)
+ panic("add_bounce_page: free page list is empty");
+
+ STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links);
+ bz->reserved_bpages--;
+ bz->active_bpages++;
+ mtx_unlock(&bounce_lock);
+
+ if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
+ /* Page offset needs to be preserved. */
+ bpage->vaddr |= addr & PAGE_MASK;
+ bpage->busaddr |= addr & PAGE_MASK;
+ }
+ bpage->datavaddr = vaddr;
+ bpage->dataaddr = addr;
+ bpage->datacount = size;
+ STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);
+ return (bpage->busaddr);
+}
+
+static void
+free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
+{
+ struct bus_dmamap *map;
+ struct bounce_zone *bz;
+
+ bz = dmat->bounce_zone;
+ bpage->datavaddr = 0;
+ bpage->datacount = 0;
+ if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
+ /*
+ * Reset the bounce page to start at offset 0. Other uses
+ * of this bounce page may need to store a full page of
+ * data and/or assume it starts on a page boundary.
+ */
+ bpage->vaddr &= ~PAGE_MASK;
+ bpage->busaddr &= ~PAGE_MASK;
+ }
+
+ mtx_lock(&bounce_lock);
+ STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
+ bz->free_bpages++;
+ bz->active_bpages--;
+ if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) {
+ if (reserve_bounce_pages(map->dmat, map, 1) == 0) {
+ STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
+ STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
+ map, links);
+ busdma_swi_pending = 1;
+ bz->total_deferred++;
+ swi_sched(vm_ih, 0);
+ }
+ }
+ mtx_unlock(&bounce_lock);
+}
+
+void
+busdma_swi(void)
+{
+ bus_dma_tag_t dmat;
+ struct bus_dmamap *map;
+
+ mtx_lock(&bounce_lock);
+ while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
+ STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
+ mtx_unlock(&bounce_lock);
+ dmat = map->dmat;
+ dmat->lockfunc(dmat->lockfuncarg, BUS_DMA_LOCK);
+ bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback,
+ map->callback_arg, BUS_DMA_WAITOK);
+ dmat->lockfunc(dmat->lockfuncarg, BUS_DMA_UNLOCK);
+ mtx_lock(&bounce_lock);
+ }
+ mtx_unlock(&bounce_lock);
+}
Property changes on: trunk/sys/arm/arm/busdma_machdep-v6.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/busdma_machdep.c
===================================================================
--- trunk/sys/arm/arm/busdma_machdep.c (rev 0)
+++ trunk/sys/arm/arm/busdma_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1510 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Ian Lepore
+ * Copyright (c) 2004 Olivier Houchard
+ * Copyright (c) 2002 Peter Grehan
+ * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From i386/busdma_machdep.c,v 1.26 2002/04/19 22:58:09 alfred
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/busdma_machdep.c 318977 2017-05-27 08:17:59Z hselasky $");
+
+/*
+ * ARM bus dma support routines.
+ *
+ * XXX Things to investigate / fix some day...
+ * - What is the earliest that this API can be called? Could there be any
+ * fallout from changing the SYSINIT() order from SI_SUB_VM to SI_SUB_KMEM?
+ * - The manpage mentions the BUS_DMA_NOWAIT flag only in the context of the
+ * bus_dmamap_load() function. This code has historically (and still does)
+ * honor it in bus_dmamem_alloc(). If we got rid of that we could lose some
+ * error checking because some resource management calls would become WAITOK
+ * and thus "cannot fail."
+ * - The decisions made by _bus_dma_can_bounce() should be made once, at tag
+ * creation time, and the result stored in the tag.
+ * - It should be possible to take some shortcuts when mapping a buffer we know
+ * came from the uma(9) allocators based on what we know about such buffers
+ * (aligned, contiguous, etc).
+ * - The allocation of bounce pages could probably be cleaned up, then we could
+ * retire arm_remap_nocache().
+ */
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/busdma_bufalloc.h>
+#include <sys/interrupt.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/memdesc.h>
+#include <sys/mutex.h>
+#include <sys/ktr.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+
+#include <vm/uma.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+
+#include <machine/atomic.h>
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+
+#define MAX_BPAGES 64
+#define BUS_DMA_COULD_BOUNCE BUS_DMA_BUS3
+#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4
+
+struct bounce_zone;
+
+struct bus_dma_tag {
+ bus_dma_tag_t parent;
+ bus_size_t alignment;
+ bus_addr_t boundary;
+ bus_addr_t lowaddr;
+ bus_addr_t highaddr;
+ bus_dma_filter_t *filter;
+ void *filterarg;
+ bus_size_t maxsize;
+ u_int nsegments;
+ bus_size_t maxsegsz;
+ int flags;
+ int ref_count;
+ int map_count;
+ bus_dma_lock_t *lockfunc;
+ void *lockfuncarg;
+ /*
+ * DMA range for this tag. If the page doesn't fall within
+ * one of these ranges, an error is returned. The caller
+ * may then decide what to do with the transfer. If the
+ * range pointer is NULL, it is ignored.
+ */
+ struct arm32_dma_range *ranges;
+ int _nranges;
+ struct bounce_zone *bounce_zone;
+ /*
+ * Most tags need one or two segments, and can use the local tagsegs
+ * array. For tags with a larger limit, we'll allocate a bigger array
+ * on first use.
+ */
+ bus_dma_segment_t *segments;
+ bus_dma_segment_t tagsegs[2];
+};
+
+struct bounce_page {
+ vm_offset_t vaddr; /* kva of bounce buffer */
+ bus_addr_t busaddr; /* Physical address */
+ vm_offset_t datavaddr; /* kva of client data */
+ bus_addr_t dataaddr; /* client physical address */
+ bus_size_t datacount; /* client data count */
+ STAILQ_ENTRY(bounce_page) links;
+};
+
+struct sync_list {
+ vm_offset_t vaddr; /* kva of bounce buffer */
+ bus_addr_t busaddr; /* Physical address */
+ bus_size_t datacount; /* client data count */
+};
+
+int busdma_swi_pending;
+
+struct bounce_zone {
+ STAILQ_ENTRY(bounce_zone) links;
+ STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
+ int total_bpages;
+ int free_bpages;
+ int reserved_bpages;
+ int active_bpages;
+ int total_bounced;
+ int total_deferred;
+ int map_count;
+ bus_size_t alignment;
+ bus_addr_t lowaddr;
+ char zoneid[8];
+ char lowaddrid[20];
+ struct sysctl_ctx_list sysctl_tree;
+ struct sysctl_oid *sysctl_tree_top;
+};
+
+static struct mtx bounce_lock;
+static int total_bpages;
+static int busdma_zonecount;
+static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+
+static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters");
+SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0,
+ "Total bounce pages");
+
+#define DMAMAP_COHERENT 0x8
+#define DMAMAP_CACHE_ALIGNED 0x10
+
+struct bus_dmamap {
+ struct bp_list bpages;
+ int pagesneeded;
+ int pagesreserved;
+ bus_dma_tag_t dmat;
+ struct memdesc mem;
+ int flags;
+ STAILQ_ENTRY(bus_dmamap) links;
+ bus_dmamap_callback_t *callback;
+ void *callback_arg;
+ int sync_count;
+ struct sync_list *slist;
+};
+
+static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
+static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
+
+static struct mtx busdma_mtx;
+
+MTX_SYSINIT(busdma_mtx, &busdma_mtx, "busdma lock", MTX_DEF);
+
+static void init_bounce_pages(void *dummy);
+static int alloc_bounce_zone(bus_dma_tag_t dmat);
+static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages);
+static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
+ int commit);
+static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
+ vm_offset_t vaddr, bus_addr_t addr,
+ bus_size_t size);
+static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
+
+/* Default tag, as most drivers provide no parent tag. */
+bus_dma_tag_t arm_root_dma_tag;
+
+/*
+ * ----------------------------------------------------------------------------
+ * Begin block of code useful to transplant to other implementations.
+ */
+
+static uma_zone_t dmamap_zone; /* Cache of struct bus_dmamap items */
+
+static busdma_bufalloc_t coherent_allocator; /* Cache of coherent buffers */
+static busdma_bufalloc_t standard_allocator; /* Cache of standard buffers */
+
+/*
+ * This is the ctor function passed to uma_zcreate() for the pool of dma maps.
+ * It'll need platform-specific changes if this code is copied.
+ */
+static int
+dmamap_ctor(void *mem, int size, void *arg, int flags)
+{
+ bus_dmamap_t map;
+ bus_dma_tag_t dmat;
+
+ map = (bus_dmamap_t)mem;
+ dmat = (bus_dma_tag_t)arg;
+
+ dmat->map_count++;
+
+ map->dmat = dmat;
+ map->flags = 0;
+ STAILQ_INIT(&map->bpages);
+
+ return (0);
+}
+
+/*
+ * This is the dtor function passed to uma_zcreate() for the pool of dma maps.
+ * It may need platform-specific changes if this code is copied .
+ */
+static void
+dmamap_dtor(void *mem, int size, void *arg)
+{
+ bus_dmamap_t map;
+
+ map = (bus_dmamap_t)mem;
+
+ map->dmat->map_count--;
+}
+
+static void
+busdma_init(void *dummy)
+{
+
+ /* Create a cache of maps for bus_dmamap_create(). */
+ dmamap_zone = uma_zcreate("dma maps", sizeof(struct bus_dmamap),
+ dmamap_ctor, dmamap_dtor, NULL, NULL, UMA_ALIGN_PTR, 0);
+
+ /* Create a cache of buffers in standard (cacheable) memory. */
+ standard_allocator = busdma_bufalloc_create("buffer",
+ arm_dcache_align, /* minimum_alignment */
+ NULL, /* uma_alloc func */
+ NULL, /* uma_free func */
+ 0); /* uma_zcreate_flags */
+
+ /*
+ * Create a cache of buffers in uncacheable memory, to implement the
+ * BUS_DMA_COHERENT (and potentially BUS_DMA_NOCACHE) flag.
+ */
+ coherent_allocator = busdma_bufalloc_create("coherent",
+ arm_dcache_align, /* minimum_alignment */
+ busdma_bufalloc_alloc_uncacheable,
+ busdma_bufalloc_free_uncacheable,
+ 0); /* uma_zcreate_flags */
+}
+
+/*
+ * This init historically used SI_SUB_VM, but now the init code requires
+ * malloc(9) using M_DEVBUF memory, which is set up later than SI_SUB_VM, by
+ * SI_SUB_KMEM and SI_ORDER_SECOND, so we'll go right after that by using
+ * SI_SUB_KMEM and SI_ORDER_THIRD.
+ */
+SYSINIT(busdma, SI_SUB_KMEM, SI_ORDER_THIRD, busdma_init, NULL);
+
+/*
+ * End block of code useful to transplant to other implementations.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Return true if a match is made.
+ *
+ * To find a match walk the chain of bus_dma_tag_t's looking for 'paddr'.
+ *
+ * If paddr is within the bounds of the dma tag then call the filter callback
+ * to check for a match, if there is no filter callback then assume a match.
+ */
+static int
+run_filter(bus_dma_tag_t dmat, bus_addr_t paddr)
+{
+ int retval;
+
+ retval = 0;
+
+ do {
+ if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr)
+ || ((paddr & (dmat->alignment - 1)) != 0))
+ && (dmat->filter == NULL
+ || (*dmat->filter)(dmat->filterarg, paddr) != 0))
+ retval = 1;
+
+ dmat = dmat->parent;
+ } while (retval == 0 && dmat != NULL);
+ return (retval);
+}
+
+/*
+ * This routine checks the exclusion zone constraints from a tag against the
+ * physical RAM available on the machine. If a tag specifies an exclusion zone
+ * but there's no RAM in that zone, then we avoid allocating resources to bounce
+ * a request, and we can use any memory allocator (as opposed to needing
+ * kmem_alloc_contig() just because it can allocate pages in an address range).
+ *
+ * Most tags have BUS_SPACE_MAXADDR or BUS_SPACE_MAXADDR_32BIT (they are the
+ * same value on 32-bit architectures) as their lowaddr constraint, and we can't
+ * possibly have RAM at an address higher than the highest address we can
+ * express, so we take a fast out.
+ */
+static __inline int
+_bus_dma_can_bounce(vm_offset_t lowaddr, vm_offset_t highaddr)
+{
+ int i;
+
+ if (lowaddr >= BUS_SPACE_MAXADDR)
+ return (0);
+
+ for (i = 0; phys_avail[i] && phys_avail[i + 1]; i += 2) {
+ if ((lowaddr >= phys_avail[i] && lowaddr <= phys_avail[i + 1])
+ || (lowaddr < phys_avail[i] &&
+ highaddr > phys_avail[i]))
+ return (1);
+ }
+ return (0);
+}
+
+static __inline struct arm32_dma_range *
+_bus_dma_inrange(struct arm32_dma_range *ranges, int nranges,
+ bus_addr_t curaddr)
+{
+ struct arm32_dma_range *dr;
+ int i;
+
+ for (i = 0, dr = ranges; i < nranges; i++, dr++) {
+ if (curaddr >= dr->dr_sysbase &&
+ round_page(curaddr) <= (dr->dr_sysbase + dr->dr_len))
+ return (dr);
+ }
+
+ return (NULL);
+}
+/*
+ * Convenience function for manipulating driver locks from busdma (during
+ * busdma_swi, for example). Drivers that don't provide their own locks
+ * should specify &Giant to dmat->lockfuncarg. Drivers that use their own
+ * non-mutex locking scheme don't have to use this at all.
+ */
+void
+busdma_lock_mutex(void *arg, bus_dma_lock_op_t op)
+{
+ struct mtx *dmtx;
+
+ dmtx = (struct mtx *)arg;
+ switch (op) {
+ case BUS_DMA_LOCK:
+ mtx_lock(dmtx);
+ break;
+ case BUS_DMA_UNLOCK:
+ mtx_unlock(dmtx);
+ break;
+ default:
+ panic("Unknown operation 0x%x for busdma_lock_mutex!", op);
+ }
+}
+
+/*
+ * dflt_lock should never get called. It gets put into the dma tag when
+ * lockfunc == NULL, which is only valid if the maps that are associated
+ * with the tag are meant to never be defered.
+ * XXX Should have a way to identify which driver is responsible here.
+ */
+static void
+dflt_lock(void *arg, bus_dma_lock_op_t op)
+{
+#ifdef INVARIANTS
+ panic("driver error: busdma dflt_lock called");
+#else
+ printf("DRIVER_ERROR: busdma dflt_lock called\n");
+#endif
+}
+
+/*
+ * Allocate a device specific dma_tag.
+ */
+#define SEG_NB 1024
+
+int
+bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
+ bus_addr_t boundary, bus_addr_t lowaddr,
+ bus_addr_t highaddr, bus_dma_filter_t *filter,
+ void *filterarg, bus_size_t maxsize, int nsegments,
+ bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
+ void *lockfuncarg, bus_dma_tag_t *dmat)
+{
+ bus_dma_tag_t newtag;
+ int error = 0;
+ /* Return a NULL tag on failure */
+ *dmat = NULL;
+ if (!parent)
+ parent = arm_root_dma_tag;
+
+ newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT);
+ if (newtag == NULL) {
+ CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
+ __func__, newtag, 0, error);
+ return (ENOMEM);
+ }
+
+ newtag->parent = parent;
+ newtag->alignment = alignment ? alignment : 1;
+ newtag->boundary = boundary;
+ newtag->lowaddr = trunc_page((vm_offset_t)lowaddr) + (PAGE_SIZE - 1);
+ newtag->highaddr = trunc_page((vm_offset_t)highaddr) + (PAGE_SIZE - 1);
+ newtag->filter = filter;
+ newtag->filterarg = filterarg;
+ newtag->maxsize = maxsize;
+ newtag->nsegments = nsegments;
+ newtag->maxsegsz = maxsegsz;
+ newtag->flags = flags;
+ newtag->ref_count = 1; /* Count ourself */
+ newtag->map_count = 0;
+ newtag->ranges = bus_dma_get_range();
+ newtag->_nranges = bus_dma_get_range_nb();
+ if (lockfunc != NULL) {
+ newtag->lockfunc = lockfunc;
+ newtag->lockfuncarg = lockfuncarg;
+ } else {
+ newtag->lockfunc = dflt_lock;
+ newtag->lockfuncarg = NULL;
+ }
+ /*
+ * If all the segments we need fit into the local tagsegs array, set the
+ * pointer now. Otherwise NULL the pointer and an array of segments
+ * will be allocated later, on first use. We don't pre-allocate now
+ * because some tags exist just to pass contraints to children in the
+ * device hierarchy, and they tend to use BUS_SPACE_UNRESTRICTED and we
+ * sure don't want to try to allocate an array for that.
+ */
+ if (newtag->nsegments <= nitems(newtag->tagsegs))
+ newtag->segments = newtag->tagsegs;
+ else
+ newtag->segments = NULL;
+ /*
+ * Take into account any restrictions imposed by our parent tag
+ */
+ if (parent != NULL) {
+ newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr);
+ newtag->highaddr = MAX(parent->highaddr, newtag->highaddr);
+ if (newtag->boundary == 0)
+ newtag->boundary = parent->boundary;
+ else if (parent->boundary != 0)
+ newtag->boundary = MIN(parent->boundary,
+ newtag->boundary);
+ if ((newtag->filter != NULL) ||
+ ((parent->flags & BUS_DMA_COULD_BOUNCE) != 0))
+ newtag->flags |= BUS_DMA_COULD_BOUNCE;
+ if (newtag->filter == NULL) {
+ /*
+ * Short circuit looking at our parent directly
+ * since we have encapsulated all of its information
+ */
+ newtag->filter = parent->filter;
+ newtag->filterarg = parent->filterarg;
+ newtag->parent = parent->parent;
+ }
+ if (newtag->parent != NULL)
+ atomic_add_int(&parent->ref_count, 1);
+ }
+ if (_bus_dma_can_bounce(newtag->lowaddr, newtag->highaddr)
+ || newtag->alignment > 1)
+ newtag->flags |= BUS_DMA_COULD_BOUNCE;
+
+ if (((newtag->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
+ (flags & BUS_DMA_ALLOCNOW) != 0) {
+ struct bounce_zone *bz;
+
+ /* Must bounce */
+
+ if ((error = alloc_bounce_zone(newtag)) != 0) {
+ free(newtag, M_DEVBUF);
+ return (error);
+ }
+ bz = newtag->bounce_zone;
+
+ if (ptoa(bz->total_bpages) < maxsize) {
+ int pages;
+
+ pages = atop(maxsize) - bz->total_bpages;
+
+ /* Add pages to our bounce pool */
+ if (alloc_bounce_pages(newtag, pages) < pages)
+ error = ENOMEM;
+ }
+ /* Performed initial allocation */
+ newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ } else
+ newtag->bounce_zone = NULL;
+ if (error != 0)
+ free(newtag, M_DEVBUF);
+ else
+ *dmat = newtag;
+ CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
+ __func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
+
+ return (error);
+}
+
+int
+bus_dma_tag_destroy(bus_dma_tag_t dmat)
+{
+#ifdef KTR
+ bus_dma_tag_t dmat_copy = dmat;
+#endif
+
+ if (dmat != NULL) {
+
+ if (dmat->map_count != 0)
+ return (EBUSY);
+
+ while (dmat != NULL) {
+ bus_dma_tag_t parent;
+
+ parent = dmat->parent;
+ atomic_subtract_int(&dmat->ref_count, 1);
+ if (dmat->ref_count == 0) {
+ if (dmat->segments != NULL &&
+ dmat->segments != dmat->tagsegs)
+ free(dmat->segments, M_DEVBUF);
+ free(dmat, M_DEVBUF);
+ /*
+ * Last reference count, so
+ * release our reference
+ * count on our parent.
+ */
+ dmat = parent;
+ } else
+ dmat = NULL;
+ }
+ }
+ CTR2(KTR_BUSDMA, "%s tag %p", __func__, dmat_copy);
+
+ return (0);
+}
+
+#include <sys/kdb.h>
+/*
+ * Allocate a handle for mapping from kva/uva/physical
+ * address space into bus device space.
+ */
+int
+bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
+{
+ struct sync_list *slist;
+ bus_dmamap_t map;
+ int error = 0;
+
+ slist = malloc(sizeof(*slist) * dmat->nsegments, M_DEVBUF, M_NOWAIT);
+ if (slist == NULL)
+ return (ENOMEM);
+
+ map = uma_zalloc_arg(dmamap_zone, dmat, M_NOWAIT);
+ *mapp = map;
+ if (map == NULL) {
+ free(slist, M_DEVBUF);
+ return (ENOMEM);
+ }
+
+ /*
+ * If the tag's segments haven't been allocated yet we need to do it
+ * now, because we can't sleep for resources at map load time.
+ */
+ if (dmat->segments == NULL) {
+ dmat->segments = malloc(dmat->nsegments *
+ sizeof(*dmat->segments), M_DEVBUF, M_NOWAIT);
+ if (dmat->segments == NULL) {
+ free(slist, M_DEVBUF);
+ uma_zfree(dmamap_zone, map);
+ *mapp = NULL;
+ return (ENOMEM);
+ }
+ }
+
+ /*
+ * Bouncing might be required if the driver asks for an active
+ * exclusion region, a data alignment that is stricter than 1, and/or
+ * an active address boundary.
+ */
+ if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
+
+ /* Must bounce */
+ struct bounce_zone *bz;
+ int maxpages;
+
+ if (dmat->bounce_zone == NULL) {
+ if ((error = alloc_bounce_zone(dmat)) != 0) {
+ free(slist, M_DEVBUF);
+ uma_zfree(dmamap_zone, map);
+ *mapp = NULL;
+ return (error);
+ }
+ }
+ bz = dmat->bounce_zone;
+
+ /* Initialize the new map */
+ STAILQ_INIT(&((*mapp)->bpages));
+
+ /*
+ * Attempt to add pages to our pool on a per-instance
+ * basis up to a sane limit.
+ */
+ maxpages = MAX_BPAGES;
+ if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
+ || (bz->map_count > 0 && bz->total_bpages < maxpages)) {
+ int pages;
+
+ pages = MAX(atop(dmat->maxsize), 1);
+ pages = MIN(maxpages - bz->total_bpages, pages);
+ pages = MAX(pages, 1);
+ if (alloc_bounce_pages(dmat, pages) < pages)
+ error = ENOMEM;
+
+ if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
+ if (error == 0)
+ dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ } else {
+ error = 0;
+ }
+ }
+ bz->map_count++;
+ }
+ map->sync_count = 0;
+ map->slist = slist;
+ CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+ __func__, dmat, dmat->flags, error);
+
+ return (0);
+}
+
+/*
+ * Destroy a handle for mapping from kva/uva/physical
+ * address space into bus device space.
+ */
+int
+bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+
+ if (STAILQ_FIRST(&map->bpages) != NULL || map->sync_count != 0) {
+ CTR3(KTR_BUSDMA, "%s: tag %p error %d",
+ __func__, dmat, EBUSY);
+ return (EBUSY);
+ }
+ free(map->slist, M_DEVBUF);
+ uma_zfree(dmamap_zone, map);
+ if (dmat->bounce_zone)
+ dmat->bounce_zone->map_count--;
+ CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
+ return (0);
+}
+
+/*
+ * Allocate a piece of memory that can be efficiently mapped into bus device
+ * space based on the constraints listed in the dma tag. Returns a pointer to
+ * the allocated memory, and a pointer to an associated bus_dmamap.
+ */
+int
+bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddrp, int flags,
+ bus_dmamap_t *mapp)
+{
+ struct sync_list *slist;
+ void * vaddr;
+ struct busdma_bufzone *bufzone;
+ busdma_bufalloc_t ba;
+ bus_dmamap_t map;
+ int mflags;
+ vm_memattr_t memattr;
+
+ if (flags & BUS_DMA_NOWAIT)
+ mflags = M_NOWAIT;
+ else
+ mflags = M_WAITOK;
+ /*
+ * If the tag's segments haven't been allocated yet we need to do it
+ * now, because we can't sleep for resources at map load time.
+ */
+ if (dmat->segments == NULL)
+ dmat->segments = malloc(dmat->nsegments *
+ sizeof(*dmat->segments), M_DEVBUF, mflags);
+
+ slist = malloc(sizeof(*slist) * dmat->nsegments, M_DEVBUF, M_NOWAIT);
+ if (slist == NULL)
+ return (ENOMEM);
+ map = uma_zalloc_arg(dmamap_zone, dmat, mflags);
+ if (map == NULL) {
+ free(slist, M_DEVBUF);
+ return (ENOMEM);
+ }
+ if (flags & BUS_DMA_COHERENT) {
+ memattr = VM_MEMATTR_UNCACHEABLE;
+ ba = coherent_allocator;
+ map->flags |= DMAMAP_COHERENT;
+ } else {
+ memattr = VM_MEMATTR_DEFAULT;
+ ba = standard_allocator;
+ }
+ /* All buffers we allocate are cache-aligned. */
+ map->flags |= DMAMAP_CACHE_ALIGNED;
+
+ if (flags & BUS_DMA_ZERO)
+ mflags |= M_ZERO;
+
+ /*
+ * Try to find a bufzone in the allocator that holds a cache of buffers
+ * of the right size for this request. If the buffer is too big to be
+ * held in the allocator cache, this returns NULL.
+ */
+ bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
+
+ /*
+ * Allocate the buffer from the uma(9) allocator if...
+ * - It's small enough to be in the allocator (bufzone not NULL).
+ * - The alignment constraint isn't larger than the allocation size
+ * (the allocator aligns buffers to their size boundaries).
+ * - There's no need to handle lowaddr/highaddr exclusion zones.
+ * else allocate non-contiguous pages if...
+ * - The page count that could get allocated doesn't exceed nsegments.
+ * - The alignment constraint isn't larger than a page boundary.
+ * - There are no boundary-crossing constraints.
+ * else allocate a block of contiguous pages because one or more of the
+ * constraints is something that only the contig allocator can fulfill.
+ */
+ if (bufzone != NULL && dmat->alignment <= bufzone->size &&
+ !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr)) {
+ vaddr = uma_zalloc(bufzone->umazone, mflags);
+ } else if (dmat->nsegments >=
+ howmany(dmat->maxsize, MIN(dmat->maxsegsz, PAGE_SIZE)) &&
+ dmat->alignment <= PAGE_SIZE &&
+ (dmat->boundary % PAGE_SIZE) == 0) {
+ vaddr = (void *)kmem_alloc_attr(kernel_arena, dmat->maxsize,
+ mflags, 0, dmat->lowaddr, memattr);
+ } else {
+ vaddr = (void *)kmem_alloc_contig(kernel_arena, dmat->maxsize,
+ mflags, 0, dmat->lowaddr, dmat->alignment, dmat->boundary,
+ memattr);
+ }
+ if (vaddr == NULL) {
+ free(slist, M_DEVBUF);
+ uma_zfree(dmamap_zone, map);
+ map = NULL;
+ } else {
+ map->slist = slist;
+ map->sync_count = 0;
+ }
+ *vaddrp = vaddr;
+ *mapp = map;
+
+ return (vaddr == NULL ? ENOMEM : 0);
+}
+
+/*
+ * Free a piece of memory that was allocated via bus_dmamem_alloc, along with
+ * its associated map.
+ */
+void
+bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
+{
+ struct busdma_bufzone *bufzone;
+ busdma_bufalloc_t ba;
+
+ if (map->flags & DMAMAP_COHERENT)
+ ba = coherent_allocator;
+ else
+ ba = standard_allocator;
+
+ free(map->slist, M_DEVBUF);
+ uma_zfree(dmamap_zone, map);
+
+ bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
+
+ if (bufzone != NULL && dmat->alignment <= bufzone->size &&
+ !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr))
+ uma_zfree(bufzone->umazone, vaddr);
+ else
+ kmem_free(kernel_arena, (vm_offset_t)vaddr, dmat->maxsize);
+}
+
+static void
+_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
+ bus_size_t buflen, int flags)
+{
+ bus_addr_t curaddr;
+ bus_size_t sgsize;
+
+ if (map->pagesneeded == 0) {
+ CTR3(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d",
+ dmat->lowaddr, dmat->boundary, dmat->alignment);
+ CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d",
+ map, map->pagesneeded);
+ /*
+ * Count the number of bounce pages
+ * needed in order to complete this transfer
+ */
+ curaddr = buf;
+ while (buflen != 0) {
+ sgsize = MIN(buflen, dmat->maxsegsz);
+ if (run_filter(dmat, curaddr) != 0) {
+ sgsize = MIN(sgsize, PAGE_SIZE);
+ map->pagesneeded++;
+ }
+ curaddr += sgsize;
+ buflen -= sgsize;
+ }
+ CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
+ }
+}
+
+static void
+_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap,
+ void *buf, bus_size_t buflen, int flags)
+{
+ vm_offset_t vaddr;
+ vm_offset_t vendaddr;
+ bus_addr_t paddr;
+
+ if (map->pagesneeded == 0) {
+ CTR3(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d",
+ dmat->lowaddr, dmat->boundary, dmat->alignment);
+ CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d",
+ map, map->pagesneeded);
+ /*
+ * Count the number of bounce pages
+ * needed in order to complete this transfer
+ */
+ vaddr = trunc_page((vm_offset_t)buf);
+ vendaddr = (vm_offset_t)buf + buflen;
+
+ while (vaddr < vendaddr) {
+ if (__predict_true(pmap == kernel_pmap))
+ paddr = pmap_kextract(vaddr);
+ else
+ paddr = pmap_extract(pmap, vaddr);
+ if (run_filter(dmat, paddr) != 0)
+ map->pagesneeded++;
+ vaddr += PAGE_SIZE;
+ }
+ CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
+ }
+}
+
+static int
+_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
+{
+
+ /* Reserve Necessary Bounce Pages */
+ mtx_lock(&bounce_lock);
+ if (flags & BUS_DMA_NOWAIT) {
+ if (reserve_bounce_pages(dmat, map, 0) != 0) {
+ mtx_unlock(&bounce_lock);
+ return (ENOMEM);
+ }
+ } else {
+ if (reserve_bounce_pages(dmat, map, 1) != 0) {
+ /* Queue us for resources */
+ STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links);
+ mtx_unlock(&bounce_lock);
+ return (EINPROGRESS);
+ }
+ }
+ mtx_unlock(&bounce_lock);
+
+ return (0);
+}
+
+/*
+ * Add a single contiguous physical range to the segment list.
+ */
+static int
+_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr,
+ bus_size_t sgsize, bus_dma_segment_t *segs, int *segp)
+{
+ bus_addr_t baddr, bmask;
+ int seg;
+
+ /*
+ * Make sure we don't cross any boundaries.
+ */
+ bmask = ~(dmat->boundary - 1);
+ if (dmat->boundary > 0) {
+ baddr = (curaddr + dmat->boundary) & bmask;
+ if (sgsize > (baddr - curaddr))
+ sgsize = (baddr - curaddr);
+ }
+ if (dmat->ranges) {
+ struct arm32_dma_range *dr;
+
+ dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges,
+ curaddr);
+ if (dr == NULL)
+ return (0);
+ /*
+ * In a valid DMA range. Translate the physical
+ * memory address to an address in the DMA window.
+ */
+ curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase;
+
+ }
+
+ seg = *segp;
+ /*
+ * Insert chunk into a segment, coalescing with
+ * the previous segment if possible.
+ */
+ if (seg >= 0 &&
+ curaddr == segs[seg].ds_addr + segs[seg].ds_len &&
+ (segs[seg].ds_len + sgsize) <= dmat->maxsegsz &&
+ (dmat->boundary == 0 ||
+ (segs[seg].ds_addr & bmask) == (curaddr & bmask))) {
+ segs[seg].ds_len += sgsize;
+ } else {
+ if (++seg >= dmat->nsegments)
+ return (0);
+ segs[seg].ds_addr = curaddr;
+ segs[seg].ds_len = sgsize;
+ }
+ *segp = seg;
+ return (sgsize);
+}
+
+/*
+ * Utility function to load a physical buffer. segp contains
+ * the starting segment on entrace, and the ending segment on exit.
+ */
+int
+_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
+ bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp)
+{
+ bus_size_t sgsize;
+ bus_addr_t curaddr;
+ int error;
+
+ if (segs == NULL)
+ segs = dmat->segments;
+
+ if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
+ _bus_dmamap_count_phys(dmat, map, buf, buflen, flags);
+ if (map->pagesneeded != 0) {
+ error = _bus_dmamap_reserve_pages(dmat, map, flags);
+ if (error)
+ return (error);
+ }
+ }
+
+ while (buflen > 0) {
+ curaddr = buf;
+ sgsize = MIN(buflen, dmat->maxsegsz);
+ if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
+ map->pagesneeded != 0 && run_filter(dmat, curaddr)) {
+ sgsize = MIN(sgsize, PAGE_SIZE);
+ curaddr = add_bounce_page(dmat, map, 0, curaddr,
+ sgsize);
+ }
+ sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
+ segp);
+ if (sgsize == 0)
+ break;
+ buf += sgsize;
+ buflen -= sgsize;
+ }
+
+ /*
+ * Did we fit?
+ */
+ if (buflen != 0) {
+ _bus_dmamap_unload(dmat, map);
+ return (EFBIG); /* XXX better return value here? */
+ }
+ return (0);
+}
+
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+
+ return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+ segs, segp));
+}
+
+/*
+ * Utility function to load a linear buffer. segp contains
+ * the starting segment on entrance, and the ending segment on exit.
+ */
+int
+_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
+ bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs,
+ int *segp)
+{
+ bus_size_t sgsize;
+ bus_addr_t curaddr;
+ struct sync_list *sl;
+ vm_offset_t vaddr = (vm_offset_t)buf;
+ int error = 0;
+
+ if (segs == NULL)
+ segs = dmat->segments;
+ if ((flags & BUS_DMA_LOAD_MBUF) != 0)
+ map->flags |= DMAMAP_CACHE_ALIGNED;
+
+ if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
+ _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags);
+ if (map->pagesneeded != 0) {
+ error = _bus_dmamap_reserve_pages(dmat, map, flags);
+ if (error)
+ return (error);
+ }
+ }
+ CTR3(KTR_BUSDMA, "lowaddr= %d boundary= %d, "
+ "alignment= %d", dmat->lowaddr, dmat->boundary, dmat->alignment);
+
+ while (buflen > 0) {
+ /*
+ * Get the physical address for this segment.
+ */
+ if (__predict_true(pmap == kernel_pmap)) {
+ curaddr = pmap_kextract(vaddr);
+ } else {
+ curaddr = pmap_extract(pmap, vaddr);
+ map->flags &= ~DMAMAP_COHERENT;
+ }
+
+ /*
+ * Compute the segment size, and adjust counts.
+ */
+ sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK);
+ if (sgsize > dmat->maxsegsz)
+ sgsize = dmat->maxsegsz;
+ if (buflen < sgsize)
+ sgsize = buflen;
+
+ if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
+ map->pagesneeded != 0 && run_filter(dmat, curaddr)) {
+ curaddr = add_bounce_page(dmat, map, vaddr, curaddr,
+ sgsize);
+ } else {
+ sl = &map->slist[map->sync_count - 1];
+ if (map->sync_count == 0 ||
+ vaddr != sl->vaddr + sl->datacount) {
+ if (++map->sync_count > dmat->nsegments)
+ goto cleanup;
+ sl++;
+ sl->vaddr = vaddr;
+ sl->datacount = sgsize;
+ sl->busaddr = curaddr;
+ } else
+ sl->datacount += sgsize;
+ }
+ sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
+ segp);
+ if (sgsize == 0)
+ break;
+ vaddr += sgsize;
+ buflen -= sgsize;
+ }
+
+cleanup:
+ /*
+ * Did we fit?
+ */
+ if (buflen != 0) {
+ _bus_dmamap_unload(dmat, map);
+ return (EFBIG); /* XXX better return value here? */
+ }
+ return (0);
+}
+
+void
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct memdesc *mem, bus_dmamap_callback_t *callback,
+ void *callback_arg)
+{
+
+ KASSERT(dmat != NULL, ("dmatag is NULL"));
+ KASSERT(map != NULL, ("dmamap is NULL"));
+ map->mem = *mem;
+ map->callback = callback;
+ map->callback_arg = callback_arg;
+}
+
+bus_dma_segment_t *
+_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+ if (segs == NULL)
+ segs = dmat->segments;
+ return (segs);
+}
+
+/*
+ * Release the mapping held by map.
+ */
+void
+_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+ struct bounce_page *bpage;
+
+ while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
+ STAILQ_REMOVE_HEAD(&map->bpages, links);
+ free_bounce_page(dmat, bpage);
+ }
+ map->sync_count = 0;
+ return;
+}
+
+static void
+bus_dmamap_sync_buf(vm_offset_t buf, int len, bus_dmasync_op_t op,
+ int bufaligned)
+{
+ char _tmp_cl[arm_dcache_align], _tmp_clend[arm_dcache_align];
+ register_t s;
+ int partial;
+
+ if ((op & BUS_DMASYNC_PREWRITE) && !(op & BUS_DMASYNC_PREREAD)) {
+ cpu_dcache_wb_range(buf, len);
+ cpu_l2cache_wb_range(buf, len);
+ }
+
+ /*
+ * If the caller promises the buffer is properly aligned to a cache line
+ * (even if the call parms make it look like it isn't) we can avoid
+ * attempting to preserve the non-DMA part of the cache line in the
+ * POSTREAD case, but we MUST still do a writeback in the PREREAD case.
+ *
+ * This covers the case of mbufs, where we know how they're aligned and
+ * know the CPU doesn't touch the header in front of the DMA data area
+ * during the IO, but it may have touched it right before invoking the
+ * sync, so a PREREAD writeback is required.
+ *
+ * It also handles buffers we created in bus_dmamem_alloc(), which are
+ * always aligned and padded to cache line size even if the IO length
+ * isn't a multiple of cache line size. In this case the PREREAD
+ * writeback probably isn't required, but it's harmless.
+ */
+ partial = (((vm_offset_t)buf) | len) & arm_dcache_align_mask;
+
+ if (op & BUS_DMASYNC_PREREAD) {
+ if (!(op & BUS_DMASYNC_PREWRITE) && !partial) {
+ cpu_dcache_inv_range(buf, len);
+ cpu_l2cache_inv_range(buf, len);
+ } else {
+ cpu_dcache_wbinv_range(buf, len);
+ cpu_l2cache_wbinv_range(buf, len);
+ }
+ }
+ if (op & BUS_DMASYNC_POSTREAD) {
+ if (partial && !bufaligned) {
+ s = intr_disable();
+ if (buf & arm_dcache_align_mask)
+ memcpy(_tmp_cl, (void *)(buf &
+ ~arm_dcache_align_mask),
+ buf & arm_dcache_align_mask);
+ if ((buf + len) & arm_dcache_align_mask)
+ memcpy(_tmp_clend,
+ (void *)(buf + len),
+ arm_dcache_align -
+ ((buf + len) & arm_dcache_align_mask));
+ }
+ cpu_dcache_inv_range(buf, len);
+ cpu_l2cache_inv_range(buf, len);
+ if (partial && !bufaligned) {
+ if (buf & arm_dcache_align_mask)
+ memcpy((void *)(buf &
+ ~arm_dcache_align_mask), _tmp_cl,
+ buf & arm_dcache_align_mask);
+ if ((buf + len) & arm_dcache_align_mask)
+ memcpy((void *)(buf + len),
+ _tmp_clend, arm_dcache_align -
+ ((buf + len) & arm_dcache_align_mask));
+ intr_restore(s);
+ }
+ }
+}
+
+static void
+_bus_dmamap_sync_bp(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
+{
+ struct bounce_page *bpage;
+
+ STAILQ_FOREACH(bpage, &map->bpages, links) {
+ if (op & BUS_DMASYNC_PREWRITE) {
+ if (bpage->datavaddr != 0)
+ bcopy((void *)bpage->datavaddr,
+ (void *)bpage->vaddr, bpage->datacount);
+ else
+ physcopyout(bpage->dataaddr,
+ (void *)bpage->vaddr,bpage->datacount);
+ cpu_dcache_wb_range(bpage->vaddr, bpage->datacount);
+ cpu_l2cache_wb_range(bpage->vaddr, bpage->datacount);
+ dmat->bounce_zone->total_bounced++;
+ }
+ if (op & BUS_DMASYNC_POSTREAD) {
+ cpu_dcache_inv_range(bpage->vaddr, bpage->datacount);
+ cpu_l2cache_inv_range(bpage->vaddr, bpage->datacount);
+ if (bpage->datavaddr != 0)
+ bcopy((void *)bpage->vaddr,
+ (void *)bpage->datavaddr, bpage->datacount);
+ else
+ physcopyin((void *)bpage->vaddr,
+ bpage->dataaddr, bpage->datacount);
+ dmat->bounce_zone->total_bounced++;
+ }
+ }
+}
+
+void
+_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
+{
+ struct sync_list *sl, *end;
+ int bufaligned;
+
+ if (op == BUS_DMASYNC_POSTWRITE)
+ return;
+ if (map->flags & DMAMAP_COHERENT)
+ goto drain;
+ if (STAILQ_FIRST(&map->bpages))
+ _bus_dmamap_sync_bp(dmat, map, op);
+ CTR3(KTR_BUSDMA, "%s: op %x flags %x", __func__, op, map->flags);
+ bufaligned = (map->flags & DMAMAP_CACHE_ALIGNED);
+ if (map->sync_count) {
+ end = &map->slist[map->sync_count];
+ for (sl = &map->slist[0]; sl != end; sl++)
+ bus_dmamap_sync_buf(sl->vaddr, sl->datacount, op,
+ bufaligned);
+ }
+
+drain:
+
+ cpu_drain_writebuf();
+}
+
+static void
+init_bounce_pages(void *dummy __unused)
+{
+
+ total_bpages = 0;
+ STAILQ_INIT(&bounce_zone_list);
+ STAILQ_INIT(&bounce_map_waitinglist);
+ STAILQ_INIT(&bounce_map_callbacklist);
+ mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
+}
+SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
+
+static struct sysctl_ctx_list *
+busdma_sysctl_tree(struct bounce_zone *bz)
+{
+ return (&bz->sysctl_tree);
+}
+
+static struct sysctl_oid *
+busdma_sysctl_tree_top(struct bounce_zone *bz)
+{
+ return (bz->sysctl_tree_top);
+}
+
+static int
+alloc_bounce_zone(bus_dma_tag_t dmat)
+{
+ struct bounce_zone *bz;
+
+ /* Check to see if we already have a suitable zone */
+ STAILQ_FOREACH(bz, &bounce_zone_list, links) {
+ if ((dmat->alignment <= bz->alignment)
+ && (dmat->lowaddr >= bz->lowaddr)) {
+ dmat->bounce_zone = bz;
+ return (0);
+ }
+ }
+
+ if ((bz = (struct bounce_zone *)malloc(sizeof(*bz), M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL)
+ return (ENOMEM);
+
+ STAILQ_INIT(&bz->bounce_page_list);
+ bz->free_bpages = 0;
+ bz->reserved_bpages = 0;
+ bz->active_bpages = 0;
+ bz->lowaddr = dmat->lowaddr;
+ bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
+ bz->map_count = 0;
+ snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
+ busdma_zonecount++;
+ snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
+ STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links);
+ dmat->bounce_zone = bz;
+
+ sysctl_ctx_init(&bz->sysctl_tree);
+ bz->sysctl_tree_top = SYSCTL_ADD_NODE(&bz->sysctl_tree,
+ SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid,
+ CTLFLAG_RD, 0, "");
+ if (bz->sysctl_tree_top == NULL) {
+ sysctl_ctx_free(&bz->sysctl_tree);
+ return (0); /* XXX error code? */
+ }
+
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0,
+ "Total bounce pages");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0,
+ "Free bounce pages");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0,
+ "Reserved bounce pages");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0,
+ "Active bounce pages");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0,
+ "Total bounce requests");
+ SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0,
+ "Total bounce requests that were deferred");
+ SYSCTL_ADD_STRING(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, "");
+ SYSCTL_ADD_ULONG(busdma_sysctl_tree(bz),
+ SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+ "alignment", CTLFLAG_RD, &bz->alignment, "");
+
+ return (0);
+}
+
+static int
+alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
+{
+ struct bounce_zone *bz;
+ int count;
+
+ bz = dmat->bounce_zone;
+ count = 0;
+ while (numpages > 0) {
+ struct bounce_page *bpage;
+
+ bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+
+ if (bpage == NULL)
+ break;
+ bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
+ M_NOWAIT, 0ul,
+ bz->lowaddr,
+ PAGE_SIZE,
+ 0);
+ if (bpage->vaddr == 0) {
+ free(bpage, M_DEVBUF);
+ break;
+ }
+ bpage->busaddr = pmap_kextract(bpage->vaddr);
+ mtx_lock(&bounce_lock);
+ STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links);
+ total_bpages++;
+ bz->total_bpages++;
+ bz->free_bpages++;
+ mtx_unlock(&bounce_lock);
+ count++;
+ numpages--;
+ }
+ return (count);
+}
+
+static int
+reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit)
+{
+ struct bounce_zone *bz;
+ int pages;
+
+ mtx_assert(&bounce_lock, MA_OWNED);
+ bz = dmat->bounce_zone;
+ pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved);
+ if (commit == 0 && map->pagesneeded > (map->pagesreserved + pages))
+ return (map->pagesneeded - (map->pagesreserved + pages));
+ bz->free_bpages -= pages;
+ bz->reserved_bpages += pages;
+ map->pagesreserved += pages;
+ pages = map->pagesneeded - map->pagesreserved;
+
+ return (pages);
+}
+
+static bus_addr_t
+add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
+ bus_addr_t addr, bus_size_t size)
+{
+ struct bounce_zone *bz;
+ struct bounce_page *bpage;
+
+ KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
+ KASSERT(map != NULL, ("add_bounce_page: bad map %p", map));
+
+ bz = dmat->bounce_zone;
+ if (map->pagesneeded == 0)
+ panic("add_bounce_page: map doesn't need any pages");
+ map->pagesneeded--;
+
+ if (map->pagesreserved == 0)
+ panic("add_bounce_page: map doesn't need any pages");
+ map->pagesreserved--;
+
+ mtx_lock(&bounce_lock);
+ bpage = STAILQ_FIRST(&bz->bounce_page_list);
+ if (bpage == NULL)
+ panic("add_bounce_page: free page list is empty");
+
+ STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links);
+ bz->reserved_bpages--;
+ bz->active_bpages++;
+ mtx_unlock(&bounce_lock);
+
+ if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
+ /* Page offset needs to be preserved. */
+ bpage->vaddr |= addr & PAGE_MASK;
+ bpage->busaddr |= addr & PAGE_MASK;
+ }
+ bpage->datavaddr = vaddr;
+ bpage->dataaddr = addr;
+ bpage->datacount = size;
+ STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);
+ return (bpage->busaddr);
+}
+
+static void
+free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
+{
+ struct bus_dmamap *map;
+ struct bounce_zone *bz;
+
+ bz = dmat->bounce_zone;
+ bpage->datavaddr = 0;
+ bpage->datacount = 0;
+ if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
+ /*
+ * Reset the bounce page to start at offset 0. Other uses
+ * of this bounce page may need to store a full page of
+ * data and/or assume it starts on a page boundary.
+ */
+ bpage->vaddr &= ~PAGE_MASK;
+ bpage->busaddr &= ~PAGE_MASK;
+ }
+
+ mtx_lock(&bounce_lock);
+ STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
+ bz->free_bpages++;
+ bz->active_bpages--;
+ if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) {
+ if (reserve_bounce_pages(map->dmat, map, 1) == 0) {
+ STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
+ STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
+ map, links);
+ busdma_swi_pending = 1;
+ bz->total_deferred++;
+ swi_sched(vm_ih, 0);
+ }
+ }
+ mtx_unlock(&bounce_lock);
+}
+
+void
+busdma_swi(void)
+{
+ bus_dma_tag_t dmat;
+ struct bus_dmamap *map;
+
+ mtx_lock(&bounce_lock);
+ while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
+ STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
+ mtx_unlock(&bounce_lock);
+ dmat = map->dmat;
+ (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
+ bus_dmamap_load_mem(map->dmat, map, &map->mem,
+ map->callback, map->callback_arg, BUS_DMA_WAITOK);
+ (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
+ mtx_lock(&bounce_lock);
+ }
+ mtx_unlock(&bounce_lock);
+}
Property changes on: trunk/sys/arm/arm/busdma_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/copystr.S
===================================================================
--- trunk/sys/arm/arm/copystr.S (rev 0)
+++ trunk/sys/arm/arm/copystr.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,216 @@
+/* $MidnightBSD$ */
+/* $NetBSD: copystr.S,v 1.8 2002/10/13 14:54:48 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * copystr.S
+ *
+ * optimised and fault protected copystr functions
+ *
+ * Created : 16/05/95
+ */
+
+
+#include "assym.s"
+#include <machine/acle-compat.h>
+#include <machine/asm.h>
+#include <machine/armreg.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/copystr.S 294681 2016-01-24 19:58:58Z ian $");
+
+#include <sys/errno.h>
+
+ .text
+ .align 2
+
+#if __ARM_ARCH >= 6
+#define GET_PCB(tmp) \
+ mrc p15, 0, tmp, c13, c0, 4; \
+ add tmp, tmp, #(TD_PCB)
+#else
+.Lpcb:
+ .word _C_LABEL(__pcpu) + PC_CURPCB
+
+#define GET_PCB(tmp) \
+ ldr tmp, .Lpcb
+#endif
+
+/*
+ * r0 - from
+ * r1 - to
+ * r2 - maxlens
+ * r3 - lencopied
+ *
+ * Copy string from r0 to r1
+ */
+ENTRY(copystr)
+ stmfd sp!, {r4-r5} /* stack is 8 byte aligned */
+ teq r2, #0x00000000
+ mov r5, #0x00000000
+ moveq r0, #ENAMETOOLONG
+ beq 2f
+
+1: ldrb r4, [r0], #0x0001
+ add r5, r5, #0x00000001
+ teq r4, #0x00000000
+ strb r4, [r1], #0x0001
+ teqne r5, r2
+ bne 1b
+
+ teq r4, #0x00000000
+ moveq r0, #0x00000000
+ movne r0, #ENAMETOOLONG
+
+2: teq r3, #0x00000000
+ strne r5, [r3]
+
+ ldmfd sp!, {r4-r5} /* stack is 8 byte aligned */
+ RET
+END(copystr)
+
+#define SAVE_REGS stmfd sp!, {r4-r6}
+#define RESTORE_REGS ldmfd sp!, {r4-r6}
+
+/*
+ * r0 - user space address
+ * r1 - kernel space address
+ * r2 - maxlens
+ * r3 - lencopied
+ *
+ * Copy string from user space to kernel space
+ */
+ENTRY(copyinstr)
+ SAVE_REGS
+
+ teq r2, #0x00000000
+ mov r6, #0x00000000
+ moveq r0, #ENAMETOOLONG
+ beq 2f
+
+ GET_PCB(r4)
+ ldr r4, [r4]
+
+#ifdef DIAGNOSTIC
+ teq r4, #0x00000000
+ beq .Lcopystrpcbfault
+#endif
+
+ adr r5, .Lcopystrfault
+ str r5, [r4, #PCB_ONFAULT]
+
+1: ldrbt r5, [r0], #0x0001
+ add r6, r6, #0x00000001
+ teq r5, #0x00000000
+ strb r5, [r1], #0x0001
+ teqne r6, r2
+ bne 1b
+
+ mov r0, #0x00000000
+ str r0, [r4, #PCB_ONFAULT]
+
+ teq r5, #0x00000000
+ moveq r0, #0x00000000
+ movne r0, #ENAMETOOLONG
+
+2: teq r3, #0x00000000
+ strne r6, [r3]
+
+ RESTORE_REGS
+ RET
+END(copyinstr)
+
+/*
+ * r0 - kernel space address
+ * r1 - user space address
+ * r2 - maxlens
+ * r3 - lencopied
+ *
+ * Copy string from kernel space to user space
+ */
+ENTRY(copyoutstr)
+ SAVE_REGS
+
+ teq r2, #0x00000000
+ mov r6, #0x00000000
+ moveq r0, #ENAMETOOLONG
+ beq 2f
+
+ GET_PCB(r4)
+ ldr r4, [r4]
+
+#ifdef DIAGNOSTIC
+ teq r4, #0x00000000
+ beq .Lcopystrpcbfault
+#endif
+
+ adr r5, .Lcopystrfault
+ str r5, [r4, #PCB_ONFAULT]
+
+1: ldrb r5, [r0], #0x0001
+ add r6, r6, #0x00000001
+ teq r5, #0x00000000
+ strbt r5, [r1], #0x0001
+ teqne r6, r2
+ bne 1b
+
+ mov r0, #0x00000000
+ str r0, [r4, #PCB_ONFAULT]
+
+ teq r5, #0x00000000
+ moveq r0, #0x00000000
+ movne r0, #ENAMETOOLONG
+
+2: teq r3, #0x00000000
+ strne r6, [r3]
+
+ RESTORE_REGS
+ RET
+END(copyoutstr)
+
+/* A fault occurred during the copy */
+.Lcopystrfault:
+ mov r1, #0x00000000
+ str r1, [r4, #PCB_ONFAULT]
+ RESTORE_REGS
+ RET
+
+#ifdef DIAGNOSTIC
+.Lcopystrpcbfault:
+ mov r2, r1
+ mov r1, r0
+ adr r0, Lcopystrpcbfaulttext
+ bic sp, sp, #7 /* align stack to 8 bytes */
+ b _C_LABEL(panic)
+
+Lcopystrpcbfaulttext:
+ .asciz "No valid PCB during copyinoutstr() addr1=%08x addr2=%08x\n"
+ .align 2
+#endif
Property changes on: trunk/sys/arm/arm/copystr.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpu_asm-v6.S
===================================================================
--- trunk/sys/arm/arm/cpu_asm-v6.S (rev 0)
+++ trunk/sys/arm/arm/cpu_asm-v6.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,211 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Svatopluk Kraus <onwahe at gmail.com>
+ * Copyright 2014 Michal Meloun <meloun at miracle.cz>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/arm/cpu_asm-v6.S 278645 2015-02-13 00:12:21Z ian $
+ */
+
+#include <machine/acle-compat.h>
+#include <machine/asm.h>
+#include <machine/asmacros.h>
+#include <machine/armreg.h>
+#include <machine/sysreg.h>
+
+/*
+ * Define cache functions used by startup code, which counts on the fact that
+ * only r0-r3,r12 (ip) are modified and no stack space is used. These functions
+ * must be called with interrupts disabled. Moreover, these work only with
+ * caches integrated to CPU (accessible via CP15); systems with an external L2
+ * cache controller such as a PL310 need separate calls to that device driver
+ * to affect L2 caches. This is not a factor during early kernel startup, as
+ * any external L2 cache controller has not been enabled yet.
+ */
+
+/* Invalidate D cache to PoC. (aka all cache levels)*/
+ASENTRY_NP(dcache_inv_poc_all)
+#if __ARM_ARCH == 6
+ mcr CP15_DCIALL
+ DSB
+ bx lr
+#else
+ mrc CP15_CLIDR(r0)
+ ands r0, r0, #0x07000000
+ mov r0, r0, lsr #23 /* Get LoC 'naturally' aligned for */
+ beq 4f /* use in the CSSELR register below */
+
+1: sub r0, #2
+ mcr CP15_CSSELR(r0) /* set cache level */
+ isb
+ mrc CP15_CCSIDR(r0) /* read CCSIDR */
+
+ ubfx r2, r0, #13, #15 /* get num sets - 1 from CCSIDR */
+ ubfx r3, r0, #3, #10 /* get num ways - 1 from CCSIDR */
+ clz r1, r3 /* number of bits to MSB of way */
+ lsl r3, r3, r1 /* shift into position */
+ mov ip, #1
+ lsl ip, ip, r1 /* ip now contains the way decr */
+
+ ubfx r0, r0, #0, #3 /* get linesize from CCSIDR */
+ add r0, r0, #4 /* apply bias */
+ lsl r2, r2, r0 /* shift sets by log2(linesize) */
+ add r3, r3, r2 /* merge numsets - 1 with numways - 1 */
+ sub ip, ip, r2 /* subtract numsets - 1 from way decr */
+ mov r1, #1
+ lsl r1, r1, r0 /* r1 now contains the set decr */
+ mov r2, ip /* r2 now contains set way decr */
+
+ /* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */
+2: mcr CP15_DCISW(r3) /* invalidate line */
+ movs r0, r3 /* get current way/set */
+ beq 3f /* at 0 means we are done */
+ movs r0, r0, lsl #10 /* clear way bits leaving only set bits*/
+ subne r3, r3, r1 /* non-zero?, decrement set */
+ subeq r3, r3, r2 /* zero?, decrement way and restore set count */
+ b 2b
+
+3:
+ mrc CP15_CSSELR(r0) /* get cache level */
+ teq r0, #0
+ bne 1b
+
+4: dsb /* wait for stores to finish */
+ mov r0, #0
+ mcr CP15_CSSELR(r0)
+ isb
+ bx lr
+#endif /* __ARM_ARCH == 6 */
+END(dcache_inv_poc_all)
+
+/* Invalidate D cache to PoU. (aka L1 cache only)*/
+ASENTRY_NP(dcache_inv_pou_all)
+#if __ARM_ARCH == 6
+ mcr CP15_DCIALL
+ DSB
+ bx lr
+#else
+ mrc CP15_CLIDR(r0)
+ ands r0, r0, #0x38000000
+ mov r0, r0, lsr #26 /* Get LoUU (naturally aligned) */
+ beq 4f
+
+1: sub r0, #2
+ mcr CP15_CSSELR(r0) /* set cache level */
+ isb
+ mrc CP15_CCSIDR(r0) /* read CCSIDR */
+
+ ubfx r2, r0, #13, #15 /* get num sets - 1 from CCSIDR */
+ ubfx r3, r0, #3, #10 /* get num ways - 1 from CCSIDR */
+ clz r1, r3 /* number of bits to MSB of way */
+ lsl r3, r3, r1 /* shift into position */
+ mov ip, #1
+ lsl ip, ip, r1 /* ip now contains the way decr */
+
+ ubfx r0, r0, #0, #3 /* get linesize from CCSIDR */
+ add r0, r0, #4 /* apply bias */
+ lsl r2, r2, r0 /* shift sets by log2(linesize) */
+ add r3, r3, r2 /* merge numsets - 1 with numways - 1 */
+ sub ip, ip, r2 /* subtract numsets - 1 from way decr */
+ mov r1, #1
+ lsl r1, r1, r0 /* r1 now contains the set decr */
+ mov r2, ip /* r2 now contains set way decr */
+
+ /* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */
+2: mcr CP15_DCISW(r3) /* invalidate line */
+ movs r0, r3 /* get current way/set */
+ beq 3f /* at 0 means we are done */
+ movs r0, r0, lsl #10 /* clear way bits leaving only set bits*/
+ subne r3, r3, r1 /* non-zero?, decrement set */
+ subeq r3, r3, r2 /* zero?, decrement way and restore set count */
+ b 2b
+
+3:
+ mrc CP15_CSSELR(r0) /* get cache level */
+ teq r0, #0
+ bne 1b
+
+4: dsb /* wait for stores to finish */
+ mov r0, #0
+ mcr CP15_CSSELR(r0)
+ bx lr
+#endif
+END(dcache_inv_pou_all)
+
+/* Write back and Invalidate D cache to PoC. */
+ASENTRY_NP(dcache_wbinv_poc_all)
+#if __ARM_ARCH == 6
+ mcr CP15_DCCIALL
+ DSB
+ bx lr
+#else
+ mrc CP15_CLIDR(r0)
+ ands r0, r0, #0x07000000
+ beq 4f
+ mov r0, #0 /* Clean from inner to outer levels */
+
+1: mcr CP15_CSSELR(r0) /* set cache level */
+ isb
+ mrc CP15_CCSIDR(r0) /* read CCSIDR */
+
+ ubfx r2, r0, #13, #15 /* get num sets - 1 from CCSIDR */
+ ubfx r3, r0, #3, #10 /* get num ways - 1 from CCSIDR */
+ clz r1, r3 /* number of bits to MSB of way */
+ lsl r3, r3, r1 /* shift into position */
+ mov ip, #1
+ lsl ip, ip, r1 /* ip now contains the way decr */
+
+ ubfx r0, r0, #0, #3 /* get linesize from CCSIDR */
+ add r0, r0, #4 /* apply bias */
+ lsl r2, r2, r0 /* shift sets by log2(linesize) */
+ add r3, r3, r2 /* merge numsets - 1 with numways - 1 */
+ sub ip, ip, r2 /* subtract numsets - 1 from way decr */
+ mov r1, #1
+ lsl r1, r1, r0 /* r1 now contains the set decr */
+ mov r2, ip /* r2 now contains set way decr */
+
+ /* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */
+2: mcr CP15_DCCISW(r3) /* clean and invalidate line */
+ movs r0, r3 /* get current way/set */
+ beq 3f /* at 0 means we are done */
+ movs r0, r0, lsl #10 /* clear way bits leaving only set bits*/
+ subne r3, r3, r1 /* non-zero?, decrement set */
+ subeq r3, r3, r2 /* zero?, decrement way and restore set count */
+ b 2b
+
+3:
+ mrc CP15_CSSELR(r0) /* get cache level */
+ add r0, r0, #2 /* next level */
+ mrc CP15_CLIDR(r1)
+ ands r1, r1, #0x07000000
+ mov r1, r1, lsr #23 /* Get LoC (naturally aligned) */
+ cmp r1, r0
+ bne 1b
+
+4: dsb /* wait for stores to finish */
+ mov r0, #0
+ mcr CP15_CSSELR(r0)
+ bx lr
+#endif /* __ARM_ARCH == 6 */
+END(dcache_wbinv_poc_all)
Property changes on: trunk/sys/arm/arm/cpu_asm-v6.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc.c
===================================================================
--- trunk/sys/arm/arm/cpufunc.c (rev 0)
+++ trunk/sys/arm/arm/cpufunc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1796 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */
+
+/*-
+ * arm9 support code Copyright (C) 2001 ARM Ltd
+ * Copyright (c) 1997 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Causality Limited.
+ * 4. The name of Causality Limited may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpufuncs.c
+ *
+ * C functions for supporting CPU / MMU / TLB specific operations.
+ *
+ * Created : 30/01/97
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc.c 283335 2015-05-23 22:48:54Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/disassem.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/uma.h>
+
+#include <machine/cpuconf.h>
+#include <machine/cpufunc.h>
+#include <machine/bootconfig.h>
+
+#ifdef CPU_XSCALE_80200
+#include <arm/xscale/i80200/i80200reg.h>
+#include <arm/xscale/i80200/i80200var.h>
+#endif
+
+#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+#endif
+
+/*
+ * Some definitions in i81342reg.h clash with i80321reg.h.
+ * This only happens for the LINT kernel. As it happens,
+ * we don't need anything from i81342reg.h that we already
+ * got from somewhere else during a LINT compile.
+ */
+#if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT)
+#include <arm/xscale/i8134x/i81342reg.h>
+#endif
+
+#ifdef CPU_XSCALE_IXP425
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+#endif
+
+/* PRIMARY CACHE VARIABLES */
+int arm_picache_size;
+int arm_picache_line_size;
+int arm_picache_ways;
+
+int arm_pdcache_size; /* and unified */
+int arm_pdcache_line_size;
+int arm_pdcache_ways;
+
+int arm_pcache_type;
+int arm_pcache_unified;
+
+int arm_dcache_align;
+int arm_dcache_align_mask;
+
+u_int arm_cache_level;
+u_int arm_cache_type[14];
+u_int arm_cache_loc;
+
+/* 1 == use cpu_sleep(), 0 == don't */
+int cpu_do_powersave;
+int ctrl;
+
+#ifdef CPU_ARM9
+struct cpu_functions arm9_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ arm9_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /* TLB functions */
+
+ armv4_tlb_flushID, /* tlb_flushID */
+ arm9_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv4_tlb_flushI, /* tlb_flushI */
+ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
+ armv4_tlb_flushD, /* tlb_flushD */
+ armv4_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ arm9_icache_sync_all, /* icache_sync_all */
+ arm9_icache_sync_range, /* icache_sync_range */
+
+ arm9_dcache_wbinv_all, /* dcache_wbinv_all */
+ arm9_dcache_wbinv_range, /* dcache_wbinv_range */
+ arm9_dcache_inv_range, /* dcache_inv_range */
+ arm9_dcache_wb_range, /* dcache_wb_range */
+
+ armv4_idcache_inv_all, /* idcache_inv_all */
+ arm9_idcache_wbinv_all, /* idcache_wbinv_all */
+ arm9_idcache_wbinv_range, /* idcache_wbinv_range */
+ cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ cpufunc_nullop, /* flush_prefetchbuf */
+ armv4_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ (void *)cpufunc_nullop, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ arm9_context_switch, /* context_switch */
+
+ arm9_setup /* cpu setup */
+
+};
+#endif /* CPU_ARM9 */
+
+#if defined(CPU_ARM9E) || defined(CPU_ARM10)
+struct cpu_functions armv5_ec_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ armv5_ec_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /* TLB functions */
+
+ armv4_tlb_flushID, /* tlb_flushID */
+ arm10_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv4_tlb_flushI, /* tlb_flushI */
+ arm10_tlb_flushI_SE, /* tlb_flushI_SE */
+ armv4_tlb_flushD, /* tlb_flushD */
+ armv4_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ armv5_ec_icache_sync_all, /* icache_sync_all */
+ armv5_ec_icache_sync_range, /* icache_sync_range */
+
+ armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */
+ armv5_ec_dcache_wbinv_range, /* dcache_wbinv_range */
+ armv5_ec_dcache_inv_range, /* dcache_inv_range */
+ armv5_ec_dcache_wb_range, /* dcache_wb_range */
+
+ armv4_idcache_inv_all, /* idcache_inv_all */
+ armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */
+ armv5_ec_idcache_wbinv_range, /* idcache_wbinv_range */
+
+ cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ cpufunc_nullop, /* flush_prefetchbuf */
+ armv4_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ (void *)cpufunc_nullop, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ arm10_context_switch, /* context_switch */
+
+ arm10_setup /* cpu setup */
+
+};
+
+struct cpu_functions sheeva_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ sheeva_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /* TLB functions */
+
+ armv4_tlb_flushID, /* tlb_flushID */
+ arm10_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv4_tlb_flushI, /* tlb_flushI */
+ arm10_tlb_flushI_SE, /* tlb_flushI_SE */
+ armv4_tlb_flushD, /* tlb_flushD */
+ armv4_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ armv5_ec_icache_sync_all, /* icache_sync_all */
+ armv5_ec_icache_sync_range, /* icache_sync_range */
+
+ armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */
+ sheeva_dcache_wbinv_range, /* dcache_wbinv_range */
+ sheeva_dcache_inv_range, /* dcache_inv_range */
+ sheeva_dcache_wb_range, /* dcache_wb_range */
+
+ armv4_idcache_inv_all, /* idcache_inv_all */
+ armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */
+ sheeva_idcache_wbinv_range, /* idcache_wbinv_all */
+
+ sheeva_l2cache_wbinv_all, /* l2cache_wbinv_all */
+ sheeva_l2cache_wbinv_range, /* l2cache_wbinv_range */
+ sheeva_l2cache_inv_range, /* l2cache_inv_range */
+ sheeva_l2cache_wb_range, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ cpufunc_nullop, /* flush_prefetchbuf */
+ armv4_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ sheeva_cpu_sleep, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ arm10_context_switch, /* context_switch */
+
+ arm10_setup /* cpu setup */
+};
+#endif /* CPU_ARM9E || CPU_ARM10 */
+
+#ifdef CPU_ARM10
+struct cpu_functions arm10_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ arm10_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /* TLB functions */
+
+ armv4_tlb_flushID, /* tlb_flushID */
+ arm10_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv4_tlb_flushI, /* tlb_flushI */
+ arm10_tlb_flushI_SE, /* tlb_flushI_SE */
+ armv4_tlb_flushD, /* tlb_flushD */
+ armv4_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ arm10_icache_sync_all, /* icache_sync_all */
+ arm10_icache_sync_range, /* icache_sync_range */
+
+ arm10_dcache_wbinv_all, /* dcache_wbinv_all */
+ arm10_dcache_wbinv_range, /* dcache_wbinv_range */
+ arm10_dcache_inv_range, /* dcache_inv_range */
+ arm10_dcache_wb_range, /* dcache_wb_range */
+
+ armv4_idcache_inv_all, /* idcache_inv_all */
+ arm10_idcache_wbinv_all, /* idcache_wbinv_all */
+ arm10_idcache_wbinv_range, /* idcache_wbinv_range */
+ cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ cpufunc_nullop, /* flush_prefetchbuf */
+ armv4_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ (void *)cpufunc_nullop, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ arm10_context_switch, /* context_switch */
+
+ arm10_setup /* cpu setup */
+
+};
+#endif /* CPU_ARM10 */
+
+#ifdef CPU_MV_PJ4B
+struct cpu_functions pj4bv7_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ arm11_drain_writebuf, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ pj4b_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /* TLB functions */
+
+ armv7_tlb_flushID, /* tlb_flushID */
+ armv7_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv7_tlb_flushID, /* tlb_flushI */
+ armv7_tlb_flushID_SE, /* tlb_flushI_SE */
+ armv7_tlb_flushID, /* tlb_flushD */
+ armv7_tlb_flushID_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+ armv7_idcache_wbinv_all, /* icache_sync_all */
+ armv7_icache_sync_range, /* icache_sync_range */
+
+ armv7_dcache_wbinv_all, /* dcache_wbinv_all */
+ armv7_dcache_wbinv_range, /* dcache_wbinv_range */
+ armv7_dcache_inv_range, /* dcache_inv_range */
+ armv7_dcache_wb_range, /* dcache_wb_range */
+
+ armv7_idcache_inv_all, /* idcache_inv_all */
+ armv7_idcache_wbinv_all, /* idcache_wbinv_all */
+ armv7_idcache_wbinv_range, /* idcache_wbinv_all */
+
+ (void *)cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ pj4b_drain_readbuf, /* flush_prefetchbuf */
+ arm11_drain_writebuf, /* drain_writebuf */
+ pj4b_flush_brnchtgt_all, /* flush_brnchtgt_C */
+ pj4b_flush_brnchtgt_va, /* flush_brnchtgt_E */
+
+ (void *)cpufunc_nullop, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ arm11_context_switch, /* context_switch */
+
+ pj4bv7_setup /* cpu setup */
+};
+#endif /* CPU_MV_PJ4B */
+
+#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_80219)
+
+struct cpu_functions xscale_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ xscale_cpwait, /* cpwait */
+
+ /* MMU functions */
+
+ xscale_control, /* control */
+ cpufunc_domains, /* domain */
+ xscale_setttb, /* setttb */
+ cpufunc_faultstatus, /* faultstatus */
+ cpufunc_faultaddress, /* faultaddress */
+
+ /* TLB functions */
+
+ armv4_tlb_flushID, /* tlb_flushID */
+ xscale_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv4_tlb_flushI, /* tlb_flushI */
+ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
+ armv4_tlb_flushD, /* tlb_flushD */
+ armv4_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ xscale_cache_syncI, /* icache_sync_all */
+ xscale_cache_syncI_rng, /* icache_sync_range */
+
+ xscale_cache_purgeD, /* dcache_wbinv_all */
+ xscale_cache_purgeD_rng, /* dcache_wbinv_range */
+ xscale_cache_flushD_rng, /* dcache_inv_range */
+ xscale_cache_cleanD_rng, /* dcache_wb_range */
+
+ xscale_cache_flushID, /* idcache_inv_all */
+ xscale_cache_purgeID, /* idcache_wbinv_all */
+ xscale_cache_purgeID_rng, /* idcache_wbinv_range */
+ cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ cpufunc_nullop, /* flush_prefetchbuf */
+ armv4_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ xscale_cpu_sleep, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ xscale_context_switch, /* context_switch */
+
+ xscale_setup /* cpu setup */
+};
+#endif
+/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
+ CPU_XSCALE_80219 */
+
+#ifdef CPU_XSCALE_81342
+struct cpu_functions xscalec3_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ xscale_cpwait, /* cpwait */
+
+ /* MMU functions */
+
+ xscale_control, /* control */
+ cpufunc_domains, /* domain */
+ xscalec3_setttb, /* setttb */
+ cpufunc_faultstatus, /* faultstatus */
+ cpufunc_faultaddress, /* faultaddress */
+
+ /* TLB functions */
+
+ armv4_tlb_flushID, /* tlb_flushID */
+ xscale_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv4_tlb_flushI, /* tlb_flushI */
+ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
+ armv4_tlb_flushD, /* tlb_flushD */
+ armv4_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ xscalec3_cache_syncI, /* icache_sync_all */
+ xscalec3_cache_syncI_rng, /* icache_sync_range */
+
+ xscalec3_cache_purgeD, /* dcache_wbinv_all */
+ xscalec3_cache_purgeD_rng, /* dcache_wbinv_range */
+ xscale_cache_flushD_rng, /* dcache_inv_range */
+ xscalec3_cache_cleanD_rng, /* dcache_wb_range */
+
+ xscale_cache_flushID, /* idcache_inv_all */
+ xscalec3_cache_purgeID, /* idcache_wbinv_all */
+ xscalec3_cache_purgeID_rng, /* idcache_wbinv_range */
+ xscalec3_l2cache_purge, /* l2cache_wbinv_all */
+ xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */
+ xscalec3_l2cache_flush_rng, /* l2cache_inv_range */
+ xscalec3_l2cache_clean_rng, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ cpufunc_nullop, /* flush_prefetchbuf */
+ armv4_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ xscale_cpu_sleep, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ xscalec3_context_switch, /* context_switch */
+
+ xscale_setup /* cpu setup */
+};
+#endif /* CPU_XSCALE_81342 */
+
+
+#if defined(CPU_FA526) || defined(CPU_FA626TE)
+struct cpu_functions fa526_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* domain */
+ fa526_setttb, /* setttb */
+ cpufunc_faultstatus, /* faultstatus */
+ cpufunc_faultaddress, /* faultaddress */
+
+ /* TLB functions */
+
+ armv4_tlb_flushID, /* tlb_flushID */
+ fa526_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv4_tlb_flushI, /* tlb_flushI */
+ fa526_tlb_flushI_SE, /* tlb_flushI_SE */
+ armv4_tlb_flushD, /* tlb_flushD */
+ armv4_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ fa526_icache_sync_all, /* icache_sync_all */
+ fa526_icache_sync_range, /* icache_sync_range */
+
+ fa526_dcache_wbinv_all, /* dcache_wbinv_all */
+ fa526_dcache_wbinv_range, /* dcache_wbinv_range */
+ fa526_dcache_inv_range, /* dcache_inv_range */
+ fa526_dcache_wb_range, /* dcache_wb_range */
+
+ armv4_idcache_inv_all, /* idcache_inv_all */
+ fa526_idcache_wbinv_all, /* idcache_wbinv_all */
+ fa526_idcache_wbinv_range, /* idcache_wbinv_range */
+ cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ fa526_flush_prefetchbuf, /* flush_prefetchbuf */
+ armv4_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ fa526_flush_brnchtgt_E, /* flush_brnchtgt_E */
+
+ fa526_cpu_sleep, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ fa526_context_switch, /* context_switch */
+
+ fa526_setup /* cpu setup */
+};
+#endif /* CPU_FA526 || CPU_FA626TE */
+
+#if defined(CPU_ARM1136)
+struct cpu_functions arm1136_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ arm11x6_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /* TLB functions */
+
+ arm11_tlb_flushID, /* tlb_flushID */
+ arm11_tlb_flushID_SE, /* tlb_flushID_SE */
+ arm11_tlb_flushI, /* tlb_flushI */
+ arm11_tlb_flushI_SE, /* tlb_flushI_SE */
+ arm11_tlb_flushD, /* tlb_flushD */
+ arm11_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ arm11x6_icache_sync_all, /* icache_sync_all */
+ arm11x6_icache_sync_range, /* icache_sync_range */
+
+ arm11x6_dcache_wbinv_all, /* dcache_wbinv_all */
+ armv6_dcache_wbinv_range, /* dcache_wbinv_range */
+ armv6_dcache_inv_range, /* dcache_inv_range */
+ armv6_dcache_wb_range, /* dcache_wb_range */
+
+ armv6_idcache_inv_all, /* idcache_inv_all */
+ arm11x6_idcache_wbinv_all, /* idcache_wbinv_all */
+ arm11x6_idcache_wbinv_range, /* idcache_wbinv_range */
+
+ (void *)cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ arm11x6_flush_prefetchbuf, /* flush_prefetchbuf */
+ arm11_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ arm11_sleep, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ arm11_context_switch, /* context_switch */
+
+ arm11x6_setup /* cpu setup */
+};
+#endif /* CPU_ARM1136 */
+#if defined(CPU_ARM1176)
+struct cpu_functions arm1176_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ arm11x6_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /* TLB functions */
+
+ arm11_tlb_flushID, /* tlb_flushID */
+ arm11_tlb_flushID_SE, /* tlb_flushID_SE */
+ arm11_tlb_flushI, /* tlb_flushI */
+ arm11_tlb_flushI_SE, /* tlb_flushI_SE */
+ arm11_tlb_flushD, /* tlb_flushD */
+ arm11_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ arm11x6_icache_sync_all, /* icache_sync_all */
+ arm11x6_icache_sync_range, /* icache_sync_range */
+
+ arm11x6_dcache_wbinv_all, /* dcache_wbinv_all */
+ armv6_dcache_wbinv_range, /* dcache_wbinv_range */
+ armv6_dcache_inv_range, /* dcache_inv_range */
+ armv6_dcache_wb_range, /* dcache_wb_range */
+
+ armv6_idcache_inv_all, /* idcache_inv_all */
+ arm11x6_idcache_wbinv_all, /* idcache_wbinv_all */
+ arm11x6_idcache_wbinv_range, /* idcache_wbinv_range */
+
+ (void *)cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ arm11x6_flush_prefetchbuf, /* flush_prefetchbuf */
+ arm11_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ arm11x6_sleep, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ arm11_context_switch, /* context_switch */
+
+ arm11x6_setup /* cpu setup */
+};
+#endif /*CPU_ARM1176 */
+
+#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+struct cpu_functions cortexa_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ armv7_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /*
+ * TLB functions. ARMv7 does all TLB ops based on a unified TLB model
+ * whether the hardware implements separate I+D or not, so we use the
+ * same 'ID' functions for all 3 variations.
+ */
+
+ armv7_tlb_flushID, /* tlb_flushID */
+ armv7_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv7_tlb_flushID, /* tlb_flushI */
+ armv7_tlb_flushID_SE, /* tlb_flushI_SE */
+ armv7_tlb_flushID, /* tlb_flushD */
+ armv7_tlb_flushID_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ armv7_icache_sync_all, /* icache_sync_all */
+ armv7_icache_sync_range, /* icache_sync_range */
+
+ armv7_dcache_wbinv_all, /* dcache_wbinv_all */
+ armv7_dcache_wbinv_range, /* dcache_wbinv_range */
+ armv7_dcache_inv_range, /* dcache_inv_range */
+ armv7_dcache_wb_range, /* dcache_wb_range */
+
+ armv7_idcache_inv_all, /* idcache_inv_all */
+ armv7_idcache_wbinv_all, /* idcache_wbinv_all */
+ armv7_idcache_wbinv_range, /* idcache_wbinv_range */
+
+ /*
+ * Note: For CPUs using the PL310 the L2 ops are filled in when the
+ * L2 cache controller is actually enabled.
+ */
+ cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+ (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
+
+ /* Other functions */
+
+ cpufunc_nullop, /* flush_prefetchbuf */
+ armv7_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ armv7_sleep, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ armv7_context_switch, /* context_switch */
+
+ cortexa_setup /* cpu setup */
+};
+#endif /* CPU_CORTEXA */
+
+/*
+ * Global constants also used by locore.s
+ */
+
+struct cpu_functions cpufuncs;
+u_int cputype;
+u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */
+
+#if defined(CPU_ARM9) || \
+ defined (CPU_ARM9E) || defined (CPU_ARM10) || defined (CPU_ARM1136) || \
+ defined(CPU_ARM1176) || defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_FA526) || defined(CPU_FA626TE) || defined(CPU_MV_PJ4B) || \
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
+ defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+
+/* Global cache line sizes, use 32 as default */
+int arm_dcache_min_line_size = 32;
+int arm_icache_min_line_size = 32;
+int arm_idcache_min_line_size = 32;
+
+static void get_cachetype_cp15(void);
+
+/* Additional cache information local to this file. Log2 of some of the
+ above numbers. */
+static int arm_dcache_l2_nsets;
+static int arm_dcache_l2_assoc;
+static int arm_dcache_l2_linesize;
+
+static void
+get_cachetype_cp15()
+{
+ u_int ctype, isize, dsize, cpuid;
+ u_int clevel, csize, i, sel;
+ u_int multiplier;
+ u_char type;
+
+ __asm __volatile("mrc p15, 0, %0, c0, c0, 1"
+ : "=r" (ctype));
+
+ cpuid = cpufunc_id();
+ /*
+ * ...and thus spake the ARM ARM:
+ *
+ * If an <opcode2> value corresponding to an unimplemented or
+ * reserved ID register is encountered, the System Control
+ * processor returns the value of the main ID register.
+ */
+ if (ctype == cpuid)
+ goto out;
+
+ if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
+ /* Resolve minimal cache line sizes */
+ arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2);
+ arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2);
+ arm_idcache_min_line_size =
+ min(arm_icache_min_line_size, arm_dcache_min_line_size);
+
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 1"
+ : "=r" (clevel));
+ arm_cache_level = clevel;
+ arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
+ i = 0;
+ while ((type = (clevel & 0x7)) && i < 7) {
+ if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
+ type == CACHE_SEP_CACHE) {
+ sel = i << 1;
+ __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
+ : : "r" (sel));
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
+ : "=r" (csize));
+ arm_cache_type[sel] = csize;
+ arm_dcache_align = 1 <<
+ (CPUV7_CT_xSIZE_LEN(csize) + 4);
+ arm_dcache_align_mask = arm_dcache_align - 1;
+ }
+ if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
+ sel = (i << 1) | 1;
+ __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
+ : : "r" (sel));
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
+ : "=r" (csize));
+ arm_cache_type[sel] = csize;
+ }
+ i++;
+ clevel >>= 3;
+ }
+ } else {
+ if ((ctype & CPU_CT_S) == 0)
+ arm_pcache_unified = 1;
+
+ /*
+ * If you want to know how this code works, go read the ARM ARM.
+ */
+
+ arm_pcache_type = CPU_CT_CTYPE(ctype);
+
+ if (arm_pcache_unified == 0) {
+ isize = CPU_CT_ISIZE(ctype);
+ multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
+ arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
+ if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
+ if (isize & CPU_CT_xSIZE_M)
+ arm_picache_line_size = 0; /* not present */
+ else
+ arm_picache_ways = 1;
+ } else {
+ arm_picache_ways = multiplier <<
+ (CPU_CT_xSIZE_ASSOC(isize) - 1);
+ }
+ arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
+ }
+
+ dsize = CPU_CT_DSIZE(ctype);
+ multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
+ arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
+ if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
+ if (dsize & CPU_CT_xSIZE_M)
+ arm_pdcache_line_size = 0; /* not present */
+ else
+ arm_pdcache_ways = 1;
+ } else {
+ arm_pdcache_ways = multiplier <<
+ (CPU_CT_xSIZE_ASSOC(dsize) - 1);
+ }
+ arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
+
+ arm_dcache_align = arm_pdcache_line_size;
+
+ arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
+ arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
+ arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
+ CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
+
+ out:
+ arm_dcache_align_mask = arm_dcache_align - 1;
+ }
+}
+#endif /* ARM9 || XSCALE */
+
+/*
+ * Cannot panic here as we may not have a console yet ...
+ */
+
+int
+set_cpufuncs()
+{
+ cputype = cpufunc_id();
+ cputype &= CPU_ID_CPU_MASK;
+
+ /*
+ * NOTE: cpu_do_powersave defaults to off. If we encounter a
+ * CPU type where we want to use it by default, then we set it.
+ */
+
+#ifdef CPU_ARM9
+ if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
+ (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
+ (cputype & 0x0000f000) == 0x00009000) {
+ cpufuncs = arm9_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
+ get_cachetype_cp15();
+ arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
+ arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
+ arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
+ arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
+ arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
+#ifdef ARM9_CACHE_WRITE_THROUGH
+ pmap_pte_init_arm9();
+#else
+ pmap_pte_init_generic();
+#endif
+ goto out;
+ }
+#endif /* CPU_ARM9 */
+#if defined(CPU_ARM9E) || defined(CPU_ARM10)
+ if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
+ cputype == CPU_ID_MV88FR571_41) {
+ uint32_t sheeva_ctrl;
+
+ sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE |
+ MV_L2_ENABLE);
+ /*
+ * Workaround for Marvell MV78100 CPU: Cache prefetch
+ * mechanism may affect the cache coherency validity,
+ * so it needs to be disabled.
+ *
+ * Refer to errata document MV-S501058-00C.pdf (p. 3.1
+ * L2 Prefetching Mechanism) for details.
+ */
+ if (cputype == CPU_ID_MV88FR571_VD ||
+ cputype == CPU_ID_MV88FR571_41)
+ sheeva_ctrl |= MV_L2_PREFETCH_DISABLE;
+
+ sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl);
+
+ cpufuncs = sheeva_cpufuncs;
+ get_cachetype_cp15();
+ pmap_pte_init_generic();
+ goto out;
+ } else if (cputype == CPU_ID_ARM926EJS || cputype == CPU_ID_ARM1026EJS) {
+ cpufuncs = armv5_ec_cpufuncs;
+ get_cachetype_cp15();
+ pmap_pte_init_generic();
+ goto out;
+ }
+#endif /* CPU_ARM9E || CPU_ARM10 */
+#ifdef CPU_ARM10
+ if (/* cputype == CPU_ID_ARM1020T || */
+ cputype == CPU_ID_ARM1020E) {
+ /*
+ * Select write-through cacheing (this isn't really an
+ * option on ARM1020T).
+ */
+ cpufuncs = arm10_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
+ get_cachetype_cp15();
+ arm10_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
+ arm10_dcache_sets_max =
+ (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) -
+ arm10_dcache_sets_inc;
+ arm10_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
+ arm10_dcache_index_max = 0U - arm10_dcache_index_inc;
+ pmap_pte_init_generic();
+ goto out;
+ }
+#endif /* CPU_ARM10 */
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+ if (cputype == CPU_ID_ARM1136JS
+ || cputype == CPU_ID_ARM1136JSR1
+ || cputype == CPU_ID_ARM1176JZS) {
+#ifdef CPU_ARM1136
+ if (cputype == CPU_ID_ARM1136JS
+ || cputype == CPU_ID_ARM1136JSR1)
+ cpufuncs = arm1136_cpufuncs;
+#endif
+#ifdef CPU_ARM1176
+ if (cputype == CPU_ID_ARM1176JZS)
+ cpufuncs = arm1176_cpufuncs;
+#endif
+ cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
+ get_cachetype_cp15();
+
+ pmap_pte_init_mmu_v6();
+
+ goto out;
+ }
+#endif /* CPU_ARM1136 || CPU_ARM1176 */
+#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+ if (cputype == CPU_ID_CORTEXA7 ||
+ cputype == CPU_ID_CORTEXA8R1 ||
+ cputype == CPU_ID_CORTEXA8R2 ||
+ cputype == CPU_ID_CORTEXA8R3 ||
+ cputype == CPU_ID_CORTEXA9R1 ||
+ cputype == CPU_ID_CORTEXA9R2 ||
+ cputype == CPU_ID_CORTEXA9R3 ||
+ cputype == CPU_ID_CORTEXA15R0 ||
+ cputype == CPU_ID_CORTEXA15R1 ||
+ cputype == CPU_ID_CORTEXA15R2 ||
+ cputype == CPU_ID_CORTEXA15R3 ||
+ cputype == CPU_ID_KRAIT ) {
+ cpufuncs = cortexa_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
+ get_cachetype_cp15();
+
+ pmap_pte_init_mmu_v6();
+ /* Use powersave on this CPU. */
+ cpu_do_powersave = 1;
+ goto out;
+ }
+#endif /* CPU_CORTEXA */
+
+#if defined(CPU_MV_PJ4B)
+ if (cputype == CPU_ID_MV88SV581X_V7 ||
+ cputype == CPU_ID_MV88SV584X_V7 ||
+ cputype == CPU_ID_ARM_88SV581X_V7) {
+ cpufuncs = pj4bv7_cpufuncs;
+ get_cachetype_cp15();
+ pmap_pte_init_mmu_v6();
+ goto out;
+ }
+#endif /* CPU_MV_PJ4B */
+
+#if defined(CPU_FA526) || defined(CPU_FA626TE)
+ if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
+ cpufuncs = fa526_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */
+ get_cachetype_cp15();
+ pmap_pte_init_generic();
+
+ /* Use powersave on this CPU. */
+ cpu_do_powersave = 1;
+
+ goto out;
+ }
+#endif /* CPU_FA526 || CPU_FA626TE */
+
+#ifdef CPU_XSCALE_80200
+ if (cputype == CPU_ID_80200) {
+ int rev = cpufunc_id() & CPU_ID_REVISION_MASK;
+
+ i80200_icu_init();
+
+#if defined(XSCALE_CCLKCFG)
+ /*
+ * Crank CCLKCFG to maximum legal value.
+ */
+ __asm __volatile ("mcr p14, 0, %0, c6, c0, 0"
+ :
+ : "r" (XSCALE_CCLKCFG));
+#endif
+
+ /*
+ * XXX Disable ECC in the Bus Controller Unit; we
+ * don't really support it, yet. Clear any pending
+ * error indications.
+ */
+ __asm __volatile("mcr p13, 0, %0, c0, c1, 0"
+ :
+ : "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV));
+
+ cpufuncs = xscale_cpufuncs;
+ /*
+ * i80200 errata: Step-A0 and A1 have a bug where
+ * D$ dirty bits are not cleared on "invalidate by
+ * address".
+ *
+ * Workaround: Clean cache line before invalidating.
+ */
+ if (rev == 0 || rev == 1)
+ cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng;
+
+ cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
+ get_cachetype_cp15();
+ pmap_pte_init_xscale();
+ goto out;
+ }
+#endif /* CPU_XSCALE_80200 */
+#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
+ if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
+ cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 ||
+ cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) {
+ cpufuncs = xscale_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
+ get_cachetype_cp15();
+ pmap_pte_init_xscale();
+ goto out;
+ }
+#endif /* CPU_XSCALE_80321 */
+
+#if defined(CPU_XSCALE_81342)
+ if (cputype == CPU_ID_81342) {
+ cpufuncs = xscalec3_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
+ get_cachetype_cp15();
+ pmap_pte_init_xscale();
+ goto out;
+ }
+#endif /* CPU_XSCALE_81342 */
+#ifdef CPU_XSCALE_PXA2X0
+ /* ignore core revision to test PXA2xx CPUs */
+ if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
+ (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
+ (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
+
+ cpufuncs = xscale_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
+ get_cachetype_cp15();
+ pmap_pte_init_xscale();
+
+ /* Use powersave on this CPU. */
+ cpu_do_powersave = 1;
+
+ goto out;
+ }
+#endif /* CPU_XSCALE_PXA2X0 */
+#ifdef CPU_XSCALE_IXP425
+ if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
+ cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
+
+ cpufuncs = xscale_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
+ get_cachetype_cp15();
+ pmap_pte_init_xscale();
+
+ goto out;
+ }
+#endif /* CPU_XSCALE_IXP425 */
+ /*
+ * Bzzzz. And the answer was ...
+ */
+ panic("No support for this CPU type (%08x) in kernel", cputype);
+ return(ARCHITECTURE_NOT_PRESENT);
+out:
+ uma_set_align(arm_dcache_align_mask);
+ return (0);
+}
+
+/*
+ * Fixup routines for data and prefetch aborts.
+ *
+ * Several compile time symbols are used
+ *
+ * DEBUG_FAULT_CORRECTION - Print debugging information during the
+ * correction of registers after a fault.
+ */
+
+
+/*
+ * Null abort fixup routine.
+ * For use when no fixup is required.
+ */
+int
+cpufunc_null_fixup(arg)
+ void *arg;
+{
+ return(ABORT_FIXUP_OK);
+}
+
+/*
+ * CPU Setup code
+ */
+
+#if defined (CPU_ARM9) || \
+ defined(CPU_ARM9E) || \
+ defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
+ defined(CPU_ARM10) || defined(CPU_ARM1136) || defined(CPU_ARM1176) ||\
+ defined(CPU_FA526) || defined(CPU_FA626TE)
+
+#define IGN 0
+#define OR 1
+#define BIC 2
+
+struct cpu_option {
+ char *co_name;
+ int co_falseop;
+ int co_trueop;
+ int co_value;
+};
+
+static u_int parse_cpu_options(char *, struct cpu_option *, u_int);
+
+static u_int
+parse_cpu_options(args, optlist, cpuctrl)
+ char *args;
+ struct cpu_option *optlist;
+ u_int cpuctrl;
+{
+ int integer;
+
+ if (args == NULL)
+ return(cpuctrl);
+
+ while (optlist->co_name) {
+ if (get_bootconf_option(args, optlist->co_name,
+ BOOTOPT_TYPE_BOOLEAN, &integer)) {
+ if (integer) {
+ if (optlist->co_trueop == OR)
+ cpuctrl |= optlist->co_value;
+ else if (optlist->co_trueop == BIC)
+ cpuctrl &= ~optlist->co_value;
+ } else {
+ if (optlist->co_falseop == OR)
+ cpuctrl |= optlist->co_value;
+ else if (optlist->co_falseop == BIC)
+ cpuctrl &= ~optlist->co_value;
+ }
+ }
+ ++optlist;
+ }
+ return(cpuctrl);
+}
+#endif /* CPU_ARM9 || XSCALE*/
+
+#ifdef CPU_ARM9
+struct cpu_option arm9_options[] = {
+ { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "arm9.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "arm9.icache", BIC, OR, CPU_CONTROL_IC_ENABLE },
+ { "arm9.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE },
+ { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE },
+ { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE },
+ { "arm9.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE },
+ { NULL, IGN, IGN, 0 }
+};
+
+void
+arm9_setup(args)
+ char *args;
+{
+ int cpuctrl, cpuctrlmask;
+
+ cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+ | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
+ | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
+ | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
+ CPU_CONTROL_ROUNDROBIN;
+ cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+ | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
+ | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
+ | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
+ | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
+ | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
+ | CPU_CONTROL_ROUNDROBIN;
+
+#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
+ cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
+#endif
+
+ cpuctrl = parse_cpu_options(args, arm9_options, cpuctrl);
+
+#ifdef __ARMEB__
+ cpuctrl |= CPU_CONTROL_BEND_ENABLE;
+#endif
+ if (vector_page == ARM_VECTORS_HIGH)
+ cpuctrl |= CPU_CONTROL_VECRELOC;
+
+ /* Clear out the cache */
+ cpu_idcache_wbinv_all();
+
+ /* Set the control register */
+ cpu_control(cpuctrlmask, cpuctrl);
+ ctrl = cpuctrl;
+
+}
+#endif /* CPU_ARM9 */
+
+#if defined(CPU_ARM9E) || defined(CPU_ARM10)
+struct cpu_option arm10_options[] = {
+ { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "arm10.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "arm10.icache", BIC, OR, CPU_CONTROL_IC_ENABLE },
+ { "arm10.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE },
+ { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE },
+ { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE },
+ { "arm10.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE },
+ { NULL, IGN, IGN, 0 }
+};
+
+void
+arm10_setup(args)
+ char *args;
+{
+ int cpuctrl, cpuctrlmask;
+
+ cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
+ | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
+ | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
+ cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
+ | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
+ | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
+ | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
+ | CPU_CONTROL_BPRD_ENABLE
+ | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
+
+#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
+ cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
+#endif
+
+ cpuctrl = parse_cpu_options(args, arm10_options, cpuctrl);
+
+#ifdef __ARMEB__
+ cpuctrl |= CPU_CONTROL_BEND_ENABLE;
+#endif
+
+ /* Clear out the cache */
+ cpu_idcache_wbinv_all();
+
+ /* Now really make sure they are clean. */
+ __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
+
+ if (vector_page == ARM_VECTORS_HIGH)
+ cpuctrl |= CPU_CONTROL_VECRELOC;
+
+ /* Set the control register */
+ ctrl = cpuctrl;
+ cpu_control(0xffffffff, cpuctrl);
+
+ /* And again. */
+ cpu_idcache_wbinv_all();
+}
+#endif /* CPU_ARM9E || CPU_ARM10 */
+
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176) \
+ || defined(CPU_MV_PJ4B) \
+ || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+static __inline void
+cpu_scc_setup_ccnt(void)
+{
+/* This is how you give userland access to the CCNT and PMCn
+ * registers.
+ * BEWARE! This gives write access also, which may not be what
+ * you want!
+ */
+#ifdef _PMC_USER_READ_WRITE_
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+ /* Use the Secure User and Non-secure Access Validation Control Register
+ * to allow userland access
+ */
+ __asm volatile ("mcr p15, 0, %0, c15, c9, 0\n\t"
+ :
+ : "r"(0x00000001));
+#else
+ /* Set PMUSERENR[0] to allow userland access */
+ __asm volatile ("mcr p15, 0, %0, c9, c14, 0\n\t"
+ :
+ : "r"(0x00000001));
+#endif
+#endif
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+ /* Set PMCR[2,0] to enable counters and reset CCNT */
+ __asm volatile ("mcr p15, 0, %0, c15, c12, 0\n\t"
+ :
+ : "r"(0x00000005));
+#else
+ /* Set up the PMCCNTR register as a cyclecounter:
+ * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
+ * Set PMCR[2,0] to enable counters and reset CCNT
+ * Set PMCNTENSET to 0x80000000 to enable CCNT */
+ __asm volatile ("mcr p15, 0, %0, c9, c14, 2\n\t"
+ "mcr p15, 0, %1, c9, c12, 0\n\t"
+ "mcr p15, 0, %2, c9, c12, 1\n\t"
+ :
+ : "r"(0xFFFFFFFF),
+ "r"(0x00000005),
+ "r"(0x80000000));
+#endif
+}
+#endif
+
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+struct cpu_option arm11_options[] = {
+ { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "arm11.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "arm11.icache", BIC, OR, CPU_CONTROL_IC_ENABLE },
+ { "arm11.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE },
+ { NULL, IGN, IGN, 0 }
+};
+
+void
+arm11x6_setup(char *args)
+{
+ int cpuctrl, cpuctrl_wax;
+ uint32_t auxctrl, auxctrl_wax;
+ uint32_t tmp, tmp2;
+ uint32_t sbz=0;
+ uint32_t cpuid;
+
+ cpuid = cpufunc_id();
+
+ cpuctrl =
+ CPU_CONTROL_MMU_ENABLE |
+ CPU_CONTROL_DC_ENABLE |
+ CPU_CONTROL_WBUF_ENABLE |
+ CPU_CONTROL_32BP_ENABLE |
+ CPU_CONTROL_32BD_ENABLE |
+ CPU_CONTROL_LABT_ENABLE |
+ CPU_CONTROL_SYST_ENABLE |
+ CPU_CONTROL_IC_ENABLE;
+
+ /*
+ * "write as existing" bits
+ * inverse of this is mask
+ */
+ cpuctrl_wax =
+ (3 << 30) | /* SBZ */
+ (1 << 29) | /* FA */
+ (1 << 28) | /* TR */
+ (3 << 26) | /* SBZ */
+ (3 << 19) | /* SBZ */
+ (1 << 17); /* SBZ */
+
+ cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
+ cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
+
+ cpuctrl = parse_cpu_options(args, arm11_options, cpuctrl);
+
+#ifdef __ARMEB__
+ cpuctrl |= CPU_CONTROL_BEND_ENABLE;
+#endif
+
+ if (vector_page == ARM_VECTORS_HIGH)
+ cpuctrl |= CPU_CONTROL_VECRELOC;
+
+ auxctrl = 0;
+ auxctrl_wax = ~0;
+ /*
+ * This options enables the workaround for the 364296 ARM1136
+ * r0pX errata (possible cache data corruption with
+ * hit-under-miss enabled). It sets the undocumented bit 31 in
+ * the auxiliary control register and the FI bit in the control
+ * register, thus disabling hit-under-miss without putting the
+ * processor into full low interrupt latency mode. ARM11MPCore
+ * is not affected.
+ */
+ if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1136JS) { /* ARM1136JSr0pX */
+ cpuctrl |= CPU_CONTROL_FI_ENABLE;
+ auxctrl = ARM1136_AUXCTL_PFI;
+ auxctrl_wax = ~ARM1136_AUXCTL_PFI;
+ }
+
+ /*
+ * Enable an errata workaround
+ */
+ if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
+ auxctrl = ARM1176_AUXCTL_PHD;
+ auxctrl_wax = ~ARM1176_AUXCTL_PHD;
+ }
+
+ /* Clear out the cache */
+ cpu_idcache_wbinv_all();
+
+ /* Now really make sure they are clean. */
+ __asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz));
+
+ /* Allow detection code to find the VFP if it's fitted. */
+ __asm volatile ("mcr\tp15, 0, %0, c1, c0, 2" : : "r" (0x0fffffff));
+
+ /* Set the control register */
+ ctrl = cpuctrl;
+ cpu_control(~cpuctrl_wax, cpuctrl);
+
+ __asm volatile ("mrc p15, 0, %0, c1, c0, 1\n\t"
+ "and %1, %0, %2\n\t"
+ "orr %1, %1, %3\n\t"
+ "teq %0, %1\n\t"
+ "mcrne p15, 0, %1, c1, c0, 1\n\t"
+ : "=r"(tmp), "=r"(tmp2) :
+ "r"(auxctrl_wax), "r"(auxctrl));
+
+ /* And again. */
+ cpu_idcache_wbinv_all();
+
+ cpu_scc_setup_ccnt();
+}
+#endif /* CPU_ARM1136 || CPU_ARM1176 */
+
+#ifdef CPU_MV_PJ4B
+void
+pj4bv7_setup(args)
+ char *args;
+{
+ int cpuctrl;
+
+ pj4b_config();
+
+ cpuctrl = CPU_CONTROL_MMU_ENABLE;
+#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
+ cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
+#endif
+ cpuctrl |= CPU_CONTROL_DC_ENABLE;
+ cpuctrl |= (0xf << 3);
+ cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
+ cpuctrl |= CPU_CONTROL_IC_ENABLE;
+ if (vector_page == ARM_VECTORS_HIGH)
+ cpuctrl |= CPU_CONTROL_VECRELOC;
+ cpuctrl |= (0x5 << 16) | (1 < 22);
+ cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
+
+ /* Clear out the cache */
+ cpu_idcache_wbinv_all();
+
+ /* Set the control register */
+ ctrl = cpuctrl;
+ cpu_control(0xFFFFFFFF, cpuctrl);
+
+ /* And again. */
+ cpu_idcache_wbinv_all();
+
+ cpu_scc_setup_ccnt();
+}
+#endif /* CPU_MV_PJ4B */
+
+#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+
+void
+cortexa_setup(char *args)
+{
+ int cpuctrl, cpuctrlmask;
+
+ cpuctrlmask = CPU_CONTROL_MMU_ENABLE | /* MMU enable [0] */
+ CPU_CONTROL_AFLT_ENABLE | /* Alignment fault [1] */
+ CPU_CONTROL_DC_ENABLE | /* DCache enable [2] */
+ CPU_CONTROL_BPRD_ENABLE | /* Branch prediction [11] */
+ CPU_CONTROL_IC_ENABLE | /* ICache enable [12] */
+ CPU_CONTROL_VECRELOC; /* Vector relocation [13] */
+
+ cpuctrl = CPU_CONTROL_MMU_ENABLE |
+ CPU_CONTROL_IC_ENABLE |
+ CPU_CONTROL_DC_ENABLE |
+ CPU_CONTROL_BPRD_ENABLE;
+
+#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
+ cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
+#endif
+
+ /* Switch to big endian */
+#ifdef __ARMEB__
+ cpuctrl |= CPU_CONTROL_BEND_ENABLE;
+#endif
+
+ /* Check if the vector page is at the high address (0xffff0000) */
+ if (vector_page == ARM_VECTORS_HIGH)
+ cpuctrl |= CPU_CONTROL_VECRELOC;
+
+ /* Clear out the cache */
+ cpu_idcache_wbinv_all();
+
+ /* Set the control register */
+ ctrl = cpuctrl;
+ cpu_control(cpuctrlmask, cpuctrl);
+
+ /* And again. */
+ cpu_idcache_wbinv_all();
+#ifdef SMP
+ armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting */
+#endif
+
+ cpu_scc_setup_ccnt();
+}
+#endif /* CPU_CORTEXA */
+
+#if defined(CPU_FA526) || defined(CPU_FA626TE)
+struct cpu_option fa526_options[] = {
+#ifdef COMPAT_12
+ { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE |
+ CPU_CONTROL_DC_ENABLE) },
+ { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
+#endif /* COMPAT_12 */
+ { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE |
+ CPU_CONTROL_DC_ENABLE) },
+ { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE |
+ CPU_CONTROL_DC_ENABLE) },
+ { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE },
+ { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE },
+ { NULL, IGN, IGN, 0 }
+};
+
+void
+fa526_setup(char *args)
+{
+ int cpuctrl, cpuctrlmask;
+
+ cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+ | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
+ | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
+ | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
+ | CPU_CONTROL_BPRD_ENABLE;
+ cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+ | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
+ | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
+ | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
+ | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
+ | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
+ | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
+
+#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
+ cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
+#endif
+
+ cpuctrl = parse_cpu_options(args, fa526_options, cpuctrl);
+
+#ifdef __ARMEB__
+ cpuctrl |= CPU_CONTROL_BEND_ENABLE;
+#endif
+
+ if (vector_page == ARM_VECTORS_HIGH)
+ cpuctrl |= CPU_CONTROL_VECRELOC;
+
+ /* Clear out the cache */
+ cpu_idcache_wbinv_all();
+
+ /* Set the control register */
+ ctrl = cpuctrl;
+ cpu_control(0xffffffff, cpuctrl);
+}
+#endif /* CPU_FA526 || CPU_FA626TE */
+
+#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
+struct cpu_option xscale_options[] = {
+#ifdef COMPAT_12
+ { "branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE },
+ { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+#endif /* COMPAT_12 */
+ { "cpu.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE },
+ { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "xscale.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE },
+ { "xscale.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+ { "xscale.icache", BIC, OR, CPU_CONTROL_IC_ENABLE },
+ { "xscale.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE },
+ { NULL, IGN, IGN, 0 }
+};
+
+void
+xscale_setup(args)
+ char *args;
+{
+ uint32_t auxctl;
+ int cpuctrl, cpuctrlmask;
+
+ /*
+ * The XScale Write Buffer is always enabled. Our option
+ * is to enable/disable coalescing. Note that bits 6:3
+ * must always be enabled.
+ */
+
+ cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+ | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
+ | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
+ | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
+ | CPU_CONTROL_BPRD_ENABLE;
+ cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+ | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
+ | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
+ | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
+ | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
+ | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
+ | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
+ CPU_CONTROL_L2_ENABLE;
+
+#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
+ cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
+#endif
+
+ cpuctrl = parse_cpu_options(args, xscale_options, cpuctrl);
+
+#ifdef __ARMEB__
+ cpuctrl |= CPU_CONTROL_BEND_ENABLE;
+#endif
+
+ if (vector_page == ARM_VECTORS_HIGH)
+ cpuctrl |= CPU_CONTROL_VECRELOC;
+#ifdef CPU_XSCALE_CORE3
+ cpuctrl |= CPU_CONTROL_L2_ENABLE;
+#endif
+
+ /* Clear out the cache */
+ cpu_idcache_wbinv_all();
+
+ /*
+ * Set the control register. Note that bits 6:3 must always
+ * be set to 1.
+ */
+ ctrl = cpuctrl;
+/* cpu_control(cpuctrlmask, cpuctrl);*/
+ cpu_control(0xffffffff, cpuctrl);
+
+ /* Make sure write coalescing is turned on */
+ __asm __volatile("mrc p15, 0, %0, c1, c0, 1"
+ : "=r" (auxctl));
+#ifdef XSCALE_NO_COALESCE_WRITES
+ auxctl |= XSCALE_AUXCTL_K;
+#else
+ auxctl &= ~XSCALE_AUXCTL_K;
+#endif
+#ifdef CPU_XSCALE_CORE3
+ auxctl |= XSCALE_AUXCTL_LLR;
+ auxctl |= XSCALE_AUXCTL_MD_MASK;
+#endif
+ __asm __volatile("mcr p15, 0, %0, c1, c0, 1"
+ : : "r" (auxctl));
+}
+#endif /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
+ CPU_XSCALE_80219 */
Property changes on: trunk/sys/arm/arm/cpufunc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,196 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm.S,v 1.12 2003/09/06 09:14:52 rearnsha Exp $ */
+
+/*-
+ * Copyright (c) 1997,1998 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Causality Limited.
+ * 4. The name of Causality Limited may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpufunc.S
+ *
+ * Assembly functions for CPU / MMU / TLB specific operations
+ *
+ * Created : 30/01/97
+ *
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm.S 278652 2015-02-13 00:49:47Z ian $");
+
+ .text
+ .align 2
+
+ENTRY(cpufunc_nullop)
+ RET
+END(cpufunc_nullop)
+
+/*
+ * Generic functions to read the internal coprocessor registers
+ *
+ * Currently these registers are :
+ * c0 - CPU ID
+ * c5 - Fault status
+ * c6 - Fault address
+ *
+ */
+
+ENTRY(cpufunc_id)
+ mrc p15, 0, r0, c0, c0, 0
+ RET
+END(cpufunc_id)
+
+ENTRY(cpufunc_cpuid)
+ mrc p15, 0, r0, c0, c0, 0
+ RET
+END(cpufunc_cpuid)
+
+ENTRY(cpu_get_control)
+ mrc p15, 0, r0, c1, c0, 0
+ RET
+END(cpu_get_control)
+
+ENTRY(cpu_read_cache_config)
+ mrc p15, 0, r0, c0, c0, 1
+ RET
+END(cpu_read_cache_config)
+
+ENTRY(cpufunc_faultstatus)
+ mrc p15, 0, r0, c5, c0, 0
+ RET
+END(cpufunc_faultstatus)
+
+ENTRY(cpufunc_faultaddress)
+ mrc p15, 0, r0, c6, c0, 0
+ RET
+END(cpufunc_faultaddress)
+
+/*
+ * Generic functions to write the internal coprocessor registers
+ *
+ *
+ * Currently these registers are
+ * c1 - CPU Control
+ * c3 - Domain Access Control
+ *
+ * All other registers are CPU architecture specific
+ */
+
+#if 0 /* See below. */
+ENTRY(cpufunc_control)
+ mcr p15, 0, r0, c1, c0, 0
+ RET
+END(cpufunc_control)
+#endif
+
+ENTRY(cpufunc_domains)
+ mcr p15, 0, r0, c3, c0, 0
+ RET
+END(cpufunc_domains)
+
+/*
+ * Generic functions to read/modify/write the internal coprocessor registers
+ *
+ *
+ * Currently these registers are
+ * c1 - CPU Control
+ *
+ * All other registers are CPU architecture specific
+ */
+
+ENTRY(cpufunc_control)
+ mrc p15, 0, r3, c1, c0, 0 /* Read the control register */
+ bic r2, r3, r0 /* Clear bits */
+ eor r2, r2, r1 /* XOR bits */
+
+
+ teq r2, r3 /* Only write if there is a change */
+ mcrne p15, 0, r2, c1, c0, 0 /* Write new control register */
+ mov r0, r3 /* Return old value */
+
+ RET
+.Lglou:
+ .asciz "plop %p\n"
+ .align 2
+END(cpufunc_control)
+
+/*
+ * other potentially useful software functions are:
+ * clean D cache entry and flush I cache entry
+ * for the moment use cache_purgeID_E
+ */
+
+/* Random odd functions */
+
+/*
+ * Function to get the offset of a stored program counter from the
+ * instruction doing the store. This offset is defined to be the same
+ * for all STRs and STMs on a given implementation. Code based on
+ * section 2.4.3 of the ARM ARM (2nd Ed.), with modifications to work
+ * in 26-bit modes as well.
+ */
+ENTRY(get_pc_str_offset)
+ mov ip, sp
+ stmfd sp!, {fp, ip, lr, pc}
+ sub fp, ip, #4
+ sub sp, sp, #4
+ mov r1, pc /* R1 = addr of following STR */
+ mov r0, r0
+ str pc, [sp] /* [SP] = . + offset */
+ ldr r0, [sp]
+ sub r0, r0, r1
+ ldmdb fp, {fp, sp, pc}
+END(get_pc_str_offset)
+
+/* Allocate and lock a cacheline for the specified address. */
+
+#define CPWAIT_BRANCH \
+ sub pc, pc, #4
+#define CPWAIT() \
+ mrc p15, 0, r2, c2, c0, 0; \
+ mov r2, r2; \
+ CPWAIT_BRANCH
+
+ENTRY(arm_lock_cache_line)
+ mcr p15, 0, r0, c7, c10, 4 /* Drain write buffer */
+ mov r1, #1
+ mcr p15, 0, r1, c9, c2, 0 /* Enable data cache lock mode */
+ CPWAIT()
+ mcr p15, 0, r0, c7, c2, 5 /* Allocate the cache line */
+ mcr p15, 0, r0, c7, c10, 4 /* Drain write buffer */
+ mov r1, #0
+ str r1, [r0]
+ mcr p15, 0, r0, c7, c10, 4 /* Drain write buffer */
+ mcr p15, 0, r1, c9, c2, 0 /* Disable data cache lock mode */
+ CPWAIT()
+ RET
+END(arm_lock_cache_line)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_arm10.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_arm10.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_arm10.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,277 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_arm10.S,v 1.1 2003/09/06 09:12:29 rearnsha Exp $ */
+
+/*-
+ * Copyright (c) 2002 ARM Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ARM10 assembly functions for CPU / MMU / TLB specific operations
+ *
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_arm10.S 278652 2015-02-13 00:49:47Z ian $");
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(arm10_setttb)
+ stmfd sp!, {r0, lr}
+ bl _C_LABEL(arm10_idcache_wbinv_all)
+ ldmfd sp!, {r0, lr}
+
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ bx lr
+END(arm10_setttb)
+
+/*
+ * TLB functions
+ */
+ENTRY(arm10_tlb_flushID_SE)
+ mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
+ mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
+ bx lr
+END(arm10_tlb_flushID_SE)
+
+ENTRY(arm10_tlb_flushI_SE)
+ mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
+ bx lr
+END(arm10_tlb_flushI_SE)
+
+/*
+ * Cache operations. For the entire cache we use the set/index
+ * operations.
+ */
+ s_max .req r0
+ i_max .req r1
+ s_inc .req r2
+ i_inc .req r3
+
+ENTRY_NP(arm10_icache_sync_range)
+ ldr ip, .Larm10_line_size
+ cmp r1, #0x4000
+ bcs .Larm10_icache_sync_all
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm10_sync_next:
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
+ mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm10_sync_next
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ bx lr
+END(arm10_icache_sync_range)
+
+ENTRY_NP(arm10_icache_sync_all)
+.Larm10_icache_sync_all:
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache cleaning code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ /* Fall through to clean Dcache. */
+
+.Larm10_dcache_wb:
+ ldr ip, .Larm10_cache_data
+ ldmia ip, {s_max, i_max, s_inc, i_inc}
+.Lnext_set:
+ orr ip, s_max, i_max
+.Lnext_index:
+ mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index /* Next index */
+ subs s_max, s_max, s_inc
+ bhs .Lnext_set /* Next set */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ bx lr
+END(arm10_icache_sync_all)
+
+.Larm10_line_size:
+ .word _C_LABEL(arm_pdcache_line_size)
+
+ENTRY(arm10_dcache_wb_range)
+ ldr ip, .Larm10_line_size
+ cmp r1, #0x4000
+ bcs .Larm10_dcache_wb
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm10_wb_next:
+ mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm10_wb_next
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ bx lr
+END(arm10_dcache_wb_range)
+
+ENTRY(arm10_dcache_wbinv_range)
+ ldr ip, .Larm10_line_size
+ cmp r1, #0x4000
+ bcs .Larm10_dcache_wbinv_all
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm10_wbinv_next:
+ mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm10_wbinv_next
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ bx lr
+END(arm10_dcache_wbinv_range)
+
+/*
+ * Note, we must not invalidate everything. If the range is too big we
+ * must use wb-inv of the entire cache.
+ */
+ENTRY(arm10_dcache_inv_range)
+ ldr ip, .Larm10_line_size
+ cmp r1, #0x4000
+ bcs .Larm10_dcache_wbinv_all
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm10_inv_next:
+ mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm10_inv_next
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ bx lr
+END(arm10_dcache_inv_range)
+
+ENTRY(arm10_idcache_wbinv_range)
+ ldr ip, .Larm10_line_size
+ cmp r1, #0x4000
+ bcs .Larm10_idcache_wbinv_all
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm10_id_wbinv_next:
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
+ mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm10_id_wbinv_next
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ bx lr
+END(arm10_idcache_wbinv_range)
+
+ENTRY_NP(arm10_idcache_wbinv_all)
+.Larm10_idcache_wbinv_all:
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache purging code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ /* Fall through to purge Dcache. */
+
+EENTRY(arm10_dcache_wbinv_all)
+.Larm10_dcache_wbinv_all:
+ ldr ip, .Larm10_cache_data
+ ldmia ip, {s_max, i_max, s_inc, i_inc}
+.Lnext_set_inv:
+ orr ip, s_max, i_max
+.Lnext_index_inv:
+ mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index_inv /* Next index */
+ subs s_max, s_max, s_inc
+ bhs .Lnext_set_inv /* Next set */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ bx lr
+EEND(arm10_dcache_wbinv_all)
+END(arm10_idcache_wbinv_all)
+
+.Larm10_cache_data:
+ .word _C_LABEL(arm10_dcache_sets_max)
+
+/*
+ * Context switch.
+ *
+ * These is the CPU-specific parts of the context switcher cpu_switch()
+ * These functions actually perform the TTB reload.
+ *
+ * NOTE: Special calling convention
+ * r1, r4-r13 must be preserved
+ */
+ENTRY(arm10_context_switch)
+ /*
+ * We can assume that the caches will only contain kernel addresses
+ * at this point. So no need to flush them again.
+ */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ mcr p15, 0, r0, c2, c0, 0 /* set the new TTB */
+ mcr p15, 0, r0, c8, c7, 0 /* and flush the I+D tlbs */
+
+ /* Paranoia -- make sure the pipeline is empty. */
+ nop
+ nop
+ nop
+ bx lr
+END(arm10_context_switch)
+
+ .bss
+
+/* XXX The following macros should probably be moved to asm.h */
+#define _DATA_OBJECT(x) .globl x; .type x,_ASM_TYPE_OBJECT; x:
+#define C_OBJECT(x) _DATA_OBJECT(_C_LABEL(x))
+
+/*
+ * Parameters for the cache cleaning code. Note that the order of these
+ * four variables is assumed in the code above. Hence the reason for
+ * declaring them in the assembler file.
+ */
+ .align 2
+C_OBJECT(arm10_dcache_sets_max)
+ .space 4
+C_OBJECT(arm10_dcache_index_max)
+ .space 4
+C_OBJECT(arm10_dcache_sets_inc)
+ .space 4
+C_OBJECT(arm10_dcache_index_inc)
+ .space 4
Property changes on: trunk/sys/arm/arm/cpufunc_asm_arm10.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_arm11.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_arm11.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_arm11.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,136 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_arm11.S,v 1.2 2005/12/11 12:16:41 christos Exp $ */
+
+/*
+ * Copyright (c) 2002, 2005 ARM Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ARM11 assembly functions for CPU / MMU / TLB specific operations
+ *
+ * XXX We make no attempt at present to take advantage of the v6 memroy
+ * architecture or physically tagged cache.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_arm11.S 266359 2014-05-17 21:28:49Z ian $");
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(arm11_setttb)
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ RET
+END(arm11_setttb)
+
+/*
+ * TLB functions
+ */
+ENTRY(arm11_tlb_flushID_SE)
+ mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
+ mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ RET
+END(arm11_tlb_flushID_SE)
+
+ENTRY(arm11_tlb_flushI_SE)
+ mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ RET
+END(arm11_tlb_flushI_SE)
+
+/*
+ * Context switch.
+ *
+ * These is the CPU-specific parts of the context switcher cpu_switch()
+ * These functions actually perform the TTB reload.
+ *
+ * NOTE: Special calling convention
+ * r1, r4-r13 must be preserved
+ */
+ENTRY(arm11_context_switch)
+ /*
+ * We can assume that the caches will only contain kernel addresses
+ * at this point. So no need to flush them again.
+ */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ mcr p15, 0, r0, c2, c0, 0 /* set the new TTB */
+ mcr p15, 0, r0, c8, c7, 0 /* and flush the I+D tlbs */
+
+ /* Paranoia -- make sure the pipeline is empty. */
+ nop
+ nop
+ nop
+ RET
+END(arm11_context_switch)
+
+/*
+ * TLB functions
+ */
+ENTRY(arm11_tlb_flushID)
+ mcr p15, 0, r0, c8, c7, 0 /* flush I+D tlb */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(arm11_tlb_flushID)
+
+ENTRY(arm11_tlb_flushI)
+ mcr p15, 0, r0, c8, c5, 0 /* flush I tlb */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(arm11_tlb_flushI)
+
+ENTRY(arm11_tlb_flushD)
+ mcr p15, 0, r0, c8, c6, 0 /* flush D tlb */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(arm11_tlb_flushD)
+
+ENTRY(arm11_tlb_flushD_SE)
+ mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(arm11_tlb_flushD_SE)
+
+/*
+ * Other functions
+ */
+ENTRY(arm11_drain_writebuf)
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(arm11_drain_writebuf)
+
+ENTRY_NP(arm11_sleep)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c0, 4 /* wait for interrupt */
+ RET
+END(arm11_sleep)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_arm11.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_arm11x6.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_arm11x6.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_arm11x6.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,223 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_arm11x6.S,v 1.1 2012/07/21 12:19:15 skrll Exp $ */
+
+/*
+ * Copyright (c) 2007 Microsoft
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Microsoft
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Eben Upton
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_arm11x6.S 275767 2014-12-14 16:28:53Z andrew $");
+
+ .cpu arm1176jz-s
+
+#if 0
+#define Invalidate_I_cache(Rtmp1, Rtmp2) \
+ mcr p15, 0, Rtmp1, c7, c5, 0 /* Invalidate Entire I cache */
+#else
+/*
+ * Workaround for
+ *
+ * Erratum 411920 in ARM1136 (fixed in r1p4)
+ * Erratum 415045 in ARM1176 (fixed in r0p5?)
+ *
+ * - value of arg 'reg' Should Be Zero
+ */
+#define Invalidate_I_cache(Rtmp1, Rtmp2) \
+ mov Rtmp1, #0; /* SBZ */ \
+ mrs Rtmp2, cpsr; \
+ cpsid ifa; \
+ mcr p15, 0, Rtmp1, c7, c5, 0; /* Nuke Whole Icache */ \
+ mcr p15, 0, Rtmp1, c7, c5, 0; /* Nuke Whole Icache */ \
+ mcr p15, 0, Rtmp1, c7, c5, 0; /* Nuke Whole Icache */ \
+ mcr p15, 0, Rtmp1, c7, c5, 0; /* Nuke Whole Icache */ \
+ msr cpsr_cx, Rtmp2; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ nop;
+#endif
+
+#if 1
+#define Flush_D_cache(reg) \
+ mov reg, #0; /* SBZ */ \
+ mcr p15, 0, reg, c7, c14, 0;/* Clean and Invalidate Entire Data Cache */ \
+ mcr p15, 0, reg, c7, c10, 4;/* Data Synchronization Barrier */
+#else
+#define Flush_D_cache(reg) \
+1: mov reg, #0; /* SBZ */ \
+ mcr p15, 0, reg, c7, c14, 0;/* Clean and Invalidate Entire Data Cache */ \
+ mrc p15, 0, reg, C7, C10, 6;/* Read Cache Dirty Status Register */ \
+ ands reg, reg, #01; /* Check if it is clean */ \
+ bne 1b; /* loop if not */ \
+ mcr p15, 0, reg, c7, c10, 4;/* Data Synchronization Barrier */
+#endif
+
+ENTRY(arm11x6_setttb)
+ mov r1, #0
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+ mcr p15, 0, r1, c8, c7, 0 /* invalidate I+D TLBs */
+ mcr p15, 0, r1, c7, c10, 4 /* drain write buffer */
+ RET
+END(arm11x6_setttb)
+
+ENTRY_NP(arm11x6_idcache_wbinv_all)
+ Flush_D_cache(r0)
+ Invalidate_I_cache(r0, r1)
+ RET
+END(arm11x6_idcache_wbinv_all)
+
+ENTRY_NP(arm11x6_dcache_wbinv_all)
+ Flush_D_cache(r0)
+ RET
+END(arm11x6_dcache_wbinv_all)
+
+ENTRY_NP(arm11x6_icache_sync_all)
+ Flush_D_cache(r0)
+ Invalidate_I_cache(r0, r1)
+ RET
+END(arm11x6_icache_sync_all)
+
+ENTRY_NP(arm11x6_flush_prefetchbuf)
+ mcr p15, 0, r0, c7, c5, 4 /* Flush Prefetch Buffer */
+ RET
+END(arm11x6_flush_prefetchbuf)
+
+ENTRY_NP(arm11x6_icache_sync_range)
+ add r1, r1, r0
+ sub r1, r1, #1
+ /* Erratum ARM1136 371025, workaround #2 */
+ /* Erratum ARM1176 371367 */
+ mrs r2, cpsr /* save the CPSR */
+ cpsid ifa /* disable interrupts (irq,fiq,abort) */
+ mov r3, #0
+ mcr p15, 0, r3, c13, c0, 0 /* write FCSE (uTLB invalidate) */
+ mcr p15, 0, r3, c7, c5, 4 /* flush prefetch buffer */
+ add r3, pc, #0x24
+ mcr p15, 0, r3, c7, c13, 1 /* prefetch I-cache line */
+ mcrr p15, 0, r1, r0, c5 /* invalidate I-cache range */
+ msr cpsr_cx, r2 /* local_irq_restore */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mcrr p15, 0, r1, r0, c12 /* clean and invalidate D cache range */ /* XXXNH */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(arm11x6_icache_sync_range)
+
+ENTRY_NP(arm11x6_idcache_wbinv_range)
+ add r1, r1, r0
+ sub r1, r1, #1
+ /* Erratum ARM1136 371025, workaround #2 */
+ /* Erratum ARM1176 371367 */
+ mrs r2, cpsr /* save the CPSR */
+ cpsid ifa /* disable interrupts (irq,fiq,abort) */
+ mov r3, #0
+ mcr p15, 0, r3, c13, c0, 0 /* write FCSE (uTLB invalidate) */
+ mcr p15, 0, r3, c7, c5, 4 /* flush prefetch buffer */
+ add r3, pc, #0x24
+ mcr p15, 0, r3, c7, c13, 1 /* prefetch I-cache line */
+ mcrr p15, 0, r1, r0, c5 /* invalidate I-cache range */
+ msr cpsr_cx, r2 /* local_irq_restore */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mcrr p15, 0, r1, r0, c14 /* clean and invalidate D cache range */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(arm11x6_idcache_wbinv_range)
+
+/*
+ * Preload the cache before issuing the WFI by conditionally disabling the
+ * mcr intstructions the first time around the loop. Ensure the function is
+ * cacheline aligned.
+ */
+ .arch armv6
+ .p2align 5
+
+ENTRY_NP(arm11x6_sleep)
+ mov r0, #0
+ mov r1, #2
+1:
+ subs r1, #1
+ nop
+ mcreq p15, 0, r0, c7, c10, 4 /* data sync barrier */
+ mcreq p15, 0, r0, c7, c0, 4 /* wait for interrupt */
+ nop
+ nop
+ nop
+ bne 1b
+ RET
+END(arm11x6_sleep)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_arm11x6.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_arm9.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_arm9.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_arm9.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,264 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_arm9.S,v 1.3 2004/01/26 15:54:16 rearnsha Exp $ */
+
+/*
+ * Copyright (c) 2001, 2004 ARM Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ARM9 assembly functions for CPU / MMU / TLB specific operations
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_arm9.S 278652 2015-02-13 00:49:47Z ian $");
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(arm9_setttb)
+ stmfd sp!, {r0, lr}
+ bl _C_LABEL(arm9_idcache_wbinv_all)
+ ldmfd sp!, {r0, lr}
+
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ mov pc, lr
+END(arm9_setttb)
+
+/*
+ * TLB functions
+ */
+ENTRY(arm9_tlb_flushID_SE)
+ mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
+ mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
+ mov pc, lr
+END(arm9_tlb_flushID_SE)
+
+/*
+ * Cache operations. For the entire cache we use the set/index
+ * operations.
+ */
+ s_max .req r0
+ i_max .req r1
+ s_inc .req r2
+ i_inc .req r3
+
+ENTRY_NP(arm9_icache_sync_range)
+ ldr ip, .Larm9_line_size
+ cmp r1, #0x4000
+ bcs .Larm9_icache_sync_all
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm9_sync_next:
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
+ mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm9_sync_next
+ mov pc, lr
+END(arm9_icache_sync_range)
+
+ENTRY_NP(arm9_icache_sync_all)
+.Larm9_icache_sync_all:
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache cleaning code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ /* Fall through to clean Dcache. */
+
+.Larm9_dcache_wb:
+ ldr ip, .Larm9_cache_data
+ ldmia ip, {s_max, i_max, s_inc, i_inc}
+.Lnext_set:
+ orr ip, s_max, i_max
+.Lnext_index:
+ mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index /* Next index */
+ subs s_max, s_max, s_inc
+ bhs .Lnext_set /* Next set */
+ mov pc, lr
+END(arm9_icache_sync_all)
+
+.Larm9_line_size:
+ .word _C_LABEL(arm_pdcache_line_size)
+
+ENTRY(arm9_dcache_wb_range)
+ ldr ip, .Larm9_line_size
+ cmp r1, #0x4000
+ bcs .Larm9_dcache_wb
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm9_wb_next:
+ mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm9_wb_next
+ mov pc, lr
+END(arm9_dcache_wb_range)
+
+ENTRY(arm9_dcache_wbinv_range)
+ ldr ip, .Larm9_line_size
+ cmp r1, #0x4000
+ bcs .Larm9_dcache_wbinv_all
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm9_wbinv_next:
+ mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm9_wbinv_next
+ mov pc, lr
+END(arm9_dcache_wbinv_range)
+
+/*
+ * Note, we must not invalidate everything. If the range is too big we
+ * must use wb-inv of the entire cache.
+ */
+ENTRY(arm9_dcache_inv_range)
+ ldr ip, .Larm9_line_size
+ cmp r1, #0x4000
+ bcs .Larm9_dcache_wbinv_all
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm9_inv_next:
+ mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm9_inv_next
+ mov pc, lr
+END(arm9_dcache_inv_range)
+
+ENTRY(arm9_idcache_wbinv_range)
+ ldr ip, .Larm9_line_size
+ cmp r1, #0x4000
+ bcs .Larm9_idcache_wbinv_all
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larm9_id_wbinv_next:
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
+ mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larm9_id_wbinv_next
+ mov pc, lr
+END(arm9_idcache_wbinv_range)
+
+ENTRY_NP(arm9_idcache_wbinv_all)
+.Larm9_idcache_wbinv_all:
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache purging code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ /* Fall through */
+
+EENTRY(arm9_dcache_wbinv_all)
+.Larm9_dcache_wbinv_all:
+ ldr ip, .Larm9_cache_data
+ ldmia ip, {s_max, i_max, s_inc, i_inc}
+.Lnext_set_inv:
+ orr ip, s_max, i_max
+.Lnext_index_inv:
+ mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index_inv /* Next index */
+ subs s_max, s_max, s_inc
+ bhs .Lnext_set_inv /* Next set */
+ mov pc, lr
+EEND(arm9_dcache_wbinv_all)
+END(arm9_idcache_wbinv_all)
+
+.Larm9_cache_data:
+ .word _C_LABEL(arm9_dcache_sets_max)
+
+/*
+ * Context switch.
+ *
+ * These is the CPU-specific parts of the context switcher cpu_switch()
+ * These functions actually perform the TTB reload.
+ *
+ * NOTE: Special calling convention
+ * r1, r4-r13 must be preserved
+ */
+ENTRY(arm9_context_switch)
+ /*
+ * We can assume that the caches will only contain kernel addresses
+ * at this point. So no need to flush them again.
+ */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ mcr p15, 0, r0, c2, c0, 0 /* set the new TTB */
+ mcr p15, 0, r0, c8, c7, 0 /* and flush the I+D tlbs */
+
+ /* Paranoia -- make sure the pipeline is empty. */
+ nop
+ nop
+ nop
+ mov pc, lr
+END(arm9_context_switch)
+
+ .bss
+
+/* XXX The following macros should probably be moved to asm.h */
+#define _DATA_OBJECT(x) .globl x; .type x,_ASM_TYPE_OBJECT; x:
+#define C_OBJECT(x) _DATA_OBJECT(_C_LABEL(x))
+
+/*
+ * Parameters for the cache cleaning code. Note that the order of these
+ * four variables is assumed in the code above. Hence the reason for
+ * declaring them in the assembler file.
+ */
+ .align 2
+C_OBJECT(arm9_dcache_sets_max)
+ .space 4
+C_OBJECT(arm9_dcache_index_max)
+ .space 4
+C_OBJECT(arm9_dcache_sets_inc)
+ .space 4
+C_OBJECT(arm9_dcache_index_inc)
+ .space 4
Property changes on: trunk/sys/arm/arm/cpufunc_asm_arm9.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_armv4.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_armv4.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_armv4.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,80 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_armv4.S,v 1.1 2001/11/10 23:14:09 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001 ARM Limited
+ * Copyright (c) 1997,1998 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Causality Limited.
+ * 4. The name of Causality Limited may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ARM9 assembly functions for CPU / MMU / TLB specific operations
+ *
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_armv4.S 266203 2014-05-16 00:14:50Z ian $");
+
+/*
+ * TLB functions
+ */
+ENTRY(armv4_tlb_flushID)
+ mcr p15, 0, r0, c8, c7, 0 /* flush I+D tlb */
+ RET
+END(armv4_tlb_flushID)
+
+ENTRY(armv4_tlb_flushI)
+ mcr p15, 0, r0, c8, c5, 0 /* flush I tlb */
+ RET
+END(armv4_tlb_flushI)
+
+ENTRY(armv4_tlb_flushD)
+ mcr p15, 0, r0, c8, c6, 0 /* flush D tlb */
+ RET
+END(armv4_tlb_flushD)
+
+ENTRY(armv4_tlb_flushD_SE)
+ mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
+ RET
+END(armv4_tlb_flushD_SE)
+
+/*
+ * Other functions
+ */
+ENTRY(armv4_drain_writebuf)
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ RET
+END(armv4_drain_writebuf)
+
+ENTRY(armv4_idcache_inv_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c7, 0 /* invalidate all I+D cache */
+ RET
+END(armv4_drain_writebuf)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_armv4.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_armv5.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_armv5.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_armv5.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,248 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_armv5.S,v 1.3 2007/01/06 00:50:54 christos Exp $ */
+
+/*
+ * Copyright (c) 2002, 2005 ARM Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ARMv5 assembly functions for manipulating caches.
+ * These routines can be used by any core that supports the set/index
+ * operations.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_armv5.S 278652 2015-02-13 00:49:47Z ian $");
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(armv5_setttb)
+ stmfd sp!, {r0, lr}
+ bl _C_LABEL(armv5_idcache_wbinv_all)
+ ldmfd sp!, {r0, lr}
+
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ RET
+END(armv5_setttb)
+
+/*
+ * Cache operations. For the entire cache we use the set/index
+ * operations.
+ */
+ s_max .req r0
+ i_max .req r1
+ s_inc .req r2
+ i_inc .req r3
+
+ENTRY_NP(armv5_icache_sync_range)
+ ldr ip, .Larmv5_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_icache_sync_all
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
+ mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_icache_sync_range)
+
+ENTRY_NP(armv5_icache_sync_all)
+.Larmv5_icache_sync_all:
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache cleaning code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ /* Fall through to clean Dcache. */
+
+.Larmv5_dcache_wb:
+ ldr ip, .Larmv5_cache_data
+ ldmia ip, {s_max, i_max, s_inc, i_inc}
+1:
+ orr ip, s_max, i_max
+2:
+ mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
+ sub ip, ip, i_inc
+ tst ip, i_max /* Index 0 is last one */
+ bne 2b /* Next index */
+ mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
+ subs s_max, s_max, s_inc
+ bpl 1b /* Next set */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_icache_sync_all)
+
+.Larmv5_line_size:
+ .word _C_LABEL(arm_pdcache_line_size)
+
+ENTRY(armv5_dcache_wb_range)
+ ldr ip, .Larmv5_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_dcache_wb
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_dcache_wb_range)
+
+ENTRY(armv5_dcache_wbinv_range)
+ ldr ip, .Larmv5_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_dcache_wbinv_all
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_dcache_wbinv_range)
+
+/*
+ * Note, we must not invalidate everything. If the range is too big we
+ * must use wb-inv of the entire cache.
+ */
+ENTRY(armv5_dcache_inv_range)
+ ldr ip, .Larmv5_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_dcache_wbinv_all
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_dcache_inv_range)
+
+ENTRY(armv5_idcache_wbinv_range)
+ ldr ip, .Larmv5_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_idcache_wbinv_all
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
+ mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_idcache_wbinv_range)
+
+ENTRY_NP(armv5_idcache_wbinv_all)
+.Larmv5_idcache_wbinv_all:
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache purging code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ /* Fall through to purge Dcache. */
+
+EENTRY(armv5_dcache_wbinv_all)
+.Larmv5_dcache_wbinv_all:
+ ldr ip, .Larmv5_cache_data
+ ldmia ip, {s_max, i_max, s_inc, i_inc}
+1:
+ orr ip, s_max, i_max
+2:
+ mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
+ sub ip, ip, i_inc
+ tst ip, i_max /* Index 0 is last one */
+ bne 2b /* Next index */
+ mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
+ subs s_max, s_max, s_inc
+ bpl 1b /* Next set */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+EEND(armv5_dcache_wbinv_all)
+END(armv5_idcache_wbinv_all)
+
+.Larmv5_cache_data:
+ .word _C_LABEL(armv5_dcache_sets_max)
+
+ .bss
+
+/* XXX The following macros should probably be moved to asm.h */
+#define _DATA_OBJECT(x) .globl x; .type x,_ASM_TYPE_OBJECT; x:
+#define C_OBJECT(x) _DATA_OBJECT(_C_LABEL(x))
+
+/*
+ * Parameters for the cache cleaning code. Note that the order of these
+ * four variables is assumed in the code above. Hence the reason for
+ * declaring them in the assembler file.
+ */
+ .align 2
+C_OBJECT(armv5_dcache_sets_max)
+ .space 4
+C_OBJECT(armv5_dcache_index_max)
+ .space 4
+C_OBJECT(armv5_dcache_sets_inc)
+ .space 4
+C_OBJECT(armv5_dcache_index_inc)
+ .space 4
Property changes on: trunk/sys/arm/arm/cpufunc_asm_armv5.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_armv5_ec.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_armv5_ec.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_armv5_ec.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,217 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_armv5_ec.S,v 1.1 2007/01/06 00:50:54 christos Exp $ */
+
+/*
+ * Copyright (c) 2002, 2005 ARM Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ARMv5 assembly functions for manipulating caches.
+ * These routines can be used by any core that supports both the set/index
+ * operations and the test and clean operations for efficiently cleaning the
+ * entire DCache. If a core does not have the test and clean operations, but
+ * does have the set/index operations, use the routines in cpufunc_asm_armv5.S.
+ * This source was derived from that file.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_armv5_ec.S 248361 2013-03-16 02:48:49Z andrew $");
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(armv5_ec_setttb)
+ /*
+ * Some other ARM ports save registers on the stack, call the
+ * idcache_wbinv_all function and then restore the registers from the
+ * stack before setting the TTB. I observed that this caused a
+ * problem when the old and new translation table entries' buffering
+ * bits were different. If I saved the registers in other registers
+ * or invalidated the caches when I returned from idcache_wbinv_all,
+ * it worked fine. If not, I ended up executing at an invalid PC.
+ * For armv5_ec_settb, the idcache_wbinv_all is simple enough, I just
+ * do it directly and entirely avoid the problem.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Invalidate ICache */
+1: mrc p15, 0, r15, c7, c14, 3 /* Test, clean and invalidate DCache */
+ bne 1b /* More to do? */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ RET
+END(armv5_ec_setttb)
+
+/*
+ * Cache operations. For the entire cache we use the enhanced cache
+ * operations.
+ */
+
+ENTRY_NP(armv5_ec_icache_sync_range)
+ ldr ip, .Larmv5_ec_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_ec_icache_sync_all
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
+ mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_ec_icache_sync_range)
+
+ENTRY_NP(armv5_ec_icache_sync_all)
+.Larmv5_ec_icache_sync_all:
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache cleaning code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ /* Fall through to clean Dcache. */
+
+.Larmv5_ec_dcache_wb:
+1:
+ mrc p15, 0, r15, c7, c10, 3 /* Test and clean (don't invalidate) */
+ bne 1b /* More to do? */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_ec_icache_sync_all)
+
+.Larmv5_ec_line_size:
+ .word _C_LABEL(arm_pdcache_line_size)
+
+ENTRY(armv5_ec_dcache_wb_range)
+ ldr ip, .Larmv5_ec_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_ec_dcache_wb
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_ec_dcache_wb_range)
+
+ENTRY(armv5_ec_dcache_wbinv_range)
+ ldr ip, .Larmv5_ec_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_ec_dcache_wbinv_all
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_ec_dcache_wbinv_range)
+
+/*
+ * Note, we must not invalidate everything. If the range is too big we
+ * must use wb-inv of the entire cache.
+ */
+ENTRY(armv5_ec_dcache_inv_range)
+ ldr ip, .Larmv5_ec_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_ec_dcache_wbinv_all
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_ec_dcache_inv_range)
+
+ENTRY(armv5_ec_idcache_wbinv_range)
+ ldr ip, .Larmv5_ec_line_size
+ cmp r1, #0x4000
+ bcs .Larmv5_ec_idcache_wbinv_all
+ ldr ip, [ip]
+ sub r1, r1, #1 /* Don't overrun */
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I cache SE with VA */
+ mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
+ add r0, r0, ip
+ subs r1, r1, ip
+ bpl 1b
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_ec_idcache_wbinv_range)
+
+ENTRY_NP(armv5_ec_idcache_wbinv_all)
+.Larmv5_ec_idcache_wbinv_all:
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache purging code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Invalidate ICache */
+ /* Fall through to purge Dcache. */
+END(armv5_ec_idcache_wbinv_all)
+
+ENTRY(armv5_ec_dcache_wbinv_all)
+.Larmv5_ec_dcache_wbinv_all:
+1: mrc p15, 0, r15, c7, c14, 3 /* Test, clean and invalidate DCache */
+ bne 1b /* More to do? */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv5_ec_dcache_wbinv_all)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_armv5_ec.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_armv6.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_armv6.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_armv6.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,153 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_armv6.S,v 1.4 2010/12/10 02:06:22 bsh Exp $ */
+
+/*
+ * Copyright (c) 2002, 2005 ARM Limited
+ * Portions Copyright (c) 2007 Microsoft
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ARMv6 assembly functions for manipulating caches.
+ * These routines can be used by any core that supports the mcrr address
+ * range operations.
+ */
+
+/*
+ * $FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_armv6.S 269796 2014-08-11 01:29:28Z ian $
+ */
+
+#include <machine/asm.h>
+
+ .arch armv6
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(armv6_setttb)
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ RET
+END(armv6_setttb)
+
+/*
+ * Cache operations.
+ */
+
+/* LINTSTUB: void armv6_icache_sync_range(vaddr_t, vsize_t); */
+ENTRY_NP(armv6_icache_sync_range)
+ add r1, r1, r0
+ sub r1, r1, #1
+ mcrr p15, 0, r1, r0, c5 /* invalidate I cache range */
+ mcrr p15, 0, r1, r0, c12 /* clean D cache range */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv6_icache_sync_range)
+
+/* LINTSTUB: void armv6_icache_sync_all(void); */
+ENTRY_NP(armv6_icache_sync_all)
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache cleaning code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ mcr p15, 0, r0, c7, c10, 0 /* Clean D cache */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv6_icache_sync_all)
+
+/* LINTSTUB: void armv6_dcache_wb_range(vaddr_t, vsize_t); */
+ENTRY(armv6_dcache_wb_range)
+ add r1, r1, r0
+ sub r1, r1, #1
+ mcrr p15, 0, r1, r0, c12 /* clean D cache range */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv6_dcache_wb_range)
+
+/* LINTSTUB: void armv6_dcache_wbinv_range(vaddr_t, vsize_t); */
+ENTRY(armv6_dcache_wbinv_range)
+ add r1, r1, r0
+ sub r1, r1, #1
+ mcrr p15, 0, r1, r0, c14 /* clean and invaliate D cache range */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv6_dcache_wbinv_range)
+
+/*
+ * Note, we must not invalidate everything. If the range is too big we
+ * must use wb-inv of the entire cache.
+ *
+ * LINTSTUB: void armv6_dcache_inv_range(vaddr_t, vsize_t);
+ */
+ENTRY(armv6_dcache_inv_range)
+ add r1, r1, r0
+ sub r1, r1, #1
+ mcrr p15, 0, r1, r0, c6 /* invaliate D cache range */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv6_dcache_inv_range)
+
+/* LINTSTUB: void armv6_idcache_wbinv_range(vaddr_t, vsize_t); */
+ENTRY(armv6_idcache_wbinv_range)
+ add r1, r1, r0
+ sub r1, r1, #1
+ mcrr p15, 0, r1, r0, c5 /* invaliate I cache range */
+ mcrr p15, 0, r1, r0, c14 /* clean & invaliate D cache range */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(armv6_idcache_wbinv_range)
+
+/* LINTSTUB: void armv6_idcache_wbinv_all(void); */
+ENTRY_NP(armv6_idcache_wbinv_all)
+ /*
+ * We assume that the code here can never be out of sync with the
+ * dcache, so that we can safely flush the Icache and fall through
+ * into the Dcache purging code.
+ */
+ mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */
+ /* Fall through to purge Dcache. */
+
+/* LINTSTUB: void armv6_dcache_wbinv_all(void); */
+EENTRY(armv6_dcache_wbinv_all)
+ mcr p15, 0, r0, c7, c14, 0 /* clean & invalidate D cache */
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+EEND(armv6_dcache_wbinv_all)
+END(armv6_idcache_wbinv_all)
+
+ENTRY(armv6_idcache_inv_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c7, 0 /* invalidate all I+D cache */
+ RET
+END(armv6_idcache_inv_all)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_armv6.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_armv7.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_armv7.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_armv7.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,375 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Per Odlund <per.odlund at armagedon.se>
+ * Copyright (C) 2011 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_armv7.S 283499 2015-05-24 18:23:57Z ian $");
+
+#include <machine/sysreg.h>
+
+ .cpu cortex-a8
+
+.Lcoherency_level:
+ .word _C_LABEL(arm_cache_loc)
+.Lcache_type:
+ .word _C_LABEL(arm_cache_type)
+.Larmv7_dcache_line_size:
+ .word _C_LABEL(arm_dcache_min_line_size)
+.Larmv7_icache_line_size:
+ .word _C_LABEL(arm_icache_min_line_size)
+.Larmv7_idcache_line_size:
+ .word _C_LABEL(arm_idcache_min_line_size)
+.Lway_mask:
+ .word 0x3ff
+.Lmax_index:
+ .word 0x7fff
+.Lpage_mask:
+ .word 0xfff
+
+#define PT_NOS (1 << 5)
+#define PT_S (1 << 1)
+#define PT_INNER_NC 0
+#define PT_INNER_WT (1 << 0)
+#define PT_INNER_WB ((1 << 0) | (1 << 6))
+#define PT_INNER_WBWA (1 << 6)
+#define PT_OUTER_NC 0
+#define PT_OUTER_WT (2 << 3)
+#define PT_OUTER_WB (3 << 3)
+#define PT_OUTER_WBWA (1 << 3)
+
+#ifdef SMP
+#define PT_ATTR (PT_S|PT_INNER_WBWA|PT_OUTER_WBWA|PT_NOS)
+#else
+#define PT_ATTR (PT_INNER_WBWA|PT_OUTER_WBWA)
+#endif
+
+ENTRY(armv7_setttb)
+ dsb
+ orr r0, r0, #PT_ATTR
+ mcr CP15_TTBR0(r0)
+ isb
+#ifdef SMP
+ mcr CP15_TLBIALLIS
+#else
+ mcr CP15_TLBIALL
+#endif
+ dsb
+ isb
+ RET
+END(armv7_setttb)
+
+ENTRY(armv7_tlb_flushID)
+ dsb
+#ifdef SMP
+ mcr CP15_TLBIALLIS
+ mcr CP15_BPIALLIS
+#else
+ mcr CP15_TLBIALL
+ mcr CP15_BPIALL
+#endif
+ dsb
+ isb
+ mov pc, lr
+END(armv7_tlb_flushID)
+
+ENTRY(armv7_tlb_flushID_SE)
+ ldr r1, .Lpage_mask
+ bic r0, r0, r1
+#ifdef SMP
+ mcr CP15_TLBIMVAAIS(r0)
+ mcr CP15_BPIALLIS
+#else
+ mcr CP15_TLBIMVA(r0)
+ mcr CP15_BPIALL
+#endif
+ dsb
+ isb
+ mov pc, lr
+END(armv7_tlb_flushID_SE)
+
+/* Based on algorithm from ARM Architecture Reference Manual */
+ENTRY(armv7_dcache_wbinv_all)
+ stmdb sp!, {r4, r5, r6, r7, r8, r9}
+
+ /* Get cache level */
+ ldr r0, .Lcoherency_level
+ ldr r3, [r0]
+ cmp r3, #0
+ beq Finished
+ /* For each cache level */
+ mov r8, #0
+Loop1:
+ /* Get cache type for given level */
+ mov r2, r8, lsl #2
+ add r2, r2, r2
+ ldr r0, .Lcache_type
+ ldr r1, [r0, r2]
+
+ /* Get line size */
+ and r2, r1, #7
+ add r2, r2, #4
+
+ /* Get number of ways */
+ ldr r4, .Lway_mask
+ ands r4, r4, r1, lsr #3
+ clz r5, r4
+
+ /* Get max index */
+ ldr r7, .Lmax_index
+ ands r7, r7, r1, lsr #13
+Loop2:
+ mov r9, r4
+Loop3:
+ mov r6, r8, lsl #1
+ orr r6, r6, r9, lsl r5
+ orr r6, r6, r7, lsl r2
+
+ /* Clean and invalidate data cache by way/index */
+ mcr CP15_DCCISW(r6)
+ subs r9, r9, #1
+ bge Loop3
+ subs r7, r7, #1
+ bge Loop2
+Skip:
+ add r8, r8, #1
+ cmp r3, r8
+ bne Loop1
+Finished:
+ dsb
+ ldmia sp!, {r4, r5, r6, r7, r8, r9}
+ RET
+END(armv7_dcache_wbinv_all)
+
+ENTRY(armv7_idcache_wbinv_all)
+ stmdb sp!, {lr}
+ bl armv7_dcache_wbinv_all
+#ifdef SMP
+ mcr CP15_ICIALLUIS
+#else
+ mcr CP15_ICIALLU
+#endif
+ dsb
+ isb
+ ldmia sp!, {lr}
+ RET
+END(armv7_idcache_wbinv_all)
+
+ENTRY(armv7_dcache_wb_range)
+ ldr ip, .Larmv7_dcache_line_size
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larmv7_wb_next:
+ mcr CP15_DCCMVAC(r0)
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larmv7_wb_next
+ dsb /* data synchronization barrier */
+ RET
+END(armv7_dcache_wb_range)
+
+ENTRY(armv7_dcache_wbinv_range)
+ ldr ip, .Larmv7_dcache_line_size
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larmv7_wbinv_next:
+ mcr CP15_DCCIMVAC(r0)
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larmv7_wbinv_next
+ dsb /* data synchronization barrier */
+ RET
+END(armv7_dcache_wbinv_range)
+
+/*
+ * Note, we must not invalidate everything. If the range is too big we
+ * must use wb-inv of the entire cache.
+ */
+ENTRY(armv7_dcache_inv_range)
+ ldr ip, .Larmv7_dcache_line_size
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larmv7_inv_next:
+ mcr CP15_DCIMVAC(r0)
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larmv7_inv_next
+ dsb /* data synchronization barrier */
+ RET
+END(armv7_dcache_inv_range)
+
+ENTRY(armv7_idcache_wbinv_range)
+ ldr ip, .Larmv7_idcache_line_size
+ ldr ip, [ip]
+ sub r3, ip, #1
+ and r2, r0, r3
+ add r1, r1, r2
+ bic r0, r0, r3
+.Larmv7_id_wbinv_next:
+ mcr CP15_ICIMVAU(r0)
+ mcr CP15_DCCIMVAC(r0)
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larmv7_id_wbinv_next
+ dsb /* data synchronization barrier */
+ isb /* instruction synchronization barrier */
+ RET
+END(armv7_idcache_wbinv_range)
+
+ENTRY_NP(armv7_icache_sync_all)
+#ifdef SMP
+ mcr CP15_ICIALLUIS
+#else
+ mcr CP15_ICIALLU
+#endif
+ dsb /* data synchronization barrier */
+ isb /* instruction synchronization barrier */
+ RET
+END(armv7_icache_sync_all)
+
+ENTRY_NP(armv7_icache_sync_range)
+ ldr ip, .Larmv7_icache_line_size
+ ldr ip, [ip]
+ sub r3, ip, #1 /* Address need not be aligned, but */
+ and r2, r0, r3 /* round length up if op spans line */
+ add r1, r1, r2 /* boundary: len += addr & linemask; */
+.Larmv7_sync_next:
+ mcr CP15_DCCMVAC(r0)
+ mcr CP15_ICIMVAU(r0)
+ add r0, r0, ip
+ subs r1, r1, ip
+ bhi .Larmv7_sync_next
+ dsb /* data synchronization barrier */
+ isb /* instruction synchronization barrier */
+ RET
+END(armv7_icache_sync_range)
+
+ENTRY(armv7_cpu_sleep)
+ dsb /* data synchronization barrier */
+ wfi /* wait for interrupt */
+ RET
+END(armv7_cpu_sleep)
+
+ENTRY(armv7_context_switch)
+ dsb
+ orr r0, r0, #PT_ATTR
+
+ mcr CP15_TTBR0(r0)
+ isb
+#ifdef SMP
+ mcr CP15_TLBIALLIS
+#else
+ mcr CP15_TLBIALL
+#endif
+ dsb
+ isb
+ RET
+END(armv7_context_switch)
+
+ENTRY(armv7_drain_writebuf)
+ dsb
+ RET
+END(armv7_drain_writebuf)
+
+ENTRY(armv7_sev)
+ dsb
+ sev
+ nop
+ RET
+END(armv7_sev)
+
+ENTRY(armv7_auxctrl)
+ mrc CP15_ACTLR(r2)
+ bic r3, r2, r0 /* Clear bits */
+ eor r3, r3, r1 /* XOR bits */
+
+ teq r2, r3
+ mcrne CP15_ACTLR(r3)
+ mov r0, r2
+ RET
+END(armv7_auxctrl)
+
+/*
+ * Invalidate all I+D+branch cache. Used by startup code, which counts
+ * on the fact that only r0-r3,ip are modified and no stack space is used.
+ */
+ENTRY(armv7_idcache_inv_all)
+ mov r0, #0
+ mcr CP15_CSSELR(r0) @ set cache level to L1
+ mrc CP15_CCSIDR(r0)
+
+ ubfx r2, r0, #13, #15 @ get num sets - 1 from CCSIDR
+ ubfx r3, r0, #3, #10 @ get numways - 1 from CCSIDR
+ clz r1, r3 @ number of bits to MSB of way
+ lsl r3, r3, r1 @ shift into position
+ mov ip, #1 @
+ lsl ip, ip, r1 @ ip now contains the way decr
+
+ ubfx r0, r0, #0, #3 @ get linesize from CCSIDR
+ add r0, r0, #4 @ apply bias
+ lsl r2, r2, r0 @ shift sets by log2(linesize)
+ add r3, r3, r2 @ merge numsets - 1 with numways - 1
+ sub ip, ip, r2 @ subtract numsets - 1 from way decr
+ mov r1, #1
+ lsl r1, r1, r0 @ r1 now contains the set decr
+ mov r2, ip @ r2 now contains set way decr
+
+ /* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */
+1: mcr CP15_DCISW(r3) @ invalidate line
+ movs r0, r3 @ get current way/set
+ beq 2f @ at 0 means we are done.
+ movs r0, r0, lsl #10 @ clear way bits leaving only set bits
+ subne r3, r3, r1 @ non-zero?, decrement set #
+ subeq r3, r3, r2 @ zero?, decrement way # and restore set count
+ b 1b
+
+2: dsb @ wait for stores to finish
+ mov r0, #0 @ and ...
+ mcr CP15_ICIALLU @ invalidate instruction+branch cache
+ isb @ instruction sync barrier
+ bx lr @ return
+END(armv7_idcache_inv_all)
+
+ENTRY_NP(armv7_sleep)
+ dsb
+ wfi
+ bx lr
+END(armv7_sleep)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_armv7.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_fa526.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_fa526.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_fa526.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,229 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_fa526.S,v 1.3 2008/10/15 16:56:49 matt Exp $*/
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt at 3am-software.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_fa526.S 248361 2013-03-16 02:48:49Z andrew $");
+
+#ifdef CPU_FA526
+#define CACHELINE_SIZE 16
+#else
+#define CACHELINE_SIZE 32
+#endif
+
+ENTRY(fa526_setttb)
+ mov r1, #0
+ mcr p15, 0, r1, c7, c14, 0 /* clean and invalidate D$ */
+ mcr p15, 0, r1, c7, c5, 0 /* invalidate I$ */
+ mcr p15, 0, r1, c7, c5, 6 /* invalidate BTB */
+ mcr p15, 0, r1, c7, c10, 4 /* drain write and fill buffer */
+
+ mcr p15, 0, r0, c2, c0, 0 /* Write the TTB */
+
+ /* If we have updated the TTB we must flush the TLB */
+ mcr p15, 0, r1, c8, c7, 0 /* invalidate I+D TLB */
+
+ /* Make sure that pipeline is emptied */
+ mov r0, r0
+ mov r0, r0
+ mov pc, lr
+END(fa526_setttb)
+
+/*
+ * TLB functions
+ */
+ENTRY(fa526_tlb_flushID_SE)
+ mcr p15, 0, r0, c8, c7, 1 /* flush Utlb single entry */
+ mov pc, lr
+END(fa526_tlb_flushID_SE)
+
+/*
+ * TLB functions
+ */
+ENTRY(fa526_tlb_flushI_SE)
+ mcr p15, 0, r0, c8, c5, 1 /* flush Itlb single entry */
+ mov pc, lr
+END(fa526_tlb_flushI_SE)
+
+ENTRY(fa526_cpu_sleep)
+ mov r0, #0
+/* nop
+ nop*/
+ mcr p15, 0, r0, c7, c0, 4 /* Wait for interrupt*/
+ mov pc, lr
+END(fa526_cpu_sleep)
+
+ENTRY(fa526_flush_prefetchbuf)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 4 /* Pre-fetch flush */
+ mov pc, lr
+END(fa526_flush_prefetchbuf)
+
+/*
+ * Cache functions
+ */
+ENTRY(fa526_idcache_wbinv_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c14, 0 /* clean and invalidate D$ */
+ mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(fa526_idcache_wbinv_all)
+
+ENTRY(fa526_icache_sync_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */
+ mov pc, lr
+END(fa526_icache_sync_all)
+
+ENTRY(fa526_dcache_wbinv_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c14, 0 /* clean and invalidate D$ */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(fa526_dcache_wbinv_all)
+
+/*
+ * Soft functions
+ */
+ENTRY(fa526_dcache_wbinv_range)
+ cmp r1, #0x4000
+ bhs _C_LABEL(fa526_dcache_wbinv_all)
+
+ and r2, r0, #(CACHELINE_SIZE - 1)
+ add r1, r1, r2
+ bic r0, r0, #(CACHELINE_SIZE - 1)
+
+1: mcr p15, 0, r0, c7, c14, 1 /* clean and invalidate D$ entry */
+ add r0, r0, #CACHELINE_SIZE
+ subs r1, r1, #CACHELINE_SIZE
+ bhi 1b
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(fa526_dcache_wbinv_range)
+
+ENTRY(fa526_dcache_wb_range)
+ cmp r1, #0x4000
+ bls 1f
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 0 /* clean entire D$ */
+ b 3f
+
+1: and r2, r0, #(CACHELINE_SIZE - 1)
+ add r1, r1, r2
+ bic r0, r0, #(CACHELINE_SIZE - 1)
+
+2: mcr p15, 0, r0, c7, c10, 1 /* clean D$ entry */
+ add r0, r0, #CACHELINE_SIZE
+ subs r1, r1, #CACHELINE_SIZE
+ bhi 2b
+
+3: mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(fa526_dcache_wb_range)
+
+ENTRY(fa526_dcache_inv_range)
+ and r2, r0, #(CACHELINE_SIZE - 1)
+ add r1, r1, r2
+ bic r0, r0, #(CACHELINE_SIZE - 1)
+
+1: mcr p15, 0, r0, c7, c6, 1 /* invalidate D$ single entry */
+ add r0, r0, #CACHELINE_SIZE
+ subs r1, r1, #CACHELINE_SIZE
+ bhi 1b
+
+ mov pc, lr
+END(fa526_dcache_inv_range)
+
+ENTRY(fa526_idcache_wbinv_range)
+ cmp r1, #0x4000
+ bhs _C_LABEL(fa526_idcache_wbinv_all)
+
+ and r2, r0, #(CACHELINE_SIZE - 1)
+ add r1, r1, r2
+ bic r0, r0, #(CACHELINE_SIZE - 1)
+
+1: mcr p15, 0, r0, c7, c14, 1 /* clean and invalidate D$ entry */
+ mcr p15, 0, r0, c7, c5, 1 /* invalidate I$ entry */
+ add r0, r0, #CACHELINE_SIZE
+ subs r1, r1, #CACHELINE_SIZE
+ bhi 1b
+
+2: mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(fa526_idcache_wbinv_range)
+
+ENTRY(fa526_icache_sync_range)
+ cmp r1, #0x4000
+ bhs _C_LABEL(fa526_icache_sync_all)
+
+ and r2, r0, #(CACHELINE_SIZE - 1)
+ add r1, r1, r2
+ bic r0, r0, #(CACHELINE_SIZE - 1)
+
+1: mcr p15, 0, r0, c7, c10, 1 /* clean D$ entry */
+ mcr p15, 0, r0, c7, c5, 1 /* invalidate I$ entry */
+ add r0, r0, #CACHELINE_SIZE
+ subs r1, r1, #CACHELINE_SIZE
+ bhi 1b
+
+2: mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mov pc, lr
+END(fa526_icache_sync_range)
+
+ENTRY(fa526_flush_brnchtgt_E)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 6 /* invalidate BTB cache */
+ mov pc, lr
+END(fa526_flush_brnchtgt_E)
+
+ENTRY(fa526_context_switch)
+ /*
+ * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
+ * Thus the data cache will contain only kernel data and the
+ * instruction cache will contain only kernel code, and all
+ * kernel mappings are shared by all processes.
+ */
+
+ mcr p15, 0, r0, c2, c0, 0 /* Write the TTB */
+
+ /* If we have updated the TTB we must flush the TLB */
+ mov r0, #0
+ mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */
+
+ /* Make sure that pipeline is emptied */
+ mov r0, r0
+ mov r0, r0
+ mov pc, lr
+END(fa526_context_switch)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_fa526.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_pj4b.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_pj4b.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_pj4b.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,131 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2011 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_pj4b.S 266046 2014-05-14 16:32:27Z ian $");
+
+#include <machine/param.h>
+
+.Lpj4b_sf_ctrl_reg:
+ .word 0xf1021820
+
+
+ENTRY(pj4b_setttb)
+ /* Cache synchronization is not required as this core has PIPT caches */
+ mcr p15, 0, r1, c7, c10, 4 /* drain the write buffer */
+#ifdef SMP
+ orr r0, r0, #2 /* Set TTB shared memory flag */
+#endif
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ RET
+END(pj4b_setttb)
+
+ENTRY(pj4b_drain_readbuf)
+ mcr p15, 0, r0, c7, c5, 4 /* flush prefetch buffers */
+ RET
+END(pj4b_drain_readbuf)
+
+ENTRY(pj4b_flush_brnchtgt_all)
+ mcr p15, 0, r0, c7, c5, 6 /* flush entrie branch target cache */
+ RET
+END(pj4b_flush_brnchtgt_all)
+
+ENTRY(pj4b_flush_brnchtgt_va)
+ mcr p15, 0, r0, c7, c5, 7 /* flush branch target cache by VA */
+ RET
+END(pj4b_flush_brnchtgt_va)
+
+ENTRY(get_core_id)
+ mrc p15, 0, r0, c0, c0, 5
+ RET
+END(get_core_id)
+
+ENTRY(pj4b_config)
+
+ /* Set Auxiliary Debug Modes Control 0 register */
+ mrc p15, 1, r0, c15, c1, 0
+ /* ARMADAXP errata fix: ARM-CPU-6136 */
+ bic r0, r0, #(1 << 12) /* LDSTM first issue is single word */
+
+ orr r0, r0, #(1 << 22) /* DVM_WAKEUP disable */
+ mcr p15, 1, r0, c15, c1, 0
+
+ /* Set Auxiliary Debug Modes Control 1 register */
+ mrc p15, 1, r0, c15, c1, 1
+ /* ARMADAXP errata fix: ARM-CPU-6409 */
+ bic r0, r0, #(1 << 2) /* Disable static branch prediction */
+
+ orr r0, r0, #(1 << 5) /* STREX backoff disable */
+ orr r0, r0, #(1 << 8) /* Internal parity handling disable */
+ orr r0, r0, #(1 << 16) /* Disable data transfer for clean line */
+ mcr p15, 1, r0, c15, c1, 1
+
+ /* Set Auxiliary Function Modes Control 0 register */
+ mrc p15, 1, r0, c15, c2, 0
+#if defined(SMP)
+ orr r0, r0, #(1 << 1) /* SMP/nAMP enabled (coherency) */
+#endif
+ orr r0, r0, #(1 << 2) /* L1 parite enable */
+ orr r0, r0, #(1 << 8) /* Cache and TLB maintenance broadcast enable */
+ mcr p15, 1, r0, c15, c2, 0
+
+ /* Set Auxiliary Debug Modes Control 2 register */
+ mrc p15, 1, r0, c15, c1, 2
+ bic r0, r0, #(1 << 23) /* Enable fast LDR */
+ orr r0, r0, #(1 << 25) /* Intervention Interleave disable */
+ orr r0, r0, #(1 << 27) /* Critical word first sequencing disable */
+ orr r0, r0, #(1 << 29) /* Disable MO device read / write */
+ orr r0, r0, #(1 << 30) /* L1 cache strict round-robin replacement policy*/
+ orr r0, r0, #(1 << 31) /* Enable write evict */
+ mcr p15, 1, r0, c15, c1, 2
+#if defined(SMP)
+ /* Set SMP mode in Auxiliary Control Register */
+ mrc p15, 0, r0, c1, c0, 1
+ orr r0, r0, #(1 << 5)
+ mcr p15, 0, r0, c1, c0, 1
+#endif
+
+ /* Load CPU number */
+ mrc p15, 0, r0, c0, c0, 5
+ and r0, r0, #0xf
+
+ /* SF Enable and invalidate */
+ ldr r1, .Lpj4b_sf_ctrl_reg
+ ldr r2, [r1, r0, lsl #8]
+ orr r2, r2, #(1 << 0)
+ bic r2, r2, #(1 << 8)
+ str r2, [r1, r0, lsl #8]
+
+ RET
+END(pj4b_config)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_pj4b.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_sheeva.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_sheeva.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_sheeva.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,422 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/armreg.h>
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_sheeva.S 278613 2015-02-12 03:50:33Z ian $");
+
+#include <machine/param.h>
+
+.Lsheeva_cache_line_size:
+ .word _C_LABEL(arm_pdcache_line_size)
+.Lsheeva_asm_page_mask:
+ .word _C_LABEL(PAGE_MASK)
+
+ENTRY(sheeva_setttb)
+ /* Disable irqs */
+ mrs r2, cpsr
+ orr r3, r2, #PSR_I | PSR_F
+ msr cpsr_c, r3
+
+ mov r1, #0
+ mcr p15, 0, r1, c7, c5, 0 /* Invalidate ICache */
+1: mrc p15, 0, r15, c7, c14, 3 /* Test, clean and invalidate DCache */
+ bne 1b /* More to do? */
+
+ mcr p15, 1, r1, c15, c9, 0 /* Clean L2 */
+ mcr p15, 1, r1, c15, c11, 0 /* Invalidate L2 */
+
+ /* Reenable irqs */
+ msr cpsr_c, r2
+
+ mcr p15, 0, r1, c7, c10, 4 /* drain the write buffer */
+
+ mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
+
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ RET
+END(sheeva_setttb)
+
+ENTRY(sheeva_dcache_wbinv_range)
+ str lr, [sp, #-4]!
+ mrs lr, cpsr
+ /* Start with cache line aligned address */
+ ldr ip, .Lsheeva_cache_line_size
+ ldr ip, [ip]
+ sub ip, ip, #1
+ and r2, r0, ip
+ add r1, r1, r2
+ add r1, r1, ip
+ bics r1, r1, ip
+ bics r0, r0, ip
+
+ ldr ip, .Lsheeva_asm_page_mask
+ and r2, r0, ip
+ rsb r2, r2, #PAGE_SIZE
+ cmp r1, r2
+ movcc ip, r1
+ movcs ip, r2
+1:
+ add r3, r0, ip
+ sub r2, r3, #1
+ /* Disable irqs */
+ orr r3, lr, #PSR_I | PSR_F
+ msr cpsr_c, r3
+ mcr p15, 5, r0, c15, c15, 0 /* Clean and inv zone start address */
+ mcr p15, 5, r2, c15, c15, 1 /* Clean and inv zone end address */
+ /* Enable irqs */
+ msr cpsr_c, lr
+
+ add r0, r0, ip
+ sub r1, r1, ip
+ cmp r1, #PAGE_SIZE
+ movcc ip, r1
+ movcs ip, #PAGE_SIZE
+ cmp r1, #0
+ bne 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ ldr lr, [sp], #4
+ RET
+END(sheeva_dcache_wbinv_range)
+
+ENTRY(sheeva_idcache_wbinv_range)
+ str lr, [sp, #-4]!
+ mrs lr, cpsr
+ /* Start with cache line aligned address */
+ ldr ip, .Lsheeva_cache_line_size
+ ldr ip, [ip]
+ sub ip, ip, #1
+ and r2, r0, ip
+ add r1, r1, r2
+ add r1, r1, ip
+ bics r1, r1, ip
+ bics r0, r0, ip
+
+ ldr ip, .Lsheeva_asm_page_mask
+ and r2, r0, ip
+ rsb r2, r2, #PAGE_SIZE
+ cmp r1, r2
+ movcc ip, r1
+ movcs ip, r2
+1:
+ add r3, r0, ip
+ sub r2, r3, #1
+ /* Disable irqs */
+ orr r3, lr, #PSR_I | PSR_F
+ msr cpsr_c, r3
+ mcr p15, 5, r0, c15, c15, 0 /* Clean and inv zone start address */
+ mcr p15, 5, r2, c15, c15, 1 /* Clean and inv zone end address */
+ /* Enable irqs */
+ msr cpsr_c, lr
+
+ /* Invalidate and clean icache line by line */
+ ldr r3, .Lsheeva_cache_line_size
+ ldr r3, [r3]
+2:
+ mcr p15, 0, r0, c7, c5, 1
+ add r0, r0, r3
+ cmp r2, r0
+ bhi 2b
+
+ add r0, r2, #1
+ sub r1, r1, ip
+ cmp r1, #PAGE_SIZE
+ movcc ip, r1
+ movcs ip, #PAGE_SIZE
+ cmp r1, #0
+ bne 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ ldr lr, [sp], #4
+ RET
+END(sheeva_idcache_wbinv_range)
+
+ENTRY(sheeva_dcache_inv_range)
+ str lr, [sp, #-4]!
+ mrs lr, cpsr
+ /* Start with cache line aligned address */
+ ldr ip, .Lsheeva_cache_line_size
+ ldr ip, [ip]
+ sub ip, ip, #1
+ and r2, r0, ip
+ add r1, r1, r2
+ add r1, r1, ip
+ bics r1, r1, ip
+ bics r0, r0, ip
+
+ ldr ip, .Lsheeva_asm_page_mask
+ and r2, r0, ip
+ rsb r2, r2, #PAGE_SIZE
+ cmp r1, r2
+ movcc ip, r1
+ movcs ip, r2
+1:
+ add r3, r0, ip
+ sub r2, r3, #1
+ /* Disable irqs */
+ orr r3, lr, #PSR_I | PSR_F
+ msr cpsr_c, r3
+ mcr p15, 5, r0, c15, c14, 0 /* Inv zone start address */
+ mcr p15, 5, r2, c15, c14, 1 /* Inv zone end address */
+ /* Enable irqs */
+ msr cpsr_c, lr
+
+ add r0, r0, ip
+ sub r1, r1, ip
+ cmp r1, #PAGE_SIZE
+ movcc ip, r1
+ movcs ip, #PAGE_SIZE
+ cmp r1, #0
+ bne 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ ldr lr, [sp], #4
+ RET
+END(sheeva_dcache_inv_range)
+
+ENTRY(sheeva_dcache_wb_range)
+ str lr, [sp, #-4]!
+ mrs lr, cpsr
+ /* Start with cache line aligned address */
+ ldr ip, .Lsheeva_cache_line_size
+ ldr ip, [ip]
+ sub ip, ip, #1
+ and r2, r0, ip
+ add r1, r1, r2
+ add r1, r1, ip
+ bics r1, r1, ip
+ bics r0, r0, ip
+
+ ldr ip, .Lsheeva_asm_page_mask
+ and r2, r0, ip
+ rsb r2, r2, #PAGE_SIZE
+ cmp r1, r2
+ movcc ip, r1
+ movcs ip, r2
+1:
+ add r3, r0, ip
+ sub r2, r3, #1
+ /* Disable irqs */
+ orr r3, lr, #PSR_I | PSR_F
+ msr cpsr_c, r3
+ mcr p15, 5, r0, c15, c13, 0 /* Clean zone start address */
+ mcr p15, 5, r2, c15, c13, 1 /* Clean zone end address */
+ /* Enable irqs */
+ msr cpsr_c, lr
+
+ add r0, r0, ip
+ sub r1, r1, ip
+ cmp r1, #PAGE_SIZE
+ movcc ip, r1
+ movcs ip, #PAGE_SIZE
+ cmp r1, #0
+ bne 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ ldr lr, [sp], #4
+ RET
+END(sheeva_dcache_wb_range)
+
+ENTRY(sheeva_l2cache_wbinv_range)
+ str lr, [sp, #-4]!
+ mrs lr, cpsr
+ /* Start with cache line aligned address */
+ ldr ip, .Lsheeva_cache_line_size
+ ldr ip, [ip]
+ sub ip, ip, #1
+ and r2, r0, ip
+ add r1, r1, r2
+ add r1, r1, ip
+ bics r1, r1, ip
+ bics r0, r0, ip
+
+ ldr ip, .Lsheeva_asm_page_mask
+ and r2, r0, ip
+ rsb r2, r2, #PAGE_SIZE
+ cmp r1, r2
+ movcc ip, r1
+ movcs ip, r2
+1:
+ add r3, r0, ip
+ sub r2, r3, #1
+ /* Disable irqs */
+ orr r3, lr, #PSR_I | PSR_F
+ msr cpsr_c, r3
+ mcr p15, 1, r0, c15, c9, 4 /* Clean L2 zone start address */
+ mcr p15, 1, r2, c15, c9, 5 /* Clean L2 zone end address */
+ mcr p15, 1, r0, c15, c11, 4 /* Inv L2 zone start address */
+ mcr p15, 1, r2, c15, c11, 5 /* Inv L2 zone end address */
+ /* Enable irqs */
+ msr cpsr_c, lr
+
+ add r0, r0, ip
+ sub r1, r1, ip
+ cmp r1, #PAGE_SIZE
+ movcc ip, r1
+ movcs ip, #PAGE_SIZE
+ cmp r1, #0
+ bne 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ ldr lr, [sp], #4
+ RET
+END(sheeva_l2cache_wbinv_range)
+
+ENTRY(sheeva_l2cache_inv_range)
+ str lr, [sp, #-4]!
+ mrs lr, cpsr
+ /* Start with cache line aligned address */
+ ldr ip, .Lsheeva_cache_line_size
+ ldr ip, [ip]
+ sub ip, ip, #1
+ and r2, r0, ip
+ add r1, r1, r2
+ add r1, r1, ip
+ bics r1, r1, ip
+ bics r0, r0, ip
+
+ ldr ip, .Lsheeva_asm_page_mask
+ and r2, r0, ip
+ rsb r2, r2, #PAGE_SIZE
+ cmp r1, r2
+ movcc ip, r1
+ movcs ip, r2
+1:
+ add r3, r0, ip
+ sub r2, r3, #1
+ /* Disable irqs */
+ orr r3, lr, #PSR_I | PSR_F
+ msr cpsr_c, r3
+ mcr p15, 1, r0, c15, c11, 4 /* Inv L2 zone start address */
+ mcr p15, 1, r2, c15, c11, 5 /* Inv L2 zone end address */
+ /* Enable irqs */
+ msr cpsr_c, lr
+
+ add r0, r0, ip
+ sub r1, r1, ip
+ cmp r1, #PAGE_SIZE
+ movcc ip, r1
+ movcs ip, #PAGE_SIZE
+ cmp r1, #0
+ bne 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ ldr lr, [sp], #4
+ RET
+END(sheeva_l2cache_inv_range)
+
+ENTRY(sheeva_l2cache_wb_range)
+ str lr, [sp, #-4]!
+ mrs lr, cpsr
+ /* Start with cache line aligned address */
+ ldr ip, .Lsheeva_cache_line_size
+ ldr ip, [ip]
+ sub ip, ip, #1
+ and r2, r0, ip
+ add r1, r1, r2
+ add r1, r1, ip
+ bics r1, r1, ip
+ bics r0, r0, ip
+
+ ldr ip, .Lsheeva_asm_page_mask
+ and r2, r0, ip
+ rsb r2, r2, #PAGE_SIZE
+ cmp r1, r2
+ movcc ip, r1
+ movcs ip, r2
+1:
+ add r3, r0, ip
+ sub r2, r3, #1
+ /* Disable irqs */
+ orr r3, lr, #PSR_I | PSR_F
+ msr cpsr_c, r3
+ mcr p15, 1, r0, c15, c9, 4 /* Clean L2 zone start address */
+ mcr p15, 1, r2, c15, c9, 5 /* Clean L2 zone end address */
+ /* Enable irqs */
+ msr cpsr_c, lr
+
+ add r0, r0, ip
+ sub r1, r1, ip
+ cmp r1, #PAGE_SIZE
+ movcc ip, r1
+ movcs ip, #PAGE_SIZE
+ cmp r1, #0
+ bne 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ ldr lr, [sp], #4
+ RET
+END(sheeva_l2cache_wb_range)
+
+ENTRY(sheeva_l2cache_wbinv_all)
+ /* Disable irqs */
+ mrs r1, cpsr
+ orr r2, r1, #PSR_I | PSR_F
+ msr cpsr_c, r2
+
+ mov r0, #0
+ mcr p15, 1, r0, c15, c9, 0 /* Clean L2 */
+ mcr p15, 1, r0, c15, c11, 0 /* Invalidate L2 */
+
+ msr cpsr_c, r1 /* Reenable irqs */
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
+ RET
+END(sheeva_l2cache_wbinv_all)
+
+/* This function modifies register value as follows:
+ *
+ * arg1 arg EFFECT (bit value saved into register)
+ * 0 0 not changed
+ * 0 1 negated
+ * 1 0 cleared
+ * 1 1 set
+ */
+ENTRY(sheeva_control_ext)
+ mrc p15, 1, r3, c15, c1, 0 /* Read the control register */
+ bic r2, r3, r0 /* Clear bits */
+ eor r2, r2, r1 /* XOR bits */
+
+ teq r2, r3 /* Only write if there is a change */
+ mcrne p15, 1, r2, c15, c1, 0 /* Write new control register */
+ mov r0, r3 /* Return old value */
+ RET
+END(sheeva_control_ext)
+
+ENTRY(sheeva_cpu_sleep)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 /* Drain write buffer */
+ mcr p15, 0, r0, c7, c0, 4 /* Wait for interrupt */
+ mov pc, lr
+END(sheeva_cpu_sleep)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_sheeva.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_xscale.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_xscale.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_xscale.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,524 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*-
+ * Copyright (c) 2001 Matt Thomas.
+ * Copyright (c) 1997,1998 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Causality Limited.
+ * 4. The name of Causality Limited may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * XScale assembly functions for CPU / MMU / TLB specific operations
+ */
+#include <machine/armreg.h>
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_xscale.S 278613 2015-02-12 03:50:33Z ian $");
+
+/*
+ * Size of the XScale core D-cache.
+ */
+#define DCACHE_SIZE 0x00008000
+
+.Lblock_userspace_access:
+ .word _C_LABEL(block_userspace_access)
+
+/*
+ * CPWAIT -- Canonical method to wait for CP15 update.
+ * From: Intel 80200 manual, section 2.3.3.
+ *
+ * NOTE: Clobbers the specified temp reg.
+ */
+#define CPWAIT_BRANCH \
+ sub pc, pc, #4
+
+#define CPWAIT(tmp) \
+ mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
+ mov tmp, tmp /* wait for it to complete */ ;\
+ CPWAIT_BRANCH /* branch to next insn */
+
+#define CPWAIT_AND_RETURN_SHIFTER lsr #32
+
+#define CPWAIT_AND_RETURN(tmp) \
+ mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
+ /* Wait for it to complete and branch to the return address */ \
+ sub pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER
+
+ENTRY(xscale_cpwait)
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cpwait)
+
+/*
+ * We need a separate cpu_control() entry point, since we have to
+ * invalidate the Branch Target Buffer in the event the BPRD bit
+ * changes in the control register.
+ */
+ENTRY(xscale_control)
+ mrc p15, 0, r3, c1, c0, 0 /* Read the control register */
+ bic r2, r3, r0 /* Clear bits */
+ eor r2, r2, r1 /* XOR bits */
+
+ teq r2, r3 /* Only write if there was a change */
+ mcrne p15, 0, r0, c7, c5, 6 /* Invalidate the BTB */
+ mcrne p15, 0, r2, c1, c0, 0 /* Write new control register */
+ mov r0, r3 /* Return old value */
+
+ CPWAIT_AND_RETURN(r1)
+END(xscale_control)
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(xscale_setttb)
+#ifdef CACHE_CLEAN_BLOCK_INTR
+ mrs r3, cpsr
+ orr r1, r3, #(PSR_I | PSR_F)
+ msr cpsr_fsxc, r1
+#else
+ ldr r3, .Lblock_userspace_access
+ ldr r2, [r3]
+ orr r1, r2, #1
+ str r1, [r3]
+#endif
+ stmfd sp!, {r0-r3, lr}
+ bl _C_LABEL(xscale_cache_cleanID)
+ mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */
+
+ CPWAIT(r0)
+
+ ldmfd sp!, {r0-r3, lr}
+
+ /* Write the TTB */
+ mcr p15, 0, r0, c2, c0, 0
+
+ /* If we have updated the TTB we must flush the TLB */
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */
+
+ /* The cleanID above means we only need to flush the I cache here */
+ mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */
+
+ CPWAIT(r0)
+
+#ifdef CACHE_CLEAN_BLOCK_INTR
+ msr cpsr_fsxc, r3
+#else
+ str r2, [r3]
+#endif
+ RET
+END(xscale_setttb)
+
+/*
+ * TLB functions
+ *
+ */
+ENTRY(xscale_tlb_flushID_SE)
+ mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
+ mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
+ CPWAIT_AND_RETURN(r0)
+END(xscale_tlb_flushID_SE)
+
+/*
+ * Cache functions
+ */
+ENTRY(xscale_cache_flushID)
+ mcr p15, 0, r0, c7, c7, 0 /* flush I+D cache */
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_flushID)
+
+ENTRY(xscale_cache_flushI)
+ mcr p15, 0, r0, c7, c5, 0 /* flush I cache */
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_flushI)
+
+ENTRY(xscale_cache_flushD)
+ mcr p15, 0, r0, c7, c6, 0 /* flush D cache */
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_flushD)
+
+ENTRY(xscale_cache_flushI_SE)
+ mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_flushI_SE)
+
+ENTRY(xscale_cache_flushD_SE)
+ /*
+ * Errata (rev < 2): Must clean-dcache-line to an address
+ * before invalidate-dcache-line to an address, or dirty
+ * bits will not be cleared in the dcache array.
+ */
+ mcr p15, 0, r0, c7, c10, 1
+ mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_flushD_SE)
+
+ENTRY(xscale_cache_cleanD_E)
+ mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_cleanD_E)
+
+/*
+ * Information for the XScale cache clean/purge functions:
+ *
+ * * Virtual address of the memory region to use
+ * * Size of memory region
+ *
+ * Note the virtual address for the Data cache clean operation
+ * does not need to be backed by physical memory, since no loads
+ * will actually be performed by the allocate-line operation.
+ *
+ * Note that the Mini-Data cache MUST be cleaned by executing
+ * loads from memory mapped into a region reserved exclusively
+ * for cleaning of the Mini-Data cache.
+ */
+ .data
+
+ .global _C_LABEL(xscale_cache_clean_addr)
+_C_LABEL(xscale_cache_clean_addr):
+ .word 0x00000000
+
+ .global _C_LABEL(xscale_cache_clean_size)
+_C_LABEL(xscale_cache_clean_size):
+ .word DCACHE_SIZE
+
+ .global _C_LABEL(xscale_minidata_clean_addr)
+_C_LABEL(xscale_minidata_clean_addr):
+ .word 0x00000000
+
+ .global _C_LABEL(xscale_minidata_clean_size)
+_C_LABEL(xscale_minidata_clean_size):
+ .word 0x00000800
+
+ .text
+
+.Lxscale_cache_clean_addr:
+ .word _C_LABEL(xscale_cache_clean_addr)
+.Lxscale_cache_clean_size:
+ .word _C_LABEL(xscale_cache_clean_size)
+
+.Lxscale_minidata_clean_addr:
+ .word _C_LABEL(xscale_minidata_clean_addr)
+.Lxscale_minidata_clean_size:
+ .word _C_LABEL(xscale_minidata_clean_size)
+
+#ifdef CACHE_CLEAN_BLOCK_INTR
+#define XSCALE_CACHE_CLEAN_BLOCK \
+ mrs r3, cpsr ; \
+ orr r0, r3, #(PSR_I | PSR_F) ; \
+ msr cpsr_fsxc, r0
+
+#define XSCALE_CACHE_CLEAN_UNBLOCK \
+ msr cpsr_fsxc, r3
+#else
+#define XSCALE_CACHE_CLEAN_BLOCK \
+ ldr r3, .Lblock_userspace_access ; \
+ ldr ip, [r3] ; \
+ orr r0, ip, #1 ; \
+ str r0, [r3]
+
+#define XSCALE_CACHE_CLEAN_UNBLOCK \
+ str ip, [r3]
+#endif /* CACHE_CLEAN_BLOCK_INTR */
+
+#define XSCALE_CACHE_CLEAN_PROLOGUE \
+ XSCALE_CACHE_CLEAN_BLOCK ; \
+ ldr r2, .Lxscale_cache_clean_addr ; \
+ ldmia r2, {r0, r1} ; \
+ /* \
+ * BUG ALERT! \
+ * \
+ * The XScale core has a strange cache eviction bug, which \
+ * requires us to use 2x the cache size for the cache clean \
+ * and for that area to be aligned to 2 * cache size. \
+ * \
+ * The work-around is to use 2 areas for cache clean, and to \
+ * alternate between them whenever this is done. No one knows \
+ * why the work-around works (mmm!). \
+ */ \
+ eor r0, r0, #(DCACHE_SIZE) ; \
+ str r0, [r2] ; \
+ add r0, r0, r1
+
+#define XSCALE_CACHE_CLEAN_EPILOGUE \
+ XSCALE_CACHE_CLEAN_UNBLOCK
+
+ENTRY_NP(xscale_cache_syncI)
+
+EENTRY_NP(xscale_cache_purgeID)
+ mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */
+EENTRY_NP(xscale_cache_cleanID)
+EENTRY_NP(xscale_cache_purgeD)
+EENTRY(xscale_cache_cleanD)
+ XSCALE_CACHE_CLEAN_PROLOGUE
+
+1: subs r0, r0, #32
+ mcr p15, 0, r0, c7, c2, 5 /* allocate cache line */
+ subs r1, r1, #32
+ bne 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT(r0)
+
+ XSCALE_CACHE_CLEAN_EPILOGUE
+ RET
+EEND(xscale_cache_cleanD)
+EEND(xscale_cache_purgeD)
+EEND(xscale_cache_cleanID)
+EEND(xscale_cache_purgeID)
+END(xscale_cache_syncI)
+
+/*
+ * Clean the mini-data cache.
+ *
+ * It's expected that we only use the mini-data cache for
+ * kernel addresses, so there is no need to purge it on
+ * context switch, and no need to prevent userspace access
+ * while we clean it.
+ */
+ENTRY(xscale_cache_clean_minidata)
+ ldr r2, .Lxscale_minidata_clean_addr
+ ldmia r2, {r0, r1}
+1: ldr r3, [r0], #32
+ subs r1, r1, #32
+ bne 1b
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r1)
+END(xscale_cache_clean_minidata)
+
+ENTRY(xscale_cache_purgeID_E)
+ mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
+ CPWAIT(r1)
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
+ mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
+ CPWAIT_AND_RETURN(r1)
+END(xscale_cache_purgeID_E)
+
+ENTRY(xscale_cache_purgeD_E)
+ mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
+ CPWAIT(r1)
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
+ CPWAIT_AND_RETURN(r1)
+END(xscale_cache_purgeD_E)
+
+/*
+ * Soft functions
+ */
+/* xscale_cache_syncI is identical to xscale_cache_purgeID */
+
+EENTRY(xscale_cache_cleanID_rng)
+ENTRY(xscale_cache_cleanD_rng)
+ cmp r1, #0x4000
+ bcs _C_LABEL(xscale_cache_cleanID)
+
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+/*END(xscale_cache_cleanID_rng)*/
+END(xscale_cache_cleanD_rng)
+
+ENTRY(xscale_cache_purgeID_rng)
+ cmp r1, #0x4000
+ bcs _C_LABEL(xscale_cache_purgeID)
+
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
+ mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
+ mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_purgeID_rng)
+
+ENTRY(xscale_cache_purgeD_rng)
+ cmp r1, #0x4000
+ bcs _C_LABEL(xscale_cache_purgeD)
+
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
+ mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_purgeD_rng)
+
+ENTRY(xscale_cache_syncI_rng)
+ cmp r1, #0x4000
+ bcs _C_LABEL(xscale_cache_syncI)
+
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
+ mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_syncI_rng)
+
+ENTRY(xscale_cache_flushD_rng)
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscale_cache_flushD_rng)
+
+/*
+ * Context switch.
+ *
+ * These is the CPU-specific parts of the context switcher cpu_switch()
+ * These functions actually perform the TTB reload.
+ *
+ * NOTE: Special calling convention
+ * r1, r4-r13 must be preserved
+ */
+ENTRY(xscale_context_switch)
+ /*
+ * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
+ * Thus the data cache will contain only kernel data and the
+ * instruction cache will contain only kernel code, and all
+ * kernel mappings are shared by all processes.
+ */
+
+ /* Write the TTB */
+ mcr p15, 0, r0, c2, c0, 0
+
+ /* If we have updated the TTB we must flush the TLB */
+ mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscale_context_switch)
+
+/*
+ * xscale_cpu_sleep
+ *
+ * This is called when there is nothing on any of the run queues.
+ * We go into IDLE mode so that any IRQ or FIQ will awaken us.
+ *
+ * If this is called with anything other than ARM_SLEEP_MODE_IDLE,
+ * ignore it.
+ */
+ENTRY(xscale_cpu_sleep)
+ tst r0, #0x00000000
+ bne 1f
+ mov r0, #0x1
+ mcr p14, 0, r0, c7, c0, 0
+
+1:
+ RET
+END(xscale_cpu_sleep)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_xscale.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpufunc_asm_xscale_c3.S
===================================================================
--- trunk/sys/arm/arm/cpufunc_asm_xscale_c3.S (rev 0)
+++ trunk/sys/arm/arm/cpufunc_asm_xscale_c3.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,417 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2007 Olivier Houchard
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*-
+ * Copyright (c) 2001 Matt Thomas.
+ * Copyright (c) 1997,1998 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Causality Limited.
+ * 4. The name of Causality Limited may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * XScale core 3 assembly functions for CPU / MMU / TLB specific operations
+ */
+
+#include <machine/armreg.h>
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpufunc_asm_xscale_c3.S 278613 2015-02-12 03:50:33Z ian $");
+
+/*
+ * Size of the XScale core D-cache.
+ */
+#define DCACHE_SIZE 0x00008000
+
+.Lblock_userspace_access:
+ .word _C_LABEL(block_userspace_access)
+
+/*
+ * CPWAIT -- Canonical method to wait for CP15 update.
+ * From: Intel 80200 manual, section 2.3.3.
+ *
+ * NOTE: Clobbers the specified temp reg.
+ */
+#define CPWAIT_BRANCH \
+ sub pc, pc, #4
+
+#define CPWAIT(tmp) \
+ mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
+ mov tmp, tmp /* wait for it to complete */ ;\
+ CPWAIT_BRANCH /* branch to next insn */
+
+#define CPWAIT_AND_RETURN_SHIFTER lsr #32
+
+#define CPWAIT_AND_RETURN(tmp) \
+ mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
+ /* Wait for it to complete and branch to the return address */ \
+ sub pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER
+
+#define ARM_USE_L2_CACHE
+
+#define L2_CACHE_SIZE 0x80000
+#define L2_CACHE_WAYS 8
+#define L2_CACHE_LINE_SIZE 32
+#define L2_CACHE_SETS (L2_CACHE_SIZE / \
+ (L2_CACHE_WAYS * L2_CACHE_LINE_SIZE))
+
+#define L1_DCACHE_SIZE 32 * 1024
+#define L1_DCACHE_WAYS 4
+#define L1_DCACHE_LINE_SIZE 32
+#define L1_DCACHE_SETS (L1_DCACHE_SIZE / \
+ (L1_DCACHE_WAYS * L1_DCACHE_LINE_SIZE))
+#ifdef CACHE_CLEAN_BLOCK_INTR
+#define XSCALE_CACHE_CLEAN_BLOCK \
+ stmfd sp!, {r4} ; \
+ mrs r4, cpsr ; \
+ orr r0, r4, #(PSR_I | PSR_F) ; \
+ msr cpsr_fsxc, r0
+
+#define XSCALE_CACHE_CLEAN_UNBLOCK \
+ msr cpsr_fsxc, r4 ; \
+ ldmfd sp!, {r4}
+#else
+#define XSCALE_CACHE_CLEAN_BLOCK \
+ stmfd sp!, {r4} ; \
+ ldr r4, .Lblock_userspace_access ; \
+ ldr ip, [r4] ; \
+ orr r0, ip, #1 ; \
+ str r0, [r4]
+
+#define XSCALE_CACHE_CLEAN_UNBLOCK \
+ str ip, [r3] ; \
+ ldmfd sp!, {r4}
+#endif /* CACHE_CLEAN_BLOCK_INTR */
+
+
+ENTRY_NP(xscalec3_cache_syncI)
+EENTRY_NP(xscalec3_cache_purgeID)
+ mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */
+EENTRY_NP(xscalec3_cache_cleanID)
+EENTRY_NP(xscalec3_cache_purgeD)
+EENTRY(xscalec3_cache_cleanD)
+
+ XSCALE_CACHE_CLEAN_BLOCK
+ mov r0, #0
+1:
+ mov r1, r0, asl #30
+ mov r2, #0
+2:
+ orr r3, r1, r2, asl #5
+ mcr p15, 0, r3, c7, c14, 2 /* clean and invalidate */
+ add r2, r2, #1
+ cmp r2, #L1_DCACHE_SETS
+ bne 2b
+ add r0, r0, #1
+ cmp r0, #4
+ bne 1b
+ CPWAIT(r0)
+ XSCALE_CACHE_CLEAN_UNBLOCK
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ RET
+EEND(xscalec3_cache_purgeID)
+EEND(xscalec3_cache_cleanID)
+EEND(xscalec3_cache_purgeD)
+EEND(xscalec3_cache_cleanD)
+END(xscalec3_cache_syncI)
+
+ENTRY(xscalec3_cache_purgeID_rng)
+
+ cmp r1, #0x4000
+ bcs _C_LABEL(xscalec3_cache_cleanID)
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c14, 1 /* clean/invalidate L1 D cache entry */
+ nop
+ mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscalec3_cache_purgeID_rng)
+
+ENTRY(xscalec3_cache_syncI_rng)
+ cmp r1, #0x4000
+ bcs _C_LABEL(xscalec3_cache_syncI)
+
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
+ mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscalec3_cache_syncI_rng)
+
+ENTRY(xscalec3_cache_purgeD_rng)
+
+ cmp r1, #0x4000
+ bcs _C_LABEL(xscalec3_cache_cleanID)
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c14, 1 /* Clean and invalidate D cache entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscalec3_cache_purgeD_rng)
+
+ENTRY(xscalec3_cache_cleanID_rng)
+EENTRY(xscalec3_cache_cleanD_rng)
+
+ cmp r1, #0x4000
+ bcs _C_LABEL(xscalec3_cache_cleanID)
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 0, r0, c7, c10, 1 /* clean L1 D cache entry */
+ nop
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+
+ CPWAIT_AND_RETURN(r0)
+EEND(xscalec3_cache_cleanD_rng)
+END(xscalec3_cache_cleanID_rng)
+
+ENTRY(xscalec3_l2cache_purge)
+ /* Clean-up the L2 cache */
+ mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
+ mov r0, #0
+1:
+ mov r1, r0, asl #29
+ mov r2, #0
+2:
+ orr r3, r1, r2, asl #5
+ mcr p15, 1, r3, c7, c15, 2
+ add r2, r2, #1
+ cmp r2, #L2_CACHE_SETS
+ bne 2b
+ add r0, r0, #1
+ cmp r0, #8
+ bne 1b
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+
+ CPWAIT(r0)
+ mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
+ RET
+END(xscalec3_l2cache_purge)
+
+ENTRY(xscalec3_l2cache_clean_rng)
+ mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
+
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 1, r0, c7, c11, 1 /* Clean L2 D cache entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+
+ CPWAIT(r0)
+
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+ mcr p15, 0, r0, c7, c10, 5
+
+ CPWAIT_AND_RETURN(r0)
+END(xscalec3_l2cache_clean_rng)
+
+ENTRY(xscalec3_l2cache_purge_rng)
+
+ mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
+
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 1, r0, c7, c11, 1 /* Clean L2 D cache entry */
+ mcr p15, 1, r0, c7, c7, 1 /* Invalidate L2 D cache entry */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+ mcr p15, 0, r0, c7, c10, 5
+
+ CPWAIT_AND_RETURN(r0)
+END(xscalec3_l2cache_purge_rng)
+
+ENTRY(xscalec3_l2cache_flush_rng)
+ mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */
+
+ and r2, r0, #0x1f
+ add r1, r1, r2
+ bic r0, r0, #0x1f
+
+1: mcr p15, 1, r0, c7, c7, 1 /* Invalidate L2 cache line */
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+ mcr p15, 0, r0, c7, c10, 5
+ CPWAIT_AND_RETURN(r0)
+END(xscalec3_l2cache_flush_rng)
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(xscalec3_setttb)
+#ifdef CACHE_CLEAN_BLOCK_INTR
+ mrs r3, cpsr
+ orr r1, r3, #(PSR_I | PSR_F)
+ msr cpsr_fsxc, r1
+#else
+ ldr r3, .Lblock_userspace_access
+ ldr r2, [r3]
+ orr r1, r2, #1
+ str r1, [r3]
+#endif
+ stmfd sp!, {r0-r3, lr}
+ bl _C_LABEL(xscalec3_cache_cleanID)
+ mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */
+ mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */
+
+ CPWAIT(r0)
+
+ ldmfd sp!, {r0-r3, lr}
+
+#ifdef ARM_USE_L2_CACHE
+ orr r0, r0, #0x18 /* cache the page table in L2 */
+#endif
+ /* Write the TTB */
+ mcr p15, 0, r0, c2, c0, 0
+
+ /* If we have updated the TTB we must flush the TLB */
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */
+
+ CPWAIT(r0)
+
+#ifdef CACHE_CLEAN_BLOCK_INTR
+ msr cpsr_fsxc, r3
+#else
+ str r2, [r3]
+#endif
+ RET
+END(xscalec3_setttb)
+
+/*
+ * Context switch.
+ *
+ * These is the CPU-specific parts of the context switcher cpu_switch()
+ * These functions actually perform the TTB reload.
+ *
+ * NOTE: Special calling convention
+ * r1, r4-r13 must be preserved
+ */
+ENTRY(xscalec3_context_switch)
+ /*
+ * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
+ * Thus the data cache will contain only kernel data and the
+ * instruction cache will contain only kernel code, and all
+ * kernel mappings are shared by all processes.
+ */
+#ifdef ARM_USE_L2_CACHE
+ orr r0, r0, #0x18 /* Cache the page table in L2 */
+#endif
+ /* Write the TTB */
+ mcr p15, 0, r0, c2, c0, 0
+
+ /* If we have updated the TTB we must flush the TLB */
+ mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */
+
+ CPWAIT_AND_RETURN(r0)
+END(xscalec3_context_switch)
+
Property changes on: trunk/sys/arm/arm/cpufunc_asm_xscale_c3.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/cpuinfo.c
===================================================================
--- trunk/sys/arm/arm/cpuinfo.c (rev 0)
+++ trunk/sys/arm/arm/cpuinfo.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,139 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Svatopluk Kraus <onwahe at gmail.com>
+ * Copyright 2014 Michal Meloun <meloun at miracle.cz>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/cpuinfo.c 283336 2015-05-23 23:05:31Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/cpuinfo.h>
+#include <machine/cpu-v6.h>
+
+struct cpuinfo cpuinfo =
+{
+ /* Use safe defaults for start */
+ .dcache_line_size = 32,
+ .dcache_line_mask = 31,
+ .icache_line_size = 32,
+ .icache_line_mask = 31,
+};
+
+/* Read and parse CPU id scheme */
+void
+cpuinfo_init(void)
+{
+
+ cpuinfo.midr = cp15_midr_get();
+ /* Test old version id schemes first */
+ if ((cpuinfo.midr & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD) {
+ if (CPU_ID_ISOLD(cpuinfo.midr)) {
+ /* obsolete ARMv2 or ARMv3 CPU */
+ cpuinfo.midr = 0;
+ return;
+ }
+ if (CPU_ID_IS7(cpuinfo.midr)) {
+ if ((cpuinfo.midr & (1 << 23)) == 0) {
+ /* obsolete ARMv3 CPU */
+ cpuinfo.midr = 0;
+ return;
+ }
+ /* ARMv4T CPU */
+ cpuinfo.architecture = 1;
+ cpuinfo.revision = (cpuinfo.midr >> 16) & 0x7F;
+ } else {
+ /* ARM new id scheme */
+ cpuinfo.architecture = (cpuinfo.midr >> 16) & 0x0F;
+ cpuinfo.revision = (cpuinfo.midr >> 20) & 0x0F;
+ }
+ } else {
+ /* non ARM -> must be new id scheme */
+ cpuinfo.architecture = (cpuinfo.midr >> 16) & 0x0F;
+ cpuinfo.revision = (cpuinfo.midr >> 20) & 0x0F;
+ }
+ /* Parse rest of MIDR */
+ cpuinfo.implementer = (cpuinfo.midr >> 24) & 0xFF;
+ cpuinfo.part_number = (cpuinfo.midr >> 4) & 0xFFF;
+ cpuinfo.patch = cpuinfo.midr & 0x0F;
+
+ /* CP15 c0,c0 regs 0-7 exist on all CPUs (although aliased with MIDR) */
+ cpuinfo.ctr = cp15_ctr_get();
+ cpuinfo.tcmtr = cp15_tcmtr_get();
+ cpuinfo.tlbtr = cp15_tlbtr_get();
+ cpuinfo.mpidr = cp15_mpidr_get();
+ cpuinfo.revidr = cp15_revidr_get();
+
+ /* if CPU is not v7 cpu id scheme */
+ if (cpuinfo.architecture != 0xF)
+ return;
+
+ cpuinfo.id_pfr0 = cp15_id_pfr0_get();
+ cpuinfo.id_pfr1 = cp15_id_pfr1_get();
+ cpuinfo.id_dfr0 = cp15_id_dfr0_get();
+ cpuinfo.id_afr0 = cp15_id_afr0_get();
+ cpuinfo.id_mmfr0 = cp15_id_mmfr0_get();
+ cpuinfo.id_mmfr1 = cp15_id_mmfr1_get();
+ cpuinfo.id_mmfr2 = cp15_id_mmfr2_get();
+ cpuinfo.id_mmfr3 = cp15_id_mmfr3_get();
+ cpuinfo.id_isar0 = cp15_id_isar0_get();
+ cpuinfo.id_isar1 = cp15_id_isar1_get();
+ cpuinfo.id_isar2 = cp15_id_isar2_get();
+ cpuinfo.id_isar3 = cp15_id_isar3_get();
+ cpuinfo.id_isar4 = cp15_id_isar4_get();
+ cpuinfo.id_isar5 = cp15_id_isar5_get();
+
+/* Not yet - CBAR only exist on ARM SMP Cortex A CPUs
+ cpuinfo.cbar = cp15_cbar_get();
+*/
+
+ /* Test if revidr is implemented */
+ if (cpuinfo.revidr == cpuinfo.midr)
+ cpuinfo.revidr = 0;
+
+ /* parsed bits of above registers */
+ /* id_mmfr0 */
+ cpuinfo.outermost_shareability = (cpuinfo.id_mmfr0 >> 8) & 0xF;
+ cpuinfo.shareability_levels = (cpuinfo.id_mmfr0 >> 12) & 0xF;
+ cpuinfo.auxiliary_registers = (cpuinfo.id_mmfr0 >> 20) & 0xF;
+ cpuinfo.innermost_shareability = (cpuinfo.id_mmfr0 >> 28) & 0xF;
+ /* id_mmfr2 */
+ cpuinfo.mem_barrier = (cpuinfo.id_mmfr2 >> 20) & 0xF;
+ /* id_mmfr3 */
+ cpuinfo.coherent_walk = (cpuinfo.id_mmfr3 >> 20) & 0xF;
+ cpuinfo.maintenance_broadcast =(cpuinfo.id_mmfr3 >> 12) & 0xF;
+ /* id_pfr1 */
+ cpuinfo.generic_timer_ext = (cpuinfo.id_pfr1 >> 16) & 0xF;
+ cpuinfo.virtualization_ext = (cpuinfo.id_pfr1 >> 12) & 0xF;
+ cpuinfo.security_ext = (cpuinfo.id_pfr1 >> 4) & 0xF;
+
+ /* L1 Cache sizes */
+ cpuinfo.dcache_line_size = 1 << (CPU_CT_DMINLINE(cpuinfo.ctr ) + 2);
+ cpuinfo.dcache_line_mask = cpuinfo.dcache_line_size - 1;
+ cpuinfo.icache_line_size= 1 << (CPU_CT_IMINLINE(cpuinfo.ctr ) + 2);
+ cpuinfo.icache_line_mask = cpuinfo.icache_line_size - 1;
+}
Property changes on: trunk/sys/arm/arm/cpuinfo.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/db_disasm.c
===================================================================
--- trunk/sys/arm/arm/db_disasm.c (rev 0)
+++ trunk/sys/arm/arm/db_disasm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,80 @@
+/* $MidnightBSD$ */
+/* $NetBSD: db_disasm.c,v 1.4 2003/07/15 00:24:38 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) 1996 Brini.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/db_disasm.c 236991 2012-06-13 04:59:55Z imp $");
+#include <sys/param.h>
+#include <machine/db_machdep.h>
+#include <ddb/ddb.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+
+#include <machine/disassem.h>
+
+/* Glue code to interface db_disasm to the generic ARM disassembler */
+
+static u_int db_disasm_read_word(u_int);
+static void db_disasm_printaddr(u_int);
+
+static const disasm_interface_t db_disasm_interface = {
+ db_disasm_read_word,
+ db_disasm_printaddr,
+ db_printf
+};
+
+static u_int
+db_disasm_read_word(u_int address)
+{
+
+ return db_get_value(address, 4, 0);
+}
+
+static void
+db_disasm_printaddr(u_int address)
+{
+
+ db_printsym((db_addr_t)address, DB_STGY_ANY);
+}
+
+vm_offset_t
+db_disasm(vm_offset_t loc, boolean_t altfmt)
+{
+
+ return disasm(&db_disasm_interface, loc, altfmt);
+}
+
+/* End of db_disasm.c */
Property changes on: trunk/sys/arm/arm/db_disasm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/db_interface.c
===================================================================
--- trunk/sys/arm/arm/db_interface.c (rev 0)
+++ trunk/sys/arm/arm/db_interface.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,388 @@
+/* $MidnightBSD$ */
+/* $NetBSD: db_interface.c,v 1.33 2003/08/25 04:51:10 mrg Exp $ */
+
+/*-
+ * Copyright (c) 1996 Scott K. Stevens
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
+ */
+
+/*
+ * Interface to new debugger.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/db_interface.c 236991 2012-06-13 04:59:55Z imp $");
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/systm.h> /* just for boothowto */
+#include <sys/exec.h>
+#ifdef KDB
+#include <sys/kdb.h>
+#endif
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+#include <machine/db_machdep.h>
+#include <machine/vmparam.h>
+#include <machine/cpu.h>
+
+#include <ddb/ddb.h>
+#include <ddb/db_access.h>
+#include <ddb/db_command.h>
+#include <ddb/db_output.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_sym.h>
+#include <sys/cons.h>
+
+static int nil = 0;
+
+int db_access_und_sp (struct db_variable *, db_expr_t *, int);
+int db_access_abt_sp (struct db_variable *, db_expr_t *, int);
+int db_access_irq_sp (struct db_variable *, db_expr_t *, int);
+
+static db_varfcn_t db_frame;
+
+#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
+struct db_variable db_regs[] = {
+ { "spsr", DB_OFFSET(tf_spsr), db_frame },
+ { "r0", DB_OFFSET(tf_r0), db_frame },
+ { "r1", DB_OFFSET(tf_r1), db_frame },
+ { "r2", DB_OFFSET(tf_r2), db_frame },
+ { "r3", DB_OFFSET(tf_r3), db_frame },
+ { "r4", DB_OFFSET(tf_r4), db_frame },
+ { "r5", DB_OFFSET(tf_r5), db_frame },
+ { "r6", DB_OFFSET(tf_r6), db_frame },
+ { "r7", DB_OFFSET(tf_r7), db_frame },
+ { "r8", DB_OFFSET(tf_r8), db_frame },
+ { "r9", DB_OFFSET(tf_r9), db_frame },
+ { "r10", DB_OFFSET(tf_r10), db_frame },
+ { "r11", DB_OFFSET(tf_r11), db_frame },
+ { "r12", DB_OFFSET(tf_r12), db_frame },
+ { "usr_sp", DB_OFFSET(tf_usr_sp), db_frame },
+ { "usr_lr", DB_OFFSET(tf_usr_lr), db_frame },
+ { "svc_sp", DB_OFFSET(tf_svc_sp), db_frame },
+ { "svc_lr", DB_OFFSET(tf_svc_lr), db_frame },
+ { "pc", DB_OFFSET(tf_pc), db_frame },
+ { "und_sp", &nil, db_access_und_sp, },
+ { "abt_sp", &nil, db_access_abt_sp, },
+ { "irq_sp", &nil, db_access_irq_sp, },
+};
+
+struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+
+int
+db_access_und_sp(struct db_variable *vp, db_expr_t *valp, int rw)
+{
+
+ if (rw == DB_VAR_GET) {
+ *valp = get_stackptr(PSR_UND32_MODE);
+ return (1);
+ }
+ return (0);
+}
+
+int
+db_access_abt_sp(struct db_variable *vp, db_expr_t *valp, int rw)
+{
+
+ if (rw == DB_VAR_GET) {
+ *valp = get_stackptr(PSR_ABT32_MODE);
+ return (1);
+ }
+ return (0);
+}
+
+int
+db_access_irq_sp(struct db_variable *vp, db_expr_t *valp, int rw)
+{
+
+ if (rw == DB_VAR_GET) {
+ *valp = get_stackptr(PSR_IRQ32_MODE);
+ return (1);
+ }
+ return (0);
+}
+
+int db_frame(struct db_variable *vp, db_expr_t *valp, int rw)
+{
+ int *reg;
+
+ if (kdb_frame == NULL)
+ return (0);
+
+ reg = (int *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
+ if (rw == DB_VAR_GET)
+ *valp = *reg;
+ else
+ *reg = *valp;
+ return (1);
+}
+
+void
+db_show_mdpcpu(struct pcpu *pc)
+{
+}
+int
+db_validate_address(vm_offset_t addr)
+{
+ struct proc *p = curproc;
+ struct pmap *pmap;
+
+ if (!p || !p->p_vmspace || !p->p_vmspace->vm_map.pmap ||
+#ifndef ARM32_NEW_VM_LAYOUT
+ addr >= VM_MAXUSER_ADDRESS
+#else
+ addr >= VM_MIN_KERNEL_ADDRESS
+#endif
+ )
+ pmap = pmap_kernel();
+ else
+ pmap = p->p_vmspace->vm_map.pmap;
+
+ return (pmap_extract(pmap, addr) == FALSE);
+}
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+int
+db_read_bytes(addr, size, data)
+ vm_offset_t addr;
+ size_t size;
+ char *data;
+{
+ char *src = (char *)addr;
+
+ if (db_validate_address((u_int)src)) {
+ db_printf("address %p is invalid\n", src);
+ return (-1);
+ }
+
+ if (size == 4 && (addr & 3) == 0 && ((uintptr_t)data & 3) == 0) {
+ *((int*)data) = *((int*)src);
+ return (0);
+ }
+
+ if (size == 2 && (addr & 1) == 0 && ((uintptr_t)data & 1) == 0) {
+ *((short*)data) = *((short*)src);
+ return (0);
+ }
+
+ while (size-- > 0) {
+ if (db_validate_address((u_int)src)) {
+ db_printf("address %p is invalid\n", src);
+ return (-1);
+ }
+ *data++ = *src++;
+ }
+ return (0);
+}
+
+/*
+ * Write bytes to kernel address space for debugger.
+ */
+int
+db_write_bytes(vm_offset_t addr, size_t size, char *data)
+{
+ char *dst;
+ size_t loop;
+
+ dst = (char *)addr;
+ if (db_validate_address((u_int)dst)) {
+ db_printf("address %p is invalid\n", dst);
+ return (0);
+ }
+
+ if (size == 4 && (addr & 3) == 0 && ((uintptr_t)data & 3) == 0)
+ *((int*)dst) = *((int*)data);
+ else
+ if (size == 2 && (addr & 1) == 0 && ((uintptr_t)data & 1) == 0)
+ *((short*)dst) = *((short*)data);
+ else {
+ loop = size;
+ while (loop-- > 0) {
+ if (db_validate_address((u_int)dst)) {
+ db_printf("address %p is invalid\n", dst);
+ return (-1);
+ }
+ *dst++ = *data++;
+ }
+ }
+
+ /* make sure the caches and memory are in sync */
+ cpu_icache_sync_range(addr, size);
+
+ /* In case the current page tables have been modified ... */
+ cpu_tlb_flushID();
+ cpu_cpwait();
+ return (0);
+}
+
+
+static u_int
+db_fetch_reg(int reg)
+{
+
+ switch (reg) {
+ case 0:
+ return (kdb_frame->tf_r0);
+ case 1:
+ return (kdb_frame->tf_r1);
+ case 2:
+ return (kdb_frame->tf_r2);
+ case 3:
+ return (kdb_frame->tf_r3);
+ case 4:
+ return (kdb_frame->tf_r4);
+ case 5:
+ return (kdb_frame->tf_r5);
+ case 6:
+ return (kdb_frame->tf_r6);
+ case 7:
+ return (kdb_frame->tf_r7);
+ case 8:
+ return (kdb_frame->tf_r8);
+ case 9:
+ return (kdb_frame->tf_r9);
+ case 10:
+ return (kdb_frame->tf_r10);
+ case 11:
+ return (kdb_frame->tf_r11);
+ case 12:
+ return (kdb_frame->tf_r12);
+ case 13:
+ return (kdb_frame->tf_svc_sp);
+ case 14:
+ return (kdb_frame->tf_svc_lr);
+ case 15:
+ return (kdb_frame->tf_pc);
+ default:
+ panic("db_fetch_reg: botch");
+ }
+}
+
+u_int
+branch_taken(u_int insn, db_addr_t pc)
+{
+ u_int addr, nregs, offset = 0;
+
+ switch ((insn >> 24) & 0xf) {
+ case 0x2: /* add pc, reg1, #value */
+ case 0x0: /* add pc, reg1, reg2, lsl #offset */
+ addr = db_fetch_reg((insn >> 16) & 0xf);
+ if (((insn >> 16) & 0xf) == 15)
+ addr += 8;
+ if (insn & 0x0200000) {
+ offset = (insn >> 7) & 0x1e;
+ offset = (insn & 0xff) << (32 - offset) |
+ (insn & 0xff) >> offset;
+ } else {
+
+ offset = db_fetch_reg(insn & 0x0f);
+ if ((insn & 0x0000ff0) != 0x00000000) {
+ if (insn & 0x10)
+ nregs = db_fetch_reg((insn >> 8) & 0xf);
+ else
+ nregs = (insn >> 7) & 0x1f;
+ switch ((insn >> 5) & 3) {
+ case 0:
+ /* lsl */
+ offset = offset << nregs;
+ break;
+ case 1:
+ /* lsr */
+ offset = offset >> nregs;
+ break;
+ default:
+ break; /* XXX */
+ }
+
+ }
+ return (addr + offset);
+
+ }
+
+ case 0xa: /* b ... */
+ case 0xb: /* bl ... */
+ addr = ((insn << 2) & 0x03ffffff);
+ if (addr & 0x02000000)
+ addr |= 0xfc000000;
+ return (pc + 8 + addr);
+ case 0x7: /* ldr pc, [pc, reg, lsl #2] */
+ addr = db_fetch_reg(insn & 0xf);
+ addr = pc + 8 + (addr << 2);
+ db_read_bytes(addr, 4, (char *)&addr);
+ return (addr);
+ case 0x1: /* mov pc, reg */
+ addr = db_fetch_reg(insn & 0xf);
+ return (addr);
+ case 0x4:
+ case 0x5: /* ldr pc, [reg] */
+ addr = db_fetch_reg((insn >> 16) & 0xf);
+ /* ldr pc, [reg, #offset] */
+ if (insn & (1 << 24))
+ offset = insn & 0xfff;
+ if (insn & 0x00800000)
+ addr += offset;
+ else
+ addr -= offset;
+ db_read_bytes(addr, 4, (char *)&addr);
+ return (addr);
+ case 0x8: /* ldmxx reg, {..., pc} */
+ case 0x9:
+ addr = db_fetch_reg((insn >> 16) & 0xf);
+ nregs = (insn & 0x5555) + ((insn >> 1) & 0x5555);
+ nregs = (nregs & 0x3333) + ((nregs >> 2) & 0x3333);
+ nregs = (nregs + (nregs >> 4)) & 0x0f0f;
+ nregs = (nregs + (nregs >> 8)) & 0x001f;
+ switch ((insn >> 23) & 0x3) {
+ case 0x0: /* ldmda */
+ addr = addr - 0;
+ break;
+ case 0x1: /* ldmia */
+ addr = addr + 0 + ((nregs - 1) << 2);
+ break;
+ case 0x2: /* ldmdb */
+ addr = addr - 4;
+ break;
+ case 0x3: /* ldmib */
+ addr = addr + 4 + ((nregs - 1) << 2);
+ break;
+ }
+ db_read_bytes(addr, 4, (char *)&addr);
+ return (addr);
+ default:
+ panic("branch_taken: botch");
+ }
+}
Property changes on: trunk/sys/arm/arm/db_interface.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/db_trace.c
===================================================================
--- trunk/sys/arm/arm/db_trace.c (rev 0)
+++ trunk/sys/arm/arm/db_trace.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,643 @@
+/* $MidnightBSD$ */
+/* $NetBSD: db_trace.c,v 1.8 2003/01/17 22:28:48 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2000, 2001 Ben Harris
+ * Copyright (c) 1996 Scott K. Stevens
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/db_trace.c 278614 2015-02-12 04:15:55Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+
+#include <sys/proc.h>
+#include <sys/kdb.h>
+#include <sys/stack.h>
+#include <machine/armreg.h>
+#include <machine/asm.h>
+#include <machine/cpufunc.h>
+#include <machine/db_machdep.h>
+#include <machine/pcb.h>
+#include <machine/stack.h>
+#include <machine/vmparam.h>
+#include <ddb/ddb.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_output.h>
+
+#ifdef __ARM_EABI__
+/*
+ * Definitions for the instruction interpreter.
+ *
+ * The ARM EABI specifies how to perform the frame unwinding in the
+ * Exception Handling ABI for the ARM Architecture document. To perform
+ * the unwind we need to know the initial frame pointer, stack pointer,
+ * link register and program counter. We then find the entry within the
+ * index table that points to the function the program counter is within.
+ * This gives us either a list of three instructions to process, a 31-bit
+ * relative offset to a table of instructions, or a value telling us
+ * we can't unwind any further.
+ *
+ * When we have the instructions to process we need to decode them
+ * following table 4 in section 9.3. This describes a collection of bit
+ * patterns to encode that steps to take to update the stack pointer and
+ * link register to the correct values at the start of the function.
+ */
+
+/* A special case when we are unable to unwind past this function */
+#define EXIDX_CANTUNWIND 1
+
+/* The register names */
+#define FP 11
+#define SP 13
+#define LR 14
+#define PC 15
+
+/*
+ * These are set in the linker script. Their addresses will be
+ * either the start or end of the exception table or index.
+ */
+extern int extab_start, extab_end, exidx_start, exidx_end;
+
+/*
+ * Entry types.
+ * These are the only entry types that have been seen in the kernel.
+ */
+#define ENTRY_MASK 0xff000000
+#define ENTRY_ARM_SU16 0x80000000
+#define ENTRY_ARM_LU16 0x81000000
+
+/* Instruction masks. */
+#define INSN_VSP_MASK 0xc0
+#define INSN_VSP_SIZE_MASK 0x3f
+#define INSN_STD_MASK 0xf0
+#define INSN_STD_DATA_MASK 0x0f
+#define INSN_POP_TYPE_MASK 0x08
+#define INSN_POP_COUNT_MASK 0x07
+#define INSN_VSP_LARGE_INC_MASK 0xff
+
+/* Instruction definitions */
+#define INSN_VSP_INC 0x00
+#define INSN_VSP_DEC 0x40
+#define INSN_POP_MASKED 0x80
+#define INSN_VSP_REG 0x90
+#define INSN_POP_COUNT 0xa0
+#define INSN_FINISH 0xb0
+#define INSN_POP_REGS 0xb1
+#define INSN_VSP_LARGE_INC 0xb2
+
+/* An item in the exception index table */
+struct unwind_idx {
+ uint32_t offset;
+ uint32_t insn;
+};
+
+/* The state of the unwind process */
+struct unwind_state {
+ uint32_t registers[16];
+ uint32_t start_pc;
+ uint32_t *insn;
+ u_int entries;
+ u_int byte;
+ uint16_t update_mask;
+};
+
+/* Expand a 31-bit signed value to a 32-bit signed value */
+static __inline int32_t
+db_expand_prel31(uint32_t prel31)
+{
+
+ return ((int32_t)(prel31 & 0x7fffffffu) << 1) / 2;
+}
+
+/*
+ * Perform a binary search of the index table to find the function
+ * with the largest address that doesn't exceed addr.
+ */
+static struct unwind_idx *
+db_find_index(uint32_t addr)
+{
+ unsigned int min, mid, max;
+ struct unwind_idx *start;
+ struct unwind_idx *item;
+ int32_t prel31_addr;
+ uint32_t func_addr;
+
+ start = (struct unwind_idx *)&exidx_start;
+
+ min = 0;
+ max = (&exidx_end - &exidx_start) / 2;
+
+ while (min != max) {
+ mid = min + (max - min + 1) / 2;
+
+ item = &start[mid];
+
+ prel31_addr = db_expand_prel31(item->offset);
+ func_addr = (uint32_t)&item->offset + prel31_addr;
+
+ if (func_addr <= addr) {
+ min = mid;
+ } else {
+ max = mid - 1;
+ }
+ }
+
+ return &start[min];
+}
+
+/* Reads the next byte from the instruction list */
+static uint8_t
+db_unwind_exec_read_byte(struct unwind_state *state)
+{
+ uint8_t insn;
+
+ /* Read the unwind instruction */
+ insn = (*state->insn) >> (state->byte * 8);
+
+ /* Update the location of the next instruction */
+ if (state->byte == 0) {
+ state->byte = 3;
+ state->insn++;
+ state->entries--;
+ } else
+ state->byte--;
+
+ return insn;
+}
+
+/* Executes the next instruction on the list */
+static int
+db_unwind_exec_insn(struct unwind_state *state)
+{
+ unsigned int insn;
+ uint32_t *vsp = (uint32_t *)state->registers[SP];
+ int update_vsp = 0;
+
+ /* This should never happen */
+ if (state->entries == 0)
+ return 1;
+
+ /* Read the next instruction */
+ insn = db_unwind_exec_read_byte(state);
+
+ if ((insn & INSN_VSP_MASK) == INSN_VSP_INC) {
+ state->registers[SP] += ((insn & INSN_VSP_SIZE_MASK) << 2) + 4;
+
+ } else if ((insn & INSN_VSP_MASK) == INSN_VSP_DEC) {
+ state->registers[SP] -= ((insn & INSN_VSP_SIZE_MASK) << 2) + 4;
+
+ } else if ((insn & INSN_STD_MASK) == INSN_POP_MASKED) {
+ unsigned int mask, reg;
+
+ /* Load the mask */
+ mask = db_unwind_exec_read_byte(state);
+ mask |= (insn & INSN_STD_DATA_MASK) << 8;
+
+ /* We have a refuse to unwind instruction */
+ if (mask == 0)
+ return 1;
+
+ /* Update SP */
+ update_vsp = 1;
+
+ /* Load the registers */
+ for (reg = 4; mask && reg < 16; mask >>= 1, reg++) {
+ if (mask & 1) {
+ state->registers[reg] = *vsp++;
+ state->update_mask |= 1 << reg;
+
+ /* If we have updated SP kep its value */
+ if (reg == SP)
+ update_vsp = 0;
+ }
+ }
+
+ } else if ((insn & INSN_STD_MASK) == INSN_VSP_REG &&
+ ((insn & INSN_STD_DATA_MASK) != 13) &&
+ ((insn & INSN_STD_DATA_MASK) != 15)) {
+ /* sp = register */
+ state->registers[SP] =
+ state->registers[insn & INSN_STD_DATA_MASK];
+
+ } else if ((insn & INSN_STD_MASK) == INSN_POP_COUNT) {
+ unsigned int count, reg;
+
+ /* Read how many registers to load */
+ count = insn & INSN_POP_COUNT_MASK;
+
+ /* Update sp */
+ update_vsp = 1;
+
+ /* Pop the registers */
+ for (reg = 4; reg <= 4 + count; reg++) {
+ state->registers[reg] = *vsp++;
+ state->update_mask |= 1 << reg;
+ }
+
+ /* Check if we are in the pop r14 version */
+ if ((insn & INSN_POP_TYPE_MASK) != 0) {
+ state->registers[14] = *vsp++;
+ }
+
+ } else if (insn == INSN_FINISH) {
+ /* Stop processing */
+ state->entries = 0;
+
+ } else if (insn == INSN_POP_REGS) {
+ unsigned int mask, reg;
+
+ mask = db_unwind_exec_read_byte(state);
+ if (mask == 0 || (mask & 0xf0) != 0)
+ return 1;
+
+ /* Update SP */
+ update_vsp = 1;
+
+ /* Load the registers */
+ for (reg = 0; mask && reg < 4; mask >>= 1, reg++) {
+ if (mask & 1) {
+ state->registers[reg] = *vsp++;
+ state->update_mask |= 1 << reg;
+ }
+ }
+
+ } else if ((insn & INSN_VSP_LARGE_INC_MASK) == INSN_VSP_LARGE_INC) {
+ unsigned int uleb128;
+
+ /* Read the increment value */
+ uleb128 = db_unwind_exec_read_byte(state);
+
+ state->registers[SP] += 0x204 + (uleb128 << 2);
+
+ } else {
+ /* We hit a new instruction that needs to be implemented */
+ db_printf("Unhandled instruction %.2x\n", insn);
+ return 1;
+ }
+
+ if (update_vsp) {
+ state->registers[SP] = (uint32_t)vsp;
+ }
+
+#if 0
+ db_printf("fp = %08x, sp = %08x, lr = %08x, pc = %08x\n",
+ state->registers[FP], state->registers[SP], state->registers[LR],
+ state->registers[PC]);
+#endif
+
+ return 0;
+}
+
+/* Performs the unwind of a function */
+static int
+db_unwind_tab(struct unwind_state *state)
+{
+ uint32_t entry;
+
+ /* Set PC to a known value */
+ state->registers[PC] = 0;
+
+ /* Read the personality */
+ entry = *state->insn & ENTRY_MASK;
+
+ if (entry == ENTRY_ARM_SU16) {
+ state->byte = 2;
+ state->entries = 1;
+ } else if (entry == ENTRY_ARM_LU16) {
+ state->byte = 1;
+ state->entries = ((*state->insn >> 16) & 0xFF) + 1;
+ } else {
+ db_printf("Unknown entry: %x\n", entry);
+ return 1;
+ }
+
+ while (state->entries > 0) {
+ if (db_unwind_exec_insn(state) != 0)
+ return 1;
+ }
+
+ /*
+ * The program counter was not updated, load it from the link register.
+ */
+ if (state->registers[PC] == 0)
+ state->registers[PC] = state->registers[LR];
+
+ return 0;
+}
+
+static void
+db_stack_trace_cmd(struct unwind_state *state)
+{
+ struct unwind_idx *index;
+ const char *name;
+ db_expr_t value;
+ db_expr_t offset;
+ c_db_sym_t sym;
+ u_int reg, i;
+ char *sep;
+ uint16_t upd_mask;
+ bool finished;
+
+ finished = false;
+ while (!finished) {
+ /* Reset the mask of updated registers */
+ state->update_mask = 0;
+
+ /* The pc value is correct and will be overwritten, save it */
+ state->start_pc = state->registers[PC];
+
+ /* Find the item to run */
+ index = db_find_index(state->start_pc);
+
+ if (index->insn != EXIDX_CANTUNWIND) {
+ if (index->insn & (1U << 31)) {
+ /* The data is within the instruction */
+ state->insn = &index->insn;
+ } else {
+ /* A prel31 offset to the unwind table */
+ state->insn = (uint32_t *)
+ ((uintptr_t)&index->insn +
+ db_expand_prel31(index->insn));
+ }
+ /* Run the unwind function */
+ finished = db_unwind_tab(state);
+ }
+
+ /* Print the frame details */
+ sym = db_search_symbol(state->start_pc, DB_STGY_ANY, &offset);
+ if (sym == C_DB_SYM_NULL) {
+ value = 0;
+ name = "(null)";
+ } else
+ db_symbol_values(sym, &name, &value);
+ db_printf("%s() at ", name);
+ db_printsym(state->start_pc, DB_STGY_PROC);
+ db_printf("\n");
+ db_printf("\t pc = 0x%08x lr = 0x%08x (", state->start_pc,
+ state->registers[LR]);
+ db_printsym(state->registers[LR], DB_STGY_PROC);
+ db_printf(")\n");
+ db_printf("\t sp = 0x%08x fp = 0x%08x",
+ state->registers[SP], state->registers[FP]);
+
+ /* Don't print the registers we have already printed */
+ upd_mask = state->update_mask &
+ ~((1 << SP) | (1 << FP) | (1 << LR) | (1 << PC));
+ sep = "\n\t";
+ for (i = 0, reg = 0; upd_mask != 0; upd_mask >>= 1, reg++) {
+ if ((upd_mask & 1) != 0) {
+ db_printf("%s%sr%d = 0x%08x", sep,
+ (reg < 10) ? " " : "", reg,
+ state->registers[reg]);
+ i++;
+ if (i == 2) {
+ sep = "\n\t";
+ i = 0;
+ } else
+ sep = " ";
+
+ }
+ }
+ db_printf("\n");
+
+ /*
+ * Stop if directed to do so, or if we've unwound back to the
+ * kernel entry point, or if the unwind function didn't change
+ * anything (to avoid getting stuck in this loop forever).
+ * If the latter happens, it's an indication that the unwind
+ * information is incorrect somehow for the function named in
+ * the last frame printed before you see the unwind failure
+ * message (maybe it needs a STOP_UNWINDING).
+ */
+ if (index->insn == EXIDX_CANTUNWIND) {
+ db_printf("Unable to unwind further\n");
+ finished = true;
+ } else if (state->registers[PC] < VM_MIN_KERNEL_ADDRESS) {
+ db_printf("Unable to unwind into user mode\n");
+ finished = true;
+ } else if (state->update_mask == 0) {
+ db_printf("Unwind failure (no registers changed)\n");
+ finished = true;
+ }
+ }
+}
+#endif
+
+/*
+ * APCS stack frames are awkward beasts, so I don't think even trying to use
+ * a structure to represent them is a good idea.
+ *
+ * Here's the diagram from the APCS. Increasing address is _up_ the page.
+ *
+ * save code pointer [fp] <- fp points to here
+ * return link value [fp, #-4]
+ * return sp value [fp, #-8]
+ * return fp value [fp, #-12]
+ * [saved v7 value]
+ * [saved v6 value]
+ * [saved v5 value]
+ * [saved v4 value]
+ * [saved v3 value]
+ * [saved v2 value]
+ * [saved v1 value]
+ * [saved a4 value]
+ * [saved a3 value]
+ * [saved a2 value]
+ * [saved a1 value]
+ *
+ * The save code pointer points twelve bytes beyond the start of the
+ * code sequence (usually a single STM) that created the stack frame.
+ * We have to disassemble it if we want to know which of the optional
+ * fields are actually present.
+ */
+
+#ifndef __ARM_EABI__ /* The frame format is differend in AAPCS */
+static void
+db_stack_trace_cmd(db_expr_t addr, db_expr_t count, boolean_t kernel_only)
+{
+ u_int32_t *frame, *lastframe;
+ c_db_sym_t sym;
+ const char *name;
+ db_expr_t value;
+ db_expr_t offset;
+ int scp_offset;
+
+ frame = (u_int32_t *)addr;
+ lastframe = NULL;
+ scp_offset = -(get_pc_str_offset() >> 2);
+
+ while (count-- && frame != NULL && !db_pager_quit) {
+ db_addr_t scp;
+ u_int32_t savecode;
+ int r;
+ u_int32_t *rp;
+ const char *sep;
+
+ /*
+ * In theory, the SCP isn't guaranteed to be in the function
+ * that generated the stack frame. We hope for the best.
+ */
+ scp = frame[FR_SCP];
+
+ sym = db_search_symbol(scp, DB_STGY_ANY, &offset);
+ if (sym == C_DB_SYM_NULL) {
+ value = 0;
+ name = "(null)";
+ } else
+ db_symbol_values(sym, &name, &value);
+ db_printf("%s() at ", name);
+ db_printsym(scp, DB_STGY_PROC);
+ db_printf("\n");
+#ifdef __PROG26
+ db_printf("\tscp=0x%08x rlv=0x%08x (", scp, frame[FR_RLV] & R15_PC);
+ db_printsym(frame[FR_RLV] & R15_PC, DB_STGY_PROC);
+ db_printf(")\n");
+#else
+ db_printf("\tscp=0x%08x rlv=0x%08x (", scp, frame[FR_RLV]);
+ db_printsym(frame[FR_RLV], DB_STGY_PROC);
+ db_printf(")\n");
+#endif
+ db_printf("\trsp=0x%08x rfp=0x%08x", frame[FR_RSP], frame[FR_RFP]);
+
+ savecode = ((u_int32_t *)scp)[scp_offset];
+ if ((savecode & 0x0e100000) == 0x08000000) {
+ /* Looks like an STM */
+ rp = frame - 4;
+ sep = "\n\t";
+ for (r = 10; r >= 0; r--) {
+ if (savecode & (1 << r)) {
+ db_printf("%sr%d=0x%08x",
+ sep, r, *rp--);
+ sep = (frame - rp) % 4 == 2 ?
+ "\n\t" : " ";
+ }
+ }
+ }
+
+ db_printf("\n");
+
+ /*
+ * Switch to next frame up
+ */
+ if (frame[FR_RFP] == 0)
+ break; /* Top of stack */
+
+ lastframe = frame;
+ frame = (u_int32_t *)(frame[FR_RFP]);
+
+ if (INKERNEL((int)frame)) {
+ /* staying in kernel */
+ if (frame <= lastframe) {
+ db_printf("Bad frame pointer: %p\n", frame);
+ break;
+ }
+ } else if (INKERNEL((int)lastframe)) {
+ /* switch from user to kernel */
+ if (kernel_only)
+ break; /* kernel stack only */
+ } else {
+ /* in user */
+ if (frame <= lastframe) {
+ db_printf("Bad user frame pointer: %p\n",
+ frame);
+ break;
+ }
+ }
+ }
+}
+#endif
+
+/* XXX stubs */
+void
+db_md_list_watchpoints()
+{
+}
+
+int
+db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
+{
+ return (0);
+}
+
+int
+db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
+{
+ return (0);
+}
+
+int
+db_trace_thread(struct thread *thr, int count)
+{
+#ifdef __ARM_EABI__
+ struct unwind_state state;
+#endif
+ struct pcb *ctx;
+
+ if (thr != curthread) {
+ ctx = kdb_thr_ctx(thr);
+
+#ifdef __ARM_EABI__
+ state.registers[FP] = ctx->pcb_regs.sf_r11;
+ state.registers[SP] = ctx->pcb_regs.sf_sp;
+ state.registers[LR] = ctx->pcb_regs.sf_lr;
+ state.registers[PC] = ctx->pcb_regs.sf_pc;
+
+ db_stack_trace_cmd(&state);
+#else
+ db_stack_trace_cmd(ctx->pcb_regs.sf_r11, -1, TRUE);
+#endif
+ } else
+ db_trace_self();
+ return (0);
+}
+
+void
+db_trace_self(void)
+{
+#ifdef __ARM_EABI__
+ struct unwind_state state;
+ uint32_t sp;
+
+ /* Read the stack pointer */
+ __asm __volatile("mov %0, sp" : "=&r" (sp));
+
+ state.registers[FP] = (uint32_t)__builtin_frame_address(0);
+ state.registers[SP] = sp;
+ state.registers[LR] = (uint32_t)__builtin_return_address(0);
+ state.registers[PC] = (uint32_t)db_trace_self;
+
+ db_stack_trace_cmd(&state);
+#else
+ db_addr_t addr;
+
+ addr = (db_addr_t)__builtin_frame_address(0);
+ db_stack_trace_cmd(addr, -1, FALSE);
+#endif
+}
Property changes on: trunk/sys/arm/arm/db_trace.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/devmap.c
===================================================================
--- trunk/sys/arm/arm/devmap.c (rev 0)
+++ trunk/sys/arm/arm/devmap.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,311 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/devmap.c 266086 2014-05-14 20:17:31Z ian $");
+
+/*
+ * Routines for mapping device memory.
+ */
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+#include <machine/armreg.h>
+#include <machine/devmap.h>
+
+static const struct arm_devmap_entry *devmap_table;
+static boolean_t devmap_bootstrap_done = false;
+
+/*
+ * The allocated-kva (akva) devmap table and metadata. Platforms can call
+ * arm_devmap_add_entry() to add static device mappings to this table using
+ * automatically allocated virtual addresses carved out of the top of kva space.
+ * Allocation begins immediately below the ARM_VECTORS_HIGH address.
+ */
+#define AKVA_DEVMAP_MAX_ENTRIES 32
+static struct arm_devmap_entry akva_devmap_entries[AKVA_DEVMAP_MAX_ENTRIES];
+static u_int akva_devmap_idx;
+static vm_offset_t akva_devmap_vaddr = ARM_VECTORS_HIGH;
+
+/*
+ * Print the contents of the static mapping table using the provided printf-like
+ * output function (which will be either printf or db_printf).
+ */
+static void
+devmap_dump_table(int (*prfunc)(const char *, ...))
+{
+ const struct arm_devmap_entry *pd;
+
+ if (devmap_table == NULL || devmap_table[0].pd_size == 0) {
+ prfunc("No static device mappings.\n");
+ return;
+ }
+
+ prfunc("Static device mappings:\n");
+ for (pd = devmap_table; pd->pd_size != 0; ++pd) {
+ prfunc(" 0x%08x - 0x%08x mapped at VA 0x%08x\n",
+ pd->pd_pa, pd->pd_pa + pd->pd_size - 1, pd->pd_va);
+ }
+}
+
+/*
+ * Print the contents of the static mapping table. Used for bootverbose.
+ */
+void
+arm_devmap_print_table()
+{
+ devmap_dump_table(printf);
+}
+
+/*
+ * Return the "last" kva address used by the registered devmap table. It's
+ * actually the lowest address used by the static mappings, i.e., the address of
+ * the first unusable byte of KVA.
+ */
+vm_offset_t
+arm_devmap_lastaddr()
+{
+ const struct arm_devmap_entry *pd;
+ vm_offset_t lowaddr;
+
+ if (akva_devmap_idx > 0)
+ return (akva_devmap_vaddr);
+
+ lowaddr = ARM_VECTORS_HIGH;
+ for (pd = devmap_table; pd != NULL && pd->pd_size != 0; ++pd) {
+ if (lowaddr > pd->pd_va)
+ lowaddr = pd->pd_va;
+ }
+
+ return (lowaddr);
+}
+
+/*
+ * Add an entry to the internal "akva" static devmap table using the given
+ * physical address and size and a virtual address allocated from the top of
+ * kva. This automatically registers the akva table on the first call, so all a
+ * platform has to do is call this routine to install as many mappings as it
+ * needs and when initarm() calls arm_devmap_bootstrap() it will pick up all the
+ * entries in the akva table automatically.
+ */
+void
+arm_devmap_add_entry(vm_paddr_t pa, vm_size_t sz)
+{
+ struct arm_devmap_entry *m;
+
+ if (devmap_bootstrap_done)
+ panic("arm_devmap_add_entry() after arm_devmap_bootstrap()");
+
+ if (akva_devmap_idx == (AKVA_DEVMAP_MAX_ENTRIES - 1))
+ panic("AKVA_DEVMAP_MAX_ENTRIES is too small");
+
+ if (akva_devmap_idx == 0)
+ arm_devmap_register_table(akva_devmap_entries);
+
+ /*
+ * Allocate virtual address space from the top of kva downwards. If the
+ * range being mapped is aligned and sized to 1MB boundaries then also
+ * align the virtual address to the next-lower 1MB boundary so that we
+ * end up with a nice efficient section mapping.
+ */
+ if ((pa & 0x000fffff) == 0 && (sz & 0x000fffff) == 0) {
+ akva_devmap_vaddr = trunc_1mpage(akva_devmap_vaddr - sz);
+ } else {
+ akva_devmap_vaddr = trunc_page(akva_devmap_vaddr - sz);
+ }
+ m = &akva_devmap_entries[akva_devmap_idx++];
+ m->pd_va = akva_devmap_vaddr;
+ m->pd_pa = pa;
+ m->pd_size = sz;
+ m->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ m->pd_cache = PTE_DEVICE;
+}
+
+/*
+ * Register the given table as the one to use in arm_devmap_bootstrap().
+ */
+void
+arm_devmap_register_table(const struct arm_devmap_entry *table)
+{
+
+ devmap_table = table;
+}
+
+/*
+ * Map all of the static regions in the devmap table, and remember the devmap
+ * table so the mapdev, ptov, and vtop functions can do lookups later.
+ *
+ * If a non-NULL table pointer is given it is used unconditionally, otherwise
+ * the previously-registered table is used. This smooths transition from legacy
+ * code that fills in a local table then calls this function passing that table,
+ * and newer code that uses arm_devmap_register_table() in platform-specific
+ * code, then lets the common initarm() call this function with a NULL pointer.
+ */
+void
+arm_devmap_bootstrap(vm_offset_t l1pt, const struct arm_devmap_entry *table)
+{
+ const struct arm_devmap_entry *pd;
+
+ devmap_bootstrap_done = true;
+
+ /*
+ * If given a table pointer, use it. Otherwise, if a table was
+ * previously registered, use it. Otherwise, no work to do.
+ */
+ if (table != NULL)
+ devmap_table = table;
+ else if (devmap_table == NULL)
+ return;
+
+ for (pd = devmap_table; pd->pd_size != 0; ++pd) {
+ pmap_map_chunk(l1pt, pd->pd_va, pd->pd_pa, pd->pd_size,
+ pd->pd_prot,pd->pd_cache);
+ }
+}
+
+/*
+ * Look up the given physical address in the static mapping data and return the
+ * corresponding virtual address, or NULL if not found.
+ */
+void *
+arm_devmap_ptov(vm_paddr_t pa, vm_size_t size)
+{
+ const struct arm_devmap_entry *pd;
+
+ if (devmap_table == NULL)
+ return (NULL);
+
+ for (pd = devmap_table; pd->pd_size != 0; ++pd) {
+ if (pa >= pd->pd_pa && pa + size <= pd->pd_pa + pd->pd_size)
+ return ((void *)(pd->pd_va + (pa - pd->pd_pa)));
+ }
+
+ return (NULL);
+}
+
+/*
+ * Look up the given virtual address in the static mapping data and return the
+ * corresponding physical address, or DEVMAP_PADDR_NOTFOUND if not found.
+ */
+vm_paddr_t
+arm_devmap_vtop(void * vpva, vm_size_t size)
+{
+ const struct arm_devmap_entry *pd;
+ vm_offset_t va;
+
+ if (devmap_table == NULL)
+ return (DEVMAP_PADDR_NOTFOUND);
+
+ va = (vm_offset_t)vpva;
+ for (pd = devmap_table; pd->pd_size != 0; ++pd) {
+ if (va >= pd->pd_va && va + size <= pd->pd_va + pd->pd_size)
+ return ((vm_paddr_t)(pd->pd_pa + (va - pd->pd_va)));
+ }
+
+ return (DEVMAP_PADDR_NOTFOUND);
+}
+
+/*
+ * Map a set of physical memory pages into the kernel virtual address space.
+ * Return a pointer to where it is mapped.
+ *
+ * This uses a pre-established static mapping if one exists for the requested
+ * range, otherwise it allocates kva space and maps the physical pages into it.
+ *
+ * This routine is intended to be used for mapping device memory, NOT real
+ * memory; the mapping type is inherently PTE_DEVICE in pmap_kenter_device().
+ */
+void *
+pmap_mapdev(vm_offset_t pa, vm_size_t size)
+{
+ vm_offset_t va, tmpva, offset;
+ void * rva;
+
+ /* First look in the static mapping table. */
+ if ((rva = arm_devmap_ptov(pa, size)) != NULL)
+ return (rva);
+
+ offset = pa & PAGE_MASK;
+ pa = trunc_page(pa);
+ size = round_page(size + offset);
+
+ va = kva_alloc(size);
+ if (!va)
+ panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
+
+ for (tmpva = va; size > 0;) {
+ pmap_kenter_device(tmpva, pa);
+ size -= PAGE_SIZE;
+ tmpva += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ }
+
+ return ((void *)(va + offset));
+}
+
+/*
+ * Unmap device memory and free the kva space.
+ */
+void
+pmap_unmapdev(vm_offset_t va, vm_size_t size)
+{
+ vm_offset_t tmpva, offset;
+ vm_size_t origsize;
+
+ /* Nothing to do if we find the mapping in the static table. */
+ if (arm_devmap_vtop((void*)va, size) != DEVMAP_PADDR_NOTFOUND)
+ return;
+
+ origsize = size;
+ offset = va & PAGE_MASK;
+ va = trunc_page(va);
+ size = round_page(size + offset);
+
+ for (tmpva = va; size > 0;) {
+ pmap_kremove(tmpva);
+ size -= PAGE_SIZE;
+ tmpva += PAGE_SIZE;
+ }
+
+ kva_free(va, origsize);
+}
+
+#ifdef DDB
+#include <ddb/ddb.h>
+
+DB_SHOW_COMMAND(devmap, db_show_devmap)
+{
+ devmap_dump_table(db_printf);
+}
+
+#endif /* DDB */
+
Property changes on: trunk/sys/arm/arm/devmap.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/disassem.c
===================================================================
--- trunk/sys/arm/arm/disassem.c (rev 0)
+++ trunk/sys/arm/arm/disassem.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,694 @@
+/* $MidnightBSD$ */
+/* $NetBSD: disassem.c,v 1.14 2003/03/27 16:58:36 mycroft Exp $ */
+
+/*-
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) 1996 Brini.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * db_disasm.c
+ *
+ * Kernel disassembler
+ *
+ * Created : 10/02/96
+ *
+ * Structured after the sparc/sparc/db_disasm.c by David S. Miller &
+ * Paul Kranenburg
+ *
+ * This code is not complete. Not all instructions are disassembled.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/disassem.c 279467 2015-03-01 01:08:14Z dim $");
+#include <sys/param.h>
+
+
+#include <sys/systm.h>
+#include <machine/disassem.h>
+#include <machine/armreg.h>
+#include <machine/acle-compat.h>
+#include <ddb/ddb.h>
+
+/*
+ * General instruction format
+ *
+ * insn[cc][mod] [operands]
+ *
+ * Those fields with an uppercase format code indicate that the field
+ * follows directly after the instruction before the separator i.e.
+ * they modify the instruction rather than just being an operand to
+ * the instruction. The only exception is the writeback flag which
+ * follows a operand.
+ *
+ *
+ * 2 - print Operand 2 of a data processing instruction
+ * d - destination register (bits 12-15)
+ * n - n register (bits 16-19)
+ * s - s register (bits 8-11)
+ * o - indirect register rn (bits 16-19) (used by swap)
+ * m - m register (bits 0-3)
+ * a - address operand of ldr/str instruction
+ * l - register list for ldm/stm instruction
+ * f - 1st fp operand (register) (bits 12-14)
+ * g - 2nd fp operand (register) (bits 16-18)
+ * h - 3rd fp operand (register/immediate) (bits 0-4)
+ * b - branch address
+ * t - thumb branch address (bits 24, 0-23)
+ * k - breakpoint comment (bits 0-3, 8-19)
+ * X - block transfer type
+ * Y - block transfer type (r13 base)
+ * c - comment field bits(0-23)
+ * p - saved or current status register
+ * F - PSR transfer fields
+ * D - destination-is-r15 (P) flag on TST, TEQ, CMP, CMN
+ * L - co-processor transfer size
+ * S - set status flag
+ * P - fp precision
+ * Q - fp precision (for ldf/stf)
+ * R - fp rounding
+ * v - co-processor data transfer registers + addressing mode
+ * W - writeback flag
+ * x - instruction in hex
+ * # - co-processor number
+ * y - co-processor data processing registers
+ * z - co-processor register transfer registers
+ */
+
+struct arm32_insn {
+ u_int mask;
+ u_int pattern;
+ char* name;
+ char* format;
+};
+
+static const struct arm32_insn arm32_i[] = {
+ { 0x0fffffff, 0x0ff00000, "imb", "c" }, /* Before swi */
+ { 0x0fffffff, 0x0ff00001, "imbrange", "c" }, /* Before swi */
+ { 0x0f000000, 0x0f000000, "swi", "c" },
+ { 0xfe000000, 0xfa000000, "blx", "t" }, /* Before b and bl */
+ { 0x0f000000, 0x0a000000, "b", "b" },
+ { 0x0f000000, 0x0b000000, "bl", "b" },
+ { 0x0fe000f0, 0x00000090, "mul", "Snms" },
+ { 0x0fe000f0, 0x00200090, "mla", "Snmsd" },
+ { 0x0fe000f0, 0x00800090, "umull", "Sdnms" },
+ { 0x0fe000f0, 0x00c00090, "smull", "Sdnms" },
+ { 0x0fe000f0, 0x00a00090, "umlal", "Sdnms" },
+ { 0x0fe000f0, 0x00e00090, "smlal", "Sdnms" },
+ { 0x0d700000, 0x04200000, "strt", "daW" },
+ { 0x0d700000, 0x04300000, "ldrt", "daW" },
+ { 0x0d700000, 0x04600000, "strbt", "daW" },
+ { 0x0d700000, 0x04700000, "ldrbt", "daW" },
+ { 0x0c500000, 0x04000000, "str", "daW" },
+ { 0x0c500000, 0x04100000, "ldr", "daW" },
+ { 0x0c500000, 0x04400000, "strb", "daW" },
+ { 0x0c500000, 0x04500000, "ldrb", "daW" },
+#if __ARM_ARCH >= 6
+ { 0xffffffff, 0xf57ff01f, "clrex", "c" },
+ { 0x0ff00ff0, 0x01800f90, "strex", "dmo" },
+ { 0x0ff00fff, 0x01900f9f, "ldrex", "do" },
+ { 0x0ff00ff0, 0x01a00f90, "strexd", "dmo" },
+ { 0x0ff00fff, 0x01b00f9f, "ldrexd", "do" },
+ { 0x0ff00ff0, 0x01c00f90, "strexb", "dmo" },
+ { 0x0ff00fff, 0x01d00f9f, "ldrexb", "do" },
+ { 0x0ff00ff0, 0x01e00f90, "strexh", "dmo" },
+ { 0x0ff00fff, 0x01f00f9f, "ldrexh", "do" },
+#endif
+ { 0x0e1f0000, 0x080d0000, "stm", "YnWl" },/* separate out r13 base */
+ { 0x0e1f0000, 0x081d0000, "ldm", "YnWl" },/* separate out r13 base */
+ { 0x0e100000, 0x08000000, "stm", "XnWl" },
+ { 0x0e100000, 0x08100000, "ldm", "XnWl" },
+ { 0x0e1000f0, 0x00100090, "ldrb", "de" },
+ { 0x0e1000f0, 0x00000090, "strb", "de" },
+ { 0x0e1000f0, 0x001000d0, "ldrsb", "de" },
+ { 0x0e1000f0, 0x001000b0, "ldrh", "de" },
+ { 0x0e1000f0, 0x000000b0, "strh", "de" },
+ { 0x0e1000f0, 0x001000f0, "ldrsh", "de" },
+ { 0x0f200090, 0x00200090, "und", "x" }, /* Before data processing */
+ { 0x0e1000d0, 0x000000d0, "und", "x" }, /* Before data processing */
+ { 0x0ff00ff0, 0x01000090, "swp", "dmo" },
+ { 0x0ff00ff0, 0x01400090, "swpb", "dmo" },
+ { 0x0fbf0fff, 0x010f0000, "mrs", "dp" }, /* Before data processing */
+ { 0x0fb0fff0, 0x0120f000, "msr", "pFm" },/* Before data processing */
+ { 0x0fb0f000, 0x0320f000, "msr", "pF2" },/* Before data processing */
+ { 0x0ffffff0, 0x012fff10, "bx", "m" },
+ { 0x0fff0ff0, 0x016f0f10, "clz", "dm" },
+ { 0x0ffffff0, 0x012fff30, "blx", "m" },
+ { 0xfff000f0, 0xe1200070, "bkpt", "k" },
+ { 0x0de00000, 0x00000000, "and", "Sdn2" },
+ { 0x0de00000, 0x00200000, "eor", "Sdn2" },
+ { 0x0de00000, 0x00400000, "sub", "Sdn2" },
+ { 0x0de00000, 0x00600000, "rsb", "Sdn2" },
+ { 0x0de00000, 0x00800000, "add", "Sdn2" },
+ { 0x0de00000, 0x00a00000, "adc", "Sdn2" },
+ { 0x0de00000, 0x00c00000, "sbc", "Sdn2" },
+ { 0x0de00000, 0x00e00000, "rsc", "Sdn2" },
+ { 0x0df00000, 0x01100000, "tst", "Dn2" },
+ { 0x0df00000, 0x01300000, "teq", "Dn2" },
+ { 0x0de00000, 0x01400000, "cmp", "Dn2" },
+ { 0x0de00000, 0x01600000, "cmn", "Dn2" },
+ { 0x0de00000, 0x01800000, "orr", "Sdn2" },
+ { 0x0de00000, 0x01a00000, "mov", "Sd2" },
+ { 0x0de00000, 0x01c00000, "bic", "Sdn2" },
+ { 0x0de00000, 0x01e00000, "mvn", "Sd2" },
+ { 0x0ff08f10, 0x0e000100, "adf", "PRfgh" },
+ { 0x0ff08f10, 0x0e100100, "muf", "PRfgh" },
+ { 0x0ff08f10, 0x0e200100, "suf", "PRfgh" },
+ { 0x0ff08f10, 0x0e300100, "rsf", "PRfgh" },
+ { 0x0ff08f10, 0x0e400100, "dvf", "PRfgh" },
+ { 0x0ff08f10, 0x0e500100, "rdf", "PRfgh" },
+ { 0x0ff08f10, 0x0e600100, "pow", "PRfgh" },
+ { 0x0ff08f10, 0x0e700100, "rpw", "PRfgh" },
+ { 0x0ff08f10, 0x0e800100, "rmf", "PRfgh" },
+ { 0x0ff08f10, 0x0e900100, "fml", "PRfgh" },
+ { 0x0ff08f10, 0x0ea00100, "fdv", "PRfgh" },
+ { 0x0ff08f10, 0x0eb00100, "frd", "PRfgh" },
+ { 0x0ff08f10, 0x0ec00100, "pol", "PRfgh" },
+ { 0x0f008f10, 0x0e000100, "fpbop", "PRfgh" },
+ { 0x0ff08f10, 0x0e008100, "mvf", "PRfh" },
+ { 0x0ff08f10, 0x0e108100, "mnf", "PRfh" },
+ { 0x0ff08f10, 0x0e208100, "abs", "PRfh" },
+ { 0x0ff08f10, 0x0e308100, "rnd", "PRfh" },
+ { 0x0ff08f10, 0x0e408100, "sqt", "PRfh" },
+ { 0x0ff08f10, 0x0e508100, "log", "PRfh" },
+ { 0x0ff08f10, 0x0e608100, "lgn", "PRfh" },
+ { 0x0ff08f10, 0x0e708100, "exp", "PRfh" },
+ { 0x0ff08f10, 0x0e808100, "sin", "PRfh" },
+ { 0x0ff08f10, 0x0e908100, "cos", "PRfh" },
+ { 0x0ff08f10, 0x0ea08100, "tan", "PRfh" },
+ { 0x0ff08f10, 0x0eb08100, "asn", "PRfh" },
+ { 0x0ff08f10, 0x0ec08100, "acs", "PRfh" },
+ { 0x0ff08f10, 0x0ed08100, "atn", "PRfh" },
+ { 0x0f008f10, 0x0e008100, "fpuop", "PRfh" },
+ { 0x0e100f00, 0x0c000100, "stf", "QLv" },
+ { 0x0e100f00, 0x0c100100, "ldf", "QLv" },
+ { 0x0ff00f10, 0x0e000110, "flt", "PRgd" },
+ { 0x0ff00f10, 0x0e100110, "fix", "PRdh" },
+ { 0x0ff00f10, 0x0e200110, "wfs", "d" },
+ { 0x0ff00f10, 0x0e300110, "rfs", "d" },
+ { 0x0ff00f10, 0x0e400110, "wfc", "d" },
+ { 0x0ff00f10, 0x0e500110, "rfc", "d" },
+ { 0x0ff0ff10, 0x0e90f110, "cmf", "PRgh" },
+ { 0x0ff0ff10, 0x0eb0f110, "cnf", "PRgh" },
+ { 0x0ff0ff10, 0x0ed0f110, "cmfe", "PRgh" },
+ { 0x0ff0ff10, 0x0ef0f110, "cnfe", "PRgh" },
+ { 0xff100010, 0xfe000010, "mcr2", "#z" },
+ { 0x0f100010, 0x0e000010, "mcr", "#z" },
+ { 0xff100010, 0xfe100010, "mrc2", "#z" },
+ { 0x0f100010, 0x0e100010, "mrc", "#z" },
+ { 0xff000010, 0xfe000000, "cdp2", "#y" },
+ { 0x0f000010, 0x0e000000, "cdp", "#y" },
+ { 0xfe100090, 0xfc100000, "ldc2", "L#v" },
+ { 0x0e100090, 0x0c100000, "ldc", "L#v" },
+ { 0xfe100090, 0xfc000000, "stc2", "L#v" },
+ { 0x0e100090, 0x0c000000, "stc", "L#v" },
+ { 0x00000000, 0x00000000, NULL, NULL }
+};
+
+static char const arm32_insn_conditions[][4] = {
+ "eq", "ne", "cs", "cc",
+ "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt",
+ "gt", "le", "", "nv"
+};
+
+static char const insn_block_transfers[][4] = {
+ "da", "ia", "db", "ib"
+};
+
+static char const insn_stack_block_transfers[][4] = {
+ "ed", "ea", "fd", "fa"
+};
+
+static char const op_shifts[][4] = {
+ "lsl", "lsr", "asr", "ror"
+};
+
+static char const insn_fpa_rounding[][2] = {
+ "", "p", "m", "z"
+};
+
+static char const insn_fpa_precision[][2] = {
+ "s", "d", "e", "p"
+};
+
+static char const insn_fpaconstants[][8] = {
+ "0.0", "1.0", "2.0", "3.0",
+ "4.0", "5.0", "0.5", "10.0"
+};
+
+#define insn_condition(x) arm32_insn_conditions[(x >> 28) & 0x0f]
+#define insn_blktrans(x) insn_block_transfers[(x >> 23) & 3]
+#define insn_stkblktrans(x) insn_stack_block_transfers[(x >> 23) & 3]
+#define op2_shift(x) op_shifts[(x >> 5) & 3]
+#define insn_fparnd(x) insn_fpa_rounding[(x >> 5) & 0x03]
+#define insn_fpaprec(x) insn_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 1]
+#define insn_fpaprect(x) insn_fpa_precision[(((x >> 21) & 2)|(x >> 15)) & 1]
+#define insn_fpaimm(x) insn_fpaconstants[x & 0x07]
+
+/* Local prototypes */
+static void disasm_register_shift(const disasm_interface_t *di, u_int insn);
+static void disasm_print_reglist(const disasm_interface_t *di, u_int insn);
+static void disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn,
+ u_int loc);
+static void disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn,
+ u_int loc);
+static void disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn,
+ u_int loc);
+static u_int disassemble_readword(u_int address);
+static void disassemble_printaddr(u_int address);
+
+vm_offset_t
+disasm(const disasm_interface_t *di, vm_offset_t loc, int altfmt)
+{
+ const struct arm32_insn *i_ptr = arm32_i;
+
+ u_int insn;
+ int matchp;
+ int branch;
+ char* f_ptr;
+ int fmt;
+
+ fmt = 0;
+ matchp = 0;
+ insn = di->di_readword(loc);
+
+/* di->di_printf("loc=%08x insn=%08x : ", loc, insn);*/
+
+ while (i_ptr->name) {
+ if ((insn & i_ptr->mask) == i_ptr->pattern) {
+ matchp = 1;
+ break;
+ }
+ i_ptr++;
+ }
+
+ if (!matchp) {
+ di->di_printf("und%s\t%08x\n", insn_condition(insn), insn);
+ return(loc + INSN_SIZE);
+ }
+
+ /* If instruction forces condition code, don't print it. */
+ if ((i_ptr->mask & 0xf0000000) == 0xf0000000)
+ di->di_printf("%s", i_ptr->name);
+ else
+ di->di_printf("%s%s", i_ptr->name, insn_condition(insn));
+
+ f_ptr = i_ptr->format;
+
+ /* Insert tab if there are no instruction modifiers */
+
+ if (*(f_ptr) < 'A' || *(f_ptr) > 'Z') {
+ ++fmt;
+ di->di_printf("\t");
+ }
+
+ while (*f_ptr) {
+ switch (*f_ptr) {
+ /* 2 - print Operand 2 of a data processing instruction */
+ case '2':
+ if (insn & 0x02000000) {
+ int rotate= ((insn >> 7) & 0x1e);
+
+ di->di_printf("#0x%08x",
+ (insn & 0xff) << (32 - rotate) |
+ (insn & 0xff) >> rotate);
+ } else {
+ disasm_register_shift(di, insn);
+ }
+ break;
+ /* d - destination register (bits 12-15) */
+ case 'd':
+ di->di_printf("r%d", ((insn >> 12) & 0x0f));
+ break;
+ /* D - insert 'p' if Rd is R15 */
+ case 'D':
+ if (((insn >> 12) & 0x0f) == 15)
+ di->di_printf("p");
+ break;
+ /* n - n register (bits 16-19) */
+ case 'n':
+ di->di_printf("r%d", ((insn >> 16) & 0x0f));
+ break;
+ /* s - s register (bits 8-11) */
+ case 's':
+ di->di_printf("r%d", ((insn >> 8) & 0x0f));
+ break;
+ /* o - indirect register rn (bits 16-19) (used by swap) */
+ case 'o':
+ di->di_printf("[r%d]", ((insn >> 16) & 0x0f));
+ break;
+ /* m - m register (bits 0-4) */
+ case 'm':
+ di->di_printf("r%d", ((insn >> 0) & 0x0f));
+ break;
+ /* a - address operand of ldr/str instruction */
+ case 'a':
+ disasm_insn_ldrstr(di, insn, loc);
+ break;
+ /* e - address operand of ldrh/strh instruction */
+ case 'e':
+ disasm_insn_ldrhstrh(di, insn, loc);
+ break;
+ /* l - register list for ldm/stm instruction */
+ case 'l':
+ disasm_print_reglist(di, insn);
+ break;
+ /* f - 1st fp operand (register) (bits 12-14) */
+ case 'f':
+ di->di_printf("f%d", (insn >> 12) & 7);
+ break;
+ /* g - 2nd fp operand (register) (bits 16-18) */
+ case 'g':
+ di->di_printf("f%d", (insn >> 16) & 7);
+ break;
+ /* h - 3rd fp operand (register/immediate) (bits 0-4) */
+ case 'h':
+ if (insn & (1 << 3))
+ di->di_printf("#%s", insn_fpaimm(insn));
+ else
+ di->di_printf("f%d", insn & 7);
+ break;
+ /* b - branch address */
+ case 'b':
+ branch = ((insn << 2) & 0x03ffffff);
+ if (branch & 0x02000000)
+ branch |= 0xfc000000;
+ di->di_printaddr(loc + 8 + branch);
+ break;
+ /* t - blx address */
+ case 't':
+ branch = ((insn << 2) & 0x03ffffff) |
+ (insn >> 23 & 0x00000002);
+ if (branch & 0x02000000)
+ branch |= 0xfc000000;
+ di->di_printaddr(loc + 8 + branch);
+ break;
+ /* X - block transfer type */
+ case 'X':
+ di->di_printf("%s", insn_blktrans(insn));
+ break;
+ /* Y - block transfer type (r13 base) */
+ case 'Y':
+ di->di_printf("%s", insn_stkblktrans(insn));
+ break;
+ /* c - comment field bits(0-23) */
+ case 'c':
+ di->di_printf("0x%08x", (insn & 0x00ffffff));
+ break;
+ /* k - breakpoint comment (bits 0-3, 8-19) */
+ case 'k':
+ di->di_printf("0x%04x",
+ (insn & 0x000fff00) >> 4 | (insn & 0x0000000f));
+ break;
+ /* p - saved or current status register */
+ case 'p':
+ if (insn & 0x00400000)
+ di->di_printf("spsr");
+ else
+ di->di_printf("cpsr");
+ break;
+ /* F - PSR transfer fields */
+ case 'F':
+ di->di_printf("_");
+ if (insn & (1 << 16))
+ di->di_printf("c");
+ if (insn & (1 << 17))
+ di->di_printf("x");
+ if (insn & (1 << 18))
+ di->di_printf("s");
+ if (insn & (1 << 19))
+ di->di_printf("f");
+ break;
+ /* B - byte transfer flag */
+ case 'B':
+ if (insn & 0x00400000)
+ di->di_printf("b");
+ break;
+ /* L - co-processor transfer size */
+ case 'L':
+ if (insn & (1 << 22))
+ di->di_printf("l");
+ break;
+ /* S - set status flag */
+ case 'S':
+ if (insn & 0x00100000)
+ di->di_printf("s");
+ break;
+ /* P - fp precision */
+ case 'P':
+ di->di_printf("%s", insn_fpaprec(insn));
+ break;
+ /* Q - fp precision (for ldf/stf) */
+ case 'Q':
+ break;
+ /* R - fp rounding */
+ case 'R':
+ di->di_printf("%s", insn_fparnd(insn));
+ break;
+ /* W - writeback flag */
+ case 'W':
+ if (insn & (1 << 21))
+ di->di_printf("!");
+ break;
+ /* # - co-processor number */
+ case '#':
+ di->di_printf("p%d", (insn >> 8) & 0x0f);
+ break;
+ /* v - co-processor data transfer registers+addressing mode */
+ case 'v':
+ disasm_insn_ldcstc(di, insn, loc);
+ break;
+ /* x - instruction in hex */
+ case 'x':
+ di->di_printf("0x%08x", insn);
+ break;
+ /* y - co-processor data processing registers */
+ case 'y':
+ di->di_printf("%d, ", (insn >> 20) & 0x0f);
+
+ di->di_printf("c%d, c%d, c%d", (insn >> 12) & 0x0f,
+ (insn >> 16) & 0x0f, insn & 0x0f);
+
+ di->di_printf(", %d", (insn >> 5) & 0x07);
+ break;
+ /* z - co-processor register transfer registers */
+ case 'z':
+ di->di_printf("%d, ", (insn >> 21) & 0x07);
+ di->di_printf("r%d, c%d, c%d, %d",
+ (insn >> 12) & 0x0f, (insn >> 16) & 0x0f,
+ insn & 0x0f, (insn >> 5) & 0x07);
+
+/* if (((insn >> 5) & 0x07) != 0)
+ di->di_printf(", %d", (insn >> 5) & 0x07);*/
+ break;
+ default:
+ di->di_printf("[%c - unknown]", *f_ptr);
+ break;
+ }
+ if (*(f_ptr+1) >= 'A' && *(f_ptr+1) <= 'Z')
+ ++f_ptr;
+ else if (*(++f_ptr)) {
+ ++fmt;
+ if (fmt == 1)
+ di->di_printf("\t");
+ else
+ di->di_printf(", ");
+ }
+ };
+
+ di->di_printf("\n");
+
+ return(loc + INSN_SIZE);
+}
+
+
+static void
+disasm_register_shift(const disasm_interface_t *di, u_int insn)
+{
+ di->di_printf("r%d", (insn & 0x0f));
+ if ((insn & 0x00000ff0) == 0)
+ ;
+ else if ((insn & 0x00000ff0) == 0x00000060)
+ di->di_printf(", rrx");
+ else {
+ if (insn & 0x10)
+ di->di_printf(", %s r%d", op2_shift(insn),
+ (insn >> 8) & 0x0f);
+ else
+ di->di_printf(", %s #%d", op2_shift(insn),
+ (insn >> 7) & 0x1f);
+ }
+}
+
+
+static void
+disasm_print_reglist(const disasm_interface_t *di, u_int insn)
+{
+ int loop;
+ int start;
+ int comma;
+
+ di->di_printf("{");
+ start = -1;
+ comma = 0;
+
+ for (loop = 0; loop < 17; ++loop) {
+ if (start != -1) {
+ if (loop == 16 || !(insn & (1 << loop))) {
+ if (comma)
+ di->di_printf(", ");
+ else
+ comma = 1;
+ if (start == loop - 1)
+ di->di_printf("r%d", start);
+ else
+ di->di_printf("r%d-r%d", start, loop - 1);
+ start = -1;
+ }
+ } else {
+ if (insn & (1 << loop))
+ start = loop;
+ }
+ }
+ di->di_printf("}");
+
+ if (insn & (1 << 22))
+ di->di_printf("^");
+}
+
+static void
+disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn, u_int loc)
+{
+ int offset;
+
+ offset = insn & 0xfff;
+ if ((insn & 0x032f0000) == 0x010f0000) {
+ /* rA = pc, immediate index */
+ if (insn & 0x00800000)
+ loc += offset;
+ else
+ loc -= offset;
+ di->di_printaddr(loc + 8);
+ } else {
+ di->di_printf("[r%d", (insn >> 16) & 0x0f);
+ if ((insn & 0x03000fff) != 0x01000000) {
+ di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
+ if (!(insn & 0x00800000))
+ di->di_printf("-");
+ if (insn & (1 << 25))
+ disasm_register_shift(di, insn);
+ else
+ di->di_printf("#0x%03x", offset);
+ }
+ if (insn & (1 << 24))
+ di->di_printf("]");
+ }
+}
+
+static void
+disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn, u_int loc)
+{
+ int offset;
+
+ offset = ((insn & 0xf00) >> 4) | (insn & 0xf);
+ if ((insn & 0x004f0000) == 0x004f0000) {
+ /* rA = pc, immediate index */
+ if (insn & 0x00800000)
+ loc += offset;
+ else
+ loc -= offset;
+ di->di_printaddr(loc + 8);
+ } else {
+ di->di_printf("[r%d", (insn >> 16) & 0x0f);
+ if ((insn & 0x01400f0f) != 0x01400000) {
+ di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
+ if (!(insn & 0x00800000))
+ di->di_printf("-");
+ if (insn & (1 << 22))
+ di->di_printf("#0x%02x", offset);
+ else
+ di->di_printf("r%d", (insn & 0x0f));
+ }
+ if (insn & (1 << 24))
+ di->di_printf("]");
+ }
+}
+
+static void
+disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, u_int loc)
+{
+ if (((insn >> 8) & 0xf) == 1)
+ di->di_printf("f%d, ", (insn >> 12) & 0x07);
+ else
+ di->di_printf("c%d, ", (insn >> 12) & 0x0f);
+
+ di->di_printf("[r%d", (insn >> 16) & 0x0f);
+
+ di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
+
+ if (!(insn & (1 << 23)))
+ di->di_printf("-");
+
+ di->di_printf("#0x%03x", (insn & 0xff) << 2);
+
+ if (insn & (1 << 24))
+ di->di_printf("]");
+
+ if (insn & (1 << 21))
+ di->di_printf("!");
+}
+
+static u_int
+disassemble_readword(u_int address)
+{
+ return(*((u_int *)address));
+}
+
+static void
+disassemble_printaddr(u_int address)
+{
+ printf("0x%08x", address);
+}
+
+static const disasm_interface_t disassemble_di = {
+ disassemble_readword, disassemble_printaddr, db_printf
+};
+
+void
+disassemble(u_int address)
+{
+
+ (void)disasm(&disassemble_di, address, 0);
+}
+
+/* End of disassem.c */
Property changes on: trunk/sys/arm/arm/disassem.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/dump_machdep.c
===================================================================
--- trunk/sys/arm/arm/dump_machdep.c (rev 0)
+++ trunk/sys/arm/arm/dump_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,410 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/dump_machdep.c 278614 2015-02-12 04:15:55Z ian $");
+
+#include "opt_watchdog.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/sysctl.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/kerneldump.h>
+#ifdef SW_WATCHDOG
+#include <sys/watchdog.h>
+#endif
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/elf.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/armreg.h>
+
+CTASSERT(sizeof(struct kerneldumpheader) == 512);
+
+int do_minidump = 1;
+TUNABLE_INT("debug.minidump", &do_minidump);
+SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RW, &do_minidump, 0,
+ "Enable mini crash dumps");
+
+/*
+ * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
+ * is to protect us from metadata and to protect metadata from us.
+ */
+#define SIZEOF_METADATA (64*1024)
+
+#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
+#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
+extern struct pcb dumppcb;
+
+struct md_pa {
+ vm_paddr_t md_start;
+ vm_paddr_t md_size;
+};
+
+typedef int callback_t(struct md_pa *, int, void *);
+
+static struct kerneldumpheader kdh;
+static off_t dumplo, fileofs;
+
+/* Handle buffered writes. */
+static char buffer[DEV_BSIZE];
+static size_t fragsz;
+
+/* XXX: I suppose 20 should be enough. */
+static struct md_pa dump_map[20];
+
+static void
+md_pa_init(void)
+{
+ int n, idx;
+
+ bzero(dump_map, sizeof(dump_map));
+ for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
+ idx = n * 2;
+ if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
+ break;
+ dump_map[n].md_start = dump_avail[idx];
+ dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
+ }
+}
+
+static struct md_pa *
+md_pa_first(void)
+{
+
+ return (&dump_map[0]);
+}
+
+static struct md_pa *
+md_pa_next(struct md_pa *mdp)
+{
+
+ mdp++;
+ if (mdp->md_size == 0)
+ mdp = NULL;
+ return (mdp);
+}
+
+static int
+buf_write(struct dumperinfo *di, char *ptr, size_t sz)
+{
+ size_t len;
+ int error;
+
+ while (sz) {
+ len = DEV_BSIZE - fragsz;
+ if (len > sz)
+ len = sz;
+ bcopy(ptr, buffer + fragsz, len);
+ fragsz += len;
+ ptr += len;
+ sz -= len;
+ if (fragsz == DEV_BSIZE) {
+ error = dump_write(di, buffer, 0, dumplo,
+ DEV_BSIZE);
+ if (error)
+ return error;
+ dumplo += DEV_BSIZE;
+ fragsz = 0;
+ }
+ }
+
+ return (0);
+}
+
+static int
+buf_flush(struct dumperinfo *di)
+{
+ int error;
+
+ if (fragsz == 0)
+ return (0);
+
+ error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
+ dumplo += DEV_BSIZE;
+ fragsz = 0;
+ return (error);
+}
+
+extern vm_offset_t kernel_l1kva;
+extern char *pouet2;
+
+static int
+cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
+{
+ struct dumperinfo *di = (struct dumperinfo*)arg;
+ vm_paddr_t a, pa;
+ void *va;
+ uint32_t pgs;
+ size_t counter, sz, chunk;
+ int i, c, error;
+
+ va = 0;
+ error = 0; /* catch case in which chunk size is 0 */
+ counter = 0;
+ pgs = mdp->md_size / PAGE_SIZE;
+ pa = mdp->md_start;
+
+ printf(" chunk %d: %dMB (%d pages)", seqnr, pgs * PAGE_SIZE / (
+ 1024*1024), pgs);
+
+ /*
+ * Make sure we write coherent data. Note that in the SMP case this
+ * only operates on the L1 cache of the current CPU, but all other CPUs
+ * have already been stopped, and their flush/invalidate was done as
+ * part of stopping.
+ */
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+#ifdef __XSCALE__
+ xscale_cache_clean_minidata();
+#endif
+ while (pgs) {
+ chunk = pgs;
+ if (chunk > MAXDUMPPGS)
+ chunk = MAXDUMPPGS;
+ sz = chunk << PAGE_SHIFT;
+ counter += sz;
+ if (counter >> 24) {
+ printf(" %d", pgs * PAGE_SIZE);
+ counter &= (1<<24) - 1;
+ }
+ for (i = 0; i < chunk; i++) {
+ a = pa + i * PAGE_SIZE;
+ va = pmap_kenter_temporary(trunc_page(a), i);
+ }
+#ifdef SW_WATCHDOG
+ wdog_kern_pat(WD_LASTVAL);
+#endif
+ error = dump_write(di, va, 0, dumplo, sz);
+ if (error)
+ break;
+ dumplo += sz;
+ pgs -= chunk;
+ pa += sz;
+
+ /* Check for user abort. */
+ c = cncheckc();
+ if (c == 0x03)
+ return (ECANCELED);
+ if (c != -1)
+ printf(" (CTRL-C to abort) ");
+ }
+ printf(" ... %s\n", (error) ? "fail" : "ok");
+ return (error);
+}
+
+static int
+cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
+{
+ struct dumperinfo *di = (struct dumperinfo*)arg;
+ Elf_Phdr phdr;
+ uint64_t size;
+ int error;
+
+ size = mdp->md_size;
+ bzero(&phdr, sizeof(phdr));
+ phdr.p_type = PT_LOAD;
+ phdr.p_flags = PF_R; /* XXX */
+ phdr.p_offset = fileofs;
+ phdr.p_vaddr = mdp->md_start;
+ phdr.p_paddr = mdp->md_start;
+ phdr.p_filesz = size;
+ phdr.p_memsz = size;
+ phdr.p_align = PAGE_SIZE;
+
+ error = buf_write(di, (char*)&phdr, sizeof(phdr));
+ fileofs += phdr.p_filesz;
+ return (error);
+}
+
+/*
+ * Add a header to be used by libkvm to get the va to pa delta
+ */
+static int
+dump_os_header(struct dumperinfo *di)
+{
+ Elf_Phdr phdr;
+ int error;
+
+ bzero(&phdr, sizeof(phdr));
+ phdr.p_type = PT_DUMP_DELTA;
+ phdr.p_flags = PF_R; /* XXX */
+ phdr.p_offset = 0;
+ phdr.p_vaddr = KERNVIRTADDR;
+ phdr.p_paddr = pmap_kextract(KERNVIRTADDR);
+ phdr.p_filesz = 0;
+ phdr.p_memsz = 0;
+ phdr.p_align = PAGE_SIZE;
+
+ error = buf_write(di, (char*)&phdr, sizeof(phdr));
+ return (error);
+}
+
+static int
+cb_size(struct md_pa *mdp, int seqnr, void *arg)
+{
+ uint32_t *sz = (uint32_t*)arg;
+
+ *sz += (uint32_t)mdp->md_size;
+ return (0);
+}
+
+static int
+foreach_chunk(callback_t cb, void *arg)
+{
+ struct md_pa *mdp;
+ int error, seqnr;
+
+ seqnr = 0;
+ mdp = md_pa_first();
+ while (mdp != NULL) {
+ error = (*cb)(mdp, seqnr++, arg);
+ if (error)
+ return (-error);
+ mdp = md_pa_next(mdp);
+ }
+ return (seqnr);
+}
+
+void
+dumpsys(struct dumperinfo *di)
+{
+ Elf_Ehdr ehdr;
+ uint32_t dumpsize;
+ off_t hdrgap;
+ size_t hdrsz;
+ int error;
+
+ if (do_minidump) {
+ minidumpsys(di);
+ return;
+ }
+
+ bzero(&ehdr, sizeof(ehdr));
+ ehdr.e_ident[EI_MAG0] = ELFMAG0;
+ ehdr.e_ident[EI_MAG1] = ELFMAG1;
+ ehdr.e_ident[EI_MAG2] = ELFMAG2;
+ ehdr.e_ident[EI_MAG3] = ELFMAG3;
+ ehdr.e_ident[EI_CLASS] = ELF_CLASS;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+#else
+ ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
+#endif
+ ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */
+ ehdr.e_type = ET_CORE;
+ ehdr.e_machine = EM_ARM;
+ ehdr.e_phoff = sizeof(ehdr);
+ ehdr.e_flags = 0;
+ ehdr.e_ehsize = sizeof(ehdr);
+ ehdr.e_phentsize = sizeof(Elf_Phdr);
+ ehdr.e_shentsize = sizeof(Elf_Shdr);
+
+ md_pa_init();
+
+ /* Calculate dump size. */
+ dumpsize = 0L;
+ ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize) + 1;
+ hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
+ fileofs = MD_ALIGN(hdrsz);
+ dumpsize += fileofs;
+ hdrgap = fileofs - DEV_ALIGN(hdrsz);
+
+ /* Determine dump offset on device. */
+ if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
+ error = ENOSPC;
+ goto fail;
+ }
+ dumplo = di->mediaoffset + di->mediasize - dumpsize;
+ dumplo -= sizeof(kdh) * 2;
+
+ mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARM_VERSION, dumpsize, di->blocksize);
+
+ printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
+ ehdr.e_phnum - 1);
+
+ /* Dump leader */
+ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
+ if (error)
+ goto fail;
+ dumplo += sizeof(kdh);
+
+ /* Dump ELF header */
+ error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
+ if (error)
+ goto fail;
+
+ /* Dump program headers */
+ error = foreach_chunk(cb_dumphdr, di);
+ if (error >= 0)
+ error = dump_os_header(di);
+ if (error < 0)
+ goto fail;
+ buf_flush(di);
+
+ /*
+ * All headers are written using blocked I/O, so we know the
+ * current offset is (still) block aligned. Skip the alignement
+ * in the file to have the segment contents aligned at page
+ * boundary. We cannot use MD_ALIGN on dumplo, because we don't
+ * care and may very well be unaligned within the dump device.
+ */
+ dumplo += hdrgap;
+
+ /* Dump memory chunks (updates dumplo) */
+ error = foreach_chunk(cb_dumpdata, di);
+ if (error < 0)
+ goto fail;
+
+ /* Dump trailer */
+ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
+ if (error)
+ goto fail;
+
+ /* Signal completion, signoff and exit stage left. */
+ dump_write(di, NULL, 0, 0, 0);
+ printf("\nDump complete\n");
+ return;
+
+ fail:
+ if (error < 0)
+ error = -error;
+
+ if (error == ECANCELED)
+ printf("\nDump aborted\n");
+ else if (error == ENOSPC)
+ printf("\nDump failed. Partition too small.\n");
+ else
+ printf("\n** DUMP FAILED (ERROR %d) **\n", error);
+}
Property changes on: trunk/sys/arm/arm/dump_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/elf_machdep.c
===================================================================
--- trunk/sys/arm/arm/elf_machdep.c (rev 0)
+++ trunk/sys/arm/arm/elf_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,248 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/elf_machdep.c 294136 2016-01-16 07:56:49Z dchagin $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/linker.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/proc.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_param.h>
+
+#include <machine/elf.h>
+#include <machine/md_var.h>
+
+struct sysentvec elf32_freebsd_sysvec = {
+ .sv_size = SYS_MAXSYSCALL,
+ .sv_table = sysent,
+ .sv_mask = 0,
+ .sv_sigsize = 0,
+ .sv_sigtbl = NULL,
+ .sv_errsize = 0,
+ .sv_errtbl = NULL,
+ .sv_transtrap = NULL,
+ .sv_fixup = __elfN(freebsd_fixup),
+ .sv_sendsig = sendsig,
+ .sv_sigcode = sigcode,
+ .sv_szsigcode = &szsigcode,
+ .sv_prepsyscall = NULL,
+ .sv_name = "FreeBSD ELF32",
+ .sv_coredump = __elfN(coredump),
+ .sv_imgact_try = NULL,
+ .sv_minsigstksz = MINSIGSTKSZ,
+ .sv_pagesize = PAGE_SIZE,
+ .sv_minuser = VM_MIN_ADDRESS,
+ .sv_maxuser = VM_MAXUSER_ADDRESS,
+ .sv_usrstack = USRSTACK,
+ .sv_psstrings = PS_STRINGS,
+ .sv_stackprot = VM_PROT_ALL,
+ .sv_copyout_strings = exec_copyout_strings,
+ .sv_setregs = exec_setregs,
+ .sv_fixlimit = NULL,
+ .sv_maxssiz = NULL,
+ .sv_flags = SV_ABI_FREEBSD | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = syscallnames,
+ .sv_schedtail = NULL,
+ .sv_thread_detach = NULL,
+ .sv_trap = NULL,
+};
+
+static Elf32_Brandinfo freebsd_brand_info = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_ARM,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/libexec/ld-elf.so.1",
+ .sysvec = &elf32_freebsd_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_info);
+
+static Elf32_Brandinfo freebsd_brand_oinfo = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_ARM,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/usr/libexec/ld-elf.so.1",
+ .sysvec = &elf32_freebsd_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_oinfo);
+
+
+void
+elf32_dump_thread(struct thread *td __unused, void *dst __unused,
+ size_t *off __unused)
+{
+}
+
+
+/* Process one elf relocation with addend. */
+static int
+elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
+ int type, int local, elf_lookup_fn lookup)
+{
+ Elf_Addr *where;
+ Elf_Addr addr;
+ Elf_Addr addend;
+ Elf_Word rtype, symidx;
+ const Elf_Rel *rel;
+ const Elf_Rela *rela;
+ int error;
+
+ switch (type) {
+ case ELF_RELOC_REL:
+ rel = (const Elf_Rel *)data;
+ where = (Elf_Addr *) (relocbase + rel->r_offset);
+ addend = *where;
+ rtype = ELF_R_TYPE(rel->r_info);
+ symidx = ELF_R_SYM(rel->r_info);
+ break;
+ case ELF_RELOC_RELA:
+ rela = (const Elf_Rela *)data;
+ where = (Elf_Addr *) (relocbase + rela->r_offset);
+ addend = rela->r_addend;
+ rtype = ELF_R_TYPE(rela->r_info);
+ symidx = ELF_R_SYM(rela->r_info);
+ break;
+ default:
+ panic("unknown reloc type %d\n", type);
+ }
+
+ if (local) {
+ if (rtype == R_ARM_RELATIVE) { /* A + B */
+ addr = elf_relocaddr(lf, relocbase + addend);
+ if (*where != addr)
+ *where = addr;
+ }
+ return (0);
+ }
+
+ switch (rtype) {
+
+ case R_ARM_NONE: /* none */
+ break;
+
+ case R_ARM_ABS32:
+ error = lookup(lf, symidx, 1, &addr);
+ if (error != 0)
+ return -1;
+ *where += addr;
+ break;
+
+ case R_ARM_COPY: /* none */
+ /*
+ * There shouldn't be copy relocations in kernel
+ * objects.
+ */
+ printf("kldload: unexpected R_COPY relocation\n");
+ return -1;
+ break;
+
+ case R_ARM_JUMP_SLOT:
+ error = lookup(lf, symidx, 1, &addr);
+ if (error == 0) {
+ *where = addr;
+ return (0);
+ }
+ return (-1);
+ case R_ARM_RELATIVE:
+ break;
+
+ default:
+ printf("kldload: unexpected relocation type %d\n",
+ rtype);
+ return -1;
+ }
+ return(0);
+}
+
+int
+elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
+ elf_lookup_fn lookup)
+{
+
+ return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
+}
+
+int
+elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
+ int type, elf_lookup_fn lookup)
+{
+
+ return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
+}
+
+int
+elf_cpu_load_file(linker_file_t lf __unused)
+{
+
+ /*
+ * The pmap code does not do an icache sync upon establishing executable
+ * mappings in the kernel pmap. It's an optimization based on the fact
+ * that kernel memory allocations always have EXECUTABLE protection even
+ * when the memory isn't going to hold executable code. The only time
+ * kernel memory holding instructions does need a sync is after loading
+ * a kernel module, and that's when this function gets called. Normal
+ * data cache maintenance has already been done by the IO code, and TLB
+ * maintenance has been done by the pmap code, so all we have to do here
+ * is invalidate the instruction cache (which also invalidates the
+ * branch predictor cache on platforms that have one).
+ */
+ cpu_icache_sync_all();
+ return (0);
+}
+
+int
+elf_cpu_unload_file(linker_file_t lf __unused)
+{
+
+ return (0);
+}
Property changes on: trunk/sys/arm/arm/elf_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/elf_trampoline.c
===================================================================
--- trunk/sys/arm/arm/elf_trampoline.c (rev 0)
+++ trunk/sys/arm/arm/elf_trampoline.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,745 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Since we are compiled outside of the normal kernel build process, we
+ * need to include opt_global.h manually.
+ */
+#include "opt_global.h"
+#include "opt_kernname.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/elf_trampoline.c 283335 2015-05-23 22:48:54Z ian $");
+#include <machine/asm.h>
+#include <sys/param.h>
+#include <sys/elf32.h>
+#include <sys/inflate.h>
+#include <machine/elf.h>
+#include <machine/pte.h>
+#include <machine/cpufunc.h>
+#include <machine/armreg.h>
+
+extern char kernel_start[];
+extern char kernel_end[];
+
+extern void *_end;
+
+void _start(void);
+void __start(void);
+void __startC(void);
+
+extern unsigned int cpufunc_id(void);
+extern void armv6_idcache_wbinv_all(void);
+extern void armv7_idcache_wbinv_all(void);
+extern void do_call(void *, void *, void *, int);
+
+#define GZ_HEAD 0xa
+
+#if defined(CPU_ARM9)
+#define cpu_idcache_wbinv_all arm9_idcache_wbinv_all
+extern void arm9_idcache_wbinv_all(void);
+#elif defined(CPU_FA526) || defined(CPU_FA626TE)
+#define cpu_idcache_wbinv_all fa526_idcache_wbinv_all
+extern void fa526_idcache_wbinv_all(void);
+#elif defined(CPU_ARM9E)
+#define cpu_idcache_wbinv_all armv5_ec_idcache_wbinv_all
+extern void armv5_ec_idcache_wbinv_all(void);
+#elif defined(CPU_ARM10)
+#define cpu_idcache_wbinv_all arm10_idcache_wbinv_all
+extern void arm10_idcache_wbinv_all(void);
+#elif defined(CPU_ARM1136) || defined(CPU_ARM1176)
+#define cpu_idcache_wbinv_all armv6_idcache_wbinv_all
+#elif defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_80219)
+#define cpu_idcache_wbinv_all xscale_cache_purgeID
+extern void xscale_cache_purgeID(void);
+#elif defined(CPU_XSCALE_81342)
+#define cpu_idcache_wbinv_all xscalec3_cache_purgeID
+extern void xscalec3_cache_purgeID(void);
+#elif defined(CPU_MV_PJ4B)
+#if !defined(SOC_MV_ARMADAXP)
+#define cpu_idcache_wbinv_all armv6_idcache_wbinv_all
+extern void armv6_idcache_wbinv_all(void);
+#else
+#define cpu_idcache_wbinv_all() armadaxp_idcache_wbinv_all
+#endif
+#endif /* CPU_MV_PJ4B */
+#ifdef CPU_XSCALE_81342
+#define cpu_l2cache_wbinv_all xscalec3_l2cache_purge
+extern void xscalec3_l2cache_purge(void);
+#elif defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
+#define cpu_l2cache_wbinv_all sheeva_l2cache_wbinv_all
+extern void sheeva_l2cache_wbinv_all(void);
+#elif defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+#define cpu_idcache_wbinv_all armv7_idcache_wbinv_all
+#define cpu_l2cache_wbinv_all()
+#else
+#define cpu_l2cache_wbinv_all()
+#endif
+
+static void armadaxp_idcache_wbinv_all(void);
+
+int arm_picache_size;
+int arm_picache_line_size;
+int arm_picache_ways;
+
+int arm_pdcache_size; /* and unified */
+int arm_pdcache_line_size = 32;
+int arm_pdcache_ways;
+
+int arm_pcache_type;
+int arm_pcache_unified;
+
+int arm_dcache_align;
+int arm_dcache_align_mask;
+
+int arm_dcache_min_line_size = 32;
+int arm_icache_min_line_size = 32;
+int arm_idcache_min_line_size = 32;
+
+u_int arm_cache_level;
+u_int arm_cache_type[14];
+u_int arm_cache_loc;
+
+/* Additional cache information local to this file. Log2 of some of the
+ above numbers. */
+static int arm_dcache_l2_nsets;
+static int arm_dcache_l2_assoc;
+static int arm_dcache_l2_linesize;
+
+
+int block_userspace_access = 0;
+extern int arm9_dcache_sets_inc;
+extern int arm9_dcache_sets_max;
+extern int arm9_dcache_index_max;
+extern int arm9_dcache_index_inc;
+
+static __inline void *
+memcpy(void *dst, const void *src, int len)
+{
+ const char *s = src;
+ char *d = dst;
+
+ while (len) {
+ if (0 && len >= 4 && !((vm_offset_t)d & 3) &&
+ !((vm_offset_t)s & 3)) {
+ *(uint32_t *)d = *(uint32_t *)s;
+ s += 4;
+ d += 4;
+ len -= 4;
+ } else {
+ *d++ = *s++;
+ len--;
+ }
+ }
+ return (dst);
+}
+
+static __inline void
+bzero(void *addr, int count)
+{
+ char *tmp = (char *)addr;
+
+ while (count > 0) {
+ if (count >= 4 && !((vm_offset_t)tmp & 3)) {
+ *(uint32_t *)tmp = 0;
+ tmp += 4;
+ count -= 4;
+ } else {
+ *tmp = 0;
+ tmp++;
+ count--;
+ }
+ }
+}
+
+static void arm9_setup(void);
+
+void
+_startC(void)
+{
+ int tmp1;
+ unsigned int sp = ((unsigned int)&_end & ~3) + 4;
+ unsigned int pc, kernphysaddr;
+
+ /*
+ * Figure out the physical address the kernel was loaded at. This
+ * assumes the entry point (this code right here) is in the first page,
+ * which will always be the case for this trampoline code.
+ */
+ __asm __volatile("mov %0, pc\n"
+ : "=r" (pc));
+ kernphysaddr = pc & ~PAGE_MASK;
+
+#if defined(FLASHADDR) && defined(PHYSADDR) && defined(LOADERRAMADDR)
+ if ((FLASHADDR > LOADERRAMADDR && pc >= FLASHADDR) ||
+ (FLASHADDR < LOADERRAMADDR && pc < LOADERRAMADDR)) {
+ /*
+ * We're running from flash, so just copy the whole thing
+ * from flash to memory.
+ * This is far from optimal, we could do the relocation or
+ * the unzipping directly from flash to memory to avoid this
+ * needless copy, but it would require to know the flash
+ * physical address.
+ */
+ unsigned int target_addr;
+ unsigned int tmp_sp;
+ uint32_t src_addr = (uint32_t)&_start - PHYSADDR + FLASHADDR
+ + (pc - FLASHADDR - ((uint32_t)&_startC - PHYSADDR)) & 0xfffff000;
+
+ target_addr = (unsigned int)&_start - PHYSADDR + LOADERRAMADDR;
+ tmp_sp = target_addr + 0x100000 +
+ (unsigned int)&_end - (unsigned int)&_start;
+ memcpy((char *)target_addr, (char *)src_addr,
+ (unsigned int)&_end - (unsigned int)&_start);
+ /* Temporary set the sp and jump to the new location. */
+ __asm __volatile(
+ "mov sp, %1\n"
+ "mov pc, %0\n"
+ : : "r" (target_addr), "r" (tmp_sp));
+
+ }
+#endif
+#ifdef KZIP
+ sp += KERNSIZE + 0x100;
+ sp &= ~(L1_TABLE_SIZE - 1);
+ sp += 2 * L1_TABLE_SIZE;
+#endif
+ sp += 1024 * 1024; /* Should be enough for a stack */
+
+ __asm __volatile("adr %0, 2f\n"
+ "bic %0, %0, #0xff000000\n"
+ "and %1, %1, #0xff000000\n"
+ "orr %0, %0, %1\n"
+ "mrc p15, 0, %1, c1, c0, 0\n"
+ "bic %1, %1, #1\n" /* Disable MMU */
+ "orr %1, %1, #(4 | 8)\n" /* Add DC enable,
+ WBUF enable */
+ "orr %1, %1, #0x1000\n" /* Add IC enable */
+ "orr %1, %1, #(0x800)\n" /* BPRD enable */
+
+ "mcr p15, 0, %1, c1, c0, 0\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "mov pc, %0\n"
+ "2: nop\n"
+ "mov sp, %2\n"
+ : "=r" (tmp1), "+r" (kernphysaddr), "+r" (sp));
+#ifndef KZIP
+#ifdef CPU_ARM9
+ /* So that idcache_wbinv works; */
+ if ((cpufunc_id() & 0x0000f000) == 0x00009000)
+ arm9_setup();
+#endif
+#endif
+ __start();
+}
+
+static void
+get_cachetype_cp15()
+{
+ u_int ctype, isize, dsize, cpuid;
+ u_int clevel, csize, i, sel;
+ u_int multiplier;
+ u_char type;
+
+ __asm __volatile("mrc p15, 0, %0, c0, c0, 1"
+ : "=r" (ctype));
+
+ cpuid = cpufunc_id();
+ /*
+ * ...and thus spake the ARM ARM:
+ *
+ * If an <opcode2> value corresponding to an unimplemented or
+ * reserved ID register is encountered, the System Control
+ * processor returns the value of the main ID register.
+ */
+ if (ctype == cpuid)
+ goto out;
+
+ if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
+ /* Resolve minimal cache line sizes */
+ arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2);
+ arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2);
+ arm_idcache_min_line_size =
+ (arm_dcache_min_line_size > arm_icache_min_line_size ?
+ arm_icache_min_line_size : arm_dcache_min_line_size);
+
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 1"
+ : "=r" (clevel));
+ arm_cache_level = clevel;
+ arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level) + 1;
+ i = 0;
+ while ((type = (clevel & 0x7)) && i < 7) {
+ if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
+ type == CACHE_SEP_CACHE) {
+ sel = i << 1;
+ __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
+ : : "r" (sel));
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
+ : "=r" (csize));
+ arm_cache_type[sel] = csize;
+ }
+ if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
+ sel = (i << 1) | 1;
+ __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
+ : : "r" (sel));
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
+ : "=r" (csize));
+ arm_cache_type[sel] = csize;
+ }
+ i++;
+ clevel >>= 3;
+ }
+ } else {
+ if ((ctype & CPU_CT_S) == 0)
+ arm_pcache_unified = 1;
+
+ /*
+ * If you want to know how this code works, go read the ARM ARM.
+ */
+
+ arm_pcache_type = CPU_CT_CTYPE(ctype);
+
+ if (arm_pcache_unified == 0) {
+ isize = CPU_CT_ISIZE(ctype);
+ multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
+ arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
+ if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
+ if (isize & CPU_CT_xSIZE_M)
+ arm_picache_line_size = 0; /* not present */
+ else
+ arm_picache_ways = 1;
+ } else {
+ arm_picache_ways = multiplier <<
+ (CPU_CT_xSIZE_ASSOC(isize) - 1);
+ }
+ arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
+ }
+
+ dsize = CPU_CT_DSIZE(ctype);
+ multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
+ arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
+ if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
+ if (dsize & CPU_CT_xSIZE_M)
+ arm_pdcache_line_size = 0; /* not present */
+ else
+ arm_pdcache_ways = 1;
+ } else {
+ arm_pdcache_ways = multiplier <<
+ (CPU_CT_xSIZE_ASSOC(dsize) - 1);
+ }
+ arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
+
+ arm_dcache_align = arm_pdcache_line_size;
+
+ arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
+ arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
+ arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
+ CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
+
+ out:
+ arm_dcache_align_mask = arm_dcache_align - 1;
+ }
+}
+
+static void
+arm9_setup(void)
+{
+
+ get_cachetype_cp15();
+ arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
+ arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
+ arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
+ arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
+ arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
+}
+
+static void
+armadaxp_idcache_wbinv_all(void)
+{
+ uint32_t feat;
+
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 0" : "=r" (feat));
+ if (feat & ARM_PFR0_THUMBEE_MASK)
+ armv7_idcache_wbinv_all();
+ else
+ armv6_idcache_wbinv_all();
+
+}
+#ifdef KZIP
+static unsigned char *orig_input, *i_input, *i_output;
+
+
+static u_int memcnt; /* Memory allocated: blocks */
+static size_t memtot; /* Memory allocated: bytes */
+/*
+ * Library functions required by inflate().
+ */
+
+#define MEMSIZ 0x8000
+
+/*
+ * Allocate memory block.
+ */
+unsigned char *
+kzipmalloc(int size)
+{
+ void *ptr;
+ static u_char mem[MEMSIZ];
+
+ if (memtot + size > MEMSIZ)
+ return NULL;
+ ptr = mem + memtot;
+ memtot += size;
+ memcnt++;
+ return ptr;
+}
+
+/*
+ * Free allocated memory block.
+ */
+void
+kzipfree(void *ptr)
+{
+ memcnt--;
+ if (!memcnt)
+ memtot = 0;
+}
+
+void
+putstr(char *dummy)
+{
+}
+
+static int
+input(void *dummy)
+{
+ if ((size_t)(i_input - orig_input) >= KERNCOMPSIZE) {
+ return (GZ_EOF);
+ }
+ return *i_input++;
+}
+
+static int
+output(void *dummy, unsigned char *ptr, unsigned long len)
+{
+
+
+ memcpy(i_output, ptr, len);
+ i_output += len;
+ return (0);
+}
+
+static void *
+inflate_kernel(void *kernel, void *startaddr)
+{
+ struct inflate infl;
+ unsigned char slide[GZ_WSIZE];
+
+ orig_input = kernel;
+ memcnt = memtot = 0;
+ i_input = (unsigned char *)kernel + GZ_HEAD;
+ if (((char *)kernel)[3] & 0x18) {
+ while (*i_input)
+ i_input++;
+ i_input++;
+ }
+ i_output = startaddr;
+ bzero(&infl, sizeof(infl));
+ infl.gz_input = input;
+ infl.gz_output = output;
+ infl.gz_slide = slide;
+ inflate(&infl);
+ return ((char *)(((vm_offset_t)i_output & ~3) + 4));
+}
+
+#endif
+
+void *
+load_kernel(unsigned int kstart, unsigned int curaddr,unsigned int func_end,
+ int d)
+{
+ Elf32_Ehdr *eh;
+ Elf32_Phdr phdr[64] /* XXX */, *php;
+ Elf32_Shdr shdr[64] /* XXX */;
+ int i,j;
+ void *entry_point;
+ int symtabindex = -1;
+ int symstrindex = -1;
+ vm_offset_t lastaddr = 0;
+ Elf_Addr ssym = 0;
+ Elf_Dyn *dp;
+
+ eh = (Elf32_Ehdr *)kstart;
+ ssym = 0;
+ entry_point = (void*)eh->e_entry;
+ memcpy(phdr, (void *)(kstart + eh->e_phoff ),
+ eh->e_phnum * sizeof(phdr[0]));
+
+ /* Determine lastaddr. */
+ for (i = 0; i < eh->e_phnum; i++) {
+ if (lastaddr < (phdr[i].p_vaddr - KERNVIRTADDR + curaddr
+ + phdr[i].p_memsz))
+ lastaddr = phdr[i].p_vaddr - KERNVIRTADDR +
+ curaddr + phdr[i].p_memsz;
+ }
+
+ /* Save the symbol tables, as there're about to be scratched. */
+ memcpy(shdr, (void *)(kstart + eh->e_shoff),
+ sizeof(*shdr) * eh->e_shnum);
+ if (eh->e_shnum * eh->e_shentsize != 0 &&
+ eh->e_shoff != 0) {
+ for (i = 0; i < eh->e_shnum; i++) {
+ if (shdr[i].sh_type == SHT_SYMTAB) {
+ for (j = 0; j < eh->e_phnum; j++) {
+ if (phdr[j].p_type == PT_LOAD &&
+ shdr[i].sh_offset >=
+ phdr[j].p_offset &&
+ (shdr[i].sh_offset +
+ shdr[i].sh_size <=
+ phdr[j].p_offset +
+ phdr[j].p_filesz)) {
+ shdr[i].sh_offset = 0;
+ shdr[i].sh_size = 0;
+ j = eh->e_phnum;
+ }
+ }
+ if (shdr[i].sh_offset != 0 &&
+ shdr[i].sh_size != 0) {
+ symtabindex = i;
+ symstrindex = shdr[i].sh_link;
+ }
+ }
+ }
+ func_end = roundup(func_end, sizeof(long));
+ if (symtabindex >= 0 && symstrindex >= 0) {
+ ssym = lastaddr;
+ if (d) {
+ memcpy((void *)func_end, (void *)(
+ shdr[symtabindex].sh_offset + kstart),
+ shdr[symtabindex].sh_size);
+ memcpy((void *)(func_end +
+ shdr[symtabindex].sh_size),
+ (void *)(shdr[symstrindex].sh_offset +
+ kstart), shdr[symstrindex].sh_size);
+ } else {
+ lastaddr += shdr[symtabindex].sh_size;
+ lastaddr = roundup(lastaddr,
+ sizeof(shdr[symtabindex].sh_size));
+ lastaddr += sizeof(shdr[symstrindex].sh_size);
+ lastaddr += shdr[symstrindex].sh_size;
+ lastaddr = roundup(lastaddr,
+ sizeof(shdr[symstrindex].sh_size));
+ }
+
+ }
+ }
+ if (!d)
+ return ((void *)lastaddr);
+
+ j = eh->e_phnum;
+ for (i = 0; i < j; i++) {
+ volatile char c;
+
+ if (phdr[i].p_type != PT_LOAD)
+ continue;
+ memcpy((void *)(phdr[i].p_vaddr - KERNVIRTADDR + curaddr),
+ (void*)(kstart + phdr[i].p_offset), phdr[i].p_filesz);
+ /* Clean space from oversized segments, eg: bss. */
+ if (phdr[i].p_filesz < phdr[i].p_memsz)
+ bzero((void *)(phdr[i].p_vaddr - KERNVIRTADDR +
+ curaddr + phdr[i].p_filesz), phdr[i].p_memsz -
+ phdr[i].p_filesz);
+ }
+ /* Now grab the symbol tables. */
+ if (symtabindex >= 0 && symstrindex >= 0) {
+ *(Elf_Size *)lastaddr =
+ shdr[symtabindex].sh_size;
+ lastaddr += sizeof(shdr[symtabindex].sh_size);
+ memcpy((void*)lastaddr,
+ (void *)func_end,
+ shdr[symtabindex].sh_size);
+ lastaddr += shdr[symtabindex].sh_size;
+ lastaddr = roundup(lastaddr,
+ sizeof(shdr[symtabindex].sh_size));
+ *(Elf_Size *)lastaddr =
+ shdr[symstrindex].sh_size;
+ lastaddr += sizeof(shdr[symstrindex].sh_size);
+ memcpy((void*)lastaddr,
+ (void*)(func_end +
+ shdr[symtabindex].sh_size),
+ shdr[symstrindex].sh_size);
+ lastaddr += shdr[symstrindex].sh_size;
+ lastaddr = roundup(lastaddr,
+ sizeof(shdr[symstrindex].sh_size));
+ *(Elf_Addr *)curaddr = MAGIC_TRAMP_NUMBER;
+ *((Elf_Addr *)curaddr + 1) = ssym - curaddr + KERNVIRTADDR;
+ *((Elf_Addr *)curaddr + 2) = lastaddr - curaddr + KERNVIRTADDR;
+ } else
+ *(Elf_Addr *)curaddr = 0;
+ /* Invalidate the instruction cache. */
+ __asm __volatile("mcr p15, 0, %0, c7, c5, 0\n"
+ "mcr p15, 0, %0, c7, c10, 4\n"
+ : : "r" (curaddr));
+ __asm __volatile("mrc p15, 0, %0, c1, c0, 0\n"
+ "bic %0, %0, #1\n" /* MMU_ENABLE */
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ : "=r" (ssym));
+ /* Jump to the entry point. */
+ ((void(*)(void))(entry_point - KERNVIRTADDR + curaddr))();
+ __asm __volatile(".globl func_end\n"
+ "func_end:");
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+extern char func_end[];
+
+
+#define PMAP_DOMAIN_KERNEL 0 /*
+ * Just define it instead of including the
+ * whole VM headers set.
+ */
+int __hack;
+static __inline void
+setup_pagetables(unsigned int pt_addr, vm_paddr_t physstart, vm_paddr_t physend,
+ int write_back)
+{
+ unsigned int *pd = (unsigned int *)pt_addr;
+ vm_paddr_t addr;
+ int domain = (DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT;
+ int tmp;
+
+ bzero(pd, L1_TABLE_SIZE);
+ for (addr = physstart; addr < physend; addr += L1_S_SIZE) {
+ pd[addr >> L1_S_SHIFT] = L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)|
+ L1_S_DOM(PMAP_DOMAIN_KERNEL) | addr;
+ if (write_back && 0)
+ pd[addr >> L1_S_SHIFT] |= L1_S_B;
+ }
+ /* XXX: See below */
+ if (0xfff00000 < physstart || 0xfff00000 > physend)
+ pd[0xfff00000 >> L1_S_SHIFT] = L1_TYPE_S|L1_S_AP(AP_KRW)|
+ L1_S_DOM(PMAP_DOMAIN_KERNEL)|physstart;
+ __asm __volatile("mcr p15, 0, %1, c2, c0, 0\n" /* set TTB */
+ "mcr p15, 0, %1, c8, c7, 0\n" /* Flush TTB */
+ "mcr p15, 0, %2, c3, c0, 0\n" /* Set DAR */
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ "orr %0, %0, #1\n" /* MMU_ENABLE */
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ "mrc p15, 0, %0, c2, c0, 0\n" /* CPWAIT */
+ "mov r0, r0\n"
+ "sub pc, pc, #4\n" :
+ "=r" (tmp) : "r" (pd), "r" (domain));
+
+ /*
+ * XXX: This is the most stupid workaround I've ever wrote.
+ * For some reason, the KB9202 won't boot the kernel unless
+ * we access an address which is not in the
+ * 0x20000000 - 0x20ffffff range. I hope I'll understand
+ * what's going on later.
+ */
+ __hack = *(volatile int *)0xfffff21c;
+}
+
+void
+__start(void)
+{
+ void *curaddr;
+ void *dst, *altdst;
+ char *kernel = (char *)&kernel_start;
+ int sp;
+ int pt_addr;
+
+ __asm __volatile("mov %0, pc" :
+ "=r" (curaddr));
+ curaddr = (void*)((unsigned int)curaddr & 0xfff00000);
+#ifdef KZIP
+ if (*kernel == 0x1f && kernel[1] == 0x8b) {
+ pt_addr = (((int)&_end + KERNSIZE + 0x100) &
+ ~(L1_TABLE_SIZE - 1)) + L1_TABLE_SIZE;
+
+#ifdef CPU_ARM9
+ /* So that idcache_wbinv works; */
+ if ((cpufunc_id() & 0x0000f000) == 0x00009000)
+ arm9_setup();
+#endif
+ setup_pagetables(pt_addr, (vm_paddr_t)curaddr,
+ (vm_paddr_t)curaddr + 0x10000000, 1);
+ /* Gzipped kernel */
+ dst = inflate_kernel(kernel, &_end);
+ kernel = (char *)&_end;
+ altdst = 4 + load_kernel((unsigned int)kernel,
+ (unsigned int)curaddr,
+ (unsigned int)&func_end + 800 , 0);
+ if (altdst > dst)
+ dst = altdst;
+
+ /*
+ * Disable MMU. Otherwise, setup_pagetables call below
+ * might overwrite the L1 table we are currently using.
+ */
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ __asm __volatile("mrc p15, 0, %0, c1, c0, 0\n"
+ "bic %0, %0, #1\n" /* MMU_DISABLE */
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ :"=r" (pt_addr));
+ } else
+#endif
+ dst = 4 + load_kernel((unsigned int)&kernel_start,
+ (unsigned int)curaddr,
+ (unsigned int)&func_end, 0);
+ dst = (void *)(((vm_offset_t)dst & ~3));
+ pt_addr = ((unsigned int)dst &~(L1_TABLE_SIZE - 1)) + L1_TABLE_SIZE;
+ setup_pagetables(pt_addr, (vm_paddr_t)curaddr,
+ (vm_paddr_t)curaddr + 0x10000000, 0);
+ sp = pt_addr + L1_TABLE_SIZE + 8192;
+ sp = sp &~3;
+ dst = (void *)(sp + 4);
+ memcpy((void *)dst, (void *)&load_kernel, (unsigned int)&func_end -
+ (unsigned int)&load_kernel + 800);
+ do_call(dst, kernel, dst + (unsigned int)(&func_end) -
+ (unsigned int)(&load_kernel) + 800, sp);
+}
+
+#ifdef __ARM_EABI__
+/* We need to provide these functions but never call them */
+void __aeabi_unwind_cpp_pr0(void);
+void __aeabi_unwind_cpp_pr1(void);
+void __aeabi_unwind_cpp_pr2(void);
+
+__strong_reference(__aeabi_unwind_cpp_pr0, __aeabi_unwind_cpp_pr1);
+__strong_reference(__aeabi_unwind_cpp_pr0, __aeabi_unwind_cpp_pr2);
+void
+__aeabi_unwind_cpp_pr0(void)
+{
+}
+#endif
+
Property changes on: trunk/sys/arm/arm/elf_trampoline.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/exception.S
===================================================================
--- trunk/sys/arm/arm/exception.S (rev 0)
+++ trunk/sys/arm/arm/exception.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,466 @@
+/* $MidnightBSD$ */
+/* $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $ */
+
+/*-
+ * Copyright (c) 1994-1997 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * exception.S
+ *
+ * Low level handlers for exception vectors
+ *
+ * Created : 24/09/94
+ *
+ * Based on kate/display/abort.s
+ *
+ */
+
+#include "assym.s"
+
+#include <machine/asm.h>
+#include <machine/armreg.h>
+#include <machine/asmacros.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/exception.S 278652 2015-02-13 00:49:47Z ian $");
+
+ .text
+ .align 2
+
+/*
+ * ASM macros for pushing and pulling trapframes from the stack
+ *
+ * These macros are used to handle the irqframe and trapframe structures
+ * defined above.
+ */
+
+/*
+ * PUSHFRAME - macro to push a trap frame on the stack in the current mode
+ * Since the current mode is used, the SVC lr field is not defined.
+ *
+ * NOTE: r13 and r14 are stored separately as a work around for the
+ * SA110 rev 2 STM^ bug
+ */
+#ifdef ARM_TP_ADDRESS
+#define PUSHFRAME \
+ sub sp, sp, #4; /* Align the stack */ \
+ str lr, [sp, #-4]!; /* Push the return address */ \
+ sub sp, sp, #(4*17); /* Adjust the stack pointer */ \
+ stmia sp, {r0-r12}; /* Push the user mode registers */ \
+ add r0, sp, #(4*13); /* Adjust the stack pointer */ \
+ stmia r0, {r13-r14}^; /* Push the user mode registers */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ mrs r0, spsr; /* Put the SPSR on the stack */ \
+ str r0, [sp, #-4]!; \
+ ldr r0, =ARM_RAS_START; \
+ mov r1, #0; \
+ str r1, [r0]; \
+ mov r1, #0xffffffff; \
+ str r1, [r0, #4];
+#else
+#define PUSHFRAME \
+ sub sp, sp, #4; /* Align the stack */ \
+ str lr, [sp, #-4]!; /* Push the return address */ \
+ sub sp, sp, #(4*17); /* Adjust the stack pointer */ \
+ stmia sp, {r0-r12}; /* Push the user mode registers */ \
+ add r0, sp, #(4*13); /* Adjust the stack pointer */ \
+ stmia r0, {r13-r14}^; /* Push the user mode registers */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ mrs r0, spsr; /* Put the SPSR on the stack */ \
+ str r0, [sp, #-4]!;
+#endif
+
+/*
+ * PULLFRAME - macro to pull a trap frame from the stack in the current mode
+ * Since the current mode is used, the SVC lr field is ignored.
+ */
+
+#ifdef ARM_TP_ADDRESS
+#define PULLFRAME \
+ ldr r0, [sp], #4; /* Get the SPSR from stack */ \
+ msr spsr_fsxc, r0; \
+ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #(4*17); /* Adjust the stack pointer */ \
+ ldr lr, [sp], #4; /* Pull the return address */ \
+ add sp, sp, #4 /* Align the stack */
+#else
+#define PULLFRAME \
+ ldr r0, [sp], #4 ; /* Get the SPSR from stack */ \
+ msr spsr_fsxc, r0; \
+ clrex; \
+ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #(4*17); /* Adjust the stack pointer */ \
+ ldr lr, [sp], #4; /* Pull the return address */ \
+ add sp, sp, #4 /* Align the stack */
+#endif
+
+/*
+ * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode
+ * This should only be used if the processor is not currently in SVC32
+ * mode. The processor mode is switched to SVC mode and the trap frame is
+ * stored. The SVC lr field is used to store the previous value of
+ * lr in SVC mode.
+ *
+ * NOTE: r13 and r14 are stored separately as a work around for the
+ * SA110 rev 2 STM^ bug
+ */
+#ifdef ARM_TP_ADDRESS
+#define PUSHFRAMEINSVC \
+ stmdb sp, {r0-r3}; /* Save 4 registers */ \
+ mov r0, lr; /* Save xxx32 r14 */ \
+ mov r1, sp; /* Save xxx32 sp */ \
+ mrs r3, spsr; /* Save xxx32 spsr */ \
+ mrs r2, cpsr; /* Get the CPSR */ \
+ bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \
+ orr r2, r2, #(PSR_SVC32_MODE); \
+ msr cpsr_c, r2; /* Punch into SVC mode */ \
+ mov r2, sp; /* Save SVC sp */ \
+ bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \
+ sub sp, sp, #4; /* Pad trapframe to keep alignment */ \
+ str r0, [sp, #-4]!; /* Push return address */ \
+ str lr, [sp, #-4]!; /* Push SVC lr */ \
+ str r2, [sp, #-4]!; /* Push SVC sp */ \
+ msr spsr_fsxc, r3; /* Restore correct spsr */ \
+ ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \
+ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ stmia sp, {r0-r12}; /* Push the user mode registers */ \
+ add r0, sp, #(4*13); /* Adjust the stack pointer */ \
+ stmia r0, {r13-r14}^; /* Push the user mode registers */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ ldr r5, =ARM_RAS_START; /* Check if there's any RAS */ \
+ ldr r4, [r5, #4]; /* reset it to point at the */ \
+ cmp r4, #0xffffffff; /* end of memory if necessary; */ \
+ movne r1, #0xffffffff; /* leave value in r4 for later */ \
+ strne r1, [r5, #4]; /* comparision against PC. */ \
+ ldr r3, [r5]; /* Retrieve global RAS_START */ \
+ cmp r3, #0; /* and reset it if non-zero. */ \
+ movne r1, #0; /* If non-zero RAS_START and */ \
+ strne r1, [r5]; /* PC was lower than RAS_END, */ \
+ ldrne r1, [r0, #16]; /* adjust the saved PC so that */ \
+ cmpne r4, r1; /* execution later resumes at */ \
+ strhi r3, [r0, #16]; /* the RAS_START location. */ \
+ mrs r0, spsr; \
+ str r0, [sp, #-4]!
+#else
+#define PUSHFRAMEINSVC \
+ stmdb sp, {r0-r3}; /* Save 4 registers */ \
+ mov r0, lr; /* Save xxx32 r14 */ \
+ mov r1, sp; /* Save xxx32 sp */ \
+ mrs r3, spsr; /* Save xxx32 spsr */ \
+ mrs r2, cpsr; /* Get the CPSR */ \
+ bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \
+ orr r2, r2, #(PSR_SVC32_MODE); \
+ msr cpsr_c, r2; /* Punch into SVC mode */ \
+ mov r2, sp; /* Save SVC sp */ \
+ bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \
+ sub sp, sp, #4; /* Pad trapframe to keep alignment */ \
+ str r0, [sp, #-4]!; /* Push return address */ \
+ str lr, [sp, #-4]!; /* Push SVC lr */ \
+ str r2, [sp, #-4]!; /* Push SVC sp */ \
+ msr spsr_fsxc, r3; /* Restore correct spsr */ \
+ ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \
+ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ stmia sp, {r0-r12}; /* Push the user mode registers */ \
+ add r0, sp, #(4*13); /* Adjust the stack pointer */ \
+ stmia r0, {r13-r14}^; /* Push the user mode registers */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ mrs r0, spsr; /* Put the SPSR on the stack */ \
+ str r0, [sp, #-4]!
+#endif
+
+/*
+ * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack
+ * in SVC32 mode and restore the saved processor mode and PC.
+ * This should be used when the SVC lr register needs to be restored on
+ * exit.
+ */
+
+#ifdef ARM_TP_ADDRESS
+#define PULLFRAMEFROMSVCANDEXIT \
+ ldr r0, [sp], #4; /* Get the SPSR from stack */ \
+ msr spsr_fsxc, r0; /* restore SPSR */ \
+ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */
+#else
+#define PULLFRAMEFROMSVCANDEXIT \
+ ldr r0, [sp], #4; /* Get the SPSR from stack */ \
+ msr spsr_fsxc, r0; /* restore SPSR */ \
+ clrex; \
+ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */
+#endif
+
+#if defined(__ARM_EABI__)
+/*
+ * Unwind hints so we can unwind past functions that use
+ * PULLFRAMEFROMSVCANDEXIT. They are run in reverse order.
+ * As the last thing we do is restore the stack pointer
+ * we can ignore the padding at the end of struct trapframe.
+ */
+#define UNWINDSVCFRAME \
+ .save {r13-r15}; /* Restore sp, lr, pc */ \
+ .pad #(2*4); /* Skip user sp and lr */ \
+ .save {r0-r12}; /* Restore r0-r12 */ \
+ .pad #(4) /* Skip spsr */
+#else
+#define UNWINDSVCFRAME
+#endif
+
+#define DO_AST \
+ ldr r0, [sp]; /* Get the SPSR from stack */ \
+ mrs r4, cpsr; /* save CPSR */ \
+ orr r1, r4, #(PSR_I|PSR_F); \
+ msr cpsr_c, r1; /* Disable interrupts */ \
+ and r0, r0, #(PSR_MODE); /* Returning to USR mode? */ \
+ teq r0, #(PSR_USR32_MODE); \
+ bne 2f; /* Nope, get out now */ \
+ bic r4, r4, #(PSR_I|PSR_F); \
+1: GET_CURTHREAD_PTR(r5); \
+ ldr r1, [r5, #(TD_FLAGS)]; \
+ and r1, r1, #(TDF_ASTPENDING|TDF_NEEDRESCHED); \
+ teq r1, #0; \
+ beq 2f; /* Nope. Just bail */ \
+ msr cpsr_c, r4; /* Restore interrupts */ \
+ mov r0, sp; \
+ bl _C_LABEL(ast); /* ast(frame) */ \
+ orr r0, r4, #(PSR_I|PSR_F); \
+ msr cpsr_c, r0; \
+ b 1b; \
+2:
+
+
+/*
+ * Entry point for a Software Interrupt (SWI).
+ *
+ * The hardware switches to svc32 mode on a swi, so we're already on the
+ * right stack; just build a trapframe and call the handler.
+ */
+ASENTRY_NP(swi_entry)
+ PUSHFRAME /* Build the trapframe on the */
+ mov r0, sp /* scv32 stack, pass it to the */
+ bl _C_LABEL(swi_handler) /* swi handler. */
+ /*
+ * The fork_trampoline() code in swtch.S aranges for the MI fork_exit()
+ * to return to swi_exit here, to return to userland. The net effect is
+ * that a newly created thread appears to return from a SWI just like
+ * the parent thread that created it.
+ */
+ASEENTRY_NP(swi_exit)
+ DO_AST /* Handle pending signals. */
+ PULLFRAME /* Deallocate trapframe. */
+ movs pc, lr /* Return to userland. */
+ STOP_UNWINDING /* Don't unwind into user mode. */
+EEND(swi_exit)
+END(swi_entry)
+
+/*
+ * Standard exception exit handler.
+ *
+ * This is used to return from all exceptions except SWI. It uses DO_AST and
+ * PULLFRAMEFROMSVCANDEXIT and can only be called if the exception entry code
+ * used PUSHFRAMEINSVC.
+ *
+ * If the return is to user mode, this uses DO_AST to deliver any pending
+ * signals and/or handle TDF_NEEDRESCHED first.
+ */
+ASENTRY_NP(exception_exit)
+ DO_AST /* Handle pending signals. */
+ PULLFRAMEFROMSVCANDEXIT /* Return. */
+ UNWINDSVCFRAME /* Special unwinding for exceptions. */
+END(exception_exit)
+
+/*
+ * Entry point for a Prefetch Abort exception.
+ *
+ * The hardware switches to the abort mode stack; we switch to svc32 before
+ * calling the handler, then return directly to the original mode/stack
+ * on exit (without transitioning back through the abort mode stack).
+ */
+ASENTRY_NP(prefetch_abort_entry)
+#ifdef __XSCALE__
+ nop /* Make absolutely sure any pending */
+ nop /* imprecise aborts have occurred. */
+#endif
+ sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */
+ PUSHFRAMEINSVC /* mode stack, build trapframe there. */
+ adr lr, exception_exit /* Return from handler via standard */
+ mov r0, sp /* exception exit routine. Pass the */
+ mov r1, #1 /* Type flag */
+ b _C_LABEL(abort_handler)
+END(prefetch_abort_entry)
+
+/*
+ * Entry point for a Data Abort exception.
+ *
+ * The hardware switches to the abort mode stack; we switch to svc32 before
+ * calling the handler, then return directly to the original mode/stack
+ * on exit (without transitioning back through the abort mode stack).
+ */
+ASENTRY_NP(data_abort_entry)
+#ifdef __XSCALE__
+ nop /* Make absolutely sure any pending */
+ nop /* imprecise aborts have occurred. */
+#endif
+ sub lr, lr, #8 /* Adjust the lr. Transition to scv32 */
+ PUSHFRAMEINSVC /* mode stack, build trapframe there. */
+ adr lr, exception_exit /* Exception exit routine */
+ mov r0, sp /* Trapframe to the handler */
+ mov r1, #0 /* Type flag */
+ b _C_LABEL(abort_handler)
+END(data_abort_entry)
+
+/*
+ * Entry point for an Undefined Instruction exception.
+ *
+ * The hardware switches to the undefined mode stack; we switch to svc32 before
+ * calling the handler, then return directly to the original mode/stack
+ * on exit (without transitioning back through the undefined mode stack).
+ */
+ASENTRY_NP(undefined_entry)
+ sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */
+ PUSHFRAMEINSVC /* mode stack, build trapframe there. */
+ adr lr, exception_exit /* Return from handler via standard */
+ mov r0, sp /* exception exit routine. Pass the */
+ b undefinedinstruction /* trapframe to the handler. */
+END(undefined_entry)
+
+/*
+ * Entry point for a normal IRQ.
+ *
+ * The hardware switches to the IRQ mode stack; we switch to svc32 before
+ * calling the handler, then return directly to the original mode/stack
+ * on exit (without transitioning back through the IRQ mode stack).
+ */
+ASENTRY_NP(irq_entry)
+ sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */
+ PUSHFRAMEINSVC /* mode stack, build trapframe there. */
+ adr lr, exception_exit /* Return from handler via standard */
+ mov r0, sp /* exception exit routine. Pass the */
+ b _C_LABEL(arm_irq_handler)/* trapframe to the handler. */
+END(irq_entry)
+
+/*
+ * Entry point for an FIQ interrupt.
+ *
+ * We don't currently support FIQ handlers very much. Something can
+ * install itself in the FIQ vector using code (that may or may not work
+ * these days) in fiq.c. If nobody does that and an FIQ happens, this
+ * default handler just disables FIQs and otherwise ignores it.
+ */
+ASENTRY_NP(fiq_entry)
+ mrs r8, cpsr /* FIQ handling isn't supported, */
+ bic r8, #(PSR_F) /* just disable FIQ and return. */
+ msr cpsr_c, r8 /* The r8 we trash here is the */
+ subs pc, lr, #4 /* banked FIQ-mode r8. */
+END(fiq_entry)
+
+/*
+ * Entry point for an Address Exception exception.
+ * This is an arm26 exception that should never happen.
+ */
+ASENTRY_NP(addr_exception_entry)
+ mov r3, lr
+ mrs r2, spsr
+ mrs r1, cpsr
+ adr r0, Laddr_exception_msg
+ b _C_LABEL(panic)
+Laddr_exception_msg:
+ .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n"
+ .balign 4
+END(addr_exception_entry)
+
+/*
+ * Entry point for the system Reset vector.
+ * This should never happen, so panic.
+ */
+ASENTRY_NP(reset_entry)
+ mov r1, lr
+ adr r0, Lreset_panicmsg
+ b _C_LABEL(panic)
+ /* NOTREACHED */
+Lreset_panicmsg:
+ .asciz "Reset vector called, LR = 0x%08x"
+ .balign 4
+END(reset_entry)
+
+/*
+ * page0 and page0_data -- An image of the ARM vectors which is copied to
+ * the ARM vectors page (high or low) as part of CPU initialization. The
+ * code that does the copy assumes that page0_data holds one 32-bit word
+ * of data for each of the predefined ARM vectors. It also assumes that
+ * page0_data follows the vectors in page0, but other stuff can appear
+ * between the two. We currently leave room between the two for some fiq
+ * handler code to be copied in.
+ */
+ .global _C_LABEL(page0), _C_LABEL(page0_data)
+
+_C_LABEL(page0):
+ ldr pc, .Lreset_entry
+ ldr pc, .Lundefined_entry
+ ldr pc, .Lswi_entry
+ ldr pc, .Lprefetch_abort_entry
+ ldr pc, .Ldata_abort_entry
+ ldr pc, .Laddr_exception_entry
+ ldr pc, .Lirq_entry
+.fiqv: ldr pc, .Lfiq_entry
+ .space 256 /* room for some fiq handler code */
+
+_C_LABEL(page0_data):
+.Lreset_entry: .word reset_entry
+.Lundefined_entry: .word undefined_entry
+.Lswi_entry: .word swi_entry
+.Lprefetch_abort_entry: .word prefetch_abort_entry
+.Ldata_abort_entry: .word data_abort_entry
+.Laddr_exception_entry: .word addr_exception_entry
+.Lirq_entry: .word irq_entry
+.Lfiq_entry: .word fiq_entry
+
+/*
+ * These items are used by the code in fiq.c to install what it calls the
+ * "null" handler. It's actually our default vector entry that just jumps
+ * to the default handler which just disables FIQs and returns.
+ */
+ .global _C_LABEL(fiq_nullhandler_code), _C_LABEL(fiq_nullhandler_size)
+
+_C_LABEL(fiq_nullhandler_code):
+ .word .fiqv
+_C_LABEL(fiq_nullhandler_size):
+ .word 4
+
+
Property changes on: trunk/sys/arm/arm/exception.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/fiq.c
===================================================================
--- trunk/sys/arm/arm/fiq.c (rev 0)
+++ trunk/sys/arm/arm/fiq.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,173 @@
+/* $MidnightBSD$ */
+/* $NetBSD: fiq.c,v 1.5 2002/04/03 23:33:27 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/fiq.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/armreg.h>
+#include <machine/cpufunc.h>
+#include <machine/fiq.h>
+#include <vm/vm.h>
+#include <machine/pcb.h>
+#include <vm/pmap.h>
+#include <machine/cpu.h>
+
+TAILQ_HEAD(, fiqhandler) fiqhandler_stack =
+ TAILQ_HEAD_INITIALIZER(fiqhandler_stack);
+
+extern char *fiq_nullhandler_code;
+extern uint32_t fiq_nullhandler_size;
+
+/*
+ * fiq_installhandler:
+ *
+ * Actually install the FIQ handler down at the FIQ vector.
+ *
+ * The FIQ vector is fixed by the hardware definition as the
+ * seventh 32-bit word in the vector page.
+ *
+ * Note: If the FIQ is invoked via an extra layer of
+ * indirection, the actual FIQ code store lives in the
+ * data segment, so there is no need to manipulate
+ * the vector page's protection.
+ */
+static void
+fiq_installhandler(void *func, size_t size)
+{
+ const uint32_t fiqvector = 7 * sizeof(uint32_t);
+
+#if !defined(__ARM_FIQ_INDIRECT)
+ vector_page_setprot(VM_PROT_READ|VM_PROT_WRITE);
+#endif
+
+ memcpy((void *)(vector_page + fiqvector), func, size);
+
+#if !defined(__ARM_FIQ_INDIRECT)
+ vector_page_setprot(VM_PROT_READ);
+ cpu_icache_sync_range((vm_offset_t) fiqvector, size);
+#endif
+}
+
+/*
+ * fiq_claim:
+ *
+ * Claim the FIQ vector.
+ */
+int
+fiq_claim(struct fiqhandler *fh)
+{
+ struct fiqhandler *ofh;
+ u_int oldirqstate;
+ int error = 0;
+
+ if (fh->fh_size > 0x100)
+ return (EFBIG);
+
+ oldirqstate = disable_interrupts(PSR_F);
+
+ if ((ofh = TAILQ_FIRST(&fiqhandler_stack)) != NULL) {
+ if ((ofh->fh_flags & FH_CANPUSH) == 0) {
+ error = EBUSY;
+ goto out;
+ }
+
+ /* Save the previous FIQ handler's registers. */
+ if (ofh->fh_regs != NULL)
+ fiq_getregs(ofh->fh_regs);
+ }
+
+ /* Set FIQ mode registers to ours. */
+ if (fh->fh_regs != NULL)
+ fiq_setregs(fh->fh_regs);
+
+ TAILQ_INSERT_HEAD(&fiqhandler_stack, fh, fh_list);
+
+ /* Now copy the actual handler into place. */
+ fiq_installhandler(fh->fh_func, fh->fh_size);
+
+ /* Make sure FIQs are enabled when we return. */
+ oldirqstate &= ~PSR_F;
+
+ out:
+ restore_interrupts(oldirqstate);
+ return (error);
+}
+
+/*
+ * fiq_release:
+ *
+ * Release the FIQ vector.
+ */
+void
+fiq_release(struct fiqhandler *fh)
+{
+ u_int oldirqstate;
+ struct fiqhandler *ofh;
+
+ oldirqstate = disable_interrupts(PSR_F);
+
+ /*
+ * If we are the currently active FIQ handler, then we
+ * need to save our registers and pop the next one back
+ * into the vector.
+ */
+ if (fh == TAILQ_FIRST(&fiqhandler_stack)) {
+ if (fh->fh_regs != NULL)
+ fiq_getregs(fh->fh_regs);
+ TAILQ_REMOVE(&fiqhandler_stack, fh, fh_list);
+ if ((ofh = TAILQ_FIRST(&fiqhandler_stack)) != NULL) {
+ if (ofh->fh_regs != NULL)
+ fiq_setregs(ofh->fh_regs);
+ fiq_installhandler(ofh->fh_func, ofh->fh_size);
+ }
+ } else
+ TAILQ_REMOVE(&fiqhandler_stack, fh, fh_list);
+
+ if (TAILQ_FIRST(&fiqhandler_stack) == NULL) {
+ /* Copy the NULL handler back down into the vector. */
+ fiq_installhandler(fiq_nullhandler_code, fiq_nullhandler_size);
+
+ /* Make sure FIQs are disabled when we return. */
+ oldirqstate |= PSR_F;
+ }
+
+ restore_interrupts(oldirqstate);
+}
Property changes on: trunk/sys/arm/arm/fiq.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/fiq_subr.S
===================================================================
--- trunk/sys/arm/arm/fiq_subr.S (rev 0)
+++ trunk/sys/arm/arm/fiq_subr.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,94 @@
+/* $MidnightBSD$ */
+/* $NetBSD: fiq_subr.S,v 1.3 2002/04/12 18:50:31 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <machine/armreg.h>
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/fiq_subr.S 266311 2014-05-17 13:53:38Z ian $");
+
+/*
+ * MODE_CHANGE_NOP should be inserted between a mode change and a
+ * banked register (R8--R15) access.
+ */
+#if defined(CPU_ARM2) || defined(CPU_ARM250)
+#define MODE_CHANGE_NOP mov r0, r0
+#else
+#define MODE_CHANGE_NOP /* Data sheet says ARM3 doesn't need it */
+#endif
+
+#define SWITCH_TO_FIQ_MODE \
+ mrs r2, cpsr ; \
+ mov r3, r2 ; \
+ bic r2, r2, #(PSR_MODE) ; \
+ orr r2, r2, #(PSR_FIQ32_MODE) ; \
+ msr cpsr_fsxc, r2
+
+#define BACK_TO_SVC_MODE \
+ msr cpsr_fsxc, r3
+
+/*
+ * fiq_getregs:
+ *
+ * Fetch the FIQ mode banked registers into the fiqhandler
+ * structure.
+ */
+ENTRY(fiq_getregs)
+ SWITCH_TO_FIQ_MODE
+
+ stmia r0, {r8-r13}
+
+ BACK_TO_SVC_MODE
+ RET
+END(fiq_getregs)
+
+/*
+ * fiq_setregs:
+ *
+ * Load the FIQ mode banked registers from the fiqhandler
+ * structure.
+ */
+ENTRY(fiq_setregs)
+ SWITCH_TO_FIQ_MODE
+
+ ldmia r0, {r8-r13}
+
+ BACK_TO_SVC_MODE
+ RET
+END(fiq_setregs)
+
Property changes on: trunk/sys/arm/arm/fiq_subr.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/fusu.S
===================================================================
--- trunk/sys/arm/arm/fusu.S (rev 0)
+++ trunk/sys/arm/arm/fusu.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,395 @@
+/* $MidnightBSD$ */
+/* $NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $ */
+
+/*-
+ * Copyright (c) 1996-1998 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+#include <machine/armreg.h>
+#include "assym.s"
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/fusu.S 294686 2016-01-24 22:05:21Z ian $");
+
+ .syntax unified
+
+#ifdef _ARM_ARCH_6
+#define GET_PCB(tmp) \
+ mrc p15, 0, tmp, c13, c0, 4; \
+ add tmp, tmp, #(TD_PCB)
+#else
+.Lcurpcb:
+ .word _C_LABEL(__pcpu) + PC_CURPCB
+#define GET_PCB(tmp) \
+ ldr tmp, .Lcurpcb
+#endif
+
+/*
+ * fuword(caddr_t uaddr);
+ * Fetch an int from the user's address space.
+ */
+
+ENTRY(casuword)
+EENTRY_NP(casuword32)
+ GET_PCB(r3)
+ ldr r3, [r3]
+
+#ifdef DIAGNOSTIC
+ teq r3, #0x00000000
+ beq .Lfusupcbfault
+#endif
+ stmfd sp!, {r4, r5}
+ adr r4, .Lcasuwordfault
+ str r4, [r3, #PCB_ONFAULT]
+#ifdef _ARM_ARCH_6
+1:
+ cmp r0, #KERNBASE
+ mvnhs r0, #0
+ bhs 2f
+
+ ldrex r5, [r0]
+ cmp r5, r1
+ movne r0, r5
+ bne 2f
+ strex r5, r2, [r0]
+ cmp r5, #0
+ bne 1b
+#else
+ ldrt r5, [r0]
+ cmp r5, r1
+ movne r0, r5
+ strteq r2, [r0]
+#endif
+ moveq r0, r1
+2:
+ ldmfd sp!, {r4, r5}
+ mov r1, #0x00000000
+ str r1, [r3, #PCB_ONFAULT]
+ RET
+EEND(casuword32)
+END(casuword)
+
+/*
+ * Handle faults from casuword. Clean up and return -1.
+ */
+
+.Lcasuwordfault:
+ mov r0, #0x00000000
+ str r0, [r3, #PCB_ONFAULT]
+ mvn r0, #0x00000000
+ ldmfd sp!, {r4, r5}
+ RET
+
+/*
+ * fuword(caddr_t uaddr);
+ * Fetch an int from the user's address space.
+ */
+
+ENTRY(fuword)
+EENTRY_NP(fuword32)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq .Lfusupcbfault
+#endif
+
+ adr r1, .Lfusufault
+ str r1, [r2, #PCB_ONFAULT]
+
+ ldrt r3, [r0]
+
+ mov r1, #0x00000000
+ str r1, [r2, #PCB_ONFAULT]
+ mov r0, r3
+ RET
+EEND(fueword32)
+END(fueword)
+
+/*
+ * fusword(caddr_t uaddr);
+ * Fetch a short from the user's address space.
+ */
+
+ENTRY(fusword)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq .Lfusupcbfault
+#endif
+
+ adr r1, .Lfusufault
+ str r1, [r2, #PCB_ONFAULT]
+
+ ldrbt r3, [r0], #1
+ ldrbt ip, [r0]
+#ifdef __ARMEB__
+ orr r0, ip, r3, asl #8
+#else
+ orr r0, r3, ip, asl #8
+#endif
+ mov r1, #0x00000000
+ str r1, [r2, #PCB_ONFAULT]
+ RET
+END(fusword)
+
+/*
+ * fuswintr(caddr_t uaddr);
+ * Fetch a short from the user's address space. Can be called during an
+ * interrupt.
+ */
+
+ENTRY(fuswintr)
+ ldr r2, Lblock_userspace_access
+ ldr r2, [r2]
+ teq r2, #0
+ mvnne r0, #0x00000000
+ RETne
+
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq .Lfusupcbfault
+#endif
+
+ adr r1, _C_LABEL(fusubailout)
+ str r1, [r2, #PCB_ONFAULT]
+
+ ldrbt r3, [r0], #1
+ ldrbt ip, [r0]
+#ifdef __ARMEB__
+ orr r0, ip, r3, asl #8
+#else
+ orr r0, r3, ip, asl #8
+#endif
+
+ mov r1, #0x00000000
+ str r1, [r2, #PCB_ONFAULT]
+ RET
+END(fuswintr)
+
+Lblock_userspace_access:
+ .word _C_LABEL(block_userspace_access)
+
+ .data
+ .align 2
+ .global _C_LABEL(block_userspace_access)
+_C_LABEL(block_userspace_access):
+ .word 0
+ .text
+
+/*
+ * fubyte(caddr_t uaddr);
+ * Fetch a byte from the user's address space.
+ */
+
+ENTRY(fubyte)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq .Lfusupcbfault
+#endif
+
+ adr r1, .Lfusufault
+ str r1, [r2, #PCB_ONFAULT]
+
+ ldrbt r3, [r0]
+
+ mov r1, #0x00000000
+ str r1, [r2, #PCB_ONFAULT]
+ mov r0, r3
+ RET
+END(fubyte)
+
+/*
+ * Handle faults from [fs]u*(). Clean up and return -1.
+ */
+
+.Lfusufault:
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mvn r0, #0x00000000
+ RET
+
+/*
+ * Handle faults from [fs]u*(). Clean up and return -1. This differs from
+ * fusufault() in that trap() will recognise it and return immediately rather
+ * than trying to page fault.
+ */
+
+/* label must be global as fault.c references it */
+ .global _C_LABEL(fusubailout)
+_C_LABEL(fusubailout):
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mvn r0, #0x00000000
+ RET
+
+#ifdef DIAGNOSTIC
+/*
+ * Handle earlier faults from [fs]u*(), due to no pcb
+ */
+
+.Lfusupcbfault:
+ mov r1, r0
+ adr r0, fusupcbfaulttext
+ b _C_LABEL(panic)
+
+fusupcbfaulttext:
+ .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n"
+ .align 2
+#endif
+
+/*
+ * suword(caddr_t uaddr, int x);
+ * Store an int in the user's address space.
+ */
+
+ENTRY(suword)
+EENTRY_NP(suword32)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq .Lfusupcbfault
+#endif
+
+ adr r3, .Lfusufault
+ str r3, [r2, #PCB_ONFAULT]
+
+ strt r1, [r0]
+
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ RET
+EEND(suword32)
+END(suword)
+
+/*
+ * suswintr(caddr_t uaddr, short x);
+ * Store a short in the user's address space. Can be called during an
+ * interrupt.
+ */
+
+ENTRY(suswintr)
+ ldr r2, Lblock_userspace_access
+ ldr r2, [r2]
+ teq r2, #0
+ mvnne r0, #0x00000000
+ RETne
+
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq .Lfusupcbfault
+#endif
+
+ adr r3, _C_LABEL(fusubailout)
+ str r3, [r2, #PCB_ONFAULT]
+
+#ifdef __ARMEB__
+ mov ip, r1, lsr #8
+ strbt ip, [r0], #1
+#else
+ strbt r1, [r0], #1
+ mov r1, r1, lsr #8
+#endif
+ strbt r1, [r0]
+
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ RET
+END(suswintr)
+
+/*
+ * susword(caddr_t uaddr, short x);
+ * Store a short in the user's address space.
+ */
+
+ENTRY(susword)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq .Lfusupcbfault
+#endif
+
+ adr r3, .Lfusufault
+ str r3, [r2, #PCB_ONFAULT]
+
+#ifdef __ARMEB__
+ mov ip, r1, lsr #8
+ strbt ip, [r0], #1
+#else
+ strbt r1, [r0], #1
+ mov r1, r1, lsr #8
+#endif
+ strbt r1, [r0]
+
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ RET
+END(susword)
+
+/*
+ * subyte(caddr_t uaddr, char x);
+ * Store a byte in the user's address space.
+ */
+
+ENTRY(subyte)
+ GET_PCB(r2)
+ ldr r2, [r2]
+
+
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq .Lfusupcbfault
+#endif
+
+ adr r3, .Lfusufault
+ str r3, [r2, #PCB_ONFAULT]
+
+ strbt r1, [r0]
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ RET
+END(subyte)
Property changes on: trunk/sys/arm/arm/fusu.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/gdb_machdep.c
===================================================================
--- trunk/sys/arm/arm/gdb_machdep.c (rev 0)
+++ trunk/sys/arm/arm/gdb_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,116 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/gdb_machdep.c 278614 2015-02-12 04:15:55Z ian $");
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/signal.h>
+
+#include <machine/gdb_machdep.h>
+#include <machine/db_machdep.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/trap.h>
+#include <machine/frame.h>
+#include <machine/endian.h>
+
+#include <gdb/gdb.h>
+
+static register_t stacktest;
+
+void *
+gdb_cpu_getreg(int regnum, size_t *regsz)
+{
+
+ *regsz = gdb_cpu_regsz(regnum);
+
+ if (kdb_thread == curthread) {
+ if (regnum < 13)
+ return (&kdb_frame->tf_r0 + regnum);
+ if (regnum == 13)
+ return (&kdb_frame->tf_svc_sp);
+ if (regnum == 14)
+ return (&kdb_frame->tf_svc_lr);
+ if (regnum == 15)
+ return (&kdb_frame->tf_pc);
+ if (regnum == 25)
+ return (&kdb_frame->tf_spsr);
+ }
+
+ switch (regnum) {
+ case 4: return (&kdb_thrctx->pcb_regs.sf_r4);
+ case 5: return (&kdb_thrctx->pcb_regs.sf_r5);
+ case 6: return (&kdb_thrctx->pcb_regs.sf_r6);
+ case 7: return (&kdb_thrctx->pcb_regs.sf_r7);
+ case 8: return (&kdb_thrctx->pcb_regs.sf_r8);
+ case 9: return (&kdb_thrctx->pcb_regs.sf_r9);
+ case 10: return (&kdb_thrctx->pcb_regs.sf_r10);
+ case 11: return (&kdb_thrctx->pcb_regs.sf_r11);
+ case 12: return (&kdb_thrctx->pcb_regs.sf_r12);
+ case 13: stacktest = kdb_thrctx->pcb_regs.sf_sp + 5 * 4;
+ return (&stacktest);
+ case 15:
+ /*
+ * On context switch, the PC is not put in the PCB, but
+ * we can retrieve it from the stack.
+ */
+ if (kdb_thrctx->pcb_regs.sf_sp > KERNBASE) {
+ kdb_thrctx->pcb_regs.sf_pc = *(register_t *)
+ (kdb_thrctx->pcb_regs.sf_sp + 4 * 4);
+ return (&kdb_thrctx->pcb_regs.sf_pc);
+ }
+ }
+
+ return (NULL);
+}
+
+void
+gdb_cpu_setreg(int regnum, void *val)
+{
+
+ switch (regnum) {
+ case GDB_REG_PC:
+ if (kdb_thread == curthread)
+ kdb_frame->tf_pc = *(register_t *)val;
+ }
+}
+
+int
+gdb_cpu_signal(int type, int code)
+{
+
+ switch (type) {
+ case T_BREAKPOINT: return (SIGTRAP);
+ }
+ return (SIGEMT);
+}
Property changes on: trunk/sys/arm/arm/gdb_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/genassym.c
===================================================================
--- trunk/sys/arm/arm/genassym.c (rev 0)
+++ trunk/sys/arm/arm/genassym.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,155 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/genassym.c 283336 2015-05-23 23:05:31Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/assym.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/vmmeter.h>
+#include <sys/bus.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <machine/vmparam.h>
+#include <machine/armreg.h>
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/cpu.h>
+#include <machine/proc.h>
+#include <machine/cpufunc.h>
+#include <machine/cpuinfo.h>
+#include <machine/pte.h>
+#include <machine/intr.h>
+#include <machine/sysarch.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/ip_var.h>
+
+ASSYM(KERNBASE, KERNBASE);
+ASSYM(PCB_NOALIGNFLT, PCB_NOALIGNFLT);
+ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_DACR, offsetof(struct pcb, pcb_dacr));
+ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
+ASSYM(PCB_PAGEDIR, offsetof(struct pcb, pcb_pagedir));
+ASSYM(PCB_L1VEC, offsetof(struct pcb, pcb_l1vec));
+ASSYM(PCB_PL1VEC, offsetof(struct pcb, pcb_pl1vec));
+ASSYM(PCB_R4, offsetof(struct pcb, pcb_regs.sf_r4));
+ASSYM(PCB_R5, offsetof(struct pcb, pcb_regs.sf_r5));
+ASSYM(PCB_R6, offsetof(struct pcb, pcb_regs.sf_r6));
+ASSYM(PCB_R7, offsetof(struct pcb, pcb_regs.sf_r7));
+ASSYM(PCB_R8, offsetof(struct pcb, pcb_regs.sf_r8));
+ASSYM(PCB_R9, offsetof(struct pcb, pcb_regs.sf_r9));
+ASSYM(PCB_R10, offsetof(struct pcb, pcb_regs.sf_r10));
+ASSYM(PCB_R11, offsetof(struct pcb, pcb_regs.sf_r11));
+ASSYM(PCB_R12, offsetof(struct pcb, pcb_regs.sf_r12));
+ASSYM(PCB_SP, offsetof(struct pcb, pcb_regs.sf_sp));
+ASSYM(PCB_LR, offsetof(struct pcb, pcb_regs.sf_lr));
+ASSYM(PCB_PC, offsetof(struct pcb, pcb_regs.sf_pc));
+
+ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
+ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
+ASSYM(M_LEN, offsetof(struct mbuf, m_len));
+ASSYM(M_DATA, offsetof(struct mbuf, m_data));
+ASSYM(M_NEXT, offsetof(struct mbuf, m_next));
+ASSYM(IP_SRC, offsetof(struct ip, ip_src));
+ASSYM(IP_DST, offsetof(struct ip, ip_dst));
+ASSYM(CF_SETTTB, offsetof(struct cpu_functions, cf_setttb));
+ASSYM(CF_CONTROL, offsetof(struct cpu_functions, cf_control));
+ASSYM(CF_CONTEXT_SWITCH, offsetof(struct cpu_functions, cf_context_switch));
+ASSYM(CF_DCACHE_WB_RANGE, offsetof(struct cpu_functions, cf_dcache_wb_range));
+ASSYM(CF_L2CACHE_WB_RANGE, offsetof(struct cpu_functions, cf_l2cache_wb_range));
+ASSYM(CF_IDCACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_idcache_wbinv_all));
+ASSYM(CF_L2CACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_l2cache_wbinv_all));
+ASSYM(CF_TLB_FLUSHID_SE, offsetof(struct cpu_functions, cf_tlb_flushID_SE));
+ASSYM(CF_ICACHE_SYNC, offsetof(struct cpu_functions, cf_icache_sync_all));
+
+ASSYM(V_TRAP, offsetof(struct vmmeter, v_trap));
+ASSYM(V_SOFT, offsetof(struct vmmeter, v_soft));
+ASSYM(V_INTR, offsetof(struct vmmeter, v_intr));
+
+ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+ASSYM(TD_PROC, offsetof(struct thread, td_proc));
+ASSYM(TD_FRAME, offsetof(struct thread, td_frame));
+ASSYM(TD_MD, offsetof(struct thread, td_md));
+ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
+ASSYM(MD_TP, offsetof(struct mdthread, md_tp));
+ASSYM(MD_RAS_START, offsetof(struct mdthread, md_ras_start));
+ASSYM(MD_RAS_END, offsetof(struct mdthread, md_ras_end));
+
+ASSYM(TF_R0, offsetof(struct trapframe, tf_r0));
+ASSYM(TF_R1, offsetof(struct trapframe, tf_r1));
+ASSYM(TF_PC, offsetof(struct trapframe, tf_pc));
+ASSYM(P_PID, offsetof(struct proc, p_pid));
+ASSYM(P_FLAG, offsetof(struct proc, p_flag));
+
+ASSYM(SIGF_UC, offsetof(struct sigframe, sf_uc));
+
+#ifdef ARM_TP_ADDRESS
+ASSYM(ARM_TP_ADDRESS, ARM_TP_ADDRESS);
+ASSYM(ARM_RAS_START, ARM_RAS_START);
+ASSYM(ARM_RAS_END, ARM_RAS_END);
+#endif
+
+#ifdef VFP
+ASSYM(PCB_VFPSTATE, offsetof(struct pcb, pcb_vfpstate));
+
+ASSYM(PC_CPU, offsetof(struct pcpu, pc_cpu));
+
+ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
+#endif
+
+ASSYM(PAGE_SIZE, PAGE_SIZE);
+ASSYM(PDESIZE, PDESIZE);
+ASSYM(PMAP_DOMAIN_KERNEL, PMAP_DOMAIN_KERNEL);
+#ifdef PMAP_INCLUDE_PTE_SYNC
+ASSYM(PMAP_INCLUDE_PTE_SYNC, 1);
+#endif
+ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
+ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
+ASSYM(P_TRACED, P_TRACED);
+ASSYM(P_SIGEVENT, P_SIGEVENT);
+ASSYM(P_PROFIL, P_PROFIL);
+ASSYM(TRAPFRAMESIZE, sizeof(struct trapframe));
+
+ASSYM(MAXCOMLEN, MAXCOMLEN);
+ASSYM(MAXCPU, MAXCPU);
+ASSYM(NIRQ, NIRQ);
+ASSYM(PCPU_SIZE, sizeof(struct pcpu));
+
+ASSYM(DCACHE_LINE_SIZE, offsetof(struct cpuinfo, dcache_line_size));
+ASSYM(DCACHE_LINE_MASK, offsetof(struct cpuinfo, dcache_line_mask));
+ASSYM(ICACHE_LINE_SIZE, offsetof(struct cpuinfo, icache_line_size));
+ASSYM(ICACHE_LINE_MASK, offsetof(struct cpuinfo, icache_line_mask));
Property changes on: trunk/sys/arm/arm/genassym.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/generic_timer.c
===================================================================
--- trunk/sys/arm/arm/generic_timer.c (rev 0)
+++ trunk/sys/arm/arm/generic_timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,394 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Based on mpcore_timer.c developed by Ben Gray <ben.r.gray at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * Cortex-A15 (and probably A7) Generic Timer
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/generic_timer.c 275764 2014-12-14 15:41:56Z andrew $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#define GT_CTRL_ENABLE (1 << 0)
+#define GT_CTRL_INT_MASK (1 << 1)
+#define GT_CTRL_INT_STAT (1 << 2)
+#define GT_REG_CTRL 0
+#define GT_REG_TVAL 1
+
+#define GT_CNTKCTL_PL0PTEN (1 << 9) /* PL0 Physical timer reg access */
+#define GT_CNTKCTL_PL0VTEN (1 << 8) /* PL0 Virtual timer reg access */
+#define GT_CNTKCTL_EVNTI (1 << 4) /* Virtual counter event bits */
+#define GT_CNTKCTL_EVNTDIR (1 << 3) /* Virtual counter event transition */
+#define GT_CNTKCTL_EVNTEN (1 << 2) /* Enables virtual counter events */
+#define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */
+#define GT_CNTKCTL_PL0PCTEN (1 << 0) /* PL0 CNTPCT and CNTFRQ access */
+
+struct arm_tmr_softc {
+ struct resource *res[4];
+ void *ihl[4];
+ uint32_t clkfreq;
+ struct eventtimer et;
+};
+
+static struct arm_tmr_softc *arm_tmr_sc = NULL;
+
+static struct resource_spec timer_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Secure */
+ { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Non-secure */
+ { SYS_RES_IRQ, 2, RF_ACTIVE }, /* Virt */
+ { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, /* Hyp */
+ { -1, 0 }
+};
+
+static timecounter_get_t arm_tmr_get_timecount;
+
+static struct timecounter arm_tmr_timecount = {
+ .tc_name = "ARM MPCore Timecounter",
+ .tc_get_timecount = arm_tmr_get_timecount,
+ .tc_poll_pps = NULL,
+ .tc_counter_mask = ~0u,
+ .tc_frequency = 0,
+ .tc_quality = 1000,
+};
+
+static inline int
+get_freq(void)
+{
+ uint32_t val;
+
+ __asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
+
+ return (val);
+}
+
+static inline int
+set_freq(uint32_t val)
+{
+
+ __asm volatile("mcr p15, 0, %[val], c14, c0, 0" : :
+ [val] "r" (val));
+ isb();
+
+ return (val);
+}
+
+
+static inline long
+get_cntpct(void)
+{
+ uint64_t val;
+
+ __asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (val));
+
+ return (val);
+}
+
+static inline int
+set_ctrl(uint32_t val)
+{
+
+ __asm volatile("mcr p15, 0, %[val], c14, c2, 1" : :
+ [val] "r" (val));
+ isb();
+
+ return (0);
+}
+
+static inline int
+set_tval(uint32_t val)
+{
+
+ __asm volatile("mcr p15, 0, %[val], c14, c2, 0" : :
+ [val] "r" (val));
+ isb();
+
+ return (0);
+}
+
+static inline int
+get_ctrl(void)
+{
+ uint32_t val;
+
+ __asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
+
+ return (val);
+}
+
+static inline int
+get_tval(void)
+{
+ uint32_t val;
+
+ __asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
+
+ return (val);
+}
+
+static inline void
+disable_user_access(void)
+{
+ uint32_t cntkctl;
+
+ __asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
+ cntkctl &= ~(GT_CNTKCTL_PL0PTEN | GT_CNTKCTL_PL0VTEN |
+ GT_CNTKCTL_EVNTEN | GT_CNTKCTL_PL0VCTEN | GT_CNTKCTL_PL0PCTEN);
+ __asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
+ isb();
+}
+
+static unsigned
+arm_tmr_get_timecount(struct timecounter *tc)
+{
+
+ return (get_cntpct());
+}
+
+static int
+arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct arm_tmr_softc *sc;
+ int counts, ctrl;
+
+ sc = (struct arm_tmr_softc *)et->et_priv;
+
+ if (first != 0) {
+ counts = ((uint32_t)et->et_frequency * first) >> 32;
+ ctrl = get_ctrl();
+ ctrl &= ~GT_CTRL_INT_MASK;
+ ctrl |= GT_CTRL_ENABLE;
+ set_tval(counts);
+ set_ctrl(ctrl);
+ return (0);
+ }
+
+ return (EINVAL);
+
+}
+
+static int
+arm_tmr_stop(struct eventtimer *et)
+{
+ int ctrl;
+
+ ctrl = get_ctrl();
+ ctrl &= GT_CTRL_ENABLE;
+ set_ctrl(ctrl);
+
+ return (0);
+}
+
+static int
+arm_tmr_intr(void *arg)
+{
+ struct arm_tmr_softc *sc;
+ int ctrl;
+
+ sc = (struct arm_tmr_softc *)arg;
+ ctrl = get_ctrl();
+ if (ctrl & GT_CTRL_INT_STAT) {
+ ctrl |= GT_CTRL_INT_MASK;
+ set_ctrl(ctrl);
+ }
+
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+
+ return (FILTER_HANDLED);
+}
+
+static int
+arm_tmr_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "arm,armv7-timer"))
+ return (ENXIO);
+
+ device_set_desc(dev, "ARMv7 Generic Timer");
+ return (BUS_PROBE_DEFAULT);
+}
+
+
+static int
+arm_tmr_attach(device_t dev)
+{
+ struct arm_tmr_softc *sc;
+ phandle_t node;
+ pcell_t clock;
+ int error;
+ int i;
+
+ sc = device_get_softc(dev);
+ if (arm_tmr_sc)
+ return (ENXIO);
+
+ /* Get the base clock frequency */
+ node = ofw_bus_get_node(dev);
+ error = OF_getprop(node, "clock-frequency", &clock, sizeof(clock));
+ if (error > 0) {
+ sc->clkfreq = fdt32_to_cpu(clock);
+ }
+
+ if (sc->clkfreq == 0) {
+ /* Try to get clock frequency from timer */
+ sc->clkfreq = get_freq();
+ }
+
+ if (sc->clkfreq == 0) {
+ device_printf(dev, "No clock frequency specified\n");
+ return (ENXIO);
+ }
+
+ if (bus_alloc_resources(dev, timer_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ };
+
+ arm_tmr_sc = sc;
+
+ /* Setup secure and non-secure IRQs handler */
+ for (i = 0; i < 2; i++) {
+ error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK,
+ arm_tmr_intr, NULL, sc, &sc->ihl[i]);
+ if (error) {
+ device_printf(dev, "Unable to alloc int resource.\n");
+ return (ENXIO);
+ }
+ }
+
+ disable_user_access();
+
+ arm_tmr_timecount.tc_frequency = sc->clkfreq;
+ tc_init(&arm_tmr_timecount);
+
+ sc->et.et_name = "ARM MPCore Eventtimer";
+ sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
+ sc->et.et_quality = 1000;
+
+ sc->et.et_frequency = sc->clkfreq;
+ sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
+ sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
+ sc->et.et_start = arm_tmr_start;
+ sc->et.et_stop = arm_tmr_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ return (0);
+}
+
+static device_method_t arm_tmr_methods[] = {
+ DEVMETHOD(device_probe, arm_tmr_probe),
+ DEVMETHOD(device_attach, arm_tmr_attach),
+ { 0, 0 }
+};
+
+static driver_t arm_tmr_driver = {
+ "generic_timer",
+ arm_tmr_methods,
+ sizeof(struct arm_tmr_softc),
+};
+
+static devclass_t arm_tmr_devclass;
+
+EARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(timer, ofwbus, arm_tmr_driver, arm_tmr_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+
+void
+DELAY(int usec)
+{
+ int32_t counts, counts_per_usec;
+ uint32_t first, last;
+
+ /*
+ * Check the timers are setup, if not just
+ * use a for loop for the meantime
+ */
+ if (arm_tmr_sc == NULL) {
+ for (; usec > 0; usec--)
+ for (counts = 200; counts > 0; counts--)
+ /*
+ * Prevent gcc from optimizing
+ * out the loop
+ */
+ cpufunc_nullop();
+ return;
+ }
+
+ /* Get the number of times to count */
+ counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1);
+
+ /*
+ * Clamp the timeout at a maximum value (about 32 seconds with
+ * a 66MHz clock). *Nobody* should be delay()ing for anywhere
+ * near that length of time and if they are, they should be hung
+ * out to dry.
+ */
+ if (usec >= (0x80000000U / counts_per_usec))
+ counts = (0x80000000U / counts_per_usec) - 1;
+ else
+ counts = usec * counts_per_usec;
+
+ first = get_cntpct();
+
+ while (counts > 0) {
+ last = get_cntpct();
+ counts -= (int32_t)(last - first);
+ first = last;
+ }
+}
Property changes on: trunk/sys/arm/arm/generic_timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/gic.c
===================================================================
--- trunk/sys/arm/arm/gic.c (rev 0)
+++ trunk/sys/arm/arm/gic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,471 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Developed by Damjan Marion <damjan.marion at gmail.com>
+ *
+ * Based on OMAP4 GIC code by Ben Gray
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/gic.c 283334 2015-05-23 22:36:41Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/cpuset.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/smp.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/* We are using GICv2 register naming */
+
+/* Distributor Registers */
+#define GICD_CTLR 0x000 /* v1 ICDDCR */
+#define GICD_TYPER 0x004 /* v1 ICDICTR */
+#define GICD_IIDR 0x008 /* v1 ICDIIDR */
+#define GICD_IGROUPR(n) (0x0080 + ((n) * 4)) /* v1 ICDISER */
+#define GICD_ISENABLER(n) (0x0100 + ((n) * 4)) /* v1 ICDISER */
+#define GICD_ICENABLER(n) (0x0180 + ((n) * 4)) /* v1 ICDICER */
+#define GICD_ISPENDR(n) (0x0200 + ((n) * 4)) /* v1 ICDISPR */
+#define GICD_ICPENDR(n) (0x0280 + ((n) * 4)) /* v1 ICDICPR */
+#define GICD_ICACTIVER(n) (0x0380 + ((n) * 4)) /* v1 ICDABR */
+#define GICD_IPRIORITYR(n) (0x0400 + ((n) * 4)) /* v1 ICDIPR */
+#define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */
+#define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */
+#define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */
+
+/* CPU Registers */
+#define GICC_CTLR 0x0000 /* v1 ICCICR */
+#define GICC_PMR 0x0004 /* v1 ICCPMR */
+#define GICC_BPR 0x0008 /* v1 ICCBPR */
+#define GICC_IAR 0x000C /* v1 ICCIAR */
+#define GICC_EOIR 0x0010 /* v1 ICCEOIR */
+#define GICC_RPR 0x0014 /* v1 ICCRPR */
+#define GICC_HPPIR 0x0018 /* v1 ICCHPIR */
+#define GICC_ABPR 0x001C /* v1 ICCABPR */
+#define GICC_IIDR 0x00FC /* v1 ICCIIDR*/
+
+#define GIC_FIRST_IPI 0 /* Irqs 0-15 are SGIs/IPIs. */
+#define GIC_LAST_IPI 15
+#define GIC_FIRST_PPI 16 /* Irqs 16-31 are private (per */
+#define GIC_LAST_PPI 31 /* core) peripheral interrupts. */
+#define GIC_FIRST_SPI 32 /* Irqs 32+ are shared peripherals. */
+
+/* First bit is a polarity bit (0 - low, 1 - high) */
+#define GICD_ICFGR_POL_LOW (0 << 0)
+#define GICD_ICFGR_POL_HIGH (1 << 0)
+#define GICD_ICFGR_POL_MASK 0x1
+/* Second bit is a trigger bit (0 - level, 1 - edge) */
+#define GICD_ICFGR_TRIG_LVL (0 << 1)
+#define GICD_ICFGR_TRIG_EDGE (1 << 1)
+#define GICD_ICFGR_TRIG_MASK 0x2
+
+struct arm_gic_softc {
+ struct resource * gic_res[3];
+ bus_space_tag_t gic_c_bst;
+ bus_space_tag_t gic_d_bst;
+ bus_space_handle_t gic_c_bsh;
+ bus_space_handle_t gic_d_bsh;
+ uint8_t ver;
+ device_t dev;
+ struct mtx mutex;
+ uint32_t nirqs;
+};
+
+static struct resource_spec arm_gic_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */
+ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */
+ { -1, 0 }
+};
+
+static struct arm_gic_softc *arm_gic_sc = NULL;
+
+#define gic_c_read_4(reg) \
+ bus_space_read_4(arm_gic_sc->gic_c_bst, arm_gic_sc->gic_c_bsh, reg)
+#define gic_c_write_4(reg, val) \
+ bus_space_write_4(arm_gic_sc->gic_c_bst, arm_gic_sc->gic_c_bsh, reg, val)
+#define gic_d_read_4(reg) \
+ bus_space_read_4(arm_gic_sc->gic_d_bst, arm_gic_sc->gic_d_bsh, reg)
+#define gic_d_write_4(reg, val) \
+ bus_space_write_4(arm_gic_sc->gic_d_bst, arm_gic_sc->gic_d_bsh, reg, val)
+
+static int gic_config_irq(int irq, enum intr_trigger trig,
+ enum intr_polarity pol);
+static void gic_post_filter(void *);
+
+static struct ofw_compat_data compat_data[] = {
+ {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */
+ {"arm,gic-400", true},
+ {"arm,cortex-a15-gic", true},
+ {"arm,cortex-a9-gic", true},
+ {"arm,cortex-a7-gic", true},
+ {"arm,arm11mp-gic", true},
+ {"brcm,brahma-b15-gic", true},
+ {NULL, false}
+};
+
+static int
+arm_gic_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+ device_set_desc(dev, "ARM Generic Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+void
+gic_init_secondary(void)
+{
+ int i, nirqs;
+
+ /* Get the number of interrupts */
+ nirqs = gic_d_read_4(GICD_TYPER);
+ nirqs = 32 * ((nirqs & 0x1f) + 1);
+
+ for (i = 0; i < nirqs; i += 4)
+ gic_d_write_4(GICD_IPRIORITYR(i >> 2), 0);
+
+ /* Set all the interrupts to be in Group 0 (secure) */
+ for (i = 0; i < nirqs; i += 32) {
+ gic_d_write_4(GICD_IGROUPR(i >> 5), 0);
+ }
+
+ /* Enable CPU interface */
+ gic_c_write_4(GICC_CTLR, 1);
+
+ /* Set priority mask register. */
+ gic_c_write_4(GICC_PMR, 0xff);
+
+ /* Enable interrupt distribution */
+ gic_d_write_4(GICD_CTLR, 0x01);
+
+ /* Activate IRQ 29, ie private timer IRQ*/
+ gic_d_write_4(GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F)));
+}
+
+int
+gic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
+ int *trig, int *pol)
+{
+ static u_int num_intr_cells;
+
+ if (num_intr_cells == 0) {
+ if (OF_searchencprop(OF_node_from_xref(iparent),
+ "#interrupt-cells", &num_intr_cells,
+ sizeof(num_intr_cells)) == -1) {
+ num_intr_cells = 1;
+ }
+ }
+
+ if (num_intr_cells == 1) {
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ } else {
+ if (fdt32_to_cpu(intr[0]) == 0)
+ *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_SPI;
+ else
+ *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_PPI;
+ /*
+ * In intr[2], bits[3:0] are trigger type and level flags.
+ * 1 = low-to-high edge triggered
+ * 2 = high-to-low edge triggered
+ * 4 = active high level-sensitive
+ * 8 = active low level-sensitive
+ * The hardware only supports active-high-level or rising-edge.
+ */
+ if (fdt32_to_cpu(intr[2]) & 0x0a) {
+ printf("unsupported trigger/polarity configuration "
+ "0x%2x\n", fdt32_to_cpu(intr[2]) & 0x0f);
+ return (ENOTSUP);
+ }
+ *pol = INTR_POLARITY_CONFORM;
+ if (fdt32_to_cpu(intr[2]) & 0x01)
+ *trig = INTR_TRIGGER_EDGE;
+ else
+ *trig = INTR_TRIGGER_LEVEL;
+ }
+ return (0);
+}
+
+static int
+arm_gic_attach(device_t dev)
+{
+ struct arm_gic_softc *sc;
+ int i;
+ uint32_t icciidr;
+
+ if (arm_gic_sc)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, arm_gic_spec, sc->gic_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Initialize mutex */
+ mtx_init(&sc->mutex, "GIC lock", "", MTX_SPIN);
+
+ /* Distributor Interface */
+ sc->gic_d_bst = rman_get_bustag(sc->gic_res[0]);
+ sc->gic_d_bsh = rman_get_bushandle(sc->gic_res[0]);
+
+ /* CPU Interface */
+ sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]);
+ sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]);
+
+ arm_gic_sc = sc;
+
+ /* Disable interrupt forwarding to the CPU interface */
+ gic_d_write_4(GICD_CTLR, 0x00);
+
+ /* Get the number of interrupts */
+ sc->nirqs = gic_d_read_4(GICD_TYPER);
+ sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1);
+
+ /* Set up function pointers */
+ arm_post_filter = gic_post_filter;
+ arm_config_irq = gic_config_irq;
+
+ icciidr = gic_c_read_4(GICC_IIDR);
+ device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
+ icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,
+ (icciidr & 0xfff), sc->nirqs);
+
+ /* Set all global interrupts to be level triggered, active low. */
+ for (i = 32; i < sc->nirqs; i += 16) {
+ gic_d_write_4(GICD_ICFGR(i >> 4), 0x00000000);
+ }
+
+ /* Disable all interrupts. */
+ for (i = 32; i < sc->nirqs; i += 32) {
+ gic_d_write_4(GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
+ }
+
+ for (i = 0; i < sc->nirqs; i += 4) {
+ gic_d_write_4(GICD_IPRIORITYR(i >> 2), 0);
+ gic_d_write_4(GICD_ITARGETSR(i >> 2), 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24);
+ }
+
+ /* Set all the interrupts to be in Group 0 (secure) */
+ for (i = 0; i < sc->nirqs; i += 32) {
+ gic_d_write_4(GICD_IGROUPR(i >> 5), 0);
+ }
+
+ /* Enable CPU interface */
+ gic_c_write_4(GICC_CTLR, 1);
+
+ /* Set priority mask register. */
+ gic_c_write_4(GICC_PMR, 0xff);
+
+ /* Enable interrupt distribution */
+ gic_d_write_4(GICD_CTLR, 0x01);
+
+ return (0);
+}
+
+static device_method_t arm_gic_methods[] = {
+ DEVMETHOD(device_probe, arm_gic_probe),
+ DEVMETHOD(device_attach, arm_gic_attach),
+ { 0, 0 }
+};
+
+static driver_t arm_gic_driver = {
+ "gic",
+ arm_gic_methods,
+ sizeof(struct arm_gic_softc),
+};
+
+static devclass_t arm_gic_devclass;
+
+EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+
+static void
+gic_post_filter(void *arg)
+{
+ uintptr_t irq = (uintptr_t) arg;
+
+ if (irq > GIC_LAST_IPI)
+ arm_irq_memory_barrier(irq);
+ gic_c_write_4(GICC_EOIR, irq);
+}
+
+int
+arm_get_next_irq(int last_irq)
+{
+ uint32_t active_irq;
+
+ active_irq = gic_c_read_4(GICC_IAR);
+
+ /*
+ * Immediatly EOIR the SGIs, because doing so requires the other
+ * bits (ie CPU number), not just the IRQ number, and we do not
+ * have this information later.
+ */
+
+ if ((active_irq & 0x3ff) <= GIC_LAST_IPI)
+ gic_c_write_4(GICC_EOIR, active_irq);
+ active_irq &= 0x3FF;
+
+ if (active_irq == 0x3FF) {
+ if (last_irq == -1)
+ printf("Spurious interrupt detected\n");
+ return -1;
+ }
+
+ return active_irq;
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+
+ gic_d_write_4(GICD_ICENABLER(nb >> 5), (1UL << (nb & 0x1F)));
+ gic_c_write_4(GICC_EOIR, nb);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+
+ if (nb > GIC_LAST_IPI)
+ arm_irq_memory_barrier(nb);
+ gic_d_write_4(GICD_ISENABLER(nb >> 5), (1UL << (nb & 0x1F)));
+}
+
+static int
+gic_config_irq(int irq, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+ uint32_t reg;
+ uint32_t mask;
+
+ /* Function is public-accessible, so validate input arguments */
+ if ((irq < 0) || (irq >= arm_gic_sc->nirqs))
+ goto invalid_args;
+ if ((trig != INTR_TRIGGER_EDGE) && (trig != INTR_TRIGGER_LEVEL) &&
+ (trig != INTR_TRIGGER_CONFORM))
+ goto invalid_args;
+ if ((pol != INTR_POLARITY_HIGH) && (pol != INTR_POLARITY_LOW) &&
+ (pol != INTR_POLARITY_CONFORM))
+ goto invalid_args;
+
+ mtx_lock_spin(&arm_gic_sc->mutex);
+
+ reg = gic_d_read_4(GICD_ICFGR(irq >> 4));
+ mask = (reg >> 2*(irq % 16)) & 0x3;
+
+ if (pol == INTR_POLARITY_LOW) {
+ mask &= ~GICD_ICFGR_POL_MASK;
+ mask |= GICD_ICFGR_POL_LOW;
+ } else if (pol == INTR_POLARITY_HIGH) {
+ mask &= ~GICD_ICFGR_POL_MASK;
+ mask |= GICD_ICFGR_POL_HIGH;
+ }
+
+ if (trig == INTR_TRIGGER_LEVEL) {
+ mask &= ~GICD_ICFGR_TRIG_MASK;
+ mask |= GICD_ICFGR_TRIG_LVL;
+ } else if (trig == INTR_TRIGGER_EDGE) {
+ mask &= ~GICD_ICFGR_TRIG_MASK;
+ mask |= GICD_ICFGR_TRIG_EDGE;
+ }
+
+ /* Set mask */
+ reg = reg & ~(0x3 << 2*(irq % 16));
+ reg = reg | (mask << 2*(irq % 16));
+ gic_d_write_4(GICD_ICFGR(irq >> 4), reg);
+
+ mtx_unlock_spin(&arm_gic_sc->mutex);
+
+ return (0);
+
+invalid_args:
+ device_printf(arm_gic_sc->dev, "gic_config_irg, invalid parameters\n");
+ return (EINVAL);
+}
+
+#ifdef SMP
+void
+pic_ipi_send(cpuset_t cpus, u_int ipi)
+{
+ uint32_t val = 0, i;
+
+ for (i = 0; i < MAXCPU; i++)
+ if (CPU_ISSET(i, &cpus))
+ val |= 1 << (16 + i);
+ gic_d_write_4(GICD_SGIR(0), val | ipi);
+
+}
+
+int
+pic_ipi_get(int i)
+{
+
+ if (i != -1) {
+ /*
+ * The intr code will automagically give the frame pointer
+ * if the interrupt argument is 0.
+ */
+ if ((unsigned int)i > 16)
+ return (0);
+ return (i);
+ }
+ return (0x3ff);
+}
+
+void
+pic_ipi_clear(int ipi)
+{
+}
+#endif
+
Property changes on: trunk/sys/arm/arm/gic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/identcpu.c
===================================================================
--- trunk/sys/arm/arm/identcpu.c (rev 0)
+++ trunk/sys/arm/arm/identcpu.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,527 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpu.c,v 1.55 2004/02/13 11:36:10 wiz Exp $ */
+
+/*-
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpu.c
+ *
+ * Probing and configuration for the master CPU
+ *
+ * Created : 10/10/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/identcpu.c 278626 2015-02-12 17:01:54Z ian $");
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <machine/cpu.h>
+#include <machine/endian.h>
+
+#include <machine/cpuconf.h>
+#include <machine/md_var.h>
+
+char machine[] = "arm";
+
+SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
+ machine, 0, "Machine class");
+
+static const char * const generic_steppings[16] = {
+ "rev 0", "rev 1", "rev 2", "rev 3",
+ "rev 4", "rev 5", "rev 6", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+static const char * const xscale_steppings[16] = {
+ "step A-0", "step A-1", "step B-0", "step C-0",
+ "step D-0", "rev 5", "rev 6", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+static const char * const i80219_steppings[16] = {
+ "step A-0", "rev 1", "rev 2", "rev 3",
+ "rev 4", "rev 5", "rev 6", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+static const char * const i80321_steppings[16] = {
+ "step A-0", "step B-0", "rev 2", "rev 3",
+ "rev 4", "rev 5", "rev 6", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+static const char * const i81342_steppings[16] = {
+ "step A-0", "rev 1", "rev 2", "rev 3",
+ "rev 4", "rev 5", "rev 6", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+/* Steppings for PXA2[15]0 */
+static const char * const pxa2x0_steppings[16] = {
+ "step A-0", "step A-1", "step B-0", "step B-1",
+ "step B-2", "step C-0", "rev 6", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+/* Steppings for PXA255/26x.
+ * rev 5: PXA26x B0, rev 6: PXA255 A0
+ */
+static const char * const pxa255_steppings[16] = {
+ "rev 0", "rev 1", "rev 2", "step A-0",
+ "rev 4", "step B-0", "step A-0", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+/* Stepping for PXA27x */
+static const char * const pxa27x_steppings[16] = {
+ "step A-0", "step A-1", "step B-0", "step B-1",
+ "step C-0", "rev 5", "rev 6", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+static const char * const ixp425_steppings[16] = {
+ "step 0 (A0)", "rev 1 (ARMv5TE)", "rev 2", "rev 3",
+ "rev 4", "rev 5", "rev 6", "rev 7",
+ "rev 8", "rev 9", "rev 10", "rev 11",
+ "rev 12", "rev 13", "rev 14", "rev 15",
+};
+
+struct cpuidtab {
+ u_int32_t cpuid;
+ enum cpu_class cpu_class;
+ const char *cpu_name;
+ const char * const *cpu_steppings;
+};
+
+const struct cpuidtab cpuids[] = {
+ { CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T",
+ generic_steppings },
+ { CPU_ID_ARM920T_ALT, CPU_CLASS_ARM9TDMI, "ARM920T",
+ generic_steppings },
+ { CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T",
+ generic_steppings },
+ { CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S",
+ generic_steppings },
+ { CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T",
+ generic_steppings },
+ { CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S",
+ generic_steppings },
+ { CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S",
+ generic_steppings },
+ { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S",
+ generic_steppings },
+ { CPU_ID_FA526, CPU_CLASS_ARM9TDMI, "FA526",
+ generic_steppings },
+ { CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE",
+ generic_steppings },
+
+ { CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T",
+ generic_steppings },
+
+ { CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E",
+ generic_steppings },
+ { CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S",
+ generic_steppings },
+ { CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S",
+ generic_steppings },
+
+ { CPU_ID_CORTEXA7, CPU_CLASS_CORTEXA, "Cortex A7",
+ generic_steppings },
+ { CPU_ID_CORTEXA8R1, CPU_CLASS_CORTEXA, "Cortex A8-r1",
+ generic_steppings },
+ { CPU_ID_CORTEXA8R2, CPU_CLASS_CORTEXA, "Cortex A8-r2",
+ generic_steppings },
+ { CPU_ID_CORTEXA8R3, CPU_CLASS_CORTEXA, "Cortex A8-r3",
+ generic_steppings },
+ { CPU_ID_CORTEXA9R1, CPU_CLASS_CORTEXA, "Cortex A9-r1",
+ generic_steppings },
+ { CPU_ID_CORTEXA9R2, CPU_CLASS_CORTEXA, "Cortex A9-r2",
+ generic_steppings },
+ { CPU_ID_CORTEXA9R3, CPU_CLASS_CORTEXA, "Cortex A9-r3",
+ generic_steppings },
+ { CPU_ID_CORTEXA15R0, CPU_CLASS_CORTEXA, "Cortex A15-r0",
+ generic_steppings },
+ { CPU_ID_CORTEXA15R1, CPU_CLASS_CORTEXA, "Cortex A15-r1",
+ generic_steppings },
+ { CPU_ID_CORTEXA15R2, CPU_CLASS_CORTEXA, "Cortex A15-r2",
+ generic_steppings },
+ { CPU_ID_CORTEXA15R3, CPU_CLASS_CORTEXA, "Cortex A15-r3",
+ generic_steppings },
+ { CPU_ID_KRAIT, CPU_CLASS_KRAIT, "Krait",
+ generic_steppings },
+
+ { CPU_ID_80200, CPU_CLASS_XSCALE, "i80200",
+ xscale_steppings },
+
+ { CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz",
+ i80321_steppings },
+ { CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz",
+ i80321_steppings },
+ { CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz",
+ i80321_steppings },
+ { CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz",
+ i80321_steppings },
+
+ { CPU_ID_81342, CPU_CLASS_XSCALE, "i81342",
+ i81342_steppings },
+
+ { CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz",
+ i80219_steppings },
+ { CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz",
+ i80219_steppings },
+
+ { CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x",
+ pxa27x_steppings },
+ { CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250",
+ pxa2x0_steppings },
+ { CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210",
+ pxa2x0_steppings },
+ { CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250",
+ pxa2x0_steppings },
+ { CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210",
+ pxa2x0_steppings },
+ { CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255",
+ pxa255_steppings },
+ { CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210",
+ pxa2x0_steppings },
+
+ { CPU_ID_IXP425_533, CPU_CLASS_XSCALE, "IXP425 533MHz",
+ ixp425_steppings },
+ { CPU_ID_IXP425_400, CPU_CLASS_XSCALE, "IXP425 400MHz",
+ ixp425_steppings },
+ { CPU_ID_IXP425_266, CPU_CLASS_XSCALE, "IXP425 266MHz",
+ ixp425_steppings },
+
+ /* XXX ixp435 steppings? */
+ { CPU_ID_IXP435, CPU_CLASS_XSCALE, "IXP435",
+ ixp425_steppings },
+
+ { CPU_ID_ARM1136JS, CPU_CLASS_ARM11J, "ARM1136J-S",
+ generic_steppings },
+ { CPU_ID_ARM1136JSR1, CPU_CLASS_ARM11J, "ARM1136J-S R1",
+ generic_steppings },
+ { CPU_ID_ARM1176JZS, CPU_CLASS_ARM11J, "ARM1176JZ-S",
+ generic_steppings },
+
+ { CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131",
+ generic_steppings },
+
+ { CPU_ID_MV88FR571_VD, CPU_CLASS_MARVELL, "Feroceon 88FR571-VD",
+ generic_steppings },
+ { CPU_ID_MV88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x",
+ generic_steppings },
+ { CPU_ID_ARM_88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x",
+ generic_steppings },
+ { CPU_ID_MV88SV584X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV584x",
+ generic_steppings },
+
+ { 0, CPU_CLASS_NONE, NULL, NULL }
+};
+
+struct cpu_classtab {
+ const char *class_name;
+ const char *class_option;
+};
+
+const struct cpu_classtab cpu_classes[] = {
+ { "unknown", NULL }, /* CPU_CLASS_NONE */
+ { "ARM9TDMI", "CPU_ARM9TDMI" }, /* CPU_CLASS_ARM9TDMI */
+ { "ARM9E-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9ES */
+ { "ARM9EJ-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9EJS */
+ { "ARM10E", "CPU_ARM10" }, /* CPU_CLASS_ARM10E */
+ { "ARM10EJ", "CPU_ARM10" }, /* CPU_CLASS_ARM10EJ */
+ { "Cortex-A", "CPU_CORTEXA" }, /* CPU_CLASS_CORTEXA */
+ { "Krait", "CPU_KRAIT" }, /* CPU_CLASS_KRAIT */
+ { "XScale", "CPU_XSCALE_..." }, /* CPU_CLASS_XSCALE */
+ { "ARM11J", "CPU_ARM11" }, /* CPU_CLASS_ARM11J */
+ { "Marvell", "CPU_MARVELL" }, /* CPU_CLASS_MARVELL */
+};
+
+/*
+ * Report the type of the specified arm processor. This uses the generic and
+ * arm specific information in the cpu structure to identify the processor.
+ * The remaining fields in the cpu structure are filled in appropriately.
+ */
+
+static const char * const wtnames[] = {
+ "write-through",
+ "write-back",
+ "write-back",
+ "**unknown 3**",
+ "**unknown 4**",
+ "write-back-locking", /* XXX XScale-specific? */
+ "write-back-locking-A",
+ "write-back-locking-B",
+ "**unknown 8**",
+ "**unknown 9**",
+ "**unknown 10**",
+ "**unknown 11**",
+ "**unknown 12**",
+ "**unknown 13**",
+ "write-back-locking-C",
+ "**unknown 15**",
+};
+
+static void
+print_enadis(int enadis, char *s)
+{
+
+ printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
+}
+
+extern int ctrl;
+enum cpu_class cpu_class = CPU_CLASS_NONE;
+
+u_int cpu_pfr(int num)
+{
+ u_int feat;
+
+ switch (num) {
+ case 0:
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 0"
+ : "=r" (feat));
+ break;
+ case 1:
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 1"
+ : "=r" (feat));
+ break;
+ default:
+ panic("Processor Feature Register %d not implemented", num);
+ break;
+ }
+
+ return (feat);
+}
+
+static
+void identify_armv7(void)
+{
+ u_int feature;
+
+ printf("Supported features:");
+ /* Get Processor Feature Register 0 */
+ feature = cpu_pfr(0);
+
+ if (feature & ARM_PFR0_ARM_ISA_MASK)
+ printf(" ARM_ISA");
+
+ if (feature & ARM_PFR0_THUMB2)
+ printf(" THUMB2");
+ else if (feature & ARM_PFR0_THUMB)
+ printf(" THUMB");
+
+ if (feature & ARM_PFR0_JAZELLE_MASK)
+ printf(" JAZELLE");
+
+ if (feature & ARM_PFR0_THUMBEE_MASK)
+ printf(" THUMBEE");
+
+
+ /* Get Processor Feature Register 1 */
+ feature = cpu_pfr(1);
+
+ if (feature & ARM_PFR1_ARMV4_MASK)
+ printf(" ARMv4");
+
+ if (feature & ARM_PFR1_SEC_EXT_MASK)
+ printf(" Security_Ext");
+
+ if (feature & ARM_PFR1_MICROCTRL_MASK)
+ printf(" M_profile");
+
+ printf("\n");
+}
+
+void
+identify_arm_cpu(void)
+{
+ u_int cpuid, reg, size, sets, ways;
+ u_int8_t type, linesize;
+ int i;
+
+ cpuid = cpu_id();
+
+ if (cpuid == 0) {
+ printf("Processor failed probe - no CPU ID\n");
+ return;
+ }
+
+ for (i = 0; cpuids[i].cpuid != 0; i++)
+ if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
+ cpu_class = cpuids[i].cpu_class;
+ printf("CPU: %s %s (%s core)\n",
+ cpuids[i].cpu_name,
+ cpuids[i].cpu_steppings[cpuid &
+ CPU_ID_REVISION_MASK],
+ cpu_classes[cpu_class].class_name);
+ break;
+ }
+ if (cpuids[i].cpuid == 0)
+ printf("unknown CPU (ID = 0x%x)\n", cpuid);
+
+ printf(" ");
+
+ if ((cpuid & CPU_ID_ARCH_MASK) == CPU_ID_CPUID_SCHEME) {
+ identify_armv7();
+ } else {
+ if (ctrl & CPU_CONTROL_BEND_ENABLE)
+ printf(" Big-endian");
+ else
+ printf(" Little-endian");
+
+ switch (cpu_class) {
+ case CPU_CLASS_ARM9TDMI:
+ case CPU_CLASS_ARM9ES:
+ case CPU_CLASS_ARM9EJS:
+ case CPU_CLASS_ARM10E:
+ case CPU_CLASS_ARM10EJ:
+ case CPU_CLASS_XSCALE:
+ case CPU_CLASS_ARM11J:
+ case CPU_CLASS_MARVELL:
+ print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
+ print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
+#ifdef CPU_XSCALE_81342
+ print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2");
+#endif
+#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
+ i = sheeva_control_ext(0, 0);
+ print_enadis(i & MV_WA_ENABLE, "WA");
+ print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
+ printf("\n ");
+ print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
+ print_enadis(i & MV_L2_ENABLE, "L2");
+ print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
+ "L2 prefetch");
+ printf("\n ");
+#endif
+ break;
+ default:
+ break;
+ }
+ }
+
+ print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
+ if (ctrl & CPU_CONTROL_LABT_ENABLE)
+ printf(" LABT");
+ else
+ printf(" EABT");
+
+ print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
+ printf("\n");
+
+ if (arm_cache_level) {
+ printf("LoUU:%d LoC:%d LoUIS:%d \n", CPU_CLIDR_LOUU(arm_cache_level) + 1,
+ arm_cache_loc + 1, CPU_CLIDR_LOUIS(arm_cache_level) + 1);
+ i = 0;
+ while (((type = CPU_CLIDR_CTYPE(arm_cache_level, i)) != 0) && i < 7) {
+ printf("Cache level %d: \n", i + 1);
+ if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
+ type == CACHE_SEP_CACHE) {
+ reg = arm_cache_type[2 * i];
+ ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
+ sets = CPUV7_CT_xSIZE_SET(reg) + 1;
+ linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
+ size = (ways * sets * linesize) / 1024;
+
+ if (type == CACHE_UNI_CACHE)
+ printf(" %dKB/%dB %d-way unified cache", size, linesize,ways);
+ else
+ printf(" %dKB/%dB %d-way data cache", size, linesize, ways);
+ if (reg & CPUV7_CT_CTYPE_WT)
+ printf(" WT");
+ if (reg & CPUV7_CT_CTYPE_WB)
+ printf(" WB");
+ if (reg & CPUV7_CT_CTYPE_RA)
+ printf(" Read-Alloc");
+ if (reg & CPUV7_CT_CTYPE_WA)
+ printf(" Write-Alloc");
+ printf("\n");
+ }
+
+ if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
+ reg = arm_cache_type[(2 * i) + 1];
+
+ ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
+ sets = CPUV7_CT_xSIZE_SET(reg) + 1;
+ linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
+ size = (ways * sets * linesize) / 1024;
+
+ printf(" %dKB/%dB %d-way instruction cache", size, linesize, ways);
+ if (reg & CPUV7_CT_CTYPE_WT)
+ printf(" WT");
+ if (reg & CPUV7_CT_CTYPE_WB)
+ printf(" WB");
+ if (reg & CPUV7_CT_CTYPE_RA)
+ printf(" Read-Alloc");
+ if (reg & CPUV7_CT_CTYPE_WA)
+ printf(" Write-Alloc");
+ printf("\n");
+ }
+ i++;
+ }
+ } else {
+ /* Print cache info. */
+ if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
+ return;
+
+ if (arm_pcache_unified) {
+ printf(" %dKB/%dB %d-way %s unified cache\n",
+ arm_pdcache_size / 1024,
+ arm_pdcache_line_size, arm_pdcache_ways,
+ wtnames[arm_pcache_type]);
+ } else {
+ printf(" %dKB/%dB %d-way instruction cache\n",
+ arm_picache_size / 1024,
+ arm_picache_line_size, arm_picache_ways);
+ printf(" %dKB/%dB %d-way %s data cache\n",
+ arm_pdcache_size / 1024,
+ arm_pdcache_line_size, arm_pdcache_ways,
+ wtnames[arm_pcache_type]);
+ }
+ }
+}
Property changes on: trunk/sys/arm/arm/identcpu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/in_cksum.c
===================================================================
--- trunk/sys/arm/arm/in_cksum.c (rev 0)
+++ trunk/sys/arm/arm/in_cksum.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,153 @@
+/* $MidnightBSD$ */
+/* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1988, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1996
+ * Matt Thomas <matt at 3am-software.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/in_cksum.c 236991 2012-06-13 04:59:55Z imp $");
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <machine/in_cksum.h>
+
+/*
+ * Checksum routine for Internet Protocol family headers
+ * (Portable Alpha version).
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ */
+
+#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
+#define REDUCE32 \
+ { \
+ q_util.q = sum; \
+ sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
+ }
+#define REDUCE16 \
+ { \
+ q_util.q = sum; \
+ l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
+ sum = l_util.s[0] + l_util.s[1]; \
+ ADDCARRY(sum); \
+ }
+
+union l_util {
+ u_int16_t s[2];
+ u_int32_t l;
+};
+union q_util {
+ u_int16_t s[4];
+ u_int32_t l[2];
+ u_int64_t q;
+};
+
+u_short
+in_addword(u_short a, u_short b)
+{
+ u_int64_t sum = a + b;
+
+ ADDCARRY(sum);
+ return (sum);
+}
+
+static
+uint64_t _do_cksum(void *addr, int len)
+{
+ uint64_t sum;
+ union q_util q_util;
+
+ sum = do_cksum(addr, len);
+ REDUCE32;
+ return (sum);
+}
+
+u_short
+in_cksum_skip(struct mbuf *m, int len, int skip)
+{
+ u_int64_t sum = 0;
+ int mlen = 0;
+ int clen = 0;
+ caddr_t addr;
+ union q_util q_util;
+ union l_util l_util;
+
+ len -= skip;
+ for (; skip && m; m = m->m_next) {
+ if (m->m_len > skip) {
+ mlen = m->m_len - skip;
+ addr = mtod(m, caddr_t) + skip;
+ goto skip_start;
+ } else {
+ skip -= m->m_len;
+ }
+ }
+
+ for (; m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ mlen = m->m_len;
+ addr = mtod(m, caddr_t);
+skip_start:
+ if (len < mlen)
+ mlen = len;
+
+ if ((clen ^ (int) addr) & 1)
+ sum += _do_cksum(addr, mlen) << 8;
+ else
+ sum += _do_cksum(addr, mlen);
+
+ clen += mlen;
+ len -= mlen;
+ }
+ REDUCE16;
+ return (~sum & 0xffff);
+}
+
+u_int in_cksum_hdr(const struct ip *ip)
+{
+ u_int64_t sum = do_cksum(ip, sizeof(struct ip));
+ union q_util q_util;
+ union l_util l_util;
+ REDUCE16;
+ return (~sum & 0xffff);
+}
Property changes on: trunk/sys/arm/arm/in_cksum.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/in_cksum_arm.S
===================================================================
--- trunk/sys/arm/arm/in_cksum_arm.S (rev 0)
+++ trunk/sys/arm/arm/in_cksum_arm.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,345 @@
+/* $MidnightBSD$ */
+/* $NetBSD: in_cksum_arm.S,v 1.2 2003/09/23 10:01:36 scw Exp $ */
+
+/*-
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Hand-optimised in_cksum() and in4_cksum() implementations for ARM/armv5e
+ */
+
+#include "opt_inet.h"
+
+#include <machine/asm.h>
+#include "assym.s"
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/in_cksum_arm.S 275767 2014-12-14 16:28:53Z andrew $");
+
+ .syntax unified
+/*
+ * int in_cksum(struct mbuf *m, int len)
+ *
+ * Entry:
+ * r0 m
+ * r1 len
+ *
+ * NOTE: Assumes 'm' is *never* NULL.
+ */
+/* LINTSTUB: Func: int in_cksum(struct mbuf *, int) */
+ENTRY(in_cksum)
+ stmfd sp!, {r4-r11,lr}
+ mov r8, #0x00
+ mov r9, r1
+ mov r10, #0x00
+ mov ip, r0
+
+.Lin_cksum_loop:
+ ldr r1, [ip, #(M_LEN)]
+ ldr r0, [ip, #(M_DATA)]
+ ldr ip, [ip, #(M_NEXT)]
+.Lin_cksum_entry4:
+ cmp r9, r1
+ movlt r1, r9
+ sub r9, r9, r1
+ eor r11, r10, r0
+ add r10, r10, r1
+ adds r2, r1, #0x00
+ blne _ASM_LABEL(L_cksumdata)
+ tst r11, #0x01
+ movne r2, r2, ror #8
+ adds r8, r8, r2
+ adc r8, r8, #0x00
+ cmp ip, #0x00
+ bne .Lin_cksum_loop
+
+ mov r1, #0xff
+ orr r1, r1, #0xff00
+ and r0, r8, r1
+ add r0, r0, r8, lsr #16
+ add r0, r0, r0, lsr #16
+ and r0, r0, r1
+ eor r0, r0, r1
+ ldmfd sp!, {r4-r11,pc}
+END(in_cksum)
+
+ENTRY(do_cksum)
+ stmfd sp!, {r4-r7, lr}
+ bl L_cksumdata
+ mov r0, r2
+ ldmfd sp!, {r4-r7, pc}
+END(do_cksum)
+
+/*
+ * The main in*_cksum() workhorse...
+ *
+ * Entry parameters:
+ * r0 Pointer to buffer
+ * r1 Buffer length
+ * lr Return address
+ *
+ * Returns:
+ * r2 Accumulated 32-bit sum
+ *
+ * Clobbers:
+ * r0-r7
+ */
+/* LINTSTUB: Ignore */
+ASENTRY_NP(L_cksumdata)
+#ifdef _ARM_ARCH_5E
+ pld [r0] /* Pre-fetch the start of the buffer */
+#endif
+ mov r2, #0
+
+ /* We first have to word-align the buffer. */
+ ands r7, r0, #0x03
+ beq .Lcksumdata_wordaligned
+ rsb r7, r7, #0x04
+ cmp r1, r7 /* Enough bytes left to make it? */
+ blt .Lcksumdata_endgame
+ cmp r7, #0x02
+ ldrb r4, [r0], #0x01 /* Fetch 1st byte */
+ ldrbge r5, [r0], #0x01 /* Fetch 2nd byte */
+ movlt r5, #0x00
+ ldrbgt r6, [r0], #0x01 /* Fetch 3rd byte */
+ movle r6, #0x00
+ /* Combine the three bytes depending on endianness and alignment */
+#ifdef __ARMEB__
+ orreq r2, r5, r4, lsl #8
+ orreq r2, r2, r6, lsl #24
+ orrne r2, r4, r5, lsl #8
+ orrne r2, r2, r6, lsl #16
+#else
+ orreq r2, r4, r5, lsl #8
+ orreq r2, r2, r6, lsl #16
+ orrne r2, r5, r4, lsl #8
+ orrne r2, r2, r6, lsl #24
+#endif
+ subs r1, r1, r7 /* Update length */
+ RETeq /* All done? */
+
+ /* Buffer is now word aligned */
+.Lcksumdata_wordaligned:
+#ifdef _ARM_ARCH_5E
+ cmp r1, #0x04 /* Less than 4 bytes left? */
+ blt .Lcksumdata_endgame /* Yup */
+
+ /* Now quad-align, if necessary */
+ ands r7, r0, #0x04
+ ldrne r7, [r0], #0x04
+ subne r1, r1, #0x04
+ subs r1, r1, #0x40
+ blt .Lcksumdata_bigloop_end /* Note: C flag clear if branch taken */
+
+ /*
+ * Buffer is now quad aligned. Sum 64 bytes at a time.
+ * Note: First ldrd is hoisted above the loop, together with
+ * setting r6 to zero to avoid stalling for results in the
+ * loop. (r7 is live, from above).
+ */
+ ldrd r4, [r0], #0x08
+ mov r6, #0x00
+.Lcksumdata_bigloop:
+ pld [r0, #0x18]
+ adds r2, r2, r6
+ adcs r2, r2, r7
+ ldrd r6, [r0], #0x08
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ ldrd r4, [r0], #0x08
+ adcs r2, r2, r6
+ adcs r2, r2, r7
+ ldrd r6, [r0], #0x08
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ ldrd r4, [r0], #0x08
+ adcs r2, r2, r6
+ adcs r2, r2, r7
+ pld [r0, #0x18]
+ ldrd r6, [r0], #0x08
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ ldrd r4, [r0], #0x08
+ adcs r2, r2, r6
+ adcs r2, r2, r7
+ ldrd r6, [r0], #0x08
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ adc r2, r2, #0x00
+ subs r1, r1, #0x40
+ ldrdge r4, [r0], #0x08
+ bge .Lcksumdata_bigloop
+
+ adds r2, r2, r6 /* r6/r7 still need summing */
+.Lcksumdata_bigloop_end:
+ adcs r2, r2, r7
+ adc r2, r2, #0x00
+
+#else /* !_ARM_ARCH_5E */
+
+ subs r1, r1, #0x40
+ blt .Lcksumdata_bigloop_end
+
+.Lcksumdata_bigloop:
+ ldmia r0!, {r3, r4, r5, r6}
+ adds r2, r2, r3
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ ldmia r0!, {r3, r4, r5, r7}
+ adcs r2, r2, r6
+ adcs r2, r2, r3
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ ldmia r0!, {r3, r4, r5, r6}
+ adcs r2, r2, r7
+ adcs r2, r2, r3
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ ldmia r0!, {r3, r4, r5, r7}
+ adcs r2, r2, r6
+ adcs r2, r2, r3
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ adcs r2, r2, r7
+ adc r2, r2, #0x00
+ subs r1, r1, #0x40
+ bge .Lcksumdata_bigloop
+.Lcksumdata_bigloop_end:
+#endif
+
+ adds r1, r1, #0x40
+ RETeq
+ cmp r1, #0x20
+
+#ifdef _ARM_ARCH_5E
+ ldrdge r4, [r0], #0x08 /* Avoid stalling pld and result */
+ blt .Lcksumdata_less_than_32
+ pld [r0, #0x18]
+ ldrd r6, [r0], #0x08
+ adds r2, r2, r4
+ adcs r2, r2, r5
+ ldrd r4, [r0], #0x08
+ adcs r2, r2, r6
+ adcs r2, r2, r7
+ ldrd r6, [r0], #0x08
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ adcs r2, r2, r6 /* XXX: Unavoidable result stall */
+ adcs r2, r2, r7
+#else
+ blt .Lcksumdata_less_than_32
+ ldmia r0!, {r3, r4, r5, r6}
+ adds r2, r2, r3
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ ldmia r0!, {r3, r4, r5, r7}
+ adcs r2, r2, r6
+ adcs r2, r2, r3
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ adcs r2, r2, r7
+#endif
+ adc r2, r2, #0x00
+ subs r1, r1, #0x20
+ RETeq
+
+.Lcksumdata_less_than_32:
+ /* There are less than 32 bytes left */
+ and r3, r1, #0x18
+ rsb r4, r3, #0x18
+ sub r1, r1, r3
+ adds r4, r4, r4, lsr #1 /* Side effect: Clear carry flag */
+ addne pc, pc, r4
+ nop
+
+/*
+ * Note: We use ldm here, even on armv5e, since the combined issue/result
+ * latencies for ldm and ldrd are the same. Using ldm avoids needless #ifdefs.
+ */
+ /* At least 24 bytes remaining... */
+ ldmia r0!, {r4, r5}
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+
+ /* At least 16 bytes remaining... */
+ ldmia r0!, {r4, r5}
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+
+ /* At least 8 bytes remaining... */
+ ldmia r0!, {r4, r5}
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+
+ /* Less than 8 bytes remaining... */
+ adc r2, r2, #0x00
+ subs r1, r1, #0x04
+ blt .Lcksumdata_lessthan4
+
+ ldr r4, [r0], #0x04
+ sub r1, r1, #0x04
+ adds r2, r2, r4
+ adc r2, r2, #0x00
+
+ /* Deal with < 4 bytes remaining */
+.Lcksumdata_lessthan4:
+ adds r1, r1, #0x04
+ RETeq
+
+ /* Deal with 1 to 3 remaining bytes, possibly misaligned */
+.Lcksumdata_endgame:
+ ldrb r3, [r0] /* Fetch first byte */
+ cmp r1, #0x02
+ ldrbge r4, [r0, #0x01] /* Fetch 2nd and 3rd as necessary */
+ movlt r4, #0x00
+ ldrbgt r5, [r0, #0x02]
+ movle r5, #0x00
+ /* Combine the three bytes depending on endianness and alignment */
+ tst r0, #0x01
+#ifdef __ARMEB__
+ orreq r3, r4, r3, lsl #8
+ orreq r3, r3, r5, lsl #24
+ orrne r3, r3, r4, lsl #8
+ orrne r3, r3, r5, lsl #16
+#else
+ orreq r3, r3, r4, lsl #8
+ orreq r3, r3, r5, lsl #16
+ orrne r3, r4, r3, lsl #8
+ orrne r3, r3, r5, lsl #24
+#endif
+ adds r2, r2, r3
+ adc r2, r2, #0x00
+ RET
+END(L_cksumdata)
+
Property changes on: trunk/sys/arm/arm/in_cksum_arm.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/inckern.S
===================================================================
--- trunk/sys/arm/arm/inckern.S (rev 0)
+++ trunk/sys/arm/arm/inckern.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,43 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_kernname.h"
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/inckern.S 159557 2006-06-12 22:58:50Z cognet $")
+ENTRY(do_call)
+ mov r6, r0
+ mov r0, r1
+ ldr r1, =0xfff00000
+ and r1, pc, r1
+ mov sp, r3
+ mov r3, #1
+ mov pc, r6
+.section ".real_kernel","aw"
+.globl kernel_start;
+kernel_start:
+.incbin KERNNAME
+.globl kernel_end;
+kernel_end:
Property changes on: trunk/sys/arm/arm/inckern.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/intr.c
===================================================================
--- trunk/sys/arm/arm/intr.c (rev 0)
+++ trunk/sys/arm/arm/intr.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,219 @@
+/* $MidnightBSD$ */
+/* $NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2004 Olivier Houchard.
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Soft interrupt and other generic interrupt functions.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/intr.c 270077 2014-08-17 01:48:12Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/syslog.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/conf.h>
+#include <machine/atomic.h>
+#include <machine/intr.h>
+#include <machine/cpu.h>
+
+#define INTRNAME_LEN (MAXCOMLEN + 1)
+
+typedef void (*mask_fn)(void *);
+
+static struct intr_event *intr_events[NIRQ];
+
+void arm_irq_handler(struct trapframe *);
+
+void (*arm_post_filter)(void *) = NULL;
+int (*arm_config_irq)(int irq, enum intr_trigger trig,
+ enum intr_polarity pol) = NULL;
+
+/* Data for statistics reporting. */
+u_long intrcnt[NIRQ];
+char intrnames[NIRQ * INTRNAME_LEN];
+size_t sintrcnt = sizeof(intrcnt);
+size_t sintrnames = sizeof(intrnames);
+
+/*
+ * Pre-format intrnames into an array of fixed-size strings containing spaces.
+ * This allows us to avoid the need for an intermediate table of indices into
+ * the names and counts arrays, while still meeting the requirements and
+ * assumptions of vmstat(8) and the kdb "show intrcnt" command, the two
+ * consumers of this data.
+ */
+static void
+intr_init(void *unused)
+{
+ int i;
+
+ for (i = 0; i < NIRQ; ++i) {
+ snprintf(&intrnames[i * INTRNAME_LEN], INTRNAME_LEN, "%-*s",
+ INTRNAME_LEN - 1, "");
+ }
+}
+
+SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
+
+void
+arm_setup_irqhandler(const char *name, driver_filter_t *filt,
+ void (*hand)(void*), void *arg, int irq, int flags, void **cookiep)
+{
+ struct intr_event *event;
+ int error;
+
+ if (irq < 0 || irq >= NIRQ)
+ return;
+ event = intr_events[irq];
+ if (event == NULL) {
+ error = intr_event_create(&event, (void *)irq, 0, irq,
+ (mask_fn)arm_mask_irq, (mask_fn)arm_unmask_irq,
+ arm_post_filter, NULL, "intr%d:", irq);
+ if (error)
+ return;
+ intr_events[irq] = event;
+ snprintf(&intrnames[irq * INTRNAME_LEN], INTRNAME_LEN,
+ "irq%d: %-*s", irq, INTRNAME_LEN - 1, name);
+ }
+ intr_event_add_handler(event, name, filt, hand, arg,
+ intr_priority(flags), flags, cookiep);
+}
+
+int
+arm_remove_irqhandler(int irq, void *cookie)
+{
+ struct intr_event *event;
+ int error;
+
+ event = intr_events[irq];
+ arm_mask_irq(irq);
+
+ error = intr_event_remove_handler(cookie);
+
+ if (!TAILQ_EMPTY(&event->ie_handlers))
+ arm_unmask_irq(irq);
+ return (error);
+}
+
+void dosoftints(void);
+void
+dosoftints(void)
+{
+}
+
+void
+arm_irq_handler(struct trapframe *frame)
+{
+ struct intr_event *event;
+ int i;
+
+ PCPU_INC(cnt.v_intr);
+ i = -1;
+ while ((i = arm_get_next_irq(i)) != -1) {
+ intrcnt[i]++;
+ event = intr_events[i];
+ if (intr_event_handle(event, frame) != 0) {
+ /* XXX: Log stray IRQs */
+ arm_mask_irq(i);
+ }
+ }
+}
+
+/*
+ * arm_irq_memory_barrier()
+ *
+ * Ensure all writes to device memory have reached devices before proceeding.
+ *
+ * This is intended to be called from the post-filter and post-thread routines
+ * of an interrupt controller implementation. A peripheral device driver should
+ * use bus_space_barrier() if it needs to ensure a write has reached the
+ * hardware for some reason other than clearing interrupt conditions.
+ *
+ * The need for this function arises from the ARM weak memory ordering model.
+ * Writes to locations mapped with the Device attribute bypass any caches, but
+ * are buffered. Multiple writes to the same device will be observed by that
+ * device in the order issued by the cpu. Writes to different devices may
+ * appear at those devices in a different order than issued by the cpu. That
+ * is, if the cpu writes to device A then device B, the write to device B could
+ * complete before the write to device A.
+ *
+ * Consider a typical device interrupt handler which services the interrupt and
+ * writes to a device status-acknowledge register to clear the interrupt before
+ * returning. That write is posted to the L2 controller which "immediately"
+ * places it in a store buffer and automatically drains that buffer. This can
+ * be less immediate than you'd think... There may be no free slots in the store
+ * buffers, so an existing buffer has to be drained first to make room. The
+ * target bus may be busy with other traffic (such as DMA for various devices),
+ * delaying the drain of the store buffer for some indeterminate time. While
+ * all this delay is happening, execution proceeds on the CPU, unwinding its way
+ * out of the interrupt call stack to the point where the interrupt driver code
+ * is ready to EOI and unmask the interrupt. The interrupt controller may be
+ * accessed via a faster bus than the hardware whose handler just ran; the write
+ * to unmask and EOI the interrupt may complete quickly while the device write
+ * to ack and clear the interrupt source is still lingering in a store buffer
+ * waiting for access to a slower bus. With the interrupt unmasked at the
+ * interrupt controller but still active at the device, as soon as interrupts
+ * are enabled on the core the device re-interrupts immediately: now you've got
+ * a spurious interrupt on your hands.
+ *
+ * The right way to fix this problem is for every device driver to use the
+ * proper bus_space_barrier() calls in its interrupt handler. For ARM a single
+ * barrier call at the end of the handler would work. This would have to be
+ * done to every driver in the system, not just arm-specific drivers.
+ *
+ * Another potential fix is to map all device memory as Strongly-Ordered rather
+ * than Device memory, which takes the store buffers out of the picture. This
+ * has a pretty big impact on overall system performance, because each strongly
+ * ordered memory access causes all L2 store buffers to be drained.
+ *
+ * A compromise solution is to have the interrupt controller implementation call
+ * this function to establish a barrier between writes to the interrupt-source
+ * device and writes to the interrupt controller device.
+ *
+ * This takes the interrupt number as an argument, and currently doesn't use it.
+ * The plan is that maybe some day there is a way to flag certain interrupts as
+ * "memory barrier safe" and we can avoid this overhead with them.
+ */
+void
+arm_irq_memory_barrier(uintptr_t irq)
+{
+
+ dsb();
+ cpu_l2cache_drain_writebuf();
+}
+
Property changes on: trunk/sys/arm/arm/intr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/locore-v4.S
===================================================================
--- trunk/sys/arm/arm/locore-v4.S (rev 0)
+++ trunk/sys/arm/arm/locore-v4.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,484 @@
+/* $MidnightBSD$ */
+/* $NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $ */
+
+/*-
+ * Copyright 2011 Semihalf
+ * Copyright (C) 1994-1997 Mark Brinicombe
+ * Copyright (C) 1994 Brini
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of Brini may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "assym.s"
+#include <sys/syscall.h>
+#include <machine/asm.h>
+#include <machine/armreg.h>
+#include <machine/cpuconf.h>
+#include <machine/pte.h>
+
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/locore-v4.S 294682 2016-01-24 20:15:52Z ian $");
+
+/* 2K initial stack is plenty, it is only used by initarm() */
+#define INIT_ARM_STACK_SIZE 2048
+
+#define CPWAIT_BRANCH \
+ sub pc, pc, #4
+
+#define CPWAIT(tmp) \
+ mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
+ mov tmp, tmp /* wait for it to complete */ ;\
+ CPWAIT_BRANCH /* branch to next insn */
+
+/*
+ * This is for libkvm, and should be the address of the beginning
+ * of the kernel text segment (not necessarily the same as kernbase).
+ *
+ * These are being phased out. Newer copies of libkvm don't need these
+ * values as the information is added to the core file by inspecting
+ * the running kernel.
+ */
+ .text
+ .align 2
+#ifdef PHYSADDR
+.globl kernbase
+.set kernbase,KERNBASE
+.globl physaddr
+.set physaddr,PHYSADDR
+#endif
+
+/*
+ * On entry for FreeBSD boot ABI:
+ * r0 - metadata pointer or 0 (boothowto on AT91's boot2)
+ * r1 - if (r0 == 0) then metadata pointer
+ * On entry for Linux boot ABI:
+ * r0 - 0
+ * r1 - machine type (passed as arg2 to initarm)
+ * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
+ *
+ * For both types of boot we gather up the args, put them in a struct arm_boot_params
+ * structure and pass that to initarm.
+ */
+ .globl btext
+btext:
+ASENTRY_NP(_start)
+ STOP_UNWINDING /* Can't unwind into the bootloader! */
+
+ mov r9, r0 /* 0 or boot mode from boot2 */
+ mov r8, r1 /* Save Machine type */
+ mov ip, r2 /* Save meta data */
+ mov fp, r3 /* Future expansion */
+
+ /* Make sure interrupts are disabled. */
+ mrs r7, cpsr
+ orr r7, r7, #(PSR_I | PSR_F)
+ msr cpsr_c, r7
+
+#if defined (FLASHADDR) && defined(LOADERRAMADDR)
+/*
+ * Sanity check the configuration.
+ * FLASHADDR and LOADERRAMADDR depend on PHYSADDR in some cases.
+ * ARMv4 and ARMv5 make assumptions on where they are loaded.
+ * TODO: Fix the ARMv4/v5 case.
+ */
+#ifndef PHYSADDR
+#error PHYSADDR must be defined for this configuration
+#endif
+
+ /* Check if we're running from flash. */
+ ldr r7, =FLASHADDR
+ /*
+ * If we're running with MMU disabled, test against the
+ * physical address instead.
+ */
+ mrc p15, 0, r2, c1, c0, 0
+ ands r2, r2, #CPU_CONTROL_MMU_ENABLE
+ ldreq r6, =PHYSADDR
+ ldrne r6, =LOADERRAMADDR
+ cmp r7, r6
+ bls flash_lower
+ cmp r7, pc
+ bhi from_ram
+ b do_copy
+
+flash_lower:
+ cmp r6, pc
+ bls from_ram
+do_copy:
+ ldr r7, =KERNBASE
+ adr r1, _start
+ ldr r0, Lreal_start
+ ldr r2, Lend
+ sub r2, r2, r0
+ sub r0, r0, r7
+ add r0, r0, r6
+ mov r4, r0
+ bl memcpy
+ ldr r0, Lram_offset
+ add pc, r4, r0
+Lram_offset: .word from_ram-_C_LABEL(_start)
+from_ram:
+ nop
+#endif
+
+disable_mmu:
+ /* Disable MMU for a while */
+ mrc p15, 0, r2, c1, c0, 0
+ bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
+ CPU_CONTROL_WBUF_ENABLE)
+ bic r2, r2, #(CPU_CONTROL_IC_ENABLE)
+ bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
+ mcr p15, 0, r2, c1, c0, 0
+
+ nop
+ nop
+ nop
+ CPWAIT(r0)
+
+Lunmapped:
+ /*
+ * Build page table from scratch.
+ */
+
+ /*
+ * Figure out the physical address we're loaded at by assuming this
+ * entry point code is in the first L1 section and so if we clear the
+ * offset bits of the pc that will give us the section-aligned load
+ * address, which remains in r5 throughout all the following code.
+ */
+ ldr r2, =(L1_S_OFFSET)
+ bic r5, pc, r2
+
+ /* Find the delta between VA and PA, result stays in r0 throughout. */
+ adr r0, Lpagetable
+ bl translate_va_to_pa
+
+ /*
+ * First map the entire 4GB address space as VA=PA. It's mapped as
+ * normal (cached) memory because it's for things like accessing the
+ * parameters passed in from the bootloader, which might be at any
+ * physical address, different for every platform.
+ */
+ mov r1, #0
+ mov r2, #0
+ mov r3, #4096
+ bl build_pagetables
+
+ /*
+ * Next we do 64MiB starting at the physical load address, mapped to
+ * the VA the kernel is linked for.
+ */
+ mov r1, r5
+ ldr r2, =(KERNVIRTADDR)
+ mov r3, #64
+ bl build_pagetables
+
+ /* Create a device mapping for early_printf if specified. */
+#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
+ ldr r1, =SOCDEV_PA
+ ldr r2, =SOCDEV_VA
+ mov r3, #1
+ bl build_device_pagetables
+#endif
+
+ mcr p15, 0, r0, c2, c0, 0 /* Set TTB */
+ mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */
+
+ /* Set the Domain Access register. Very important! */
+ mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
+ mcr p15, 0, r0, c3, c0, 0
+ /*
+ * Enable MMU.
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ orr r0, r0, #(CPU_CONTROL_MMU_ENABLE)
+ mcr p15, 0, r0, c1, c0, 0
+ nop
+ nop
+ nop
+ CPWAIT(r0)
+
+ /* Transition the PC from physical to virtual addressing. */
+ ldr pc,=mmu_done
+
+mmu_done:
+ nop
+ adr r1, .Lstart
+ ldmia r1, {r1, r2, sp} /* Set initial stack and */
+ sub r2, r2, r1 /* get zero init data */
+ mov r3, #0
+.L1:
+ str r3, [r1], #0x0004 /* get zero init data */
+ subs r2, r2, #4
+ bgt .L1
+
+virt_done:
+ mov r1, #28 /* loader info size is 28 bytes also second arg */
+ subs sp, sp, r1 /* allocate arm_boot_params struct on stack */
+ mov r0, sp /* loader info pointer is first arg */
+ bic sp, sp, #7 /* align stack to 8 bytes */
+ str r1, [r0] /* Store length of loader info */
+ str r9, [r0, #4] /* Store r0 from boot loader */
+ str r8, [r0, #8] /* Store r1 from boot loader */
+ str ip, [r0, #12] /* store r2 from boot loader */
+ str fp, [r0, #16] /* store r3 from boot loader */
+ str r5, [r0, #20] /* store the physical address */
+ adr r4, Lpagetable /* load the pagetable address */
+ ldr r5, [r4, #4]
+ str r5, [r0, #24] /* store the pagetable address */
+ mov fp, #0 /* trace back starts here */
+ bl _C_LABEL(initarm) /* Off we go */
+
+ /* init arm will return the new stack pointer. */
+ mov sp, r0
+
+ bl _C_LABEL(mi_startup) /* call mi_startup()! */
+
+ adr r0, .Lmainreturned
+ b _C_LABEL(panic)
+ /* NOTREACHED */
+END(_start)
+
+#define VA_TO_PA_POINTER(name, table) \
+name: ;\
+ .word . ;\
+ .word table
+
+/*
+ * Returns the physical address of a magic va to pa pointer.
+ * r0 - The pagetable data pointer. This must be built using the
+ * VA_TO_PA_POINTER macro.
+ * e.g.
+ * VA_TO_PA_POINTER(Lpagetable, pagetable)
+ * ...
+ * adr r0, Lpagetable
+ * bl translate_va_to_pa
+ * r0 will now contain the physical address of pagetable
+ * r1, r2 - Trashed
+ */
+translate_va_to_pa:
+ ldr r1, [r0]
+ sub r2, r1, r0
+ /* At this point: r2 = VA - PA */
+
+ /*
+ * Find the physical address of the table. After these two
+ * instructions:
+ * r1 = va(pagetable)
+ *
+ * r0 = va(pagetable) - (VA - PA)
+ * = va(pagetable) - VA + PA
+ * = pa(pagetable)
+ */
+ ldr r1, [r0, #4]
+ sub r0, r1, r2
+ RET
+
+/*
+ * Builds the page table
+ * r0 - The table base address
+ * r1 - The physical address (trashed)
+ * r2 - The virtual address (trashed)
+ * r3 - The number of 1MiB sections
+ * r4 - Trashed
+ *
+ * Addresses must be 1MiB aligned
+ */
+build_device_pagetables:
+ ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW))
+ b 1f
+build_pagetables:
+ /* Set the required page attributed */
+ ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
+1:
+ orr r1, r4
+
+ /* Move the virtual address to the correct bit location */
+ lsr r2, #(L1_S_SHIFT - 2)
+
+ mov r4, r3
+2:
+ str r1, [r0, r2]
+ add r2, r2, #4
+ add r1, r1, #(L1_S_SIZE)
+ adds r4, r4, #-1
+ bhi 2b
+
+ RET
+
+VA_TO_PA_POINTER(Lpagetable, pagetable)
+
+Lreal_start:
+ .word _start
+Lend:
+ .word _edata
+
+.Lstart:
+ .word _edata
+ .word _ebss
+ .word svcstk + INIT_ARM_STACK_SIZE
+
+.Lvirt_done:
+ .word virt_done
+
+.Lmainreturned:
+ .asciz "main() returned"
+ .align 2
+
+ .bss
+svcstk:
+ .space INIT_ARM_STACK_SIZE
+
+/*
+ * Memory for the initial pagetable. We are unable to place this in
+ * the bss as this will be cleared after the table is loaded.
+ */
+ .section ".init_pagetable"
+ .align 14 /* 16KiB aligned */
+pagetable:
+ .space L1_TABLE_SIZE
+
+ .text
+ .align 2
+
+.Lcpufuncs:
+ .word _C_LABEL(cpufuncs)
+
+ENTRY_NP(cpu_halt)
+ mrs r2, cpsr
+ bic r2, r2, #(PSR_MODE)
+ orr r2, r2, #(PSR_SVC32_MODE)
+ orr r2, r2, #(PSR_I | PSR_F)
+ msr cpsr_fsxc, r2
+
+ ldr r4, .Lcpu_reset_address
+ ldr r4, [r4]
+
+ ldr r0, .Lcpufuncs
+ mov lr, pc
+ ldr pc, [r0, #CF_IDCACHE_WBINV_ALL]
+ mov lr, pc
+ ldr pc, [r0, #CF_L2CACHE_WBINV_ALL]
+
+ /*
+ * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
+ * necessary.
+ */
+
+ ldr r1, .Lcpu_reset_needs_v4_MMU_disable
+ ldr r1, [r1]
+ cmp r1, #0
+ mov r2, #0
+
+ /*
+ * MMU & IDC off, 32 bit program & data space
+ * Hurl ourselves into the ROM
+ */
+ mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
+ mcr p15, 0, r0, c1, c0, 0
+ mcrne p15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */
+ mov pc, r4
+
+ /*
+ * _cpu_reset_address contains the address to branch to, to complete
+ * the cpu reset after turning the MMU off
+ * This variable is provided by the hardware specific code
+ */
+.Lcpu_reset_address:
+ .word _C_LABEL(cpu_reset_address)
+
+ /*
+ * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
+ * v4 MMU disable instruction needs executing... it is an illegal instruction
+ * on f.e. ARM6/7 that locks up the computer in an endless illegal
+ * instruction / data-abort / reset loop.
+ */
+.Lcpu_reset_needs_v4_MMU_disable:
+ .word _C_LABEL(cpu_reset_needs_v4_MMU_disable)
+END(cpu_halt)
+
+
+/*
+ * setjump + longjmp
+ */
+ENTRY(setjmp)
+ stmia r0, {r4-r14}
+ mov r0, #0x00000000
+ RET
+END(setjmp)
+
+ENTRY(longjmp)
+ ldmia r0, {r4-r14}
+ mov r0, #0x00000001
+ RET
+END(longjmp)
+
+ .data
+ .global _C_LABEL(esym)
+_C_LABEL(esym): .word _C_LABEL(end)
+
+ENTRY_NP(abort)
+ b _C_LABEL(abort)
+END(abort)
+
+ENTRY_NP(sigcode)
+ mov r0, sp
+ add r0, r0, #SIGF_UC
+
+ /*
+ * Call the sigreturn system call.
+ *
+ * We have to load r7 manually rather than using
+ * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
+ * correct. Using the alternative places esigcode at the address
+ * of the data rather than the address one past the data.
+ */
+
+ ldr r7, [pc, #12] /* Load SYS_sigreturn */
+ swi SYS_sigreturn
+
+ /* Well if that failed we better exit quick ! */
+
+ ldr r7, [pc, #8] /* Load SYS_exit */
+ swi SYS_exit
+
+ /* Branch back to retry SYS_sigreturn */
+ b . - 16
+END(sigcode)
+ .word SYS_sigreturn
+ .word SYS_exit
+
+ .align 2
+ .global _C_LABEL(esigcode)
+ _C_LABEL(esigcode):
+
+ .data
+ .global szsigcode
+szsigcode:
+ .long esigcode-sigcode
+
+/* End of locore.S */
Property changes on: trunk/sys/arm/arm/locore-v4.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/locore-v6.S
===================================================================
--- trunk/sys/arm/arm/locore-v6.S (rev 0)
+++ trunk/sys/arm/arm/locore-v6.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,567 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2004-2014 Olivier Houchard <cognet at FreeBSD.org>
+ * Copyright 2012-2014 Ian Lepore <ian at FreeBSD.org>
+ * Copyright 2013-2014 Andrew Turner <andrew at FreeBSD.org>
+ * Copyright 2014 Svatopluk Kraus <onwahe at gmail.com>
+ * Copyright 2014 Michal Meloun <meloun at miracle.cz>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "assym.s"
+#include <sys/syscall.h>
+#include <machine/asm.h>
+#include <machine/asmacros.h>
+#include <machine/armreg.h>
+#include <machine/sysreg.h>
+#include <machine/cpuconf.h>
+#include <machine/pte.h>
+
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/locore-v6.S 294682 2016-01-24 20:15:52Z ian $");
+
+#ifndef ARM_NEW_PMAP
+#define PTE1_OFFSET L1_S_OFFSET
+#define PTE1_SHIFT L1_S_SHIFT
+#define PTE1_SIZE L1_S_SIZE
+#endif
+
+/* A small statically-allocated stack used only during initarm() and AP startup. */
+#define INIT_ARM_STACK_SIZE 2048
+
+ .text
+ .align 2
+
+/*
+ * On entry for FreeBSD boot ABI:
+ * r0 - metadata pointer or 0 (boothowto on AT91's boot2)
+ * r1 - if (r0 == 0) then metadata pointer
+ * On entry for Linux boot ABI:
+ * r0 - 0
+ * r1 - machine type (passed as arg2 to initarm)
+ * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
+ *
+ * For both types of boot we gather up the args, put them in a struct arm_boot_params
+ * structure and pass that to initarm.
+ */
+ .globl btext
+btext:
+ASENTRY_NP(_start)
+ STOP_UNWINDING /* Can't unwind into the bootloader! */
+
+ /* Make sure interrupts are disabled. */
+ cpsid ifa
+
+ mov r8, r0 /* 0 or boot mode from boot2 */
+ mov r9, r1 /* Save Machine type */
+ mov r10, r2 /* Save meta data */
+ mov r11, r3 /* Future expansion */
+
+ /*
+ * Check whether data cache is enabled. If it is, then we know
+ * current tags are valid (not power-on garbage values) and there
+ * might be dirty lines that need cleaning. Disable cache to prevent
+ * new lines being allocated, then call wbinv_poc_all to clean it.
+ */
+ mrc CP15_SCTLR(r7)
+ tst r7, #CPU_CONTROL_DC_ENABLE
+ blne dcache_wbinv_poc_all
+
+ /* ! Do not write to memory between wbinv and disabling cache ! */
+
+ /*
+ * Now there are no dirty lines, but there may still be lines marked
+ * valid. Disable all caches and the MMU, and invalidate everything
+ * before setting up new page tables and re-enabling the mmu.
+ */
+1:
+ bic r7, #CPU_CONTROL_DC_ENABLE
+ bic r7, #CPU_CONTROL_MMU_ENABLE
+ bic r7, #CPU_CONTROL_IC_ENABLE
+ bic r7, #CPU_CONTROL_UNAL_ENABLE
+ bic r7, #CPU_CONTROL_BPRD_ENABLE
+ bic r7, #CPU_CONTROL_SW_ENABLE
+ orr r7, #CPU_CONTROL_AFLT_ENABLE
+ orr r7, #CPU_CONTROL_VECRELOC
+ mcr CP15_SCTLR(r7)
+ DSB
+ ISB
+ bl dcache_inv_poc_all
+ mcr CP15_ICIALLU
+ DSB
+ ISB
+
+ /*
+ * Build page table from scratch.
+ */
+
+ /*
+ * Figure out the physical address we're loaded at by assuming this
+ * entry point code is in the first L1 section and so if we clear the
+ * offset bits of the pc that will give us the section-aligned load
+ * address, which remains in r5 throughout all the following code.
+ */
+ ldr r2, =(L1_S_OFFSET)
+ bic r5, pc, r2
+
+ /* Find the delta between VA and PA, result stays in r0 throughout. */
+ adr r0, Lpagetable
+ bl translate_va_to_pa
+
+ /*
+ * First map the entire 4GB address space as VA=PA. It's mapped as
+ * normal (cached) memory because it's for things like accessing the
+ * parameters passed in from the bootloader, which might be at any
+ * physical address, different for every platform.
+ */
+ mov r1, #0
+ mov r2, #0
+ mov r3, #4096
+ bl build_pagetables
+
+ /*
+ * Next we do 64MiB starting at the physical load address, mapped to
+ * the VA the kernel is linked for.
+ */
+ mov r1, r5
+ ldr r2, =(KERNVIRTADDR)
+ mov r3, #64
+ bl build_pagetables
+
+ /* Create a device mapping for early_printf if specified. */
+#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
+ ldr r1, =SOCDEV_PA
+ ldr r2, =SOCDEV_VA
+ mov r3, #1
+ bl build_device_pagetables
+#endif
+ bl init_mmu
+
+ /* Transition the PC from physical to virtual addressing. */
+ ldr pc, =1f
+1:
+
+ /* Setup stack, clear BSS */
+ ldr r1, =.Lstart
+ ldmia r1, {r1, r2, sp} /* Set initial stack and */
+ add sp, sp, #INIT_ARM_STACK_SIZE
+ sub r2, r2, r1 /* get zero init data */
+ mov r3, #0
+2:
+ str r3, [r1], #0x0004 /* get zero init data */
+ subs r2, r2, #4
+ bgt 2b
+
+ mov r1, #28 /* loader info size is 28 bytes also second arg */
+ subs sp, sp, r1 /* allocate arm_boot_params struct on stack */
+ mov r0, sp /* loader info pointer is first arg */
+ bic sp, sp, #7 /* align stack to 8 bytes */
+ str r1, [r0] /* Store length of loader info */
+ str r8, [r0, #4] /* Store r0 from boot loader */
+ str r9, [r0, #8] /* Store r1 from boot loader */
+ str r10, [r0, #12] /* store r2 from boot loader */
+ str r11, [r0, #16] /* store r3 from boot loader */
+ str r5, [r0, #20] /* store the physical address */
+ adr r4, Lpagetable /* load the pagetable address */
+ ldr r5, [r4, #4]
+ str r5, [r0, #24] /* store the pagetable address */
+ mov fp, #0 /* trace back starts here */
+ bl _C_LABEL(initarm) /* Off we go */
+
+ /* init arm will return the new stack pointer. */
+ mov sp, r0
+
+ bl _C_LABEL(mi_startup) /* call mi_startup()! */
+
+ ldr r0, =.Lmainreturned
+ b _C_LABEL(panic)
+ /* NOTREACHED */
+END(_start)
+
+#define VA_TO_PA_POINTER(name, table) \
+name: ;\
+ .word . ;\
+ .word table
+
+/*
+ * Returns the physical address of a magic va to pa pointer.
+ * r0 - The pagetable data pointer. This must be built using the
+ * VA_TO_PA_POINTER macro.
+ * e.g.
+ * VA_TO_PA_POINTER(Lpagetable, pagetable)
+ * ...
+ * adr r0, Lpagetable
+ * bl translate_va_to_pa
+ * r0 will now contain the physical address of pagetable
+ * r1, r2 - Trashed
+ */
+translate_va_to_pa:
+ ldr r1, [r0]
+ sub r2, r1, r0
+ /* At this point: r2 = VA - PA */
+
+ /*
+ * Find the physical address of the table. After these two
+ * instructions:
+ * r1 = va(pagetable)
+ *
+ * r0 = va(pagetable) - (VA - PA)
+ * = va(pagetable) - VA + PA
+ * = pa(pagetable)
+ */
+ ldr r1, [r0, #4]
+ sub r0, r1, r2
+ mov pc, lr
+
+/*
+ * Init MMU
+ * r0 - the table base address
+ */
+
+ASENTRY_NP(init_mmu)
+
+ /* Setup TLB and MMU registers */
+ mcr CP15_TTBR0(r0) /* Set TTB */
+ mov r0, #0
+ mcr CP15_CONTEXTIDR(r0) /* Set ASID to 0 */
+
+ /* Set the Domain Access register */
+ mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
+ mcr CP15_DACR(r0)
+
+#ifdef ARM_NEW_PMAP
+ /*
+ * Set TEX remap registers
+ * - All is set to uncacheable memory
+ */
+ ldr r0, =0xAAAAA
+ mrc CP15_PRRR(r0)
+ mov r0, #0
+ mcr CP15_NMRR(r0)
+#endif
+ mcr CP15_TLBIALL /* Flush TLB */
+ DSB
+ ISB
+
+ /* Enable MMU */
+ mrc CP15_SCTLR(r0)
+ orr r0, r0, #CPU_CONTROL_MMU_ENABLE
+ orr r0, r0, #CPU_CONTROL_V6_EXTPAGE
+#ifdef ARM_NEW_PMAP
+ orr r0, r0, #CPU_CONTROL_TR_ENABLE
+#endif
+ orr r0, r0, #CPU_CONTROL_AF_ENABLE
+ mcr CP15_SCTLR(r0)
+ DSB
+ ISB
+ mcr CP15_TLBIALL /* Flush TLB */
+ mcr CP15_BPIALL /* Flush Branch predictor */
+ DSB
+ ISB
+
+ mov pc, lr
+END(init_mmu)
+
+
+/*
+ * Init SMP coherent mode, enable caching and switch to final MMU table.
+ * Called with disabled caches
+ * r0 - The table base address
+ * r1 - clear bits for aux register
+ * r2 - set bits for aux register
+ */
+ASENTRY_NP(reinit_mmu)
+ push {r4-r11, lr}
+ mov r4, r0
+ mov r5, r1
+ mov r6, r2
+
+ /* !! Be very paranoid here !! */
+ /* !! We cannot write single bit here !! */
+
+#if 0 /* XXX writeback shouldn't be necessary */
+ /* Write back and invalidate all integrated caches */
+ bl dcache_wbinv_poc_all
+#else
+ bl dcache_inv_pou_all
+#endif
+ mcr CP15_ICIALLU
+ DSB
+ ISB
+
+ /* Set auxiliary register */
+ mrc CP15_ACTLR(r7)
+ bic r8, r7, r5 /* Mask bits */
+ eor r8, r8, r6 /* Set bits */
+ teq r7, r8
+ mcrne CP15_ACTLR(r8)
+ DSB
+ ISB
+
+ /* Enable caches. */
+ mrc CP15_SCTLR(r7)
+ orr r7, #CPU_CONTROL_DC_ENABLE
+ orr r7, #CPU_CONTROL_IC_ENABLE
+ orr r7, #CPU_CONTROL_BPRD_ENABLE
+ mcr CP15_SCTLR(r7)
+ DSB
+
+ mcr CP15_TTBR0(r4) /* Set new TTB */
+ DSB
+ ISB
+
+ mcr CP15_TLBIALL /* Flush TLB */
+ mcr CP15_BPIALL /* Flush Branch predictor */
+ DSB
+ ISB
+
+#if 0 /* XXX writeback shouldn't be necessary */
+ /* Write back and invalidate all integrated caches */
+ bl dcache_wbinv_poc_all
+#else
+ bl dcache_inv_pou_all
+#endif
+ mcr CP15_ICIALLU
+ DSB
+ ISB
+
+ pop {r4-r11, pc}
+END(reinit_mmu)
+
+
+/*
+ * Builds the page table
+ * r0 - The table base address
+ * r1 - The physical address (trashed)
+ * r2 - The virtual address (trashed)
+ * r3 - The number of 1MiB sections
+ * r4 - Trashed
+ *
+ * Addresses must be 1MiB aligned
+ */
+build_device_pagetables:
+#if defined(ARM_NEW_PMAP)
+ ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0
+#elif defined(SMP)
+ ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)|L1_SHARED)
+#else
+ ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW))
+#endif
+ b 1f
+build_pagetables:
+ /* Set the required page attributed */
+#if defined(ARM_NEW_PMAP)
+ ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0
+#elif defined(SMP)
+ ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)|L1_SHARED)
+#else
+ ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
+#endif
+1:
+ orr r1, r4
+
+ /* Move the virtual address to the correct bit location */
+ lsr r2, #(PTE1_SHIFT - 2)
+
+ mov r4, r3
+2:
+ str r1, [r0, r2]
+ add r2, r2, #4
+ add r1, r1, #(PTE1_SIZE)
+ adds r4, r4, #-1
+ bhi 2b
+
+ mov pc, lr
+
+VA_TO_PA_POINTER(Lpagetable, boot_pt1)
+
+
+.Lstart:
+ .word _edata /* Note that these three items are */
+ .word _ebss /* loaded with a single ldmia and */
+ .word svcstk /* must remain in order together. */
+
+.Lmainreturned:
+ .asciz "main() returned"
+ .align 2
+
+ .bss
+svcstk:
+ .space INIT_ARM_STACK_SIZE * MAXCPU
+
+/*
+ * Memory for the initial pagetable. We are unable to place this in
+ * the bss as this will be cleared after the table is loaded.
+ */
+ .section ".init_pagetable"
+ .align 14 /* 16KiB aligned */
+ .globl boot_pt1
+boot_pt1:
+ .space L1_TABLE_SIZE
+
+ .text
+ .align 2
+
+.Lcpufuncs:
+ .word _C_LABEL(cpufuncs)
+
+#if defined(SMP)
+
+ASENTRY_NP(mpentry)
+ /* Make sure interrupts are disabled. */
+ cpsid ifa
+
+ /* Setup core, disable all caches. */
+ mrc CP15_SCTLR(r0)
+ bic r0, #CPU_CONTROL_MMU_ENABLE
+ bic r0, #CPU_CONTROL_DC_ENABLE
+ bic r0, #CPU_CONTROL_IC_ENABLE
+ bic r0, #CPU_CONTROL_UNAL_ENABLE
+ bic r0, #CPU_CONTROL_BPRD_ENABLE
+ bic r0, #CPU_CONTROL_SW_ENABLE
+ orr r0, #CPU_CONTROL_AFLT_ENABLE
+ orr r0, #CPU_CONTROL_VECRELOC
+ mcr CP15_SCTLR(r0)
+ DSB
+ ISB
+
+ /* Invalidate L1 cache I+D cache */
+ bl dcache_inv_pou_all
+ mcr CP15_ICIALLU
+ DSB
+ ISB
+
+ /* Find the delta between VA and PA */
+ adr r0, Lpagetable
+ bl translate_va_to_pa
+
+ bl init_mmu
+
+ adr r1, .Lstart+8 /* Get initstack pointer from */
+ ldr sp, [r1] /* startup data. */
+ mrc CP15_MPIDR(r0) /* Get processor id number. */
+ and r0, r0, #0x0f
+ mov r1, #INIT_ARM_STACK_SIZE
+ mul r2, r1, r0 /* Point sp to initstack */
+ add sp, sp, r2 /* area for this processor. */
+
+ /* Switch to virtual addresses. */
+ ldr pc, =1f
+1:
+ mov fp, #0 /* trace back starts here */
+ bl _C_LABEL(init_secondary)/* Off we go, cpu id in r0. */
+
+ adr r0, .Lmpreturned
+ b _C_LABEL(panic)
+ /* NOTREACHED */
+END(mpentry)
+
+.Lmpreturned:
+ .asciz "init_secondary() returned"
+ .align 2
+#endif
+
+ENTRY_NP(cpu_halt)
+
+ /* XXX re-implement !!! */
+ cpsid ifa
+ bl dcache_wbinv_poc_all
+
+ ldr r4, .Lcpu_reset_address
+ ldr r4, [r4]
+ teq r4, #0
+ movne pc, r4
+1:
+ WFI
+ b 1b
+
+ /*
+ * _cpu_reset_address contains the address to branch to, to complete
+ * the cpu reset after turning the MMU off
+ * This variable is provided by the hardware specific code
+ */
+.Lcpu_reset_address:
+ .word _C_LABEL(cpu_reset_address)
+END(cpu_halt)
+
+
+/*
+ * setjump + longjmp
+ */
+ENTRY(setjmp)
+ stmia r0, {r4-r14}
+ mov r0, #0x00000000
+ RET
+END(setjmp)
+
+ENTRY(longjmp)
+ ldmia r0, {r4-r14}
+ mov r0, #0x00000001
+ RET
+END(longjmp)
+
+ .data
+ .global _C_LABEL(esym)
+_C_LABEL(esym): .word _C_LABEL(end)
+
+ENTRY_NP(abort)
+ b _C_LABEL(abort)
+END(abort)
+
+ENTRY_NP(sigcode)
+ mov r0, sp
+ add r0, r0, #SIGF_UC
+
+ /*
+ * Call the sigreturn system call.
+ *
+ * We have to load r7 manually rather than using
+ * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
+ * correct. Using the alternative places esigcode at the address
+ * of the data rather than the address one past the data.
+ */
+
+ ldr r7, [pc, #12] /* Load SYS_sigreturn */
+ swi SYS_sigreturn
+
+ /* Well if that failed we better exit quick ! */
+
+ ldr r7, [pc, #8] /* Load SYS_exit */
+ swi SYS_exit
+
+ /* Branch back to retry SYS_sigreturn */
+ b . - 16
+END(sigcode)
+ .word SYS_sigreturn
+ .word SYS_exit
+
+ .align 2
+ .global _C_LABEL(esigcode)
+ _C_LABEL(esigcode):
+
+ .data
+ .global szsigcode
+szsigcode:
+ .long esigcode-sigcode
+
+/* End of locore.S */
Property changes on: trunk/sys/arm/arm/locore-v6.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/locore.S
===================================================================
--- trunk/sys/arm/arm/locore.S (rev 0)
+++ trunk/sys/arm/arm/locore.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,42 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
+ * All rights excluded.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/arm/locore.S 278643 2015-02-13 00:06:07Z ian $
+ */
+
+/*
+ * The kernel build machinery wants the file containing the entry point to be
+ * named locore.S, but we want separate files for v4 and v6 builds, so just
+ * include the arch-appropriate file from this properly-named file.
+ */
+
+#include <machine/acle-compat.h>
+
+#if __ARM_ARCH >= 6
+#include "locore-v6.S"
+#else
+#include "locore-v4.S"
+#endif
Property changes on: trunk/sys/arm/arm/locore.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/machdep.c
===================================================================
--- trunk/sys/arm/arm/machdep.c (rev 0)
+++ trunk/sys/arm/arm/machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1311 @@
+/* $MidnightBSD$ */
+/* $NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $ */
+
+/*-
+ * Copyright (c) 2004 Olivier Houchard
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * Created : 17/09/94
+ * Updated : 18/04/01 updated for new wscons
+ */
+
+#include "opt_compat.h"
+#include "opt_ddb.h"
+#include "opt_platform.h"
+#include "opt_sched.h"
+#include "opt_timer.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/machdep.c 294683 2016-01-24 21:04:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/cpu.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/ptrace.h>
+#include <sys/rwlock.h>
+#include <sys/sched.h>
+#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
+
+#include <machine/armreg.h>
+#include <machine/atags.h>
+#include <machine/cpu.h>
+#include <machine/cpuinfo.h>
+#include <machine/devmap.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+#include <machine/machdep.h>
+#include <machine/md_var.h>
+#include <machine/metadata.h>
+#include <machine/pcb.h>
+#include <machine/physmem.h>
+#include <machine/reg.h>
+#include <machine/trap.h>
+#include <machine/undefined.h>
+#include <machine/vfp.h>
+#include <machine/vmparam.h>
+#include <machine/sysarch.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#endif
+
+#ifdef DEBUG
+#define debugf(fmt, args...) printf(fmt, ##args)
+#else
+#define debugf(fmt, args...)
+#endif
+
+struct pcpu __pcpu[MAXCPU];
+struct pcpu *pcpup = &__pcpu[0];
+
+static struct trapframe proc0_tf;
+uint32_t cpu_reset_address = 0;
+int cold = 1;
+vm_offset_t vector_page;
+
+int (*_arm_memcpy)(void *, void *, int, int) = NULL;
+int (*_arm_bzero)(void *, int, int) = NULL;
+int _min_memcpy_size = 0;
+int _min_bzero_size = 0;
+
+extern int *end;
+#ifdef DDB
+extern vm_offset_t ksym_start, ksym_end;
+#endif
+
+#ifdef FDT
+/*
+ * This is the number of L2 page tables required for covering max
+ * (hypothetical) memsize of 4GB and all kernel mappings (vectors, msgbuf,
+ * stacks etc.), uprounded to be divisible by 4.
+ */
+#define KERNEL_PT_MAX 78
+
+static struct pv_addr kernel_pt_table[KERNEL_PT_MAX];
+
+vm_paddr_t pmap_pa;
+
+struct pv_addr systempage;
+static struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+static struct pv_addr kernelstack;
+
+#endif
+
+#if defined(LINUX_BOOT_ABI)
+#define LBABI_MAX_BANKS 10
+
+uint32_t board_id;
+struct arm_lbabi_tag *atag_list;
+char linux_command_line[LBABI_MAX_COMMAND_LINE + 1];
+char atags[LBABI_MAX_COMMAND_LINE * 2];
+uint32_t memstart[LBABI_MAX_BANKS];
+uint32_t memsize[LBABI_MAX_BANKS];
+uint32_t membanks;
+#endif
+
+static uint32_t board_revision;
+/* hex representation of uint64_t */
+static char board_serial[32];
+
+SYSCTL_NODE(_hw, OID_AUTO, board, CTLFLAG_RD, 0, "Board attributes");
+SYSCTL_UINT(_hw_board, OID_AUTO, revision, CTLFLAG_RD,
+ &board_revision, 0, "Board revision");
+SYSCTL_STRING(_hw_board, OID_AUTO, serial, CTLFLAG_RD,
+ board_serial, 0, "Board serial");
+
+int vfp_exists;
+SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
+ &vfp_exists, 0, "Floating point support enabled");
+
+void
+board_set_serial(uint64_t serial)
+{
+
+ snprintf(board_serial, sizeof(board_serial)-1,
+ "%016jx", serial);
+}
+
+void
+board_set_revision(uint32_t revision)
+{
+
+ board_revision = revision;
+}
+
+void
+sendsig(catcher, ksi, mask)
+ sig_t catcher;
+ ksiginfo_t *ksi;
+ sigset_t *mask;
+{
+ struct thread *td;
+ struct proc *p;
+ struct trapframe *tf;
+ struct sigframe *fp, frame;
+ struct sigacts *psp;
+ int onstack;
+ int sig;
+ int code;
+
+ td = curthread;
+ p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
+ psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
+ tf = td->td_frame;
+ onstack = sigonstack(tf->tf_usr_sp);
+
+ CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
+ catcher, sig);
+
+ /* Allocate and validate space for the signal handler context. */
+ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !(onstack) &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ fp = (struct sigframe *)(td->td_sigstk.ss_sp +
+ td->td_sigstk.ss_size);
+#if defined(COMPAT_43)
+ td->td_sigstk.ss_flags |= SS_ONSTACK;
+#endif
+ } else
+ fp = (struct sigframe *)td->td_frame->tf_usr_sp;
+
+ /* make room on the stack */
+ fp--;
+
+ /* make the stack aligned */
+ fp = (struct sigframe *)STACKALIGN(fp);
+ /* Populate the siginfo frame. */
+ get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
+ frame.sf_si = ksi->ksi_info;
+ frame.sf_uc.uc_sigmask = *mask;
+ frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK )
+ ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+ frame.sf_uc.uc_stack = td->td_sigstk;
+ mtx_unlock(&psp->ps_mtx);
+ PROC_UNLOCK(td->td_proc);
+
+ /* Copy the sigframe out to the user's stack. */
+ if (copyout(&frame, fp, sizeof(*fp)) != 0) {
+ /* Process has trashed its stack. Kill it. */
+ CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
+ PROC_LOCK(p);
+ sigexit(td, SIGILL);
+ }
+
+ /*
+ * Build context to run handler in. We invoke the handler
+ * directly, only returning via the trampoline. Note the
+ * trampoline version numbers are coordinated with machine-
+ * dependent code in libc.
+ */
+
+ tf->tf_r0 = sig;
+ tf->tf_r1 = (register_t)&fp->sf_si;
+ tf->tf_r2 = (register_t)&fp->sf_uc;
+
+ /* the trampoline uses r5 as the uc address */
+ tf->tf_r5 = (register_t)&fp->sf_uc;
+ tf->tf_pc = (register_t)catcher;
+ tf->tf_usr_sp = (register_t)fp;
+ tf->tf_usr_lr = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
+
+ CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_usr_lr,
+ tf->tf_usr_sp);
+
+ PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
+}
+
+struct kva_md_info kmi;
+
+/*
+ * arm32_vector_init:
+ *
+ * Initialize the vector page, and select whether or not to
+ * relocate the vectors.
+ *
+ * NOTE: We expect the vector page to be mapped at its expected
+ * destination.
+ */
+
+extern unsigned int page0[], page0_data[];
+void
+arm_vector_init(vm_offset_t va, int which)
+{
+ unsigned int *vectors = (int *) va;
+ unsigned int *vectors_data = vectors + (page0_data - page0);
+ int vec;
+
+ /*
+ * Loop through the vectors we're taking over, and copy the
+ * vector's insn and data word.
+ */
+ for (vec = 0; vec < ARM_NVEC; vec++) {
+ if ((which & (1 << vec)) == 0) {
+ /* Don't want to take over this vector. */
+ continue;
+ }
+ vectors[vec] = page0[vec];
+ vectors_data[vec] = page0_data[vec];
+ }
+
+ /* Now sync the vectors. */
+ cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
+
+ vector_page = va;
+
+ if (va == ARM_VECTORS_HIGH) {
+ /*
+ * Assume the MD caller knows what it's doing here, and
+ * really does want the vector page relocated.
+ *
+ * Note: This has to be done here (and not just in
+ * cpu_setup()) because the vector page needs to be
+ * accessible *before* cpu_startup() is called.
+ * Think ddb(9) ...
+ *
+ * NOTE: If the CPU control register is not readable,
+ * this will totally fail! We'll just assume that
+ * any system that has high vector support has a
+ * readable CPU control register, for now. If we
+ * ever encounter one that does not, we'll have to
+ * rethink this.
+ */
+ cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC);
+ }
+}
+
+static void
+cpu_startup(void *dummy)
+{
+ struct pcb *pcb = thread0.td_pcb;
+ const unsigned int mbyte = 1024 * 1024;
+#ifdef ARM_TP_ADDRESS
+#ifndef ARM_CACHE_LOCK_ENABLE
+ vm_page_t m;
+#endif
+#endif
+
+ identify_arm_cpu();
+
+ vm_ksubmap_init(&kmi);
+
+ /*
+ * Display the RAM layout.
+ */
+ printf("real memory = %ju (%ju MB)\n",
+ (uintmax_t)arm32_ptob(realmem),
+ (uintmax_t)arm32_ptob(realmem) / mbyte);
+ printf("avail memory = %ju (%ju MB)\n",
+ (uintmax_t)arm32_ptob(cnt.v_free_count),
+ (uintmax_t)arm32_ptob(cnt.v_free_count) / mbyte);
+ if (bootverbose) {
+ arm_physmem_print_tables();
+ arm_devmap_print_table();
+ }
+
+ bufinit();
+ vm_pager_bufferinit();
+ pcb->pcb_regs.sf_sp = (u_int)thread0.td_kstack +
+ USPACE_SVC_STACK_TOP;
+ vector_page_setprot(VM_PROT_READ);
+ pmap_set_pcb_pagedir(pmap_kernel(), pcb);
+ pmap_postinit();
+#ifdef ARM_TP_ADDRESS
+#ifdef ARM_CACHE_LOCK_ENABLE
+ pmap_kenter_user(ARM_TP_ADDRESS, ARM_TP_ADDRESS);
+ arm_lock_cache_line(ARM_TP_ADDRESS);
+#else
+ m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_ZERO);
+ pmap_kenter_user(ARM_TP_ADDRESS, VM_PAGE_TO_PHYS(m));
+#endif
+ *(uint32_t *)ARM_RAS_START = 0;
+ *(uint32_t *)ARM_RAS_END = 0xffffffff;
+#endif
+}
+
+SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
+
+/*
+ * Flush the D-cache for non-DMA I/O so that the I-cache can
+ * be made coherent later.
+ */
+void
+cpu_flush_dcache(void *ptr, size_t len)
+{
+
+ cpu_dcache_wb_range((uintptr_t)ptr, len);
+#ifdef ARM_L2_PIPT
+ cpu_l2cache_wb_range((uintptr_t)vtophys(ptr), len);
+#else
+ cpu_l2cache_wb_range((uintptr_t)ptr, len);
+#endif
+}
+
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+
+ return (ENXIO);
+}
+
+void
+cpu_idle(int busy)
+{
+
+ CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", busy, curcpu);
+ spinlock_enter();
+#ifndef NO_EVENTTIMERS
+ if (!busy)
+ cpu_idleclock();
+#endif
+ if (!sched_runnable())
+ cpu_sleep(0);
+#ifndef NO_EVENTTIMERS
+ if (!busy)
+ cpu_activeclock();
+#endif
+ spinlock_exit();
+ CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done", busy, curcpu);
+}
+
+int
+cpu_idle_wakeup(int cpu)
+{
+
+ return (0);
+}
+
+/*
+ * Most ARM platforms don't need to do anything special to init their clocks
+ * (they get intialized during normal device attachment), and by not defining a
+ * cpu_initclocks() function they get this generic one. Any platform that needs
+ * to do something special can just provide their own implementation, which will
+ * override this one due to the weak linkage.
+ */
+void
+arm_generic_initclocks(void)
+{
+
+#ifndef NO_EVENTTIMERS
+#ifdef SMP
+ if (PCPU_GET(cpuid) == 0)
+ cpu_initclocks_bsp();
+ else
+ cpu_initclocks_ap();
+#else
+ cpu_initclocks_bsp();
+#endif
+#endif
+}
+__weak_reference(arm_generic_initclocks, cpu_initclocks);
+
+int
+fill_regs(struct thread *td, struct reg *regs)
+{
+ struct trapframe *tf = td->td_frame;
+ bcopy(&tf->tf_r0, regs->r, sizeof(regs->r));
+ regs->r_sp = tf->tf_usr_sp;
+ regs->r_lr = tf->tf_usr_lr;
+ regs->r_pc = tf->tf_pc;
+ regs->r_cpsr = tf->tf_spsr;
+ return (0);
+}
+int
+fill_fpregs(struct thread *td, struct fpreg *regs)
+{
+ bzero(regs, sizeof(*regs));
+ return (0);
+}
+
+int
+set_regs(struct thread *td, struct reg *regs)
+{
+ struct trapframe *tf = td->td_frame;
+
+ bcopy(regs->r, &tf->tf_r0, sizeof(regs->r));
+ tf->tf_usr_sp = regs->r_sp;
+ tf->tf_usr_lr = regs->r_lr;
+ tf->tf_pc = regs->r_pc;
+ tf->tf_spsr &= ~PSR_FLAGS;
+ tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
+ return (0);
+}
+
+int
+set_fpregs(struct thread *td, struct fpreg *regs)
+{
+ return (0);
+}
+
+int
+fill_dbregs(struct thread *td, struct dbreg *regs)
+{
+ return (0);
+}
+int
+set_dbregs(struct thread *td, struct dbreg *regs)
+{
+ return (0);
+}
+
+
+static int
+ptrace_read_int(struct thread *td, vm_offset_t addr, u_int32_t *v)
+{
+ struct iovec iov;
+ struct uio uio;
+
+ PROC_LOCK_ASSERT(td->td_proc, MA_NOTOWNED);
+ iov.iov_base = (caddr_t) v;
+ iov.iov_len = sizeof(u_int32_t);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)addr;
+ uio.uio_resid = sizeof(u_int32_t);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_td = td;
+ return proc_rwmem(td->td_proc, &uio);
+}
+
+static int
+ptrace_write_int(struct thread *td, vm_offset_t addr, u_int32_t v)
+{
+ struct iovec iov;
+ struct uio uio;
+
+ PROC_LOCK_ASSERT(td->td_proc, MA_NOTOWNED);
+ iov.iov_base = (caddr_t) &v;
+ iov.iov_len = sizeof(u_int32_t);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)addr;
+ uio.uio_resid = sizeof(u_int32_t);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_WRITE;
+ uio.uio_td = td;
+ return proc_rwmem(td->td_proc, &uio);
+}
+
+int
+ptrace_single_step(struct thread *td)
+{
+ struct proc *p;
+ int error;
+
+ KASSERT(td->td_md.md_ptrace_instr == 0,
+ ("Didn't clear single step"));
+ p = td->td_proc;
+ PROC_UNLOCK(p);
+ error = ptrace_read_int(td, td->td_frame->tf_pc + 4,
+ &td->td_md.md_ptrace_instr);
+ if (error)
+ goto out;
+ error = ptrace_write_int(td, td->td_frame->tf_pc + 4,
+ PTRACE_BREAKPOINT);
+ if (error)
+ td->td_md.md_ptrace_instr = 0;
+ td->td_md.md_ptrace_addr = td->td_frame->tf_pc + 4;
+out:
+ PROC_LOCK(p);
+ return (error);
+}
+
+int
+ptrace_clear_single_step(struct thread *td)
+{
+ struct proc *p;
+
+ if (td->td_md.md_ptrace_instr) {
+ p = td->td_proc;
+ PROC_UNLOCK(p);
+ ptrace_write_int(td, td->td_md.md_ptrace_addr,
+ td->td_md.md_ptrace_instr);
+ PROC_LOCK(p);
+ td->td_md.md_ptrace_instr = 0;
+ }
+ return (0);
+}
+
+int
+ptrace_set_pc(struct thread *td, unsigned long addr)
+{
+ td->td_frame->tf_pc = addr;
+ return (0);
+}
+
+void
+cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
+{
+}
+
+void
+spinlock_enter(void)
+{
+ struct thread *td;
+ register_t cspr;
+
+ td = curthread;
+ if (td->td_md.md_spinlock_count == 0) {
+ cspr = disable_interrupts(PSR_I | PSR_F);
+ td->td_md.md_spinlock_count = 1;
+ td->td_md.md_saved_cspr = cspr;
+ } else
+ td->td_md.md_spinlock_count++;
+ critical_enter();
+}
+
+void
+spinlock_exit(void)
+{
+ struct thread *td;
+ register_t cspr;
+
+ td = curthread;
+ critical_exit();
+ cspr = td->td_md.md_saved_cspr;
+ td->td_md.md_spinlock_count--;
+ if (td->td_md.md_spinlock_count == 0)
+ restore_interrupts(cspr);
+}
+
+/*
+ * Clear registers on exec
+ */
+void
+exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
+{
+ struct trapframe *tf = td->td_frame;
+
+ memset(tf, 0, sizeof(*tf));
+ tf->tf_usr_sp = stack;
+ tf->tf_usr_lr = imgp->entry_addr;
+ tf->tf_svc_lr = 0x77777777;
+ tf->tf_pc = imgp->entry_addr;
+ tf->tf_spsr = PSR_USR32_MODE;
+}
+
+/*
+ * Get machine context.
+ */
+int
+get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
+{
+ struct trapframe *tf = td->td_frame;
+ __greg_t *gr = mcp->__gregs;
+
+ if (clear_ret & GET_MC_CLEAR_RET)
+ gr[_REG_R0] = 0;
+ else
+ gr[_REG_R0] = tf->tf_r0;
+ gr[_REG_R1] = tf->tf_r1;
+ gr[_REG_R2] = tf->tf_r2;
+ gr[_REG_R3] = tf->tf_r3;
+ gr[_REG_R4] = tf->tf_r4;
+ gr[_REG_R5] = tf->tf_r5;
+ gr[_REG_R6] = tf->tf_r6;
+ gr[_REG_R7] = tf->tf_r7;
+ gr[_REG_R8] = tf->tf_r8;
+ gr[_REG_R9] = tf->tf_r9;
+ gr[_REG_R10] = tf->tf_r10;
+ gr[_REG_R11] = tf->tf_r11;
+ gr[_REG_R12] = tf->tf_r12;
+ gr[_REG_SP] = tf->tf_usr_sp;
+ gr[_REG_LR] = tf->tf_usr_lr;
+ gr[_REG_PC] = tf->tf_pc;
+ gr[_REG_CPSR] = tf->tf_spsr;
+
+ return (0);
+}
+
+/*
+ * Set machine context.
+ *
+ * However, we don't set any but the user modifiable flags, and we won't
+ * touch the cs selector.
+ */
+int
+set_mcontext(struct thread *td, mcontext_t *mcp)
+{
+ struct trapframe *tf = td->td_frame;
+ const __greg_t *gr = mcp->__gregs;
+
+ tf->tf_r0 = gr[_REG_R0];
+ tf->tf_r1 = gr[_REG_R1];
+ tf->tf_r2 = gr[_REG_R2];
+ tf->tf_r3 = gr[_REG_R3];
+ tf->tf_r4 = gr[_REG_R4];
+ tf->tf_r5 = gr[_REG_R5];
+ tf->tf_r6 = gr[_REG_R6];
+ tf->tf_r7 = gr[_REG_R7];
+ tf->tf_r8 = gr[_REG_R8];
+ tf->tf_r9 = gr[_REG_R9];
+ tf->tf_r10 = gr[_REG_R10];
+ tf->tf_r11 = gr[_REG_R11];
+ tf->tf_r12 = gr[_REG_R12];
+ tf->tf_usr_sp = gr[_REG_SP];
+ tf->tf_usr_lr = gr[_REG_LR];
+ tf->tf_pc = gr[_REG_PC];
+ tf->tf_spsr = gr[_REG_CPSR];
+
+ return (0);
+}
+
+/*
+ * MPSAFE
+ */
+int
+sys_sigreturn(td, uap)
+ struct thread *td;
+ struct sigreturn_args /* {
+ const struct __ucontext *sigcntxp;
+ } */ *uap;
+{
+ ucontext_t uc;
+ int spsr;
+
+ if (uap == NULL)
+ return (EFAULT);
+ if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
+ return (EFAULT);
+ /*
+ * Make sure the processor mode has not been tampered with and
+ * interrupts have not been disabled.
+ */
+ spsr = uc.uc_mcontext.__gregs[_REG_CPSR];
+ if ((spsr & PSR_MODE) != PSR_USR32_MODE ||
+ (spsr & (PSR_I | PSR_F)) != 0)
+ return (EINVAL);
+ /* Restore register context. */
+ set_mcontext(td, &uc.uc_mcontext);
+
+ /* Restore signal mask. */
+ kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
+
+ return (EJUSTRETURN);
+}
+
+
+/*
+ * Construct a PCB from a trapframe. This is called from kdb_trap() where
+ * we want to start a backtrace from the function that caused us to enter
+ * the debugger. We have the context in the trapframe, but base the trace
+ * on the PCB. The PCB doesn't have to be perfect, as long as it contains
+ * enough for a backtrace.
+ */
+void
+makectx(struct trapframe *tf, struct pcb *pcb)
+{
+ pcb->pcb_regs.sf_r4 = tf->tf_r4;
+ pcb->pcb_regs.sf_r5 = tf->tf_r5;
+ pcb->pcb_regs.sf_r6 = tf->tf_r6;
+ pcb->pcb_regs.sf_r7 = tf->tf_r7;
+ pcb->pcb_regs.sf_r8 = tf->tf_r8;
+ pcb->pcb_regs.sf_r9 = tf->tf_r9;
+ pcb->pcb_regs.sf_r10 = tf->tf_r10;
+ pcb->pcb_regs.sf_r11 = tf->tf_r11;
+ pcb->pcb_regs.sf_r12 = tf->tf_r12;
+ pcb->pcb_regs.sf_pc = tf->tf_pc;
+ pcb->pcb_regs.sf_lr = tf->tf_usr_lr;
+ pcb->pcb_regs.sf_sp = tf->tf_usr_sp;
+}
+
+/*
+ * Fake up a boot descriptor table
+ */
+vm_offset_t
+fake_preload_metadata(struct arm_boot_params *abp __unused)
+{
+#ifdef DDB
+ vm_offset_t zstart = 0, zend = 0;
+#endif
+ vm_offset_t lastaddr;
+ int i = 0;
+ static uint32_t fake_preload[35];
+
+ fake_preload[i++] = MODINFO_NAME;
+ fake_preload[i++] = strlen("kernel") + 1;
+ strcpy((char*)&fake_preload[i++], "kernel");
+ i += 1;
+ fake_preload[i++] = MODINFO_TYPE;
+ fake_preload[i++] = strlen("elf kernel") + 1;
+ strcpy((char*)&fake_preload[i++], "elf kernel");
+ i += 2;
+ fake_preload[i++] = MODINFO_ADDR;
+ fake_preload[i++] = sizeof(vm_offset_t);
+ fake_preload[i++] = KERNVIRTADDR;
+ fake_preload[i++] = MODINFO_SIZE;
+ fake_preload[i++] = sizeof(uint32_t);
+ fake_preload[i++] = (uint32_t)&end - KERNVIRTADDR;
+#ifdef DDB
+ if (*(uint32_t *)KERNVIRTADDR == MAGIC_TRAMP_NUMBER) {
+ fake_preload[i++] = MODINFO_METADATA|MODINFOMD_SSYM;
+ fake_preload[i++] = sizeof(vm_offset_t);
+ fake_preload[i++] = *(uint32_t *)(KERNVIRTADDR + 4);
+ fake_preload[i++] = MODINFO_METADATA|MODINFOMD_ESYM;
+ fake_preload[i++] = sizeof(vm_offset_t);
+ fake_preload[i++] = *(uint32_t *)(KERNVIRTADDR + 8);
+ lastaddr = *(uint32_t *)(KERNVIRTADDR + 8);
+ zend = lastaddr;
+ zstart = *(uint32_t *)(KERNVIRTADDR + 4);
+ ksym_start = zstart;
+ ksym_end = zend;
+ } else
+#endif
+ lastaddr = (vm_offset_t)&end;
+ fake_preload[i++] = 0;
+ fake_preload[i] = 0;
+ preload_metadata = (void *)fake_preload;
+
+ init_static_kenv(NULL, 0);
+
+ return (lastaddr);
+}
+
+void
+pcpu0_init(void)
+{
+#if __ARM_ARCH >= 6
+ set_curthread(&thread0);
+#endif
+ pcpu_init(pcpup, 0, sizeof(struct pcpu));
+ PCPU_SET(curthread, &thread0);
+#ifdef VFP
+ PCPU_SET(cpu, 0);
+#endif
+}
+
+#if defined(LINUX_BOOT_ABI)
+vm_offset_t
+linux_parse_boot_param(struct arm_boot_params *abp)
+{
+ struct arm_lbabi_tag *walker;
+ uint32_t revision;
+ uint64_t serial;
+
+ /*
+ * Linux boot ABI: r0 = 0, r1 is the board type (!= 0) and r2
+ * is atags or dtb pointer. If all of these aren't satisfied,
+ * then punt.
+ */
+ if (!(abp->abp_r0 == 0 && abp->abp_r1 != 0 && abp->abp_r2 != 0))
+ return 0;
+
+ board_id = abp->abp_r1;
+ walker = (struct arm_lbabi_tag *)
+ (abp->abp_r2 + KERNVIRTADDR - abp->abp_physaddr);
+
+ /* xxx - Need to also look for binary device tree */
+ if (ATAG_TAG(walker) != ATAG_CORE)
+ return 0;
+
+ atag_list = walker;
+ while (ATAG_TAG(walker) != ATAG_NONE) {
+ switch (ATAG_TAG(walker)) {
+ case ATAG_CORE:
+ break;
+ case ATAG_MEM:
+ arm_physmem_hardware_region(walker->u.tag_mem.start,
+ walker->u.tag_mem.size);
+ break;
+ case ATAG_INITRD2:
+ break;
+ case ATAG_SERIAL:
+ serial = walker->u.tag_sn.low |
+ ((uint64_t)walker->u.tag_sn.high << 32);
+ board_set_serial(serial);
+ break;
+ case ATAG_REVISION:
+ revision = walker->u.tag_rev.rev;
+ board_set_revision(revision);
+ break;
+ case ATAG_CMDLINE:
+ /* XXX open question: Parse this for boothowto? */
+ bcopy(walker->u.tag_cmd.command, linux_command_line,
+ ATAG_SIZE(walker));
+ break;
+ default:
+ break;
+ }
+ walker = ATAG_NEXT(walker);
+ }
+
+ /* Save a copy for later */
+ bcopy(atag_list, atags,
+ (char *)walker - (char *)atag_list + ATAG_SIZE(walker));
+
+ init_static_kenv(NULL, 0);
+
+ return fake_preload_metadata(abp);
+}
+#endif
+
+#if defined(FREEBSD_BOOT_LOADER)
+vm_offset_t
+freebsd_parse_boot_param(struct arm_boot_params *abp)
+{
+ vm_offset_t lastaddr = 0;
+ void *mdp;
+ void *kmdp;
+
+ /*
+ * Mask metadata pointer: it is supposed to be on page boundary. If
+ * the first argument (mdp) doesn't point to a valid address the
+ * bootloader must have passed us something else than the metadata
+ * ptr, so we give up. Also give up if we cannot find metadta section
+ * the loader creates that we get all this data out of.
+ */
+
+ if ((mdp = (void *)(abp->abp_r0 & ~PAGE_MASK)) == NULL)
+ return 0;
+ preload_metadata = mdp;
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp == NULL)
+ return 0;
+
+ boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
+ init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 0);
+ lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
+#ifdef DDB
+ ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
+ ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+#endif
+ return lastaddr;
+}
+#endif
+
+vm_offset_t
+default_parse_boot_param(struct arm_boot_params *abp)
+{
+ vm_offset_t lastaddr;
+
+#if defined(LINUX_BOOT_ABI)
+ if ((lastaddr = linux_parse_boot_param(abp)) != 0)
+ return lastaddr;
+#endif
+#if defined(FREEBSD_BOOT_LOADER)
+ if ((lastaddr = freebsd_parse_boot_param(abp)) != 0)
+ return lastaddr;
+#endif
+ /* Fall back to hardcoded metadata. */
+ lastaddr = fake_preload_metadata(abp);
+
+ return lastaddr;
+}
+
+/*
+ * Stub version of the boot parameter parsing routine. We are
+ * called early in initarm, before even VM has been initialized.
+ * This routine needs to preserve any data that the boot loader
+ * has passed in before the kernel starts to grow past the end
+ * of the BSS, traditionally the place boot-loaders put this data.
+ *
+ * Since this is called so early, things that depend on the vm system
+ * being setup (including access to some SoC's serial ports), about
+ * all that can be done in this routine is to copy the arguments.
+ *
+ * This is the default boot parameter parsing routine. Individual
+ * kernels/boards can override this weak function with one of their
+ * own. We just fake metadata...
+ */
+__weak_reference(default_parse_boot_param, parse_boot_param);
+
+/*
+ * Initialize proc0
+ */
+void
+init_proc0(vm_offset_t kstack)
+{
+ proc_linkup0(&proc0, &thread0);
+ thread0.td_kstack = kstack;
+ thread0.td_pcb = (struct pcb *)
+ (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
+ thread0.td_pcb->pcb_flags = 0;
+ thread0.td_pcb->pcb_vfpcpu = -1;
+ thread0.td_pcb->pcb_vfpstate.fpscr = VFPSCR_DN | VFPSCR_FZ;
+ thread0.td_frame = &proc0_tf;
+ pcpup->pc_curpcb = thread0.td_pcb;
+}
+
+void
+set_stackptrs(int cpu)
+{
+
+ set_stackptr(PSR_IRQ32_MODE,
+ irqstack.pv_va + ((IRQ_STACK_SIZE * PAGE_SIZE) * (cpu + 1)));
+ set_stackptr(PSR_ABT32_MODE,
+ abtstack.pv_va + ((ABT_STACK_SIZE * PAGE_SIZE) * (cpu + 1)));
+ set_stackptr(PSR_UND32_MODE,
+ undstack.pv_va + ((UND_STACK_SIZE * PAGE_SIZE) * (cpu + 1)));
+}
+
+#ifdef FDT
+static char *
+kenv_next(char *cp)
+{
+
+ if (cp != NULL) {
+ while (*cp != 0)
+ cp++;
+ cp++;
+ if (*cp == 0)
+ cp = NULL;
+ }
+ return (cp);
+}
+
+static void
+print_kenv(void)
+{
+ int len;
+ char *cp;
+
+ debugf("loader passed (static) kenv:\n");
+ if (kern_envp == NULL) {
+ debugf(" no env, null ptr\n");
+ return;
+ }
+ debugf(" kern_envp = 0x%08x\n", (uint32_t)kern_envp);
+
+ len = 0;
+ for (cp = kern_envp; cp != NULL; cp = kenv_next(cp))
+ debugf(" %x %s\n", (uint32_t)cp, cp);
+}
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+ struct mem_region mem_regions[FDT_MEM_REGIONS];
+ struct pv_addr kernel_l1pt;
+ struct pv_addr dpcpu;
+ vm_offset_t dtbp, freemempos, l2_start, lastaddr;
+ uint32_t memsize, l2size;
+ char *env;
+ void *kmdp;
+ u_int l1pagetable;
+ int i, j, err_devmap, mem_regions_sz;
+
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+
+ memsize = 0;
+
+ cpuinfo_init();
+ set_cpufuncs();
+
+ /*
+ * Find the dtb passed in by the boot loader.
+ */
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp != NULL)
+ dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
+ else
+ dtbp = (vm_offset_t)NULL;
+
+#if defined(FDT_DTB_STATIC)
+ /*
+ * In case the device tree blob was not retrieved (from metadata) try
+ * to use the statically embedded one.
+ */
+ if (dtbp == (vm_offset_t)NULL)
+ dtbp = (vm_offset_t)&fdt_static_dtb;
+#endif
+
+ if (OF_install(OFW_FDT, 0) == FALSE)
+ panic("Cannot install FDT");
+
+ if (OF_init((void *)dtbp) != 0)
+ panic("OF_init failed with the found device tree");
+
+ /* Grab physical memory regions information from device tree. */
+ if (fdt_get_mem_regions(mem_regions, &mem_regions_sz, &memsize) != 0)
+ panic("Cannot get physical memory regions");
+ arm_physmem_hardware_regions(mem_regions, mem_regions_sz);
+
+ /* Grab reserved memory regions information from device tree. */
+ if (fdt_get_reserved_regions(mem_regions, &mem_regions_sz) == 0)
+ arm_physmem_exclude_regions(mem_regions, mem_regions_sz,
+ EXFLAG_NODUMP | EXFLAG_NOALLOC);
+
+ /* Platform-specific initialisation */
+ initarm_early_init();
+
+ pcpu0_init();
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+ /* Calculate number of L2 tables needed for mapping vm_page_array */
+ l2size = (memsize / PAGE_SIZE) * sizeof(struct vm_page);
+ l2size = (l2size >> L1_S_SHIFT) + 1;
+
+ /*
+ * Add one table for end of kernel map, one for stacks, msgbuf and
+ * L1 and L2 tables map and one for vectors map.
+ */
+ l2size += 3;
+
+ /* Make it divisible by 4 */
+ l2size = (l2size + 3) & ~3;
+
+ freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK;
+
+ /* Define a macro to simplify memory allocation */
+#define valloc_pages(var, np) \
+ alloc_pages((var).pv_va, (np)); \
+ (var).pv_pa = (var).pv_va + (abp->abp_physaddr - KERNVIRTADDR);
+
+#define alloc_pages(var, np) \
+ (var) = freemempos; \
+ freemempos += (np * PAGE_SIZE); \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos += PAGE_SIZE;
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+
+ for (i = 0, j = 0; i < l2size; ++i) {
+ if (!(i % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[i],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ j = i;
+ } else {
+ kernel_pt_table[i].pv_va = kernel_pt_table[j].pv_va +
+ L2_TABLE_SIZE_REAL * (i - j);
+ kernel_pt_table[i].pv_pa =
+ kernel_pt_table[i].pv_va - KERNVIRTADDR +
+ abp->abp_physaddr;
+
+ }
+ }
+ /*
+ * Allocate a page for the system page mapped to 0x00000000
+ * or 0xffff0000. This page will just contain the system vectors
+ * and can be shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate dynamic per-cpu area. */
+ valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
+ dpcpu_init((void *)dpcpu.pv_va, 0);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE * MAXCPU);
+ valloc_pages(abtstack, ABT_STACK_SIZE * MAXCPU);
+ valloc_pages(undstack, UND_STACK_SIZE * MAXCPU);
+ valloc_pages(kernelstack, KSTACK_PAGES * MAXCPU);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+
+ /*
+ * Now we start construction of the L1 page table
+ * We start by mapping the L2 page tables into the L1.
+ * This means that we can replace L1 mappings later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /*
+ * Try to map as much as possible of kernel text and data using
+ * 1MB section mapping and for the rest of initial kernel address
+ * space use L2 coarse tables.
+ *
+ * Link L2 tables for mapping remainder of kernel (modulo 1MB)
+ * and kernel structures
+ */
+ l2_start = lastaddr & ~(L1_S_OFFSET);
+ for (i = 0 ; i < l2size - 1; i++)
+ pmap_link_l2pt(l1pagetable, l2_start + i * L1_S_SIZE,
+ &kernel_pt_table[i]);
+
+ pmap_curmaxkvaddr = l2_start + (l2size - 1) * L1_S_SIZE;
+
+ /* Map kernel code and data */
+ pmap_map_chunk(l1pagetable, KERNVIRTADDR, abp->abp_physaddr,
+ (((uint32_t)(lastaddr) - KERNVIRTADDR) + PAGE_MASK) & ~PAGE_MASK,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ /* Map L1 directory and allocated L2 page tables */
+ pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
+ L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+
+ pmap_map_chunk(l1pagetable, kernel_pt_table[0].pv_va,
+ kernel_pt_table[0].pv_pa,
+ L2_TABLE_SIZE_REAL * l2size,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+
+ /* Map allocated DPCPU, stacks and msgbuf */
+ pmap_map_chunk(l1pagetable, dpcpu.pv_va, dpcpu.pv_pa,
+ freemempos - dpcpu.pv_va,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ /* Link and map the vector page */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH,
+ &kernel_pt_table[l2size - 1]);
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE, PTE_CACHE);
+
+ /* Establish static device mappings. */
+ err_devmap = initarm_devmap_init();
+ arm_devmap_bootstrap(l1pagetable, NULL);
+ vm_max_kernel_address = initarm_lastaddr();
+
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT);
+ pmap_pa = kernel_l1pt.pv_pa;
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2));
+
+ /*
+ * Now that proper page tables are installed, call cpu_setup() to enable
+ * instruction and data caches and other chip-specific features.
+ */
+ cpu_setup("");
+
+ /*
+ * Only after the SOC registers block is mapped we can perform device
+ * tree fixups, as they may attempt to read parameters from hardware.
+ */
+ OF_interpret("perform-fixup", 0);
+
+ initarm_gpio_init();
+
+ cninit();
+
+ debugf("initarm: console initialized\n");
+ debugf(" arg1 kmdp = 0x%08x\n", (uint32_t)kmdp);
+ debugf(" boothowto = 0x%08x\n", boothowto);
+ debugf(" dtbp = 0x%08x\n", (uint32_t)dtbp);
+ print_kenv();
+
+ env = getenv("kernelname");
+ if (env != NULL)
+ strlcpy(kernelname, env, sizeof(kernelname));
+
+ if (err_devmap != 0)
+ printf("WARNING: could not fully configure devmap, error=%d\n",
+ err_devmap);
+
+ initarm_late_init();
+
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+ cpu_control(CPU_CONTROL_MMU_ENABLE, CPU_CONTROL_MMU_ENABLE);
+
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+ pmap_bootstrap(freemempos, &kernel_l1pt);
+ msgbufp = (void *)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+
+ /*
+ * Exclude the kernel (and all the things we allocated which immediately
+ * follow the kernel) from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ (virtual_avail - KERNVIRTADDR), EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+}
+#endif
Property changes on: trunk/sys/arm/arm/machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/mem.c
===================================================================
--- trunk/sys/arm/arm/mem.c (rev 0)
+++ trunk/sys/arm/arm/mem.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,168 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department, and code derived from software contributed to
+ * Berkeley by William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: mem.c 1.13 89/10/08$
+ * from: @(#)mem.c 7.2 (Berkeley) 5/9/91
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/mem.c 278746 2015-02-14 08:44:12Z kib $");
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/ioccom.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/memrange.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/sx.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <machine/memdev.h>
+#include <machine/vmparam.h>
+
+/*
+ * Used in /dev/mem drivers and elsewhere
+ */
+MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors");
+
+struct mem_range_softc mem_range_softc;
+
+static struct sx tmppt_lock;
+SX_SYSINIT(tmppt, &tmppt_lock, "mem4map");
+
+/* ARGSUSED */
+int
+memrw(struct cdev *dev, struct uio *uio, int flags)
+{
+ int o;
+ u_int c = 0, v;
+ struct iovec *iov;
+ int error = 0;
+ vm_offset_t addr, eaddr;
+
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("memrw");
+ continue;
+ }
+ if (dev2unit(dev) == CDEV_MINOR_MEM) {
+ int i;
+ int address_valid = 0;
+
+ v = uio->uio_offset;
+ v &= ~PAGE_MASK;
+ for (i = 0; dump_avail[i] || dump_avail[i + 1];
+ i += 2) {
+ if (v >= dump_avail[i] &&
+ v < dump_avail[i + 1]) {
+ address_valid = 1;
+ break;
+ }
+ }
+ if (!address_valid)
+ return (EINVAL);
+ sx_xlock(&tmppt_lock);
+ pmap_kenter((vm_offset_t)_tmppt, v);
+ o = (int)uio->uio_offset & PAGE_MASK;
+ c = (u_int)(PAGE_SIZE - ((int)iov->iov_base & PAGE_MASK));
+ c = min(c, (u_int)(PAGE_SIZE - o));
+ c = min(c, (u_int)iov->iov_len);
+ error = uiomove((caddr_t)&_tmppt[o], (int)c, uio);
+ pmap_qremove((vm_offset_t)_tmppt, 1);
+ sx_xunlock(&tmppt_lock);
+ continue;
+ }
+ else if (dev2unit(dev) == CDEV_MINOR_KMEM) {
+ c = iov->iov_len;
+
+ /*
+ * Make sure that all of the pages are currently
+ * resident so that we don't create any zero-fill
+ * pages.
+ */
+ addr = trunc_page(uio->uio_offset);
+ eaddr = round_page(uio->uio_offset + c);
+
+ for (; addr < eaddr; addr += PAGE_SIZE)
+ if (pmap_extract(kernel_pmap, addr) == 0)
+ return (EFAULT);
+ if (!kernacc((caddr_t)(int)uio->uio_offset, c,
+ uio->uio_rw == UIO_READ ?
+ VM_PROT_READ : VM_PROT_WRITE))
+ return (EFAULT);
+ error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio);
+ continue;
+ }
+ /* else panic! */
+ }
+ return (error);
+}
+
+/*
+ * allow user processes to MMAP some memory sections
+ * instead of going through read/write
+ */
+/* ARGSUSED */
+
+int
+memmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int prot __unused, vm_memattr_t *memattr __unused)
+{
+ if (dev2unit(dev) == CDEV_MINOR_MEM)
+ *paddr = offset;
+ else if (dev2unit(dev) == CDEV_MINOR_KMEM)
+ *paddr = vtophys(offset);
+ /* else panic! */
+ return (0);
+}
Property changes on: trunk/sys/arm/arm/mem.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/minidump_machdep.c
===================================================================
--- trunk/sys/arm/arm/minidump_machdep.c (rev 0)
+++ trunk/sys/arm/arm/minidump_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,498 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Semihalf, Grzegorz Bernacki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: FreeBSD: src/sys/i386/i386/minidump_machdep.c,v 1.6 2008/08/17 23:27:27
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/minidump_machdep.c 278614 2015-02-12 04:15:55Z ian $");
+
+#include "opt_watchdog.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+#include <sys/kerneldump.h>
+#include <sys/msgbuf.h>
+#ifdef SW_WATCHDOG
+#include <sys/watchdog.h>
+#endif
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/atomic.h>
+#include <machine/elf.h>
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+#include <machine/minidump.h>
+#include <machine/cpufunc.h>
+
+CTASSERT(sizeof(struct kerneldumpheader) == 512);
+
+/*
+ * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
+ * is to protect us from metadata and to protect metadata from us.
+ */
+#define SIZEOF_METADATA (64*1024)
+
+uint32_t *vm_page_dump;
+int vm_page_dump_size;
+
+static struct kerneldumpheader kdh;
+static off_t dumplo;
+
+/* Handle chunked writes. */
+static size_t fragsz, offset;
+static void *dump_va;
+static uint64_t counter, progress;
+
+CTASSERT(sizeof(*vm_page_dump) == 4);
+
+static int
+is_dumpable(vm_paddr_t pa)
+{
+ int i;
+
+ for (i = 0; dump_avail[i] != 0 || dump_avail[i + 1] != 0; i += 2) {
+ if (pa >= dump_avail[i] && pa < dump_avail[i + 1])
+ return (1);
+ }
+ return (0);
+}
+
+#define PG2MB(pgs) (((pgs) + (1 << 8) - 1) >> 8)
+
+static int
+blk_flush(struct dumperinfo *di)
+{
+ int error;
+
+ if (fragsz == 0)
+ return (0);
+
+ error = dump_write(di, (char*)dump_va + offset, 0, dumplo, fragsz - offset);
+ dumplo += (fragsz - offset);
+ fragsz = 0;
+ offset = 0;
+ return (error);
+}
+
+static int
+blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
+{
+ size_t len;
+ int error, i, c;
+ u_int maxdumpsz;
+
+ maxdumpsz = di->maxiosize;
+
+ if (maxdumpsz == 0) /* seatbelt */
+ maxdumpsz = PAGE_SIZE;
+
+ error = 0;
+
+ if (ptr != NULL && pa != 0) {
+ printf("cant have both va and pa!\n");
+ return (EINVAL);
+ }
+
+ if (ptr != NULL) {
+ /* If we're doing a virtual dump, flush any pre-existing pa pages */
+ error = blk_flush(di);
+ if (error)
+ return (error);
+ }
+
+ while (sz) {
+ if (fragsz == 0) {
+ offset = pa & PAGE_MASK;
+ fragsz += offset;
+ }
+ len = maxdumpsz - fragsz;
+ if (len > sz)
+ len = sz;
+ counter += len;
+ progress -= len;
+
+ if (counter >> 22) {
+ printf(" %lld", PG2MB(progress >> PAGE_SHIFT));
+ counter &= (1<<22) - 1;
+ }
+
+#ifdef SW_WATCHDOG
+ wdog_kern_pat(WD_LASTVAL);
+#endif
+ if (ptr) {
+ error = dump_write(di, ptr, 0, dumplo, len);
+ if (error)
+ return (error);
+ dumplo += len;
+ ptr += len;
+ sz -= len;
+ } else {
+ for (i = 0; i < len; i += PAGE_SIZE)
+ dump_va = pmap_kenter_temporary(pa + i,
+ (i + fragsz) >> PAGE_SHIFT);
+ fragsz += len;
+ pa += len;
+ sz -= len;
+ if (fragsz == maxdumpsz) {
+ error = blk_flush(di);
+ if (error)
+ return (error);
+ }
+ }
+
+ /* Check for user abort. */
+ c = cncheckc();
+ if (c == 0x03)
+ return (ECANCELED);
+ if (c != -1)
+ printf(" (CTRL-C to abort) ");
+ }
+
+ return (0);
+}
+
+static int
+blk_write_cont(struct dumperinfo *di, vm_paddr_t pa, size_t sz)
+{
+ int error;
+
+ error = blk_write(di, 0, pa, sz);
+ if (error)
+ return (error);
+
+ error = blk_flush(di);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+/* A fake page table page, to avoid having to handle both 4K and 2M pages */
+static pt_entry_t fakept[NPTEPG];
+
+void
+minidumpsys(struct dumperinfo *di)
+{
+ struct minidumphdr mdhdr;
+ uint64_t dumpsize;
+ uint32_t ptesize;
+ uint32_t bits;
+ uint32_t pa, prev_pa = 0, count = 0;
+ vm_offset_t va;
+ pd_entry_t *pdp;
+ pt_entry_t *pt, *ptp;
+ int i, k, bit, error;
+ char *addr;
+
+ /*
+ * Flush caches. Note that in the SMP case this operates only on the
+ * current CPU's L1 cache. Before we reach this point, code in either
+ * the system shutdown or kernel debugger has called stop_cpus() to stop
+ * all cores other than this one. Part of the ARM handling of
+ * stop_cpus() is to call wbinv_all() on that core's local L1 cache. So
+ * by time we get to here, all that remains is to flush the L1 for the
+ * current CPU, then the L2.
+ */
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+
+ counter = 0;
+ /* Walk page table pages, set bits in vm_page_dump */
+ ptesize = 0;
+ for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) {
+ /*
+ * We always write a page, even if it is zero. Each
+ * page written corresponds to 2MB of space
+ */
+ ptesize += L2_TABLE_SIZE_REAL;
+ pmap_get_pde_pte(pmap_kernel(), va, &pdp, &ptp);
+ if (pmap_pde_v(pdp) && pmap_pde_section(pdp)) {
+ /* This is a section mapping 1M page. */
+ pa = (*pdp & L1_S_ADDR_MASK) | (va & ~L1_S_ADDR_MASK);
+ for (k = 0; k < (L1_S_SIZE / PAGE_SIZE); k++) {
+ if (is_dumpable(pa))
+ dump_add_page(pa);
+ pa += PAGE_SIZE;
+ }
+ continue;
+ }
+ if (pmap_pde_v(pdp) && pmap_pde_page(pdp)) {
+ /* Set bit for each valid page in this 1MB block */
+ addr = pmap_kenter_temporary(*pdp & L1_C_ADDR_MASK, 0);
+ pt = (pt_entry_t*)(addr +
+ (((uint32_t)*pdp & L1_C_ADDR_MASK) & PAGE_MASK));
+ for (k = 0; k < 256; k++) {
+ if ((pt[k] & L2_TYPE_MASK) == L2_TYPE_L) {
+ pa = (pt[k] & L2_L_FRAME) |
+ (va & L2_L_OFFSET);
+ for (i = 0; i < 16; i++) {
+ if (is_dumpable(pa))
+ dump_add_page(pa);
+ k++;
+ pa += PAGE_SIZE;
+ }
+ } else if ((pt[k] & L2_TYPE_MASK) == L2_TYPE_S) {
+ pa = (pt[k] & L2_S_FRAME) |
+ (va & L2_S_OFFSET);
+ if (is_dumpable(pa))
+ dump_add_page(pa);
+ }
+ }
+ } else {
+ /* Nothing, we're going to dump a null page */
+ }
+ }
+
+ /* Calculate dump size. */
+ dumpsize = ptesize;
+ dumpsize += round_page(msgbufp->msg_size);
+ dumpsize += round_page(vm_page_dump_size);
+
+ for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) {
+ bits = vm_page_dump[i];
+ while (bits) {
+ bit = ffs(bits) - 1;
+ pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) +
+ bit) * PAGE_SIZE;
+ /* Clear out undumpable pages now if needed */
+ if (is_dumpable(pa))
+ dumpsize += PAGE_SIZE;
+ else
+ dump_drop_page(pa);
+ bits &= ~(1ul << bit);
+ }
+ }
+
+ dumpsize += PAGE_SIZE;
+
+ /* Determine dump offset on device. */
+ if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
+ error = ENOSPC;
+ goto fail;
+ }
+
+ dumplo = di->mediaoffset + di->mediasize - dumpsize;
+ dumplo -= sizeof(kdh) * 2;
+ progress = dumpsize;
+
+ /* Initialize mdhdr */
+ bzero(&mdhdr, sizeof(mdhdr));
+ strcpy(mdhdr.magic, MINIDUMP_MAGIC);
+ mdhdr.version = MINIDUMP_VERSION;
+ mdhdr.msgbufsize = msgbufp->msg_size;
+ mdhdr.bitmapsize = vm_page_dump_size;
+ mdhdr.ptesize = ptesize;
+ mdhdr.kernbase = KERNBASE;
+
+ mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARM_VERSION, dumpsize,
+ di->blocksize);
+
+ printf("Physical memory: %u MB\n", ptoa((uintmax_t)physmem) / 1048576);
+ printf("Dumping %llu MB:", (long long)dumpsize >> 20);
+
+ /* Dump leader */
+ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
+ if (error)
+ goto fail;
+ dumplo += sizeof(kdh);
+
+ /* Dump my header */
+ bzero(&fakept, sizeof(fakept));
+ bcopy(&mdhdr, &fakept, sizeof(mdhdr));
+ error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
+ if (error)
+ goto fail;
+
+ /* Dump msgbuf up front */
+ error = blk_write(di, (char *)msgbufp->msg_ptr, 0, round_page(msgbufp->msg_size));
+ if (error)
+ goto fail;
+
+ /* Dump bitmap */
+ error = blk_write(di, (char *)vm_page_dump, 0,
+ round_page(vm_page_dump_size));
+ if (error)
+ goto fail;
+
+ /* Dump kernel page table pages */
+ for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) {
+ /* We always write a page, even if it is zero */
+ pmap_get_pde_pte(pmap_kernel(), va, &pdp, &ptp);
+
+ if (pmap_pde_v(pdp) && pmap_pde_section(pdp)) {
+ if (count) {
+ error = blk_write_cont(di, prev_pa,
+ count * L2_TABLE_SIZE_REAL);
+ if (error)
+ goto fail;
+ count = 0;
+ prev_pa = 0;
+ }
+ /* This is a single 2M block. Generate a fake PTP */
+ pa = (*pdp & L1_S_ADDR_MASK) | (va & ~L1_S_ADDR_MASK);
+ for (k = 0; k < (L1_S_SIZE / PAGE_SIZE); k++) {
+ fakept[k] = L2_S_PROTO | (pa + (k * PAGE_SIZE)) |
+ L2_S_PROT(PTE_KERNEL,
+ VM_PROT_READ | VM_PROT_WRITE);
+ }
+ error = blk_write(di, (char *)&fakept, 0,
+ L2_TABLE_SIZE_REAL);
+ if (error)
+ goto fail;
+ /* Flush, in case we reuse fakept in the same block */
+ error = blk_flush(di);
+ if (error)
+ goto fail;
+ continue;
+ }
+ if (pmap_pde_v(pdp) && pmap_pde_page(pdp)) {
+ pa = *pdp & L1_C_ADDR_MASK;
+ if (!count) {
+ prev_pa = pa;
+ count++;
+ }
+ else {
+ if (pa == (prev_pa + count * L2_TABLE_SIZE_REAL))
+ count++;
+ else {
+ error = blk_write_cont(di, prev_pa,
+ count * L2_TABLE_SIZE_REAL);
+ if (error)
+ goto fail;
+ count = 1;
+ prev_pa = pa;
+ }
+ }
+ } else {
+ if (count) {
+ error = blk_write_cont(di, prev_pa,
+ count * L2_TABLE_SIZE_REAL);
+ if (error)
+ goto fail;
+ count = 0;
+ prev_pa = 0;
+ }
+ bzero(fakept, sizeof(fakept));
+ error = blk_write(di, (char *)&fakept, 0,
+ L2_TABLE_SIZE_REAL);
+ if (error)
+ goto fail;
+ /* Flush, in case we reuse fakept in the same block */
+ error = blk_flush(di);
+ if (error)
+ goto fail;
+ }
+ }
+
+ if (count) {
+ error = blk_write_cont(di, prev_pa, count * L2_TABLE_SIZE_REAL);
+ if (error)
+ goto fail;
+ count = 0;
+ prev_pa = 0;
+ }
+
+ /* Dump memory chunks */
+ for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) {
+ bits = vm_page_dump[i];
+ while (bits) {
+ bit = ffs(bits) - 1;
+ pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) +
+ bit) * PAGE_SIZE;
+ if (!count) {
+ prev_pa = pa;
+ count++;
+ } else {
+ if (pa == (prev_pa + count * PAGE_SIZE))
+ count++;
+ else {
+ error = blk_write_cont(di, prev_pa,
+ count * PAGE_SIZE);
+ if (error)
+ goto fail;
+ count = 1;
+ prev_pa = pa;
+ }
+ }
+ bits &= ~(1ul << bit);
+ }
+ }
+ if (count) {
+ error = blk_write_cont(di, prev_pa, count * PAGE_SIZE);
+ if (error)
+ goto fail;
+ count = 0;
+ prev_pa = 0;
+ }
+
+ /* Dump trailer */
+ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
+ if (error)
+ goto fail;
+ dumplo += sizeof(kdh);
+
+ /* Signal completion, signoff and exit stage left. */
+ dump_write(di, NULL, 0, 0, 0);
+ printf("\nDump complete\n");
+ return;
+
+fail:
+ if (error < 0)
+ error = -error;
+
+ if (error == ECANCELED)
+ printf("\nDump aborted\n");
+ else if (error == ENOSPC)
+ printf("\nDump failed. Partition too small.\n");
+ else
+ printf("\n** DUMP FAILED (ERROR %d) **\n", error);
+}
+
+void
+dump_add_page(vm_paddr_t pa)
+{
+ int idx, bit;
+
+ pa >>= PAGE_SHIFT;
+ idx = pa >> 5; /* 2^5 = 32 */
+ bit = pa & 31;
+ atomic_set_int(&vm_page_dump[idx], 1ul << bit);
+}
+
+void
+dump_drop_page(vm_paddr_t pa)
+{
+ int idx, bit;
+
+ pa >>= PAGE_SHIFT;
+ idx = pa >> 5; /* 2^5 = 32 */
+ bit = pa & 31;
+ atomic_clear_int(&vm_page_dump[idx], 1ul << bit);
+}
Property changes on: trunk/sys/arm/arm/minidump_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/mp_machdep.c
===================================================================
--- trunk/sys/arm/arm/mp_machdep.c (rev 0)
+++ trunk/sys/arm/arm/mp_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,411 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/mp_machdep.c 278639 2015-02-12 21:20:28Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/pcpu.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+#include <sys/ktr.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+
+#include <machine/armreg.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/smp.h>
+#include <machine/pcb.h>
+#include <machine/pte.h>
+#include <machine/physmem.h>
+#include <machine/intr.h>
+#include <machine/vmparam.h>
+#ifdef VFP
+#include <machine/vfp.h>
+#endif
+#ifdef CPU_MV_PJ4B
+#include <arm/mv/mvwin.h>
+#include <dev/fdt/fdt_common.h>
+#endif
+
+#include "opt_smp.h"
+
+extern struct pcpu __pcpu[];
+/* used to hold the AP's until we are ready to release them */
+struct mtx ap_boot_mtx;
+struct pcb stoppcbs[MAXCPU];
+
+/* # of Applications processors */
+volatile int mp_naps;
+
+/* Set to 1 once we're ready to let the APs out of the pen. */
+volatile int aps_ready = 0;
+
+static int ipi_handler(void *arg);
+void set_stackptrs(int cpu);
+
+/* Temporary variables for init_secondary() */
+void *dpcpu[MAXCPU - 1];
+
+/* Determine if we running MP machine */
+int
+cpu_mp_probe(void)
+{
+ CPU_SETOF(0, &all_cpus);
+
+ return (platform_mp_probe());
+}
+
+/* Start Application Processor via platform specific function */
+static int
+check_ap(void)
+{
+ uint32_t ms;
+
+ for (ms = 0; ms < 2000; ++ms) {
+ if ((mp_naps + 1) == mp_ncpus)
+ return (0); /* success */
+ else
+ DELAY(1000);
+ }
+
+ return (-2);
+}
+
+extern unsigned char _end[];
+
+/* Initialize and fire up non-boot processors */
+void
+cpu_mp_start(void)
+{
+ int error, i;
+
+ mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
+
+ /* Reserve memory for application processors */
+ for(i = 0; i < (mp_ncpus - 1); i++)
+ dpcpu[i] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
+ M_WAITOK | M_ZERO);
+
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ cpu_idcache_wbinv_all();
+
+ /* Initialize boot code and start up processors */
+ platform_mp_start_ap();
+
+ /* Check if ap's started properly */
+ error = check_ap();
+ if (error)
+ printf("WARNING: Some AP's failed to start\n");
+ else
+ for (i = 1; i < mp_ncpus; i++)
+ CPU_SET(i, &all_cpus);
+
+}
+
+/* Introduce rest of cores to the world */
+void
+cpu_mp_announce(void)
+{
+
+}
+
+extern vm_paddr_t pmap_pa;
+void
+init_secondary(int cpu)
+{
+ struct pcpu *pc;
+ uint32_t loop_counter;
+ int start = 0, end = 0;
+
+ cpu_setup(NULL);
+ setttb(pmap_pa);
+ cpu_tlb_flushID();
+
+ pc = &__pcpu[cpu];
+
+ /*
+ * pcpu_init() updates queue, so it should not be executed in parallel
+ * on several cores
+ */
+ while(mp_naps < (cpu - 1))
+ ;
+
+ pcpu_init(pc, cpu, sizeof(struct pcpu));
+ dpcpu_init(dpcpu[cpu - 1], cpu);
+
+ /* Provide stack pointers for other processor modes. */
+ set_stackptrs(cpu);
+
+ /* Signal our startup to BSP */
+ atomic_add_rel_32(&mp_naps, 1);
+
+ /* Spin until the BSP releases the APs */
+ while (!aps_ready)
+ ;
+
+ /* Initialize curthread */
+ KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
+ pc->pc_curthread = pc->pc_idlethread;
+ pc->pc_curpcb = pc->pc_idlethread->td_pcb;
+ set_curthread(pc->pc_idlethread);
+#ifdef VFP
+ pc->pc_cpu = cpu;
+
+ vfp_init();
+#endif
+
+ mtx_lock_spin(&ap_boot_mtx);
+
+ atomic_add_rel_32(&smp_cpus, 1);
+
+ if (smp_cpus == mp_ncpus) {
+ /* enable IPI's, tlb shootdown, freezes etc */
+ atomic_store_rel_int(&smp_started, 1);
+ }
+
+ mtx_unlock_spin(&ap_boot_mtx);
+
+ /* Enable ipi */
+#ifdef IPI_IRQ_START
+ start = IPI_IRQ_START;
+#ifdef IPI_IRQ_END
+ end = IPI_IRQ_END;
+#else
+ end = IPI_IRQ_START;
+#endif
+#endif
+
+ for (int i = start; i <= end; i++)
+ arm_unmask_irq(i);
+ enable_interrupts(PSR_I);
+
+ loop_counter = 0;
+ while (smp_started == 0) {
+ DELAY(100);
+ loop_counter++;
+ if (loop_counter == 1000)
+ CTR0(KTR_SMP, "AP still wait for smp_started");
+ }
+ /* Start per-CPU event timers. */
+ cpu_initclocks_ap();
+
+ CTR0(KTR_SMP, "go into scheduler");
+ platform_mp_init_secondary();
+
+ /* Enter the scheduler */
+ sched_throw(NULL);
+
+ panic("scheduler returned us to %s", __func__);
+ /* NOTREACHED */
+}
+
+static int
+ipi_handler(void *arg)
+{
+ u_int cpu, ipi;
+
+ cpu = PCPU_GET(cpuid);
+
+ ipi = pic_ipi_get((int)arg);
+
+ while ((ipi != 0x3ff)) {
+ switch (ipi) {
+ case IPI_RENDEZVOUS:
+ CTR0(KTR_SMP, "IPI_RENDEZVOUS");
+ smp_rendezvous_action();
+ break;
+
+ case IPI_AST:
+ CTR0(KTR_SMP, "IPI_AST");
+ break;
+
+ case IPI_STOP:
+ /*
+ * IPI_STOP_HARD is mapped to IPI_STOP so it is not
+ * necessary to add it in the switch.
+ */
+ CTR0(KTR_SMP, "IPI_STOP or IPI_STOP_HARD");
+
+ savectx(&stoppcbs[cpu]);
+
+ /*
+ * CPUs are stopped when entering the debugger and at
+ * system shutdown, both events which can precede a
+ * panic dump. For the dump to be correct, all caches
+ * must be flushed and invalidated, but on ARM there's
+ * no way to broadcast a wbinv_all to other cores.
+ * Instead, we have each core do the local wbinv_all as
+ * part of stopping the core. The core requesting the
+ * stop will do the l2 cache flush after all other cores
+ * have done their l1 flushes and stopped.
+ */
+ cpu_idcache_wbinv_all();
+
+ /* Indicate we are stopped */
+ CPU_SET_ATOMIC(cpu, &stopped_cpus);
+
+ /* Wait for restart */
+ while (!CPU_ISSET(cpu, &started_cpus))
+ cpu_spinwait();
+
+ CPU_CLR_ATOMIC(cpu, &started_cpus);
+ CPU_CLR_ATOMIC(cpu, &stopped_cpus);
+ CTR0(KTR_SMP, "IPI_STOP (restart)");
+ break;
+ case IPI_PREEMPT:
+ CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
+ sched_preempt(curthread);
+ break;
+ case IPI_HARDCLOCK:
+ CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
+ hardclockintr();
+ break;
+ case IPI_TLB:
+ CTR1(KTR_SMP, "%s: IPI_TLB", __func__);
+ cpufuncs.cf_tlb_flushID();
+ break;
+ default:
+ panic("Unknown IPI 0x%0x on cpu %d", ipi, curcpu);
+ }
+
+ pic_ipi_clear(ipi);
+ ipi = pic_ipi_get(-1);
+ }
+
+ return (FILTER_HANDLED);
+}
+
+static void
+release_aps(void *dummy __unused)
+{
+ uint32_t loop_counter;
+ int start = 0, end = 0;
+
+ if (mp_ncpus == 1)
+ return;
+#ifdef IPI_IRQ_START
+ start = IPI_IRQ_START;
+#ifdef IPI_IRQ_END
+ end = IPI_IRQ_END;
+#else
+ end = IPI_IRQ_START;
+#endif
+#endif
+
+ for (int i = start; i <= end; i++) {
+ /*
+ * IPI handler
+ */
+ /*
+ * Use 0xdeadbeef as the argument value for irq 0,
+ * if we used 0, the intr code will give the trap frame
+ * pointer instead.
+ */
+ arm_setup_irqhandler("ipi", ipi_handler, NULL, (void *)i, i,
+ INTR_TYPE_MISC | INTR_EXCL, NULL);
+
+ /* Enable ipi */
+ arm_unmask_irq(i);
+ }
+ atomic_store_rel_int(&aps_ready, 1);
+
+ printf("Release APs\n");
+
+ for (loop_counter = 0; loop_counter < 2000; loop_counter++) {
+ if (smp_started)
+ return;
+ DELAY(1000);
+ }
+ printf("AP's not started\n");
+}
+
+SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL);
+
+struct cpu_group *
+cpu_topo(void)
+{
+
+ return (smp_topo_1level(CG_SHARE_L2, mp_ncpus, 0));
+}
+
+void
+cpu_mp_setmaxid(void)
+{
+
+ platform_mp_setmaxid();
+}
+
+/* Sending IPI */
+void
+ipi_all_but_self(u_int ipi)
+{
+ cpuset_t other_cpus;
+
+ other_cpus = all_cpus;
+ CPU_CLR(PCPU_GET(cpuid), &other_cpus);
+ CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
+ platform_ipi_send(other_cpus, ipi);
+}
+
+void
+ipi_cpu(int cpu, u_int ipi)
+{
+ cpuset_t cpus;
+
+ CPU_ZERO(&cpus);
+ CPU_SET(cpu, &cpus);
+
+ CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi);
+ platform_ipi_send(cpus, ipi);
+}
+
+void
+ipi_selected(cpuset_t cpus, u_int ipi)
+{
+
+ CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
+ platform_ipi_send(cpus, ipi);
+}
+
+void
+tlb_broadcast(int ipi)
+{
+
+ if (smp_started)
+ ipi_all_but_self(ipi);
+}
Property changes on: trunk/sys/arm/arm/mp_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/mpcore_timer.c
===================================================================
--- trunk/sys/arm/arm/mpcore_timer.c (rev 0)
+++ trunk/sys/arm/arm/mpcore_timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,548 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Developed by Ben Gray <ben.r.gray at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * The ARM Cortex-A9 core can support a global timer plus a private and
+ * watchdog timer per core. This driver reserves memory and interrupt
+ * resources for accessing both timer register sets, these resources are
+ * stored globally and used to setup the timecount and eventtimer.
+ *
+ * The timecount timer uses the global 64-bit counter, whereas the
+ * per-CPU eventtimer uses the private 32-bit counters.
+ *
+ *
+ * REF: ARM Cortex-A9 MPCore, Technical Reference Manual (rev. r2p2)
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/mpcore_timer.c 273673 2014-10-26 03:55:09Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/arm/mpcore_timervar.h>
+
+/* Private (per-CPU) timer register map */
+#define PRV_TIMER_LOAD 0x0000
+#define PRV_TIMER_COUNT 0x0004
+#define PRV_TIMER_CTRL 0x0008
+#define PRV_TIMER_INTR 0x000C
+
+#define PRV_TIMER_CTR_PRESCALER_SHIFT 8
+#define PRV_TIMER_CTRL_IRQ_ENABLE (1UL << 2)
+#define PRV_TIMER_CTRL_AUTO_RELOAD (1UL << 1)
+#define PRV_TIMER_CTRL_TIMER_ENABLE (1UL << 0)
+
+#define PRV_TIMER_INTR_EVENT (1UL << 0)
+
+/* Global timer register map */
+#define GBL_TIMER_COUNT_LOW 0x0000
+#define GBL_TIMER_COUNT_HIGH 0x0004
+#define GBL_TIMER_CTRL 0x0008
+#define GBL_TIMER_INTR 0x000C
+
+#define GBL_TIMER_CTR_PRESCALER_SHIFT 8
+#define GBL_TIMER_CTRL_AUTO_INC (1UL << 3)
+#define GBL_TIMER_CTRL_IRQ_ENABLE (1UL << 2)
+#define GBL_TIMER_CTRL_COMP_ENABLE (1UL << 1)
+#define GBL_TIMER_CTRL_TIMER_ENABLE (1UL << 0)
+
+#define GBL_TIMER_INTR_EVENT (1UL << 0)
+
+struct arm_tmr_softc {
+ device_t dev;
+ int irqrid;
+ int memrid;
+ struct resource * gbl_mem;
+ struct resource * prv_mem;
+ struct resource * prv_irq;
+ uint64_t clkfreq;
+ struct eventtimer et;
+};
+
+static struct eventtimer *arm_tmr_et;
+static struct timecounter *arm_tmr_tc;
+static uint64_t arm_tmr_freq;
+static boolean_t arm_tmr_freq_varies;
+
+#define tmr_prv_read_4(sc, reg) bus_read_4((sc)->prv_mem, reg)
+#define tmr_prv_write_4(sc, reg, val) bus_write_4((sc)->prv_mem, reg, val)
+#define tmr_gbl_read_4(sc, reg) bus_read_4((sc)->gbl_mem, reg)
+#define tmr_gbl_write_4(sc, reg, val) bus_write_4((sc)->gbl_mem, reg, val)
+
+static timecounter_get_t arm_tmr_get_timecount;
+
+static struct timecounter arm_tmr_timecount = {
+ .tc_name = "MPCore",
+ .tc_get_timecount = arm_tmr_get_timecount,
+ .tc_poll_pps = NULL,
+ .tc_counter_mask = ~0u,
+ .tc_frequency = 0,
+ .tc_quality = 800,
+};
+
+#define TMR_GBL 0x01
+#define TMR_PRV 0x02
+#define TMR_BOTH (TMR_GBL | TMR_PRV)
+#define TMR_NONE 0
+
+static struct ofw_compat_data compat_data[] = {
+ {"arm,mpcore-timers", TMR_BOTH}, /* Non-standard, FreeBSD. */
+ {"arm,cortex-a9-global-timer", TMR_GBL},
+ {"arm,cortex-a5-global-timer", TMR_GBL},
+ {"arm,cortex-a9-twd-timer", TMR_PRV},
+ {"arm,cortex-a5-twd-timer", TMR_PRV},
+ {"arm,arm11mp-twd-timer", TMR_PRV},
+ {NULL, TMR_NONE}
+};
+
+/**
+ * arm_tmr_get_timecount - reads the timecount (global) timer
+ * @tc: pointer to arm_tmr_timecount struct
+ *
+ * We only read the lower 32-bits, the timecount stuff only uses 32-bits
+ * so (for now?) ignore the upper 32-bits.
+ *
+ * RETURNS
+ * The lower 32-bits of the counter.
+ */
+static unsigned
+arm_tmr_get_timecount(struct timecounter *tc)
+{
+ struct arm_tmr_softc *sc;
+
+ sc = tc->tc_priv;
+ return (tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW));
+}
+
+/**
+ * arm_tmr_start - starts the eventtimer (private) timer
+ * @et: pointer to eventtimer struct
+ * @first: the number of seconds and fractional sections to trigger in
+ * @period: the period (in seconds and fractional sections) to set
+ *
+ * If the eventtimer is required to be in oneshot mode, period will be
+ * NULL and first will point to the time to trigger. If in periodic mode
+ * period will contain the time period and first may optionally contain
+ * the time for the first period.
+ *
+ * RETURNS
+ * Always returns 0
+ */
+static int
+arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct arm_tmr_softc *sc;
+ uint32_t load, count;
+ uint32_t ctrl;
+
+ sc = et->et_priv;
+ tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0);
+ tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
+
+ ctrl = PRV_TIMER_CTRL_IRQ_ENABLE | PRV_TIMER_CTRL_TIMER_ENABLE;
+
+ if (period != 0) {
+ load = ((uint32_t)et->et_frequency * period) >> 32;
+ ctrl |= PRV_TIMER_CTRL_AUTO_RELOAD;
+ } else
+ load = 0;
+
+ if (first != 0)
+ count = (uint32_t)((et->et_frequency * first) >> 32);
+ else
+ count = load;
+
+ tmr_prv_write_4(sc, PRV_TIMER_LOAD, load);
+ tmr_prv_write_4(sc, PRV_TIMER_COUNT, count);
+ tmr_prv_write_4(sc, PRV_TIMER_CTRL, ctrl);
+
+ return (0);
+}
+
+/**
+ * arm_tmr_stop - stops the eventtimer (private) timer
+ * @et: pointer to eventtimer struct
+ *
+ * Simply stops the private timer by clearing all bits in the ctrl register.
+ *
+ * RETURNS
+ * Always returns 0
+ */
+static int
+arm_tmr_stop(struct eventtimer *et)
+{
+ struct arm_tmr_softc *sc;
+
+ sc = et->et_priv;
+ tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0);
+ tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
+ return (0);
+}
+
+/**
+ * arm_tmr_intr - ISR for the eventtimer (private) timer
+ * @arg: pointer to arm_tmr_softc struct
+ *
+ * Clears the event register and then calls the eventtimer callback.
+ *
+ * RETURNS
+ * Always returns FILTER_HANDLED
+ */
+static int
+arm_tmr_intr(void *arg)
+{
+ struct arm_tmr_softc *sc;
+
+ sc = arg;
+ tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+ return (FILTER_HANDLED);
+}
+
+
+
+
+/**
+ * arm_tmr_probe - timer probe routine
+ * @dev: new device
+ *
+ * The probe function returns success when probed with the fdt compatible
+ * string set to "arm,mpcore-timers".
+ *
+ * RETURNS
+ * BUS_PROBE_DEFAULT if the fdt device is compatible, otherwise ENXIO.
+ */
+static int
+arm_tmr_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == TMR_NONE)
+ return (ENXIO);
+
+ device_set_desc(dev, "ARM MPCore Timers");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+attach_tc(struct arm_tmr_softc *sc)
+{
+ int rid;
+
+ if (arm_tmr_tc != NULL)
+ return (EBUSY);
+
+ rid = sc->memrid;
+ sc->gbl_mem = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->gbl_mem == NULL) {
+ device_printf(sc->dev, "could not allocate gbl mem resources\n");
+ return (ENXIO);
+ }
+ tmr_gbl_write_4(sc, GBL_TIMER_CTRL, 0x00000000);
+
+ arm_tmr_timecount.tc_frequency = sc->clkfreq;
+ arm_tmr_timecount.tc_priv = sc;
+ tc_init(&arm_tmr_timecount);
+ arm_tmr_tc = &arm_tmr_timecount;
+
+ tmr_gbl_write_4(sc, GBL_TIMER_CTRL, GBL_TIMER_CTRL_TIMER_ENABLE);
+
+ return (0);
+}
+
+static int
+attach_et(struct arm_tmr_softc *sc)
+{
+ void *ihl;
+ int irid, mrid;
+
+ if (arm_tmr_et != NULL)
+ return (EBUSY);
+
+ mrid = sc->memrid;
+ sc->prv_mem = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &mrid,
+ RF_ACTIVE);
+ if (sc->prv_mem == NULL) {
+ device_printf(sc->dev, "could not allocate prv mem resources\n");
+ return (ENXIO);
+ }
+ tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0x00000000);
+
+ irid = sc->irqrid;
+ sc->prv_irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &irid, RF_ACTIVE);
+ if (sc->prv_irq == NULL) {
+ bus_release_resource(sc->dev, SYS_RES_MEMORY, mrid, sc->prv_mem);
+ device_printf(sc->dev, "could not allocate prv irq resources\n");
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(sc->dev, sc->prv_irq, INTR_TYPE_CLK, arm_tmr_intr,
+ NULL, sc, &ihl) != 0) {
+ bus_release_resource(sc->dev, SYS_RES_MEMORY, mrid, sc->prv_mem);
+ bus_release_resource(sc->dev, SYS_RES_IRQ, irid, sc->prv_irq);
+ device_printf(sc->dev, "unable to setup the et irq handler.\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Setup and register the eventtimer. Most event timers set their min
+ * and max period values to some value calculated from the clock
+ * frequency. We might not know yet what our runtime clock frequency
+ * will be, so we just use some safe values. A max of 2 seconds ensures
+ * that even if our base clock frequency is 2GHz (meaning a 4GHz CPU),
+ * we won't overflow our 32-bit timer count register. A min of 20
+ * nanoseconds is pretty much completely arbitrary.
+ */
+ sc->et.et_name = "MPCore";
+ sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
+ sc->et.et_quality = 1000;
+ sc->et.et_frequency = sc->clkfreq;
+ sc->et.et_min_period = 20 * SBT_1NS;
+ sc->et.et_max_period = 2 * SBT_1S;
+ sc->et.et_start = arm_tmr_start;
+ sc->et.et_stop = arm_tmr_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+ arm_tmr_et = &sc->et;
+
+ return (0);
+}
+
+/**
+ * arm_tmr_attach - attaches the timer to the simplebus
+ * @dev: new device
+ *
+ * Reserves memory and interrupt resources, stores the softc structure
+ * globally and registers both the timecount and eventtimer objects.
+ *
+ * RETURNS
+ * Zero on sucess or ENXIO if an error occuried.
+ */
+static int
+arm_tmr_attach(device_t dev)
+{
+ struct arm_tmr_softc *sc;
+ phandle_t node;
+ pcell_t clock;
+ int et_err, tc_err, tmrtype;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (arm_tmr_freq_varies) {
+ sc->clkfreq = arm_tmr_freq;
+ } else {
+ if (arm_tmr_freq != 0) {
+ sc->clkfreq = arm_tmr_freq;
+ } else {
+ /* Get the base clock frequency */
+ node = ofw_bus_get_node(dev);
+ if ((OF_getencprop(node, "clock-frequency", &clock,
+ sizeof(clock))) <= 0) {
+ device_printf(dev, "missing clock-frequency "
+ "attribute in FDT\n");
+ return (ENXIO);
+ }
+ sc->clkfreq = clock;
+ }
+ }
+
+ tmrtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ tc_err = ENXIO;
+ et_err = ENXIO;
+
+ /*
+ * If we're handling the global timer and it is fixed-frequency, set it
+ * up to use as a timecounter. If it's variable frequency it won't work
+ * as a timecounter. We also can't use it for DELAY(), so hopefully the
+ * platform provides its own implementation. If it doesn't, ours will
+ * get used, but since the frequency isn't set, it will only use the
+ * bogus loop counter.
+ */
+ if (tmrtype & TMR_GBL) {
+ if (!arm_tmr_freq_varies)
+ tc_err = attach_tc(sc);
+ else if (bootverbose)
+ device_printf(sc->dev,
+ "not using variable-frequency device as timecounter");
+ sc->memrid++;
+ sc->irqrid++;
+ }
+
+ /* If we are handling the private timer, set it up as an eventtimer. */
+ if (tmrtype & TMR_PRV) {
+ et_err = attach_et(sc);
+ }
+
+ /*
+ * If we didn't successfully set up a timecounter or eventtimer then we
+ * didn't actually attach at all, return error.
+ */
+ if (tc_err != 0 && et_err != 0) {
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static device_method_t arm_tmr_methods[] = {
+ DEVMETHOD(device_probe, arm_tmr_probe),
+ DEVMETHOD(device_attach, arm_tmr_attach),
+ { 0, 0 }
+};
+
+static driver_t arm_tmr_driver = {
+ "mp_tmr",
+ arm_tmr_methods,
+ sizeof(struct arm_tmr_softc),
+};
+
+static devclass_t arm_tmr_devclass;
+
+EARLY_DRIVER_MODULE(mp_tmr, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(mp_tmr, ofwbus, arm_tmr_driver, arm_tmr_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+
+/*
+ * Handle a change in clock frequency. The mpcore timer runs at half the CPU
+ * frequency. When the CPU frequency changes due to power-saving or thermal
+ * managment, the platform-specific code that causes the frequency change calls
+ * this routine to inform the clock driver, and we in turn inform the event
+ * timer system, which actually updates the value in et->frequency for us and
+ * reschedules the current event(s) in a way that's atomic with respect to
+ * start/stop/intr code that may be running on various CPUs at the time of the
+ * call.
+ *
+ * This routine can also be called by a platform's early init code. If the
+ * value passed is ARM_TMR_FREQUENCY_VARIES, that will cause the attach() code
+ * to register as an eventtimer, but not a timecounter. If the value passed in
+ * is any other non-zero value it is used as the fixed frequency for the timer.
+ */
+void
+arm_tmr_change_frequency(uint64_t newfreq)
+{
+
+ if (newfreq == ARM_TMR_FREQUENCY_VARIES) {
+ arm_tmr_freq_varies = true;
+ return;
+ }
+
+ arm_tmr_freq = newfreq;
+ if (arm_tmr_et != NULL)
+ et_change_frequency(arm_tmr_et, newfreq);
+}
+
+/**
+ * DELAY - Delay for at least usec microseconds.
+ * @usec: number of microseconds to delay by
+ *
+ * This function is called all over the kernel and is suppose to provide a
+ * consistent delay. This function may also be called before the console
+ * is setup so no printf's can be called here.
+ *
+ * RETURNS:
+ * nothing
+ */
+static void __used /* Must emit function code for the weak ref below. */
+arm_tmr_DELAY(int usec)
+{
+ struct arm_tmr_softc *sc;
+ int32_t counts_per_usec;
+ int32_t counts;
+ uint32_t first, last;
+
+ /* Check the timers are setup, if not just use a for loop for the meantime */
+ if (arm_tmr_tc == NULL || arm_tmr_timecount.tc_frequency == 0) {
+ for (; usec > 0; usec--)
+ for (counts = 200; counts > 0; counts--)
+ cpufunc_nullop(); /* Prevent gcc from optimizing
+ * out the loop
+ */
+ return;
+ }
+
+ sc = arm_tmr_tc->tc_priv;
+
+ /* Get the number of times to count */
+ counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1);
+
+ /*
+ * Clamp the timeout at a maximum value (about 32 seconds with
+ * a 66MHz clock). *Nobody* should be delay()ing for anywhere
+ * near that length of time and if they are, they should be hung
+ * out to dry.
+ */
+ if (usec >= (0x80000000U / counts_per_usec))
+ counts = (0x80000000U / counts_per_usec) - 1;
+ else
+ counts = usec * counts_per_usec;
+
+ first = tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW);
+
+ while (counts > 0) {
+ last = tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW);
+ counts -= (int32_t)(last - first);
+ first = last;
+ }
+}
+
+/*
+ * Supply a DELAY() implementation via weak linkage. A platform may want to use
+ * the mpcore per-cpu eventtimers but provide its own DELAY() routine,
+ * especially when the core frequency can change on the fly.
+ */
+__weak_reference(arm_tmr_DELAY, DELAY);
+
Property changes on: trunk/sys/arm/arm/mpcore_timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/mpcore_timervar.h
===================================================================
--- trunk/sys/arm/arm/mpcore_timervar.h (rev 0)
+++ trunk/sys/arm/arm/mpcore_timervar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,48 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/arm/mpcore_timervar.h 266347 2014-05-17 20:10:12Z ian $
+ */
+
+#ifndef _ARM_MPCORE_TIMERVAR_H_
+#define _ARM_MPCORE_TIMERVAR_H_
+
+/*
+ * This value, passed to arm_tmr_change_frequency() any time before the mpcore
+ * timer device attaches, informs the driver that the mpcore clock frequency can
+ * change on the fly, and thus can't be used as a timecounter. The hardware can
+ * still be used as an eventtimer, as long as each frequency change is
+ * communicated to it with calls to arm_tmr_change_frequency().
+ */
+#define ARM_TMR_FREQUENCY_VARIES -1ULL
+
+/*
+ * Inform the mpcore timer driver of a new clock frequency. This can be called
+ * both before and after the mpcore timer driver attaches.
+ */
+void arm_tmr_change_frequency(uint64_t newfreq);
+
+#endif
Property changes on: trunk/sys/arm/arm/mpcore_timervar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/nexus.c
===================================================================
--- trunk/sys/arm/arm/nexus.c (rev 0)
+++ trunk/sys/arm/arm/nexus.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,362 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 1998 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * This code implements a `root nexus' for Arm Architecture
+ * machines. The function of the root nexus is to serve as an
+ * attachment point for both processors and buses, and to manage
+ * resources which are common to all of them. In particular,
+ * this code implements the core resource managers for interrupt
+ * requests, DMA requests (which rightfully should be a part of the
+ * ISA code but it's easier to do it here for now), I/O port addresses,
+ * and I/O memory address space.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/nexus.c 274268 2014-11-08 03:42:19Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/interrupt.h>
+
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include "opt_platform.h"
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <machine/fdt.h>
+#include "ofw_bus_if.h"
+#endif
+
+static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
+
+struct nexus_device {
+ struct resource_list nx_resources;
+};
+
+#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev))
+
+static struct rman mem_rman;
+
+static int nexus_probe(device_t);
+static int nexus_attach(device_t);
+static int nexus_print_child(device_t, device_t);
+static device_t nexus_add_child(device_t, u_int, const char *, int);
+static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
+ u_long, u_long, u_long, u_int);
+static int nexus_activate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol);
+static int nexus_deactivate_resource(device_t, device_t, int, int,
+ struct resource *);
+
+static int nexus_setup_intr(device_t dev, device_t child, struct resource *res,
+ int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep);
+static int nexus_teardown_intr(device_t, device_t, struct resource *, void *);
+
+#ifdef FDT
+static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent,
+ int icells, pcell_t *intr);
+#endif
+
+static device_method_t nexus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nexus_probe),
+ DEVMETHOD(device_attach, nexus_attach),
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, nexus_print_child),
+ DEVMETHOD(bus_add_child, nexus_add_child),
+ DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
+ DEVMETHOD(bus_activate_resource, nexus_activate_resource),
+ DEVMETHOD(bus_config_intr, nexus_config_intr),
+ DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, nexus_setup_intr),
+ DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
+#ifdef FDT
+ DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr),
+#endif
+ { 0, 0 }
+};
+
+static devclass_t nexus_devclass;
+static driver_t nexus_driver = {
+ "nexus",
+ nexus_methods,
+ 1 /* no softc */
+};
+EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0,
+ BUS_PASS_BUS + BUS_PASS_ORDER_EARLY);
+
+static int
+nexus_probe(device_t dev)
+{
+
+ device_quiet(dev); /* suppress attach message for neatness */
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+nexus_attach(device_t dev)
+{
+
+ mem_rman.rm_start = 0;
+ mem_rman.rm_end = ~0ul;
+ mem_rman.rm_type = RMAN_ARRAY;
+ mem_rman.rm_descr = "I/O memory addresses";
+ if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0))
+ panic("nexus_probe mem_rman");
+
+ /*
+ * First, deal with the children we know about already
+ */
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static int
+nexus_print_child(device_t bus, device_t child)
+{
+ int retval = 0;
+
+ retval += bus_print_child_header(bus, child);
+ retval += printf("\n");
+
+ return (retval);
+}
+
+static device_t
+nexus_add_child(device_t bus, u_int order, const char *name, int unit)
+{
+ device_t child;
+ struct nexus_device *ndev;
+
+ ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO);
+ if (!ndev)
+ return (0);
+ resource_list_init(&ndev->nx_resources);
+
+ child = device_add_child_ordered(bus, order, name, unit);
+
+ /* should we free this in nexus_child_detached? */
+ device_set_ivars(child, ndev);
+
+ return (child);
+}
+
+
+/*
+ * Allocate a resource on behalf of child. NB: child is usually going to be a
+ * child of one of our descendants, not a direct child of nexus0.
+ * (Exceptions include footbridge.)
+ */
+static struct resource *
+nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct resource *rv;
+ struct rman *rm;
+ int needactivate = flags & RF_ACTIVE;
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ case SYS_RES_IOPORT:
+ rm = &mem_rman;
+ break;
+
+ default:
+ return (0);
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == 0)
+ return (0);
+
+ rman_set_rid(rv, *rid);
+ rman_set_bushandle(rv, rman_get_start(rv));
+
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (0);
+ }
+ }
+
+ return (rv);
+}
+
+static int
+nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+ int ret = ENODEV;
+
+ if (arm_config_irq)
+ ret = (*arm_config_irq)(irq, trig, pol);
+
+ return (ret);
+}
+
+static int
+nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
+ driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
+{
+ int irq;
+
+ if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
+ flags |= INTR_EXCL;
+
+ for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
+ arm_setup_irqhandler(device_get_nameunit(child),
+ filt, intr, arg, irq, flags, cookiep);
+ arm_unmask_irq(irq);
+ }
+ return (0);
+}
+
+static int
+nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
+{
+
+ return (arm_remove_irqhandler(rman_get_start(r), ih));
+}
+
+
+static int
+nexus_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ int err;
+ bus_addr_t paddr;
+ bus_size_t psize;
+ bus_space_handle_t vaddr;
+
+ if ((err = rman_activate_resource(r)) != 0)
+ return (err);
+
+ /*
+ * If this is a memory resource, map it into the kernel.
+ */
+ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+ paddr = (bus_addr_t)rman_get_start(r);
+ psize = (bus_size_t)rman_get_size(r);
+#ifdef FDT
+ err = bus_space_map(fdtbus_bs_tag, paddr, psize, 0, &vaddr);
+ if (err != 0) {
+ rman_deactivate_resource(r);
+ return (err);
+ }
+ rman_set_bustag(r, fdtbus_bs_tag);
+#else
+ vaddr = (bus_space_handle_t)pmap_mapdev((vm_offset_t)paddr,
+ (vm_size_t)psize);
+ if (vaddr == 0) {
+ rman_deactivate_resource(r);
+ return (ENOMEM);
+ }
+ rman_set_bustag(r, (void *)1);
+#endif
+ rman_set_virtual(r, (void *)vaddr);
+ rman_set_bushandle(r, vaddr);
+ }
+ return (0);
+}
+
+static int
+nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ bus_size_t psize;
+ bus_space_handle_t vaddr;
+
+ psize = (bus_size_t)rman_get_size(r);
+ vaddr = rman_get_bushandle(r);
+
+ if (vaddr != 0) {
+#ifdef FDT
+ bus_space_unmap(fdtbus_bs_tag, vaddr, psize);
+#else
+ pmap_unmapdev((vm_offset_t)vaddr, (vm_size_t)psize);
+#endif
+ rman_set_virtual(r, NULL);
+ rman_set_bushandle(r, 0);
+ }
+
+ return (rman_deactivate_resource(r));
+}
+
+#ifdef FDT
+static int
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+ pcell_t *intr)
+{
+ fdt_pic_decode_t intr_decode;
+ phandle_t intr_parent;
+ int i, rv, interrupt, trig, pol;
+
+ intr_parent = OF_node_from_xref(iparent);
+ for (i = 0; i < icells; i++)
+ intr[i] = cpu_to_fdt32(intr[i]);
+
+ for (i = 0; fdt_pic_table[i] != NULL; i++) {
+ intr_decode = fdt_pic_table[i];
+ rv = intr_decode(intr_parent, intr, &interrupt, &trig, &pol);
+
+ if (rv == 0) {
+ /* This was recognized as our PIC and decoded. */
+ interrupt = FDT_MAP_IRQ(intr_parent, interrupt);
+ return (interrupt);
+ }
+ }
+
+ /* Not in table, so guess */
+ interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0]));
+
+ return (interrupt);
+}
+#endif
+
Property changes on: trunk/sys/arm/arm/nexus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/physmem.c
===================================================================
--- trunk/sys/arm/arm/physmem.c (rev 0)
+++ trunk/sys/arm/arm/physmem.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,364 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
+ * All rights excluded.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/physmem.c 294685 2016-01-24 22:00:36Z ian $");
+
+#include "opt_ddb.h"
+
+/*
+ * Routines for describing and initializing anything related to physical memory.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <machine/md_var.h>
+#include <machine/physmem.h>
+
+/*
+ * These structures are used internally to keep track of regions of physical
+ * ram, and regions within the physical ram that need to be excluded. An
+ * exclusion region can be excluded from crash dumps, from the vm pool of pages
+ * that can be allocated, or both, depending on the exclusion flags associated
+ * with the region.
+ */
+#define MAX_HWCNT 10
+#define MAX_EXCNT 10
+
+struct region {
+ vm_paddr_t addr;
+ vm_size_t size;
+ uint32_t flags;
+};
+
+static struct region hwregions[MAX_HWCNT];
+static struct region exregions[MAX_EXCNT];
+
+static size_t hwcnt;
+static size_t excnt;
+
+/*
+ * These "avail lists" are globals used to communicate physical memory layout to
+ * other parts of the kernel. Within the arrays, each value is the starting
+ * address of a contiguous area of physical address space. The values at even
+ * indexes are areas that contain usable memory and the values at odd indexes
+ * are areas that aren't usable. Each list is terminated by a pair of zero
+ * entries.
+ *
+ * dump_avail tells the dump code what regions to include in a crash dump, and
+ * phys_avail is the way we hand all the remaining physical ram we haven't used
+ * in early kernel init over to the vm system for allocation management.
+ *
+ * We size these arrays to hold twice as many available regions as we allow for
+ * hardware memory regions, to allow for the fact that exclusions can split a
+ * hardware region into two or more available regions. In the real world there
+ * will typically be one or two hardware regions and two or three exclusions.
+ *
+ * Each available region in this list occupies two array slots (the start of the
+ * available region and the start of the unavailable region that follows it).
+ */
+#define MAX_AVAIL_REGIONS (MAX_HWCNT * 2)
+#define MAX_AVAIL_ENTRIES (MAX_AVAIL_REGIONS * 2)
+
+vm_paddr_t phys_avail[MAX_AVAIL_ENTRIES + 2]; /* +2 to allow for a pair */
+vm_paddr_t dump_avail[MAX_AVAIL_ENTRIES + 2]; /* of zeroes to terminate. */
+
+/*
+ * realmem is the total number of hardware pages, excluded or not.
+ * Maxmem is one greater than the last physical page number.
+ */
+long realmem;
+long Maxmem;
+
+/* The address at which the kernel was loaded. Set early in initarm(). */
+vm_paddr_t arm_physmem_kernaddr;
+
+/*
+ * Print the contents of the physical and excluded region tables using the
+ * provided printf-like output function (which will be either printf or
+ * db_printf).
+ */
+static void
+physmem_dump_tables(int (*prfunc)(const char *, ...))
+{
+ int flags, i;
+ uintmax_t addr, size;
+ const unsigned int mbyte = 1024 * 1024;
+
+ prfunc("Physical memory chunk(s):\n");
+ for (i = 0; i < hwcnt; ++i) {
+ addr = hwregions[i].addr;
+ size = hwregions[i].size;
+ prfunc(" 0x%08jx - 0x%08jx, %5ju MB (%7ju pages)\n", addr,
+ addr + size - 1, size / mbyte, size / PAGE_SIZE);
+ }
+
+ prfunc("Excluded memory regions:\n");
+ for (i = 0; i < excnt; ++i) {
+ addr = exregions[i].addr;
+ size = exregions[i].size;
+ flags = exregions[i].flags;
+ prfunc(" 0x%08jx - 0x%08jx, %5ju MB (%7ju pages) %s %s\n",
+ addr, addr + size - 1, size / mbyte, size / PAGE_SIZE,
+ (flags & EXFLAG_NOALLOC) ? "NoAlloc" : "",
+ (flags & EXFLAG_NODUMP) ? "NoDump" : "");
+ }
+
+#ifdef DEBUG
+ prfunc("Avail lists:\n");
+ for (i = 0; phys_avail[i] != 0; ++i) {
+ prfunc(" phys_avail[%d] 0x%08x\n", i, phys_avail[i]);
+ }
+ for (i = 0; dump_avail[i] != 0; ++i) {
+ prfunc(" dump_avail[%d] 0x%08x\n", i, dump_avail[i]);
+ }
+#endif
+}
+
+/*
+ * Print the contents of the static mapping table. Used for bootverbose.
+ */
+void
+arm_physmem_print_tables()
+{
+
+ physmem_dump_tables(printf);
+}
+
+/*
+ * Walk the list of hardware regions, processing it against the list of
+ * exclusions that contain the given exflags, and generating an "avail list".
+ *
+ * Updates the value at *pavail with the sum of all pages in all hw regions.
+ *
+ * Returns the number of pages of non-excluded memory added to the avail list.
+ */
+static size_t
+regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail)
+{
+ size_t acnt, exi, hwi;
+ uint64_t end, start, xend, xstart;
+ long availmem;
+ const struct region *exp, *hwp;
+
+ realmem = 0;
+ availmem = 0;
+ acnt = 0;
+ for (hwi = 0, hwp = hwregions; hwi < hwcnt; ++hwi, ++hwp) {
+ start = hwp->addr;
+ end = hwp->size + start;
+ realmem += arm32_btop((vm_offset_t)(end - start));
+ for (exi = 0, exp = exregions; exi < excnt; ++exi, ++exp) {
+ /*
+ * If the excluded region does not match given flags,
+ * continue checking with the next excluded region.
+ */
+ if ((exp->flags & exflags) == 0)
+ continue;
+ xstart = exp->addr;
+ xend = exp->size + xstart;
+ /*
+ * If the excluded region ends before this hw region,
+ * continue checking with the next excluded region.
+ */
+ if (xend <= start)
+ continue;
+ /*
+ * If the excluded region begins after this hw region
+ * we're done because both lists are sorted.
+ */
+ if (xstart >= end)
+ break;
+ /*
+ * If the excluded region completely covers this hw
+ * region, shrink this hw region to zero size.
+ */
+ if ((start >= xstart) && (end <= xend)) {
+ start = xend;
+ end = xend;
+ break;
+ }
+ /*
+ * If the excluded region falls wholly within this hw
+ * region without abutting or overlapping the beginning
+ * or end, create an available entry from the leading
+ * fragment, then adjust the start of this hw region to
+ * the end of the excluded region, and continue checking
+ * the next excluded region because another exclusion
+ * could affect the remainder of this hw region.
+ */
+ if ((xstart > start) && (xend < end)) {
+ avail[acnt++] = (vm_paddr_t)start;
+ avail[acnt++] = (vm_paddr_t)xstart;
+ availmem +=
+ arm32_btop((vm_offset_t)(xstart - start));
+ start = xend;
+ continue;
+ }
+ /*
+ * We know the excluded region overlaps either the start
+ * or end of this hardware region (but not both), trim
+ * the excluded portion off the appropriate end.
+ */
+ if (xstart <= start)
+ start = xend;
+ else
+ end = xstart;
+ }
+ /*
+ * If the trimming actions above left a non-zero size, create an
+ * available entry for it.
+ */
+ if (end > start) {
+ avail[acnt++] = (vm_paddr_t)start;
+ avail[acnt++] = (vm_paddr_t)end;
+ availmem += arm32_btop((vm_offset_t)(end - start));
+ }
+ if (acnt >= MAX_AVAIL_ENTRIES)
+ panic("Not enough space in the dump/phys_avail arrays");
+ }
+
+ if (pavail)
+ *pavail = availmem;
+ return (acnt);
+}
+
+/*
+ * Insertion-sort a new entry into a regions list; sorted by start address.
+ */
+static void
+insert_region(struct region *regions, size_t rcnt, vm_paddr_t addr,
+ vm_size_t size, uint32_t flags)
+{
+ size_t i;
+ struct region *ep, *rp;
+
+ ep = regions + rcnt;
+ for (i = 0, rp = regions; i < rcnt; ++i, ++rp) {
+ if (addr < rp->addr) {
+ bcopy(rp, rp + 1, (ep - rp) * sizeof(*rp));
+ break;
+ }
+ }
+ rp->addr = addr;
+ rp->size = size;
+ rp->flags = flags;
+}
+
+/*
+ * Add a hardware memory region.
+ */
+void
+arm_physmem_hardware_region(vm_paddr_t pa, vm_size_t sz)
+{
+ vm_offset_t adj;
+
+ /*
+ * Filter out the page at PA 0x00000000. The VM can't handle it, as
+ * pmap_extract() == 0 means failure.
+ *
+ * Also filter out the page at the end of the physical address space --
+ * if addr is non-zero and addr+size is zero we wrapped to the next byte
+ * beyond what vm_paddr_t can express. That leads to a NULL pointer
+ * deref early in startup; work around it by leaving the last page out.
+ *
+ * XXX This just in: subtract out a whole megabyte, not just 1 page.
+ * Reducing the size by anything less than 1MB results in the NULL
+ * pointer deref in _vm_map_lock_read(). Better to give up a megabyte
+ * than leave some folks with an unusable system while we investigate.
+ */
+ if (pa == 0) {
+ pa = PAGE_SIZE;
+ sz -= PAGE_SIZE;
+ } else if (pa + sz == 0) {
+ sz -= 1024 * 1024;
+ }
+
+ /*
+ * Round the starting address up to a page boundary, and truncate the
+ * ending page down to a page boundary.
+ */
+ adj = round_page(pa) - pa;
+ pa = round_page(pa);
+ sz = trunc_page(sz - adj);
+
+ if (hwcnt < nitems(hwregions))
+ insert_region(hwregions, hwcnt++, pa, sz, 0);
+}
+
+/*
+ * Add an exclusion region.
+ */
+void arm_physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t exflags)
+{
+ vm_offset_t adj;
+
+ /*
+ * Truncate the starting address down to a page boundary, and round the
+ * ending page up to a page boundary.
+ */
+ adj = pa - trunc_page(pa);
+ pa = trunc_page(pa);
+ sz = round_page(sz + adj);
+
+ if (excnt < nitems(exregions))
+ insert_region(exregions, excnt++, pa, sz, exflags);
+}
+
+/*
+ * Process all the regions added earlier into the global avail lists.
+ *
+ * Updates the kernel global 'physmem' with the number of physical pages
+ * available for use (all pages not in any exclusion region).
+ *
+ * Updates the kernel global 'Maxmem' with the page number one greater then the
+ * last page of physical memory in the system.
+ */
+void
+arm_physmem_init_kernel_globals(void)
+{
+ size_t nextidx;
+
+ regions_to_avail(dump_avail, EXFLAG_NODUMP, NULL);
+ nextidx = regions_to_avail(phys_avail, EXFLAG_NOALLOC, &physmem);
+ if (nextidx == 0)
+ panic("No memory entries in phys_avail");
+ Maxmem = atop(phys_avail[nextidx - 1]);
+}
+
+#ifdef DDB
+#include <ddb/ddb.h>
+
+DB_SHOW_COMMAND(physmem, db_show_physmem)
+{
+
+ physmem_dump_tables(db_printf);
+}
+
+#endif /* DDB */
+
Property changes on: trunk/sys/arm/arm/physmem.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/pl190.c
===================================================================
--- trunk/sys/arm/arm/pl190.c (rev 0)
+++ trunk/sys/arm/arm/pl190.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,193 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at bluezbox.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/pl190.c 270075 2014-08-17 01:28:03Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#ifdef DEBUG
+#define dprintf(fmt, args...) printf(fmt, ##args)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+#define VICIRQSTATUS 0x000
+#define VICFIQSTATUS 0x004
+#define VICRAWINTR 0x008
+#define VICINTSELECT 0x00C
+#define VICINTENABLE 0x010
+#define VICINTENCLEAR 0x014
+#define VICSOFTINT 0x018
+#define VICSOFTINTCLEAR 0x01C
+#define VICPROTECTION 0x020
+#define VICPERIPHID 0xFE0
+#define VICPRIMECELLID 0xFF0
+
+#define VIC_NIRQS 32
+
+struct pl190_intc_softc {
+ device_t sc_dev;
+ struct resource * intc_res;
+};
+
+static struct pl190_intc_softc *pl190_intc_sc = NULL;
+
+#define intc_vic_read_4(reg) \
+ bus_read_4(pl190_intc_sc->intc_res, (reg))
+#define intc_vic_write_4(reg, val) \
+ bus_write_4(pl190_intc_sc->intc_res, (reg), (val))
+
+static int
+pl190_intc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "arm,versatile-vic"))
+ return (ENXIO);
+ device_set_desc(dev, "ARM PL190 VIC");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+pl190_intc_attach(device_t dev)
+{
+ struct pl190_intc_softc *sc = device_get_softc(dev);
+ uint32_t id;
+ int i, rid;
+
+ sc->sc_dev = dev;
+
+ if (pl190_intc_sc)
+ return (ENXIO);
+
+ /* Request memory resources */
+ rid = 0;
+ sc->intc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->intc_res == NULL) {
+ device_printf(dev, "Error: could not allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ pl190_intc_sc = sc;
+ /*
+ * All interrupts should use IRQ line
+ */
+ intc_vic_write_4(VICINTSELECT, 0x00000000);
+ /* Disable all interrupts */
+ intc_vic_write_4(VICINTENCLEAR, 0xffffffff);
+ /* Enable INT31, SIC IRQ */
+ intc_vic_write_4(VICINTENABLE, (1U << 31));
+
+ id = 0;
+ for (i = 3; i >= 0; i--) {
+ id = (id << 8) |
+ (intc_vic_read_4(VICPERIPHID + i*4) & 0xff);
+ }
+
+ device_printf(dev, "Peripheral ID: %08x\n", id);
+
+ id = 0;
+ for (i = 3; i >= 0; i--) {
+ id = (id << 8) |
+ (intc_vic_read_4(VICPRIMECELLID + i*4) & 0xff);
+ }
+
+ device_printf(dev, "PrimeCell ID: %08x\n", id);
+
+ return (0);
+}
+
+static device_method_t pl190_intc_methods[] = {
+ DEVMETHOD(device_probe, pl190_intc_probe),
+ DEVMETHOD(device_attach, pl190_intc_attach),
+ { 0, 0 }
+};
+
+static driver_t pl190_intc_driver = {
+ "intc",
+ pl190_intc_methods,
+ sizeof(struct pl190_intc_softc),
+};
+
+static devclass_t pl190_intc_devclass;
+
+EARLY_DRIVER_MODULE(intc, simplebus, pl190_intc_driver, pl190_intc_devclass,
+ 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+
+int
+arm_get_next_irq(int last_irq)
+{
+ uint32_t pending;
+ int32_t irq = last_irq + 1;
+
+ /* Sanity check */
+ if (irq < 0)
+ irq = 0;
+
+ pending = intc_vic_read_4(VICIRQSTATUS);
+ while (irq < VIC_NIRQS) {
+ if (pending & (1 << irq))
+ return (irq);
+ irq++;
+ }
+
+ return (-1);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+
+ dprintf("%s: %d\n", __func__, nb);
+ intc_vic_write_4(VICINTENCLEAR, (1 << nb));
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+
+ dprintf("%s: %d\n", __func__, nb);
+ intc_vic_write_4(VICINTENABLE, (1 << nb));
+}
Property changes on: trunk/sys/arm/arm/pl190.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/pl310.c
===================================================================
--- trunk/sys/arm/arm/pl310.c (rev 0)
+++ trunk/sys/arm/arm/pl310.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,545 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard <cognet at FreeBSD.org>
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/pl310.c 273695 2014-10-26 16:09:59Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <machine/intr.h>
+
+#include <machine/bus.h>
+#include <machine/pl310.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * Define this if you need to disable PL310 for debugging purpose
+ * Spec:
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0246e/DDI0246E_l2c310_r3p1_trm.pdf
+ */
+
+/*
+ * Hardcode errata for now
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0246b/pr01s02s02.html
+ */
+#define PL310_ERRATA_588369
+#define PL310_ERRATA_753970
+#define PL310_ERRATA_727915
+
+#define PL310_LOCK(sc) do { \
+ mtx_lock_spin(&(sc)->sc_mtx); \
+} while(0);
+
+#define PL310_UNLOCK(sc) do { \
+ mtx_unlock_spin(&(sc)->sc_mtx); \
+} while(0);
+
+static int pl310_enabled = 1;
+TUNABLE_INT("hw.pl310.enabled", &pl310_enabled);
+
+static uint32_t g_l2cache_way_mask;
+
+static const uint32_t g_l2cache_line_size = 32;
+static const uint32_t g_l2cache_align_mask = (32 - 1);
+
+static uint32_t g_l2cache_size;
+static uint32_t g_way_size;
+static uint32_t g_ways_assoc;
+
+static struct pl310_softc *pl310_softc;
+
+static struct ofw_compat_data compat_data[] = {
+ {"arm,pl310", true}, /* Non-standard, FreeBSD. */
+ {"arm,pl310-cache", true},
+ {NULL, false}
+};
+
+void
+pl310_print_config(struct pl310_softc *sc)
+{
+ uint32_t aux, prefetch;
+ const char *dis = "disabled";
+ const char *ena = "enabled";
+
+ aux = pl310_read4(sc, PL310_AUX_CTRL);
+ prefetch = pl310_read4(sc, PL310_PREFETCH_CTRL);
+
+ device_printf(sc->sc_dev, "Early BRESP response: %s\n",
+ (aux & AUX_CTRL_EARLY_BRESP) ? ena : dis);
+ device_printf(sc->sc_dev, "Instruction prefetch: %s\n",
+ (aux & AUX_CTRL_INSTR_PREFETCH) ? ena : dis);
+ device_printf(sc->sc_dev, "Data prefetch: %s\n",
+ (aux & AUX_CTRL_DATA_PREFETCH) ? ena : dis);
+ device_printf(sc->sc_dev, "Non-secure interrupt control: %s\n",
+ (aux & AUX_CTRL_NS_INT_CTRL) ? ena : dis);
+ device_printf(sc->sc_dev, "Non-secure lockdown: %s\n",
+ (aux & AUX_CTRL_NS_LOCKDOWN) ? ena : dis);
+ device_printf(sc->sc_dev, "Share override: %s\n",
+ (aux & AUX_CTRL_SHARE_OVERRIDE) ? ena : dis);
+
+ device_printf(sc->sc_dev, "Double linefill: %s\n",
+ (prefetch & PREFETCH_CTRL_DL) ? ena : dis);
+ device_printf(sc->sc_dev, "Instruction prefetch: %s\n",
+ (prefetch & PREFETCH_CTRL_INSTR_PREFETCH) ? ena : dis);
+ device_printf(sc->sc_dev, "Data prefetch: %s\n",
+ (prefetch & PREFETCH_CTRL_DATA_PREFETCH) ? ena : dis);
+ device_printf(sc->sc_dev, "Double linefill on WRAP request: %s\n",
+ (prefetch & PREFETCH_CTRL_DL_ON_WRAP) ? ena : dis);
+ device_printf(sc->sc_dev, "Prefetch drop: %s\n",
+ (prefetch & PREFETCH_CTRL_PREFETCH_DROP) ? ena : dis);
+ device_printf(sc->sc_dev, "Incr double Linefill: %s\n",
+ (prefetch & PREFETCH_CTRL_INCR_DL) ? ena : dis);
+ device_printf(sc->sc_dev, "Not same ID on exclusive sequence: %s\n",
+ (prefetch & PREFETCH_CTRL_NOTSAMEID) ? ena : dis);
+ device_printf(sc->sc_dev, "Prefetch offset: %d\n",
+ (prefetch & PREFETCH_CTRL_OFFSET_MASK));
+}
+
+void
+pl310_set_ram_latency(struct pl310_softc *sc, uint32_t which_reg,
+ uint32_t read, uint32_t write, uint32_t setup)
+{
+ uint32_t v;
+
+ KASSERT(which_reg == PL310_TAG_RAM_CTRL ||
+ which_reg == PL310_DATA_RAM_CTRL,
+ ("bad pl310 ram latency register address"));
+
+ v = pl310_read4(sc, which_reg);
+ if (setup != 0) {
+ KASSERT(setup <= 8, ("bad pl310 setup latency: %d", setup));
+ v &= ~RAM_CTRL_SETUP_MASK;
+ v |= (setup - 1) << RAM_CTRL_SETUP_SHIFT;
+ }
+ if (read != 0) {
+ KASSERT(read <= 8, ("bad pl310 read latency: %d", read));
+ v &= ~RAM_CTRL_READ_MASK;
+ v |= (read - 1) << RAM_CTRL_READ_SHIFT;
+ }
+ if (write != 0) {
+ KASSERT(write <= 8, ("bad pl310 write latency: %d", write));
+ v &= ~RAM_CTRL_WRITE_MASK;
+ v |= (write - 1) << RAM_CTRL_WRITE_SHIFT;
+ }
+ pl310_write4(sc, which_reg, v);
+}
+
+static int
+pl310_filter(void *arg)
+{
+ struct pl310_softc *sc = arg;
+ uint32_t intr;
+
+ intr = pl310_read4(sc, PL310_INTR_MASK);
+
+ if (!sc->sc_enabled && (intr & INTR_MASK_ECNTR)) {
+ /*
+ * This is for debug purpose, so be blunt about it
+ * We disable PL310 only when something fishy is going
+ * on and we need to make sure L2 cache is 100% disabled
+ */
+ panic("pl310: caches disabled but cache event detected\n");
+ }
+
+ return (FILTER_HANDLED);
+}
+
+static __inline void
+pl310_wait_background_op(uint32_t off, uint32_t mask)
+{
+
+ while (pl310_read4(pl310_softc, off) & mask)
+ continue;
+}
+
+
+/**
+ * pl310_cache_sync - performs a cache sync operation
+ *
+ * According to the TRM:
+ *
+ * "Before writing to any other register you must perform an explicit
+ * Cache Sync operation. This is particularly important when the cache is
+ * enabled and changes to how the cache allocates new lines are to be made."
+ *
+ *
+ */
+static __inline void
+pl310_cache_sync(void)
+{
+
+ if ((pl310_softc == NULL) || !pl310_softc->sc_enabled)
+ return;
+
+#ifdef PL310_ERRATA_753970
+ if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
+ /* Write uncached PL310 register */
+ pl310_write4(pl310_softc, 0x740, 0xffffffff);
+ else
+#endif
+ pl310_write4(pl310_softc, PL310_CACHE_SYNC, 0xffffffff);
+}
+
+
+static void
+pl310_wbinv_all(void)
+{
+
+ if ((pl310_softc == NULL) || !pl310_softc->sc_enabled)
+ return;
+
+ PL310_LOCK(pl310_softc);
+#ifdef PL310_ERRATA_727915
+ if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r2p0) {
+ int i, j;
+
+ for (i = 0; i < g_ways_assoc; i++) {
+ for (j = 0; j < g_way_size / g_l2cache_line_size; j++) {
+ pl310_write4(pl310_softc,
+ PL310_CLEAN_INV_LINE_IDX,
+ (i << 28 | j << 5));
+ }
+ }
+ pl310_cache_sync();
+ PL310_UNLOCK(pl310_softc);
+ return;
+
+ }
+ if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
+ platform_pl310_write_debug(pl310_softc, 3);
+#endif
+ pl310_write4(pl310_softc, PL310_CLEAN_INV_WAY, g_l2cache_way_mask);
+ pl310_wait_background_op(PL310_CLEAN_INV_WAY, g_l2cache_way_mask);
+ pl310_cache_sync();
+#ifdef PL310_ERRATA_727915
+ if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
+ platform_pl310_write_debug(pl310_softc, 0);
+#endif
+ PL310_UNLOCK(pl310_softc);
+}
+
+static void
+pl310_wbinv_range(vm_paddr_t start, vm_size_t size)
+{
+
+ if ((pl310_softc == NULL) || !pl310_softc->sc_enabled)
+ return;
+
+ PL310_LOCK(pl310_softc);
+ if (start & g_l2cache_align_mask) {
+ size += start & g_l2cache_align_mask;
+ start &= ~g_l2cache_align_mask;
+ }
+ if (size & g_l2cache_align_mask) {
+ size &= ~g_l2cache_align_mask;
+ size += g_l2cache_line_size;
+ }
+
+
+#ifdef PL310_ERRATA_727915
+ platform_pl310_write_debug(pl310_softc, 3);
+#endif
+ while (size > 0) {
+#ifdef PL310_ERRATA_588369
+ if (pl310_softc->sc_rtl_revision <= CACHE_ID_RELEASE_r1p0) {
+ /*
+ * Errata 588369 says that clean + inv may keep the
+ * cache line if it was clean, the recommanded
+ * workaround is to clean then invalidate the cache
+ * line, with write-back and cache linefill disabled.
+ */
+ pl310_write4(pl310_softc, PL310_CLEAN_LINE_PA, start);
+ pl310_write4(pl310_softc, PL310_INV_LINE_PA, start);
+ } else
+#endif
+ pl310_write4(pl310_softc, PL310_CLEAN_INV_LINE_PA,
+ start);
+ start += g_l2cache_line_size;
+ size -= g_l2cache_line_size;
+ }
+#ifdef PL310_ERRATA_727915
+ platform_pl310_write_debug(pl310_softc, 0);
+#endif
+
+ pl310_cache_sync();
+ PL310_UNLOCK(pl310_softc);
+}
+
+static void
+pl310_wb_range(vm_paddr_t start, vm_size_t size)
+{
+
+ if ((pl310_softc == NULL) || !pl310_softc->sc_enabled)
+ return;
+
+ PL310_LOCK(pl310_softc);
+ if (start & g_l2cache_align_mask) {
+ size += start & g_l2cache_align_mask;
+ start &= ~g_l2cache_align_mask;
+ }
+
+ if (size & g_l2cache_align_mask) {
+ size &= ~g_l2cache_align_mask;
+ size += g_l2cache_line_size;
+ }
+
+ while (size > 0) {
+ pl310_write4(pl310_softc, PL310_CLEAN_LINE_PA, start);
+ start += g_l2cache_line_size;
+ size -= g_l2cache_line_size;
+ }
+
+ pl310_cache_sync();
+ PL310_UNLOCK(pl310_softc);
+}
+
+static void
+pl310_inv_range(vm_paddr_t start, vm_size_t size)
+{
+
+ if ((pl310_softc == NULL) || !pl310_softc->sc_enabled)
+ return;
+
+ PL310_LOCK(pl310_softc);
+ if (start & g_l2cache_align_mask) {
+ size += start & g_l2cache_align_mask;
+ start &= ~g_l2cache_align_mask;
+ }
+ if (size & g_l2cache_align_mask) {
+ size &= ~g_l2cache_align_mask;
+ size += g_l2cache_line_size;
+ }
+ while (size > 0) {
+ pl310_write4(pl310_softc, PL310_INV_LINE_PA, start);
+ start += g_l2cache_line_size;
+ size -= g_l2cache_line_size;
+ }
+
+ pl310_cache_sync();
+ PL310_UNLOCK(pl310_softc);
+}
+
+static void
+pl310_drain_writebuf(void)
+{
+
+ if ((pl310_softc == NULL) || !pl310_softc->sc_enabled)
+ return;
+
+ PL310_LOCK(pl310_softc);
+ pl310_cache_sync();
+ PL310_UNLOCK(pl310_softc);
+}
+
+static void
+pl310_set_way_sizes(struct pl310_softc *sc)
+{
+ uint32_t aux_value;
+
+ aux_value = pl310_read4(sc, PL310_AUX_CTRL);
+ g_way_size = (aux_value & AUX_CTRL_WAY_SIZE_MASK) >>
+ AUX_CTRL_WAY_SIZE_SHIFT;
+ g_way_size = 1 << (g_way_size + 13);
+ if (aux_value & (1 << AUX_CTRL_ASSOCIATIVITY_SHIFT))
+ g_ways_assoc = 16;
+ else
+ g_ways_assoc = 8;
+ g_l2cache_way_mask = (1 << g_ways_assoc) - 1;
+ g_l2cache_size = g_way_size * g_ways_assoc;
+}
+
+/*
+ * Setup interrupt handling. This is done only if the cache controller is
+ * disabled, for debugging. We set counters so when a cache event happens we'll
+ * get interrupted and be warned that something is wrong, because no cache
+ * events should happen if we're disabled.
+ */
+static void
+pl310_config_intr(void *arg)
+{
+ struct pl310_softc * sc;
+
+ sc = arg;
+
+ /* activate the interrupt */
+ bus_setup_intr(sc->sc_dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ pl310_filter, NULL, sc, &sc->sc_irq_h);
+
+ /* Cache Line Eviction for Counter 0 */
+ pl310_write4(sc, PL310_EVENT_COUNTER0_CONF,
+ EVENT_COUNTER_CONF_INCR | EVENT_COUNTER_CONF_CO);
+ /* Data Read Request for Counter 1 */
+ pl310_write4(sc, PL310_EVENT_COUNTER1_CONF,
+ EVENT_COUNTER_CONF_INCR | EVENT_COUNTER_CONF_DRREQ);
+
+ /* Enable and clear pending interrupts */
+ pl310_write4(sc, PL310_INTR_CLEAR, INTR_MASK_ECNTR);
+ pl310_write4(sc, PL310_INTR_MASK, INTR_MASK_ALL);
+
+ /* Enable counters and reset C0 and C1 */
+ pl310_write4(sc, PL310_EVENT_COUNTER_CTRL,
+ EVENT_COUNTER_CTRL_ENABLED |
+ EVENT_COUNTER_CTRL_C0_RESET |
+ EVENT_COUNTER_CTRL_C1_RESET);
+
+ config_intrhook_disestablish(sc->sc_ich);
+ free(sc->sc_ich, M_DEVBUF);
+}
+
+static int
+pl310_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+ device_set_desc(dev, "PL310 L2 cache controller");
+ return (0);
+}
+
+static int
+pl310_attach(device_t dev)
+{
+ struct pl310_softc *sc = device_get_softc(dev);
+ int rid;
+ uint32_t cache_id, debug_ctrl;
+
+ sc->sc_dev = dev;
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL)
+ panic("%s: Cannot map registers", device_get_name(dev));
+
+ /* Allocate an IRQ resource */
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->sc_irq_res == NULL) {
+ panic("Cannot allocate IRQ\n");
+ }
+
+ pl310_softc = sc;
+ mtx_init(&sc->sc_mtx, "pl310lock", NULL, MTX_SPIN);
+
+ cache_id = pl310_read4(sc, PL310_CACHE_ID);
+ sc->sc_rtl_revision = (cache_id >> CACHE_ID_RELEASE_SHIFT) &
+ CACHE_ID_RELEASE_MASK;
+ device_printf(dev, "Part number: 0x%x, release: 0x%x\n",
+ (cache_id >> CACHE_ID_PARTNUM_SHIFT) & CACHE_ID_PARTNUM_MASK,
+ (cache_id >> CACHE_ID_RELEASE_SHIFT) & CACHE_ID_RELEASE_MASK);
+
+ /*
+ * If L2 cache is already enabled then something has violated the rules,
+ * because caches are supposed to be off at kernel entry. The cache
+ * must be disabled to write the configuration registers without
+ * triggering an access error (SLVERR), but there's no documented safe
+ * procedure for disabling the L2 cache in the manual. So we'll try to
+ * invent one:
+ * - Use the debug register to force write-through mode and prevent
+ * linefills (allocation of new lines on read); now anything we do
+ * will not cause new data to come into the L2 cache.
+ * - Writeback and invalidate the current contents.
+ * - Disable the controller.
+ * - Restore the original debug settings.
+ */
+ if (pl310_read4(sc, PL310_CTRL) & CTRL_ENABLED) {
+ device_printf(dev, "Warning: L2 Cache should not already be "
+ "active; trying to de-activate and re-initialize...\n");
+ sc->sc_enabled = 1;
+ debug_ctrl = pl310_read4(sc, PL310_DEBUG_CTRL);
+ platform_pl310_write_debug(sc, debug_ctrl |
+ DEBUG_CTRL_DISABLE_WRITEBACK | DEBUG_CTRL_DISABLE_LINEFILL);
+ pl310_set_way_sizes(sc);
+ pl310_wbinv_all();
+ platform_pl310_write_ctrl(sc, CTRL_DISABLED);
+ platform_pl310_write_debug(sc, debug_ctrl);
+ }
+ sc->sc_enabled = pl310_enabled;
+
+ if (sc->sc_enabled) {
+ platform_pl310_init(sc);
+ pl310_set_way_sizes(sc); /* platform init might change these */
+ pl310_write4(pl310_softc, PL310_INV_WAY, 0xffff);
+ pl310_wait_background_op(PL310_INV_WAY, 0xffff);
+ platform_pl310_write_ctrl(sc, CTRL_ENABLED);
+ device_printf(dev, "L2 Cache enabled: %uKB/%dB %d ways\n",
+ (g_l2cache_size / 1024), g_l2cache_line_size, g_ways_assoc);
+ if (bootverbose)
+ pl310_print_config(sc);
+ } else {
+ malloc(sizeof(*sc->sc_ich), M_DEVBUF, M_WAITOK);
+ sc->sc_ich->ich_func = pl310_config_intr;
+ sc->sc_ich->ich_arg = sc;
+ if (config_intrhook_establish(sc->sc_ich) != 0) {
+ device_printf(dev,
+ "config_intrhook_establish failed\n");
+ return(ENXIO);
+ }
+ device_printf(dev, "L2 Cache disabled\n");
+ }
+
+ /* Set the l2 functions in the set of cpufuncs */
+ cpufuncs.cf_l2cache_wbinv_all = pl310_wbinv_all;
+ cpufuncs.cf_l2cache_wbinv_range = pl310_wbinv_range;
+ cpufuncs.cf_l2cache_inv_range = pl310_inv_range;
+ cpufuncs.cf_l2cache_wb_range = pl310_wb_range;
+ cpufuncs.cf_l2cache_drain_writebuf = pl310_drain_writebuf;
+
+ return (0);
+}
+
+static device_method_t pl310_methods[] = {
+ DEVMETHOD(device_probe, pl310_probe),
+ DEVMETHOD(device_attach, pl310_attach),
+ DEVMETHOD_END
+};
+
+static driver_t pl310_driver = {
+ "l2cache",
+ pl310_methods,
+ sizeof(struct pl310_softc),
+};
+static devclass_t pl310_devclass;
+
+EARLY_DRIVER_MODULE(pl310, simplebus, pl310_driver, pl310_devclass, 0, 0,
+ BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE);
+
Property changes on: trunk/sys/arm/arm/pl310.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/pmap-v6.c
===================================================================
--- trunk/sys/arm/arm/pmap-v6.c (rev 0)
+++ trunk/sys/arm/arm/pmap-v6.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5342 @@
+/* $MidnightBSD$ */
+/* From: $NetBSD: pmap.c,v 1.148 2004/04/03 04:35:48 bsh Exp $ */
+/*-
+ * Copyright 2011 Semihalf
+ * Copyright 2004 Olivier Houchard.
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * From: FreeBSD: src/sys/arm/arm/pmap.c,v 1.113 2009/07/24 13:50:29
+ */
+
+/*-
+ * Copyright (c) 2002-2003 Wasabi Systems, Inc.
+ * Copyright (c) 2001 Richard Earnshaw
+ * Copyright (c) 2001-2002 Christopher Gilbert
+ * All rights reserved.
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *
+ * RiscBSD kernel project
+ *
+ * pmap.c
+ *
+ * Machine dependant vm stuff
+ *
+ * Created : 20/09/94
+ */
+
+/*
+ * Special compilation symbols
+ * PMAP_DEBUG - Build in pmap_debug_level code
+ *
+ * Note that pmap_mapdev() and pmap_unmapdev() are implemented in arm/devmap.c
+*/
+/* Include header files */
+
+#include "opt_vm.h"
+#include "opt_pmap.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/pmap-v6.c 278614 2015-02-12 04:15:55Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/vmmeter.h>
+#include <sys/mman.h>
+#include <sys/rwlock.h>
+#include <sys/smp.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/uma.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_object.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_phys.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_reserv.h>
+
+#include <machine/md_var.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/pcb.h>
+
+#ifdef DEBUG
+extern int last_fault_code;
+#endif
+
+#ifdef PMAP_DEBUG
+#define PDEBUG(_lev_,_stat_) \
+ if (pmap_debug_level >= (_lev_)) \
+ ((_stat_))
+#define dprintf printf
+
+int pmap_debug_level = 0;
+#define PMAP_INLINE
+#else /* PMAP_DEBUG */
+#define PDEBUG(_lev_,_stat_) /* Nothing */
+#define dprintf(x, arg...)
+#define PMAP_INLINE __inline
+#endif /* PMAP_DEBUG */
+
+#ifdef PV_STATS
+#define PV_STAT(x) do { x ; } while (0)
+#else
+#define PV_STAT(x) do { } while (0)
+#endif
+
+#define pa_to_pvh(pa) (&pv_table[pa_index(pa)])
+
+#ifdef ARM_L2_PIPT
+#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((pa), (size))
+#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((pa), (size))
+#else
+#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((va), (size))
+#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((va), (size))
+#endif
+
+extern struct pv_addr systempage;
+
+/*
+ * Internal function prototypes
+ */
+
+static PMAP_INLINE
+struct pv_entry *pmap_find_pv(struct md_page *, pmap_t, vm_offset_t);
+static void pmap_free_pv_chunk(struct pv_chunk *pc);
+static void pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv);
+static pv_entry_t pmap_get_pv_entry(pmap_t pmap, boolean_t try);
+static vm_page_t pmap_pv_reclaim(pmap_t locked_pmap);
+static boolean_t pmap_pv_insert_section(pmap_t, vm_offset_t,
+ vm_paddr_t);
+static struct pv_entry *pmap_remove_pv(struct vm_page *, pmap_t, vm_offset_t);
+static int pmap_pvh_wired_mappings(struct md_page *, int);
+
+static int pmap_enter_locked(pmap_t, vm_offset_t, vm_page_t,
+ vm_prot_t, u_int);
+static vm_paddr_t pmap_extract_locked(pmap_t pmap, vm_offset_t va);
+static void pmap_alloc_l1(pmap_t);
+static void pmap_free_l1(pmap_t);
+
+static void pmap_map_section(pmap_t, vm_offset_t, vm_offset_t,
+ vm_prot_t, boolean_t);
+static void pmap_promote_section(pmap_t, vm_offset_t);
+static boolean_t pmap_demote_section(pmap_t, vm_offset_t);
+static boolean_t pmap_enter_section(pmap_t, vm_offset_t, vm_page_t,
+ vm_prot_t);
+static void pmap_remove_section(pmap_t, vm_offset_t);
+
+static int pmap_clearbit(struct vm_page *, u_int);
+
+static struct l2_bucket *pmap_get_l2_bucket(pmap_t, vm_offset_t);
+static struct l2_bucket *pmap_alloc_l2_bucket(pmap_t, vm_offset_t);
+static void pmap_free_l2_bucket(pmap_t, struct l2_bucket *, u_int);
+static vm_offset_t kernel_pt_lookup(vm_paddr_t);
+
+static MALLOC_DEFINE(M_VMPMAP, "pmap", "PMAP L1");
+
+vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */
+vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
+vm_offset_t pmap_curmaxkvaddr;
+vm_paddr_t kernel_l1pa;
+
+vm_offset_t kernel_vm_end = 0;
+
+vm_offset_t vm_max_kernel_address;
+
+struct pmap kernel_pmap_store;
+
+/*
+ * Resources for quickly copying and zeroing pages using virtual address space
+ * and page table entries that are pre-allocated per-CPU by pmap_init().
+ */
+struct czpages {
+ struct mtx lock;
+ pt_entry_t *srcptep;
+ pt_entry_t *dstptep;
+ vm_offset_t srcva;
+ vm_offset_t dstva;
+};
+static struct czpages cpu_czpages[MAXCPU];
+
+static void pmap_init_l1(struct l1_ttable *, pd_entry_t *);
+/*
+ * These routines are called when the CPU type is identified to set up
+ * the PTE prototypes, cache modes, etc.
+ *
+ * The variables are always here, just in case LKMs need to reference
+ * them (though, they shouldn't).
+ */
+static void pmap_set_prot(pt_entry_t *pte, vm_prot_t prot, uint8_t user);
+pt_entry_t pte_l1_s_cache_mode;
+pt_entry_t pte_l1_s_cache_mode_pt;
+
+pt_entry_t pte_l2_l_cache_mode;
+pt_entry_t pte_l2_l_cache_mode_pt;
+
+pt_entry_t pte_l2_s_cache_mode;
+pt_entry_t pte_l2_s_cache_mode_pt;
+
+struct msgbuf *msgbufp = 0;
+
+/*
+ * Crashdump maps.
+ */
+static caddr_t crashdumpmap;
+
+extern void bcopy_page(vm_offset_t, vm_offset_t);
+extern void bzero_page(vm_offset_t);
+
+char *_tmppt;
+
+/*
+ * Metadata for L1 translation tables.
+ */
+struct l1_ttable {
+ /* Entry on the L1 Table list */
+ SLIST_ENTRY(l1_ttable) l1_link;
+
+ /* Entry on the L1 Least Recently Used list */
+ TAILQ_ENTRY(l1_ttable) l1_lru;
+
+ /* Track how many domains are allocated from this L1 */
+ volatile u_int l1_domain_use_count;
+
+ /*
+ * A free-list of domain numbers for this L1.
+ * We avoid using ffs() and a bitmap to track domains since ffs()
+ * is slow on ARM.
+ */
+ u_int8_t l1_domain_first;
+ u_int8_t l1_domain_free[PMAP_DOMAINS];
+
+ /* Physical address of this L1 page table */
+ vm_paddr_t l1_physaddr;
+
+ /* KVA of this L1 page table */
+ pd_entry_t *l1_kva;
+};
+
+/*
+ * Convert a virtual address into its L1 table index. That is, the
+ * index used to locate the L2 descriptor table pointer in an L1 table.
+ * This is basically used to index l1->l1_kva[].
+ *
+ * Each L2 descriptor table represents 1MB of VA space.
+ */
+#define L1_IDX(va) (((vm_offset_t)(va)) >> L1_S_SHIFT)
+
+/*
+ * L1 Page Tables are tracked using a Least Recently Used list.
+ * - New L1s are allocated from the HEAD.
+ * - Freed L1s are added to the TAIl.
+ * - Recently accessed L1s (where an 'access' is some change to one of
+ * the userland pmaps which owns this L1) are moved to the TAIL.
+ */
+static TAILQ_HEAD(, l1_ttable) l1_lru_list;
+/*
+ * A list of all L1 tables
+ */
+static SLIST_HEAD(, l1_ttable) l1_list;
+static struct mtx l1_lru_lock;
+
+/*
+ * The l2_dtable tracks L2_BUCKET_SIZE worth of L1 slots.
+ *
+ * This is normally 16MB worth L2 page descriptors for any given pmap.
+ * Reference counts are maintained for L2 descriptors so they can be
+ * freed when empty.
+ */
+struct l2_dtable {
+ /* The number of L2 page descriptors allocated to this l2_dtable */
+ u_int l2_occupancy;
+
+ /* List of L2 page descriptors */
+ struct l2_bucket {
+ pt_entry_t *l2b_kva; /* KVA of L2 Descriptor Table */
+ vm_paddr_t l2b_phys; /* Physical address of same */
+ u_short l2b_l1idx; /* This L2 table's L1 index */
+ u_short l2b_occupancy; /* How many active descriptors */
+ } l2_bucket[L2_BUCKET_SIZE];
+};
+
+/* pmap_kenter_internal flags */
+#define KENTER_CACHE 0x1
+#define KENTER_DEVICE 0x2
+#define KENTER_USER 0x4
+
+/*
+ * Given an L1 table index, calculate the corresponding l2_dtable index
+ * and bucket index within the l2_dtable.
+ */
+#define L2_IDX(l1idx) (((l1idx) >> L2_BUCKET_LOG2) & \
+ (L2_SIZE - 1))
+#define L2_BUCKET(l1idx) ((l1idx) & (L2_BUCKET_SIZE - 1))
+
+/*
+ * Given a virtual address, this macro returns the
+ * virtual address required to drop into the next L2 bucket.
+ */
+#define L2_NEXT_BUCKET(va) (((va) & L1_S_FRAME) + L1_S_SIZE)
+
+/*
+ * We try to map the page tables write-through, if possible. However, not
+ * all CPUs have a write-through cache mode, so on those we have to sync
+ * the cache when we frob page tables.
+ *
+ * We try to evaluate this at compile time, if possible. However, it's
+ * not always possible to do that, hence this run-time var.
+ */
+int pmap_needs_pte_sync;
+
+/*
+ * Macro to determine if a mapping might be resident in the
+ * instruction cache and/or TLB
+ */
+#define PTE_BEEN_EXECD(pte) (L2_S_EXECUTABLE(pte) && L2_S_REFERENCED(pte))
+
+/*
+ * Macro to determine if a mapping might be resident in the
+ * data cache and/or TLB
+ */
+#define PTE_BEEN_REFD(pte) (L2_S_REFERENCED(pte))
+
+#ifndef PMAP_SHPGPERPROC
+#define PMAP_SHPGPERPROC 200
+#endif
+
+#define pmap_is_current(pm) ((pm) == pmap_kernel() || \
+ curproc->p_vmspace->vm_map.pmap == (pm))
+
+/*
+ * Data for the pv entry allocation mechanism
+ */
+static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
+static int pv_entry_count, pv_entry_max, pv_entry_high_water;
+static struct md_page *pv_table;
+static int shpgperproc = PMAP_SHPGPERPROC;
+
+struct pv_chunk *pv_chunkbase; /* KVA block for pv_chunks */
+int pv_maxchunks; /* How many chunks we have KVA for */
+vm_offset_t pv_vafree; /* Freelist stored in the PTE */
+
+static __inline struct pv_chunk *
+pv_to_chunk(pv_entry_t pv)
+{
+
+ return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK));
+}
+
+#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap)
+
+CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE);
+CTASSERT(_NPCM == 8);
+CTASSERT(_NPCPV == 252);
+
+#define PC_FREE0_6 0xfffffffful /* Free values for index 0 through 6 */
+#define PC_FREE7 0x0ffffffful /* Free values for index 7 */
+
+static const uint32_t pc_freemask[_NPCM] = {
+ PC_FREE0_6, PC_FREE0_6, PC_FREE0_6,
+ PC_FREE0_6, PC_FREE0_6, PC_FREE0_6,
+ PC_FREE0_6, PC_FREE7
+};
+
+static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
+
+/* Superpages utilization enabled = 1 / disabled = 0 */
+static int sp_enabled = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, sp_enabled, CTLFLAG_RDTUN, &sp_enabled, 0,
+ "Are large page mappings enabled?");
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
+ "Current number of pv entries");
+
+#ifdef PV_STATS
+static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail;
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0,
+ "Current number of pv entry chunks");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0,
+ "Current number of pv entry chunks allocated");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0,
+ "Current number of pv entry chunks frees");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail, 0,
+ "Number of times tried to get a chunk page but failed.");
+
+static long pv_entry_frees, pv_entry_allocs;
+static int pv_entry_spare;
+
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0,
+ "Current number of pv entry frees");
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs, 0,
+ "Current number of pv entry allocs");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
+ "Current number of spare pv entries");
+#endif
+
+uma_zone_t l2zone;
+static uma_zone_t l2table_zone;
+static vm_offset_t pmap_kernel_l2dtable_kva;
+static vm_offset_t pmap_kernel_l2ptp_kva;
+static vm_paddr_t pmap_kernel_l2ptp_phys;
+static struct rwlock pvh_global_lock;
+
+int l1_mem_types[] = {
+ ARM_L1S_STRONG_ORD,
+ ARM_L1S_DEVICE_NOSHARE,
+ ARM_L1S_DEVICE_SHARE,
+ ARM_L1S_NRML_NOCACHE,
+ ARM_L1S_NRML_IWT_OWT,
+ ARM_L1S_NRML_IWB_OWB,
+ ARM_L1S_NRML_IWBA_OWBA
+};
+
+int l2l_mem_types[] = {
+ ARM_L2L_STRONG_ORD,
+ ARM_L2L_DEVICE_NOSHARE,
+ ARM_L2L_DEVICE_SHARE,
+ ARM_L2L_NRML_NOCACHE,
+ ARM_L2L_NRML_IWT_OWT,
+ ARM_L2L_NRML_IWB_OWB,
+ ARM_L2L_NRML_IWBA_OWBA
+};
+
+int l2s_mem_types[] = {
+ ARM_L2S_STRONG_ORD,
+ ARM_L2S_DEVICE_NOSHARE,
+ ARM_L2S_DEVICE_SHARE,
+ ARM_L2S_NRML_NOCACHE,
+ ARM_L2S_NRML_IWT_OWT,
+ ARM_L2S_NRML_IWB_OWB,
+ ARM_L2S_NRML_IWBA_OWBA
+};
+
+/*
+ * This list exists for the benefit of pmap_map_chunk(). It keeps track
+ * of the kernel L2 tables during bootstrap, so that pmap_map_chunk() can
+ * find them as necessary.
+ *
+ * Note that the data on this list MUST remain valid after initarm() returns,
+ * as pmap_bootstrap() uses it to contruct L2 table metadata.
+ */
+SLIST_HEAD(, pv_addr) kernel_pt_list = SLIST_HEAD_INITIALIZER(kernel_pt_list);
+
+static void
+pmap_init_l1(struct l1_ttable *l1, pd_entry_t *l1pt)
+{
+ int i;
+
+ l1->l1_kva = l1pt;
+ l1->l1_domain_use_count = 0;
+ l1->l1_domain_first = 0;
+
+ for (i = 0; i < PMAP_DOMAINS; i++)
+ l1->l1_domain_free[i] = i + 1;
+
+ /*
+ * Copy the kernel's L1 entries to each new L1.
+ */
+ if (l1pt != pmap_kernel()->pm_l1->l1_kva)
+ memcpy(l1pt, pmap_kernel()->pm_l1->l1_kva, L1_TABLE_SIZE);
+
+ if ((l1->l1_physaddr = pmap_extract(pmap_kernel(), (vm_offset_t)l1pt)) == 0)
+ panic("pmap_init_l1: can't get PA of L1 at %p", l1pt);
+ SLIST_INSERT_HEAD(&l1_list, l1, l1_link);
+ TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
+}
+
+static vm_offset_t
+kernel_pt_lookup(vm_paddr_t pa)
+{
+ struct pv_addr *pv;
+
+ SLIST_FOREACH(pv, &kernel_pt_list, pv_list) {
+ if (pv->pv_pa == pa)
+ return (pv->pv_va);
+ }
+ return (0);
+}
+
+void
+pmap_pte_init_mmu_v6(void)
+{
+
+ if (PTE_PAGETABLE >= 3)
+ pmap_needs_pte_sync = 1;
+ pte_l1_s_cache_mode = l1_mem_types[PTE_CACHE];
+ pte_l2_l_cache_mode = l2l_mem_types[PTE_CACHE];
+ pte_l2_s_cache_mode = l2s_mem_types[PTE_CACHE];
+
+ pte_l1_s_cache_mode_pt = l1_mem_types[PTE_PAGETABLE];
+ pte_l2_l_cache_mode_pt = l2l_mem_types[PTE_PAGETABLE];
+ pte_l2_s_cache_mode_pt = l2s_mem_types[PTE_PAGETABLE];
+
+}
+
+/*
+ * Allocate an L1 translation table for the specified pmap.
+ * This is called at pmap creation time.
+ */
+static void
+pmap_alloc_l1(pmap_t pmap)
+{
+ struct l1_ttable *l1;
+ u_int8_t domain;
+
+ /*
+ * Remove the L1 at the head of the LRU list
+ */
+ mtx_lock(&l1_lru_lock);
+ l1 = TAILQ_FIRST(&l1_lru_list);
+ TAILQ_REMOVE(&l1_lru_list, l1, l1_lru);
+
+ /*
+ * Pick the first available domain number, and update
+ * the link to the next number.
+ */
+ domain = l1->l1_domain_first;
+ l1->l1_domain_first = l1->l1_domain_free[domain];
+
+ /*
+ * If there are still free domain numbers in this L1,
+ * put it back on the TAIL of the LRU list.
+ */
+ if (++l1->l1_domain_use_count < PMAP_DOMAINS)
+ TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
+
+ mtx_unlock(&l1_lru_lock);
+
+ /*
+ * Fix up the relevant bits in the pmap structure
+ */
+ pmap->pm_l1 = l1;
+ pmap->pm_domain = domain + 1;
+}
+
+/*
+ * Free an L1 translation table.
+ * This is called at pmap destruction time.
+ */
+static void
+pmap_free_l1(pmap_t pmap)
+{
+ struct l1_ttable *l1 = pmap->pm_l1;
+
+ mtx_lock(&l1_lru_lock);
+
+ /*
+ * If this L1 is currently on the LRU list, remove it.
+ */
+ if (l1->l1_domain_use_count < PMAP_DOMAINS)
+ TAILQ_REMOVE(&l1_lru_list, l1, l1_lru);
+
+ /*
+ * Free up the domain number which was allocated to the pmap
+ */
+ l1->l1_domain_free[pmap->pm_domain - 1] = l1->l1_domain_first;
+ l1->l1_domain_first = pmap->pm_domain - 1;
+ l1->l1_domain_use_count--;
+
+ /*
+ * The L1 now must have at least 1 free domain, so add
+ * it back to the LRU list. If the use count is zero,
+ * put it at the head of the list, otherwise it goes
+ * to the tail.
+ */
+ if (l1->l1_domain_use_count == 0) {
+ TAILQ_INSERT_HEAD(&l1_lru_list, l1, l1_lru);
+ } else
+ TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
+
+ mtx_unlock(&l1_lru_lock);
+}
+
+/*
+ * Returns a pointer to the L2 bucket associated with the specified pmap
+ * and VA, or NULL if no L2 bucket exists for the address.
+ */
+static PMAP_INLINE struct l2_bucket *
+pmap_get_l2_bucket(pmap_t pmap, vm_offset_t va)
+{
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ u_short l1idx;
+
+ l1idx = L1_IDX(va);
+
+ if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL ||
+ (l2b = &l2->l2_bucket[L2_BUCKET(l1idx)])->l2b_kva == NULL)
+ return (NULL);
+
+ return (l2b);
+}
+
+/*
+ * Returns a pointer to the L2 bucket associated with the specified pmap
+ * and VA.
+ *
+ * If no L2 bucket exists, perform the necessary allocations to put an L2
+ * bucket/page table in place.
+ *
+ * Note that if a new L2 bucket/page was allocated, the caller *must*
+ * increment the bucket occupancy counter appropriately *before*
+ * releasing the pmap's lock to ensure no other thread or cpu deallocates
+ * the bucket/page in the meantime.
+ */
+static struct l2_bucket *
+pmap_alloc_l2_bucket(pmap_t pmap, vm_offset_t va)
+{
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ u_short l1idx;
+
+ l1idx = L1_IDX(va);
+
+ PMAP_ASSERT_LOCKED(pmap);
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL) {
+ /*
+ * No mapping at this address, as there is
+ * no entry in the L1 table.
+ * Need to allocate a new l2_dtable.
+ */
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+ if ((l2 = uma_zalloc(l2table_zone, M_NOWAIT)) == NULL) {
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ return (NULL);
+ }
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ if (pmap->pm_l2[L2_IDX(l1idx)] != NULL) {
+ /*
+ * Someone already allocated the l2_dtable while
+ * we were doing the same.
+ */
+ uma_zfree(l2table_zone, l2);
+ l2 = pmap->pm_l2[L2_IDX(l1idx)];
+ } else {
+ bzero(l2, sizeof(*l2));
+ /*
+ * Link it into the parent pmap
+ */
+ pmap->pm_l2[L2_IDX(l1idx)] = l2;
+ }
+ }
+
+ l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+
+ /*
+ * Fetch pointer to the L2 page table associated with the address.
+ */
+ if (l2b->l2b_kva == NULL) {
+ pt_entry_t *ptep;
+
+ /*
+ * No L2 page table has been allocated. Chances are, this
+ * is because we just allocated the l2_dtable, above.
+ */
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+ ptep = uma_zalloc(l2zone, M_NOWAIT);
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ if (l2b->l2b_kva != 0) {
+ /* We lost the race. */
+ uma_zfree(l2zone, ptep);
+ return (l2b);
+ }
+ l2b->l2b_phys = vtophys(ptep);
+ if (ptep == NULL) {
+ /*
+ * Oops, no more L2 page tables available at this
+ * time. We may need to deallocate the l2_dtable
+ * if we allocated a new one above.
+ */
+ if (l2->l2_occupancy == 0) {
+ pmap->pm_l2[L2_IDX(l1idx)] = NULL;
+ uma_zfree(l2table_zone, l2);
+ }
+ return (NULL);
+ }
+
+ l2->l2_occupancy++;
+ l2b->l2b_kva = ptep;
+ l2b->l2b_l1idx = l1idx;
+ }
+
+ return (l2b);
+}
+
+static PMAP_INLINE void
+pmap_free_l2_ptp(pt_entry_t *l2)
+{
+ uma_zfree(l2zone, l2);
+}
+/*
+ * One or more mappings in the specified L2 descriptor table have just been
+ * invalidated.
+ *
+ * Garbage collect the metadata and descriptor table itself if necessary.
+ *
+ * The pmap lock must be acquired when this is called (not necessary
+ * for the kernel pmap).
+ */
+static void
+pmap_free_l2_bucket(pmap_t pmap, struct l2_bucket *l2b, u_int count)
+{
+ struct l2_dtable *l2;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep;
+ u_short l1idx;
+
+
+ /*
+ * Update the bucket's reference count according to how many
+ * PTEs the caller has just invalidated.
+ */
+ l2b->l2b_occupancy -= count;
+
+ /*
+ * Note:
+ *
+ * Level 2 page tables allocated to the kernel pmap are never freed
+ * as that would require checking all Level 1 page tables and
+ * removing any references to the Level 2 page table. See also the
+ * comment elsewhere about never freeing bootstrap L2 descriptors.
+ *
+ * We make do with just invalidating the mapping in the L2 table.
+ *
+ * This isn't really a big deal in practice and, in fact, leads
+ * to a performance win over time as we don't need to continually
+ * alloc/free.
+ */
+ if (l2b->l2b_occupancy > 0 || pmap == pmap_kernel())
+ return;
+
+ /*
+ * There are no more valid mappings in this level 2 page table.
+ * Go ahead and NULL-out the pointer in the bucket, then
+ * free the page table.
+ */
+ l1idx = l2b->l2b_l1idx;
+ ptep = l2b->l2b_kva;
+ l2b->l2b_kva = NULL;
+
+ pl1pd = &pmap->pm_l1->l1_kva[l1idx];
+
+ /*
+ * If the L1 slot matches the pmap's domain
+ * number, then invalidate it.
+ */
+ l1pd = *pl1pd & (L1_TYPE_MASK | L1_C_DOM_MASK);
+ if (l1pd == (L1_C_DOM(pmap->pm_domain) | L1_TYPE_C)) {
+ *pl1pd = 0;
+ PTE_SYNC(pl1pd);
+ cpu_tlb_flushD_SE((vm_offset_t)ptep);
+ cpu_cpwait();
+ }
+
+ /*
+ * Release the L2 descriptor table back to the pool cache.
+ */
+ pmap_free_l2_ptp(ptep);
+
+ /*
+ * Update the reference count in the associated l2_dtable
+ */
+ l2 = pmap->pm_l2[L2_IDX(l1idx)];
+ if (--l2->l2_occupancy > 0)
+ return;
+
+ /*
+ * There are no more valid mappings in any of the Level 1
+ * slots managed by this l2_dtable. Go ahead and NULL-out
+ * the pointer in the parent pmap and free the l2_dtable.
+ */
+ pmap->pm_l2[L2_IDX(l1idx)] = NULL;
+ uma_zfree(l2table_zone, l2);
+}
+
+/*
+ * Pool cache constructors for L2 descriptor tables, metadata and pmap
+ * structures.
+ */
+static int
+pmap_l2ptp_ctor(void *mem, int size, void *arg, int flags)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, pte;
+ vm_offset_t va = (vm_offset_t)mem & ~PAGE_MASK;
+
+ /*
+ * The mappings for these page tables were initially made using
+ * pmap_kenter() by the pool subsystem. Therefore, the cache-
+ * mode will not be right for page table mappings. To avoid
+ * polluting the pmap_kenter() code with a special case for
+ * page tables, we simply fix up the cache-mode here if it's not
+ * correct.
+ */
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ pte = *ptep;
+
+ cpu_idcache_wbinv_range(va, PAGE_SIZE);
+ pmap_l2cache_wbinv_range(va, pte & L2_S_FRAME, PAGE_SIZE);
+ if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
+ /*
+ * Page tables must have the cache-mode set to
+ * Write-Thru.
+ */
+ *ptep = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt;
+ PTE_SYNC(ptep);
+ cpu_tlb_flushD_SE(va);
+ cpu_cpwait();
+ }
+
+ memset(mem, 0, L2_TABLE_SIZE_REAL);
+ return (0);
+}
+
+/*
+ * Modify pte bits for all ptes corresponding to the given physical address.
+ * We use `maskbits' rather than `clearbits' because we're always passing
+ * constants and the latter would require an extra inversion at run-time.
+ */
+static int
+pmap_clearbit(struct vm_page *m, u_int maskbits)
+{
+ struct l2_bucket *l2b;
+ struct pv_entry *pv, *pve, *next_pv;
+ struct md_page *pvh;
+ pd_entry_t *pl1pd;
+ pt_entry_t *ptep, npte, opte;
+ pmap_t pmap;
+ vm_offset_t va;
+ u_int oflags;
+ int count = 0;
+
+ rw_wlock(&pvh_global_lock);
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ goto small_mappings;
+
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
+ va = pv->pv_va;
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ KASSERT((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO,
+ ("pmap_clearbit: valid section mapping expected"));
+ if ((maskbits & PVF_WRITE) && (pv->pv_flags & PVF_WRITE))
+ (void)pmap_demote_section(pmap, va);
+ else if ((maskbits & PVF_REF) && L1_S_REFERENCED(*pl1pd)) {
+ if (pmap_demote_section(pmap, va)) {
+ if ((pv->pv_flags & PVF_WIRED) == 0) {
+ /*
+ * Remove the mapping to a single page
+ * so that a subsequent access may
+ * repromote. Since the underlying
+ * l2_bucket is fully populated, this
+ * removal never frees an entire
+ * l2_bucket.
+ */
+ va += (VM_PAGE_TO_PHYS(m) &
+ L1_S_OFFSET);
+ l2b = pmap_get_l2_bucket(pmap, va);
+ KASSERT(l2b != NULL,
+ ("pmap_clearbit: no l2 bucket for "
+ "va 0x%#x, pmap 0x%p", va, pmap));
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ *ptep = 0;
+ PTE_SYNC(ptep);
+ pmap_free_l2_bucket(pmap, l2b, 1);
+ pve = pmap_remove_pv(m, pmap, va);
+ KASSERT(pve != NULL, ("pmap_clearbit: "
+ "no PV entry for managed mapping"));
+ pmap_free_pv_entry(pmap, pve);
+
+ }
+ }
+ } else if ((maskbits & PVF_MOD) && L1_S_WRITABLE(*pl1pd)) {
+ if (pmap_demote_section(pmap, va)) {
+ if ((pv->pv_flags & PVF_WIRED) == 0) {
+ /*
+ * Write protect the mapping to a
+ * single page so that a subsequent
+ * write access may repromote.
+ */
+ va += (VM_PAGE_TO_PHYS(m) &
+ L1_S_OFFSET);
+ l2b = pmap_get_l2_bucket(pmap, va);
+ KASSERT(l2b != NULL,
+ ("pmap_clearbit: no l2 bucket for "
+ "va 0x%#x, pmap 0x%p", va, pmap));
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ if ((*ptep & L2_S_PROTO) != 0) {
+ pve = pmap_find_pv(&m->md,
+ pmap, va);
+ KASSERT(pve != NULL,
+ ("pmap_clearbit: no PV "
+ "entry for managed mapping"));
+ pve->pv_flags &= ~PVF_WRITE;
+ *ptep |= L2_APX;
+ PTE_SYNC(ptep);
+ }
+ }
+ }
+ }
+ PMAP_UNLOCK(pmap);
+ }
+
+small_mappings:
+ if (TAILQ_EMPTY(&m->md.pv_list)) {
+ rw_wunlock(&pvh_global_lock);
+ return (0);
+ }
+
+ /*
+ * Loop over all current mappings setting/clearing as appropos
+ */
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ va = pv->pv_va;
+ pmap = PV_PMAP(pv);
+ oflags = pv->pv_flags;
+ pv->pv_flags &= ~maskbits;
+
+ PMAP_LOCK(pmap);
+
+ l2b = pmap_get_l2_bucket(pmap, va);
+ KASSERT(l2b != NULL, ("pmap_clearbit: no l2 bucket for "
+ "va 0x%#x, pmap 0x%p", va, pmap));
+
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ npte = opte = *ptep;
+
+ if (maskbits & (PVF_WRITE | PVF_MOD)) {
+ /* make the pte read only */
+ npte |= L2_APX;
+ }
+
+ if (maskbits & PVF_REF) {
+ /*
+ * Clear referenced flag in PTE so that we
+ * will take a flag fault the next time the mapping
+ * is referenced.
+ */
+ npte &= ~L2_S_REF;
+ }
+
+ CTR4(KTR_PMAP,"clearbit: pmap:%p bits:%x pte:%x->%x",
+ pmap, maskbits, opte, npte);
+ if (npte != opte) {
+ count++;
+ *ptep = npte;
+ PTE_SYNC(ptep);
+ /* Flush the TLB entry if a current pmap. */
+ if (PTE_BEEN_EXECD(opte))
+ cpu_tlb_flushID_SE(pv->pv_va);
+ else if (PTE_BEEN_REFD(opte))
+ cpu_tlb_flushD_SE(pv->pv_va);
+ cpu_cpwait();
+ }
+
+ PMAP_UNLOCK(pmap);
+
+ }
+
+ if (maskbits & PVF_WRITE)
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ rw_wunlock(&pvh_global_lock);
+ return (count);
+}
+
+/*
+ * main pv_entry manipulation functions:
+ * pmap_enter_pv: enter a mapping onto a vm_page list
+ * pmap_remove_pv: remove a mappiing from a vm_page list
+ *
+ * NOTE: pmap_enter_pv expects to lock the pvh itself
+ * pmap_remove_pv expects the caller to lock the pvh before calling
+ */
+
+/*
+ * pmap_enter_pv: enter a mapping onto a vm_page's PV list
+ *
+ * => caller should hold the proper lock on pvh_global_lock
+ * => caller should have pmap locked
+ * => we will (someday) gain the lock on the vm_page's PV list
+ * => caller should adjust ptp's wire_count before calling
+ * => caller should not adjust pmap's wire_count
+ */
+static void
+pmap_enter_pv(struct vm_page *m, struct pv_entry *pve, pmap_t pmap,
+ vm_offset_t va, u_int flags)
+{
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+
+ PMAP_ASSERT_LOCKED(pmap);
+ pve->pv_va = va;
+ pve->pv_flags = flags;
+
+ TAILQ_INSERT_HEAD(&m->md.pv_list, pve, pv_list);
+ if (pve->pv_flags & PVF_WIRED)
+ ++pmap->pm_stats.wired_count;
+}
+
+/*
+ *
+ * pmap_find_pv: Find a pv entry
+ *
+ * => caller should hold lock on vm_page
+ */
+static PMAP_INLINE struct pv_entry *
+pmap_find_pv(struct md_page *md, pmap_t pmap, vm_offset_t va)
+{
+ struct pv_entry *pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ TAILQ_FOREACH(pv, &md->pv_list, pv_list)
+ if (pmap == PV_PMAP(pv) && va == pv->pv_va)
+ break;
+
+ return (pv);
+}
+
+/*
+ * vector_page_setprot:
+ *
+ * Manipulate the protection of the vector page.
+ */
+void
+vector_page_setprot(int prot)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep;
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), vector_page);
+
+ ptep = &l2b->l2b_kva[l2pte_index(vector_page)];
+ /*
+ * Set referenced flag.
+ * Vectors' page is always desired
+ * to be allowed to reside in TLB.
+ */
+ *ptep |= L2_S_REF;
+
+ pmap_set_prot(ptep, prot|VM_PROT_EXECUTE, 0);
+ PTE_SYNC(ptep);
+ cpu_tlb_flushID_SE(vector_page);
+ cpu_cpwait();
+}
+
+static void
+pmap_set_prot(pt_entry_t *ptep, vm_prot_t prot, uint8_t user)
+{
+
+ *ptep &= ~(L2_S_PROT_MASK | L2_XN);
+
+ if (!(prot & VM_PROT_EXECUTE))
+ *ptep |= L2_XN;
+
+ /* Set defaults first - kernel read access */
+ *ptep |= L2_APX;
+ *ptep |= L2_S_PROT_R;
+ /* Now tune APs as desired */
+ if (user)
+ *ptep |= L2_S_PROT_U;
+
+ if (prot & VM_PROT_WRITE)
+ *ptep &= ~(L2_APX);
+}
+
+/*
+ * pmap_remove_pv: try to remove a mapping from a pv_list
+ *
+ * => caller should hold proper lock on pmap_main_lock
+ * => pmap should be locked
+ * => caller should hold lock on vm_page [so that attrs can be adjusted]
+ * => caller should adjust ptp's wire_count and free PTP if needed
+ * => caller should NOT adjust pmap's wire_count
+ * => we return the removed pve
+ */
+static struct pv_entry *
+pmap_remove_pv(struct vm_page *m, pmap_t pmap, vm_offset_t va)
+{
+ struct pv_entry *pve;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_ASSERT_LOCKED(pmap);
+
+ pve = pmap_find_pv(&m->md, pmap, va); /* find corresponding pve */
+ if (pve != NULL) {
+ TAILQ_REMOVE(&m->md.pv_list, pve, pv_list);
+ if (pve->pv_flags & PVF_WIRED)
+ --pmap->pm_stats.wired_count;
+ }
+ if (TAILQ_EMPTY(&m->md.pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+
+ return(pve); /* return removed pve */
+}
+
+/*
+ *
+ * pmap_modify_pv: Update pv flags
+ *
+ * => caller should hold lock on vm_page [so that attrs can be adjusted]
+ * => caller should NOT adjust pmap's wire_count
+ * => we return the old flags
+ *
+ * Modify a physical-virtual mapping in the pv table
+ */
+static u_int
+pmap_modify_pv(struct vm_page *m, pmap_t pmap, vm_offset_t va,
+ u_int clr_mask, u_int set_mask)
+{
+ struct pv_entry *npv;
+ u_int flags, oflags;
+
+ PMAP_ASSERT_LOCKED(pmap);
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ if ((npv = pmap_find_pv(&m->md, pmap, va)) == NULL)
+ return (0);
+
+ /*
+ * There is at least one VA mapping this page.
+ */
+ oflags = npv->pv_flags;
+ npv->pv_flags = flags = (oflags & ~clr_mask) | set_mask;
+
+ if ((flags ^ oflags) & PVF_WIRED) {
+ if (flags & PVF_WIRED)
+ ++pmap->pm_stats.wired_count;
+ else
+ --pmap->pm_stats.wired_count;
+ }
+
+ return (oflags);
+}
+
+/* Function to set the debug level of the pmap code */
+#ifdef PMAP_DEBUG
+void
+pmap_debug(int level)
+{
+ pmap_debug_level = level;
+ dprintf("pmap_debug: level=%d\n", pmap_debug_level);
+}
+#endif /* PMAP_DEBUG */
+
+void
+pmap_pinit0(struct pmap *pmap)
+{
+ PDEBUG(1, printf("pmap_pinit0: pmap = %08x\n", (u_int32_t) pmap));
+
+ bcopy(kernel_pmap, pmap, sizeof(*pmap));
+ bzero(&pmap->pm_mtx, sizeof(pmap->pm_mtx));
+ PMAP_LOCK_INIT(pmap);
+ TAILQ_INIT(&pmap->pm_pvchunk);
+}
+
+/*
+ * Initialize a vm_page's machine-dependent fields.
+ */
+void
+pmap_page_init(vm_page_t m)
+{
+
+ TAILQ_INIT(&m->md.pv_list);
+ m->md.pv_memattr = VM_MEMATTR_DEFAULT;
+}
+
+static vm_offset_t
+pmap_ptelist_alloc(vm_offset_t *head)
+{
+ pt_entry_t *pte;
+ vm_offset_t va;
+
+ va = *head;
+ if (va == 0)
+ return (va); /* Out of memory */
+ pte = vtopte(va);
+ *head = *pte;
+ if ((*head & L2_TYPE_MASK) != L2_TYPE_INV)
+ panic("%s: va is not L2_TYPE_INV!", __func__);
+ *pte = 0;
+ return (va);
+}
+
+static void
+pmap_ptelist_free(vm_offset_t *head, vm_offset_t va)
+{
+ pt_entry_t *pte;
+
+ if ((va & L2_TYPE_MASK) != L2_TYPE_INV)
+ panic("%s: freeing va that is not L2_TYPE INV!", __func__);
+ pte = vtopte(va);
+ *pte = *head; /* virtual! L2_TYPE is L2_TYPE_INV though */
+ *head = va;
+}
+
+static void
+pmap_ptelist_init(vm_offset_t *head, void *base, int npages)
+{
+ int i;
+ vm_offset_t va;
+
+ *head = 0;
+ for (i = npages - 1; i >= 0; i--) {
+ va = (vm_offset_t)base + i * PAGE_SIZE;
+ pmap_ptelist_free(head, va);
+ }
+}
+
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
+void
+pmap_init(void)
+{
+ vm_size_t s;
+ int i, pv_npg;
+
+ l2zone = uma_zcreate("L2 Table", L2_TABLE_SIZE_REAL, pmap_l2ptp_ctor,
+ NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
+ l2table_zone = uma_zcreate("L2 Table", sizeof(struct l2_dtable), NULL,
+ NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
+
+ /*
+ * Are large page mappings supported and enabled?
+ */
+ TUNABLE_INT_FETCH("vm.pmap.sp_enabled", &sp_enabled);
+ if (sp_enabled) {
+ KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0,
+ ("pmap_init: can't assign to pagesizes[1]"));
+ pagesizes[1] = NBPDR;
+ }
+
+ /*
+ * Calculate the size of the pv head table for superpages.
+ * Handle the possibility that "vm_phys_segs[...].end" is zero.
+ */
+ pv_npg = trunc_1mpage(vm_phys_segs[vm_phys_nsegs - 1].end -
+ PAGE_SIZE) / NBPDR + 1;
+
+ /*
+ * Allocate memory for the pv head table for superpages.
+ */
+ s = (vm_size_t)(pv_npg * sizeof(struct md_page));
+ s = round_page(s);
+ pv_table = (struct md_page *)kmem_malloc(kernel_arena, s,
+ M_WAITOK | M_ZERO);
+ for (i = 0; i < pv_npg; i++)
+ TAILQ_INIT(&pv_table[i].pv_list);
+
+ /*
+ * Initialize the address space for the pv chunks.
+ */
+
+ TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
+ pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
+ TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
+ pv_entry_max = roundup(pv_entry_max, _NPCPV);
+ pv_entry_high_water = 9 * (pv_entry_max / 10);
+
+ pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc);
+ pv_chunkbase = (struct pv_chunk *)kva_alloc(PAGE_SIZE * pv_maxchunks);
+
+ if (pv_chunkbase == NULL)
+ panic("pmap_init: not enough kvm for pv chunks");
+
+ pmap_ptelist_init(&pv_vafree, pv_chunkbase, pv_maxchunks);
+
+ /*
+ * Now it is safe to enable pv_table recording.
+ */
+ PDEBUG(1, printf("pmap_init: done!\n"));
+}
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0,
+ "Max number of PV entries");
+SYSCTL_INT(_vm_pmap, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0,
+ "Page share factor per proc");
+
+static SYSCTL_NODE(_vm_pmap, OID_AUTO, section, CTLFLAG_RD, 0,
+ "1MB page mapping counters");
+
+static u_long pmap_section_demotions;
+SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, demotions, CTLFLAG_RD,
+ &pmap_section_demotions, 0, "1MB page demotions");
+
+static u_long pmap_section_mappings;
+SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, mappings, CTLFLAG_RD,
+ &pmap_section_mappings, 0, "1MB page mappings");
+
+static u_long pmap_section_p_failures;
+SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, p_failures, CTLFLAG_RD,
+ &pmap_section_p_failures, 0, "1MB page promotion failures");
+
+static u_long pmap_section_promotions;
+SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, promotions, CTLFLAG_RD,
+ &pmap_section_promotions, 0, "1MB page promotions");
+
+int
+pmap_fault_fixup(pmap_t pmap, vm_offset_t va, vm_prot_t ftype, int user)
+{
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep, pte;
+ vm_paddr_t pa;
+ u_int l1idx;
+ int rv = 0;
+
+ l1idx = L1_IDX(va);
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ /*
+ * Check and possibly fix-up L1 section mapping
+ * only when superpage mappings are enabled to speed up.
+ */
+ if (sp_enabled) {
+ pl1pd = &pmap->pm_l1->l1_kva[l1idx];
+ l1pd = *pl1pd;
+ if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+ /* Catch an access to the vectors section */
+ if (l1idx == L1_IDX(vector_page))
+ goto out;
+ /*
+ * Stay away from the kernel mappings.
+ * None of them should fault from L1 entry.
+ */
+ if (pmap == pmap_kernel())
+ goto out;
+ /*
+ * Catch a forbidden userland access
+ */
+ if (user && !(l1pd & L1_S_PROT_U))
+ goto out;
+ /*
+ * Superpage is always either mapped read only
+ * or it is modified and permitted to be written
+ * by default. Therefore, process only reference
+ * flag fault and demote page in case of write fault.
+ */
+ if ((ftype & VM_PROT_WRITE) && !L1_S_WRITABLE(l1pd) &&
+ L1_S_REFERENCED(l1pd)) {
+ (void)pmap_demote_section(pmap, va);
+ goto out;
+ } else if (!L1_S_REFERENCED(l1pd)) {
+ /* Mark the page "referenced" */
+ *pl1pd = l1pd | L1_S_REF;
+ PTE_SYNC(pl1pd);
+ goto l1_section_out;
+ } else
+ goto out;
+ }
+ }
+ /*
+ * If there is no l2_dtable for this address, then the process
+ * has no business accessing it.
+ *
+ * Note: This will catch userland processes trying to access
+ * kernel addresses.
+ */
+ l2 = pmap->pm_l2[L2_IDX(l1idx)];
+ if (l2 == NULL)
+ goto out;
+
+ /*
+ * Likewise if there is no L2 descriptor table
+ */
+ l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+ if (l2b->l2b_kva == NULL)
+ goto out;
+
+ /*
+ * Check the PTE itself.
+ */
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ pte = *ptep;
+ if (pte == 0)
+ goto out;
+
+ /*
+ * Catch a userland access to the vector page mapped at 0x0
+ */
+ if (user && !(pte & L2_S_PROT_U))
+ goto out;
+ if (va == vector_page)
+ goto out;
+
+ pa = l2pte_pa(pte);
+ CTR5(KTR_PMAP, "pmap_fault_fix: pmap:%p va:%x pte:0x%x ftype:%x user:%x",
+ pmap, va, pte, ftype, user);
+ if ((ftype & VM_PROT_WRITE) && !(L2_S_WRITABLE(pte)) &&
+ L2_S_REFERENCED(pte)) {
+ /*
+ * This looks like a good candidate for "page modified"
+ * emulation...
+ */
+ struct pv_entry *pv;
+ struct vm_page *m;
+
+ /* Extract the physical address of the page */
+ if ((m = PHYS_TO_VM_PAGE(pa)) == NULL) {
+ goto out;
+ }
+ /* Get the current flags for this page. */
+
+ pv = pmap_find_pv(&m->md, pmap, va);
+ if (pv == NULL) {
+ goto out;
+ }
+
+ /*
+ * Do the flags say this page is writable? If not then it
+ * is a genuine write fault. If yes then the write fault is
+ * our fault as we did not reflect the write access in the
+ * PTE. Now we know a write has occurred we can correct this
+ * and also set the modified bit
+ */
+ if ((pv->pv_flags & PVF_WRITE) == 0) {
+ goto out;
+ }
+
+ vm_page_dirty(m);
+
+ /* Re-enable write permissions for the page */
+ *ptep = (pte & ~L2_APX);
+ PTE_SYNC(ptep);
+ rv = 1;
+ CTR1(KTR_PMAP, "pmap_fault_fix: new pte:0x%x", *ptep);
+ } else if (!L2_S_REFERENCED(pte)) {
+ /*
+ * This looks like a good candidate for "page referenced"
+ * emulation.
+ */
+ struct pv_entry *pv;
+ struct vm_page *m;
+
+ /* Extract the physical address of the page */
+ if ((m = PHYS_TO_VM_PAGE(pa)) == NULL)
+ goto out;
+ /* Get the current flags for this page. */
+ pv = pmap_find_pv(&m->md, pmap, va);
+ if (pv == NULL)
+ goto out;
+
+ vm_page_aflag_set(m, PGA_REFERENCED);
+
+ /* Mark the page "referenced" */
+ *ptep = pte | L2_S_REF;
+ PTE_SYNC(ptep);
+ rv = 1;
+ CTR1(KTR_PMAP, "pmap_fault_fix: new pte:0x%x", *ptep);
+ }
+
+ /*
+ * We know there is a valid mapping here, so simply
+ * fix up the L1 if necessary.
+ */
+ pl1pd = &pmap->pm_l1->l1_kva[l1idx];
+ l1pd = l2b->l2b_phys | L1_C_DOM(pmap->pm_domain) | L1_C_PROTO;
+ if (*pl1pd != l1pd) {
+ *pl1pd = l1pd;
+ PTE_SYNC(pl1pd);
+ rv = 1;
+ }
+
+#ifdef DEBUG
+ /*
+ * If 'rv == 0' at this point, it generally indicates that there is a
+ * stale TLB entry for the faulting address. This happens when two or
+ * more processes are sharing an L1. Since we don't flush the TLB on
+ * a context switch between such processes, we can take domain faults
+ * for mappings which exist at the same VA in both processes. EVEN IF
+ * WE'VE RECENTLY FIXED UP THE CORRESPONDING L1 in pmap_enter(), for
+ * example.
+ *
+ * This is extremely likely to happen if pmap_enter() updated the L1
+ * entry for a recently entered mapping. In this case, the TLB is
+ * flushed for the new mapping, but there may still be TLB entries for
+ * other mappings belonging to other processes in the 1MB range
+ * covered by the L1 entry.
+ *
+ * Since 'rv == 0', we know that the L1 already contains the correct
+ * value, so the fault must be due to a stale TLB entry.
+ *
+ * Since we always need to flush the TLB anyway in the case where we
+ * fixed up the L1, or frobbed the L2 PTE, we effectively deal with
+ * stale TLB entries dynamically.
+ *
+ * However, the above condition can ONLY happen if the current L1 is
+ * being shared. If it happens when the L1 is unshared, it indicates
+ * that other parts of the pmap are not doing their job WRT managing
+ * the TLB.
+ */
+ if (rv == 0 && pmap->pm_l1->l1_domain_use_count == 1) {
+ printf("fixup: pmap %p, va 0x%08x, ftype %d - nothing to do!\n",
+ pmap, va, ftype);
+ printf("fixup: l2 %p, l2b %p, ptep %p, pl1pd %p\n",
+ l2, l2b, ptep, pl1pd);
+ printf("fixup: pte 0x%x, l1pd 0x%x, last code 0x%x\n",
+ pte, l1pd, last_fault_code);
+#ifdef DDB
+ Debugger();
+#endif
+ }
+#endif
+
+l1_section_out:
+ cpu_tlb_flushID_SE(va);
+ cpu_cpwait();
+
+ rv = 1;
+
+out:
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ return (rv);
+}
+
+void
+pmap_postinit(void)
+{
+ struct l2_bucket *l2b;
+ struct l1_ttable *l1;
+ pd_entry_t *pl1pt;
+ pt_entry_t *ptep, pte;
+ vm_offset_t va, eva;
+ u_int loop, needed;
+
+ needed = (maxproc / PMAP_DOMAINS) + ((maxproc % PMAP_DOMAINS) ? 1 : 0);
+ needed -= 1;
+ l1 = malloc(sizeof(*l1) * needed, M_VMPMAP, M_WAITOK);
+
+ for (loop = 0; loop < needed; loop++, l1++) {
+ /* Allocate a L1 page table */
+ va = (vm_offset_t)contigmalloc(L1_TABLE_SIZE, M_VMPMAP, 0, 0x0,
+ 0xffffffff, L1_TABLE_SIZE, 0);
+
+ if (va == 0)
+ panic("Cannot allocate L1 KVM");
+
+ eva = va + L1_TABLE_SIZE;
+ pl1pt = (pd_entry_t *)va;
+
+ while (va < eva) {
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ pte = *ptep;
+ pte = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt;
+ *ptep = pte;
+ PTE_SYNC(ptep);
+ cpu_tlb_flushID_SE(va);
+ cpu_cpwait();
+ va += PAGE_SIZE;
+ }
+ pmap_init_l1(l1, pl1pt);
+ }
+#ifdef DEBUG
+ printf("pmap_postinit: Allocated %d static L1 descriptor tables\n",
+ needed);
+#endif
+}
+
+/*
+ * This is used to stuff certain critical values into the PCB where they
+ * can be accessed quickly from cpu_switch() et al.
+ */
+void
+pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb)
+{
+ struct l2_bucket *l2b;
+
+ pcb->pcb_pagedir = pmap->pm_l1->l1_physaddr;
+ pcb->pcb_dacr = (DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) |
+ (DOMAIN_CLIENT << (pmap->pm_domain * 2));
+
+ if (vector_page < KERNBASE) {
+ pcb->pcb_pl1vec = &pmap->pm_l1->l1_kva[L1_IDX(vector_page)];
+ l2b = pmap_get_l2_bucket(pmap, vector_page);
+ pcb->pcb_l1vec = l2b->l2b_phys | L1_C_PROTO |
+ L1_C_DOM(pmap->pm_domain) | L1_C_DOM(PMAP_DOMAIN_KERNEL);
+ } else
+ pcb->pcb_pl1vec = NULL;
+}
+
+void
+pmap_activate(struct thread *td)
+{
+ pmap_t pmap;
+ struct pcb *pcb;
+
+ pmap = vmspace_pmap(td->td_proc->p_vmspace);
+ pcb = td->td_pcb;
+
+ critical_enter();
+ pmap_set_pcb_pagedir(pmap, pcb);
+
+ if (td == curthread) {
+ u_int cur_dacr, cur_ttb;
+
+ __asm __volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(cur_ttb));
+ __asm __volatile("mrc p15, 0, %0, c3, c0, 0" : "=r"(cur_dacr));
+
+ cur_ttb &= ~(L1_TABLE_SIZE - 1);
+
+ if (cur_ttb == (u_int)pcb->pcb_pagedir &&
+ cur_dacr == pcb->pcb_dacr) {
+ /*
+ * No need to switch address spaces.
+ */
+ critical_exit();
+ return;
+ }
+
+
+ /*
+ * We MUST, I repeat, MUST fix up the L1 entry corresponding
+ * to 'vector_page' in the incoming L1 table before switching
+ * to it otherwise subsequent interrupts/exceptions (including
+ * domain faults!) will jump into hyperspace.
+ */
+ if (pcb->pcb_pl1vec) {
+ *pcb->pcb_pl1vec = pcb->pcb_l1vec;
+ }
+
+ cpu_domains(pcb->pcb_dacr);
+ cpu_setttb(pcb->pcb_pagedir);
+ }
+ critical_exit();
+}
+
+static int
+pmap_set_pt_cache_mode(pd_entry_t *kl1, vm_offset_t va)
+{
+ pd_entry_t *pdep, pde;
+ pt_entry_t *ptep, pte;
+ vm_offset_t pa;
+ int rv = 0;
+
+ /*
+ * Make sure the descriptor itself has the correct cache mode
+ */
+ pdep = &kl1[L1_IDX(va)];
+ pde = *pdep;
+
+ if (l1pte_section_p(pde)) {
+ if ((pde & L1_S_CACHE_MASK) != pte_l1_s_cache_mode_pt) {
+ *pdep = (pde & ~L1_S_CACHE_MASK) |
+ pte_l1_s_cache_mode_pt;
+ PTE_SYNC(pdep);
+ rv = 1;
+ }
+ } else {
+ pa = (vm_paddr_t)(pde & L1_C_ADDR_MASK);
+ ptep = (pt_entry_t *)kernel_pt_lookup(pa);
+ if (ptep == NULL)
+ panic("pmap_bootstrap: No L2 for L2 @ va %p\n", ptep);
+
+ ptep = &ptep[l2pte_index(va)];
+ pte = *ptep;
+ if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
+ *ptep = (pte & ~L2_S_CACHE_MASK) |
+ pte_l2_s_cache_mode_pt;
+ PTE_SYNC(ptep);
+ rv = 1;
+ }
+ }
+
+ return (rv);
+}
+
+static void
+pmap_alloc_specials(vm_offset_t *availp, int pages, vm_offset_t *vap,
+ pt_entry_t **ptep)
+{
+ vm_offset_t va = *availp;
+ struct l2_bucket *l2b;
+
+ if (ptep) {
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ if (l2b == NULL)
+ panic("pmap_alloc_specials: no l2b for 0x%x", va);
+
+ *ptep = &l2b->l2b_kva[l2pte_index(va)];
+ }
+
+ *vap = va;
+ *availp = va + (PAGE_SIZE * pages);
+}
+
+/*
+ * Bootstrap the system enough to run with virtual memory.
+ *
+ * On the arm this is called after mapping has already been enabled
+ * and just syncs the pmap module with what has already been done.
+ * [We can't call it easily with mapping off since the kernel is not
+ * mapped with PA == VA, hence we would have to relocate every address
+ * from the linked base (virtual) address "KERNBASE" to the actual
+ * (physical) address starting relative to 0]
+ */
+#define PMAP_STATIC_L2_SIZE 16
+
+void
+pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt)
+{
+ static struct l1_ttable static_l1;
+ static struct l2_dtable static_l2[PMAP_STATIC_L2_SIZE];
+ struct l1_ttable *l1 = &static_l1;
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ struct czpages *czp;
+ pd_entry_t pde;
+ pd_entry_t *kernel_l1pt = (pd_entry_t *)l1pt->pv_va;
+ pt_entry_t *ptep;
+ vm_paddr_t pa;
+ vm_offset_t va;
+ vm_size_t size;
+ int i, l1idx, l2idx, l2next = 0;
+
+ PDEBUG(1, printf("firstaddr = %08x, lastaddr = %08x\n",
+ firstaddr, vm_max_kernel_address));
+
+ virtual_avail = firstaddr;
+ kernel_pmap->pm_l1 = l1;
+ kernel_l1pa = l1pt->pv_pa;
+
+ /*
+ * Scan the L1 translation table created by initarm() and create
+ * the required metadata for all valid mappings found in it.
+ */
+ for (l1idx = 0; l1idx < (L1_TABLE_SIZE / sizeof(pd_entry_t)); l1idx++) {
+ pde = kernel_l1pt[l1idx];
+
+ /*
+ * We're only interested in Coarse mappings.
+ * pmap_extract() can deal with section mappings without
+ * recourse to checking L2 metadata.
+ */
+ if ((pde & L1_TYPE_MASK) != L1_TYPE_C)
+ continue;
+
+ /*
+ * Lookup the KVA of this L2 descriptor table
+ */
+ pa = (vm_paddr_t)(pde & L1_C_ADDR_MASK);
+ ptep = (pt_entry_t *)kernel_pt_lookup(pa);
+
+ if (ptep == NULL) {
+ panic("pmap_bootstrap: No L2 for va 0x%x, pa 0x%lx",
+ (u_int)l1idx << L1_S_SHIFT, (long unsigned int)pa);
+ }
+
+ /*
+ * Fetch the associated L2 metadata structure.
+ * Allocate a new one if necessary.
+ */
+ if ((l2 = kernel_pmap->pm_l2[L2_IDX(l1idx)]) == NULL) {
+ if (l2next == PMAP_STATIC_L2_SIZE)
+ panic("pmap_bootstrap: out of static L2s");
+ kernel_pmap->pm_l2[L2_IDX(l1idx)] = l2 =
+ &static_l2[l2next++];
+ }
+
+ /*
+ * One more L1 slot tracked...
+ */
+ l2->l2_occupancy++;
+
+ /*
+ * Fill in the details of the L2 descriptor in the
+ * appropriate bucket.
+ */
+ l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+ l2b->l2b_kva = ptep;
+ l2b->l2b_phys = pa;
+ l2b->l2b_l1idx = l1idx;
+
+ /*
+ * Establish an initial occupancy count for this descriptor
+ */
+ for (l2idx = 0;
+ l2idx < (L2_TABLE_SIZE_REAL / sizeof(pt_entry_t));
+ l2idx++) {
+ if ((ptep[l2idx] & L2_TYPE_MASK) != L2_TYPE_INV) {
+ l2b->l2b_occupancy++;
+ }
+ }
+
+ /*
+ * Make sure the descriptor itself has the correct cache mode.
+ * If not, fix it, but whine about the problem. Port-meisters
+ * should consider this a clue to fix up their initarm()
+ * function. :)
+ */
+ if (pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)ptep)) {
+ printf("pmap_bootstrap: WARNING! wrong cache mode for "
+ "L2 pte @ %p\n", ptep);
+ }
+ }
+
+
+ /*
+ * Ensure the primary (kernel) L1 has the correct cache mode for
+ * a page table. Bitch if it is not correctly set.
+ */
+ for (va = (vm_offset_t)kernel_l1pt;
+ va < ((vm_offset_t)kernel_l1pt + L1_TABLE_SIZE); va += PAGE_SIZE) {
+ if (pmap_set_pt_cache_mode(kernel_l1pt, va))
+ printf("pmap_bootstrap: WARNING! wrong cache mode for "
+ "primary L1 @ 0x%x\n", va);
+ }
+
+ cpu_dcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ cpu_tlb_flushID();
+ cpu_cpwait();
+
+ PMAP_LOCK_INIT(kernel_pmap);
+ CPU_FILL(&kernel_pmap->pm_active);
+ kernel_pmap->pm_domain = PMAP_DOMAIN_KERNEL;
+ TAILQ_INIT(&kernel_pmap->pm_pvchunk);
+
+ /*
+ * Initialize the global pv list lock.
+ */
+ rw_init(&pvh_global_lock, "pmap pv global");
+
+ /*
+ * Reserve some special page table entries/VA space for temporary
+ * mapping of pages that are being copied or zeroed.
+ */
+ for (czp = cpu_czpages, i = 0; i < MAXCPU; ++i, ++czp) {
+ mtx_init(&czp->lock, "czpages", NULL, MTX_DEF);
+ pmap_alloc_specials(&virtual_avail, 1, &czp->srcva, &czp->srcptep);
+ pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)czp->srcptep);
+ pmap_alloc_specials(&virtual_avail, 1, &czp->dstva, &czp->dstptep);
+ pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)czp->dstptep);
+ }
+
+ size = ((vm_max_kernel_address - pmap_curmaxkvaddr) + L1_S_OFFSET) /
+ L1_S_SIZE;
+ pmap_alloc_specials(&virtual_avail,
+ round_page(size * L2_TABLE_SIZE_REAL) / PAGE_SIZE,
+ &pmap_kernel_l2ptp_kva, NULL);
+
+ size = (size + (L2_BUCKET_SIZE - 1)) / L2_BUCKET_SIZE;
+ pmap_alloc_specials(&virtual_avail,
+ round_page(size * sizeof(struct l2_dtable)) / PAGE_SIZE,
+ &pmap_kernel_l2dtable_kva, NULL);
+
+ pmap_alloc_specials(&virtual_avail,
+ 1, (vm_offset_t*)&_tmppt, NULL);
+ pmap_alloc_specials(&virtual_avail,
+ MAXDUMPPGS, (vm_offset_t *)&crashdumpmap, NULL);
+ SLIST_INIT(&l1_list);
+ TAILQ_INIT(&l1_lru_list);
+ mtx_init(&l1_lru_lock, "l1 list lock", NULL, MTX_DEF);
+ pmap_init_l1(l1, kernel_l1pt);
+ cpu_dcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ cpu_tlb_flushID();
+ cpu_cpwait();
+
+ virtual_avail = round_page(virtual_avail);
+ virtual_end = vm_max_kernel_address;
+ kernel_vm_end = pmap_curmaxkvaddr;
+
+ pmap_set_pcb_pagedir(kernel_pmap, thread0.td_pcb);
+}
+
+/***************************************************
+ * Pmap allocation/deallocation routines.
+ ***************************************************/
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+void
+pmap_release(pmap_t pmap)
+{
+ struct pcb *pcb;
+
+ cpu_tlb_flushID();
+ cpu_cpwait();
+ if (vector_page < KERNBASE) {
+ struct pcb *curpcb = PCPU_GET(curpcb);
+ pcb = thread0.td_pcb;
+ if (pmap_is_current(pmap)) {
+ /*
+ * Frob the L1 entry corresponding to the vector
+ * page so that it contains the kernel pmap's domain
+ * number. This will ensure pmap_remove() does not
+ * pull the current vector page out from under us.
+ */
+ critical_enter();
+ *pcb->pcb_pl1vec = pcb->pcb_l1vec;
+ cpu_domains(pcb->pcb_dacr);
+ cpu_setttb(pcb->pcb_pagedir);
+ critical_exit();
+ }
+ pmap_remove(pmap, vector_page, vector_page + PAGE_SIZE);
+ /*
+ * Make sure cpu_switch(), et al, DTRT. This is safe to do
+ * since this process has no remaining mappings of its own.
+ */
+ curpcb->pcb_pl1vec = pcb->pcb_pl1vec;
+ curpcb->pcb_l1vec = pcb->pcb_l1vec;
+ curpcb->pcb_dacr = pcb->pcb_dacr;
+ curpcb->pcb_pagedir = pcb->pcb_pagedir;
+
+ }
+ pmap_free_l1(pmap);
+
+ dprintf("pmap_release()\n");
+}
+
+
+
+/*
+ * Helper function for pmap_grow_l2_bucket()
+ */
+static __inline int
+pmap_grow_map(vm_offset_t va, pt_entry_t cache_mode, vm_paddr_t *pap)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep;
+ vm_paddr_t pa;
+ struct vm_page *m;
+
+ m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_WIRED);
+ if (m == NULL)
+ return (1);
+ pa = VM_PAGE_TO_PHYS(m);
+
+ if (pap)
+ *pap = pa;
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ *ptep = L2_S_PROTO | pa | cache_mode | L2_S_REF;
+ pmap_set_prot(ptep, VM_PROT_READ | VM_PROT_WRITE, 0);
+ PTE_SYNC(ptep);
+ cpu_tlb_flushD_SE(va);
+ cpu_cpwait();
+
+ return (0);
+}
+
+/*
+ * This is the same as pmap_alloc_l2_bucket(), except that it is only
+ * used by pmap_growkernel().
+ */
+static __inline struct l2_bucket *
+pmap_grow_l2_bucket(pmap_t pmap, vm_offset_t va)
+{
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ struct l1_ttable *l1;
+ pd_entry_t *pl1pd;
+ u_short l1idx;
+ vm_offset_t nva;
+
+ l1idx = L1_IDX(va);
+
+ if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL) {
+ /*
+ * No mapping at this address, as there is
+ * no entry in the L1 table.
+ * Need to allocate a new l2_dtable.
+ */
+ nva = pmap_kernel_l2dtable_kva;
+ if ((nva & PAGE_MASK) == 0) {
+ /*
+ * Need to allocate a backing page
+ */
+ if (pmap_grow_map(nva, pte_l2_s_cache_mode, NULL))
+ return (NULL);
+ }
+
+ l2 = (struct l2_dtable *)nva;
+ nva += sizeof(struct l2_dtable);
+
+ if ((nva & PAGE_MASK) < (pmap_kernel_l2dtable_kva &
+ PAGE_MASK)) {
+ /*
+ * The new l2_dtable straddles a page boundary.
+ * Map in another page to cover it.
+ */
+ if (pmap_grow_map(nva, pte_l2_s_cache_mode, NULL))
+ return (NULL);
+ }
+
+ pmap_kernel_l2dtable_kva = nva;
+
+ /*
+ * Link it into the parent pmap
+ */
+ pmap->pm_l2[L2_IDX(l1idx)] = l2;
+ memset(l2, 0, sizeof(*l2));
+ }
+
+ l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+
+ /*
+ * Fetch pointer to the L2 page table associated with the address.
+ */
+ if (l2b->l2b_kva == NULL) {
+ pt_entry_t *ptep;
+
+ /*
+ * No L2 page table has been allocated. Chances are, this
+ * is because we just allocated the l2_dtable, above.
+ */
+ nva = pmap_kernel_l2ptp_kva;
+ ptep = (pt_entry_t *)nva;
+ if ((nva & PAGE_MASK) == 0) {
+ /*
+ * Need to allocate a backing page
+ */
+ if (pmap_grow_map(nva, pte_l2_s_cache_mode_pt,
+ &pmap_kernel_l2ptp_phys))
+ return (NULL);
+ }
+ memset(ptep, 0, L2_TABLE_SIZE_REAL);
+ l2->l2_occupancy++;
+ l2b->l2b_kva = ptep;
+ l2b->l2b_l1idx = l1idx;
+ l2b->l2b_phys = pmap_kernel_l2ptp_phys;
+
+ pmap_kernel_l2ptp_kva += L2_TABLE_SIZE_REAL;
+ pmap_kernel_l2ptp_phys += L2_TABLE_SIZE_REAL;
+ }
+
+ /* Distribute new L1 entry to all other L1s */
+ SLIST_FOREACH(l1, &l1_list, l1_link) {
+ pl1pd = &l1->l1_kva[L1_IDX(va)];
+ *pl1pd = l2b->l2b_phys | L1_C_DOM(PMAP_DOMAIN_KERNEL) |
+ L1_C_PROTO;
+ PTE_SYNC(pl1pd);
+ }
+ cpu_tlb_flushID_SE(va);
+ cpu_cpwait();
+
+ return (l2b);
+}
+
+
+/*
+ * grow the number of kernel page table entries, if needed
+ */
+void
+pmap_growkernel(vm_offset_t addr)
+{
+ pmap_t kpmap = pmap_kernel();
+
+ if (addr <= pmap_curmaxkvaddr)
+ return; /* we are OK */
+
+ /*
+ * whoops! we need to add kernel PTPs
+ */
+
+ /* Map 1MB at a time */
+ for (; pmap_curmaxkvaddr < addr; pmap_curmaxkvaddr += L1_S_SIZE)
+ pmap_grow_l2_bucket(kpmap, pmap_curmaxkvaddr);
+
+ kernel_vm_end = pmap_curmaxkvaddr;
+}
+
+/*
+ * Returns TRUE if the given page is mapped individually or as part of
+ * a 1MB section. Otherwise, returns FALSE.
+ */
+boolean_t
+pmap_page_is_mapped(vm_page_t m)
+{
+ boolean_t rv;
+
+ if ((m->oflags & VPO_UNMANAGED) != 0)
+ return (FALSE);
+ rw_wlock(&pvh_global_lock);
+ rv = !TAILQ_EMPTY(&m->md.pv_list) ||
+ ((m->flags & PG_FICTITIOUS) == 0 &&
+ !TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list));
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * Remove all pages from specified address space
+ * this aids process exit speeds. Also, this code
+ * is special cased for current process only, but
+ * can have the more generic (and slightly slower)
+ * mode enabled. This is much faster than pmap_remove
+ * in the case of running down an entire address space.
+ */
+void
+pmap_remove_pages(pmap_t pmap)
+{
+ struct pv_entry *pv;
+ struct l2_bucket *l2b = NULL;
+ struct pv_chunk *pc, *npc;
+ struct md_page *pvh;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep;
+ vm_page_t m, mt;
+ vm_offset_t va;
+ uint32_t inuse, bitmask;
+ int allfree, bit, field, idx;
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+
+ TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
+ allfree = 1;
+ for (field = 0; field < _NPCM; field++) {
+ inuse = ~pc->pc_map[field] & pc_freemask[field];
+ while (inuse != 0) {
+ bit = ffs(inuse) - 1;
+ bitmask = 1ul << bit;
+ idx = field * sizeof(inuse) * NBBY + bit;
+ pv = &pc->pc_pventry[idx];
+ va = pv->pv_va;
+ inuse &= ~bitmask;
+ if (pv->pv_flags & PVF_WIRED) {
+ /* Cannot remove wired pages now. */
+ allfree = 0;
+ continue;
+ }
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ l1pd = *pl1pd;
+ l2b = pmap_get_l2_bucket(pmap, va);
+ if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+ pvh = pa_to_pvh(l1pd & L1_S_FRAME);
+ TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
+ if (TAILQ_EMPTY(&pvh->pv_list)) {
+ m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME);
+ KASSERT((vm_offset_t)m >= KERNBASE,
+ ("Trying to access non-existent page "
+ "va %x l1pd %x", trunc_1mpage(va), l1pd));
+ for (mt = m; mt < &m[L2_PTE_NUM_TOTAL]; mt++) {
+ if (TAILQ_EMPTY(&mt->md.pv_list))
+ vm_page_aflag_clear(mt, PGA_WRITEABLE);
+ }
+ }
+ if (l2b != NULL) {
+ KASSERT(l2b->l2b_occupancy == L2_PTE_NUM_TOTAL,
+ ("pmap_remove_pages: l2_bucket occupancy error"));
+ pmap_free_l2_bucket(pmap, l2b, L2_PTE_NUM_TOTAL);
+ }
+ pmap->pm_stats.resident_count -= L2_PTE_NUM_TOTAL;
+ *pl1pd = 0;
+ PTE_SYNC(pl1pd);
+ } else {
+ KASSERT(l2b != NULL,
+ ("No L2 bucket in pmap_remove_pages"));
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep));
+ KASSERT((vm_offset_t)m >= KERNBASE,
+ ("Trying to access non-existent page "
+ "va %x pte %x", va, *ptep));
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+ if (TAILQ_EMPTY(&m->md.pv_list) &&
+ (m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(l2pte_pa(*ptep));
+ if (TAILQ_EMPTY(&pvh->pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ }
+ *ptep = 0;
+ PTE_SYNC(ptep);
+ pmap_free_l2_bucket(pmap, l2b, 1);
+ pmap->pm_stats.resident_count--;
+ }
+
+ /* Mark free */
+ PV_STAT(pv_entry_frees++);
+ PV_STAT(pv_entry_spare++);
+ pv_entry_count--;
+ pc->pc_map[field] |= bitmask;
+ }
+ }
+ if (allfree) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ pmap_free_pv_chunk(pc);
+ }
+
+ }
+
+ rw_wunlock(&pvh_global_lock);
+ cpu_tlb_flushID();
+ cpu_cpwait();
+ PMAP_UNLOCK(pmap);
+}
+
+
+/***************************************************
+ * Low level mapping routines.....
+ ***************************************************/
+
+#ifdef ARM_HAVE_SUPERSECTIONS
+/* Map a super section into the KVA. */
+
+void
+pmap_kenter_supersection(vm_offset_t va, uint64_t pa, int flags)
+{
+ pd_entry_t pd = L1_S_PROTO | L1_S_SUPERSEC | (pa & L1_SUP_FRAME) |
+ (((pa >> 32) & 0xf) << 20) | L1_S_PROT(PTE_KERNEL,
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) |
+ L1_S_DOM(PMAP_DOMAIN_KERNEL);
+ struct l1_ttable *l1;
+ vm_offset_t va0, va_end;
+
+ KASSERT(((va | pa) & L1_SUP_OFFSET) == 0,
+ ("Not a valid super section mapping"));
+ if (flags & SECTION_CACHE)
+ pd |= pte_l1_s_cache_mode;
+ else if (flags & SECTION_PT)
+ pd |= pte_l1_s_cache_mode_pt;
+
+ va0 = va & L1_SUP_FRAME;
+ va_end = va + L1_SUP_SIZE;
+ SLIST_FOREACH(l1, &l1_list, l1_link) {
+ va = va0;
+ for (; va < va_end; va += L1_S_SIZE) {
+ l1->l1_kva[L1_IDX(va)] = pd;
+ PTE_SYNC(&l1->l1_kva[L1_IDX(va)]);
+ }
+ }
+}
+#endif
+
+/* Map a section into the KVA. */
+
+void
+pmap_kenter_section(vm_offset_t va, vm_offset_t pa, int flags)
+{
+ pd_entry_t pd = L1_S_PROTO | pa | L1_S_PROT(PTE_KERNEL,
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) | L1_S_REF |
+ L1_S_DOM(PMAP_DOMAIN_KERNEL);
+ struct l1_ttable *l1;
+
+ KASSERT(((va | pa) & L1_S_OFFSET) == 0,
+ ("Not a valid section mapping"));
+ if (flags & SECTION_CACHE)
+ pd |= pte_l1_s_cache_mode;
+ else if (flags & SECTION_PT)
+ pd |= pte_l1_s_cache_mode_pt;
+
+ SLIST_FOREACH(l1, &l1_list, l1_link) {
+ l1->l1_kva[L1_IDX(va)] = pd;
+ PTE_SYNC(&l1->l1_kva[L1_IDX(va)]);
+ }
+ cpu_tlb_flushID_SE(va);
+ cpu_cpwait();
+}
+
+/*
+ * Make a temporary mapping for a physical address. This is only intended
+ * to be used for panic dumps.
+ */
+void *
+pmap_kenter_temporary(vm_paddr_t pa, int i)
+{
+ vm_offset_t va;
+
+ va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE);
+ pmap_kenter(va, pa);
+ return ((void *)crashdumpmap);
+}
+
+/*
+ * add a wired page to the kva
+ * note that in order for the mapping to take effect -- you
+ * should do a invltlb after doing the pmap_kenter...
+ */
+static PMAP_INLINE void
+pmap_kenter_internal(vm_offset_t va, vm_offset_t pa, int flags)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep;
+ pt_entry_t opte;
+
+ PDEBUG(1, printf("pmap_kenter: va = %08x, pa = %08x\n",
+ (uint32_t) va, (uint32_t) pa));
+
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ if (l2b == NULL)
+ l2b = pmap_grow_l2_bucket(pmap_kernel(), va);
+ KASSERT(l2b != NULL, ("No L2 Bucket"));
+
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ opte = *ptep;
+
+ if (flags & KENTER_CACHE)
+ *ptep = L2_S_PROTO | l2s_mem_types[PTE_CACHE] | pa | L2_S_REF;
+ else if (flags & KENTER_DEVICE)
+ *ptep = L2_S_PROTO | l2s_mem_types[PTE_DEVICE] | pa | L2_S_REF;
+ else
+ *ptep = L2_S_PROTO | l2s_mem_types[PTE_NOCACHE] | pa | L2_S_REF;
+
+ if (flags & KENTER_CACHE) {
+ pmap_set_prot(ptep, VM_PROT_READ | VM_PROT_WRITE,
+ flags & KENTER_USER);
+ } else {
+ pmap_set_prot(ptep, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
+ 0);
+ }
+
+ PTE_SYNC(ptep);
+ if (l2pte_valid(opte)) {
+ if (L2_S_EXECUTABLE(opte) || L2_S_EXECUTABLE(*ptep))
+ cpu_tlb_flushID_SE(va);
+ else
+ cpu_tlb_flushD_SE(va);
+ } else {
+ if (opte == 0)
+ l2b->l2b_occupancy++;
+ }
+ cpu_cpwait();
+
+ PDEBUG(1, printf("pmap_kenter: pte = %08x, opte = %08x, npte = %08x\n",
+ (uint32_t) ptep, opte, *ptep));
+}
+
+void
+pmap_kenter(vm_offset_t va, vm_paddr_t pa)
+{
+ pmap_kenter_internal(va, pa, KENTER_CACHE);
+}
+
+void
+pmap_kenter_nocache(vm_offset_t va, vm_paddr_t pa)
+{
+
+ pmap_kenter_internal(va, pa, 0);
+}
+
+void
+pmap_kenter_device(vm_offset_t va, vm_paddr_t pa)
+{
+
+ pmap_kenter_internal(va, pa, KENTER_DEVICE);
+}
+
+void
+pmap_kenter_user(vm_offset_t va, vm_paddr_t pa)
+{
+
+ pmap_kenter_internal(va, pa, KENTER_CACHE|KENTER_USER);
+ /*
+ * Call pmap_fault_fixup now, to make sure we'll have no exception
+ * at the first use of the new address, or bad things will happen,
+ * as we use one of these addresses in the exception handlers.
+ */
+ pmap_fault_fixup(pmap_kernel(), va, VM_PROT_READ|VM_PROT_WRITE, 1);
+}
+
+vm_paddr_t
+pmap_kextract(vm_offset_t va)
+{
+
+ if (kernel_vm_end == 0)
+ return (0);
+ return (pmap_extract_locked(kernel_pmap, va));
+}
+
+/*
+ * remove a page from the kernel pagetables
+ */
+void
+pmap_kremove(vm_offset_t va)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, opte;
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ if (!l2b)
+ return;
+ KASSERT(l2b != NULL, ("No L2 Bucket"));
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ opte = *ptep;
+ if (l2pte_valid(opte)) {
+ va = va & ~PAGE_MASK;
+ *ptep = 0;
+ PTE_SYNC(ptep);
+ if (L2_S_EXECUTABLE(opte))
+ cpu_tlb_flushID_SE(va);
+ else
+ cpu_tlb_flushD_SE(va);
+ cpu_cpwait();
+ }
+}
+
+
+/*
+ * Used to map a range of physical addresses into kernel
+ * virtual address space.
+ *
+ * The value passed in '*virt' is a suggested virtual address for
+ * the mapping. Architectures which can support a direct-mapped
+ * physical to virtual region can return the appropriate address
+ * within that region, leaving '*virt' unchanged. Other
+ * architectures should map the pages starting at '*virt' and
+ * update '*virt' with the first usable address after the mapped
+ * region.
+ */
+vm_offset_t
+pmap_map(vm_offset_t *virt, vm_offset_t start, vm_offset_t end, int prot)
+{
+ vm_offset_t sva = *virt;
+ vm_offset_t va = sva;
+
+ PDEBUG(1, printf("pmap_map: virt = %08x, start = %08x, end = %08x, "
+ "prot = %d\n", (uint32_t) *virt, (uint32_t) start, (uint32_t) end,
+ prot));
+
+ while (start < end) {
+ pmap_kenter(va, start);
+ va += PAGE_SIZE;
+ start += PAGE_SIZE;
+ }
+ *virt = va;
+ return (sva);
+}
+
+/*
+ * Add a list of wired pages to the kva
+ * this routine is only used for temporary
+ * kernel mappings that do not need to have
+ * page modification or references recorded.
+ * Note that old mappings are simply written
+ * over. The page *must* be wired.
+ */
+void
+pmap_qenter(vm_offset_t va, vm_page_t *m, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ pmap_kenter_internal(va, VM_PAGE_TO_PHYS(m[i]),
+ KENTER_CACHE);
+ va += PAGE_SIZE;
+ }
+}
+
+
+/*
+ * this routine jerks page mappings from the
+ * kernel -- it is meant only for temporary mappings.
+ */
+void
+pmap_qremove(vm_offset_t va, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (vtophys(va))
+ pmap_kremove(va);
+
+ va += PAGE_SIZE;
+ }
+}
+
+
+/*
+ * pmap_object_init_pt preloads the ptes for a given object
+ * into the specified pmap. This eliminates the blast of soft
+ * faults on process startup and immediately after an mmap.
+ */
+void
+pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
+ vm_pindex_t pindex, vm_size_t size)
+{
+
+ VM_OBJECT_ASSERT_WLOCKED(object);
+ KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
+ ("pmap_object_init_pt: non-device object"));
+}
+
+
+/*
+ * pmap_is_prefaultable:
+ *
+ * Return whether or not the specified virtual address is elgible
+ * for prefault.
+ */
+boolean_t
+pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
+{
+ pd_entry_t *pdep;
+ pt_entry_t *ptep;
+
+ if (!pmap_get_pde_pte(pmap, addr, &pdep, &ptep))
+ return (FALSE);
+ KASSERT((pdep != NULL && (l1pte_section_p(*pdep) || ptep != NULL)),
+ ("Valid mapping but no pte ?"));
+ if (*pdep != 0 && !l1pte_section_p(*pdep))
+ if (*ptep == 0)
+ return (TRUE);
+ return (FALSE);
+}
+
+/*
+ * Fetch pointers to the PDE/PTE for the given pmap/VA pair.
+ * Returns TRUE if the mapping exists, else FALSE.
+ *
+ * NOTE: This function is only used by a couple of arm-specific modules.
+ * It is not safe to take any pmap locks here, since we could be right
+ * in the middle of debugging the pmap anyway...
+ *
+ * It is possible for this routine to return FALSE even though a valid
+ * mapping does exist. This is because we don't lock, so the metadata
+ * state may be inconsistent.
+ *
+ * NOTE: We can return a NULL *ptp in the case where the L1 pde is
+ * a "section" mapping.
+ */
+boolean_t
+pmap_get_pde_pte(pmap_t pmap, vm_offset_t va, pd_entry_t **pdp,
+ pt_entry_t **ptp)
+{
+ struct l2_dtable *l2;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep;
+ u_short l1idx;
+
+ if (pmap->pm_l1 == NULL)
+ return (FALSE);
+
+ l1idx = L1_IDX(va);
+ *pdp = pl1pd = &pmap->pm_l1->l1_kva[l1idx];
+ l1pd = *pl1pd;
+
+ if (l1pte_section_p(l1pd)) {
+ *ptp = NULL;
+ return (TRUE);
+ }
+
+ if (pmap->pm_l2 == NULL)
+ return (FALSE);
+
+ l2 = pmap->pm_l2[L2_IDX(l1idx)];
+
+ if (l2 == NULL ||
+ (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
+ return (FALSE);
+ }
+
+ *ptp = &ptep[l2pte_index(va)];
+ return (TRUE);
+}
+
+/*
+ * Routine: pmap_remove_all
+ * Function:
+ * Removes this physical page from
+ * all physical maps in which it resides.
+ * Reflects back modify bits to the pager.
+ *
+ * Notes:
+ * Original versions of this routine were very
+ * inefficient because they iteratively called
+ * pmap_remove (slow...)
+ */
+void
+pmap_remove_all(vm_page_t m)
+{
+ struct md_page *pvh;
+ pv_entry_t pv;
+ pmap_t pmap;
+ pt_entry_t *ptep;
+ struct l2_bucket *l2b;
+ boolean_t flush = FALSE;
+ pmap_t curpmap;
+ u_int is_exec = 0;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_remove_all: page %p is not managed", m));
+ rw_wlock(&pvh_global_lock);
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ goto small_mappings;
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pd_entry_t *pl1pd;
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)];
+ KASSERT((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO,
+ ("pmap_remove_all: valid section mapping expected"));
+ (void)pmap_demote_section(pmap, pv->pv_va);
+ PMAP_UNLOCK(pmap);
+ }
+small_mappings:
+ curpmap = vmspace_pmap(curproc->p_vmspace);
+ while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
+ pmap = PV_PMAP(pv);
+ if (flush == FALSE && (pmap == curpmap ||
+ pmap == pmap_kernel()))
+ flush = TRUE;
+
+ PMAP_LOCK(pmap);
+ l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
+ KASSERT(l2b != NULL, ("No l2 bucket"));
+ ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+ is_exec |= PTE_BEEN_EXECD(*ptep);
+ *ptep = 0;
+ if (pmap_is_current(pmap))
+ PTE_SYNC(ptep);
+ pmap_free_l2_bucket(pmap, l2b, 1);
+ pmap->pm_stats.resident_count--;
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+ if (pv->pv_flags & PVF_WIRED)
+ pmap->pm_stats.wired_count--;
+ pmap_free_pv_entry(pmap, pv);
+ PMAP_UNLOCK(pmap);
+ }
+
+ if (flush) {
+ if (is_exec)
+ cpu_tlb_flushID();
+ else
+ cpu_tlb_flushD();
+ cpu_cpwait();
+ }
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ rw_wunlock(&pvh_global_lock);
+}
+
+int
+pmap_change_attr(vm_offset_t sva, vm_size_t len, int mode)
+{
+ vm_offset_t base, offset, tmpva;
+ vm_size_t size;
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, pte;
+ vm_offset_t next_bucket;
+
+ PMAP_LOCK(kernel_pmap);
+
+ base = trunc_page(sva);
+ offset = sva & PAGE_MASK;
+ size = roundup(offset + len, PAGE_SIZE);
+
+#ifdef checkit
+ /*
+ * Only supported on kernel virtual addresses, including the direct
+ * map but excluding the recursive map.
+ */
+ if (base < DMAP_MIN_ADDRESS) {
+ PMAP_UNLOCK(kernel_pmap);
+ return (EINVAL);
+ }
+#endif
+ for (tmpva = base; tmpva < base + size; ) {
+ next_bucket = L2_NEXT_BUCKET(tmpva);
+ if (next_bucket > base + size)
+ next_bucket = base + size;
+
+ l2b = pmap_get_l2_bucket(kernel_pmap, tmpva);
+ if (l2b == NULL) {
+ tmpva = next_bucket;
+ continue;
+ }
+
+ ptep = &l2b->l2b_kva[l2pte_index(tmpva)];
+
+ if (*ptep == 0) {
+ PMAP_UNLOCK(kernel_pmap);
+ return(EINVAL);
+ }
+
+ pte = *ptep &~ L2_S_CACHE_MASK;
+ cpu_idcache_wbinv_range(tmpva, PAGE_SIZE);
+ pmap_l2cache_wbinv_range(tmpva, pte & L2_S_FRAME, PAGE_SIZE);
+ *ptep = pte;
+ cpu_tlb_flushID_SE(tmpva);
+ cpu_cpwait();
+
+ dprintf("%s: for va:%x ptep:%x pte:%x\n",
+ __func__, tmpva, (uint32_t)ptep, pte);
+ tmpva += PAGE_SIZE;
+ }
+
+ PMAP_UNLOCK(kernel_pmap);
+
+ return (0);
+}
+
+/*
+ * Set the physical protection on the
+ * specified range of this map as requested.
+ */
+void
+pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
+{
+ struct l2_bucket *l2b;
+ struct md_page *pvh;
+ struct pv_entry *pve;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep, pte;
+ vm_offset_t next_bucket;
+ u_int is_exec, is_refd;
+ int flush;
+
+ if ((prot & VM_PROT_READ) == 0) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
+
+ if (prot & VM_PROT_WRITE) {
+ /*
+ * If this is a read->write transition, just ignore it and let
+ * vm_fault() take care of it later.
+ */
+ return;
+ }
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+
+ /*
+ * OK, at this point, we know we're doing write-protect operation.
+ * If the pmap is active, write-back the range.
+ */
+
+ flush = ((eva - sva) >= (PAGE_SIZE * 4)) ? 0 : -1;
+ is_exec = is_refd = 0;
+
+ while (sva < eva) {
+ next_bucket = L2_NEXT_BUCKET(sva);
+ /*
+ * Check for large page.
+ */
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)];
+ l1pd = *pl1pd;
+ if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+ KASSERT(pmap != pmap_kernel(),
+ ("pmap_protect: trying to modify "
+ "kernel section protections"));
+ /*
+ * Are we protecting the entire large page? If not,
+ * demote the mapping and fall through.
+ */
+ if (sva + L1_S_SIZE == L2_NEXT_BUCKET(sva) &&
+ eva >= L2_NEXT_BUCKET(sva)) {
+ l1pd &= ~(L1_S_PROT_MASK | L1_S_XN);
+ if (!(prot & VM_PROT_EXECUTE))
+ *pl1pd |= L1_S_XN;
+ /*
+ * At this point we are always setting
+ * write-protect bit.
+ */
+ l1pd |= L1_S_APX;
+ /* All managed superpages are user pages. */
+ l1pd |= L1_S_PROT_U;
+ *pl1pd = l1pd;
+ PTE_SYNC(pl1pd);
+ pvh = pa_to_pvh(l1pd & L1_S_FRAME);
+ pve = pmap_find_pv(pvh, pmap,
+ trunc_1mpage(sva));
+ pve->pv_flags &= ~PVF_WRITE;
+ sva = next_bucket;
+ continue;
+ } else if (!pmap_demote_section(pmap, sva)) {
+ /* The large page mapping was destroyed. */
+ sva = next_bucket;
+ continue;
+ }
+ }
+ if (next_bucket > eva)
+ next_bucket = eva;
+ l2b = pmap_get_l2_bucket(pmap, sva);
+ if (l2b == NULL) {
+ sva = next_bucket;
+ continue;
+ }
+
+ ptep = &l2b->l2b_kva[l2pte_index(sva)];
+
+ while (sva < next_bucket) {
+ if ((pte = *ptep) != 0 && L2_S_WRITABLE(pte)) {
+ struct vm_page *m;
+
+ m = PHYS_TO_VM_PAGE(l2pte_pa(pte));
+ pmap_set_prot(ptep, prot,
+ !(pmap == pmap_kernel()));
+ PTE_SYNC(ptep);
+
+ pmap_modify_pv(m, pmap, sva, PVF_WRITE, 0);
+
+ if (flush >= 0) {
+ flush++;
+ is_exec |= PTE_BEEN_EXECD(pte);
+ is_refd |= PTE_BEEN_REFD(pte);
+ } else {
+ if (PTE_BEEN_EXECD(pte))
+ cpu_tlb_flushID_SE(sva);
+ else if (PTE_BEEN_REFD(pte))
+ cpu_tlb_flushD_SE(sva);
+ }
+ }
+
+ sva += PAGE_SIZE;
+ ptep++;
+ }
+ }
+
+
+ if (flush) {
+ if (is_exec)
+ cpu_tlb_flushID();
+ else
+ if (is_refd)
+ cpu_tlb_flushD();
+ cpu_cpwait();
+ }
+ rw_wunlock(&pvh_global_lock);
+
+ PMAP_UNLOCK(pmap);
+}
+
+
+/*
+ * Insert the given physical page (p) at
+ * the specified virtual address (v) in the
+ * target physical map with the protection requested.
+ *
+ * If specified, the page will be wired down, meaning
+ * that the related pte can not be reclaimed.
+ *
+ * NB: This is the only routine which MAY NOT lazy-evaluate
+ * or lose information. That is, this routine must actually
+ * insert this page into the given map NOW.
+ */
+
+int
+pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ u_int flags, int8_t psind __unused)
+{
+ struct l2_bucket *l2b;
+ int rv;
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ rv = pmap_enter_locked(pmap, va, m, prot, flags);
+ if (rv == KERN_SUCCESS) {
+ /*
+ * If both the l2b_occupancy and the reservation are fully
+ * populated, then attempt promotion.
+ */
+ l2b = pmap_get_l2_bucket(pmap, va);
+ if (l2b != NULL && l2b->l2b_occupancy == L2_PTE_NUM_TOTAL &&
+ sp_enabled && (m->flags & PG_FICTITIOUS) == 0 &&
+ vm_reserv_level_iffullpop(m) == 0)
+ pmap_promote_section(pmap, va);
+ }
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * The pvh global and pmap locks must be held.
+ */
+static int
+pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ u_int flags)
+{
+ struct l2_bucket *l2b = NULL;
+ struct vm_page *om;
+ struct pv_entry *pve = NULL;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep, npte, opte;
+ u_int nflags;
+ u_int is_exec, is_refd;
+ vm_paddr_t pa;
+ u_char user;
+
+ PMAP_ASSERT_LOCKED(pmap);
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ if (va == vector_page) {
+ pa = systempage.pv_pa;
+ m = NULL;
+ } else {
+ if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
+ VM_OBJECT_ASSERT_LOCKED(m->object);
+ pa = VM_PAGE_TO_PHYS(m);
+ }
+
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ if ((va < VM_MAXUSER_ADDRESS) &&
+ (*pl1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+ (void)pmap_demote_section(pmap, va);
+ }
+
+ user = 0;
+ /*
+ * Make sure userland mappings get the right permissions
+ */
+ if (pmap != pmap_kernel() && va != vector_page)
+ user = 1;
+
+ nflags = 0;
+
+ if (prot & VM_PROT_WRITE)
+ nflags |= PVF_WRITE;
+ if ((flags & PMAP_ENTER_WIRED) != 0)
+ nflags |= PVF_WIRED;
+
+ PDEBUG(1, printf("pmap_enter: pmap = %08x, va = %08x, m = %08x, "
+ "prot = %x, flags = %x\n", (uint32_t) pmap, va, (uint32_t) m,
+ prot, flags));
+
+ if (pmap == pmap_kernel()) {
+ l2b = pmap_get_l2_bucket(pmap, va);
+ if (l2b == NULL)
+ l2b = pmap_grow_l2_bucket(pmap, va);
+ } else {
+do_l2b_alloc:
+ l2b = pmap_alloc_l2_bucket(pmap, va);
+ if (l2b == NULL) {
+ if ((flags & PMAP_ENTER_NOSLEEP) == 0) {
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+ VM_WAIT;
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ goto do_l2b_alloc;
+ }
+ return (KERN_RESOURCE_SHORTAGE);
+ }
+ }
+
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
+ panic("pmap_enter: attempt to enter on 1MB page, va: %#x", va);
+
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+
+ opte = *ptep;
+ npte = pa;
+ is_exec = is_refd = 0;
+
+ if (opte) {
+ if (l2pte_pa(opte) == pa) {
+ /*
+ * We're changing the attrs of an existing mapping.
+ */
+ if (m != NULL)
+ pmap_modify_pv(m, pmap, va,
+ PVF_WRITE | PVF_WIRED, nflags);
+ is_exec |= PTE_BEEN_EXECD(opte);
+ is_refd |= PTE_BEEN_REFD(opte);
+ goto validate;
+ }
+ if ((om = PHYS_TO_VM_PAGE(l2pte_pa(opte)))) {
+ /*
+ * Replacing an existing mapping with a new one.
+ * It is part of our managed memory so we
+ * must remove it from the PV list
+ */
+ if ((pve = pmap_remove_pv(om, pmap, va))) {
+ is_exec |= PTE_BEEN_EXECD(opte);
+ is_refd |= PTE_BEEN_REFD(opte);
+
+ if (m && ((m->oflags & VPO_UNMANAGED)))
+ pmap_free_pv_entry(pmap, pve);
+ }
+ }
+
+ } else {
+ /*
+ * Keep the stats up to date
+ */
+ l2b->l2b_occupancy++;
+ pmap->pm_stats.resident_count++;
+ }
+
+ /*
+ * Enter on the PV list if part of our managed memory.
+ */
+ if ((m && !(m->oflags & VPO_UNMANAGED))) {
+ if ((!pve) && (pve = pmap_get_pv_entry(pmap, FALSE)) == NULL)
+ panic("pmap_enter: no pv entries");
+
+ KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
+ ("pmap_enter: managed mapping within the clean submap"));
+ KASSERT(pve != NULL, ("No pv"));
+ pmap_enter_pv(m, pve, pmap, va, nflags);
+ }
+
+validate:
+ /* Make the new PTE valid */
+ npte |= L2_S_PROTO;
+#ifdef SMP
+ npte |= L2_SHARED;
+#endif
+ /* Set defaults first - kernel read access */
+ npte |= L2_APX;
+ npte |= L2_S_PROT_R;
+ /* Set "referenced" flag */
+ npte |= L2_S_REF;
+
+ /* Now tune APs as desired */
+ if (user)
+ npte |= L2_S_PROT_U;
+ /*
+ * If this is not a vector_page
+ * then continue setting mapping parameters
+ */
+ if (m != NULL) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
+ if (prot & (VM_PROT_ALL)) {
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ } else {
+ /*
+ * Need to do page referenced emulation.
+ */
+ npte &= ~L2_S_REF;
+ }
+ }
+
+ if (prot & VM_PROT_WRITE) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
+ vm_page_aflag_set(m, PGA_WRITEABLE);
+ /*
+ * XXX: Skip modified bit emulation for now.
+ * The emulation reveals problems
+ * that result in random failures
+ * during memory allocation on some
+ * platforms.
+ * Therefore, the page is marked RW
+ * immediately.
+ */
+ npte &= ~(L2_APX);
+ vm_page_dirty(m);
+ } else
+ npte &= ~(L2_APX);
+ }
+ if (!(prot & VM_PROT_EXECUTE))
+ npte |= L2_XN;
+
+ if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
+ npte |= pte_l2_s_cache_mode;
+ }
+
+ CTR5(KTR_PMAP,"enter: pmap:%p va:%x prot:%x pte:%x->%x",
+ pmap, va, prot, opte, npte);
+ /*
+ * If this is just a wiring change, the two PTEs will be
+ * identical, so there's no need to update the page table.
+ */
+ if (npte != opte) {
+ boolean_t is_cached = pmap_is_current(pmap);
+
+ *ptep = npte;
+ PTE_SYNC(ptep);
+ if (is_cached) {
+ /*
+ * We only need to frob the cache/tlb if this pmap
+ * is current
+ */
+ if (L1_IDX(va) != L1_IDX(vector_page) &&
+ l2pte_valid(npte)) {
+ /*
+ * This mapping is likely to be accessed as
+ * soon as we return to userland. Fix up the
+ * L1 entry to avoid taking another
+ * page/domain fault.
+ */
+ l1pd = l2b->l2b_phys |
+ L1_C_DOM(pmap->pm_domain) | L1_C_PROTO;
+ if (*pl1pd != l1pd) {
+ *pl1pd = l1pd;
+ PTE_SYNC(pl1pd);
+ }
+ }
+ }
+
+ if (is_exec)
+ cpu_tlb_flushID_SE(va);
+ else if (is_refd)
+ cpu_tlb_flushD_SE(va);
+ cpu_cpwait();
+ }
+
+ if ((pmap != pmap_kernel()) && (pmap == &curproc->p_vmspace->vm_pmap))
+ cpu_icache_sync_range(va, PAGE_SIZE);
+ return (KERN_SUCCESS);
+}
+
+/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start. This page is
+ * mapped at the given virtual address start. Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object. The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end. Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
+void
+pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
+ vm_page_t m_start, vm_prot_t prot)
+{
+ vm_offset_t va;
+ vm_page_t m;
+ vm_pindex_t diff, psize;
+
+ VM_OBJECT_ASSERT_LOCKED(m_start->object);
+
+ psize = atop(end - start);
+ m = m_start;
+ prot &= VM_PROT_READ | VM_PROT_EXECUTE;
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+ va = start + ptoa(diff);
+ if ((va & L1_S_OFFSET) == 0 && L2_NEXT_BUCKET(va) <= end &&
+ m->psind == 1 && sp_enabled &&
+ pmap_enter_section(pmap, va, m, prot))
+ m = &m[L1_S_SIZE / PAGE_SIZE - 1];
+ else
+ pmap_enter_locked(pmap, va, m, prot,
+ PMAP_ENTER_NOSLEEP);
+ m = TAILQ_NEXT(m, listq);
+ }
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * this code makes some *MAJOR* assumptions:
+ * 1. Current pmap & pmap exists.
+ * 2. Not wired.
+ * 3. Read access.
+ * 4. No page table pages.
+ * but is *MUCH* faster than pmap_enter...
+ */
+
+void
+pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+{
+
+ prot &= VM_PROT_READ | VM_PROT_EXECUTE;
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ pmap_enter_locked(pmap, va, m, prot, PMAP_ENTER_NOSLEEP);
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * Clear the wired attribute from the mappings for the specified range of
+ * addresses in the given pmap. Every valid mapping within that range
+ * must have the wired attribute set. In contrast, invalid mappings
+ * cannot have the wired attribute set, so they are ignored.
+ *
+ * XXX Wired mappings of unmanaged pages cannot be counted by this pmap
+ * implementation.
+ */
+void
+pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+ struct l2_bucket *l2b;
+ struct md_page *pvh;
+ pd_entry_t l1pd;
+ pt_entry_t *ptep, pte;
+ pv_entry_t pv;
+ vm_offset_t next_bucket;
+ vm_paddr_t pa;
+ vm_page_t m;
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ while (sva < eva) {
+ next_bucket = L2_NEXT_BUCKET(sva);
+ l1pd = pmap->pm_l1->l1_kva[L1_IDX(sva)];
+ if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+ pa = l1pd & L1_S_FRAME;
+ m = PHYS_TO_VM_PAGE(pa);
+ KASSERT(m != NULL && (m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_unwire: unmanaged 1mpage %p", m));
+ pvh = pa_to_pvh(pa);
+ pv = pmap_find_pv(pvh, pmap, trunc_1mpage(sva));
+ if ((pv->pv_flags & PVF_WIRED) == 0)
+ panic("pmap_unwire: pv %p isn't wired", pv);
+
+ /*
+ * Are we unwiring the entire large page? If not,
+ * demote the mapping and fall through.
+ */
+ if (sva + L1_S_SIZE == next_bucket &&
+ eva >= next_bucket) {
+ pv->pv_flags &= ~PVF_WIRED;
+ pmap->pm_stats.wired_count -= L2_PTE_NUM_TOTAL;
+ sva = next_bucket;
+ continue;
+ } else if (!pmap_demote_section(pmap, sva))
+ panic("pmap_unwire: demotion failed");
+ }
+ if (next_bucket > eva)
+ next_bucket = eva;
+ l2b = pmap_get_l2_bucket(pmap, sva);
+ if (l2b == NULL) {
+ sva = next_bucket;
+ continue;
+ }
+ for (ptep = &l2b->l2b_kva[l2pte_index(sva)]; sva < next_bucket;
+ sva += PAGE_SIZE, ptep++) {
+ if ((pte = *ptep) == 0 ||
+ (m = PHYS_TO_VM_PAGE(l2pte_pa(pte))) == NULL ||
+ (m->oflags & VPO_UNMANAGED) != 0)
+ continue;
+ pv = pmap_find_pv(&m->md, pmap, sva);
+ if ((pv->pv_flags & PVF_WIRED) == 0)
+ panic("pmap_unwire: pv %p isn't wired", pv);
+ pv->pv_flags &= ~PVF_WIRED;
+ pmap->pm_stats.wired_count--;
+ }
+ }
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
+
+
+/*
+ * Copy the range specified by src_addr/len
+ * from the source map to the range dst_addr/len
+ * in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+void
+pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
+ vm_size_t len, vm_offset_t src_addr)
+{
+}
+
+
+/*
+ * Routine: pmap_extract
+ * Function:
+ * Extract the physical page address associated
+ * with the given map/virtual_address pair.
+ */
+vm_paddr_t
+pmap_extract(pmap_t pmap, vm_offset_t va)
+{
+ vm_paddr_t pa;
+
+ if (kernel_vm_end != 0)
+ PMAP_LOCK(pmap);
+ pa = pmap_extract_locked(pmap, va);
+ if (kernel_vm_end != 0)
+ PMAP_UNLOCK(pmap);
+ return (pa);
+}
+
+static vm_paddr_t
+pmap_extract_locked(pmap_t pmap, vm_offset_t va)
+{
+ struct l2_dtable *l2;
+ pd_entry_t l1pd;
+ pt_entry_t *ptep, pte;
+ vm_paddr_t pa;
+ u_int l1idx;
+
+ if (kernel_vm_end != 0 && pmap != kernel_pmap)
+ PMAP_ASSERT_LOCKED(pmap);
+ l1idx = L1_IDX(va);
+ l1pd = pmap->pm_l1->l1_kva[l1idx];
+ if (l1pte_section_p(l1pd)) {
+ /* XXX: what to do about the bits > 32 ? */
+ if (l1pd & L1_S_SUPERSEC)
+ pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
+ else
+ pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
+ } else {
+ /*
+ * Note that we can't rely on the validity of the L1
+ * descriptor as an indication that a mapping exists.
+ * We have to look it up in the L2 dtable.
+ */
+ l2 = pmap->pm_l2[L2_IDX(l1idx)];
+ if (l2 == NULL ||
+ (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL)
+ return (0);
+ pte = ptep[l2pte_index(va)];
+ if (pte == 0)
+ return (0);
+ switch (pte & L2_TYPE_MASK) {
+ case L2_TYPE_L:
+ pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
+ break;
+ default:
+ pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
+ break;
+ }
+ }
+ return (pa);
+}
+
+/*
+ * Atomically extract and hold the physical page with the given
+ * pmap and virtual address pair if that mapping permits the given
+ * protection.
+ *
+ */
+vm_page_t
+pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
+{
+ struct l2_dtable *l2;
+ pd_entry_t l1pd;
+ pt_entry_t *ptep, pte;
+ vm_paddr_t pa, paddr;
+ vm_page_t m = NULL;
+ u_int l1idx;
+ l1idx = L1_IDX(va);
+ paddr = 0;
+
+ PMAP_LOCK(pmap);
+retry:
+ l1pd = pmap->pm_l1->l1_kva[l1idx];
+ if (l1pte_section_p(l1pd)) {
+ /* XXX: what to do about the bits > 32 ? */
+ if (l1pd & L1_S_SUPERSEC)
+ pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
+ else
+ pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
+ if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
+ goto retry;
+ if (L1_S_WRITABLE(l1pd) || (prot & VM_PROT_WRITE) == 0) {
+ m = PHYS_TO_VM_PAGE(pa);
+ vm_page_hold(m);
+ }
+ } else {
+ /*
+ * Note that we can't rely on the validity of the L1
+ * descriptor as an indication that a mapping exists.
+ * We have to look it up in the L2 dtable.
+ */
+ l2 = pmap->pm_l2[L2_IDX(l1idx)];
+
+ if (l2 == NULL ||
+ (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
+ PMAP_UNLOCK(pmap);
+ return (NULL);
+ }
+
+ ptep = &ptep[l2pte_index(va)];
+ pte = *ptep;
+
+ if (pte == 0) {
+ PMAP_UNLOCK(pmap);
+ return (NULL);
+ } else if ((prot & VM_PROT_WRITE) && (pte & L2_APX)) {
+ PMAP_UNLOCK(pmap);
+ return (NULL);
+ } else {
+ switch (pte & L2_TYPE_MASK) {
+ case L2_TYPE_L:
+ panic("extract and hold section mapping");
+ break;
+ default:
+ pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
+ break;
+ }
+ if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
+ goto retry;
+ m = PHYS_TO_VM_PAGE(pa);
+ vm_page_hold(m);
+ }
+
+ }
+
+ PMAP_UNLOCK(pmap);
+ PA_UNLOCK_COND(paddr);
+ return (m);
+}
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+
+int
+pmap_pinit(pmap_t pmap)
+{
+ PDEBUG(1, printf("pmap_pinit: pmap = %08x\n", (uint32_t) pmap));
+
+ pmap_alloc_l1(pmap);
+ bzero(pmap->pm_l2, sizeof(pmap->pm_l2));
+
+ CPU_ZERO(&pmap->pm_active);
+
+ TAILQ_INIT(&pmap->pm_pvchunk);
+ bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
+ pmap->pm_stats.resident_count = 1;
+ if (vector_page < KERNBASE) {
+ pmap_enter(pmap, vector_page,
+ PHYS_TO_VM_PAGE(systempage.pv_pa), VM_PROT_READ,
+ PMAP_ENTER_WIRED, 0);
+ }
+ return (1);
+}
+
+
+/***************************************************
+ * Superpage management routines.
+ ***************************************************/
+
+static PMAP_INLINE struct pv_entry *
+pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+{
+ pv_entry_t pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+
+ pv = pmap_find_pv(pvh, pmap, va);
+ if (pv != NULL)
+ TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
+
+ return (pv);
+}
+
+static void
+pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+{
+ pv_entry_t pv;
+
+ pv = pmap_pvh_remove(pvh, pmap, va);
+ KASSERT(pv != NULL, ("pmap_pvh_free: pv not found"));
+ pmap_free_pv_entry(pmap, pv);
+}
+
+static boolean_t
+pmap_pv_insert_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+ struct md_page *pvh;
+ pv_entry_t pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ if (pv_entry_count < pv_entry_high_water &&
+ (pv = pmap_get_pv_entry(pmap, TRUE)) != NULL) {
+ pv->pv_va = va;
+ pvh = pa_to_pvh(pa);
+ TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
+ return (TRUE);
+ } else
+ return (FALSE);
+}
+
+/*
+ * Create the pv entries for each of the pages within a superpage.
+ */
+static void
+pmap_pv_demote_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+ struct md_page *pvh;
+ pv_entry_t pve, pv;
+ vm_offset_t va_last;
+ vm_page_t m;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ KASSERT((pa & L1_S_OFFSET) == 0,
+ ("pmap_pv_demote_section: pa is not 1mpage aligned"));
+
+ /*
+ * Transfer the 1mpage's pv entry for this mapping to the first
+ * page's pv list.
+ */
+ pvh = pa_to_pvh(pa);
+ va = trunc_1mpage(va);
+ pv = pmap_pvh_remove(pvh, pmap, va);
+ KASSERT(pv != NULL, ("pmap_pv_demote_section: pv not found"));
+ m = PHYS_TO_VM_PAGE(pa);
+ TAILQ_INSERT_HEAD(&m->md.pv_list, pv, pv_list);
+ /* Instantiate the remaining pv entries. */
+ va_last = L2_NEXT_BUCKET(va) - PAGE_SIZE;
+ do {
+ m++;
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_pv_demote_section: page %p is not managed", m));
+ va += PAGE_SIZE;
+ pve = pmap_get_pv_entry(pmap, FALSE);
+ pmap_enter_pv(m, pve, pmap, va, pv->pv_flags);
+ } while (va < va_last);
+}
+
+static void
+pmap_pv_promote_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+ struct md_page *pvh;
+ pv_entry_t pv;
+ vm_offset_t va_last;
+ vm_page_t m;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ KASSERT((pa & L1_S_OFFSET) == 0,
+ ("pmap_pv_promote_section: pa is not 1mpage aligned"));
+
+ /*
+ * Transfer the first page's pv entry for this mapping to the
+ * 1mpage's pv list. Aside from avoiding the cost of a call
+ * to get_pv_entry(), a transfer avoids the possibility that
+ * get_pv_entry() calls pmap_pv_reclaim() and that pmap_pv_reclaim()
+ * removes one of the mappings that is being promoted.
+ */
+ m = PHYS_TO_VM_PAGE(pa);
+ va = trunc_1mpage(va);
+ pv = pmap_pvh_remove(&m->md, pmap, va);
+ KASSERT(pv != NULL, ("pmap_pv_promote_section: pv not found"));
+ pvh = pa_to_pvh(pa);
+ TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
+ /* Free the remaining pv entries in the newly mapped section pages */
+ va_last = L2_NEXT_BUCKET(va) - PAGE_SIZE;
+ do {
+ m++;
+ va += PAGE_SIZE;
+ /*
+ * Don't care the flags, first pv contains sufficient
+ * information for all of the pages so nothing is really lost.
+ */
+ pmap_pvh_free(&m->md, pmap, va);
+ } while (va < va_last);
+}
+
+/*
+ * Tries to create a 1MB page mapping. Returns TRUE if successful and
+ * FALSE otherwise. Fails if (1) page is unmanageg, kernel pmap or vectors
+ * page, (2) a mapping already exists at the specified virtual address, or
+ * (3) a pv entry cannot be allocated without reclaiming another pv entry.
+ */
+static boolean_t
+pmap_enter_section(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+{
+ pd_entry_t *pl1pd;
+ vm_offset_t pa;
+ struct l2_bucket *l2b;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_ASSERT_LOCKED(pmap);
+
+ /* Skip kernel, vectors page and unmanaged mappings */
+ if ((pmap == pmap_kernel()) || (L1_IDX(va) == L1_IDX(vector_page)) ||
+ ((m->oflags & VPO_UNMANAGED) != 0)) {
+ CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx"
+ " in pmap %p", va, pmap);
+ return (FALSE);
+ }
+ /*
+ * Check whether this is a valid section superpage entry or
+ * there is a l2_bucket associated with that L1 page directory.
+ */
+ va = trunc_1mpage(va);
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ l2b = pmap_get_l2_bucket(pmap, va);
+ if ((*pl1pd & L1_S_PROTO) || (l2b != NULL)) {
+ CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx"
+ " in pmap %p", va, pmap);
+ return (FALSE);
+ }
+ pa = VM_PAGE_TO_PHYS(m);
+ /*
+ * Abort this mapping if its PV entry could not be created.
+ */
+ if (!pmap_pv_insert_section(pmap, va, VM_PAGE_TO_PHYS(m))) {
+ CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx"
+ " in pmap %p", va, pmap);
+ return (FALSE);
+ }
+ /*
+ * Increment counters.
+ */
+ pmap->pm_stats.resident_count += L2_PTE_NUM_TOTAL;
+ /*
+ * Despite permissions, mark the superpage read-only.
+ */
+ prot &= ~VM_PROT_WRITE;
+ /*
+ * Map the superpage.
+ */
+ pmap_map_section(pmap, va, pa, prot, FALSE);
+
+ pmap_section_mappings++;
+ CTR2(KTR_PMAP, "pmap_enter_section: success for va %#lx"
+ " in pmap %p", va, pmap);
+ return (TRUE);
+}
+
+/*
+ * pmap_remove_section: do the things to unmap a superpage in a process
+ */
+static void
+pmap_remove_section(pmap_t pmap, vm_offset_t sva)
+{
+ struct md_page *pvh;
+ struct l2_bucket *l2b;
+ pd_entry_t *pl1pd, l1pd;
+ vm_offset_t eva, va;
+ vm_page_t m;
+
+ PMAP_ASSERT_LOCKED(pmap);
+ if ((pmap == pmap_kernel()) || (L1_IDX(sva) == L1_IDX(vector_page)))
+ return;
+
+ KASSERT((sva & L1_S_OFFSET) == 0,
+ ("pmap_remove_section: sva is not 1mpage aligned"));
+
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)];
+ l1pd = *pl1pd;
+
+ m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME);
+ KASSERT((m != NULL && ((m->oflags & VPO_UNMANAGED) == 0)),
+ ("pmap_remove_section: no corresponding vm_page or "
+ "page unmanaged"));
+
+ pmap->pm_stats.resident_count -= L2_PTE_NUM_TOTAL;
+ pvh = pa_to_pvh(l1pd & L1_S_FRAME);
+ pmap_pvh_free(pvh, pmap, sva);
+ eva = L2_NEXT_BUCKET(sva);
+ for (va = sva, m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME);
+ va < eva; va += PAGE_SIZE, m++) {
+ /*
+ * Mark base pages referenced but skip marking them dirty.
+ * If the superpage is writeable, hence all base pages were
+ * already marked as dirty in pmap_fault_fixup() before
+ * promotion. Reference bit however, might not have been set
+ * for each base page when the superpage was created at once,
+ * not as a result of promotion.
+ */
+ if (L1_S_REFERENCED(l1pd))
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ if (TAILQ_EMPTY(&m->md.pv_list) &&
+ TAILQ_EMPTY(&pvh->pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ }
+
+ l2b = pmap_get_l2_bucket(pmap, sva);
+ if (l2b != NULL) {
+ KASSERT(l2b->l2b_occupancy == L2_PTE_NUM_TOTAL,
+ ("pmap_remove_section: l2_bucket occupancy error"));
+ pmap_free_l2_bucket(pmap, l2b, L2_PTE_NUM_TOTAL);
+ }
+ /* Now invalidate L1 slot */
+ *pl1pd = 0;
+ PTE_SYNC(pl1pd);
+ if (L1_S_EXECUTABLE(l1pd))
+ cpu_tlb_flushID_SE(sva);
+ else
+ cpu_tlb_flushD_SE(sva);
+ cpu_cpwait();
+}
+
+/*
+ * Tries to promote the 256, contiguous 4KB page mappings that are
+ * within a single l2_bucket to a single 1MB section mapping.
+ * For promotion to occur, two conditions must be met: (1) the 4KB page
+ * mappings must map aligned, contiguous physical memory and (2) the 4KB page
+ * mappings must have identical characteristics.
+ */
+static void
+pmap_promote_section(pmap_t pmap, vm_offset_t va)
+{
+ pt_entry_t *firstptep, firstpte, oldpte, pa, *pte;
+ vm_page_t m, oldm;
+ vm_offset_t first_va, old_va;
+ struct l2_bucket *l2b = NULL;
+ vm_prot_t prot;
+ struct pv_entry *pve, *first_pve;
+
+ PMAP_ASSERT_LOCKED(pmap);
+
+ prot = VM_PROT_ALL;
+ /*
+ * Skip promoting kernel pages. This is justified by following:
+ * 1. Kernel is already mapped using section mappings in each pmap
+ * 2. Managed mappings within the kernel are not to be promoted anyway
+ */
+ if (pmap == pmap_kernel()) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
+ " in pmap %p", va, pmap);
+ return;
+ }
+ /* Do not attemp to promote vectors pages */
+ if (L1_IDX(va) == L1_IDX(vector_page)) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
+ " in pmap %p", va, pmap);
+ return;
+ }
+ /*
+ * Examine the first PTE in the specified l2_bucket. Abort if this PTE
+ * is either invalid, unused, or does not map the first 4KB physical
+ * page within 1MB page.
+ */
+ first_va = trunc_1mpage(va);
+ l2b = pmap_get_l2_bucket(pmap, first_va);
+ KASSERT(l2b != NULL, ("pmap_promote_section: trying to promote "
+ "not existing l2 bucket"));
+ firstptep = &l2b->l2b_kva[0];
+
+ firstpte = *firstptep;
+ if ((l2pte_pa(firstpte) & L1_S_OFFSET) != 0) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
+ " in pmap %p", va, pmap);
+ return;
+ }
+
+ if ((firstpte & (L2_S_PROTO | L2_S_REF)) != (L2_S_PROTO | L2_S_REF)) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
+ " in pmap %p", va, pmap);
+ return;
+ }
+ /*
+ * ARM uses pv_entry to mark particular mapping WIRED so don't promote
+ * unmanaged pages since it is impossible to determine, whether the
+ * page is wired or not if there is no corresponding pv_entry.
+ */
+ m = PHYS_TO_VM_PAGE(l2pte_pa(firstpte));
+ if (m && ((m->oflags & VPO_UNMANAGED) != 0)) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
+ " in pmap %p", va, pmap);
+ return;
+ }
+ first_pve = pmap_find_pv(&m->md, pmap, first_va);
+ /*
+ * PTE is modified only on write due to modified bit
+ * emulation. If the entry is referenced and writable
+ * then it is modified and we don't clear write enable.
+ * Otherwise, writing is disabled in PTE anyway and
+ * we just configure protections for the section mapping
+ * that is going to be created.
+ */
+ if ((first_pve->pv_flags & PVF_WRITE) != 0) {
+ if (!L2_S_WRITABLE(firstpte)) {
+ first_pve->pv_flags &= ~PVF_WRITE;
+ prot &= ~VM_PROT_WRITE;
+ }
+ } else
+ prot &= ~VM_PROT_WRITE;
+
+ if (!L2_S_EXECUTABLE(firstpte))
+ prot &= ~VM_PROT_EXECUTE;
+
+ /*
+ * Examine each of the other PTEs in the specified l2_bucket.
+ * Abort if this PTE maps an unexpected 4KB physical page or
+ * does not have identical characteristics to the first PTE.
+ */
+ pa = l2pte_pa(firstpte) + ((L2_PTE_NUM_TOTAL - 1) * PAGE_SIZE);
+ old_va = L2_NEXT_BUCKET(first_va) - PAGE_SIZE;
+
+ for (pte = (firstptep + L2_PTE_NUM_TOTAL - 1); pte > firstptep; pte--) {
+ oldpte = *pte;
+ if (l2pte_pa(oldpte) != pa) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for "
+ "va %#x in pmap %p", va, pmap);
+ return;
+ }
+ if ((oldpte & L2_S_PROMOTE) != (firstpte & L2_S_PROMOTE)) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for "
+ "va %#x in pmap %p", va, pmap);
+ return;
+ }
+ oldm = PHYS_TO_VM_PAGE(l2pte_pa(oldpte));
+ if (oldm && ((oldm->oflags & VPO_UNMANAGED) != 0)) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for "
+ "va %#x in pmap %p", va, pmap);
+ return;
+ }
+
+ pve = pmap_find_pv(&oldm->md, pmap, old_va);
+ if (pve == NULL) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for "
+ "va %#x old_va %x - no pve", va, old_va);
+ return;
+ }
+
+ if (!L2_S_WRITABLE(oldpte) && (pve->pv_flags & PVF_WRITE))
+ pve->pv_flags &= ~PVF_WRITE;
+ if (pve->pv_flags != first_pve->pv_flags) {
+ pmap_section_p_failures++;
+ CTR2(KTR_PMAP, "pmap_promote_section: failure for "
+ "va %#x in pmap %p", va, pmap);
+ return;
+ }
+
+ old_va -= PAGE_SIZE;
+ pa -= PAGE_SIZE;
+ }
+ /*
+ * Promote the pv entries.
+ */
+ pmap_pv_promote_section(pmap, first_va, l2pte_pa(firstpte));
+ /*
+ * Map the superpage.
+ */
+ pmap_map_section(pmap, first_va, l2pte_pa(firstpte), prot, TRUE);
+ /*
+ * Invalidate all possible TLB mappings for small
+ * pages within the newly created superpage.
+ * Rely on the first PTE's attributes since they
+ * have to be consistent across all of the base pages
+ * within the superpage. If page is not executable it
+ * is at least referenced.
+ * The fastest way to do that is to invalidate whole
+ * TLB at once instead of executing 256 CP15 TLB
+ * invalidations by single entry. TLBs usually maintain
+ * several dozen entries so loss of unrelated entries is
+ * still a less agresive approach.
+ */
+ if (L2_S_EXECUTABLE(firstpte))
+ cpu_tlb_flushID();
+ else
+ cpu_tlb_flushD();
+ cpu_cpwait();
+
+ pmap_section_promotions++;
+ CTR2(KTR_PMAP, "pmap_promote_section: success for va %#x"
+ " in pmap %p", first_va, pmap);
+}
+
+/*
+ * Fills a l2_bucket with mappings to consecutive physical pages.
+ */
+static void
+pmap_fill_l2b(struct l2_bucket *l2b, pt_entry_t newpte)
+{
+ pt_entry_t *ptep;
+ int i;
+
+ for (i = 0; i < L2_PTE_NUM_TOTAL; i++) {
+ ptep = &l2b->l2b_kva[i];
+ *ptep = newpte;
+ PTE_SYNC(ptep);
+
+ newpte += PAGE_SIZE;
+ }
+
+ l2b->l2b_occupancy = L2_PTE_NUM_TOTAL;
+}
+
+/*
+ * Tries to demote a 1MB section mapping. If demotion fails, the
+ * 1MB section mapping is invalidated.
+ */
+static boolean_t
+pmap_demote_section(pmap_t pmap, vm_offset_t va)
+{
+ struct l2_bucket *l2b;
+ struct pv_entry *l1pdpve;
+ struct md_page *pvh;
+ pd_entry_t *pl1pd, l1pd, newl1pd;
+ pt_entry_t *firstptep, newpte;
+ vm_offset_t pa;
+ vm_page_t m;
+
+ PMAP_ASSERT_LOCKED(pmap);
+ /*
+ * According to assumptions described in pmap_promote_section,
+ * kernel is and always should be mapped using 1MB section mappings.
+ * What more, managed kernel pages were not to be promoted.
+ */
+ KASSERT(pmap != pmap_kernel() && L1_IDX(va) != L1_IDX(vector_page),
+ ("pmap_demote_section: forbidden section mapping"));
+
+ va = trunc_1mpage(va);
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ l1pd = *pl1pd;
+ KASSERT((l1pd & L1_TYPE_MASK) == L1_S_PROTO,
+ ("pmap_demote_section: not section or invalid section"));
+
+ pa = l1pd & L1_S_FRAME;
+ m = PHYS_TO_VM_PAGE(pa);
+ KASSERT((m != NULL && (m->oflags & VPO_UNMANAGED) == 0),
+ ("pmap_demote_section: no vm_page for selected superpage or"
+ "unmanaged"));
+
+ pvh = pa_to_pvh(pa);
+ l1pdpve = pmap_find_pv(pvh, pmap, va);
+ KASSERT(l1pdpve != NULL, ("pmap_demote_section: no pv entry for "
+ "managed page"));
+
+ l2b = pmap_get_l2_bucket(pmap, va);
+ if (l2b == NULL) {
+ KASSERT((l1pdpve->pv_flags & PVF_WIRED) == 0,
+ ("pmap_demote_section: No l2_bucket for wired mapping"));
+ /*
+ * Invalidate the 1MB section mapping and return
+ * "failure" if the mapping was never accessed or the
+ * allocation of the new l2_bucket fails.
+ */
+ if (!L1_S_REFERENCED(l1pd) ||
+ (l2b = pmap_alloc_l2_bucket(pmap, va)) == NULL) {
+ /* Unmap and invalidate superpage. */
+ pmap_remove_section(pmap, trunc_1mpage(va));
+ CTR2(KTR_PMAP, "pmap_demote_section: failure for "
+ "va %#x in pmap %p", va, pmap);
+ return (FALSE);
+ }
+ }
+
+ /*
+ * Now we should have corresponding l2_bucket available.
+ * Let's process it to recreate 256 PTEs for each base page
+ * within superpage.
+ */
+ newpte = pa | L1_S_DEMOTE(l1pd);
+ if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
+ newpte |= pte_l2_s_cache_mode;
+
+ /*
+ * If the l2_bucket is new, initialize it.
+ */
+ if (l2b->l2b_occupancy == 0)
+ pmap_fill_l2b(l2b, newpte);
+ else {
+ firstptep = &l2b->l2b_kva[0];
+ KASSERT(l2pte_pa(*firstptep) == (pa),
+ ("pmap_demote_section: firstpte and newpte map different "
+ "physical addresses"));
+ /*
+ * If the mapping has changed attributes, update the page table
+ * entries.
+ */
+ if ((*firstptep & L2_S_PROMOTE) != (L1_S_DEMOTE(l1pd)))
+ pmap_fill_l2b(l2b, newpte);
+ }
+ /* Demote PV entry */
+ pmap_pv_demote_section(pmap, va, pa);
+
+ /* Now fix-up L1 */
+ newl1pd = l2b->l2b_phys | L1_C_DOM(pmap->pm_domain) | L1_C_PROTO;
+ *pl1pd = newl1pd;
+ PTE_SYNC(pl1pd);
+ /* Invalidate old TLB mapping */
+ if (L1_S_EXECUTABLE(l1pd))
+ cpu_tlb_flushID_SE(va);
+ else if (L1_S_REFERENCED(l1pd))
+ cpu_tlb_flushD_SE(va);
+ cpu_cpwait();
+
+ pmap_section_demotions++;
+ CTR2(KTR_PMAP, "pmap_demote_section: success for va %#x"
+ " in pmap %p", va, pmap);
+ return (TRUE);
+}
+
+/***************************************************
+ * page management routines.
+ ***************************************************/
+
+/*
+ * We are in a serious low memory condition. Resort to
+ * drastic measures to free some pages so we can allocate
+ * another pv entry chunk.
+ */
+static vm_page_t
+pmap_pv_reclaim(pmap_t locked_pmap)
+{
+ struct pch newtail;
+ struct pv_chunk *pc;
+ struct l2_bucket *l2b = NULL;
+ pmap_t pmap;
+ pd_entry_t *pl1pd;
+ pt_entry_t *ptep;
+ pv_entry_t pv;
+ vm_offset_t va;
+ vm_page_t free, m, m_pc;
+ uint32_t inuse;
+ int bit, field, freed, idx;
+
+ PMAP_ASSERT_LOCKED(locked_pmap);
+ pmap = NULL;
+ free = m_pc = NULL;
+ TAILQ_INIT(&newtail);
+ while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 ||
+ free == NULL)) {
+ TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
+ if (pmap != pc->pc_pmap) {
+ if (pmap != NULL) {
+ cpu_tlb_flushID();
+ cpu_cpwait();
+ if (pmap != locked_pmap)
+ PMAP_UNLOCK(pmap);
+ }
+ pmap = pc->pc_pmap;
+ /* Avoid deadlock and lock recursion. */
+ if (pmap > locked_pmap)
+ PMAP_LOCK(pmap);
+ else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) {
+ pmap = NULL;
+ TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+ continue;
+ }
+ }
+
+ /*
+ * Destroy every non-wired, 4 KB page mapping in the chunk.
+ */
+ freed = 0;
+ for (field = 0; field < _NPCM; field++) {
+ for (inuse = ~pc->pc_map[field] & pc_freemask[field];
+ inuse != 0; inuse &= ~(1UL << bit)) {
+ bit = ffs(inuse) - 1;
+ idx = field * sizeof(inuse) * NBBY + bit;
+ pv = &pc->pc_pventry[idx];
+ va = pv->pv_va;
+
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
+ continue;
+ if (pv->pv_flags & PVF_WIRED)
+ continue;
+
+ l2b = pmap_get_l2_bucket(pmap, va);
+ KASSERT(l2b != NULL, ("No l2 bucket"));
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep));
+ KASSERT((vm_offset_t)m >= KERNBASE,
+ ("Trying to access non-existent page "
+ "va %x pte %x", va, *ptep));
+ *ptep = 0;
+ PTE_SYNC(ptep);
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+ if (TAILQ_EMPTY(&m->md.pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ pc->pc_map[field] |= 1UL << bit;
+ freed++;
+ }
+ }
+
+ if (freed == 0) {
+ TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+ continue;
+ }
+ /* Every freed mapping is for a 4 KB page. */
+ pmap->pm_stats.resident_count -= freed;
+ PV_STAT(pv_entry_frees += freed);
+ PV_STAT(pv_entry_spare += freed);
+ pv_entry_count -= freed;
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ for (field = 0; field < _NPCM; field++)
+ if (pc->pc_map[field] != pc_freemask[field]) {
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc,
+ pc_list);
+ TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+
+ /*
+ * One freed pv entry in locked_pmap is
+ * sufficient.
+ */
+ if (pmap == locked_pmap)
+ goto out;
+ break;
+ }
+ if (field == _NPCM) {
+ PV_STAT(pv_entry_spare -= _NPCPV);
+ PV_STAT(pc_chunk_count--);
+ PV_STAT(pc_chunk_frees++);
+ /* Entire chunk is free; return it. */
+ m_pc = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc));
+ pmap_qremove((vm_offset_t)pc, 1);
+ pmap_ptelist_free(&pv_vafree, (vm_offset_t)pc);
+ break;
+ }
+ }
+out:
+ TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru);
+ if (pmap != NULL) {
+ cpu_tlb_flushID();
+ cpu_cpwait();
+ if (pmap != locked_pmap)
+ PMAP_UNLOCK(pmap);
+ }
+ return (m_pc);
+}
+
+/*
+ * free the pv_entry back to the free list
+ */
+static void
+pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv)
+{
+ struct pv_chunk *pc;
+ int bit, field, idx;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_ASSERT_LOCKED(pmap);
+ PV_STAT(pv_entry_frees++);
+ PV_STAT(pv_entry_spare++);
+ pv_entry_count--;
+ pc = pv_to_chunk(pv);
+ idx = pv - &pc->pc_pventry[0];
+ field = idx / (sizeof(u_long) * NBBY);
+ bit = idx % (sizeof(u_long) * NBBY);
+ pc->pc_map[field] |= 1ul << bit;
+ for (idx = 0; idx < _NPCM; idx++)
+ if (pc->pc_map[idx] != pc_freemask[idx]) {
+ /*
+ * 98% of the time, pc is already at the head of the
+ * list. If it isn't already, move it to the head.
+ */
+ if (__predict_false(TAILQ_FIRST(&pmap->pm_pvchunk) !=
+ pc)) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc,
+ pc_list);
+ }
+ return;
+ }
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ pmap_free_pv_chunk(pc);
+}
+
+static void
+pmap_free_pv_chunk(struct pv_chunk *pc)
+{
+ vm_page_t m;
+
+ TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
+ PV_STAT(pv_entry_spare -= _NPCPV);
+ PV_STAT(pc_chunk_count--);
+ PV_STAT(pc_chunk_frees++);
+ /* entire chunk is free, return it */
+ m = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc));
+ pmap_qremove((vm_offset_t)pc, 1);
+ vm_page_unwire(m, 0);
+ vm_page_free(m);
+ pmap_ptelist_free(&pv_vafree, (vm_offset_t)pc);
+
+}
+
+static pv_entry_t
+pmap_get_pv_entry(pmap_t pmap, boolean_t try)
+{
+ static const struct timeval printinterval = { 60, 0 };
+ static struct timeval lastprint;
+ struct pv_chunk *pc;
+ pv_entry_t pv;
+ vm_page_t m;
+ int bit, field, idx;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_ASSERT_LOCKED(pmap);
+ PV_STAT(pv_entry_allocs++);
+ pv_entry_count++;
+
+ if (pv_entry_count > pv_entry_high_water)
+ if (ratecheck(&lastprint, &printinterval))
+ printf("%s: Approaching the limit on PV entries.\n",
+ __func__);
+retry:
+ pc = TAILQ_FIRST(&pmap->pm_pvchunk);
+ if (pc != NULL) {
+ for (field = 0; field < _NPCM; field++) {
+ if (pc->pc_map[field]) {
+ bit = ffs(pc->pc_map[field]) - 1;
+ break;
+ }
+ }
+ if (field < _NPCM) {
+ idx = field * sizeof(pc->pc_map[field]) * NBBY + bit;
+ pv = &pc->pc_pventry[idx];
+ pc->pc_map[field] &= ~(1ul << bit);
+ /* If this was the last item, move it to tail */
+ for (field = 0; field < _NPCM; field++)
+ if (pc->pc_map[field] != 0) {
+ PV_STAT(pv_entry_spare--);
+ return (pv); /* not full, return */
+ }
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc, pc_list);
+ PV_STAT(pv_entry_spare--);
+ return (pv);
+ }
+ }
+ /*
+ * Access to the ptelist "pv_vafree" is synchronized by the pvh
+ * global lock. If "pv_vafree" is currently non-empty, it will
+ * remain non-empty until pmap_ptelist_alloc() completes.
+ */
+ if (pv_vafree == 0 || (m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED)) == NULL) {
+ if (try) {
+ pv_entry_count--;
+ PV_STAT(pc_chunk_tryfail++);
+ return (NULL);
+ }
+ m = pmap_pv_reclaim(pmap);
+ if (m == NULL)
+ goto retry;
+ }
+ PV_STAT(pc_chunk_count++);
+ PV_STAT(pc_chunk_allocs++);
+ pc = (struct pv_chunk *)pmap_ptelist_alloc(&pv_vafree);
+ pmap_qenter((vm_offset_t)pc, &m, 1);
+ pc->pc_pmap = pmap;
+ pc->pc_map[0] = pc_freemask[0] & ~1ul; /* preallocated bit 0 */
+ for (field = 1; field < _NPCM; field++)
+ pc->pc_map[field] = pc_freemask[field];
+ TAILQ_INSERT_TAIL(&pv_chunks, pc, pc_lru);
+ pv = &pc->pc_pventry[0];
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
+ PV_STAT(pv_entry_spare += _NPCPV - 1);
+ return (pv);
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ *
+ * It is assumed that the start and end are properly
+ * rounded to the page size.
+ */
+#define PMAP_REMOVE_CLEAN_LIST_SIZE 3
+void
+pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+ struct l2_bucket *l2b;
+ vm_offset_t next_bucket;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep;
+ u_int total;
+ u_int mappings, is_exec, is_refd;
+ int flushall = 0;
+
+
+ /*
+ * we lock in the pmap => pv_head direction
+ */
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ total = 0;
+ while (sva < eva) {
+ /*
+ * Check for large page.
+ */
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)];
+ l1pd = *pl1pd;
+ if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+ KASSERT((l1pd & L1_S_DOM_MASK) !=
+ L1_S_DOM(PMAP_DOMAIN_KERNEL), ("pmap_remove: "
+ "Trying to remove kernel section mapping"));
+ /*
+ * Are we removing the entire large page? If not,
+ * demote the mapping and fall through.
+ */
+ if (sva + L1_S_SIZE == L2_NEXT_BUCKET(sva) &&
+ eva >= L2_NEXT_BUCKET(sva)) {
+ pmap_remove_section(pmap, sva);
+ sva = L2_NEXT_BUCKET(sva);
+ continue;
+ } else if (!pmap_demote_section(pmap, sva)) {
+ /* The large page mapping was destroyed. */
+ sva = L2_NEXT_BUCKET(sva);
+ continue;
+ }
+ }
+ /*
+ * Do one L2 bucket's worth at a time.
+ */
+ next_bucket = L2_NEXT_BUCKET(sva);
+ if (next_bucket > eva)
+ next_bucket = eva;
+
+ l2b = pmap_get_l2_bucket(pmap, sva);
+ if (l2b == NULL) {
+ sva = next_bucket;
+ continue;
+ }
+
+ ptep = &l2b->l2b_kva[l2pte_index(sva)];
+ mappings = 0;
+
+ while (sva < next_bucket) {
+ struct vm_page *m;
+ pt_entry_t pte;
+ vm_paddr_t pa;
+
+ pte = *ptep;
+
+ if (pte == 0) {
+ /*
+ * Nothing here, move along
+ */
+ sva += PAGE_SIZE;
+ ptep++;
+ continue;
+ }
+
+ pmap->pm_stats.resident_count--;
+ pa = l2pte_pa(pte);
+ is_exec = 0;
+ is_refd = 1;
+
+ /*
+ * Update flags. In a number of circumstances,
+ * we could cluster a lot of these and do a
+ * number of sequential pages in one go.
+ */
+ if ((m = PHYS_TO_VM_PAGE(pa)) != NULL) {
+ struct pv_entry *pve;
+
+ pve = pmap_remove_pv(m, pmap, sva);
+ if (pve) {
+ is_exec = PTE_BEEN_EXECD(pte);
+ is_refd = PTE_BEEN_REFD(pte);
+ pmap_free_pv_entry(pmap, pve);
+ }
+ }
+
+ *ptep = 0;
+ PTE_SYNC(ptep);
+ if (pmap_is_current(pmap)) {
+ total++;
+ if (total < PMAP_REMOVE_CLEAN_LIST_SIZE) {
+ if (is_exec)
+ cpu_tlb_flushID_SE(sva);
+ else if (is_refd)
+ cpu_tlb_flushD_SE(sva);
+ } else if (total == PMAP_REMOVE_CLEAN_LIST_SIZE)
+ flushall = 1;
+ }
+
+ sva += PAGE_SIZE;
+ ptep++;
+ mappings++;
+ }
+
+ pmap_free_l2_bucket(pmap, l2b, mappings);
+ }
+
+ rw_wunlock(&pvh_global_lock);
+ if (flushall)
+ cpu_tlb_flushID();
+ cpu_cpwait();
+
+ PMAP_UNLOCK(pmap);
+}
+
+/*
+ * pmap_zero_page()
+ *
+ * Zero a given physical page by mapping it at a page hook point.
+ * In doing the zero page op, the page we zero is mapped cachable, as with
+ * StrongARM accesses to non-cached pages are non-burst making writing
+ * _any_ bulk data very slow.
+ */
+static void
+pmap_zero_page_gen(vm_page_t m, int off, int size)
+{
+ struct czpages *czp;
+
+ KASSERT(TAILQ_EMPTY(&m->md.pv_list),
+ ("pmap_zero_page_gen: page has mappings"));
+
+ vm_paddr_t phys = VM_PAGE_TO_PHYS(m);
+
+ sched_pin();
+ czp = &cpu_czpages[PCPU_GET(cpuid)];
+ mtx_lock(&czp->lock);
+
+ /*
+ * Hook in the page, zero it.
+ */
+ *czp->dstptep = L2_S_PROTO | phys | pte_l2_s_cache_mode | L2_S_REF;
+ pmap_set_prot(czp->dstptep, VM_PROT_WRITE, 0);
+ PTE_SYNC(czp->dstptep);
+ cpu_tlb_flushD_SE(czp->dstva);
+ cpu_cpwait();
+
+ if (off || size != PAGE_SIZE)
+ bzero((void *)(czp->dstva + off), size);
+ else
+ bzero_page(czp->dstva);
+
+ /*
+ * Although aliasing is not possible, if we use temporary mappings with
+ * memory that will be mapped later as non-cached or with write-through
+ * caches, we might end up overwriting it when calling wbinv_all. So
+ * make sure caches are clean after the operation.
+ */
+ cpu_idcache_wbinv_range(czp->dstva, size);
+ pmap_l2cache_wbinv_range(czp->dstva, phys, size);
+
+ mtx_unlock(&czp->lock);
+ sched_unpin();
+}
+
+/*
+ * pmap_zero_page zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents.
+ */
+void
+pmap_zero_page(vm_page_t m)
+{
+ pmap_zero_page_gen(m, 0, PAGE_SIZE);
+}
+
+
+/*
+ * pmap_zero_page_area zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents.
+ *
+ * off and size may not cover an area beyond a single hardware page.
+ */
+void
+pmap_zero_page_area(vm_page_t m, int off, int size)
+{
+
+ pmap_zero_page_gen(m, off, size);
+}
+
+
+/*
+ * pmap_zero_page_idle zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents. This
+ * is intended to be called from the vm_pagezero process only and
+ * outside of Giant.
+ */
+void
+pmap_zero_page_idle(vm_page_t m)
+{
+
+ pmap_zero_page(m);
+}
+
+/*
+ * pmap_copy_page copies the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bcopy to copy the page, one machine dependent page at a
+ * time.
+ */
+
+/*
+ * pmap_copy_page()
+ *
+ * Copy one physical page into another, by mapping the pages into
+ * hook points. The same comment regarding cachability as in
+ * pmap_zero_page also applies here.
+ */
+void
+pmap_copy_page_generic(vm_paddr_t src, vm_paddr_t dst)
+{
+ struct czpages *czp;
+
+ sched_pin();
+ czp = &cpu_czpages[PCPU_GET(cpuid)];
+ mtx_lock(&czp->lock);
+
+ /*
+ * Map the pages into the page hook points, copy them, and purge the
+ * cache for the appropriate page.
+ */
+ *czp->srcptep = L2_S_PROTO | src | pte_l2_s_cache_mode | L2_S_REF;
+ pmap_set_prot(czp->srcptep, VM_PROT_READ, 0);
+ PTE_SYNC(czp->srcptep);
+ cpu_tlb_flushD_SE(czp->srcva);
+ *czp->dstptep = L2_S_PROTO | dst | pte_l2_s_cache_mode | L2_S_REF;
+ pmap_set_prot(czp->dstptep, VM_PROT_READ | VM_PROT_WRITE, 0);
+ PTE_SYNC(czp->dstptep);
+ cpu_tlb_flushD_SE(czp->dstva);
+ cpu_cpwait();
+
+ bcopy_page(czp->srcva, czp->dstva);
+
+ /*
+ * Although aliasing is not possible, if we use temporary mappings with
+ * memory that will be mapped later as non-cached or with write-through
+ * caches, we might end up overwriting it when calling wbinv_all. So
+ * make sure caches are clean after the operation.
+ */
+ cpu_idcache_wbinv_range(czp->dstva, PAGE_SIZE);
+ pmap_l2cache_wbinv_range(czp->dstva, dst, PAGE_SIZE);
+
+ mtx_unlock(&czp->lock);
+ sched_unpin();
+}
+
+int unmapped_buf_allowed = 1;
+
+void
+pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
+ vm_offset_t b_offset, int xfersize)
+{
+ vm_page_t a_pg, b_pg;
+ vm_offset_t a_pg_offset, b_pg_offset;
+ int cnt;
+ struct czpages *czp;
+
+ sched_pin();
+ czp = &cpu_czpages[PCPU_GET(cpuid)];
+ mtx_lock(&czp->lock);
+
+ while (xfersize > 0) {
+ a_pg = ma[a_offset >> PAGE_SHIFT];
+ a_pg_offset = a_offset & PAGE_MASK;
+ cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+ b_pg = mb[b_offset >> PAGE_SHIFT];
+ b_pg_offset = b_offset & PAGE_MASK;
+ cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+ *czp->srcptep = L2_S_PROTO | VM_PAGE_TO_PHYS(a_pg) |
+ pte_l2_s_cache_mode | L2_S_REF;
+ pmap_set_prot(czp->srcptep, VM_PROT_READ, 0);
+ PTE_SYNC(czp->srcptep);
+ cpu_tlb_flushD_SE(czp->srcva);
+ *czp->dstptep = L2_S_PROTO | VM_PAGE_TO_PHYS(b_pg) |
+ pte_l2_s_cache_mode | L2_S_REF;
+ pmap_set_prot(czp->dstptep, VM_PROT_READ | VM_PROT_WRITE, 0);
+ PTE_SYNC(czp->dstptep);
+ cpu_tlb_flushD_SE(czp->dstva);
+ cpu_cpwait();
+ bcopy((char *)czp->srcva + a_pg_offset, (char *)czp->dstva + b_pg_offset,
+ cnt);
+ cpu_idcache_wbinv_range(czp->dstva + b_pg_offset, cnt);
+ pmap_l2cache_wbinv_range(czp->dstva + b_pg_offset,
+ VM_PAGE_TO_PHYS(b_pg) + b_pg_offset, cnt);
+ xfersize -= cnt;
+ a_offset += cnt;
+ b_offset += cnt;
+ }
+
+ mtx_unlock(&czp->lock);
+ sched_unpin();
+}
+
+void
+pmap_copy_page(vm_page_t src, vm_page_t dst)
+{
+
+ if (_arm_memcpy && PAGE_SIZE >= _min_memcpy_size &&
+ _arm_memcpy((void *)VM_PAGE_TO_PHYS(dst),
+ (void *)VM_PAGE_TO_PHYS(src), PAGE_SIZE, IS_PHYSICAL) == 0)
+ return;
+
+ pmap_copy_page_generic(VM_PAGE_TO_PHYS(src), VM_PAGE_TO_PHYS(dst));
+}
+
+/*
+ * this routine returns true if a physical page resides
+ * in the given pmap.
+ */
+boolean_t
+pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
+{
+ struct md_page *pvh;
+ pv_entry_t pv;
+ int loops = 0;
+ boolean_t rv;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_page_exists_quick: page %p is not managed", m));
+ rv = FALSE;
+ rw_wlock(&pvh_global_lock);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ if (PV_PMAP(pv) == pmap) {
+ rv = TRUE;
+ break;
+ }
+ loops++;
+ if (loops >= 16)
+ break;
+ }
+ if (!rv && loops < 16 && (m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
+ if (PV_PMAP(pv) == pmap) {
+ rv = TRUE;
+ break;
+ }
+ loops++;
+ if (loops >= 16)
+ break;
+ }
+ }
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * pmap_page_wired_mappings:
+ *
+ * Return the number of managed mappings to the given physical page
+ * that are wired.
+ */
+int
+pmap_page_wired_mappings(vm_page_t m)
+{
+ int count;
+
+ count = 0;
+ if ((m->oflags & VPO_UNMANAGED) != 0)
+ return (count);
+ rw_wlock(&pvh_global_lock);
+ count = pmap_pvh_wired_mappings(&m->md, count);
+ if ((m->flags & PG_FICTITIOUS) == 0) {
+ count = pmap_pvh_wired_mappings(pa_to_pvh(VM_PAGE_TO_PHYS(m)),
+ count);
+ }
+ rw_wunlock(&pvh_global_lock);
+ return (count);
+}
+
+/*
+ * pmap_pvh_wired_mappings:
+ *
+ * Return the updated number "count" of managed mappings that are wired.
+ */
+static int
+pmap_pvh_wired_mappings(struct md_page *pvh, int count)
+{
+ pv_entry_t pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
+ if ((pv->pv_flags & PVF_WIRED) != 0)
+ count++;
+ }
+ return (count);
+}
+
+/*
+ * Returns TRUE if any of the given mappings were referenced and FALSE
+ * otherwise. Both page and section mappings are supported.
+ */
+static boolean_t
+pmap_is_referenced_pvh(struct md_page *pvh)
+{
+ struct l2_bucket *l2b;
+ pv_entry_t pv;
+ pd_entry_t *pl1pd;
+ pt_entry_t *ptep;
+ pmap_t pmap;
+ boolean_t rv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ rv = FALSE;
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)];
+ if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
+ rv = L1_S_REFERENCED(*pl1pd);
+ else {
+ l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
+ ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+ rv = L2_S_REFERENCED(*ptep);
+ }
+ PMAP_UNLOCK(pmap);
+ if (rv)
+ break;
+ }
+ return (rv);
+}
+
+/*
+ * pmap_is_referenced:
+ *
+ * Return whether or not the specified physical page was referenced
+ * in any physical maps.
+ */
+boolean_t
+pmap_is_referenced(vm_page_t m)
+{
+ boolean_t rv;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_is_referenced: page %p is not managed", m));
+ rw_wlock(&pvh_global_lock);
+ rv = pmap_is_referenced_pvh(&m->md) ||
+ ((m->flags & PG_FICTITIOUS) == 0 &&
+ pmap_is_referenced_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m))));
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * pmap_ts_referenced:
+ *
+ * Return the count of reference bits for a page, clearing all of them.
+ */
+int
+pmap_ts_referenced(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_ts_referenced: page %p is not managed", m));
+ return (pmap_clearbit(m, PVF_REF));
+}
+
+/*
+ * Returns TRUE if any of the given mappings were used to modify
+ * physical memory. Otherwise, returns FALSE. Both page and 1MB section
+ * mappings are supported.
+ */
+static boolean_t
+pmap_is_modified_pvh(struct md_page *pvh)
+{
+ pd_entry_t *pl1pd;
+ struct l2_bucket *l2b;
+ pv_entry_t pv;
+ pt_entry_t *ptep;
+ pmap_t pmap;
+ boolean_t rv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ rv = FALSE;
+
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)];
+ if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
+ rv = L1_S_WRITABLE(*pl1pd);
+ else {
+ l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
+ ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+ rv = L2_S_WRITABLE(*ptep);
+ }
+ PMAP_UNLOCK(pmap);
+ if (rv)
+ break;
+ }
+
+ return (rv);
+}
+
+boolean_t
+pmap_is_modified(vm_page_t m)
+{
+ boolean_t rv;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_is_modified: page %p is not managed", m));
+ /*
+ * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
+ * is clear, no PTEs can have APX cleared.
+ */
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+ return (FALSE);
+ rw_wlock(&pvh_global_lock);
+ rv = pmap_is_modified_pvh(&m->md) ||
+ ((m->flags & PG_FICTITIOUS) == 0 &&
+ pmap_is_modified_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m))));
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * Apply the given advice to the specified range of addresses within the
+ * given pmap. Depending on the advice, clear the referenced and/or
+ * modified flags in each mapping.
+ */
+void
+pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice)
+{
+ struct l2_bucket *l2b;
+ struct pv_entry *pve;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep, opte, pte;
+ vm_offset_t next_bucket;
+ vm_page_t m;
+
+ if (advice != MADV_DONTNEED && advice != MADV_FREE)
+ return;
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ for (; sva < eva; sva = next_bucket) {
+ next_bucket = L2_NEXT_BUCKET(sva);
+ if (next_bucket < sva)
+ next_bucket = eva;
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)];
+ l1pd = *pl1pd;
+ if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+ if (pmap == pmap_kernel())
+ continue;
+ if (!pmap_demote_section(pmap, sva)) {
+ /*
+ * The large page mapping was destroyed.
+ */
+ continue;
+ }
+ /*
+ * Unless the page mappings are wired, remove the
+ * mapping to a single page so that a subsequent
+ * access may repromote. Since the underlying
+ * l2_bucket is fully populated, this removal
+ * never frees an entire l2_bucket.
+ */
+ l2b = pmap_get_l2_bucket(pmap, sva);
+ KASSERT(l2b != NULL,
+ ("pmap_advise: no l2 bucket for "
+ "va 0x%#x, pmap 0x%p", sva, pmap));
+ ptep = &l2b->l2b_kva[l2pte_index(sva)];
+ opte = *ptep;
+ m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep));
+ KASSERT(m != NULL,
+ ("pmap_advise: no vm_page for demoted superpage"));
+ pve = pmap_find_pv(&m->md, pmap, sva);
+ KASSERT(pve != NULL,
+ ("pmap_advise: no PV entry for managed mapping"));
+ if ((pve->pv_flags & PVF_WIRED) == 0) {
+ pmap_free_l2_bucket(pmap, l2b, 1);
+ pve = pmap_remove_pv(m, pmap, sva);
+ pmap_free_pv_entry(pmap, pve);
+ *ptep = 0;
+ PTE_SYNC(ptep);
+ if (pmap_is_current(pmap)) {
+ if (PTE_BEEN_EXECD(opte))
+ cpu_tlb_flushID_SE(sva);
+ else if (PTE_BEEN_REFD(opte))
+ cpu_tlb_flushD_SE(sva);
+ }
+ }
+ }
+ if (next_bucket > eva)
+ next_bucket = eva;
+ l2b = pmap_get_l2_bucket(pmap, sva);
+ if (l2b == NULL)
+ continue;
+ for (ptep = &l2b->l2b_kva[l2pte_index(sva)];
+ sva != next_bucket; ptep++, sva += PAGE_SIZE) {
+ opte = pte = *ptep;
+ if ((opte & L2_S_PROTO) == 0)
+ continue;
+ m = PHYS_TO_VM_PAGE(l2pte_pa(opte));
+ if (m == NULL || (m->oflags & VPO_UNMANAGED) != 0)
+ continue;
+ else if (L2_S_WRITABLE(opte)) {
+ if (advice == MADV_DONTNEED) {
+ /*
+ * Don't need to mark the page
+ * dirty as it was already marked as
+ * such in pmap_fault_fixup() or
+ * pmap_enter_locked().
+ * Just clear the state.
+ */
+ } else
+ pte |= L2_APX;
+
+ pte &= ~L2_S_REF;
+ *ptep = pte;
+ PTE_SYNC(ptep);
+ } else if (L2_S_REFERENCED(opte)) {
+ pte &= ~L2_S_REF;
+ *ptep = pte;
+ PTE_SYNC(ptep);
+ } else
+ continue;
+ if (pmap_is_current(pmap)) {
+ if (PTE_BEEN_EXECD(opte))
+ cpu_tlb_flushID_SE(sva);
+ else if (PTE_BEEN_REFD(opte))
+ cpu_tlb_flushD_SE(sva);
+ }
+ }
+ }
+ cpu_cpwait();
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
+
+/*
+ * Clear the modify bits on the specified physical page.
+ */
+void
+pmap_clear_modify(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_clear_modify: page %p is not managed", m));
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ KASSERT(!vm_page_xbusied(m),
+ ("pmap_clear_modify: page %p is exclusive busied", m));
+
+ /*
+ * If the page is not PGA_WRITEABLE, then no mappings can be modified.
+ * If the object containing the page is locked and the page is not
+ * exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
+ */
+ if ((m->aflags & PGA_WRITEABLE) == 0)
+ return;
+ if (pmap_is_modified(m))
+ pmap_clearbit(m, PVF_MOD);
+}
+
+
+/*
+ * Clear the write and modified bits in each of the given page's mappings.
+ */
+void
+pmap_remove_write(vm_page_t m)
+{
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_remove_write: page %p is not managed", m));
+
+ /*
+ * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+ * set by another thread while the object is locked. Thus,
+ * if PGA_WRITEABLE is clear, no page table entries need updating.
+ */
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ if (vm_page_xbusied(m) || (m->aflags & PGA_WRITEABLE) != 0)
+ pmap_clearbit(m, PVF_WRITE);
+}
+
+
+/*
+ * perform the pmap work for mincore
+ */
+int
+pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
+{
+ struct l2_bucket *l2b;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep, pte;
+ vm_paddr_t pa;
+ vm_page_t m;
+ int val;
+ boolean_t managed;
+
+ PMAP_LOCK(pmap);
+retry:
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(addr)];
+ l1pd = *pl1pd;
+ if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+ pa = (l1pd & L1_S_FRAME);
+ val = MINCORE_SUPER | MINCORE_INCORE;
+ if (L1_S_WRITABLE(l1pd))
+ val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER;
+ managed = FALSE;
+ m = PHYS_TO_VM_PAGE(pa);
+ if (m != NULL && (m->oflags & VPO_UNMANAGED) == 0)
+ managed = TRUE;
+ if (managed) {
+ if (L1_S_REFERENCED(l1pd))
+ val |= MINCORE_REFERENCED |
+ MINCORE_REFERENCED_OTHER;
+ }
+ } else {
+ l2b = pmap_get_l2_bucket(pmap, addr);
+ if (l2b == NULL) {
+ val = 0;
+ goto out;
+ }
+ ptep = &l2b->l2b_kva[l2pte_index(addr)];
+ pte = *ptep;
+ if (!l2pte_valid(pte)) {
+ val = 0;
+ goto out;
+ }
+ val = MINCORE_INCORE;
+ if (L2_S_WRITABLE(pte))
+ val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER;
+ managed = FALSE;
+ pa = l2pte_pa(pte);
+ m = PHYS_TO_VM_PAGE(pa);
+ if (m != NULL && (m->oflags & VPO_UNMANAGED) == 0)
+ managed = TRUE;
+ if (managed) {
+ if (L2_S_REFERENCED(pte))
+ val |= MINCORE_REFERENCED |
+ MINCORE_REFERENCED_OTHER;
+ }
+ }
+ if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) !=
+ (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER) && managed) {
+ /* Ensure that "PHYS_TO_VM_PAGE(pa)->object" doesn't change. */
+ if (vm_page_pa_tryrelock(pmap, pa, locked_pa))
+ goto retry;
+ } else
+out:
+ PA_UNLOCK_COND(*locked_pa);
+ PMAP_UNLOCK(pmap);
+ return (val);
+}
+
+void
+pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t sz)
+{
+}
+
+/*
+ * Increase the starting virtual address of the given mapping if a
+ * different alignment might result in more superpage mappings.
+ */
+void
+pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
+ vm_offset_t *addr, vm_size_t size)
+{
+ vm_offset_t superpage_offset;
+
+ if (size < NBPDR)
+ return;
+ if (object != NULL && (object->flags & OBJ_COLORED) != 0)
+ offset += ptoa(object->pg_color);
+ superpage_offset = offset & PDRMASK;
+ if (size - ((NBPDR - superpage_offset) & PDRMASK) < NBPDR ||
+ (*addr & PDRMASK) == superpage_offset)
+ return;
+ if ((*addr & PDRMASK) < superpage_offset)
+ *addr = (*addr & ~PDRMASK) + superpage_offset;
+ else
+ *addr = ((*addr + PDRMASK) & ~PDRMASK) + superpage_offset;
+}
+
+/*
+ * pmap_map_section:
+ *
+ * Create a single section mapping.
+ */
+void
+pmap_map_section(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot,
+ boolean_t ref)
+{
+ pd_entry_t *pl1pd, l1pd;
+ pd_entry_t fl;
+
+ KASSERT(((va | pa) & L1_S_OFFSET) == 0,
+ ("Not a valid section mapping"));
+
+ fl = pte_l1_s_cache_mode;
+
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ l1pd = L1_S_PROTO | pa | L1_S_PROT(PTE_USER, prot) | fl |
+ L1_S_DOM(pmap->pm_domain);
+
+ /* Mark page referenced if this section is a result of a promotion. */
+ if (ref == TRUE)
+ l1pd |= L1_S_REF;
+#ifdef SMP
+ l1pd |= L1_SHARED;
+#endif
+ *pl1pd = l1pd;
+ PTE_SYNC(pl1pd);
+}
+
+/*
+ * pmap_link_l2pt:
+ *
+ * Link the L2 page table specified by l2pv.pv_pa into the L1
+ * page table at the slot for "va".
+ */
+void
+pmap_link_l2pt(vm_offset_t l1pt, vm_offset_t va, struct pv_addr *l2pv)
+{
+ pd_entry_t *pde = (pd_entry_t *) l1pt, proto;
+ u_int slot = va >> L1_S_SHIFT;
+
+ proto = L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_C_PROTO;
+
+#ifdef VERBOSE_INIT_ARM
+ printf("pmap_link_l2pt: pa=0x%x va=0x%x\n", l2pv->pv_pa, l2pv->pv_va);
+#endif
+
+ pde[slot + 0] = proto | (l2pv->pv_pa + 0x000);
+ PTE_SYNC(&pde[slot]);
+
+ SLIST_INSERT_HEAD(&kernel_pt_list, l2pv, pv_list);
+
+}
+
+/*
+ * pmap_map_entry
+ *
+ * Create a single page mapping.
+ */
+void
+pmap_map_entry(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, int prot,
+ int cache)
+{
+ pd_entry_t *pde = (pd_entry_t *) l1pt;
+ pt_entry_t fl;
+ pt_entry_t *ptep;
+
+ KASSERT(((va | pa) & PAGE_MASK) == 0, ("ouin"));
+
+ fl = l2s_mem_types[cache];
+
+ if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C)
+ panic("pmap_map_entry: no L2 table for VA 0x%08x", va);
+
+ ptep = (pt_entry_t *)kernel_pt_lookup(pde[L1_IDX(va)] & L1_C_ADDR_MASK);
+
+ if (ptep == NULL)
+ panic("pmap_map_entry: can't find L2 table for VA 0x%08x", va);
+
+ ptep[l2pte_index(va)] = L2_S_PROTO | pa | fl | L2_S_REF;
+ pmap_set_prot(&ptep[l2pte_index(va)], prot, 0);
+ PTE_SYNC(&ptep[l2pte_index(va)]);
+}
+
+/*
+ * pmap_map_chunk:
+ *
+ * Map a chunk of memory using the most efficient mappings
+ * possible (section. large page, small page) into the
+ * provided L1 and L2 tables at the specified virtual address.
+ */
+vm_size_t
+pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa,
+ vm_size_t size, int prot, int type)
+{
+ pd_entry_t *pde = (pd_entry_t *) l1pt;
+ pt_entry_t *ptep, f1, f2s, f2l;
+ vm_size_t resid;
+ int i;
+
+ resid = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+
+ if (l1pt == 0)
+ panic("pmap_map_chunk: no L1 table provided");
+
+#ifdef VERBOSE_INIT_ARM
+ printf("pmap_map_chunk: pa=0x%x va=0x%x size=0x%x resid=0x%x "
+ "prot=0x%x type=%d\n", pa, va, size, resid, prot, type);
+#endif
+
+ f1 = l1_mem_types[type];
+ f2l = l2l_mem_types[type];
+ f2s = l2s_mem_types[type];
+
+ size = resid;
+
+ while (resid > 0) {
+ /* See if we can use a section mapping. */
+ if (L1_S_MAPPABLE_P(va, pa, resid)) {
+#ifdef VERBOSE_INIT_ARM
+ printf("S");
+#endif
+ pde[va >> L1_S_SHIFT] = L1_S_PROTO | pa |
+ L1_S_PROT(PTE_KERNEL, prot | VM_PROT_EXECUTE) |
+ f1 | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_REF;
+ PTE_SYNC(&pde[va >> L1_S_SHIFT]);
+ va += L1_S_SIZE;
+ pa += L1_S_SIZE;
+ resid -= L1_S_SIZE;
+ continue;
+ }
+
+ /*
+ * Ok, we're going to use an L2 table. Make sure
+ * one is actually in the corresponding L1 slot
+ * for the current VA.
+ */
+ if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C)
+ panic("pmap_map_chunk: no L2 table for VA 0x%08x", va);
+
+ ptep = (pt_entry_t *) kernel_pt_lookup(
+ pde[L1_IDX(va)] & L1_C_ADDR_MASK);
+ if (ptep == NULL)
+ panic("pmap_map_chunk: can't find L2 table for VA"
+ "0x%08x", va);
+ /* See if we can use a L2 large page mapping. */
+ if (L2_L_MAPPABLE_P(va, pa, resid)) {
+#ifdef VERBOSE_INIT_ARM
+ printf("L");
+#endif
+ for (i = 0; i < 16; i++) {
+ ptep[l2pte_index(va) + i] =
+ L2_L_PROTO | pa |
+ L2_L_PROT(PTE_KERNEL, prot) | f2l;
+ PTE_SYNC(&ptep[l2pte_index(va) + i]);
+ }
+ va += L2_L_SIZE;
+ pa += L2_L_SIZE;
+ resid -= L2_L_SIZE;
+ continue;
+ }
+
+ /* Use a small page mapping. */
+#ifdef VERBOSE_INIT_ARM
+ printf("P");
+#endif
+ ptep[l2pte_index(va)] = L2_S_PROTO | pa | f2s | L2_S_REF;
+ pmap_set_prot(&ptep[l2pte_index(va)], prot, 0);
+ PTE_SYNC(&ptep[l2pte_index(va)]);
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ resid -= PAGE_SIZE;
+ }
+#ifdef VERBOSE_INIT_ARM
+ printf("\n");
+#endif
+ return (size);
+
+}
+
+int
+pmap_dmap_iscurrent(pmap_t pmap)
+{
+ return(pmap_is_current(pmap));
+}
+
+void
+pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
+{
+ /*
+ * Remember the memattr in a field that gets used to set the appropriate
+ * bits in the PTEs as mappings are established.
+ */
+ m->md.pv_memattr = ma;
+
+ /*
+ * It appears that this function can only be called before any mappings
+ * for the page are established on ARM. If this ever changes, this code
+ * will need to walk the pv_list and make each of the existing mappings
+ * uncacheable, being careful to sync caches and PTEs (and maybe
+ * invalidate TLB?) for any current mapping it modifies.
+ */
+ if (TAILQ_FIRST(&m->md.pv_list) != NULL)
+ panic("Can't change memattr on page with existing mappings");
+}
Property changes on: trunk/sys/arm/arm/pmap-v6.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/pmap.c
===================================================================
--- trunk/sys/arm/arm/pmap.c (rev 0)
+++ trunk/sys/arm/arm/pmap.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,4828 @@
+/* $MidnightBSD$ */
+/* From: $NetBSD: pmap.c,v 1.148 2004/04/03 04:35:48 bsh Exp $ */
+/*-
+ * Copyright 2004 Olivier Houchard.
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2002-2003 Wasabi Systems, Inc.
+ * Copyright (c) 2001 Richard Earnshaw
+ * Copyright (c) 2001-2002 Christopher Gilbert
+ * All rights reserved.
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *
+ * RiscBSD kernel project
+ *
+ * pmap.c
+ *
+ * Machine dependant vm stuff
+ *
+ * Created : 20/09/94
+ */
+
+/*
+ * Special compilation symbols
+ * PMAP_DEBUG - Build in pmap_debug_level code
+ *
+ * Note that pmap_mapdev() and pmap_unmapdev() are implemented in arm/devmap.c
+ */
+/* Include header files */
+
+#include "opt_vm.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/pmap.c 283931 2015-06-02 21:36:45Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/vmmeter.h>
+#include <sys/mman.h>
+#include <sys/rwlock.h>
+#include <sys/smp.h>
+#include <sys/sched.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/uma.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_object.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_phys.h>
+#include <vm/vm_extern.h>
+
+#include <machine/md_var.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/pcb.h>
+
+#ifdef PMAP_DEBUG
+#define PDEBUG(_lev_,_stat_) \
+ if (pmap_debug_level >= (_lev_)) \
+ ((_stat_))
+#define dprintf printf
+
+int pmap_debug_level = 0;
+#define PMAP_INLINE
+#else /* PMAP_DEBUG */
+#define PDEBUG(_lev_,_stat_) /* Nothing */
+#define dprintf(x, arg...)
+#define PMAP_INLINE __inline
+#endif /* PMAP_DEBUG */
+
+extern struct pv_addr systempage;
+
+extern int last_fault_code;
+
+/*
+ * Internal function prototypes
+ */
+static void pmap_free_pv_entry (pv_entry_t);
+static pv_entry_t pmap_get_pv_entry(void);
+
+static int pmap_enter_locked(pmap_t, vm_offset_t, vm_page_t,
+ vm_prot_t, u_int);
+static vm_paddr_t pmap_extract_locked(pmap_t pmap, vm_offset_t va);
+static void pmap_fix_cache(struct vm_page *, pmap_t, vm_offset_t);
+static void pmap_alloc_l1(pmap_t);
+static void pmap_free_l1(pmap_t);
+
+static int pmap_clearbit(struct vm_page *, u_int);
+
+static struct l2_bucket *pmap_get_l2_bucket(pmap_t, vm_offset_t);
+static struct l2_bucket *pmap_alloc_l2_bucket(pmap_t, vm_offset_t);
+static void pmap_free_l2_bucket(pmap_t, struct l2_bucket *, u_int);
+static vm_offset_t kernel_pt_lookup(vm_paddr_t);
+
+static MALLOC_DEFINE(M_VMPMAP, "pmap", "PMAP L1");
+
+vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */
+vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
+vm_offset_t pmap_curmaxkvaddr;
+vm_paddr_t kernel_l1pa;
+
+vm_offset_t kernel_vm_end = 0;
+
+vm_offset_t vm_max_kernel_address;
+
+struct pmap kernel_pmap_store;
+
+static pt_entry_t *csrc_pte, *cdst_pte;
+static vm_offset_t csrcp, cdstp;
+static struct mtx cmtx;
+
+static void pmap_init_l1(struct l1_ttable *, pd_entry_t *);
+/*
+ * These routines are called when the CPU type is identified to set up
+ * the PTE prototypes, cache modes, etc.
+ *
+ * The variables are always here, just in case LKMs need to reference
+ * them (though, they shouldn't).
+ */
+
+pt_entry_t pte_l1_s_cache_mode;
+pt_entry_t pte_l1_s_cache_mode_pt;
+pt_entry_t pte_l1_s_cache_mask;
+
+pt_entry_t pte_l2_l_cache_mode;
+pt_entry_t pte_l2_l_cache_mode_pt;
+pt_entry_t pte_l2_l_cache_mask;
+
+pt_entry_t pte_l2_s_cache_mode;
+pt_entry_t pte_l2_s_cache_mode_pt;
+pt_entry_t pte_l2_s_cache_mask;
+
+pt_entry_t pte_l2_s_prot_u;
+pt_entry_t pte_l2_s_prot_w;
+pt_entry_t pte_l2_s_prot_mask;
+
+pt_entry_t pte_l1_s_proto;
+pt_entry_t pte_l1_c_proto;
+pt_entry_t pte_l2_s_proto;
+
+void (*pmap_copy_page_func)(vm_paddr_t, vm_paddr_t);
+void (*pmap_copy_page_offs_func)(vm_paddr_t a_phys,
+ vm_offset_t a_offs, vm_paddr_t b_phys, vm_offset_t b_offs,
+ int cnt);
+void (*pmap_zero_page_func)(vm_paddr_t, int, int);
+
+struct msgbuf *msgbufp = 0;
+
+/*
+ * Crashdump maps.
+ */
+static caddr_t crashdumpmap;
+
+extern void bcopy_page(vm_offset_t, vm_offset_t);
+extern void bzero_page(vm_offset_t);
+
+extern vm_offset_t alloc_firstaddr;
+
+char *_tmppt;
+
+/*
+ * Metadata for L1 translation tables.
+ */
+struct l1_ttable {
+ /* Entry on the L1 Table list */
+ SLIST_ENTRY(l1_ttable) l1_link;
+
+ /* Entry on the L1 Least Recently Used list */
+ TAILQ_ENTRY(l1_ttable) l1_lru;
+
+ /* Track how many domains are allocated from this L1 */
+ volatile u_int l1_domain_use_count;
+
+ /*
+ * A free-list of domain numbers for this L1.
+ * We avoid using ffs() and a bitmap to track domains since ffs()
+ * is slow on ARM.
+ */
+ u_int8_t l1_domain_first;
+ u_int8_t l1_domain_free[PMAP_DOMAINS];
+
+ /* Physical address of this L1 page table */
+ vm_paddr_t l1_physaddr;
+
+ /* KVA of this L1 page table */
+ pd_entry_t *l1_kva;
+};
+
+/*
+ * Convert a virtual address into its L1 table index. That is, the
+ * index used to locate the L2 descriptor table pointer in an L1 table.
+ * This is basically used to index l1->l1_kva[].
+ *
+ * Each L2 descriptor table represents 1MB of VA space.
+ */
+#define L1_IDX(va) (((vm_offset_t)(va)) >> L1_S_SHIFT)
+
+/*
+ * L1 Page Tables are tracked using a Least Recently Used list.
+ * - New L1s are allocated from the HEAD.
+ * - Freed L1s are added to the TAIl.
+ * - Recently accessed L1s (where an 'access' is some change to one of
+ * the userland pmaps which owns this L1) are moved to the TAIL.
+ */
+static TAILQ_HEAD(, l1_ttable) l1_lru_list;
+/*
+ * A list of all L1 tables
+ */
+static SLIST_HEAD(, l1_ttable) l1_list;
+static struct mtx l1_lru_lock;
+
+/*
+ * The l2_dtable tracks L2_BUCKET_SIZE worth of L1 slots.
+ *
+ * This is normally 16MB worth L2 page descriptors for any given pmap.
+ * Reference counts are maintained for L2 descriptors so they can be
+ * freed when empty.
+ */
+struct l2_dtable {
+ /* The number of L2 page descriptors allocated to this l2_dtable */
+ u_int l2_occupancy;
+
+ /* List of L2 page descriptors */
+ struct l2_bucket {
+ pt_entry_t *l2b_kva; /* KVA of L2 Descriptor Table */
+ vm_paddr_t l2b_phys; /* Physical address of same */
+ u_short l2b_l1idx; /* This L2 table's L1 index */
+ u_short l2b_occupancy; /* How many active descriptors */
+ } l2_bucket[L2_BUCKET_SIZE];
+};
+
+/* pmap_kenter_internal flags */
+#define KENTER_CACHE 0x1
+#define KENTER_USER 0x2
+
+/*
+ * Given an L1 table index, calculate the corresponding l2_dtable index
+ * and bucket index within the l2_dtable.
+ */
+#define L2_IDX(l1idx) (((l1idx) >> L2_BUCKET_LOG2) & \
+ (L2_SIZE - 1))
+#define L2_BUCKET(l1idx) ((l1idx) & (L2_BUCKET_SIZE - 1))
+
+/*
+ * Given a virtual address, this macro returns the
+ * virtual address required to drop into the next L2 bucket.
+ */
+#define L2_NEXT_BUCKET(va) (((va) & L1_S_FRAME) + L1_S_SIZE)
+
+/*
+ * We try to map the page tables write-through, if possible. However, not
+ * all CPUs have a write-through cache mode, so on those we have to sync
+ * the cache when we frob page tables.
+ *
+ * We try to evaluate this at compile time, if possible. However, it's
+ * not always possible to do that, hence this run-time var.
+ */
+int pmap_needs_pte_sync;
+
+/*
+ * Macro to determine if a mapping might be resident in the
+ * instruction cache and/or TLB
+ */
+#define PV_BEEN_EXECD(f) (((f) & (PVF_REF | PVF_EXEC)) == (PVF_REF | PVF_EXEC))
+
+/*
+ * Macro to determine if a mapping might be resident in the
+ * data cache and/or TLB
+ */
+#define PV_BEEN_REFD(f) (((f) & PVF_REF) != 0)
+
+#ifndef PMAP_SHPGPERPROC
+#define PMAP_SHPGPERPROC 200
+#endif
+
+#define pmap_is_current(pm) ((pm) == pmap_kernel() || \
+ curproc->p_vmspace->vm_map.pmap == (pm))
+static uma_zone_t pvzone = NULL;
+uma_zone_t l2zone;
+static uma_zone_t l2table_zone;
+static vm_offset_t pmap_kernel_l2dtable_kva;
+static vm_offset_t pmap_kernel_l2ptp_kva;
+static vm_paddr_t pmap_kernel_l2ptp_phys;
+static int pv_entry_count=0, pv_entry_max=0, pv_entry_high_water=0;
+static struct rwlock pvh_global_lock;
+
+void pmap_copy_page_offs_generic(vm_paddr_t a_phys, vm_offset_t a_offs,
+ vm_paddr_t b_phys, vm_offset_t b_offs, int cnt);
+#if ARM_MMU_XSCALE == 1
+void pmap_copy_page_offs_xscale(vm_paddr_t a_phys, vm_offset_t a_offs,
+ vm_paddr_t b_phys, vm_offset_t b_offs, int cnt);
+#endif
+
+/*
+ * This list exists for the benefit of pmap_map_chunk(). It keeps track
+ * of the kernel L2 tables during bootstrap, so that pmap_map_chunk() can
+ * find them as necessary.
+ *
+ * Note that the data on this list MUST remain valid after initarm() returns,
+ * as pmap_bootstrap() uses it to contruct L2 table metadata.
+ */
+SLIST_HEAD(, pv_addr) kernel_pt_list = SLIST_HEAD_INITIALIZER(kernel_pt_list);
+
+static void
+pmap_init_l1(struct l1_ttable *l1, pd_entry_t *l1pt)
+{
+ int i;
+
+ l1->l1_kva = l1pt;
+ l1->l1_domain_use_count = 0;
+ l1->l1_domain_first = 0;
+
+ for (i = 0; i < PMAP_DOMAINS; i++)
+ l1->l1_domain_free[i] = i + 1;
+
+ /*
+ * Copy the kernel's L1 entries to each new L1.
+ */
+ if (l1pt != pmap_kernel()->pm_l1->l1_kva)
+ memcpy(l1pt, pmap_kernel()->pm_l1->l1_kva, L1_TABLE_SIZE);
+
+ if ((l1->l1_physaddr = pmap_extract(pmap_kernel(), (vm_offset_t)l1pt)) == 0)
+ panic("pmap_init_l1: can't get PA of L1 at %p", l1pt);
+ SLIST_INSERT_HEAD(&l1_list, l1, l1_link);
+ TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
+}
+
+static vm_offset_t
+kernel_pt_lookup(vm_paddr_t pa)
+{
+ struct pv_addr *pv;
+
+ SLIST_FOREACH(pv, &kernel_pt_list, pv_list) {
+ if (pv->pv_pa == pa)
+ return (pv->pv_va);
+ }
+ return (0);
+}
+
+#if ARM_MMU_GENERIC != 0
+void
+pmap_pte_init_generic(void)
+{
+
+ pte_l1_s_cache_mode = L1_S_B|L1_S_C;
+ pte_l1_s_cache_mask = L1_S_CACHE_MASK_generic;
+
+ pte_l2_l_cache_mode = L2_B|L2_C;
+ pte_l2_l_cache_mask = L2_L_CACHE_MASK_generic;
+
+ pte_l2_s_cache_mode = L2_B|L2_C;
+ pte_l2_s_cache_mask = L2_S_CACHE_MASK_generic;
+
+ /*
+ * If we have a write-through cache, set B and C. If
+ * we have a write-back cache, then we assume setting
+ * only C will make those pages write-through.
+ */
+ if (cpufuncs.cf_dcache_wb_range == (void *) cpufunc_nullop) {
+ pte_l1_s_cache_mode_pt = L1_S_B|L1_S_C;
+ pte_l2_l_cache_mode_pt = L2_B|L2_C;
+ pte_l2_s_cache_mode_pt = L2_B|L2_C;
+ } else {
+ pte_l1_s_cache_mode_pt = L1_S_C;
+ pte_l2_l_cache_mode_pt = L2_C;
+ pte_l2_s_cache_mode_pt = L2_C;
+ }
+
+ pte_l2_s_prot_u = L2_S_PROT_U_generic;
+ pte_l2_s_prot_w = L2_S_PROT_W_generic;
+ pte_l2_s_prot_mask = L2_S_PROT_MASK_generic;
+
+ pte_l1_s_proto = L1_S_PROTO_generic;
+ pte_l1_c_proto = L1_C_PROTO_generic;
+ pte_l2_s_proto = L2_S_PROTO_generic;
+
+ pmap_copy_page_func = pmap_copy_page_generic;
+ pmap_copy_page_offs_func = pmap_copy_page_offs_generic;
+ pmap_zero_page_func = pmap_zero_page_generic;
+}
+
+#if defined(CPU_ARM9) && defined(ARM9_CACHE_WRITE_THROUGH)
+void
+pmap_pte_init_arm9(void)
+{
+
+ /*
+ * ARM9 is compatible with generic, but we want to use
+ * write-through caching for now.
+ */
+ pmap_pte_init_generic();
+
+ pte_l1_s_cache_mode = L1_S_C;
+ pte_l2_l_cache_mode = L2_C;
+ pte_l2_s_cache_mode = L2_C;
+
+ pte_l1_s_cache_mode_pt = L1_S_C;
+ pte_l2_l_cache_mode_pt = L2_C;
+ pte_l2_s_cache_mode_pt = L2_C;
+}
+#endif /* CPU_ARM9 */
+#endif /* ARM_MMU_GENERIC != 0 */
+
+#if defined(CPU_ARM10)
+void
+pmap_pte_init_arm10(void)
+{
+
+ /*
+ * ARM10 is compatible with generic, but we want to use
+ * write-through caching for now.
+ */
+ pmap_pte_init_generic();
+
+ pte_l1_s_cache_mode = L1_S_B | L1_S_C;
+ pte_l2_l_cache_mode = L2_B | L2_C;
+ pte_l2_s_cache_mode = L2_B | L2_C;
+
+ pte_l1_s_cache_mode_pt = L1_S_C;
+ pte_l2_l_cache_mode_pt = L2_C;
+ pte_l2_s_cache_mode_pt = L2_C;
+
+}
+#endif /* CPU_ARM10 */
+
+#if ARM_MMU_XSCALE == 1
+#if (ARM_NMMUS > 1) || defined (CPU_XSCALE_CORE3)
+static u_int xscale_use_minidata;
+#endif
+
+void
+pmap_pte_init_xscale(void)
+{
+ uint32_t auxctl;
+ int write_through = 0;
+
+ pte_l1_s_cache_mode = L1_S_B|L1_S_C|L1_S_XSCALE_P;
+ pte_l1_s_cache_mask = L1_S_CACHE_MASK_xscale;
+
+ pte_l2_l_cache_mode = L2_B|L2_C;
+ pte_l2_l_cache_mask = L2_L_CACHE_MASK_xscale;
+
+ pte_l2_s_cache_mode = L2_B|L2_C;
+ pte_l2_s_cache_mask = L2_S_CACHE_MASK_xscale;
+
+ pte_l1_s_cache_mode_pt = L1_S_C;
+ pte_l2_l_cache_mode_pt = L2_C;
+ pte_l2_s_cache_mode_pt = L2_C;
+#ifdef XSCALE_CACHE_READ_WRITE_ALLOCATE
+ /*
+ * The XScale core has an enhanced mode where writes that
+ * miss the cache cause a cache line to be allocated. This
+ * is significantly faster than the traditional, write-through
+ * behavior of this case.
+ */
+ pte_l1_s_cache_mode |= L1_S_XSCALE_TEX(TEX_XSCALE_X);
+ pte_l2_l_cache_mode |= L2_XSCALE_L_TEX(TEX_XSCALE_X);
+ pte_l2_s_cache_mode |= L2_XSCALE_T_TEX(TEX_XSCALE_X);
+#endif /* XSCALE_CACHE_READ_WRITE_ALLOCATE */
+#ifdef XSCALE_CACHE_WRITE_THROUGH
+ /*
+ * Some versions of the XScale core have various bugs in
+ * their cache units, the work-around for which is to run
+ * the cache in write-through mode. Unfortunately, this
+ * has a major (negative) impact on performance. So, we
+ * go ahead and run fast-and-loose, in the hopes that we
+ * don't line up the planets in a way that will trip the
+ * bugs.
+ *
+ * However, we give you the option to be slow-but-correct.
+ */
+ write_through = 1;
+#elif defined(XSCALE_CACHE_WRITE_BACK)
+ /* force write back cache mode */
+ write_through = 0;
+#elif defined(CPU_XSCALE_PXA2X0)
+ /*
+ * Intel PXA2[15]0 processors are known to have a bug in
+ * write-back cache on revision 4 and earlier (stepping
+ * A[01] and B[012]). Fixed for C0 and later.
+ */
+ {
+ uint32_t id, type;
+
+ id = cpufunc_id();
+ type = id & ~(CPU_ID_XSCALE_COREREV_MASK|CPU_ID_REVISION_MASK);
+
+ if (type == CPU_ID_PXA250 || type == CPU_ID_PXA210) {
+ if ((id & CPU_ID_REVISION_MASK) < 5) {
+ /* write through for stepping A0-1 and B0-2 */
+ write_through = 1;
+ }
+ }
+ }
+#endif /* XSCALE_CACHE_WRITE_THROUGH */
+
+ if (write_through) {
+ pte_l1_s_cache_mode = L1_S_C;
+ pte_l2_l_cache_mode = L2_C;
+ pte_l2_s_cache_mode = L2_C;
+ }
+
+#if (ARM_NMMUS > 1)
+ xscale_use_minidata = 1;
+#endif
+
+ pte_l2_s_prot_u = L2_S_PROT_U_xscale;
+ pte_l2_s_prot_w = L2_S_PROT_W_xscale;
+ pte_l2_s_prot_mask = L2_S_PROT_MASK_xscale;
+
+ pte_l1_s_proto = L1_S_PROTO_xscale;
+ pte_l1_c_proto = L1_C_PROTO_xscale;
+ pte_l2_s_proto = L2_S_PROTO_xscale;
+
+#ifdef CPU_XSCALE_CORE3
+ pmap_copy_page_func = pmap_copy_page_generic;
+ pmap_copy_page_offs_func = pmap_copy_page_offs_generic;
+ pmap_zero_page_func = pmap_zero_page_generic;
+ xscale_use_minidata = 0;
+ /* Make sure it is L2-cachable */
+ pte_l1_s_cache_mode |= L1_S_XSCALE_TEX(TEX_XSCALE_T);
+ pte_l1_s_cache_mode_pt = pte_l1_s_cache_mode &~ L1_S_XSCALE_P;
+ pte_l2_l_cache_mode |= L2_XSCALE_L_TEX(TEX_XSCALE_T) ;
+ pte_l2_l_cache_mode_pt = pte_l1_s_cache_mode;
+ pte_l2_s_cache_mode |= L2_XSCALE_T_TEX(TEX_XSCALE_T);
+ pte_l2_s_cache_mode_pt = pte_l2_s_cache_mode;
+
+#else
+ pmap_copy_page_func = pmap_copy_page_xscale;
+ pmap_copy_page_offs_func = pmap_copy_page_offs_xscale;
+ pmap_zero_page_func = pmap_zero_page_xscale;
+#endif
+
+ /*
+ * Disable ECC protection of page table access, for now.
+ */
+ __asm __volatile("mrc p15, 0, %0, c1, c0, 1" : "=r" (auxctl));
+ auxctl &= ~XSCALE_AUXCTL_P;
+ __asm __volatile("mcr p15, 0, %0, c1, c0, 1" : : "r" (auxctl));
+}
+
+/*
+ * xscale_setup_minidata:
+ *
+ * Set up the mini-data cache clean area. We require the
+ * caller to allocate the right amount of physically and
+ * virtually contiguous space.
+ */
+extern vm_offset_t xscale_minidata_clean_addr;
+extern vm_size_t xscale_minidata_clean_size; /* already initialized */
+void
+xscale_setup_minidata(vm_offset_t l1pt, vm_offset_t va, vm_paddr_t pa)
+{
+ pd_entry_t *pde = (pd_entry_t *) l1pt;
+ pt_entry_t *pte;
+ vm_size_t size;
+ uint32_t auxctl;
+
+ xscale_minidata_clean_addr = va;
+
+ /* Round it to page size. */
+ size = (xscale_minidata_clean_size + L2_S_OFFSET) & L2_S_FRAME;
+
+ for (; size != 0;
+ va += L2_S_SIZE, pa += L2_S_SIZE, size -= L2_S_SIZE) {
+ pte = (pt_entry_t *) kernel_pt_lookup(
+ pde[L1_IDX(va)] & L1_C_ADDR_MASK);
+ if (pte == NULL)
+ panic("xscale_setup_minidata: can't find L2 table for "
+ "VA 0x%08x", (u_int32_t) va);
+ pte[l2pte_index(va)] =
+ L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, VM_PROT_READ) |
+ L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X);
+ }
+
+ /*
+ * Configure the mini-data cache for write-back with
+ * read/write-allocate.
+ *
+ * NOTE: In order to reconfigure the mini-data cache, we must
+ * make sure it contains no valid data! In order to do that,
+ * we must issue a global data cache invalidate command!
+ *
+ * WE ASSUME WE ARE RUNNING UN-CACHED WHEN THIS ROUTINE IS CALLED!
+ * THIS IS VERY IMPORTANT!
+ */
+
+ /* Invalidate data and mini-data. */
+ __asm __volatile("mcr p15, 0, %0, c7, c6, 0" : : "r" (0));
+ __asm __volatile("mrc p15, 0, %0, c1, c0, 1" : "=r" (auxctl));
+ auxctl = (auxctl & ~XSCALE_AUXCTL_MD_MASK) | XSCALE_AUXCTL_MD_WB_RWA;
+ __asm __volatile("mcr p15, 0, %0, c1, c0, 1" : : "r" (auxctl));
+}
+#endif
+
+/*
+ * Allocate an L1 translation table for the specified pmap.
+ * This is called at pmap creation time.
+ */
+static void
+pmap_alloc_l1(pmap_t pm)
+{
+ struct l1_ttable *l1;
+ u_int8_t domain;
+
+ /*
+ * Remove the L1 at the head of the LRU list
+ */
+ mtx_lock(&l1_lru_lock);
+ l1 = TAILQ_FIRST(&l1_lru_list);
+ TAILQ_REMOVE(&l1_lru_list, l1, l1_lru);
+
+ /*
+ * Pick the first available domain number, and update
+ * the link to the next number.
+ */
+ domain = l1->l1_domain_first;
+ l1->l1_domain_first = l1->l1_domain_free[domain];
+
+ /*
+ * If there are still free domain numbers in this L1,
+ * put it back on the TAIL of the LRU list.
+ */
+ if (++l1->l1_domain_use_count < PMAP_DOMAINS)
+ TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
+
+ mtx_unlock(&l1_lru_lock);
+
+ /*
+ * Fix up the relevant bits in the pmap structure
+ */
+ pm->pm_l1 = l1;
+ pm->pm_domain = domain + 1;
+}
+
+/*
+ * Free an L1 translation table.
+ * This is called at pmap destruction time.
+ */
+static void
+pmap_free_l1(pmap_t pm)
+{
+ struct l1_ttable *l1 = pm->pm_l1;
+
+ mtx_lock(&l1_lru_lock);
+
+ /*
+ * If this L1 is currently on the LRU list, remove it.
+ */
+ if (l1->l1_domain_use_count < PMAP_DOMAINS)
+ TAILQ_REMOVE(&l1_lru_list, l1, l1_lru);
+
+ /*
+ * Free up the domain number which was allocated to the pmap
+ */
+ l1->l1_domain_free[pm->pm_domain - 1] = l1->l1_domain_first;
+ l1->l1_domain_first = pm->pm_domain - 1;
+ l1->l1_domain_use_count--;
+
+ /*
+ * The L1 now must have at least 1 free domain, so add
+ * it back to the LRU list. If the use count is zero,
+ * put it at the head of the list, otherwise it goes
+ * to the tail.
+ */
+ if (l1->l1_domain_use_count == 0) {
+ TAILQ_INSERT_HEAD(&l1_lru_list, l1, l1_lru);
+ } else
+ TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
+
+ mtx_unlock(&l1_lru_lock);
+}
+
+/*
+ * Returns a pointer to the L2 bucket associated with the specified pmap
+ * and VA, or NULL if no L2 bucket exists for the address.
+ */
+static PMAP_INLINE struct l2_bucket *
+pmap_get_l2_bucket(pmap_t pm, vm_offset_t va)
+{
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ u_short l1idx;
+
+ l1idx = L1_IDX(va);
+
+ if ((l2 = pm->pm_l2[L2_IDX(l1idx)]) == NULL ||
+ (l2b = &l2->l2_bucket[L2_BUCKET(l1idx)])->l2b_kva == NULL)
+ return (NULL);
+
+ return (l2b);
+}
+
+/*
+ * Returns a pointer to the L2 bucket associated with the specified pmap
+ * and VA.
+ *
+ * If no L2 bucket exists, perform the necessary allocations to put an L2
+ * bucket/page table in place.
+ *
+ * Note that if a new L2 bucket/page was allocated, the caller *must*
+ * increment the bucket occupancy counter appropriately *before*
+ * releasing the pmap's lock to ensure no other thread or cpu deallocates
+ * the bucket/page in the meantime.
+ */
+static struct l2_bucket *
+pmap_alloc_l2_bucket(pmap_t pm, vm_offset_t va)
+{
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ u_short l1idx;
+
+ l1idx = L1_IDX(va);
+
+ PMAP_ASSERT_LOCKED(pm);
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ if ((l2 = pm->pm_l2[L2_IDX(l1idx)]) == NULL) {
+ /*
+ * No mapping at this address, as there is
+ * no entry in the L1 table.
+ * Need to allocate a new l2_dtable.
+ */
+ PMAP_UNLOCK(pm);
+ rw_wunlock(&pvh_global_lock);
+ if ((l2 = uma_zalloc(l2table_zone, M_NOWAIT)) == NULL) {
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pm);
+ return (NULL);
+ }
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pm);
+ if (pm->pm_l2[L2_IDX(l1idx)] != NULL) {
+ /*
+ * Someone already allocated the l2_dtable while
+ * we were doing the same.
+ */
+ uma_zfree(l2table_zone, l2);
+ l2 = pm->pm_l2[L2_IDX(l1idx)];
+ } else {
+ bzero(l2, sizeof(*l2));
+ /*
+ * Link it into the parent pmap
+ */
+ pm->pm_l2[L2_IDX(l1idx)] = l2;
+ }
+ }
+
+ l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+
+ /*
+ * Fetch pointer to the L2 page table associated with the address.
+ */
+ if (l2b->l2b_kva == NULL) {
+ pt_entry_t *ptep;
+
+ /*
+ * No L2 page table has been allocated. Chances are, this
+ * is because we just allocated the l2_dtable, above.
+ */
+ PMAP_UNLOCK(pm);
+ rw_wunlock(&pvh_global_lock);
+ ptep = uma_zalloc(l2zone, M_NOWAIT);
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pm);
+ if (l2b->l2b_kva != 0) {
+ /* We lost the race. */
+ uma_zfree(l2zone, ptep);
+ return (l2b);
+ }
+ l2b->l2b_phys = vtophys(ptep);
+ if (ptep == NULL) {
+ /*
+ * Oops, no more L2 page tables available at this
+ * time. We may need to deallocate the l2_dtable
+ * if we allocated a new one above.
+ */
+ if (l2->l2_occupancy == 0) {
+ pm->pm_l2[L2_IDX(l1idx)] = NULL;
+ uma_zfree(l2table_zone, l2);
+ }
+ return (NULL);
+ }
+
+ l2->l2_occupancy++;
+ l2b->l2b_kva = ptep;
+ l2b->l2b_l1idx = l1idx;
+ }
+
+ return (l2b);
+}
+
+static PMAP_INLINE void
+#ifndef PMAP_INCLUDE_PTE_SYNC
+pmap_free_l2_ptp(pt_entry_t *l2)
+#else
+pmap_free_l2_ptp(boolean_t need_sync, pt_entry_t *l2)
+#endif
+{
+#ifdef PMAP_INCLUDE_PTE_SYNC
+ /*
+ * Note: With a write-back cache, we may need to sync this
+ * L2 table before re-using it.
+ * This is because it may have belonged to a non-current
+ * pmap, in which case the cache syncs would have been
+ * skipped when the pages were being unmapped. If the
+ * L2 table were then to be immediately re-allocated to
+ * the *current* pmap, it may well contain stale mappings
+ * which have not yet been cleared by a cache write-back
+ * and so would still be visible to the mmu.
+ */
+ if (need_sync)
+ PTE_SYNC_RANGE(l2, L2_TABLE_SIZE_REAL / sizeof(pt_entry_t));
+#endif
+ uma_zfree(l2zone, l2);
+}
+/*
+ * One or more mappings in the specified L2 descriptor table have just been
+ * invalidated.
+ *
+ * Garbage collect the metadata and descriptor table itself if necessary.
+ *
+ * The pmap lock must be acquired when this is called (not necessary
+ * for the kernel pmap).
+ */
+static void
+pmap_free_l2_bucket(pmap_t pm, struct l2_bucket *l2b, u_int count)
+{
+ struct l2_dtable *l2;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep;
+ u_short l1idx;
+
+
+ /*
+ * Update the bucket's reference count according to how many
+ * PTEs the caller has just invalidated.
+ */
+ l2b->l2b_occupancy -= count;
+
+ /*
+ * Note:
+ *
+ * Level 2 page tables allocated to the kernel pmap are never freed
+ * as that would require checking all Level 1 page tables and
+ * removing any references to the Level 2 page table. See also the
+ * comment elsewhere about never freeing bootstrap L2 descriptors.
+ *
+ * We make do with just invalidating the mapping in the L2 table.
+ *
+ * This isn't really a big deal in practice and, in fact, leads
+ * to a performance win over time as we don't need to continually
+ * alloc/free.
+ */
+ if (l2b->l2b_occupancy > 0 || pm == pmap_kernel())
+ return;
+
+ /*
+ * There are no more valid mappings in this level 2 page table.
+ * Go ahead and NULL-out the pointer in the bucket, then
+ * free the page table.
+ */
+ l1idx = l2b->l2b_l1idx;
+ ptep = l2b->l2b_kva;
+ l2b->l2b_kva = NULL;
+
+ pl1pd = &pm->pm_l1->l1_kva[l1idx];
+
+ /*
+ * If the L1 slot matches the pmap's domain
+ * number, then invalidate it.
+ */
+ l1pd = *pl1pd & (L1_TYPE_MASK | L1_C_DOM_MASK);
+ if (l1pd == (L1_C_DOM(pm->pm_domain) | L1_TYPE_C)) {
+ *pl1pd = 0;
+ PTE_SYNC(pl1pd);
+ }
+
+ /*
+ * Release the L2 descriptor table back to the pool cache.
+ */
+#ifndef PMAP_INCLUDE_PTE_SYNC
+ pmap_free_l2_ptp(ptep);
+#else
+ pmap_free_l2_ptp(!pmap_is_current(pm), ptep);
+#endif
+
+ /*
+ * Update the reference count in the associated l2_dtable
+ */
+ l2 = pm->pm_l2[L2_IDX(l1idx)];
+ if (--l2->l2_occupancy > 0)
+ return;
+
+ /*
+ * There are no more valid mappings in any of the Level 1
+ * slots managed by this l2_dtable. Go ahead and NULL-out
+ * the pointer in the parent pmap and free the l2_dtable.
+ */
+ pm->pm_l2[L2_IDX(l1idx)] = NULL;
+ uma_zfree(l2table_zone, l2);
+}
+
+/*
+ * Pool cache constructors for L2 descriptor tables, metadata and pmap
+ * structures.
+ */
+static int
+pmap_l2ptp_ctor(void *mem, int size, void *arg, int flags)
+{
+#ifndef PMAP_INCLUDE_PTE_SYNC
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, pte;
+
+ vm_offset_t va = (vm_offset_t)mem & ~PAGE_MASK;
+
+ /*
+ * The mappings for these page tables were initially made using
+ * pmap_kenter() by the pool subsystem. Therefore, the cache-
+ * mode will not be right for page table mappings. To avoid
+ * polluting the pmap_kenter() code with a special case for
+ * page tables, we simply fix up the cache-mode here if it's not
+ * correct.
+ */
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ pte = *ptep;
+
+ if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
+ /*
+ * Page tables must have the cache-mode set to
+ * Write-Thru.
+ */
+ *ptep = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt;
+ PTE_SYNC(ptep);
+ cpu_tlb_flushD_SE(va);
+ cpu_cpwait();
+ }
+#endif
+ memset(mem, 0, L2_TABLE_SIZE_REAL);
+ PTE_SYNC_RANGE(mem, L2_TABLE_SIZE_REAL / sizeof(pt_entry_t));
+ return (0);
+}
+
+/*
+ * A bunch of routines to conditionally flush the caches/TLB depending
+ * on whether the specified pmap actually needs to be flushed at any
+ * given time.
+ */
+static PMAP_INLINE void
+pmap_tlb_flushID_SE(pmap_t pm, vm_offset_t va)
+{
+
+ if (pmap_is_current(pm))
+ cpu_tlb_flushID_SE(va);
+}
+
+static PMAP_INLINE void
+pmap_tlb_flushD_SE(pmap_t pm, vm_offset_t va)
+{
+
+ if (pmap_is_current(pm))
+ cpu_tlb_flushD_SE(va);
+}
+
+static PMAP_INLINE void
+pmap_tlb_flushID(pmap_t pm)
+{
+
+ if (pmap_is_current(pm))
+ cpu_tlb_flushID();
+}
+static PMAP_INLINE void
+pmap_tlb_flushD(pmap_t pm)
+{
+
+ if (pmap_is_current(pm))
+ cpu_tlb_flushD();
+}
+
+static int
+pmap_has_valid_mapping(pmap_t pm, vm_offset_t va)
+{
+ pd_entry_t *pde;
+ pt_entry_t *ptep;
+
+ if (pmap_get_pde_pte(pm, va, &pde, &ptep) &&
+ ptep && ((*ptep & L2_TYPE_MASK) != L2_TYPE_INV))
+ return (1);
+
+ return (0);
+}
+
+static PMAP_INLINE void
+pmap_idcache_wbinv_range(pmap_t pm, vm_offset_t va, vm_size_t len)
+{
+ vm_size_t rest;
+
+ CTR4(KTR_PMAP, "pmap_dcache_wbinv_range: pmap %p is_kernel %d va 0x%08x"
+ " len 0x%x ", pm, pm == pmap_kernel(), va, len);
+
+ if (pmap_is_current(pm) || pm == pmap_kernel()) {
+ rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len);
+ while (len > 0) {
+ if (pmap_has_valid_mapping(pm, va)) {
+ cpu_idcache_wbinv_range(va, rest);
+ cpu_l2cache_wbinv_range(va, rest);
+ }
+ len -= rest;
+ va += rest;
+ rest = MIN(PAGE_SIZE, len);
+ }
+ }
+}
+
+static PMAP_INLINE void
+pmap_dcache_wb_range(pmap_t pm, vm_offset_t va, vm_size_t len, boolean_t do_inv,
+ boolean_t rd_only)
+{
+ vm_size_t rest;
+
+ CTR4(KTR_PMAP, "pmap_dcache_wb_range: pmap %p is_kernel %d va 0x%08x "
+ "len 0x%x ", pm, pm == pmap_kernel(), va, len);
+ CTR2(KTR_PMAP, " do_inv %d rd_only %d", do_inv, rd_only);
+
+ if (pmap_is_current(pm)) {
+ rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len);
+ while (len > 0) {
+ if (pmap_has_valid_mapping(pm, va)) {
+ if (do_inv && rd_only) {
+ cpu_dcache_inv_range(va, rest);
+ cpu_l2cache_inv_range(va, rest);
+ } else if (do_inv) {
+ cpu_dcache_wbinv_range(va, rest);
+ cpu_l2cache_wbinv_range(va, rest);
+ } else if (!rd_only) {
+ cpu_dcache_wb_range(va, rest);
+ cpu_l2cache_wb_range(va, rest);
+ }
+ }
+ len -= rest;
+ va += rest;
+
+ rest = MIN(PAGE_SIZE, len);
+ }
+ }
+}
+
+static PMAP_INLINE void
+pmap_idcache_wbinv_all(pmap_t pm)
+{
+
+ if (pmap_is_current(pm)) {
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ }
+}
+
+#ifdef notyet
+static PMAP_INLINE void
+pmap_dcache_wbinv_all(pmap_t pm)
+{
+
+ if (pmap_is_current(pm)) {
+ cpu_dcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ }
+}
+#endif
+
+/*
+ * PTE_SYNC_CURRENT:
+ *
+ * Make sure the pte is written out to RAM.
+ * We need to do this for one of two cases:
+ * - We're dealing with the kernel pmap
+ * - There is no pmap active in the cache/tlb.
+ * - The specified pmap is 'active' in the cache/tlb.
+ */
+#ifdef PMAP_INCLUDE_PTE_SYNC
+#define PTE_SYNC_CURRENT(pm, ptep) \
+do { \
+ if (PMAP_NEEDS_PTE_SYNC && \
+ pmap_is_current(pm)) \
+ PTE_SYNC(ptep); \
+} while (/*CONSTCOND*/0)
+#else
+#define PTE_SYNC_CURRENT(pm, ptep) /* nothing */
+#endif
+
+/*
+ * cacheable == -1 means we must make the entry uncacheable, 1 means
+ * cacheable;
+ */
+static __inline void
+pmap_set_cache_entry(pv_entry_t pv, pmap_t pm, vm_offset_t va, int cacheable)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, pte;
+
+ l2b = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
+ ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+
+ if (cacheable == 1) {
+ pte = (*ptep & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode;
+ if (l2pte_valid(pte)) {
+ if (PV_BEEN_EXECD(pv->pv_flags)) {
+ pmap_tlb_flushID_SE(pv->pv_pmap, pv->pv_va);
+ } else if (PV_BEEN_REFD(pv->pv_flags)) {
+ pmap_tlb_flushD_SE(pv->pv_pmap, pv->pv_va);
+ }
+ }
+ } else {
+ pte = *ptep &~ L2_S_CACHE_MASK;
+ if ((va != pv->pv_va || pm != pv->pv_pmap) &&
+ l2pte_valid(pte)) {
+ if (PV_BEEN_EXECD(pv->pv_flags)) {
+ pmap_idcache_wbinv_range(pv->pv_pmap,
+ pv->pv_va, PAGE_SIZE);
+ pmap_tlb_flushID_SE(pv->pv_pmap, pv->pv_va);
+ } else if (PV_BEEN_REFD(pv->pv_flags)) {
+ pmap_dcache_wb_range(pv->pv_pmap,
+ pv->pv_va, PAGE_SIZE, TRUE,
+ (pv->pv_flags & PVF_WRITE) == 0);
+ pmap_tlb_flushD_SE(pv->pv_pmap,
+ pv->pv_va);
+ }
+ }
+ }
+ *ptep = pte;
+ PTE_SYNC_CURRENT(pv->pv_pmap, ptep);
+}
+
+static void
+pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va)
+{
+ int pmwc = 0;
+ int writable = 0, kwritable = 0, uwritable = 0;
+ int entries = 0, kentries = 0, uentries = 0;
+ struct pv_entry *pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+
+ /* the cache gets written back/invalidated on context switch.
+ * therefore, if a user page shares an entry in the same page or
+ * with the kernel map and at least one is writable, then the
+ * cache entry must be set write-through.
+ */
+
+ TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list) {
+ /* generate a count of the pv_entry uses */
+ if (pv->pv_flags & PVF_WRITE) {
+ if (pv->pv_pmap == pmap_kernel())
+ kwritable++;
+ else if (pv->pv_pmap == pm)
+ uwritable++;
+ writable++;
+ }
+ if (pv->pv_pmap == pmap_kernel())
+ kentries++;
+ else {
+ if (pv->pv_pmap == pm)
+ uentries++;
+ entries++;
+ }
+ }
+ /*
+ * check if the user duplicate mapping has
+ * been removed.
+ */
+ if ((pm != pmap_kernel()) && (((uentries > 1) && uwritable) ||
+ (uwritable > 1)))
+ pmwc = 1;
+
+ TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list) {
+ /* check for user uncachable conditions - order is important */
+ if (pm != pmap_kernel() &&
+ (pv->pv_pmap == pm || pv->pv_pmap == pmap_kernel())) {
+
+ if ((uentries > 1 && uwritable) || uwritable > 1) {
+
+ /* user duplicate mapping */
+ if (pv->pv_pmap != pmap_kernel())
+ pv->pv_flags |= PVF_MWC;
+
+ if (!(pv->pv_flags & PVF_NC)) {
+ pv->pv_flags |= PVF_NC;
+ pmap_set_cache_entry(pv, pm, va, -1);
+ }
+ continue;
+ } else /* no longer a duplicate user */
+ pv->pv_flags &= ~PVF_MWC;
+ }
+
+ /*
+ * check for kernel uncachable conditions
+ * kernel writable or kernel readable with writable user entry
+ */
+ if ((kwritable && (entries || kentries > 1)) ||
+ (kwritable > 1) ||
+ ((kwritable != writable) && kentries &&
+ (pv->pv_pmap == pmap_kernel() ||
+ (pv->pv_flags & PVF_WRITE) ||
+ (pv->pv_flags & PVF_MWC)))) {
+
+ if (!(pv->pv_flags & PVF_NC)) {
+ pv->pv_flags |= PVF_NC;
+ pmap_set_cache_entry(pv, pm, va, -1);
+ }
+ continue;
+ }
+
+ /* kernel and user are cachable */
+ if ((pm == pmap_kernel()) && !(pv->pv_flags & PVF_MWC) &&
+ (pv->pv_flags & PVF_NC)) {
+
+ pv->pv_flags &= ~PVF_NC;
+ if (pg->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
+ pmap_set_cache_entry(pv, pm, va, 1);
+ continue;
+ }
+ /* user is no longer sharable and writable */
+ if (pm != pmap_kernel() &&
+ (pv->pv_pmap == pm || pv->pv_pmap == pmap_kernel()) &&
+ !pmwc && (pv->pv_flags & PVF_NC)) {
+
+ pv->pv_flags &= ~(PVF_NC | PVF_MWC);
+ if (pg->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
+ pmap_set_cache_entry(pv, pm, va, 1);
+ }
+ }
+
+ if ((kwritable == 0) && (writable == 0)) {
+ pg->md.pvh_attrs &= ~PVF_MOD;
+ vm_page_aflag_clear(pg, PGA_WRITEABLE);
+ return;
+ }
+}
+
+/*
+ * Modify pte bits for all ptes corresponding to the given physical address.
+ * We use `maskbits' rather than `clearbits' because we're always passing
+ * constants and the latter would require an extra inversion at run-time.
+ */
+static int
+pmap_clearbit(struct vm_page *pg, u_int maskbits)
+{
+ struct l2_bucket *l2b;
+ struct pv_entry *pv;
+ pt_entry_t *ptep, npte, opte;
+ pmap_t pm;
+ vm_offset_t va;
+ u_int oflags;
+ int count = 0;
+
+ rw_wlock(&pvh_global_lock);
+
+ if (maskbits & PVF_WRITE)
+ maskbits |= PVF_MOD;
+ /*
+ * Clear saved attributes (modify, reference)
+ */
+ pg->md.pvh_attrs &= ~(maskbits & (PVF_MOD | PVF_REF));
+
+ if (TAILQ_EMPTY(&pg->md.pv_list)) {
+ rw_wunlock(&pvh_global_lock);
+ return (0);
+ }
+
+ /*
+ * Loop over all current mappings setting/clearing as appropos
+ */
+ TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list) {
+ va = pv->pv_va;
+ pm = pv->pv_pmap;
+ oflags = pv->pv_flags;
+
+ if (!(oflags & maskbits)) {
+ if ((maskbits & PVF_WRITE) && (pv->pv_flags & PVF_NC)) {
+ if (pg->md.pv_memattr !=
+ VM_MEMATTR_UNCACHEABLE) {
+ PMAP_LOCK(pm);
+ l2b = pmap_get_l2_bucket(pm, va);
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ *ptep |= pte_l2_s_cache_mode;
+ PTE_SYNC(ptep);
+ PMAP_UNLOCK(pm);
+ }
+ pv->pv_flags &= ~(PVF_NC | PVF_MWC);
+ }
+ continue;
+ }
+ pv->pv_flags &= ~maskbits;
+
+ PMAP_LOCK(pm);
+
+ l2b = pmap_get_l2_bucket(pm, va);
+
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ npte = opte = *ptep;
+
+ if (maskbits & (PVF_WRITE|PVF_MOD)) {
+ if ((pv->pv_flags & PVF_NC)) {
+ /*
+ * Entry is not cacheable:
+ *
+ * Don't turn caching on again if this is a
+ * modified emulation. This would be
+ * inconsitent with the settings created by
+ * pmap_fix_cache(). Otherwise, it's safe
+ * to re-enable cacheing.
+ *
+ * There's no need to call pmap_fix_cache()
+ * here: all pages are losing their write
+ * permission.
+ */
+ if (maskbits & PVF_WRITE) {
+ if (pg->md.pv_memattr !=
+ VM_MEMATTR_UNCACHEABLE)
+ npte |= pte_l2_s_cache_mode;
+ pv->pv_flags &= ~(PVF_NC | PVF_MWC);
+ }
+ } else
+ if (opte & L2_S_PROT_W) {
+ vm_page_dirty(pg);
+ /*
+ * Entry is writable/cacheable: check if pmap
+ * is current if it is flush it, otherwise it
+ * won't be in the cache
+ */
+ if (PV_BEEN_EXECD(oflags))
+ pmap_idcache_wbinv_range(pm, pv->pv_va,
+ PAGE_SIZE);
+ else
+ if (PV_BEEN_REFD(oflags))
+ pmap_dcache_wb_range(pm, pv->pv_va,
+ PAGE_SIZE,
+ (maskbits & PVF_REF) ? TRUE : FALSE,
+ FALSE);
+ }
+
+ /* make the pte read only */
+ npte &= ~L2_S_PROT_W;
+ }
+
+ if (maskbits & PVF_REF) {
+ if ((pv->pv_flags & PVF_NC) == 0 &&
+ (maskbits & (PVF_WRITE|PVF_MOD)) == 0) {
+ /*
+ * Check npte here; we may have already
+ * done the wbinv above, and the validity
+ * of the PTE is the same for opte and
+ * npte.
+ */
+ if (npte & L2_S_PROT_W) {
+ if (PV_BEEN_EXECD(oflags))
+ pmap_idcache_wbinv_range(pm,
+ pv->pv_va, PAGE_SIZE);
+ else
+ if (PV_BEEN_REFD(oflags))
+ pmap_dcache_wb_range(pm,
+ pv->pv_va, PAGE_SIZE,
+ TRUE, FALSE);
+ } else
+ if ((npte & L2_TYPE_MASK) != L2_TYPE_INV) {
+ /* XXXJRT need idcache_inv_range */
+ if (PV_BEEN_EXECD(oflags))
+ pmap_idcache_wbinv_range(pm,
+ pv->pv_va, PAGE_SIZE);
+ else
+ if (PV_BEEN_REFD(oflags))
+ pmap_dcache_wb_range(pm,
+ pv->pv_va, PAGE_SIZE,
+ TRUE, TRUE);
+ }
+ }
+
+ /*
+ * Make the PTE invalid so that we will take a
+ * page fault the next time the mapping is
+ * referenced.
+ */
+ npte &= ~L2_TYPE_MASK;
+ npte |= L2_TYPE_INV;
+ }
+
+ if (npte != opte) {
+ count++;
+ *ptep = npte;
+ PTE_SYNC(ptep);
+ /* Flush the TLB entry if a current pmap. */
+ if (PV_BEEN_EXECD(oflags))
+ pmap_tlb_flushID_SE(pm, pv->pv_va);
+ else
+ if (PV_BEEN_REFD(oflags))
+ pmap_tlb_flushD_SE(pm, pv->pv_va);
+ }
+
+ PMAP_UNLOCK(pm);
+
+ }
+
+ if (maskbits & PVF_WRITE)
+ vm_page_aflag_clear(pg, PGA_WRITEABLE);
+ rw_wunlock(&pvh_global_lock);
+ return (count);
+}
+
+/*
+ * main pv_entry manipulation functions:
+ * pmap_enter_pv: enter a mapping onto a vm_page list
+ * pmap_remove_pv: remove a mappiing from a vm_page list
+ *
+ * NOTE: pmap_enter_pv expects to lock the pvh itself
+ * pmap_remove_pv expects the caller to lock the pvh before calling
+ */
+
+/*
+ * pmap_enter_pv: enter a mapping onto a vm_page's PV list
+ *
+ * => caller should hold the proper lock on pvh_global_lock
+ * => caller should have pmap locked
+ * => we will (someday) gain the lock on the vm_page's PV list
+ * => caller should adjust ptp's wire_count before calling
+ * => caller should not adjust pmap's wire_count
+ */
+static void
+pmap_enter_pv(struct vm_page *pg, struct pv_entry *pve, pmap_t pm,
+ vm_offset_t va, u_int flags)
+{
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_ASSERT_LOCKED(pm);
+ if (pg->md.pv_kva != 0) {
+ pve->pv_pmap = kernel_pmap;
+ pve->pv_va = pg->md.pv_kva;
+ pve->pv_flags = PVF_WRITE | PVF_UNMAN;
+ if (pm != kernel_pmap)
+ PMAP_LOCK(kernel_pmap);
+ TAILQ_INSERT_HEAD(&pg->md.pv_list, pve, pv_list);
+ TAILQ_INSERT_HEAD(&kernel_pmap->pm_pvlist, pve, pv_plist);
+ if (pm != kernel_pmap)
+ PMAP_UNLOCK(kernel_pmap);
+ pg->md.pv_kva = 0;
+ if ((pve = pmap_get_pv_entry()) == NULL)
+ panic("pmap_kenter_pv: no pv entries");
+ }
+ pve->pv_pmap = pm;
+ pve->pv_va = va;
+ pve->pv_flags = flags;
+ TAILQ_INSERT_HEAD(&pg->md.pv_list, pve, pv_list);
+ TAILQ_INSERT_HEAD(&pm->pm_pvlist, pve, pv_plist);
+ pg->md.pvh_attrs |= flags & (PVF_REF | PVF_MOD);
+ if (pve->pv_flags & PVF_WIRED)
+ ++pm->pm_stats.wired_count;
+ vm_page_aflag_set(pg, PGA_REFERENCED);
+}
+
+/*
+ *
+ * pmap_find_pv: Find a pv entry
+ *
+ * => caller should hold lock on vm_page
+ */
+static PMAP_INLINE struct pv_entry *
+pmap_find_pv(struct vm_page *pg, pmap_t pm, vm_offset_t va)
+{
+ struct pv_entry *pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list)
+ if (pm == pv->pv_pmap && va == pv->pv_va)
+ break;
+ return (pv);
+}
+
+/*
+ * vector_page_setprot:
+ *
+ * Manipulate the protection of the vector page.
+ */
+void
+vector_page_setprot(int prot)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep;
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), vector_page);
+
+ ptep = &l2b->l2b_kva[l2pte_index(vector_page)];
+
+ *ptep = (*ptep & ~L1_S_PROT_MASK) | L2_S_PROT(PTE_KERNEL, prot);
+ PTE_SYNC(ptep);
+ cpu_tlb_flushD_SE(vector_page);
+ cpu_cpwait();
+}
+
+/*
+ * pmap_remove_pv: try to remove a mapping from a pv_list
+ *
+ * => caller should hold proper lock on pmap_main_lock
+ * => pmap should be locked
+ * => caller should hold lock on vm_page [so that attrs can be adjusted]
+ * => caller should adjust ptp's wire_count and free PTP if needed
+ * => caller should NOT adjust pmap's wire_count
+ * => we return the removed pve
+ */
+
+static void
+pmap_nuke_pv(struct vm_page *pg, pmap_t pm, struct pv_entry *pve)
+{
+
+ struct pv_entry *pv;
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_ASSERT_LOCKED(pm);
+ TAILQ_REMOVE(&pg->md.pv_list, pve, pv_list);
+ TAILQ_REMOVE(&pm->pm_pvlist, pve, pv_plist);
+ if (pve->pv_flags & PVF_WIRED)
+ --pm->pm_stats.wired_count;
+ if (pg->md.pvh_attrs & PVF_MOD)
+ vm_page_dirty(pg);
+ if (TAILQ_FIRST(&pg->md.pv_list) == NULL)
+ pg->md.pvh_attrs &= ~PVF_REF;
+ else
+ vm_page_aflag_set(pg, PGA_REFERENCED);
+ if ((pve->pv_flags & PVF_NC) && ((pm == pmap_kernel()) ||
+ (pve->pv_flags & PVF_WRITE) || !(pve->pv_flags & PVF_MWC)))
+ pmap_fix_cache(pg, pm, 0);
+ else if (pve->pv_flags & PVF_WRITE) {
+ TAILQ_FOREACH(pve, &pg->md.pv_list, pv_list)
+ if (pve->pv_flags & PVF_WRITE)
+ break;
+ if (!pve) {
+ pg->md.pvh_attrs &= ~PVF_MOD;
+ vm_page_aflag_clear(pg, PGA_WRITEABLE);
+ }
+ }
+ pv = TAILQ_FIRST(&pg->md.pv_list);
+ if (pv != NULL && (pv->pv_flags & PVF_UNMAN) &&
+ TAILQ_NEXT(pv, pv_list) == NULL) {
+ pm = kernel_pmap;
+ pg->md.pv_kva = pv->pv_va;
+ /* a recursive pmap_nuke_pv */
+ TAILQ_REMOVE(&pg->md.pv_list, pv, pv_list);
+ TAILQ_REMOVE(&pm->pm_pvlist, pv, pv_plist);
+ if (pv->pv_flags & PVF_WIRED)
+ --pm->pm_stats.wired_count;
+ pg->md.pvh_attrs &= ~PVF_REF;
+ pg->md.pvh_attrs &= ~PVF_MOD;
+ vm_page_aflag_clear(pg, PGA_WRITEABLE);
+ pmap_free_pv_entry(pv);
+ }
+}
+
+static struct pv_entry *
+pmap_remove_pv(struct vm_page *pg, pmap_t pm, vm_offset_t va)
+{
+ struct pv_entry *pve;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ pve = TAILQ_FIRST(&pg->md.pv_list);
+
+ while (pve) {
+ if (pve->pv_pmap == pm && pve->pv_va == va) { /* match? */
+ pmap_nuke_pv(pg, pm, pve);
+ break;
+ }
+ pve = TAILQ_NEXT(pve, pv_list);
+ }
+
+ if (pve == NULL && pg->md.pv_kva == va)
+ pg->md.pv_kva = 0;
+
+ return(pve); /* return removed pve */
+}
+/*
+ *
+ * pmap_modify_pv: Update pv flags
+ *
+ * => caller should hold lock on vm_page [so that attrs can be adjusted]
+ * => caller should NOT adjust pmap's wire_count
+ * => we return the old flags
+ *
+ * Modify a physical-virtual mapping in the pv table
+ */
+static u_int
+pmap_modify_pv(struct vm_page *pg, pmap_t pm, vm_offset_t va,
+ u_int clr_mask, u_int set_mask)
+{
+ struct pv_entry *npv;
+ u_int flags, oflags;
+
+ PMAP_ASSERT_LOCKED(pm);
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ if ((npv = pmap_find_pv(pg, pm, va)) == NULL)
+ return (0);
+
+ /*
+ * There is at least one VA mapping this page.
+ */
+
+ if (clr_mask & (PVF_REF | PVF_MOD))
+ pg->md.pvh_attrs |= set_mask & (PVF_REF | PVF_MOD);
+
+ oflags = npv->pv_flags;
+ npv->pv_flags = flags = (oflags & ~clr_mask) | set_mask;
+
+ if ((flags ^ oflags) & PVF_WIRED) {
+ if (flags & PVF_WIRED)
+ ++pm->pm_stats.wired_count;
+ else
+ --pm->pm_stats.wired_count;
+ }
+
+ if ((flags ^ oflags) & PVF_WRITE)
+ pmap_fix_cache(pg, pm, 0);
+
+ return (oflags);
+}
+
+/* Function to set the debug level of the pmap code */
+#ifdef PMAP_DEBUG
+void
+pmap_debug(int level)
+{
+ pmap_debug_level = level;
+ dprintf("pmap_debug: level=%d\n", pmap_debug_level);
+}
+#endif /* PMAP_DEBUG */
+
+void
+pmap_pinit0(struct pmap *pmap)
+{
+ PDEBUG(1, printf("pmap_pinit0: pmap = %08x\n", (u_int32_t) pmap));
+
+ bcopy(kernel_pmap, pmap, sizeof(*pmap));
+ bzero(&pmap->pm_mtx, sizeof(pmap->pm_mtx));
+ PMAP_LOCK_INIT(pmap);
+}
+
+/*
+ * Initialize a vm_page's machine-dependent fields.
+ */
+void
+pmap_page_init(vm_page_t m)
+{
+
+ TAILQ_INIT(&m->md.pv_list);
+ m->md.pv_memattr = VM_MEMATTR_DEFAULT;
+}
+
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
+void
+pmap_init(void)
+{
+ int shpgperproc = PMAP_SHPGPERPROC;
+
+ l2zone = uma_zcreate("L2 Table", L2_TABLE_SIZE_REAL, pmap_l2ptp_ctor,
+ NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
+ l2table_zone = uma_zcreate("L2 Table", sizeof(struct l2_dtable), NULL,
+ NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
+
+ /*
+ * Initialize the PV entry allocator.
+ */
+ pvzone = uma_zcreate("PV ENTRY", sizeof (struct pv_entry), NULL, NULL,
+ NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
+ TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
+ pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
+ uma_zone_reserve_kva(pvzone, pv_entry_max);
+ pv_entry_high_water = 9 * (pv_entry_max / 10);
+
+ /*
+ * Now it is safe to enable pv_table recording.
+ */
+ PDEBUG(1, printf("pmap_init: done!\n"));
+}
+
+int
+pmap_fault_fixup(pmap_t pm, vm_offset_t va, vm_prot_t ftype, int user)
+{
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep, pte;
+ vm_paddr_t pa;
+ u_int l1idx;
+ int rv = 0;
+
+ l1idx = L1_IDX(va);
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pm);
+
+ /*
+ * If there is no l2_dtable for this address, then the process
+ * has no business accessing it.
+ *
+ * Note: This will catch userland processes trying to access
+ * kernel addresses.
+ */
+ l2 = pm->pm_l2[L2_IDX(l1idx)];
+ if (l2 == NULL)
+ goto out;
+
+ /*
+ * Likewise if there is no L2 descriptor table
+ */
+ l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+ if (l2b->l2b_kva == NULL)
+ goto out;
+
+ /*
+ * Check the PTE itself.
+ */
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ pte = *ptep;
+ if (pte == 0)
+ goto out;
+
+ /*
+ * Catch a userland access to the vector page mapped at 0x0
+ */
+ if (user && (pte & L2_S_PROT_U) == 0)
+ goto out;
+ if (va == vector_page)
+ goto out;
+
+ pa = l2pte_pa(pte);
+
+ if ((ftype & VM_PROT_WRITE) && (pte & L2_S_PROT_W) == 0) {
+ /*
+ * This looks like a good candidate for "page modified"
+ * emulation...
+ */
+ struct pv_entry *pv;
+ struct vm_page *pg;
+
+ /* Extract the physical address of the page */
+ if ((pg = PHYS_TO_VM_PAGE(pa)) == NULL) {
+ goto out;
+ }
+ /* Get the current flags for this page. */
+
+ pv = pmap_find_pv(pg, pm, va);
+ if (pv == NULL) {
+ goto out;
+ }
+
+ /*
+ * Do the flags say this page is writable? If not then it
+ * is a genuine write fault. If yes then the write fault is
+ * our fault as we did not reflect the write access in the
+ * PTE. Now we know a write has occurred we can correct this
+ * and also set the modified bit
+ */
+ if ((pv->pv_flags & PVF_WRITE) == 0) {
+ goto out;
+ }
+
+ pg->md.pvh_attrs |= PVF_REF | PVF_MOD;
+ vm_page_dirty(pg);
+ pv->pv_flags |= PVF_REF | PVF_MOD;
+
+ /*
+ * Re-enable write permissions for the page. No need to call
+ * pmap_fix_cache(), since this is just a
+ * modified-emulation fault, and the PVF_WRITE bit isn't
+ * changing. We've already set the cacheable bits based on
+ * the assumption that we can write to this page.
+ */
+ *ptep = (pte & ~L2_TYPE_MASK) | L2_S_PROTO | L2_S_PROT_W;
+ PTE_SYNC(ptep);
+ rv = 1;
+ } else
+ if ((pte & L2_TYPE_MASK) == L2_TYPE_INV) {
+ /*
+ * This looks like a good candidate for "page referenced"
+ * emulation.
+ */
+ struct pv_entry *pv;
+ struct vm_page *pg;
+
+ /* Extract the physical address of the page */
+ if ((pg = PHYS_TO_VM_PAGE(pa)) == NULL)
+ goto out;
+ /* Get the current flags for this page. */
+
+ pv = pmap_find_pv(pg, pm, va);
+ if (pv == NULL)
+ goto out;
+
+ pg->md.pvh_attrs |= PVF_REF;
+ pv->pv_flags |= PVF_REF;
+
+
+ *ptep = (pte & ~L2_TYPE_MASK) | L2_S_PROTO;
+ PTE_SYNC(ptep);
+ rv = 1;
+ }
+
+ /*
+ * We know there is a valid mapping here, so simply
+ * fix up the L1 if necessary.
+ */
+ pl1pd = &pm->pm_l1->l1_kva[l1idx];
+ l1pd = l2b->l2b_phys | L1_C_DOM(pm->pm_domain) | L1_C_PROTO;
+ if (*pl1pd != l1pd) {
+ *pl1pd = l1pd;
+ PTE_SYNC(pl1pd);
+ rv = 1;
+ }
+
+#ifdef DEBUG
+ /*
+ * If 'rv == 0' at this point, it generally indicates that there is a
+ * stale TLB entry for the faulting address. This happens when two or
+ * more processes are sharing an L1. Since we don't flush the TLB on
+ * a context switch between such processes, we can take domain faults
+ * for mappings which exist at the same VA in both processes. EVEN IF
+ * WE'VE RECENTLY FIXED UP THE CORRESPONDING L1 in pmap_enter(), for
+ * example.
+ *
+ * This is extremely likely to happen if pmap_enter() updated the L1
+ * entry for a recently entered mapping. In this case, the TLB is
+ * flushed for the new mapping, but there may still be TLB entries for
+ * other mappings belonging to other processes in the 1MB range
+ * covered by the L1 entry.
+ *
+ * Since 'rv == 0', we know that the L1 already contains the correct
+ * value, so the fault must be due to a stale TLB entry.
+ *
+ * Since we always need to flush the TLB anyway in the case where we
+ * fixed up the L1, or frobbed the L2 PTE, we effectively deal with
+ * stale TLB entries dynamically.
+ *
+ * However, the above condition can ONLY happen if the current L1 is
+ * being shared. If it happens when the L1 is unshared, it indicates
+ * that other parts of the pmap are not doing their job WRT managing
+ * the TLB.
+ */
+ if (rv == 0 && pm->pm_l1->l1_domain_use_count == 1) {
+ printf("fixup: pm %p, va 0x%lx, ftype %d - nothing to do!\n",
+ pm, (u_long)va, ftype);
+ printf("fixup: l2 %p, l2b %p, ptep %p, pl1pd %p\n",
+ l2, l2b, ptep, pl1pd);
+ printf("fixup: pte 0x%x, l1pd 0x%x, last code 0x%x\n",
+ pte, l1pd, last_fault_code);
+#ifdef DDB
+ Debugger();
+#endif
+ }
+#endif
+
+ cpu_tlb_flushID_SE(va);
+ cpu_cpwait();
+
+ rv = 1;
+
+out:
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pm);
+ return (rv);
+}
+
+void
+pmap_postinit(void)
+{
+ struct l2_bucket *l2b;
+ struct l1_ttable *l1;
+ pd_entry_t *pl1pt;
+ pt_entry_t *ptep, pte;
+ vm_offset_t va, eva;
+ u_int loop, needed;
+
+ needed = (maxproc / PMAP_DOMAINS) + ((maxproc % PMAP_DOMAINS) ? 1 : 0);
+ needed -= 1;
+ l1 = malloc(sizeof(*l1) * needed, M_VMPMAP, M_WAITOK);
+
+ for (loop = 0; loop < needed; loop++, l1++) {
+ /* Allocate a L1 page table */
+ va = (vm_offset_t)contigmalloc(L1_TABLE_SIZE, M_VMPMAP, 0, 0x0,
+ 0xffffffff, L1_TABLE_SIZE, 0);
+
+ if (va == 0)
+ panic("Cannot allocate L1 KVM");
+
+ eva = va + L1_TABLE_SIZE;
+ pl1pt = (pd_entry_t *)va;
+
+ while (va < eva) {
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ pte = *ptep;
+ pte = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt;
+ *ptep = pte;
+ PTE_SYNC(ptep);
+ cpu_tlb_flushD_SE(va);
+
+ va += PAGE_SIZE;
+ }
+ pmap_init_l1(l1, pl1pt);
+ }
+
+
+#ifdef DEBUG
+ printf("pmap_postinit: Allocated %d static L1 descriptor tables\n",
+ needed);
+#endif
+}
+
+/*
+ * This is used to stuff certain critical values into the PCB where they
+ * can be accessed quickly from cpu_switch() et al.
+ */
+void
+pmap_set_pcb_pagedir(pmap_t pm, struct pcb *pcb)
+{
+ struct l2_bucket *l2b;
+
+ pcb->pcb_pagedir = pm->pm_l1->l1_physaddr;
+ pcb->pcb_dacr = (DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) |
+ (DOMAIN_CLIENT << (pm->pm_domain * 2));
+
+ if (vector_page < KERNBASE) {
+ pcb->pcb_pl1vec = &pm->pm_l1->l1_kva[L1_IDX(vector_page)];
+ l2b = pmap_get_l2_bucket(pm, vector_page);
+ pcb->pcb_l1vec = l2b->l2b_phys | L1_C_PROTO |
+ L1_C_DOM(pm->pm_domain) | L1_C_DOM(PMAP_DOMAIN_KERNEL);
+ } else
+ pcb->pcb_pl1vec = NULL;
+}
+
+void
+pmap_activate(struct thread *td)
+{
+ pmap_t pm;
+ struct pcb *pcb;
+
+ pm = vmspace_pmap(td->td_proc->p_vmspace);
+ pcb = td->td_pcb;
+
+ critical_enter();
+ pmap_set_pcb_pagedir(pm, pcb);
+
+ if (td == curthread) {
+ u_int cur_dacr, cur_ttb;
+
+ __asm __volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(cur_ttb));
+ __asm __volatile("mrc p15, 0, %0, c3, c0, 0" : "=r"(cur_dacr));
+
+ cur_ttb &= ~(L1_TABLE_SIZE - 1);
+
+ if (cur_ttb == (u_int)pcb->pcb_pagedir &&
+ cur_dacr == pcb->pcb_dacr) {
+ /*
+ * No need to switch address spaces.
+ */
+ critical_exit();
+ return;
+ }
+
+
+ /*
+ * We MUST, I repeat, MUST fix up the L1 entry corresponding
+ * to 'vector_page' in the incoming L1 table before switching
+ * to it otherwise subsequent interrupts/exceptions (including
+ * domain faults!) will jump into hyperspace.
+ */
+ if (pcb->pcb_pl1vec) {
+
+ *pcb->pcb_pl1vec = pcb->pcb_l1vec;
+ /*
+ * Don't need to PTE_SYNC() at this point since
+ * cpu_setttb() is about to flush both the cache
+ * and the TLB.
+ */
+ }
+
+ cpu_domains(pcb->pcb_dacr);
+ cpu_setttb(pcb->pcb_pagedir);
+ }
+ critical_exit();
+}
+
+static int
+pmap_set_pt_cache_mode(pd_entry_t *kl1, vm_offset_t va)
+{
+ pd_entry_t *pdep, pde;
+ pt_entry_t *ptep, pte;
+ vm_offset_t pa;
+ int rv = 0;
+
+ /*
+ * Make sure the descriptor itself has the correct cache mode
+ */
+ pdep = &kl1[L1_IDX(va)];
+ pde = *pdep;
+
+ if (l1pte_section_p(pde)) {
+ if ((pde & L1_S_CACHE_MASK) != pte_l1_s_cache_mode_pt) {
+ *pdep = (pde & ~L1_S_CACHE_MASK) |
+ pte_l1_s_cache_mode_pt;
+ PTE_SYNC(pdep);
+ cpu_dcache_wbinv_range((vm_offset_t)pdep,
+ sizeof(*pdep));
+ cpu_l2cache_wbinv_range((vm_offset_t)pdep,
+ sizeof(*pdep));
+ rv = 1;
+ }
+ } else {
+ pa = (vm_paddr_t)(pde & L1_C_ADDR_MASK);
+ ptep = (pt_entry_t *)kernel_pt_lookup(pa);
+ if (ptep == NULL)
+ panic("pmap_bootstrap: No L2 for L2 @ va %p\n", ptep);
+
+ ptep = &ptep[l2pte_index(va)];
+ pte = *ptep;
+ if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
+ *ptep = (pte & ~L2_S_CACHE_MASK) |
+ pte_l2_s_cache_mode_pt;
+ PTE_SYNC(ptep);
+ cpu_dcache_wbinv_range((vm_offset_t)ptep,
+ sizeof(*ptep));
+ cpu_l2cache_wbinv_range((vm_offset_t)ptep,
+ sizeof(*ptep));
+ rv = 1;
+ }
+ }
+
+ return (rv);
+}
+
+static void
+pmap_alloc_specials(vm_offset_t *availp, int pages, vm_offset_t *vap,
+ pt_entry_t **ptep)
+{
+ vm_offset_t va = *availp;
+ struct l2_bucket *l2b;
+
+ if (ptep) {
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ if (l2b == NULL)
+ panic("pmap_alloc_specials: no l2b for 0x%x", va);
+
+ *ptep = &l2b->l2b_kva[l2pte_index(va)];
+ }
+
+ *vap = va;
+ *availp = va + (PAGE_SIZE * pages);
+}
+
+/*
+ * Bootstrap the system enough to run with virtual memory.
+ *
+ * On the arm this is called after mapping has already been enabled
+ * and just syncs the pmap module with what has already been done.
+ * [We can't call it easily with mapping off since the kernel is not
+ * mapped with PA == VA, hence we would have to relocate every address
+ * from the linked base (virtual) address "KERNBASE" to the actual
+ * (physical) address starting relative to 0]
+ */
+#define PMAP_STATIC_L2_SIZE 16
+void
+pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt)
+{
+ static struct l1_ttable static_l1;
+ static struct l2_dtable static_l2[PMAP_STATIC_L2_SIZE];
+ struct l1_ttable *l1 = &static_l1;
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ pd_entry_t pde;
+ pd_entry_t *kernel_l1pt = (pd_entry_t *)l1pt->pv_va;
+ pt_entry_t *ptep;
+ vm_paddr_t pa;
+ vm_offset_t va;
+ vm_size_t size;
+ int l1idx, l2idx, l2next = 0;
+
+ PDEBUG(1, printf("firstaddr = %08x, lastaddr = %08x\n",
+ firstaddr, vm_max_kernel_address));
+
+ virtual_avail = firstaddr;
+ kernel_pmap->pm_l1 = l1;
+ kernel_l1pa = l1pt->pv_pa;
+
+ /*
+ * Scan the L1 translation table created by initarm() and create
+ * the required metadata for all valid mappings found in it.
+ */
+ for (l1idx = 0; l1idx < (L1_TABLE_SIZE / sizeof(pd_entry_t)); l1idx++) {
+ pde = kernel_l1pt[l1idx];
+
+ /*
+ * We're only interested in Coarse mappings.
+ * pmap_extract() can deal with section mappings without
+ * recourse to checking L2 metadata.
+ */
+ if ((pde & L1_TYPE_MASK) != L1_TYPE_C)
+ continue;
+
+ /*
+ * Lookup the KVA of this L2 descriptor table
+ */
+ pa = (vm_paddr_t)(pde & L1_C_ADDR_MASK);
+ ptep = (pt_entry_t *)kernel_pt_lookup(pa);
+
+ if (ptep == NULL) {
+ panic("pmap_bootstrap: No L2 for va 0x%x, pa 0x%lx",
+ (u_int)l1idx << L1_S_SHIFT, (long unsigned int)pa);
+ }
+
+ /*
+ * Fetch the associated L2 metadata structure.
+ * Allocate a new one if necessary.
+ */
+ if ((l2 = kernel_pmap->pm_l2[L2_IDX(l1idx)]) == NULL) {
+ if (l2next == PMAP_STATIC_L2_SIZE)
+ panic("pmap_bootstrap: out of static L2s");
+ kernel_pmap->pm_l2[L2_IDX(l1idx)] = l2 =
+ &static_l2[l2next++];
+ }
+
+ /*
+ * One more L1 slot tracked...
+ */
+ l2->l2_occupancy++;
+
+ /*
+ * Fill in the details of the L2 descriptor in the
+ * appropriate bucket.
+ */
+ l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+ l2b->l2b_kva = ptep;
+ l2b->l2b_phys = pa;
+ l2b->l2b_l1idx = l1idx;
+
+ /*
+ * Establish an initial occupancy count for this descriptor
+ */
+ for (l2idx = 0;
+ l2idx < (L2_TABLE_SIZE_REAL / sizeof(pt_entry_t));
+ l2idx++) {
+ if ((ptep[l2idx] & L2_TYPE_MASK) != L2_TYPE_INV) {
+ l2b->l2b_occupancy++;
+ }
+ }
+
+ /*
+ * Make sure the descriptor itself has the correct cache mode.
+ * If not, fix it, but whine about the problem. Port-meisters
+ * should consider this a clue to fix up their initarm()
+ * function. :)
+ */
+ if (pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)ptep)) {
+ printf("pmap_bootstrap: WARNING! wrong cache mode for "
+ "L2 pte @ %p\n", ptep);
+ }
+ }
+
+
+ /*
+ * Ensure the primary (kernel) L1 has the correct cache mode for
+ * a page table. Bitch if it is not correctly set.
+ */
+ for (va = (vm_offset_t)kernel_l1pt;
+ va < ((vm_offset_t)kernel_l1pt + L1_TABLE_SIZE); va += PAGE_SIZE) {
+ if (pmap_set_pt_cache_mode(kernel_l1pt, va))
+ printf("pmap_bootstrap: WARNING! wrong cache mode for "
+ "primary L1 @ 0x%x\n", va);
+ }
+
+ cpu_dcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ cpu_tlb_flushID();
+ cpu_cpwait();
+
+ PMAP_LOCK_INIT(kernel_pmap);
+ CPU_FILL(&kernel_pmap->pm_active);
+ kernel_pmap->pm_domain = PMAP_DOMAIN_KERNEL;
+ TAILQ_INIT(&kernel_pmap->pm_pvlist);
+
+ /*
+ * Initialize the global pv list lock.
+ */
+ rw_init_flags(&pvh_global_lock, "pmap pv global", RW_RECURSE);
+
+ /*
+ * Reserve some special page table entries/VA space for temporary
+ * mapping of pages.
+ */
+#define SYSMAP(c, p, v, n) \
+ v = (c)va; va += ((n)*PAGE_SIZE); p = pte; pte += (n);
+
+ pmap_alloc_specials(&virtual_avail, 1, &csrcp, &csrc_pte);
+ pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)csrc_pte);
+ pmap_alloc_specials(&virtual_avail, 1, &cdstp, &cdst_pte);
+ pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)cdst_pte);
+ size = ((vm_max_kernel_address - pmap_curmaxkvaddr) + L1_S_OFFSET) /
+ L1_S_SIZE;
+ pmap_alloc_specials(&virtual_avail,
+ round_page(size * L2_TABLE_SIZE_REAL) / PAGE_SIZE,
+ &pmap_kernel_l2ptp_kva, NULL);
+
+ size = (size + (L2_BUCKET_SIZE - 1)) / L2_BUCKET_SIZE;
+ pmap_alloc_specials(&virtual_avail,
+ round_page(size * sizeof(struct l2_dtable)) / PAGE_SIZE,
+ &pmap_kernel_l2dtable_kva, NULL);
+
+ pmap_alloc_specials(&virtual_avail,
+ 1, (vm_offset_t*)&_tmppt, NULL);
+ pmap_alloc_specials(&virtual_avail,
+ MAXDUMPPGS, (vm_offset_t *)&crashdumpmap, NULL);
+ SLIST_INIT(&l1_list);
+ TAILQ_INIT(&l1_lru_list);
+ mtx_init(&l1_lru_lock, "l1 list lock", NULL, MTX_DEF);
+ pmap_init_l1(l1, kernel_l1pt);
+ cpu_dcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+
+ virtual_avail = round_page(virtual_avail);
+ virtual_end = vm_max_kernel_address;
+ kernel_vm_end = pmap_curmaxkvaddr;
+ mtx_init(&cmtx, "TMP mappings mtx", NULL, MTX_DEF);
+
+ pmap_set_pcb_pagedir(kernel_pmap, thread0.td_pcb);
+}
+
+/***************************************************
+ * Pmap allocation/deallocation routines.
+ ***************************************************/
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+void
+pmap_release(pmap_t pmap)
+{
+ struct pcb *pcb;
+
+ pmap_idcache_wbinv_all(pmap);
+ cpu_l2cache_wbinv_all();
+ pmap_tlb_flushID(pmap);
+ cpu_cpwait();
+ if (vector_page < KERNBASE) {
+ struct pcb *curpcb = PCPU_GET(curpcb);
+ pcb = thread0.td_pcb;
+ if (pmap_is_current(pmap)) {
+ /*
+ * Frob the L1 entry corresponding to the vector
+ * page so that it contains the kernel pmap's domain
+ * number. This will ensure pmap_remove() does not
+ * pull the current vector page out from under us.
+ */
+ critical_enter();
+ *pcb->pcb_pl1vec = pcb->pcb_l1vec;
+ cpu_domains(pcb->pcb_dacr);
+ cpu_setttb(pcb->pcb_pagedir);
+ critical_exit();
+ }
+ pmap_remove(pmap, vector_page, vector_page + PAGE_SIZE);
+ /*
+ * Make sure cpu_switch(), et al, DTRT. This is safe to do
+ * since this process has no remaining mappings of its own.
+ */
+ curpcb->pcb_pl1vec = pcb->pcb_pl1vec;
+ curpcb->pcb_l1vec = pcb->pcb_l1vec;
+ curpcb->pcb_dacr = pcb->pcb_dacr;
+ curpcb->pcb_pagedir = pcb->pcb_pagedir;
+
+ }
+ pmap_free_l1(pmap);
+
+ dprintf("pmap_release()\n");
+}
+
+
+
+/*
+ * Helper function for pmap_grow_l2_bucket()
+ */
+static __inline int
+pmap_grow_map(vm_offset_t va, pt_entry_t cache_mode, vm_paddr_t *pap)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep;
+ vm_paddr_t pa;
+ struct vm_page *pg;
+
+ pg = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_WIRED);
+ if (pg == NULL)
+ return (1);
+ pa = VM_PAGE_TO_PHYS(pg);
+
+ if (pap)
+ *pap = pa;
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+ *ptep = L2_S_PROTO | pa | cache_mode |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_READ | VM_PROT_WRITE);
+ PTE_SYNC(ptep);
+ return (0);
+}
+
+/*
+ * This is the same as pmap_alloc_l2_bucket(), except that it is only
+ * used by pmap_growkernel().
+ */
+static __inline struct l2_bucket *
+pmap_grow_l2_bucket(pmap_t pm, vm_offset_t va)
+{
+ struct l2_dtable *l2;
+ struct l2_bucket *l2b;
+ struct l1_ttable *l1;
+ pd_entry_t *pl1pd;
+ u_short l1idx;
+ vm_offset_t nva;
+
+ l1idx = L1_IDX(va);
+
+ if ((l2 = pm->pm_l2[L2_IDX(l1idx)]) == NULL) {
+ /*
+ * No mapping at this address, as there is
+ * no entry in the L1 table.
+ * Need to allocate a new l2_dtable.
+ */
+ nva = pmap_kernel_l2dtable_kva;
+ if ((nva & PAGE_MASK) == 0) {
+ /*
+ * Need to allocate a backing page
+ */
+ if (pmap_grow_map(nva, pte_l2_s_cache_mode, NULL))
+ return (NULL);
+ }
+
+ l2 = (struct l2_dtable *)nva;
+ nva += sizeof(struct l2_dtable);
+
+ if ((nva & PAGE_MASK) < (pmap_kernel_l2dtable_kva &
+ PAGE_MASK)) {
+ /*
+ * The new l2_dtable straddles a page boundary.
+ * Map in another page to cover it.
+ */
+ if (pmap_grow_map(nva, pte_l2_s_cache_mode, NULL))
+ return (NULL);
+ }
+
+ pmap_kernel_l2dtable_kva = nva;
+
+ /*
+ * Link it into the parent pmap
+ */
+ pm->pm_l2[L2_IDX(l1idx)] = l2;
+ memset(l2, 0, sizeof(*l2));
+ }
+
+ l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+
+ /*
+ * Fetch pointer to the L2 page table associated with the address.
+ */
+ if (l2b->l2b_kva == NULL) {
+ pt_entry_t *ptep;
+
+ /*
+ * No L2 page table has been allocated. Chances are, this
+ * is because we just allocated the l2_dtable, above.
+ */
+ nva = pmap_kernel_l2ptp_kva;
+ ptep = (pt_entry_t *)nva;
+ if ((nva & PAGE_MASK) == 0) {
+ /*
+ * Need to allocate a backing page
+ */
+ if (pmap_grow_map(nva, pte_l2_s_cache_mode_pt,
+ &pmap_kernel_l2ptp_phys))
+ return (NULL);
+ PTE_SYNC_RANGE(ptep, PAGE_SIZE / sizeof(pt_entry_t));
+ }
+ memset(ptep, 0, L2_TABLE_SIZE_REAL);
+ l2->l2_occupancy++;
+ l2b->l2b_kva = ptep;
+ l2b->l2b_l1idx = l1idx;
+ l2b->l2b_phys = pmap_kernel_l2ptp_phys;
+
+ pmap_kernel_l2ptp_kva += L2_TABLE_SIZE_REAL;
+ pmap_kernel_l2ptp_phys += L2_TABLE_SIZE_REAL;
+ }
+
+ /* Distribute new L1 entry to all other L1s */
+ SLIST_FOREACH(l1, &l1_list, l1_link) {
+ pl1pd = &l1->l1_kva[L1_IDX(va)];
+ *pl1pd = l2b->l2b_phys | L1_C_DOM(PMAP_DOMAIN_KERNEL) |
+ L1_C_PROTO;
+ PTE_SYNC(pl1pd);
+ }
+
+ return (l2b);
+}
+
+
+/*
+ * grow the number of kernel page table entries, if needed
+ */
+void
+pmap_growkernel(vm_offset_t addr)
+{
+ pmap_t kpm = pmap_kernel();
+
+ if (addr <= pmap_curmaxkvaddr)
+ return; /* we are OK */
+
+ /*
+ * whoops! we need to add kernel PTPs
+ */
+
+ /* Map 1MB at a time */
+ for (; pmap_curmaxkvaddr < addr; pmap_curmaxkvaddr += L1_S_SIZE)
+ pmap_grow_l2_bucket(kpm, pmap_curmaxkvaddr);
+
+ /*
+ * flush out the cache, expensive but growkernel will happen so
+ * rarely
+ */
+ cpu_dcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ cpu_tlb_flushD();
+ cpu_cpwait();
+ kernel_vm_end = pmap_curmaxkvaddr;
+}
+
+
+/*
+ * Remove all pages from specified address space
+ * this aids process exit speeds. Also, this code
+ * is special cased for current process only, but
+ * can have the more generic (and slightly slower)
+ * mode enabled. This is much faster than pmap_remove
+ * in the case of running down an entire address space.
+ */
+void
+pmap_remove_pages(pmap_t pmap)
+{
+ struct pv_entry *pv, *npv;
+ struct l2_bucket *l2b = NULL;
+ vm_page_t m;
+ pt_entry_t *pt;
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ for (pv = TAILQ_FIRST(&pmap->pm_pvlist); pv; pv = npv) {
+ if (pv->pv_flags & PVF_WIRED || pv->pv_flags & PVF_UNMAN) {
+ /* Cannot remove wired or unmanaged pages now. */
+ npv = TAILQ_NEXT(pv, pv_plist);
+ continue;
+ }
+ pmap->pm_stats.resident_count--;
+ l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
+ KASSERT(l2b != NULL, ("No L2 bucket in pmap_remove_pages"));
+ pt = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+ m = PHYS_TO_VM_PAGE(*pt & L2_ADDR_MASK);
+ KASSERT((vm_offset_t)m >= KERNBASE, ("Trying to access non-existent page va %x pte %x", pv->pv_va, *pt));
+ *pt = 0;
+ PTE_SYNC(pt);
+ npv = TAILQ_NEXT(pv, pv_plist);
+ pmap_nuke_pv(m, pmap, pv);
+ if (TAILQ_EMPTY(&m->md.pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ pmap_free_pv_entry(pv);
+ pmap_free_l2_bucket(pmap, l2b, 1);
+ }
+ rw_wunlock(&pvh_global_lock);
+ cpu_tlb_flushID();
+ cpu_cpwait();
+ PMAP_UNLOCK(pmap);
+}
+
+
+/***************************************************
+ * Low level mapping routines.....
+ ***************************************************/
+
+#ifdef ARM_HAVE_SUPERSECTIONS
+/* Map a super section into the KVA. */
+
+void
+pmap_kenter_supersection(vm_offset_t va, uint64_t pa, int flags)
+{
+ pd_entry_t pd = L1_S_PROTO | L1_S_SUPERSEC | (pa & L1_SUP_FRAME) |
+ (((pa >> 32) & 0xf) << 20) | L1_S_PROT(PTE_KERNEL,
+ VM_PROT_READ|VM_PROT_WRITE) | L1_S_DOM(PMAP_DOMAIN_KERNEL);
+ struct l1_ttable *l1;
+ vm_offset_t va0, va_end;
+
+ KASSERT(((va | pa) & L1_SUP_OFFSET) == 0,
+ ("Not a valid super section mapping"));
+ if (flags & SECTION_CACHE)
+ pd |= pte_l1_s_cache_mode;
+ else if (flags & SECTION_PT)
+ pd |= pte_l1_s_cache_mode_pt;
+ va0 = va & L1_SUP_FRAME;
+ va_end = va + L1_SUP_SIZE;
+ SLIST_FOREACH(l1, &l1_list, l1_link) {
+ va = va0;
+ for (; va < va_end; va += L1_S_SIZE) {
+ l1->l1_kva[L1_IDX(va)] = pd;
+ PTE_SYNC(&l1->l1_kva[L1_IDX(va)]);
+ }
+ }
+}
+#endif
+
+/* Map a section into the KVA. */
+
+void
+pmap_kenter_section(vm_offset_t va, vm_offset_t pa, int flags)
+{
+ pd_entry_t pd = L1_S_PROTO | pa | L1_S_PROT(PTE_KERNEL,
+ VM_PROT_READ|VM_PROT_WRITE) | L1_S_DOM(PMAP_DOMAIN_KERNEL);
+ struct l1_ttable *l1;
+
+ KASSERT(((va | pa) & L1_S_OFFSET) == 0,
+ ("Not a valid section mapping"));
+ if (flags & SECTION_CACHE)
+ pd |= pte_l1_s_cache_mode;
+ else if (flags & SECTION_PT)
+ pd |= pte_l1_s_cache_mode_pt;
+ SLIST_FOREACH(l1, &l1_list, l1_link) {
+ l1->l1_kva[L1_IDX(va)] = pd;
+ PTE_SYNC(&l1->l1_kva[L1_IDX(va)]);
+ }
+}
+
+/*
+ * Make a temporary mapping for a physical address. This is only intended
+ * to be used for panic dumps.
+ */
+void *
+pmap_kenter_temporary(vm_paddr_t pa, int i)
+{
+ vm_offset_t va;
+
+ va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE);
+ pmap_kenter(va, pa);
+ return ((void *)crashdumpmap);
+}
+
+/*
+ * add a wired page to the kva
+ * note that in order for the mapping to take effect -- you
+ * should do a invltlb after doing the pmap_kenter...
+ */
+static PMAP_INLINE void
+pmap_kenter_internal(vm_offset_t va, vm_offset_t pa, int flags)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *pte;
+ pt_entry_t opte;
+ struct pv_entry *pve;
+ vm_page_t m;
+
+ PDEBUG(1, printf("pmap_kenter: va = %08x, pa = %08x\n",
+ (uint32_t) va, (uint32_t) pa));
+
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ if (l2b == NULL)
+ l2b = pmap_grow_l2_bucket(pmap_kernel(), va);
+ KASSERT(l2b != NULL, ("No L2 Bucket"));
+ pte = &l2b->l2b_kva[l2pte_index(va)];
+ opte = *pte;
+ PDEBUG(1, printf("pmap_kenter: pte = %08x, opte = %08x, npte = %08x\n",
+ (uint32_t) pte, opte, *pte));
+ if (l2pte_valid(opte)) {
+ pmap_kremove(va);
+ } else {
+ if (opte == 0)
+ l2b->l2b_occupancy++;
+ }
+ *pte = L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL,
+ VM_PROT_READ | VM_PROT_WRITE);
+ if (flags & KENTER_CACHE)
+ *pte |= pte_l2_s_cache_mode;
+ if (flags & KENTER_USER)
+ *pte |= L2_S_PROT_U;
+ PTE_SYNC(pte);
+
+ /*
+ * A kernel mapping may not be the page's only mapping, so create a PV
+ * entry to ensure proper caching.
+ *
+ * The existence test for the pvzone is used to delay the recording of
+ * kernel mappings until the VM system is fully initialized.
+ *
+ * This expects the physical memory to have a vm_page_array entry.
+ */
+ if (pvzone != NULL && (m = vm_phys_paddr_to_vm_page(pa)) != NULL) {
+ rw_wlock(&pvh_global_lock);
+ if (!TAILQ_EMPTY(&m->md.pv_list) || m->md.pv_kva != 0) {
+ if ((pve = pmap_get_pv_entry()) == NULL)
+ panic("pmap_kenter_internal: no pv entries");
+ PMAP_LOCK(pmap_kernel());
+ pmap_enter_pv(m, pve, pmap_kernel(), va,
+ PVF_WRITE | PVF_UNMAN);
+ pmap_fix_cache(m, pmap_kernel(), va);
+ PMAP_UNLOCK(pmap_kernel());
+ } else {
+ m->md.pv_kva = va;
+ }
+ rw_wunlock(&pvh_global_lock);
+ }
+}
+
+void
+pmap_kenter(vm_offset_t va, vm_paddr_t pa)
+{
+ pmap_kenter_internal(va, pa, KENTER_CACHE);
+}
+
+void
+pmap_kenter_nocache(vm_offset_t va, vm_paddr_t pa)
+{
+
+ pmap_kenter_internal(va, pa, 0);
+}
+
+void
+pmap_kenter_device(vm_offset_t va, vm_paddr_t pa)
+{
+
+ /*
+ * XXX - Need a way for kenter_internal to handle PTE_DEVICE mapping as
+ * a potentially different thing than PTE_NOCACHE.
+ */
+ pmap_kenter_internal(va, pa, 0);
+}
+
+void
+pmap_kenter_user(vm_offset_t va, vm_paddr_t pa)
+{
+
+ pmap_kenter_internal(va, pa, KENTER_CACHE|KENTER_USER);
+ /*
+ * Call pmap_fault_fixup now, to make sure we'll have no exception
+ * at the first use of the new address, or bad things will happen,
+ * as we use one of these addresses in the exception handlers.
+ */
+ pmap_fault_fixup(pmap_kernel(), va, VM_PROT_READ|VM_PROT_WRITE, 1);
+}
+
+vm_paddr_t
+pmap_kextract(vm_offset_t va)
+{
+
+ return (pmap_extract_locked(kernel_pmap, va));
+}
+
+/*
+ * remove a page from the kernel pagetables
+ */
+void
+pmap_kremove(vm_offset_t va)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *pte, opte;
+ struct pv_entry *pve;
+ vm_page_t m;
+ vm_offset_t pa;
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ if (!l2b)
+ return;
+ KASSERT(l2b != NULL, ("No L2 Bucket"));
+ pte = &l2b->l2b_kva[l2pte_index(va)];
+ opte = *pte;
+ if (l2pte_valid(opte)) {
+ /* pa = vtophs(va) taken from pmap_extract() */
+ switch (opte & L2_TYPE_MASK) {
+ case L2_TYPE_L:
+ pa = (opte & L2_L_FRAME) | (va & L2_L_OFFSET);
+ break;
+ default:
+ pa = (opte & L2_S_FRAME) | (va & L2_S_OFFSET);
+ break;
+ }
+ /* note: should never have to remove an allocation
+ * before the pvzone is initialized.
+ */
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap_kernel());
+ if (pvzone != NULL && (m = vm_phys_paddr_to_vm_page(pa)) &&
+ (pve = pmap_remove_pv(m, pmap_kernel(), va)))
+ pmap_free_pv_entry(pve);
+ PMAP_UNLOCK(pmap_kernel());
+ rw_wunlock(&pvh_global_lock);
+ va = va & ~PAGE_MASK;
+ cpu_dcache_wbinv_range(va, PAGE_SIZE);
+ cpu_l2cache_wbinv_range(va, PAGE_SIZE);
+ cpu_tlb_flushD_SE(va);
+ cpu_cpwait();
+ *pte = 0;
+ }
+}
+
+
+/*
+ * Used to map a range of physical addresses into kernel
+ * virtual address space.
+ *
+ * The value passed in '*virt' is a suggested virtual address for
+ * the mapping. Architectures which can support a direct-mapped
+ * physical to virtual region can return the appropriate address
+ * within that region, leaving '*virt' unchanged. Other
+ * architectures should map the pages starting at '*virt' and
+ * update '*virt' with the first usable address after the mapped
+ * region.
+ */
+vm_offset_t
+pmap_map(vm_offset_t *virt, vm_offset_t start, vm_offset_t end, int prot)
+{
+ vm_offset_t sva = *virt;
+ vm_offset_t va = sva;
+
+ PDEBUG(1, printf("pmap_map: virt = %08x, start = %08x, end = %08x, "
+ "prot = %d\n", (uint32_t) *virt, (uint32_t) start, (uint32_t) end,
+ prot));
+
+ while (start < end) {
+ pmap_kenter(va, start);
+ va += PAGE_SIZE;
+ start += PAGE_SIZE;
+ }
+ *virt = va;
+ return (sva);
+}
+
+static void
+pmap_wb_page(vm_page_t m)
+{
+ struct pv_entry *pv;
+
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list)
+ pmap_dcache_wb_range(pv->pv_pmap, pv->pv_va, PAGE_SIZE, FALSE,
+ (pv->pv_flags & PVF_WRITE) == 0);
+}
+
+static void
+pmap_inv_page(vm_page_t m)
+{
+ struct pv_entry *pv;
+
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list)
+ pmap_dcache_wb_range(pv->pv_pmap, pv->pv_va, PAGE_SIZE, TRUE, TRUE);
+}
+/*
+ * Add a list of wired pages to the kva
+ * this routine is only used for temporary
+ * kernel mappings that do not need to have
+ * page modification or references recorded.
+ * Note that old mappings are simply written
+ * over. The page *must* be wired.
+ */
+void
+pmap_qenter(vm_offset_t va, vm_page_t *m, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ pmap_wb_page(m[i]);
+ pmap_kenter_internal(va, VM_PAGE_TO_PHYS(m[i]),
+ KENTER_CACHE);
+ va += PAGE_SIZE;
+ }
+}
+
+
+/*
+ * this routine jerks page mappings from the
+ * kernel -- it is meant only for temporary mappings.
+ */
+void
+pmap_qremove(vm_offset_t va, int count)
+{
+ vm_paddr_t pa;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ pa = vtophys(va);
+ if (pa) {
+ pmap_inv_page(PHYS_TO_VM_PAGE(pa));
+ pmap_kremove(va);
+ }
+ va += PAGE_SIZE;
+ }
+}
+
+
+/*
+ * pmap_object_init_pt preloads the ptes for a given object
+ * into the specified pmap. This eliminates the blast of soft
+ * faults on process startup and immediately after an mmap.
+ */
+void
+pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
+ vm_pindex_t pindex, vm_size_t size)
+{
+
+ VM_OBJECT_ASSERT_WLOCKED(object);
+ KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
+ ("pmap_object_init_pt: non-device object"));
+}
+
+
+/*
+ * pmap_is_prefaultable:
+ *
+ * Return whether or not the specified virtual address is elgible
+ * for prefault.
+ */
+boolean_t
+pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
+{
+ pd_entry_t *pde;
+ pt_entry_t *pte;
+
+ if (!pmap_get_pde_pte(pmap, addr, &pde, &pte))
+ return (FALSE);
+ KASSERT(pte != NULL, ("Valid mapping but no pte ?"));
+ if (*pte == 0)
+ return (TRUE);
+ return (FALSE);
+}
+
+/*
+ * Fetch pointers to the PDE/PTE for the given pmap/VA pair.
+ * Returns TRUE if the mapping exists, else FALSE.
+ *
+ * NOTE: This function is only used by a couple of arm-specific modules.
+ * It is not safe to take any pmap locks here, since we could be right
+ * in the middle of debugging the pmap anyway...
+ *
+ * It is possible for this routine to return FALSE even though a valid
+ * mapping does exist. This is because we don't lock, so the metadata
+ * state may be inconsistent.
+ *
+ * NOTE: We can return a NULL *ptp in the case where the L1 pde is
+ * a "section" mapping.
+ */
+boolean_t
+pmap_get_pde_pte(pmap_t pm, vm_offset_t va, pd_entry_t **pdp, pt_entry_t **ptp)
+{
+ struct l2_dtable *l2;
+ pd_entry_t *pl1pd, l1pd;
+ pt_entry_t *ptep;
+ u_short l1idx;
+
+ if (pm->pm_l1 == NULL)
+ return (FALSE);
+
+ l1idx = L1_IDX(va);
+ *pdp = pl1pd = &pm->pm_l1->l1_kva[l1idx];
+ l1pd = *pl1pd;
+
+ if (l1pte_section_p(l1pd)) {
+ *ptp = NULL;
+ return (TRUE);
+ }
+
+ if (pm->pm_l2 == NULL)
+ return (FALSE);
+
+ l2 = pm->pm_l2[L2_IDX(l1idx)];
+
+ if (l2 == NULL ||
+ (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
+ return (FALSE);
+ }
+
+ *ptp = &ptep[l2pte_index(va)];
+ return (TRUE);
+}
+
+/*
+ * Routine: pmap_remove_all
+ * Function:
+ * Removes this physical page from
+ * all physical maps in which it resides.
+ * Reflects back modify bits to the pager.
+ *
+ * Notes:
+ * Original versions of this routine were very
+ * inefficient because they iteratively called
+ * pmap_remove (slow...)
+ */
+void
+pmap_remove_all(vm_page_t m)
+{
+ pv_entry_t pv;
+ pt_entry_t *ptep;
+ struct l2_bucket *l2b;
+ boolean_t flush = FALSE;
+ pmap_t curpm;
+ int flags = 0;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_remove_all: page %p is not managed", m));
+ if (TAILQ_EMPTY(&m->md.pv_list))
+ return;
+ rw_wlock(&pvh_global_lock);
+ pmap_remove_write(m);
+ curpm = vmspace_pmap(curproc->p_vmspace);
+ while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
+ if (flush == FALSE && (pv->pv_pmap == curpm ||
+ pv->pv_pmap == pmap_kernel()))
+ flush = TRUE;
+
+ PMAP_LOCK(pv->pv_pmap);
+ /*
+ * Cached contents were written-back in pmap_remove_write(),
+ * but we still have to invalidate the cache entry to make
+ * sure stale data are not retrieved when another page will be
+ * mapped under this virtual address.
+ */
+ if (pmap_is_current(pv->pv_pmap)) {
+ cpu_dcache_inv_range(pv->pv_va, PAGE_SIZE);
+ if (pmap_has_valid_mapping(pv->pv_pmap, pv->pv_va))
+ cpu_l2cache_inv_range(pv->pv_va, PAGE_SIZE);
+ }
+
+ if (pv->pv_flags & PVF_UNMAN) {
+ /* remove the pv entry, but do not remove the mapping
+ * and remember this is a kernel mapped page
+ */
+ m->md.pv_kva = pv->pv_va;
+ } else {
+ /* remove the mapping and pv entry */
+ l2b = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
+ KASSERT(l2b != NULL, ("No l2 bucket"));
+ ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+ *ptep = 0;
+ PTE_SYNC_CURRENT(pv->pv_pmap, ptep);
+ pmap_free_l2_bucket(pv->pv_pmap, l2b, 1);
+ pv->pv_pmap->pm_stats.resident_count--;
+ flags |= pv->pv_flags;
+ }
+ pmap_nuke_pv(m, pv->pv_pmap, pv);
+ PMAP_UNLOCK(pv->pv_pmap);
+ pmap_free_pv_entry(pv);
+ }
+
+ if (flush) {
+ if (PV_BEEN_EXECD(flags))
+ pmap_tlb_flushID(curpm);
+ else
+ pmap_tlb_flushD(curpm);
+ }
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ rw_wunlock(&pvh_global_lock);
+}
+
+
+/*
+ * Set the physical protection on the
+ * specified range of this map as requested.
+ */
+void
+pmap_protect(pmap_t pm, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, pte;
+ vm_offset_t next_bucket;
+ u_int flags;
+ int flush;
+
+ CTR4(KTR_PMAP, "pmap_protect: pmap %p sva 0x%08x eva 0x%08x prot %x",
+ pm, sva, eva, prot);
+
+ if ((prot & VM_PROT_READ) == 0) {
+ pmap_remove(pm, sva, eva);
+ return;
+ }
+
+ if (prot & VM_PROT_WRITE) {
+ /*
+ * If this is a read->write transition, just ignore it and let
+ * vm_fault() take care of it later.
+ */
+ return;
+ }
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pm);
+
+ /*
+ * OK, at this point, we know we're doing write-protect operation.
+ * If the pmap is active, write-back the range.
+ */
+ pmap_dcache_wb_range(pm, sva, eva - sva, FALSE, FALSE);
+
+ flush = ((eva - sva) >= (PAGE_SIZE * 4)) ? 0 : -1;
+ flags = 0;
+
+ while (sva < eva) {
+ next_bucket = L2_NEXT_BUCKET(sva);
+ if (next_bucket > eva)
+ next_bucket = eva;
+
+ l2b = pmap_get_l2_bucket(pm, sva);
+ if (l2b == NULL) {
+ sva = next_bucket;
+ continue;
+ }
+
+ ptep = &l2b->l2b_kva[l2pte_index(sva)];
+
+ while (sva < next_bucket) {
+ if ((pte = *ptep) != 0 && (pte & L2_S_PROT_W) != 0) {
+ struct vm_page *pg;
+ u_int f;
+
+ pg = PHYS_TO_VM_PAGE(l2pte_pa(pte));
+ pte &= ~L2_S_PROT_W;
+ *ptep = pte;
+ PTE_SYNC(ptep);
+
+ if (!(pg->oflags & VPO_UNMANAGED)) {
+ f = pmap_modify_pv(pg, pm, sva,
+ PVF_WRITE, 0);
+ if (f & PVF_WRITE)
+ vm_page_dirty(pg);
+ } else
+ f = 0;
+
+ if (flush >= 0) {
+ flush++;
+ flags |= f;
+ } else
+ if (PV_BEEN_EXECD(f))
+ pmap_tlb_flushID_SE(pm, sva);
+ else
+ if (PV_BEEN_REFD(f))
+ pmap_tlb_flushD_SE(pm, sva);
+ }
+
+ sva += PAGE_SIZE;
+ ptep++;
+ }
+ }
+
+
+ if (flush) {
+ if (PV_BEEN_EXECD(flags))
+ pmap_tlb_flushID(pm);
+ else
+ if (PV_BEEN_REFD(flags))
+ pmap_tlb_flushD(pm);
+ }
+ rw_wunlock(&pvh_global_lock);
+
+ PMAP_UNLOCK(pm);
+}
+
+
+/*
+ * Insert the given physical page (p) at
+ * the specified virtual address (v) in the
+ * target physical map with the protection requested.
+ *
+ * If specified, the page will be wired down, meaning
+ * that the related pte can not be reclaimed.
+ *
+ * NB: This is the only routine which MAY NOT lazy-evaluate
+ * or lose information. That is, this routine must actually
+ * insert this page into the given map NOW.
+ */
+
+int
+pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ u_int flags, int8_t psind __unused)
+{
+ int rv;
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ rv = pmap_enter_locked(pmap, va, m, prot, flags);
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ return (rv);
+}
+
+/*
+ * The pvh global and pmap locks must be held.
+ */
+static int
+pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ u_int flags)
+{
+ struct l2_bucket *l2b = NULL;
+ struct vm_page *opg;
+ struct pv_entry *pve = NULL;
+ pt_entry_t *ptep, npte, opte;
+ u_int nflags;
+ u_int oflags;
+ vm_paddr_t pa;
+
+ PMAP_ASSERT_LOCKED(pmap);
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ if (va == vector_page) {
+ pa = systempage.pv_pa;
+ m = NULL;
+ } else {
+ if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
+ VM_OBJECT_ASSERT_LOCKED(m->object);
+ pa = VM_PAGE_TO_PHYS(m);
+ }
+ nflags = 0;
+ if (prot & VM_PROT_WRITE)
+ nflags |= PVF_WRITE;
+ if (prot & VM_PROT_EXECUTE)
+ nflags |= PVF_EXEC;
+ if ((flags & PMAP_ENTER_WIRED) != 0)
+ nflags |= PVF_WIRED;
+ PDEBUG(1, printf("pmap_enter: pmap = %08x, va = %08x, m = %08x, prot = %x, "
+ "flags = %x\n", (uint32_t) pmap, va, (uint32_t) m, prot, flags));
+
+ if (pmap == pmap_kernel()) {
+ l2b = pmap_get_l2_bucket(pmap, va);
+ if (l2b == NULL)
+ l2b = pmap_grow_l2_bucket(pmap, va);
+ } else {
+do_l2b_alloc:
+ l2b = pmap_alloc_l2_bucket(pmap, va);
+ if (l2b == NULL) {
+ if ((flags & PMAP_ENTER_NOSLEEP) == 0) {
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+ VM_WAIT;
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ goto do_l2b_alloc;
+ }
+ return (KERN_RESOURCE_SHORTAGE);
+ }
+ }
+
+ ptep = &l2b->l2b_kva[l2pte_index(va)];
+
+ opte = *ptep;
+ npte = pa;
+ oflags = 0;
+ if (opte) {
+ /*
+ * There is already a mapping at this address.
+ * If the physical address is different, lookup the
+ * vm_page.
+ */
+ if (l2pte_pa(opte) != pa)
+ opg = PHYS_TO_VM_PAGE(l2pte_pa(opte));
+ else
+ opg = m;
+ } else
+ opg = NULL;
+
+ if ((prot & (VM_PROT_ALL)) ||
+ (!m || m->md.pvh_attrs & PVF_REF)) {
+ /*
+ * - The access type indicates that we don't need
+ * to do referenced emulation.
+ * OR
+ * - The physical page has already been referenced
+ * so no need to re-do referenced emulation here.
+ */
+ npte |= L2_S_PROTO;
+
+ nflags |= PVF_REF;
+
+ if (m && ((prot & VM_PROT_WRITE) != 0 ||
+ (m->md.pvh_attrs & PVF_MOD))) {
+ /*
+ * This is a writable mapping, and the
+ * page's mod state indicates it has
+ * already been modified. Make it
+ * writable from the outset.
+ */
+ nflags |= PVF_MOD;
+ if (!(m->md.pvh_attrs & PVF_MOD))
+ vm_page_dirty(m);
+ }
+ if (m && opte)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ } else {
+ /*
+ * Need to do page referenced emulation.
+ */
+ npte |= L2_TYPE_INV;
+ }
+
+ if (prot & VM_PROT_WRITE) {
+ npte |= L2_S_PROT_W;
+ if (m != NULL &&
+ (m->oflags & VPO_UNMANAGED) == 0)
+ vm_page_aflag_set(m, PGA_WRITEABLE);
+ }
+ if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
+ npte |= pte_l2_s_cache_mode;
+ if (m && m == opg) {
+ /*
+ * We're changing the attrs of an existing mapping.
+ */
+ oflags = pmap_modify_pv(m, pmap, va,
+ PVF_WRITE | PVF_EXEC | PVF_WIRED |
+ PVF_MOD | PVF_REF, nflags);
+
+ /*
+ * We may need to flush the cache if we're
+ * doing rw-ro...
+ */
+ if (pmap_is_current(pmap) &&
+ (oflags & PVF_NC) == 0 &&
+ (opte & L2_S_PROT_W) != 0 &&
+ (prot & VM_PROT_WRITE) == 0 &&
+ (opte & L2_TYPE_MASK) != L2_TYPE_INV) {
+ cpu_dcache_wb_range(va, PAGE_SIZE);
+ cpu_l2cache_wb_range(va, PAGE_SIZE);
+ }
+ } else {
+ /*
+ * New mapping, or changing the backing page
+ * of an existing mapping.
+ */
+ if (opg) {
+ /*
+ * Replacing an existing mapping with a new one.
+ * It is part of our managed memory so we
+ * must remove it from the PV list
+ */
+ if ((pve = pmap_remove_pv(opg, pmap, va))) {
+
+ /* note for patch: the oflags/invalidation was moved
+ * because PG_FICTITIOUS pages could free the pve
+ */
+ oflags = pve->pv_flags;
+ /*
+ * If the old mapping was valid (ref/mod
+ * emulation creates 'invalid' mappings
+ * initially) then make sure to frob
+ * the cache.
+ */
+ if ((oflags & PVF_NC) == 0 && l2pte_valid(opte)) {
+ if (PV_BEEN_EXECD(oflags)) {
+ pmap_idcache_wbinv_range(pmap, va,
+ PAGE_SIZE);
+ } else
+ if (PV_BEEN_REFD(oflags)) {
+ pmap_dcache_wb_range(pmap, va,
+ PAGE_SIZE, TRUE,
+ (oflags & PVF_WRITE) == 0);
+ }
+ }
+
+ /* free/allocate a pv_entry for UNMANAGED pages if
+ * this physical page is not/is already mapped.
+ */
+
+ if (m && (m->oflags & VPO_UNMANAGED) &&
+ !m->md.pv_kva &&
+ TAILQ_EMPTY(&m->md.pv_list)) {
+ pmap_free_pv_entry(pve);
+ pve = NULL;
+ }
+ } else if (m &&
+ (!(m->oflags & VPO_UNMANAGED) || m->md.pv_kva ||
+ !TAILQ_EMPTY(&m->md.pv_list)))
+ pve = pmap_get_pv_entry();
+ } else if (m &&
+ (!(m->oflags & VPO_UNMANAGED) || m->md.pv_kva ||
+ !TAILQ_EMPTY(&m->md.pv_list)))
+ pve = pmap_get_pv_entry();
+
+ if (m) {
+ if ((m->oflags & VPO_UNMANAGED)) {
+ if (!TAILQ_EMPTY(&m->md.pv_list) ||
+ m->md.pv_kva) {
+ KASSERT(pve != NULL, ("No pv"));
+ nflags |= PVF_UNMAN;
+ pmap_enter_pv(m, pve, pmap, va, nflags);
+ } else
+ m->md.pv_kva = va;
+ } else {
+ KASSERT(va < kmi.clean_sva ||
+ va >= kmi.clean_eva,
+ ("pmap_enter: managed mapping within the clean submap"));
+ KASSERT(pve != NULL, ("No pv"));
+ pmap_enter_pv(m, pve, pmap, va, nflags);
+ }
+ }
+ }
+ /*
+ * Make sure userland mappings get the right permissions
+ */
+ if (pmap != pmap_kernel() && va != vector_page) {
+ npte |= L2_S_PROT_U;
+ }
+
+ /*
+ * Keep the stats up to date
+ */
+ if (opte == 0) {
+ l2b->l2b_occupancy++;
+ pmap->pm_stats.resident_count++;
+ }
+
+ /*
+ * If this is just a wiring change, the two PTEs will be
+ * identical, so there's no need to update the page table.
+ */
+ if (npte != opte) {
+ boolean_t is_cached = pmap_is_current(pmap);
+
+ *ptep = npte;
+ if (is_cached) {
+ /*
+ * We only need to frob the cache/tlb if this pmap
+ * is current
+ */
+ PTE_SYNC(ptep);
+ if (L1_IDX(va) != L1_IDX(vector_page) &&
+ l2pte_valid(npte)) {
+ /*
+ * This mapping is likely to be accessed as
+ * soon as we return to userland. Fix up the
+ * L1 entry to avoid taking another
+ * page/domain fault.
+ */
+ pd_entry_t *pl1pd, l1pd;
+
+ pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+ l1pd = l2b->l2b_phys | L1_C_DOM(pmap->pm_domain) |
+ L1_C_PROTO;
+ if (*pl1pd != l1pd) {
+ *pl1pd = l1pd;
+ PTE_SYNC(pl1pd);
+ }
+ }
+ }
+
+ if (PV_BEEN_EXECD(oflags))
+ pmap_tlb_flushID_SE(pmap, va);
+ else if (PV_BEEN_REFD(oflags))
+ pmap_tlb_flushD_SE(pmap, va);
+
+
+ if (m)
+ pmap_fix_cache(m, pmap, va);
+ }
+ return (KERN_SUCCESS);
+}
+
+/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start. This page is
+ * mapped at the given virtual address start. Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object. The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end. Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
+void
+pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
+ vm_page_t m_start, vm_prot_t prot)
+{
+ vm_page_t m;
+ vm_pindex_t diff, psize;
+
+ VM_OBJECT_ASSERT_LOCKED(m_start->object);
+
+ psize = atop(end - start);
+ m = m_start;
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+ pmap_enter_locked(pmap, start + ptoa(diff), m, prot &
+ (VM_PROT_READ | VM_PROT_EXECUTE), PMAP_ENTER_NOSLEEP);
+ m = TAILQ_NEXT(m, listq);
+ }
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
+
+/*
+ * this code makes some *MAJOR* assumptions:
+ * 1. Current pmap & pmap exists.
+ * 2. Not wired.
+ * 3. Read access.
+ * 4. No page table pages.
+ * but is *MUCH* faster than pmap_enter...
+ */
+
+void
+pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+{
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ pmap_enter_locked(pmap, va, m, prot & (VM_PROT_READ | VM_PROT_EXECUTE),
+ PMAP_ENTER_NOSLEEP);
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
+
+/*
+ * Clear the wired attribute from the mappings for the specified range of
+ * addresses in the given pmap. Every valid mapping within that range
+ * must have the wired attribute set. In contrast, invalid mappings
+ * cannot have the wired attribute set, so they are ignored.
+ *
+ * XXX Wired mappings of unmanaged pages cannot be counted by this pmap
+ * implementation.
+ */
+void
+pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, pte;
+ pv_entry_t pv;
+ vm_offset_t next_bucket;
+ vm_page_t m;
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ while (sva < eva) {
+ next_bucket = L2_NEXT_BUCKET(sva);
+ if (next_bucket > eva)
+ next_bucket = eva;
+ l2b = pmap_get_l2_bucket(pmap, sva);
+ if (l2b == NULL) {
+ sva = next_bucket;
+ continue;
+ }
+ for (ptep = &l2b->l2b_kva[l2pte_index(sva)]; sva < next_bucket;
+ sva += PAGE_SIZE, ptep++) {
+ if ((pte = *ptep) == 0 ||
+ (m = PHYS_TO_VM_PAGE(l2pte_pa(pte))) == NULL ||
+ (m->oflags & VPO_UNMANAGED) != 0)
+ continue;
+ pv = pmap_find_pv(m, pmap, sva);
+ if ((pv->pv_flags & PVF_WIRED) == 0)
+ panic("pmap_unwire: pv %p isn't wired", pv);
+ pv->pv_flags &= ~PVF_WIRED;
+ pmap->pm_stats.wired_count--;
+ }
+ }
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
+
+
+/*
+ * Copy the range specified by src_addr/len
+ * from the source map to the range dst_addr/len
+ * in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+void
+pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
+ vm_size_t len, vm_offset_t src_addr)
+{
+}
+
+
+/*
+ * Routine: pmap_extract
+ * Function:
+ * Extract the physical page address associated
+ * with the given map/virtual_address pair.
+ */
+vm_paddr_t
+pmap_extract(pmap_t pmap, vm_offset_t va)
+{
+ vm_paddr_t pa;
+
+ PMAP_LOCK(pmap);
+ pa = pmap_extract_locked(pmap, va);
+ PMAP_UNLOCK(pmap);
+ return (pa);
+}
+
+static vm_paddr_t
+pmap_extract_locked(pmap_t pmap, vm_offset_t va)
+{
+ struct l2_dtable *l2;
+ pd_entry_t l1pd;
+ pt_entry_t *ptep, pte;
+ vm_paddr_t pa;
+ u_int l1idx;
+
+ if (pmap != kernel_pmap)
+ PMAP_ASSERT_LOCKED(pmap);
+ l1idx = L1_IDX(va);
+ l1pd = pmap->pm_l1->l1_kva[l1idx];
+ if (l1pte_section_p(l1pd)) {
+ /*
+ * These should only happen for the kernel pmap.
+ */
+ KASSERT(pmap == kernel_pmap, ("unexpected section"));
+ /* XXX: what to do about the bits > 32 ? */
+ if (l1pd & L1_S_SUPERSEC)
+ pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
+ else
+ pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
+ } else {
+ /*
+ * Note that we can't rely on the validity of the L1
+ * descriptor as an indication that a mapping exists.
+ * We have to look it up in the L2 dtable.
+ */
+ l2 = pmap->pm_l2[L2_IDX(l1idx)];
+ if (l2 == NULL ||
+ (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL)
+ return (0);
+ pte = ptep[l2pte_index(va)];
+ if (pte == 0)
+ return (0);
+ switch (pte & L2_TYPE_MASK) {
+ case L2_TYPE_L:
+ pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
+ break;
+ default:
+ pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
+ break;
+ }
+ }
+ return (pa);
+}
+
+/*
+ * Atomically extract and hold the physical page with the given
+ * pmap and virtual address pair if that mapping permits the given
+ * protection.
+ *
+ */
+vm_page_t
+pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
+{
+ struct l2_dtable *l2;
+ pd_entry_t l1pd;
+ pt_entry_t *ptep, pte;
+ vm_paddr_t pa, paddr;
+ vm_page_t m = NULL;
+ u_int l1idx;
+ l1idx = L1_IDX(va);
+ paddr = 0;
+
+ PMAP_LOCK(pmap);
+retry:
+ l1pd = pmap->pm_l1->l1_kva[l1idx];
+ if (l1pte_section_p(l1pd)) {
+ /*
+ * These should only happen for pmap_kernel()
+ */
+ KASSERT(pmap == pmap_kernel(), ("huh"));
+ /* XXX: what to do about the bits > 32 ? */
+ if (l1pd & L1_S_SUPERSEC)
+ pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
+ else
+ pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
+ if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
+ goto retry;
+ if (l1pd & L1_S_PROT_W || (prot & VM_PROT_WRITE) == 0) {
+ m = PHYS_TO_VM_PAGE(pa);
+ vm_page_hold(m);
+ }
+
+ } else {
+ /*
+ * Note that we can't rely on the validity of the L1
+ * descriptor as an indication that a mapping exists.
+ * We have to look it up in the L2 dtable.
+ */
+ l2 = pmap->pm_l2[L2_IDX(l1idx)];
+
+ if (l2 == NULL ||
+ (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
+ PMAP_UNLOCK(pmap);
+ return (NULL);
+ }
+
+ ptep = &ptep[l2pte_index(va)];
+ pte = *ptep;
+
+ if (pte == 0) {
+ PMAP_UNLOCK(pmap);
+ return (NULL);
+ }
+ if (pte & L2_S_PROT_W || (prot & VM_PROT_WRITE) == 0) {
+ switch (pte & L2_TYPE_MASK) {
+ case L2_TYPE_L:
+ pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
+ break;
+
+ default:
+ pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
+ break;
+ }
+ if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
+ goto retry;
+ m = PHYS_TO_VM_PAGE(pa);
+ vm_page_hold(m);
+ }
+ }
+
+ PMAP_UNLOCK(pmap);
+ PA_UNLOCK_COND(paddr);
+ return (m);
+}
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+
+int
+pmap_pinit(pmap_t pmap)
+{
+ PDEBUG(1, printf("pmap_pinit: pmap = %08x\n", (uint32_t) pmap));
+
+ pmap_alloc_l1(pmap);
+ bzero(pmap->pm_l2, sizeof(pmap->pm_l2));
+
+ CPU_ZERO(&pmap->pm_active);
+
+ TAILQ_INIT(&pmap->pm_pvlist);
+ bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
+ pmap->pm_stats.resident_count = 1;
+ if (vector_page < KERNBASE) {
+ pmap_enter(pmap, vector_page, PHYS_TO_VM_PAGE(systempage.pv_pa),
+ VM_PROT_READ, PMAP_ENTER_WIRED | VM_PROT_READ, 0);
+ }
+ return (1);
+}
+
+
+/***************************************************
+ * page management routines.
+ ***************************************************/
+
+
+static void
+pmap_free_pv_entry(pv_entry_t pv)
+{
+ pv_entry_count--;
+ uma_zfree(pvzone, pv);
+}
+
+
+/*
+ * get a new pv_entry, allocating a block from the system
+ * when needed.
+ * the memory allocation is performed bypassing the malloc code
+ * because of the possibility of allocations at interrupt time.
+ */
+static pv_entry_t
+pmap_get_pv_entry(void)
+{
+ pv_entry_t ret_value;
+
+ pv_entry_count++;
+ if (pv_entry_count > pv_entry_high_water)
+ pagedaemon_wakeup();
+ ret_value = uma_zalloc(pvzone, M_NOWAIT);
+ return ret_value;
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ *
+ * It is assumed that the start and end are properly
+ * rounded to the page size.
+ */
+#define PMAP_REMOVE_CLEAN_LIST_SIZE 3
+void
+pmap_remove(pmap_t pm, vm_offset_t sva, vm_offset_t eva)
+{
+ struct l2_bucket *l2b;
+ vm_offset_t next_bucket;
+ pt_entry_t *ptep;
+ u_int total;
+ u_int mappings, is_exec, is_refd;
+ int flushall = 0;
+
+
+ /*
+ * we lock in the pmap => pv_head direction
+ */
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pm);
+ total = 0;
+ while (sva < eva) {
+ /*
+ * Do one L2 bucket's worth at a time.
+ */
+ next_bucket = L2_NEXT_BUCKET(sva);
+ if (next_bucket > eva)
+ next_bucket = eva;
+
+ l2b = pmap_get_l2_bucket(pm, sva);
+ if (l2b == NULL) {
+ sva = next_bucket;
+ continue;
+ }
+
+ ptep = &l2b->l2b_kva[l2pte_index(sva)];
+ mappings = 0;
+
+ while (sva < next_bucket) {
+ struct vm_page *pg;
+ pt_entry_t pte;
+ vm_paddr_t pa;
+
+ pte = *ptep;
+
+ if (pte == 0) {
+ /*
+ * Nothing here, move along
+ */
+ sva += PAGE_SIZE;
+ ptep++;
+ continue;
+ }
+
+ pm->pm_stats.resident_count--;
+ pa = l2pte_pa(pte);
+ is_exec = 0;
+ is_refd = 1;
+
+ /*
+ * Update flags. In a number of circumstances,
+ * we could cluster a lot of these and do a
+ * number of sequential pages in one go.
+ */
+ if ((pg = PHYS_TO_VM_PAGE(pa)) != NULL) {
+ struct pv_entry *pve;
+
+ pve = pmap_remove_pv(pg, pm, sva);
+ if (pve) {
+ is_exec = PV_BEEN_EXECD(pve->pv_flags);
+ is_refd = PV_BEEN_REFD(pve->pv_flags);
+ pmap_free_pv_entry(pve);
+ }
+ }
+
+ if (l2pte_valid(pte) && pmap_is_current(pm)) {
+ if (total < PMAP_REMOVE_CLEAN_LIST_SIZE) {
+ total++;
+ if (is_exec) {
+ cpu_idcache_wbinv_range(sva,
+ PAGE_SIZE);
+ cpu_l2cache_wbinv_range(sva,
+ PAGE_SIZE);
+ cpu_tlb_flushID_SE(sva);
+ } else if (is_refd) {
+ cpu_dcache_wbinv_range(sva,
+ PAGE_SIZE);
+ cpu_l2cache_wbinv_range(sva,
+ PAGE_SIZE);
+ cpu_tlb_flushD_SE(sva);
+ }
+ } else if (total == PMAP_REMOVE_CLEAN_LIST_SIZE) {
+ /* flushall will also only get set for
+ * for a current pmap
+ */
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ flushall = 1;
+ total++;
+ }
+ }
+ *ptep = 0;
+ PTE_SYNC(ptep);
+
+ sva += PAGE_SIZE;
+ ptep++;
+ mappings++;
+ }
+
+ pmap_free_l2_bucket(pm, l2b, mappings);
+ }
+
+ rw_wunlock(&pvh_global_lock);
+ if (flushall)
+ cpu_tlb_flushID();
+ PMAP_UNLOCK(pm);
+}
+
+/*
+ * pmap_zero_page()
+ *
+ * Zero a given physical page by mapping it at a page hook point.
+ * In doing the zero page op, the page we zero is mapped cachable, as with
+ * StrongARM accesses to non-cached pages are non-burst making writing
+ * _any_ bulk data very slow.
+ */
+#if ARM_MMU_GENERIC != 0 || defined(CPU_XSCALE_CORE3)
+void
+pmap_zero_page_generic(vm_paddr_t phys, int off, int size)
+{
+
+ if (_arm_bzero && size >= _min_bzero_size &&
+ _arm_bzero((void *)(phys + off), size, IS_PHYSICAL) == 0)
+ return;
+
+ mtx_lock(&cmtx);
+ /*
+ * Hook in the page, zero it, invalidate the TLB as needed.
+ *
+ * Note the temporary zero-page mapping must be a non-cached page in
+ * order to work without corruption when write-allocate is enabled.
+ */
+ *cdst_pte = L2_S_PROTO | phys | L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE);
+ PTE_SYNC(cdst_pte);
+ cpu_tlb_flushD_SE(cdstp);
+ cpu_cpwait();
+ if (off || size != PAGE_SIZE)
+ bzero((void *)(cdstp + off), size);
+ else
+ bzero_page(cdstp);
+
+ mtx_unlock(&cmtx);
+}
+#endif /* ARM_MMU_GENERIC != 0 */
+
+#if ARM_MMU_XSCALE == 1
+void
+pmap_zero_page_xscale(vm_paddr_t phys, int off, int size)
+{
+
+ if (_arm_bzero && size >= _min_bzero_size &&
+ _arm_bzero((void *)(phys + off), size, IS_PHYSICAL) == 0)
+ return;
+
+ mtx_lock(&cmtx);
+ /*
+ * Hook in the page, zero it, and purge the cache for that
+ * zeroed page. Invalidate the TLB as needed.
+ */
+ *cdst_pte = L2_S_PROTO | phys |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) |
+ L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X); /* mini-data */
+ PTE_SYNC(cdst_pte);
+ cpu_tlb_flushD_SE(cdstp);
+ cpu_cpwait();
+ if (off || size != PAGE_SIZE)
+ bzero((void *)(cdstp + off), size);
+ else
+ bzero_page(cdstp);
+ mtx_unlock(&cmtx);
+ xscale_cache_clean_minidata();
+}
+
+/*
+ * Change the PTEs for the specified kernel mappings such that they
+ * will use the mini data cache instead of the main data cache.
+ */
+void
+pmap_use_minicache(vm_offset_t va, vm_size_t size)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, *sptep, pte;
+ vm_offset_t next_bucket, eva;
+
+#if (ARM_NMMUS > 1) || defined(CPU_XSCALE_CORE3)
+ if (xscale_use_minidata == 0)
+ return;
+#endif
+
+ eva = va + size;
+
+ while (va < eva) {
+ next_bucket = L2_NEXT_BUCKET(va);
+ if (next_bucket > eva)
+ next_bucket = eva;
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+
+ sptep = ptep = &l2b->l2b_kva[l2pte_index(va)];
+
+ while (va < next_bucket) {
+ pte = *ptep;
+ if (!l2pte_minidata(pte)) {
+ cpu_dcache_wbinv_range(va, PAGE_SIZE);
+ cpu_tlb_flushD_SE(va);
+ *ptep = pte & ~L2_B;
+ }
+ ptep++;
+ va += PAGE_SIZE;
+ }
+ PTE_SYNC_RANGE(sptep, (u_int)(ptep - sptep));
+ }
+ cpu_cpwait();
+}
+#endif /* ARM_MMU_XSCALE == 1 */
+
+/*
+ * pmap_zero_page zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents.
+ */
+void
+pmap_zero_page(vm_page_t m)
+{
+ pmap_zero_page_func(VM_PAGE_TO_PHYS(m), 0, PAGE_SIZE);
+}
+
+
+/*
+ * pmap_zero_page_area zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents.
+ *
+ * off and size may not cover an area beyond a single hardware page.
+ */
+void
+pmap_zero_page_area(vm_page_t m, int off, int size)
+{
+
+ pmap_zero_page_func(VM_PAGE_TO_PHYS(m), off, size);
+}
+
+
+/*
+ * pmap_zero_page_idle zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents. This
+ * is intended to be called from the vm_pagezero process only and
+ * outside of Giant.
+ */
+void
+pmap_zero_page_idle(vm_page_t m)
+{
+
+ pmap_zero_page(m);
+}
+
+#if 0
+/*
+ * pmap_clean_page()
+ *
+ * This is a local function used to work out the best strategy to clean
+ * a single page referenced by its entry in the PV table. It should be used by
+ * pmap_copy_page, pmap_zero page and maybe some others later on.
+ *
+ * Its policy is effectively:
+ * o If there are no mappings, we don't bother doing anything with the cache.
+ * o If there is one mapping, we clean just that page.
+ * o If there are multiple mappings, we clean the entire cache.
+ *
+ * So that some functions can be further optimised, it returns 0 if it didn't
+ * clean the entire cache, or 1 if it did.
+ *
+ * XXX One bug in this routine is that if the pv_entry has a single page
+ * mapped at 0x00000000 a whole cache clean will be performed rather than
+ * just the 1 page. Since this should not occur in everyday use and if it does
+ * it will just result in not the most efficient clean for the page.
+ *
+ * We don't yet use this function but may want to.
+ */
+static int
+pmap_clean_page(struct pv_entry *pv, boolean_t is_src)
+{
+ pmap_t pm, pm_to_clean = NULL;
+ struct pv_entry *npv;
+ u_int cache_needs_cleaning = 0;
+ u_int flags = 0;
+ vm_offset_t page_to_clean = 0;
+
+ if (pv == NULL) {
+ /* nothing mapped in so nothing to flush */
+ return (0);
+ }
+
+ /*
+ * Since we flush the cache each time we change to a different
+ * user vmspace, we only need to flush the page if it is in the
+ * current pmap.
+ */
+ if (curthread)
+ pm = vmspace_pmap(curproc->p_vmspace);
+ else
+ pm = pmap_kernel();
+
+ for (npv = pv; npv; npv = TAILQ_NEXT(npv, pv_list)) {
+ if (npv->pv_pmap == pmap_kernel() || npv->pv_pmap == pm) {
+ flags |= npv->pv_flags;
+ /*
+ * The page is mapped non-cacheable in
+ * this map. No need to flush the cache.
+ */
+ if (npv->pv_flags & PVF_NC) {
+#ifdef DIAGNOSTIC
+ if (cache_needs_cleaning)
+ panic("pmap_clean_page: "
+ "cache inconsistency");
+#endif
+ break;
+ } else if (is_src && (npv->pv_flags & PVF_WRITE) == 0)
+ continue;
+ if (cache_needs_cleaning) {
+ page_to_clean = 0;
+ break;
+ } else {
+ page_to_clean = npv->pv_va;
+ pm_to_clean = npv->pv_pmap;
+ }
+ cache_needs_cleaning = 1;
+ }
+ }
+ if (page_to_clean) {
+ if (PV_BEEN_EXECD(flags))
+ pmap_idcache_wbinv_range(pm_to_clean, page_to_clean,
+ PAGE_SIZE);
+ else
+ pmap_dcache_wb_range(pm_to_clean, page_to_clean,
+ PAGE_SIZE, !is_src, (flags & PVF_WRITE) == 0);
+ } else if (cache_needs_cleaning) {
+ if (PV_BEEN_EXECD(flags))
+ pmap_idcache_wbinv_all(pm);
+ else
+ pmap_dcache_wbinv_all(pm);
+ return (1);
+ }
+ return (0);
+}
+#endif
+
+/*
+ * pmap_copy_page copies the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bcopy to copy the page, one machine dependent page at a
+ * time.
+ */
+
+/*
+ * pmap_copy_page()
+ *
+ * Copy one physical page into another, by mapping the pages into
+ * hook points. The same comment regarding cachability as in
+ * pmap_zero_page also applies here.
+ */
+#if ARM_MMU_GENERIC != 0 || defined (CPU_XSCALE_CORE3)
+void
+pmap_copy_page_generic(vm_paddr_t src, vm_paddr_t dst)
+{
+#if 0
+ struct vm_page *src_pg = PHYS_TO_VM_PAGE(src);
+#endif
+
+ /*
+ * Clean the source page. Hold the source page's lock for
+ * the duration of the copy so that no other mappings can
+ * be created while we have a potentially aliased mapping.
+ */
+#if 0
+ /*
+ * XXX: Not needed while we call cpu_dcache_wbinv_all() in
+ * pmap_copy_page().
+ */
+ (void) pmap_clean_page(TAILQ_FIRST(&src_pg->md.pv_list), TRUE);
+#endif
+ /*
+ * Map the pages into the page hook points, copy them, and purge
+ * the cache for the appropriate page. Invalidate the TLB
+ * as required.
+ */
+ mtx_lock(&cmtx);
+ *csrc_pte = L2_S_PROTO | src |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_READ) | pte_l2_s_cache_mode;
+ PTE_SYNC(csrc_pte);
+ *cdst_pte = L2_S_PROTO | dst |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) | pte_l2_s_cache_mode;
+ PTE_SYNC(cdst_pte);
+ cpu_tlb_flushD_SE(csrcp);
+ cpu_tlb_flushD_SE(cdstp);
+ cpu_cpwait();
+ bcopy_page(csrcp, cdstp);
+ mtx_unlock(&cmtx);
+ cpu_dcache_inv_range(csrcp, PAGE_SIZE);
+ cpu_dcache_wbinv_range(cdstp, PAGE_SIZE);
+ cpu_l2cache_inv_range(csrcp, PAGE_SIZE);
+ cpu_l2cache_wbinv_range(cdstp, PAGE_SIZE);
+}
+
+void
+pmap_copy_page_offs_generic(vm_paddr_t a_phys, vm_offset_t a_offs,
+ vm_paddr_t b_phys, vm_offset_t b_offs, int cnt)
+{
+
+ mtx_lock(&cmtx);
+ *csrc_pte = L2_S_PROTO | a_phys |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_READ) | pte_l2_s_cache_mode;
+ PTE_SYNC(csrc_pte);
+ *cdst_pte = L2_S_PROTO | b_phys |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) | pte_l2_s_cache_mode;
+ PTE_SYNC(cdst_pte);
+ cpu_tlb_flushD_SE(csrcp);
+ cpu_tlb_flushD_SE(cdstp);
+ cpu_cpwait();
+ bcopy((char *)csrcp + a_offs, (char *)cdstp + b_offs, cnt);
+ mtx_unlock(&cmtx);
+ cpu_dcache_inv_range(csrcp + a_offs, cnt);
+ cpu_dcache_wbinv_range(cdstp + b_offs, cnt);
+ cpu_l2cache_inv_range(csrcp + a_offs, cnt);
+ cpu_l2cache_wbinv_range(cdstp + b_offs, cnt);
+}
+#endif /* ARM_MMU_GENERIC != 0 */
+
+#if ARM_MMU_XSCALE == 1
+void
+pmap_copy_page_xscale(vm_paddr_t src, vm_paddr_t dst)
+{
+#if 0
+ /* XXX: Only needed for pmap_clean_page(), which is commented out. */
+ struct vm_page *src_pg = PHYS_TO_VM_PAGE(src);
+#endif
+
+ /*
+ * Clean the source page. Hold the source page's lock for
+ * the duration of the copy so that no other mappings can
+ * be created while we have a potentially aliased mapping.
+ */
+#if 0
+ /*
+ * XXX: Not needed while we call cpu_dcache_wbinv_all() in
+ * pmap_copy_page().
+ */
+ (void) pmap_clean_page(TAILQ_FIRST(&src_pg->md.pv_list), TRUE);
+#endif
+ /*
+ * Map the pages into the page hook points, copy them, and purge
+ * the cache for the appropriate page. Invalidate the TLB
+ * as required.
+ */
+ mtx_lock(&cmtx);
+ *csrc_pte = L2_S_PROTO | src |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_READ) |
+ L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X); /* mini-data */
+ PTE_SYNC(csrc_pte);
+ *cdst_pte = L2_S_PROTO | dst |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) |
+ L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X); /* mini-data */
+ PTE_SYNC(cdst_pte);
+ cpu_tlb_flushD_SE(csrcp);
+ cpu_tlb_flushD_SE(cdstp);
+ cpu_cpwait();
+ bcopy_page(csrcp, cdstp);
+ mtx_unlock(&cmtx);
+ xscale_cache_clean_minidata();
+}
+
+void
+pmap_copy_page_offs_xscale(vm_paddr_t a_phys, vm_offset_t a_offs,
+ vm_paddr_t b_phys, vm_offset_t b_offs, int cnt)
+{
+
+ mtx_lock(&cmtx);
+ *csrc_pte = L2_S_PROTO | a_phys |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_READ) |
+ L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X);
+ PTE_SYNC(csrc_pte);
+ *cdst_pte = L2_S_PROTO | b_phys |
+ L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) |
+ L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X);
+ PTE_SYNC(cdst_pte);
+ cpu_tlb_flushD_SE(csrcp);
+ cpu_tlb_flushD_SE(cdstp);
+ cpu_cpwait();
+ bcopy((char *)csrcp + a_offs, (char *)cdstp + b_offs, cnt);
+ mtx_unlock(&cmtx);
+ xscale_cache_clean_minidata();
+}
+#endif /* ARM_MMU_XSCALE == 1 */
+
+void
+pmap_copy_page(vm_page_t src, vm_page_t dst)
+{
+
+ cpu_dcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ if (_arm_memcpy && PAGE_SIZE >= _min_memcpy_size &&
+ _arm_memcpy((void *)VM_PAGE_TO_PHYS(dst),
+ (void *)VM_PAGE_TO_PHYS(src), PAGE_SIZE, IS_PHYSICAL) == 0)
+ return;
+ pmap_copy_page_func(VM_PAGE_TO_PHYS(src), VM_PAGE_TO_PHYS(dst));
+}
+
+/*
+ * We have code to do unmapped I/O. However, it isn't quite right and
+ * causes un-page-aligned I/O to devices to fail (most notably newfs
+ * or fsck). We give up a little performance to not allow unmapped I/O
+ * to gain stability.
+ */
+int unmapped_buf_allowed = 0;
+
+void
+pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
+ vm_offset_t b_offset, int xfersize)
+{
+ vm_page_t a_pg, b_pg;
+ vm_offset_t a_pg_offset, b_pg_offset;
+ int cnt;
+
+ cpu_dcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ while (xfersize > 0) {
+ a_pg = ma[a_offset >> PAGE_SHIFT];
+ a_pg_offset = a_offset & PAGE_MASK;
+ cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+ b_pg = mb[b_offset >> PAGE_SHIFT];
+ b_pg_offset = b_offset & PAGE_MASK;
+ cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+ pmap_copy_page_offs_func(VM_PAGE_TO_PHYS(a_pg), a_pg_offset,
+ VM_PAGE_TO_PHYS(b_pg), b_pg_offset, cnt);
+ xfersize -= cnt;
+ a_offset += cnt;
+ b_offset += cnt;
+ }
+}
+
+/*
+ * this routine returns true if a physical page resides
+ * in the given pmap.
+ */
+boolean_t
+pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
+{
+ pv_entry_t pv;
+ int loops = 0;
+ boolean_t rv;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_page_exists_quick: page %p is not managed", m));
+ rv = FALSE;
+ rw_wlock(&pvh_global_lock);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ if (pv->pv_pmap == pmap) {
+ rv = TRUE;
+ break;
+ }
+ loops++;
+ if (loops >= 16)
+ break;
+ }
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * pmap_page_wired_mappings:
+ *
+ * Return the number of managed mappings to the given physical page
+ * that are wired.
+ */
+int
+pmap_page_wired_mappings(vm_page_t m)
+{
+ pv_entry_t pv;
+ int count;
+
+ count = 0;
+ if ((m->oflags & VPO_UNMANAGED) != 0)
+ return (count);
+ rw_wlock(&pvh_global_lock);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list)
+ if ((pv->pv_flags & PVF_WIRED) != 0)
+ count++;
+ rw_wunlock(&pvh_global_lock);
+ return (count);
+}
+
+/*
+ * This function is advisory.
+ */
+void
+pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice)
+{
+}
+
+/*
+ * pmap_ts_referenced:
+ *
+ * Return the count of reference bits for a page, clearing all of them.
+ */
+int
+pmap_ts_referenced(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_ts_referenced: page %p is not managed", m));
+ return (pmap_clearbit(m, PVF_REF));
+}
+
+
+boolean_t
+pmap_is_modified(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_is_modified: page %p is not managed", m));
+ if (m->md.pvh_attrs & PVF_MOD)
+ return (TRUE);
+
+ return(FALSE);
+}
+
+
+/*
+ * Clear the modify bits on the specified physical page.
+ */
+void
+pmap_clear_modify(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_clear_modify: page %p is not managed", m));
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ KASSERT(!vm_page_xbusied(m),
+ ("pmap_clear_modify: page %p is exclusive busied", m));
+
+ /*
+ * If the page is not PGA_WRITEABLE, then no mappings can be modified.
+ * If the object containing the page is locked and the page is not
+ * exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
+ */
+ if ((m->aflags & PGA_WRITEABLE) == 0)
+ return;
+ if (m->md.pvh_attrs & PVF_MOD)
+ pmap_clearbit(m, PVF_MOD);
+}
+
+
+/*
+ * pmap_is_referenced:
+ *
+ * Return whether or not the specified physical page was referenced
+ * in any physical maps.
+ */
+boolean_t
+pmap_is_referenced(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_is_referenced: page %p is not managed", m));
+ return ((m->md.pvh_attrs & PVF_REF) != 0);
+}
+
+
+/*
+ * Clear the write and modified bits in each of the given page's mappings.
+ */
+void
+pmap_remove_write(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_remove_write: page %p is not managed", m));
+
+ /*
+ * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+ * set by another thread while the object is locked. Thus,
+ * if PGA_WRITEABLE is clear, no page table entries need updating.
+ */
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ if (vm_page_xbusied(m) || (m->aflags & PGA_WRITEABLE) != 0)
+ pmap_clearbit(m, PVF_WRITE);
+}
+
+
+/*
+ * perform the pmap work for mincore
+ */
+int
+pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
+{
+ struct l2_bucket *l2b;
+ pt_entry_t *ptep, pte;
+ vm_paddr_t pa;
+ vm_page_t m;
+ int val;
+ boolean_t managed;
+
+ PMAP_LOCK(pmap);
+retry:
+ l2b = pmap_get_l2_bucket(pmap, addr);
+ if (l2b == NULL) {
+ val = 0;
+ goto out;
+ }
+ ptep = &l2b->l2b_kva[l2pte_index(addr)];
+ pte = *ptep;
+ if (!l2pte_valid(pte)) {
+ val = 0;
+ goto out;
+ }
+ val = MINCORE_INCORE;
+ if (pte & L2_S_PROT_W)
+ val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER;
+ managed = false;
+ pa = l2pte_pa(pte);
+ m = PHYS_TO_VM_PAGE(pa);
+ if (m != NULL && !(m->oflags & VPO_UNMANAGED))
+ managed = true;
+ if (managed) {
+ /*
+ * The ARM pmap tries to maintain a per-mapping
+ * reference bit. The trouble is that it's kept in
+ * the PV entry, not the PTE, so it's costly to access
+ * here. You would need to acquire the pvh global
+ * lock, call pmap_find_pv(), and introduce a custom
+ * version of vm_page_pa_tryrelock() that releases and
+ * reacquires the pvh global lock. In the end, I
+ * doubt it's worthwhile. This may falsely report
+ * the given address as referenced.
+ */
+ if ((m->md.pvh_attrs & PVF_REF) != 0)
+ val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER;
+ }
+ if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) !=
+ (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER) && managed) {
+ /* Ensure that "PHYS_TO_VM_PAGE(pa)->object" doesn't change. */
+ if (vm_page_pa_tryrelock(pmap, pa, locked_pa))
+ goto retry;
+ } else
+out:
+ PA_UNLOCK_COND(*locked_pa);
+ PMAP_UNLOCK(pmap);
+ return (val);
+}
+
+
+void
+pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz)
+{
+}
+
+
+/*
+ * Increase the starting virtual address of the given mapping if a
+ * different alignment might result in more superpage mappings.
+ */
+void
+pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
+ vm_offset_t *addr, vm_size_t size)
+{
+}
+
+#define BOOTSTRAP_DEBUG
+
+/*
+ * pmap_map_section:
+ *
+ * Create a single section mapping.
+ */
+void
+pmap_map_section(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa,
+ int prot, int cache)
+{
+ pd_entry_t *pde = (pd_entry_t *) l1pt;
+ pd_entry_t fl;
+
+ KASSERT(((va | pa) & L1_S_OFFSET) == 0, ("ouin2"));
+
+ switch (cache) {
+ case PTE_NOCACHE:
+ default:
+ fl = 0;
+ break;
+
+ case PTE_CACHE:
+ fl = pte_l1_s_cache_mode;
+ break;
+
+ case PTE_PAGETABLE:
+ fl = pte_l1_s_cache_mode_pt;
+ break;
+ }
+
+ pde[va >> L1_S_SHIFT] = L1_S_PROTO | pa |
+ L1_S_PROT(PTE_KERNEL, prot) | fl | L1_S_DOM(PMAP_DOMAIN_KERNEL);
+ PTE_SYNC(&pde[va >> L1_S_SHIFT]);
+
+}
+
+/*
+ * pmap_link_l2pt:
+ *
+ * Link the L2 page table specified by l2pv.pv_pa into the L1
+ * page table at the slot for "va".
+ */
+void
+pmap_link_l2pt(vm_offset_t l1pt, vm_offset_t va, struct pv_addr *l2pv)
+{
+ pd_entry_t *pde = (pd_entry_t *) l1pt, proto;
+ u_int slot = va >> L1_S_SHIFT;
+
+ proto = L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_C_PROTO;
+
+#ifdef VERBOSE_INIT_ARM
+ printf("pmap_link_l2pt: pa=0x%x va=0x%x\n", l2pv->pv_pa, l2pv->pv_va);
+#endif
+
+ pde[slot + 0] = proto | (l2pv->pv_pa + 0x000);
+
+ PTE_SYNC(&pde[slot]);
+
+ SLIST_INSERT_HEAD(&kernel_pt_list, l2pv, pv_list);
+
+
+}
+
+/*
+ * pmap_map_entry
+ *
+ * Create a single page mapping.
+ */
+void
+pmap_map_entry(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, int prot,
+ int cache)
+{
+ pd_entry_t *pde = (pd_entry_t *) l1pt;
+ pt_entry_t fl;
+ pt_entry_t *pte;
+
+ KASSERT(((va | pa) & PAGE_MASK) == 0, ("ouin"));
+
+ switch (cache) {
+ case PTE_NOCACHE:
+ default:
+ fl = 0;
+ break;
+
+ case PTE_CACHE:
+ fl = pte_l2_s_cache_mode;
+ break;
+
+ case PTE_PAGETABLE:
+ fl = pte_l2_s_cache_mode_pt;
+ break;
+ }
+
+ if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C)
+ panic("pmap_map_entry: no L2 table for VA 0x%08x", va);
+
+ pte = (pt_entry_t *) kernel_pt_lookup(pde[L1_IDX(va)] & L1_C_ADDR_MASK);
+
+ if (pte == NULL)
+ panic("pmap_map_entry: can't find L2 table for VA 0x%08x", va);
+
+ pte[l2pte_index(va)] =
+ L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot) | fl;
+ PTE_SYNC(&pte[l2pte_index(va)]);
+}
+
+/*
+ * pmap_map_chunk:
+ *
+ * Map a chunk of memory using the most efficient mappings
+ * possible (section. large page, small page) into the
+ * provided L1 and L2 tables at the specified virtual address.
+ */
+vm_size_t
+pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa,
+ vm_size_t size, int prot, int cache)
+{
+ pd_entry_t *pde = (pd_entry_t *) l1pt;
+ pt_entry_t *pte, f1, f2s, f2l;
+ vm_size_t resid;
+ int i;
+
+ resid = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+
+ if (l1pt == 0)
+ panic("pmap_map_chunk: no L1 table provided");
+
+#ifdef VERBOSE_INIT_ARM
+ printf("pmap_map_chunk: pa=0x%x va=0x%x size=0x%x resid=0x%x "
+ "prot=0x%x cache=%d\n", pa, va, size, resid, prot, cache);
+#endif
+
+ switch (cache) {
+ case PTE_NOCACHE:
+ default:
+ f1 = 0;
+ f2l = 0;
+ f2s = 0;
+ break;
+
+ case PTE_CACHE:
+ f1 = pte_l1_s_cache_mode;
+ f2l = pte_l2_l_cache_mode;
+ f2s = pte_l2_s_cache_mode;
+ break;
+
+ case PTE_PAGETABLE:
+ f1 = pte_l1_s_cache_mode_pt;
+ f2l = pte_l2_l_cache_mode_pt;
+ f2s = pte_l2_s_cache_mode_pt;
+ break;
+ }
+
+ size = resid;
+
+ while (resid > 0) {
+ /* See if we can use a section mapping. */
+ if (L1_S_MAPPABLE_P(va, pa, resid)) {
+#ifdef VERBOSE_INIT_ARM
+ printf("S");
+#endif
+ pde[va >> L1_S_SHIFT] = L1_S_PROTO | pa |
+ L1_S_PROT(PTE_KERNEL, prot) | f1 |
+ L1_S_DOM(PMAP_DOMAIN_KERNEL);
+ PTE_SYNC(&pde[va >> L1_S_SHIFT]);
+ va += L1_S_SIZE;
+ pa += L1_S_SIZE;
+ resid -= L1_S_SIZE;
+ continue;
+ }
+
+ /*
+ * Ok, we're going to use an L2 table. Make sure
+ * one is actually in the corresponding L1 slot
+ * for the current VA.
+ */
+ if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C)
+ panic("pmap_map_chunk: no L2 table for VA 0x%08x", va);
+
+ pte = (pt_entry_t *) kernel_pt_lookup(
+ pde[L1_IDX(va)] & L1_C_ADDR_MASK);
+ if (pte == NULL)
+ panic("pmap_map_chunk: can't find L2 table for VA"
+ "0x%08x", va);
+ /* See if we can use a L2 large page mapping. */
+ if (L2_L_MAPPABLE_P(va, pa, resid)) {
+#ifdef VERBOSE_INIT_ARM
+ printf("L");
+#endif
+ for (i = 0; i < 16; i++) {
+ pte[l2pte_index(va) + i] =
+ L2_L_PROTO | pa |
+ L2_L_PROT(PTE_KERNEL, prot) | f2l;
+ PTE_SYNC(&pte[l2pte_index(va) + i]);
+ }
+ va += L2_L_SIZE;
+ pa += L2_L_SIZE;
+ resid -= L2_L_SIZE;
+ continue;
+ }
+
+ /* Use a small page mapping. */
+#ifdef VERBOSE_INIT_ARM
+ printf("P");
+#endif
+ pte[l2pte_index(va)] =
+ L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot) | f2s;
+ PTE_SYNC(&pte[l2pte_index(va)]);
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ resid -= PAGE_SIZE;
+ }
+#ifdef VERBOSE_INIT_ARM
+ printf("\n");
+#endif
+ return (size);
+
+}
+
+void
+pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
+{
+ /*
+ * Remember the memattr in a field that gets used to set the appropriate
+ * bits in the PTEs as mappings are established.
+ */
+ m->md.pv_memattr = ma;
+
+ /*
+ * It appears that this function can only be called before any mappings
+ * for the page are established on ARM. If this ever changes, this code
+ * will need to walk the pv_list and make each of the existing mappings
+ * uncacheable, being careful to sync caches and PTEs (and maybe
+ * invalidate TLB?) for any current mapping it modifies.
+ */
+ if (m->md.pv_kva != 0 || TAILQ_FIRST(&m->md.pv_list) != NULL)
+ panic("Can't change memattr on page with existing mappings");
+}
+
+
Property changes on: trunk/sys/arm/arm/pmap.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/sc_machdep.c
===================================================================
--- trunk/sys/arm/arm/sc_machdep.c (rev 0)
+++ trunk/sys/arm/arm/sc_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,91 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/sc_machdep.c 239696 2012-08-25 23:59:31Z gonzo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/kbio.h>
+#include <sys/consio.h>
+#include <sys/sysctl.h>
+
+#include <dev/syscons/syscons.h>
+
+static sc_softc_t sc_softcs[8];
+
+int
+sc_get_cons_priority(int *unit, int *flags)
+{
+
+ *unit = 0;
+ *flags = 0;
+ return (CN_INTERNAL);
+}
+
+int
+sc_max_unit(void)
+{
+ return (1);
+}
+
+sc_softc_t *
+sc_get_softc(int unit, int flags)
+{
+ sc_softc_t *sc;
+
+ if (unit < 0)
+ return (NULL);
+ sc = &sc_softcs[unit];
+ sc->unit = unit;
+ if ((sc->flags & SC_INIT_DONE) == 0) {
+ sc->keyboard = -1;
+ sc->adapter = -1;
+ sc->cursor_char = SC_CURSOR_CHAR;
+ sc->mouse_char = SC_MOUSE_CHAR;
+ }
+ return (sc);
+}
+
+void
+sc_get_bios_values(bios_values_t *values)
+{
+ values->cursor_start = 0;
+ values->cursor_end = 32;
+ values->shift_state = 0;
+}
+
+int
+sc_tone(int hz)
+{
+ return (0);
+}
Property changes on: trunk/sys/arm/arm/sc_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/setcpsr.S
===================================================================
--- trunk/sys/arm/arm/setcpsr.S (rev 0)
+++ trunk/sys/arm/arm/setcpsr.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,83 @@
+/* $MidnightBSD$ */
+/* $NetBSD: setcpsr.S,v 1.2 2002/08/15 01:37:02 briggs Exp $ */
+
+/*-
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * setcpsr.S
+ *
+ * Miscellaneous routines to play with the CPSR register
+ *
+ * Eventually this routine can be inline assembly.
+ *
+ * Created : 12/09/94
+ *
+ * Based of kate/display/setcpsr.s
+ *
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/setcpsr.S 266144 2014-05-15 15:40:05Z ian $");
+
+/* Sets and clears bits in the CPSR register
+ *
+ * r0 - bic mask
+ * r1 - eor mask
+ */
+
+ENTRY_NP(SetCPSR)
+ mrs r3, cpsr /* Set the CPSR */
+ bic r2, r3, r0
+ eor r2, r2, r1
+ msr cpsr_fsxc, r2
+
+ mov r0, r3 /* Return the old CPSR */
+
+ RET
+END(SetCPSR)
+
+
+/* Gets the CPSR register
+ *
+ * Returns the CPSR in r0
+ */
+
+ENTRY_NP(GetCPSR)
+ mrs r0, cpsr /* Get the CPSR */
+
+ RET
+END(GetCPSR)
+
Property changes on: trunk/sys/arm/arm/setcpsr.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/setstack.s
===================================================================
--- trunk/sys/arm/arm/setstack.s (rev 0)
+++ trunk/sys/arm/arm/setstack.s 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,95 @@
+/* $MidnightBSD$ */
+/* $NetBSD: setstack.S,v 1.1 2001/07/28 13:28:03 chris Exp $ */
+
+/*-
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * setstack.S
+ *
+ * Miscellaneous routine to play with the stack pointer in different CPU modes
+ *
+ * Eventually this routine can be inline assembly.
+ *
+ * Created : 17/09/94
+ *
+ * Based of kate/display/setstack.s
+ *
+ */
+
+#include <machine/armreg.h>
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/setstack.s 269796 2014-08-11 01:29:28Z ian $");
+
+/* To set the stack pointer for a particular mode we must switch
+ * to that mode update the banked r13 and then switch back.
+ * This routine provides an easy way of doing this for any mode
+ *
+ * r0 = CPU mode
+ * r1 = stackptr
+ */
+
+ENTRY(set_stackptr)
+ mrs r3, cpsr /* Switch to the appropriate mode */
+ bic r2, r3, #(PSR_MODE)
+ orr r2, r2, r0
+ msr cpsr_fsxc, r2
+
+ mov sp, r1 /* Set the stack pointer */
+
+ msr cpsr_fsxc, r3 /* Restore the old mode */
+
+ mov pc, lr /* Exit */
+END(set_stackptr)
+/* To get the stack pointer for a particular mode we must switch
+ * to that mode copy the banked r13 and then switch back.
+ * This routine provides an easy way of doing this for any mode
+ *
+ * r0 = CPU mode
+ */
+
+ENTRY(get_stackptr)
+ mrs r3, cpsr /* Switch to the appropriate mode */
+ bic r2, r3, #(PSR_MODE)
+ orr r2, r2, r0
+ msr cpsr_fsxc, r2
+
+ mov r0, sp /* Set the stack pointer */
+
+ msr cpsr_fsxc, r3 /* Restore the old mode */
+
+ mov pc, lr /* Exit */
+END(get_stackptr)
+/* End of setstack.S */
Property changes on: trunk/sys/arm/arm/setstack.s
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/stack_machdep.c
===================================================================
--- trunk/sys/arm/arm/stack_machdep.c (rev 0)
+++ trunk/sys/arm/arm/stack_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,93 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Antoine Brodin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/stack_machdep.c 278614 2015-02-12 04:15:55Z ian $");
+
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/stack.h>
+
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/stack.h>
+
+/*
+ * This code makes assumptions about the stack layout. These are correct
+ * when using APCS (the old ABI), but are no longer true with AAPCS and the
+ * ARM EABI. There is also an issue with clang and llvm when building for
+ * APCS where it lays out the stack incorrectly. Because of this we disable
+ * this when building for ARM EABI or when building with clang.
+ */
+
+extern vm_offset_t kernel_vm_end;
+
+static void
+stack_capture(struct stack *st, u_int32_t *frame)
+{
+#if !defined(__ARM_EABI__) && !defined(__clang__)
+ vm_offset_t callpc;
+
+ while (INKERNEL(frame) && (vm_offset_t)frame < kernel_vm_end) {
+ callpc = frame[FR_SCP];
+ if (stack_put(st, callpc) == -1)
+ break;
+ frame = (u_int32_t *)(frame[FR_RFP]);
+ }
+#endif
+}
+
+void
+stack_save_td(struct stack *st, struct thread *td)
+{
+ u_int32_t *frame;
+
+ if (TD_IS_SWAPPED(td))
+ panic("stack_save_td: swapped");
+ if (TD_IS_RUNNING(td))
+ panic("stack_save_td: running");
+
+ /*
+ * This register, the frame pointer, is incorrect for the ARM EABI
+ * as it doesn't have a frame pointer, however it's value is not used
+ * when building for EABI.
+ */
+ frame = (u_int32_t *)td->td_pcb->pcb_regs.sf_r11;
+ stack_zero(st);
+ stack_capture(st, frame);
+}
+
+void
+stack_save(struct stack *st)
+{
+ u_int32_t *frame;
+
+ frame = (u_int32_t *)__builtin_frame_address(0);
+ stack_zero(st);
+ stack_capture(st, frame);
+}
Property changes on: trunk/sys/arm/arm/stack_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/stdatomic.c
===================================================================
--- trunk/sys/arm/arm/stdatomic.c (rev 0)
+++ trunk/sys/arm/arm/stdatomic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,895 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ed Schouten <ed at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/stdatomic.c 275776 2014-12-14 18:28:01Z andrew $");
+
+#include <sys/param.h>
+#include <sys/stdatomic.h>
+#include <sys/types.h>
+
+#include <machine/cpufunc.h>
+#include <machine/sysarch.h>
+
+#ifdef _KERNEL
+#include "opt_global.h"
+#endif
+
+/*
+ * Executing statements with interrupts disabled.
+ */
+
+#if defined(_KERNEL) && !defined(SMP)
+#define WITHOUT_INTERRUPTS(s) do { \
+ register_t regs; \
+ \
+ regs = intr_disable(); \
+ do s while (0); \
+ intr_restore(regs); \
+} while (0)
+#endif /* _KERNEL && !SMP */
+
+/*
+ * Memory barriers.
+ *
+ * It turns out __sync_synchronize() does not emit any code when used
+ * with GCC 4.2. Implement our own version that does work reliably.
+ *
+ * Although __sync_lock_test_and_set() should only perform an acquire
+ * barrier, make it do a full barrier like the other functions. This
+ * should make <stdatomic.h>'s atomic_exchange_explicit() work reliably.
+ */
+
+#if defined(_KERNEL) && !defined(SMP)
+static inline void
+do_sync(void)
+{
+
+ __asm volatile ("" : : : "memory");
+}
+#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
+static inline void
+do_sync(void)
+{
+
+ __asm volatile ("dmb" : : : "memory");
+}
+#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
+ defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
+ defined(__ARM_ARCH_6ZK__)
+static inline void
+do_sync(void)
+{
+
+ __asm volatile ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory");
+}
+#endif
+
+#if defined(__CLANG_ATOMICS) || defined(__GNUC_ATOMICS)
+
+/*
+ * New C11 __atomic_* API.
+ */
+
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
+ defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
+ defined(__ARM_ARCH_6ZK__) || \
+ defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
+
+/* These systems should be supported by the compiler. */
+
+#else /* __ARM_ARCH_5__ */
+
+/* Clang doesn't allow us to reimplement builtins without this. */
+#ifdef __clang__
+#pragma redefine_extname __sync_synchronize_ext __sync_synchronize
+#define __sync_synchronize __sync_synchronize_ext
+#endif
+
+void
+__sync_synchronize(void)
+{
+}
+
+#ifdef _KERNEL
+
+#ifdef SMP
+#error "On SMP systems we should have proper atomic operations."
+#endif
+
+/*
+ * On uniprocessor systems, we can perform the atomic operations by
+ * disabling interrupts.
+ */
+
+#define EMIT_LOAD_N(N, uintN_t) \
+uintN_t \
+__atomic_load_##N(uintN_t *mem, int model __unused) \
+{ \
+ uintN_t ret; \
+ \
+ WITHOUT_INTERRUPTS({ \
+ ret = *mem; \
+ }); \
+ return (ret); \
+}
+
+#define EMIT_STORE_N(N, uintN_t) \
+void \
+__atomic_store_##N(uintN_t *mem, uintN_t val, int model __unused) \
+{ \
+ \
+ WITHOUT_INTERRUPTS({ \
+ *mem = val; \
+ }); \
+}
+
+#define EMIT_COMPARE_EXCHANGE_N(N, uintN_t) \
+_Bool \
+__atomic_compare_exchange_##N(uintN_t *mem, uintN_t *expected, \
+ uintN_t desired, int success __unused, int failure __unused) \
+{ \
+ _Bool ret; \
+ \
+ WITHOUT_INTERRUPTS({ \
+ if (*mem == *expected) { \
+ *mem = desired; \
+ ret = 1; \
+ } else { \
+ *expected = *mem; \
+ ret = 0; \
+ } \
+ }); \
+ return (ret); \
+}
+
+#define EMIT_FETCH_OP_N(N, uintN_t, name, op) \
+uintN_t \
+__atomic_##name##_##N(uintN_t *mem, uintN_t val, int model __unused) \
+{ \
+ uintN_t ret; \
+ \
+ WITHOUT_INTERRUPTS({ \
+ ret = *mem; \
+ *mem op val; \
+ }); \
+ return (ret); \
+}
+
+#define EMIT_ALL_OPS_N(N, uintN_t) \
+EMIT_LOAD_N(N, uintN_t) \
+EMIT_STORE_N(N, uintN_t) \
+EMIT_COMPARE_EXCHANGE_N(N, uintN_t) \
+EMIT_FETCH_OP_N(N, uintN_t, exchange, =) \
+EMIT_FETCH_OP_N(N, uintN_t, fetch_add, +=) \
+EMIT_FETCH_OP_N(N, uintN_t, fetch_and, &=) \
+EMIT_FETCH_OP_N(N, uintN_t, fetch_or, |=) \
+EMIT_FETCH_OP_N(N, uintN_t, fetch_sub, -=) \
+EMIT_FETCH_OP_N(N, uintN_t, fetch_xor, ^=)
+
+EMIT_ALL_OPS_N(1, uint8_t)
+EMIT_ALL_OPS_N(2, uint16_t)
+EMIT_ALL_OPS_N(4, uint32_t)
+EMIT_ALL_OPS_N(8, uint64_t)
+#undef EMIT_ALL_OPS_N
+
+#else /* !_KERNEL */
+
+/*
+ * For userspace on uniprocessor systems, we can implement the atomic
+ * operations by using a Restartable Atomic Sequence. This makes the
+ * kernel restart the code from the beginning when interrupted.
+ */
+
+#define EMIT_LOAD_N(N, uintN_t) \
+uintN_t \
+__atomic_load_##N(uintN_t *mem, int model __unused) \
+{ \
+ \
+ return (*mem); \
+}
+
+#define EMIT_STORE_N(N, uintN_t) \
+void \
+__atomic_store_##N(uintN_t *mem, uintN_t val, int model __unused) \
+{ \
+ \
+ *mem = val; \
+}
+
+#define EMIT_EXCHANGE_N(N, uintN_t, ldr, str) \
+uintN_t \
+__atomic_exchange_##N(uintN_t *mem, uintN_t val, int model __unused) \
+{ \
+ uint32_t old, temp, ras_start; \
+ \
+ ras_start = ARM_RAS_START; \
+ __asm volatile ( \
+ /* Set up Restartable Atomic Sequence. */ \
+ "1:" \
+ "\tadr %2, 1b\n" \
+ "\tstr %2, [%5]\n" \
+ "\tadr %2, 2f\n" \
+ "\tstr %2, [%5, #4]\n" \
+ \
+ "\t"ldr" %0, %4\n" /* Load old value. */ \
+ "\t"str" %3, %1\n" /* Store new value. */ \
+ \
+ /* Tear down Restartable Atomic Sequence. */ \
+ "2:" \
+ "\tmov %2, #0x00000000\n" \
+ "\tstr %2, [%5]\n" \
+ "\tmov %2, #0xffffffff\n" \
+ "\tstr %2, [%5, #4]\n" \
+ : "=&r" (old), "=m" (*mem), "=&r" (temp) \
+ : "r" (val), "m" (*mem), "r" (ras_start)); \
+ return (old); \
+}
+
+#define EMIT_COMPARE_EXCHANGE_N(N, uintN_t, ldr, streq) \
+_Bool \
+__atomic_compare_exchange_##N(uintN_t *mem, uintN_t *pexpected, \
+ uintN_t desired, int success __unused, int failure __unused) \
+{ \
+ uint32_t expected, old, temp, ras_start; \
+ \
+ expected = *pexpected; \
+ ras_start = ARM_RAS_START; \
+ __asm volatile ( \
+ /* Set up Restartable Atomic Sequence. */ \
+ "1:" \
+ "\tadr %2, 1b\n" \
+ "\tstr %2, [%6]\n" \
+ "\tadr %2, 2f\n" \
+ "\tstr %2, [%6, #4]\n" \
+ \
+ "\t"ldr" %0, %5\n" /* Load old value. */ \
+ "\tcmp %0, %3\n" /* Compare to expected value. */\
+ "\t"streq" %4, %1\n" /* Store new value. */ \
+ \
+ /* Tear down Restartable Atomic Sequence. */ \
+ "2:" \
+ "\tmov %2, #0x00000000\n" \
+ "\tstr %2, [%6]\n" \
+ "\tmov %2, #0xffffffff\n" \
+ "\tstr %2, [%6, #4]\n" \
+ : "=&r" (old), "=m" (*mem), "=&r" (temp) \
+ : "r" (expected), "r" (desired), "m" (*mem), \
+ "r" (ras_start)); \
+ if (old == expected) { \
+ return (1); \
+ } else { \
+ *pexpected = old; \
+ return (0); \
+ } \
+}
+
+#define EMIT_FETCH_OP_N(N, uintN_t, ldr, str, name, op) \
+uintN_t \
+__atomic_##name##_##N(uintN_t *mem, uintN_t val, int model __unused) \
+{ \
+ uint32_t old, temp, ras_start; \
+ \
+ ras_start = ARM_RAS_START; \
+ __asm volatile ( \
+ /* Set up Restartable Atomic Sequence. */ \
+ "1:" \
+ "\tadr %2, 1b\n" \
+ "\tstr %2, [%5]\n" \
+ "\tadr %2, 2f\n" \
+ "\tstr %2, [%5, #4]\n" \
+ \
+ "\t"ldr" %0, %4\n" /* Load old value. */ \
+ "\t"op" %2, %0, %3\n" /* Calculate new value. */ \
+ "\t"str" %2, %1\n" /* Store new value. */ \
+ \
+ /* Tear down Restartable Atomic Sequence. */ \
+ "2:" \
+ "\tmov %2, #0x00000000\n" \
+ "\tstr %2, [%5]\n" \
+ "\tmov %2, #0xffffffff\n" \
+ "\tstr %2, [%5, #4]\n" \
+ : "=&r" (old), "=m" (*mem), "=&r" (temp) \
+ : "r" (val), "m" (*mem), "r" (ras_start)); \
+ return (old); \
+}
+
+#define EMIT_ALL_OPS_N(N, uintN_t, ldr, str, streq) \
+EMIT_LOAD_N(N, uintN_t) \
+EMIT_STORE_N(N, uintN_t) \
+EMIT_EXCHANGE_N(N, uintN_t, ldr, str) \
+EMIT_COMPARE_EXCHANGE_N(N, uintN_t, ldr, streq) \
+EMIT_FETCH_OP_N(N, uintN_t, ldr, str, fetch_add, "add") \
+EMIT_FETCH_OP_N(N, uintN_t, ldr, str, fetch_and, "and") \
+EMIT_FETCH_OP_N(N, uintN_t, ldr, str, fetch_or, "orr") \
+EMIT_FETCH_OP_N(N, uintN_t, ldr, str, fetch_sub, "sub") \
+EMIT_FETCH_OP_N(N, uintN_t, ldr, str, fetch_xor, "eor")
+
+EMIT_ALL_OPS_N(1, uint8_t, "ldrb", "strb", "strbeq")
+EMIT_ALL_OPS_N(2, uint16_t, "ldrh", "strh", "strheq")
+EMIT_ALL_OPS_N(4, uint32_t, "ldr", "str", "streq")
+#undef EMIT_ALL_OPS_N
+
+#endif /* _KERNEL */
+
+#endif
+
+#endif /* __CLANG_ATOMICS || __GNUC_ATOMICS */
+
+#if defined(__SYNC_ATOMICS) || defined(EMIT_SYNC_ATOMICS)
+
+#ifdef __clang__
+#pragma redefine_extname __sync_lock_test_and_set_1_c __sync_lock_test_and_set_1
+#pragma redefine_extname __sync_lock_test_and_set_2_c __sync_lock_test_and_set_2
+#pragma redefine_extname __sync_lock_test_and_set_4_c __sync_lock_test_and_set_4
+#pragma redefine_extname __sync_val_compare_and_swap_1_c __sync_val_compare_and_swap_1
+#pragma redefine_extname __sync_val_compare_and_swap_2_c __sync_val_compare_and_swap_2
+#pragma redefine_extname __sync_val_compare_and_swap_4_c __sync_val_compare_and_swap_4
+#pragma redefine_extname __sync_fetch_and_add_1_c __sync_fetch_and_add_1
+#pragma redefine_extname __sync_fetch_and_add_2_c __sync_fetch_and_add_2
+#pragma redefine_extname __sync_fetch_and_add_4_c __sync_fetch_and_add_4
+#pragma redefine_extname __sync_fetch_and_and_1_c __sync_fetch_and_and_1
+#pragma redefine_extname __sync_fetch_and_and_2_c __sync_fetch_and_and_2
+#pragma redefine_extname __sync_fetch_and_and_4_c __sync_fetch_and_and_4
+#pragma redefine_extname __sync_fetch_and_or_1_c __sync_fetch_and_or_1
+#pragma redefine_extname __sync_fetch_and_or_2_c __sync_fetch_and_or_2
+#pragma redefine_extname __sync_fetch_and_or_4_c __sync_fetch_and_or_4
+#pragma redefine_extname __sync_fetch_and_xor_1_c __sync_fetch_and_xor_1
+#pragma redefine_extname __sync_fetch_and_xor_2_c __sync_fetch_and_xor_2
+#pragma redefine_extname __sync_fetch_and_xor_4_c __sync_fetch_and_xor_4
+#pragma redefine_extname __sync_fetch_and_sub_1_c __sync_fetch_and_sub_1
+#pragma redefine_extname __sync_fetch_and_sub_2_c __sync_fetch_and_sub_2
+#pragma redefine_extname __sync_fetch_and_sub_4_c __sync_fetch_and_sub_4
+#endif
+
+/*
+ * Old __sync_* API.
+ */
+
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
+ defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
+ defined(__ARM_ARCH_6ZK__) || \
+ defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
+
+/* Implementations for old GCC versions, lacking support for atomics. */
+
+typedef union {
+ uint8_t v8[4];
+ uint32_t v32;
+} reg_t;
+
+/*
+ * Given a memory address pointing to an 8-bit or 16-bit integer, return
+ * the address of the 32-bit word containing it.
+ */
+
+static inline uint32_t *
+round_to_word(void *ptr)
+{
+
+ return ((uint32_t *)((intptr_t)ptr & ~3));
+}
+
+/*
+ * Utility functions for loading and storing 8-bit and 16-bit integers
+ * in 32-bit words at an offset corresponding with the location of the
+ * atomic variable.
+ */
+
+static inline void
+put_1(reg_t *r, const uint8_t *offset_ptr, uint8_t val)
+{
+ size_t offset;
+
+ offset = (intptr_t)offset_ptr & 3;
+ r->v8[offset] = val;
+}
+
+static inline uint8_t
+get_1(const reg_t *r, const uint8_t *offset_ptr)
+{
+ size_t offset;
+
+ offset = (intptr_t)offset_ptr & 3;
+ return (r->v8[offset]);
+}
+
+static inline void
+put_2(reg_t *r, const uint16_t *offset_ptr, uint16_t val)
+{
+ size_t offset;
+ union {
+ uint16_t in;
+ uint8_t out[2];
+ } bytes;
+
+ offset = (intptr_t)offset_ptr & 3;
+ bytes.in = val;
+ r->v8[offset] = bytes.out[0];
+ r->v8[offset + 1] = bytes.out[1];
+}
+
+static inline uint16_t
+get_2(const reg_t *r, const uint16_t *offset_ptr)
+{
+ size_t offset;
+ union {
+ uint8_t in[2];
+ uint16_t out;
+ } bytes;
+
+ offset = (intptr_t)offset_ptr & 3;
+ bytes.in[0] = r->v8[offset];
+ bytes.in[1] = r->v8[offset + 1];
+ return (bytes.out);
+}
+
+/*
+ * 8-bit and 16-bit routines.
+ *
+ * These operations are not natively supported by the CPU, so we use
+ * some shifting and bitmasking on top of the 32-bit instructions.
+ */
+
+#define EMIT_LOCK_TEST_AND_SET_N(N, uintN_t) \
+uintN_t \
+__sync_lock_test_and_set_##N##_c(uintN_t *mem, uintN_t val) \
+{ \
+ uint32_t *mem32; \
+ reg_t val32, negmask, old; \
+ uint32_t temp1, temp2; \
+ \
+ mem32 = round_to_word(mem); \
+ val32.v32 = 0x00000000; \
+ put_##N(&val32, mem, val); \
+ negmask.v32 = 0xffffffff; \
+ put_##N(&negmask, mem, 0); \
+ \
+ do_sync(); \
+ __asm volatile ( \
+ "1:" \
+ "\tldrex %0, %6\n" /* Load old value. */ \
+ "\tand %2, %5, %0\n" /* Remove the old value. */ \
+ "\torr %2, %2, %4\n" /* Put in the new value. */ \
+ "\tstrex %3, %2, %1\n" /* Attempt to store. */ \
+ "\tcmp %3, #0\n" /* Did it succeed? */ \
+ "\tbne 1b\n" /* Spin if failed. */ \
+ : "=&r" (old.v32), "=m" (*mem32), "=&r" (temp1), \
+ "=&r" (temp2) \
+ : "r" (val32.v32), "r" (negmask.v32), "m" (*mem32)); \
+ return (get_##N(&old, mem)); \
+}
+
+EMIT_LOCK_TEST_AND_SET_N(1, uint8_t)
+EMIT_LOCK_TEST_AND_SET_N(2, uint16_t)
+
+#define EMIT_VAL_COMPARE_AND_SWAP_N(N, uintN_t) \
+uintN_t \
+__sync_val_compare_and_swap_##N##_c(uintN_t *mem, uintN_t expected, \
+ uintN_t desired) \
+{ \
+ uint32_t *mem32; \
+ reg_t expected32, desired32, posmask, old; \
+ uint32_t negmask, temp1, temp2; \
+ \
+ mem32 = round_to_word(mem); \
+ expected32.v32 = 0x00000000; \
+ put_##N(&expected32, mem, expected); \
+ desired32.v32 = 0x00000000; \
+ put_##N(&desired32, mem, desired); \
+ posmask.v32 = 0x00000000; \
+ put_##N(&posmask, mem, ~0); \
+ negmask = ~posmask.v32; \
+ \
+ do_sync(); \
+ __asm volatile ( \
+ "1:" \
+ "\tldrex %0, %8\n" /* Load old value. */ \
+ "\tand %2, %6, %0\n" /* Isolate the old value. */ \
+ "\tcmp %2, %4\n" /* Compare to expected value. */\
+ "\tbne 2f\n" /* Values are unequal. */ \
+ "\tand %2, %7, %0\n" /* Remove the old value. */ \
+ "\torr %2, %5\n" /* Put in the new value. */ \
+ "\tstrex %3, %2, %1\n" /* Attempt to store. */ \
+ "\tcmp %3, #0\n" /* Did it succeed? */ \
+ "\tbne 1b\n" /* Spin if failed. */ \
+ "2:" \
+ : "=&r" (old), "=m" (*mem32), "=&r" (temp1), \
+ "=&r" (temp2) \
+ : "r" (expected32.v32), "r" (desired32.v32), \
+ "r" (posmask.v32), "r" (negmask), "m" (*mem32)); \
+ return (get_##N(&old, mem)); \
+}
+
+EMIT_VAL_COMPARE_AND_SWAP_N(1, uint8_t)
+EMIT_VAL_COMPARE_AND_SWAP_N(2, uint16_t)
+
+#define EMIT_ARITHMETIC_FETCH_AND_OP_N(N, uintN_t, name, op) \
+uintN_t \
+__sync_##name##_##N##_c(uintN_t *mem, uintN_t val) \
+{ \
+ uint32_t *mem32; \
+ reg_t val32, posmask, old; \
+ uint32_t negmask, temp1, temp2; \
+ \
+ mem32 = round_to_word(mem); \
+ val32.v32 = 0x00000000; \
+ put_##N(&val32, mem, val); \
+ posmask.v32 = 0x00000000; \
+ put_##N(&posmask, mem, ~0); \
+ negmask = ~posmask.v32; \
+ \
+ do_sync(); \
+ __asm volatile ( \
+ "1:" \
+ "\tldrex %0, %7\n" /* Load old value. */ \
+ "\t"op" %2, %0, %4\n" /* Calculate new value. */ \
+ "\tand %2, %5\n" /* Isolate the new value. */ \
+ "\tand %3, %6, %0\n" /* Remove the old value. */ \
+ "\torr %2, %2, %3\n" /* Put in the new value. */ \
+ "\tstrex %3, %2, %1\n" /* Attempt to store. */ \
+ "\tcmp %3, #0\n" /* Did it succeed? */ \
+ "\tbne 1b\n" /* Spin if failed. */ \
+ : "=&r" (old.v32), "=m" (*mem32), "=&r" (temp1), \
+ "=&r" (temp2) \
+ : "r" (val32.v32), "r" (posmask.v32), "r" (negmask), \
+ "m" (*mem32)); \
+ return (get_##N(&old, mem)); \
+}
+
+EMIT_ARITHMETIC_FETCH_AND_OP_N(1, uint8_t, fetch_and_add, "add")
+EMIT_ARITHMETIC_FETCH_AND_OP_N(1, uint8_t, fetch_and_sub, "sub")
+EMIT_ARITHMETIC_FETCH_AND_OP_N(2, uint16_t, fetch_and_add, "add")
+EMIT_ARITHMETIC_FETCH_AND_OP_N(2, uint16_t, fetch_and_sub, "sub")
+
+#define EMIT_BITWISE_FETCH_AND_OP_N(N, uintN_t, name, op, idempotence) \
+uintN_t \
+__sync_##name##_##N##_c(uintN_t *mem, uintN_t val) \
+{ \
+ uint32_t *mem32; \
+ reg_t val32, old; \
+ uint32_t temp1, temp2; \
+ \
+ mem32 = round_to_word(mem); \
+ val32.v32 = idempotence ? 0xffffffff : 0x00000000; \
+ put_##N(&val32, mem, val); \
+ \
+ do_sync(); \
+ __asm volatile ( \
+ "1:" \
+ "\tldrex %0, %5\n" /* Load old value. */ \
+ "\t"op" %2, %4, %0\n" /* Calculate new value. */ \
+ "\tstrex %3, %2, %1\n" /* Attempt to store. */ \
+ "\tcmp %3, #0\n" /* Did it succeed? */ \
+ "\tbne 1b\n" /* Spin if failed. */ \
+ : "=&r" (old.v32), "=m" (*mem32), "=&r" (temp1), \
+ "=&r" (temp2) \
+ : "r" (val32.v32), "m" (*mem32)); \
+ return (get_##N(&old, mem)); \
+}
+
+EMIT_BITWISE_FETCH_AND_OP_N(1, uint8_t, fetch_and_and, "and", 1)
+EMIT_BITWISE_FETCH_AND_OP_N(1, uint8_t, fetch_and_or, "orr", 0)
+EMIT_BITWISE_FETCH_AND_OP_N(1, uint8_t, fetch_and_xor, "eor", 0)
+EMIT_BITWISE_FETCH_AND_OP_N(2, uint16_t, fetch_and_and, "and", 1)
+EMIT_BITWISE_FETCH_AND_OP_N(2, uint16_t, fetch_and_or, "orr", 0)
+EMIT_BITWISE_FETCH_AND_OP_N(2, uint16_t, fetch_and_xor, "eor", 0)
+
+/*
+ * 32-bit routines.
+ */
+
+uint32_t
+__sync_lock_test_and_set_4_c(uint32_t *mem, uint32_t val)
+{
+ uint32_t old, temp;
+
+ do_sync();
+ __asm volatile (
+ "1:"
+ "\tldrex %0, %4\n" /* Load old value. */
+ "\tstrex %2, %3, %1\n" /* Attempt to store. */
+ "\tcmp %2, #0\n" /* Did it succeed? */
+ "\tbne 1b\n" /* Spin if failed. */
+ : "=&r" (old), "=m" (*mem), "=&r" (temp)
+ : "r" (val), "m" (*mem));
+ return (old);
+}
+
+uint32_t
+__sync_val_compare_and_swap_4_c(uint32_t *mem, uint32_t expected,
+ uint32_t desired)
+{
+ uint32_t old, temp;
+
+ do_sync();
+ __asm volatile (
+ "1:"
+ "\tldrex %0, %5\n" /* Load old value. */
+ "\tcmp %0, %3\n" /* Compare to expected value. */
+ "\tbne 2f\n" /* Values are unequal. */
+ "\tstrex %2, %4, %1\n" /* Attempt to store. */
+ "\tcmp %2, #0\n" /* Did it succeed? */
+ "\tbne 1b\n" /* Spin if failed. */
+ "2:"
+ : "=&r" (old), "=m" (*mem), "=&r" (temp)
+ : "r" (expected), "r" (desired), "m" (*mem));
+ return (old);
+}
+
+#define EMIT_FETCH_AND_OP_4(name, op) \
+uint32_t \
+__sync_##name##_4##_c(uint32_t *mem, uint32_t val) \
+{ \
+ uint32_t old, temp1, temp2; \
+ \
+ do_sync(); \
+ __asm volatile ( \
+ "1:" \
+ "\tldrex %0, %5\n" /* Load old value. */ \
+ "\t"op" %2, %0, %4\n" /* Calculate new value. */ \
+ "\tstrex %3, %2, %1\n" /* Attempt to store. */ \
+ "\tcmp %3, #0\n" /* Did it succeed? */ \
+ "\tbne 1b\n" /* Spin if failed. */ \
+ : "=&r" (old), "=m" (*mem), "=&r" (temp1), \
+ "=&r" (temp2) \
+ : "r" (val), "m" (*mem)); \
+ return (old); \
+}
+
+EMIT_FETCH_AND_OP_4(fetch_and_add, "add")
+EMIT_FETCH_AND_OP_4(fetch_and_and, "and")
+EMIT_FETCH_AND_OP_4(fetch_and_or, "orr")
+EMIT_FETCH_AND_OP_4(fetch_and_sub, "sub")
+EMIT_FETCH_AND_OP_4(fetch_and_xor, "eor")
+
+#ifndef __clang__
+__strong_reference(__sync_lock_test_and_set_1_c, __sync_lock_test_and_set_1);
+__strong_reference(__sync_lock_test_and_set_2_c, __sync_lock_test_and_set_2);
+__strong_reference(__sync_lock_test_and_set_4_c, __sync_lock_test_and_set_4);
+__strong_reference(__sync_val_compare_and_swap_1_c, __sync_val_compare_and_swap_1);
+__strong_reference(__sync_val_compare_and_swap_2_c, __sync_val_compare_and_swap_2);
+__strong_reference(__sync_val_compare_and_swap_4_c, __sync_val_compare_and_swap_4);
+__strong_reference(__sync_fetch_and_add_1_c, __sync_fetch_and_add_1);
+__strong_reference(__sync_fetch_and_add_2_c, __sync_fetch_and_add_2);
+__strong_reference(__sync_fetch_and_add_4_c, __sync_fetch_and_add_4);
+__strong_reference(__sync_fetch_and_and_1_c, __sync_fetch_and_and_1);
+__strong_reference(__sync_fetch_and_and_2_c, __sync_fetch_and_and_2);
+__strong_reference(__sync_fetch_and_and_4_c, __sync_fetch_and_and_4);
+__strong_reference(__sync_fetch_and_sub_1_c, __sync_fetch_and_sub_1);
+__strong_reference(__sync_fetch_and_sub_2_c, __sync_fetch_and_sub_2);
+__strong_reference(__sync_fetch_and_sub_4_c, __sync_fetch_and_sub_4);
+__strong_reference(__sync_fetch_and_or_1_c, __sync_fetch_and_or_1);
+__strong_reference(__sync_fetch_and_or_2_c, __sync_fetch_and_or_2);
+__strong_reference(__sync_fetch_and_or_4_c, __sync_fetch_and_or_4);
+__strong_reference(__sync_fetch_and_xor_1_c, __sync_fetch_and_xor_1);
+__strong_reference(__sync_fetch_and_xor_2_c, __sync_fetch_and_xor_2);
+__strong_reference(__sync_fetch_and_xor_4_c, __sync_fetch_and_xor_4);
+#endif
+
+#else /* __ARM_ARCH_5__ */
+
+#ifdef _KERNEL
+
+#ifdef SMP
+#error "On SMP systems we should have proper atomic operations."
+#endif
+
+/*
+ * On uniprocessor systems, we can perform the atomic operations by
+ * disabling interrupts.
+ */
+
+#define EMIT_VAL_COMPARE_AND_SWAP_N(N, uintN_t) \
+uintN_t \
+__sync_val_compare_and_swap_##N(uintN_t *mem, uintN_t expected, \
+ uintN_t desired) \
+{ \
+ uintN_t ret; \
+ \
+ WITHOUT_INTERRUPTS({ \
+ ret = *mem; \
+ if (*mem == expected) \
+ *mem = desired; \
+ }); \
+ return (ret); \
+}
+
+#define EMIT_FETCH_AND_OP_N(N, uintN_t, name, op) \
+uintN_t \
+__sync_##name##_##N(uintN_t *mem, uintN_t val) \
+{ \
+ uintN_t ret; \
+ \
+ WITHOUT_INTERRUPTS({ \
+ ret = *mem; \
+ *mem op val; \
+ }); \
+ return (ret); \
+}
+
+#define EMIT_ALL_OPS_N(N, uintN_t) \
+EMIT_VAL_COMPARE_AND_SWAP_N(N, uintN_t) \
+EMIT_FETCH_AND_OP_N(N, uintN_t, lock_test_and_set, =) \
+EMIT_FETCH_AND_OP_N(N, uintN_t, fetch_and_add, +=) \
+EMIT_FETCH_AND_OP_N(N, uintN_t, fetch_and_and, &=) \
+EMIT_FETCH_AND_OP_N(N, uintN_t, fetch_and_or, |=) \
+EMIT_FETCH_AND_OP_N(N, uintN_t, fetch_and_sub, -=) \
+EMIT_FETCH_AND_OP_N(N, uintN_t, fetch_and_xor, ^=)
+
+EMIT_ALL_OPS_N(1, uint8_t)
+EMIT_ALL_OPS_N(2, uint16_t)
+EMIT_ALL_OPS_N(4, uint32_t)
+EMIT_ALL_OPS_N(8, uint64_t)
+#undef EMIT_ALL_OPS_N
+
+#else /* !_KERNEL */
+
+/*
+ * For userspace on uniprocessor systems, we can implement the atomic
+ * operations by using a Restartable Atomic Sequence. This makes the
+ * kernel restart the code from the beginning when interrupted.
+ */
+
+#define EMIT_LOCK_TEST_AND_SET_N(N, uintN_t, ldr, str) \
+uintN_t \
+__sync_lock_test_and_set_##N##_c(uintN_t *mem, uintN_t val) \
+{ \
+ uint32_t old, temp, ras_start; \
+ \
+ ras_start = ARM_RAS_START; \
+ __asm volatile ( \
+ /* Set up Restartable Atomic Sequence. */ \
+ "1:" \
+ "\tadr %2, 1b\n" \
+ "\tstr %2, [%5]\n" \
+ "\tadr %2, 2f\n" \
+ "\tstr %2, [%5, #4]\n" \
+ \
+ "\t"ldr" %0, %4\n" /* Load old value. */ \
+ "\t"str" %3, %1\n" /* Store new value. */ \
+ \
+ /* Tear down Restartable Atomic Sequence. */ \
+ "2:" \
+ "\tmov %2, #0x00000000\n" \
+ "\tstr %2, [%5]\n" \
+ "\tmov %2, #0xffffffff\n" \
+ "\tstr %2, [%5, #4]\n" \
+ : "=&r" (old), "=m" (*mem), "=&r" (temp) \
+ : "r" (val), "m" (*mem), "r" (ras_start)); \
+ return (old); \
+}
+
+#define EMIT_VAL_COMPARE_AND_SWAP_N(N, uintN_t, ldr, streq) \
+uintN_t \
+__sync_val_compare_and_swap_##N##_c(uintN_t *mem, uintN_t expected, \
+ uintN_t desired) \
+{ \
+ uint32_t old, temp, ras_start; \
+ \
+ ras_start = ARM_RAS_START; \
+ __asm volatile ( \
+ /* Set up Restartable Atomic Sequence. */ \
+ "1:" \
+ "\tadr %2, 1b\n" \
+ "\tstr %2, [%6]\n" \
+ "\tadr %2, 2f\n" \
+ "\tstr %2, [%6, #4]\n" \
+ \
+ "\t"ldr" %0, %5\n" /* Load old value. */ \
+ "\tcmp %0, %3\n" /* Compare to expected value. */\
+ "\t"streq" %4, %1\n" /* Store new value. */ \
+ \
+ /* Tear down Restartable Atomic Sequence. */ \
+ "2:" \
+ "\tmov %2, #0x00000000\n" \
+ "\tstr %2, [%6]\n" \
+ "\tmov %2, #0xffffffff\n" \
+ "\tstr %2, [%6, #4]\n" \
+ : "=&r" (old), "=m" (*mem), "=&r" (temp) \
+ : "r" (expected), "r" (desired), "m" (*mem), \
+ "r" (ras_start)); \
+ return (old); \
+}
+
+#define EMIT_FETCH_AND_OP_N(N, uintN_t, ldr, str, name, op) \
+uintN_t \
+__sync_##name##_##N##_c(uintN_t *mem, uintN_t val) \
+{ \
+ uint32_t old, temp, ras_start; \
+ \
+ ras_start = ARM_RAS_START; \
+ __asm volatile ( \
+ /* Set up Restartable Atomic Sequence. */ \
+ "1:" \
+ "\tadr %2, 1b\n" \
+ "\tstr %2, [%5]\n" \
+ "\tadr %2, 2f\n" \
+ "\tstr %2, [%5, #4]\n" \
+ \
+ "\t"ldr" %0, %4\n" /* Load old value. */ \
+ "\t"op" %2, %0, %3\n" /* Calculate new value. */ \
+ "\t"str" %2, %1\n" /* Store new value. */ \
+ \
+ /* Tear down Restartable Atomic Sequence. */ \
+ "2:" \
+ "\tmov %2, #0x00000000\n" \
+ "\tstr %2, [%5]\n" \
+ "\tmov %2, #0xffffffff\n" \
+ "\tstr %2, [%5, #4]\n" \
+ : "=&r" (old), "=m" (*mem), "=&r" (temp) \
+ : "r" (val), "m" (*mem), "r" (ras_start)); \
+ return (old); \
+}
+
+#define EMIT_ALL_OPS_N(N, uintN_t, ldr, str, streq) \
+EMIT_LOCK_TEST_AND_SET_N(N, uintN_t, ldr, str) \
+EMIT_VAL_COMPARE_AND_SWAP_N(N, uintN_t, ldr, streq) \
+EMIT_FETCH_AND_OP_N(N, uintN_t, ldr, str, fetch_and_add, "add") \
+EMIT_FETCH_AND_OP_N(N, uintN_t, ldr, str, fetch_and_and, "and") \
+EMIT_FETCH_AND_OP_N(N, uintN_t, ldr, str, fetch_and_or, "orr") \
+EMIT_FETCH_AND_OP_N(N, uintN_t, ldr, str, fetch_and_sub, "sub") \
+EMIT_FETCH_AND_OP_N(N, uintN_t, ldr, str, fetch_and_xor, "eor")
+
+#ifdef __clang__
+EMIT_ALL_OPS_N(1, uint8_t, "ldrb", "strb", "strbeq")
+EMIT_ALL_OPS_N(2, uint16_t, "ldrh", "strh", "strheq")
+#else
+EMIT_ALL_OPS_N(1, uint8_t, "ldrb", "strb", "streqb")
+EMIT_ALL_OPS_N(2, uint16_t, "ldrh", "strh", "streqh")
+#endif
+EMIT_ALL_OPS_N(4, uint32_t, "ldr", "str", "streq")
+
+#ifndef __clang__
+__strong_reference(__sync_lock_test_and_set_1_c, __sync_lock_test_and_set_1);
+__strong_reference(__sync_lock_test_and_set_2_c, __sync_lock_test_and_set_2);
+__strong_reference(__sync_lock_test_and_set_4_c, __sync_lock_test_and_set_4);
+__strong_reference(__sync_val_compare_and_swap_1_c, __sync_val_compare_and_swap_1);
+__strong_reference(__sync_val_compare_and_swap_2_c, __sync_val_compare_and_swap_2);
+__strong_reference(__sync_val_compare_and_swap_4_c, __sync_val_compare_and_swap_4);
+__strong_reference(__sync_fetch_and_add_1_c, __sync_fetch_and_add_1);
+__strong_reference(__sync_fetch_and_add_2_c, __sync_fetch_and_add_2);
+__strong_reference(__sync_fetch_and_add_4_c, __sync_fetch_and_add_4);
+__strong_reference(__sync_fetch_and_and_1_c, __sync_fetch_and_and_1);
+__strong_reference(__sync_fetch_and_and_2_c, __sync_fetch_and_and_2);
+__strong_reference(__sync_fetch_and_and_4_c, __sync_fetch_and_and_4);
+__strong_reference(__sync_fetch_and_sub_1_c, __sync_fetch_and_sub_1);
+__strong_reference(__sync_fetch_and_sub_2_c, __sync_fetch_and_sub_2);
+__strong_reference(__sync_fetch_and_sub_4_c, __sync_fetch_and_sub_4);
+__strong_reference(__sync_fetch_and_or_1_c, __sync_fetch_and_or_1);
+__strong_reference(__sync_fetch_and_or_2_c, __sync_fetch_and_or_2);
+__strong_reference(__sync_fetch_and_or_4_c, __sync_fetch_and_or_4);
+__strong_reference(__sync_fetch_and_xor_1_c, __sync_fetch_and_xor_1);
+__strong_reference(__sync_fetch_and_xor_2_c, __sync_fetch_and_xor_2);
+__strong_reference(__sync_fetch_and_xor_4_c, __sync_fetch_and_xor_4);
+#endif
+
+#endif /* _KERNEL */
+
+#endif
+
+#endif /* __SYNC_ATOMICS */
Property changes on: trunk/sys/arm/arm/stdatomic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/support.S
===================================================================
--- trunk/sys/arm/arm/support.S (rev 0)
+++ trunk/sys/arm/arm/support.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,2966 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/support.S 275767 2014-12-14 16:28:53Z andrew $");
+
+#include "assym.s"
+
+ .syntax unified
+
+.L_arm_memcpy:
+ .word _C_LABEL(_arm_memcpy)
+.L_arm_bzero:
+ .word _C_LABEL(_arm_bzero)
+.L_min_memcpy_size:
+ .word _C_LABEL(_min_memcpy_size)
+.L_min_bzero_size:
+ .word _C_LABEL(_min_bzero_size)
+/*
+ * memset: Sets a block of memory to the specified value
+ *
+ * On entry:
+ * r0 - dest address
+ * r1 - byte to write
+ * r2 - number of bytes to write
+ *
+ * On exit:
+ * r0 - dest address
+ */
+/* LINTSTUB: Func: void bzero(void *, size_t) */
+ENTRY(bzero)
+ ldr r3, .L_arm_bzero
+ ldr r3, [r3]
+ cmp r3, #0
+ beq .Lnormal0
+ ldr r2, .L_min_bzero_size
+ ldr r2, [r2]
+ cmp r1, r2
+ blt .Lnormal0
+ stmfd sp!, {r0, r1, lr}
+ mov r2, #0
+ mov lr, pc
+ mov pc, r3
+ cmp r0, #0
+ ldmfd sp!, {r0, r1, lr}
+ RETeq
+.Lnormal0:
+ mov r3, #0x00
+ b do_memset
+END(bzero)
+/* LINTSTUB: Func: void *memset(void *, int, size_t) */
+ENTRY(memset)
+ and r3, r1, #0xff /* We deal with bytes */
+ mov r1, r2
+do_memset:
+ cmp r1, #0x04 /* Do we have less than 4 bytes */
+ mov ip, r0
+ blt .Lmemset_lessthanfour
+
+ /* Ok first we will word align the address */
+ ands r2, ip, #0x03 /* Get the bottom two bits */
+ bne .Lmemset_wordunaligned /* The address is not word aligned */
+
+ /* We are now word aligned */
+.Lmemset_wordaligned:
+ orr r3, r3, r3, lsl #8 /* Extend value to 16-bits */
+#ifdef _ARM_ARCH_5E
+ tst ip, #0x04 /* Quad-align for armv5e */
+#else
+ cmp r1, #0x10
+#endif
+ orr r3, r3, r3, lsl #16 /* Extend value to 32-bits */
+#ifdef _ARM_ARCH_5E
+ subne r1, r1, #0x04 /* Quad-align if necessary */
+ strne r3, [ip], #0x04
+ cmp r1, #0x10
+#endif
+ blt .Lmemset_loop4 /* If less than 16 then use words */
+ mov r2, r3 /* Duplicate data */
+ cmp r1, #0x80 /* If < 128 then skip the big loop */
+ blt .Lmemset_loop32
+
+ /* Do 128 bytes at a time */
+.Lmemset_loop128:
+ subs r1, r1, #0x80
+#ifdef _ARM_ARCH_5E
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+#else
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+#endif
+ bgt .Lmemset_loop128
+ RETeq /* Zero length so just exit */
+
+ add r1, r1, #0x80 /* Adjust for extra sub */
+
+ /* Do 32 bytes at a time */
+.Lmemset_loop32:
+ subs r1, r1, #0x20
+#ifdef _ARM_ARCH_5E
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+#else
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+#endif
+ bgt .Lmemset_loop32
+ RETeq /* Zero length so just exit */
+
+ adds r1, r1, #0x10 /* Partially adjust for extra sub */
+
+ /* Deal with 16 bytes or more */
+#ifdef _ARM_ARCH_5E
+ strdge r2, [ip], #0x08
+ strdge r2, [ip], #0x08
+#else
+ stmiage ip!, {r2-r3}
+ stmiage ip!, {r2-r3}
+#endif
+ RETeq /* Zero length so just exit */
+
+ addlt r1, r1, #0x10 /* Possibly adjust for extra sub */
+
+ /* We have at least 4 bytes so copy as words */
+.Lmemset_loop4:
+ subs r1, r1, #0x04
+ strge r3, [ip], #0x04
+ bgt .Lmemset_loop4
+ RETeq /* Zero length so just exit */
+
+#ifdef _ARM_ARCH_5E
+ /* Compensate for 64-bit alignment check */
+ adds r1, r1, #0x04
+ RETeq
+ cmp r1, #2
+#else
+ cmp r1, #-2
+#endif
+
+ strb r3, [ip], #0x01 /* Set 1 byte */
+ strbge r3, [ip], #0x01 /* Set another byte */
+ strbgt r3, [ip] /* and a third */
+ RET /* Exit */
+
+.Lmemset_wordunaligned:
+ rsb r2, r2, #0x004
+ strb r3, [ip], #0x01 /* Set 1 byte */
+ cmp r2, #0x02
+ strbge r3, [ip], #0x01 /* Set another byte */
+ sub r1, r1, r2
+ strbgt r3, [ip], #0x01 /* and a third */
+ cmp r1, #0x04 /* More than 4 bytes left? */
+ bge .Lmemset_wordaligned /* Yup */
+
+.Lmemset_lessthanfour:
+ cmp r1, #0x00
+ RETeq /* Zero length so exit */
+ strb r3, [ip], #0x01 /* Set 1 byte */
+ cmp r1, #0x02
+ strbge r3, [ip], #0x01 /* Set another byte */
+ strbgt r3, [ip] /* and a third */
+ RET /* Exit */
+EEND(memset)
+END(bzero)
+
+ENTRY(bcmp)
+ mov ip, r0
+ cmp r2, #0x06
+ beq .Lmemcmp_6bytes
+ mov r0, #0x00
+
+ /* Are both addresses aligned the same way? */
+ cmp r2, #0x00
+ eorsne r3, ip, r1
+ RETeq /* len == 0, or same addresses! */
+ tst r3, #0x03
+ subne r2, r2, #0x01
+ bne .Lmemcmp_bytewise2 /* Badly aligned. Do it the slow way */
+
+ /* Word-align the addresses, if necessary */
+ sub r3, r1, #0x05
+ ands r3, r3, #0x03
+ add r3, r3, r3, lsl #1
+ addne pc, pc, r3, lsl #3
+ nop
+
+ /* Compare up to 3 bytes */
+ ldrb r0, [ip], #0x01
+ ldrb r3, [r1], #0x01
+ subs r0, r0, r3
+ RETne
+ subs r2, r2, #0x01
+ RETeq
+
+ /* Compare up to 2 bytes */
+ ldrb r0, [ip], #0x01
+ ldrb r3, [r1], #0x01
+ subs r0, r0, r3
+ RETne
+ subs r2, r2, #0x01
+ RETeq
+
+ /* Compare 1 byte */
+ ldrb r0, [ip], #0x01
+ ldrb r3, [r1], #0x01
+ subs r0, r0, r3
+ RETne
+ subs r2, r2, #0x01
+ RETeq
+
+ /* Compare 4 bytes at a time, if possible */
+ subs r2, r2, #0x04
+ bcc .Lmemcmp_bytewise
+.Lmemcmp_word_aligned:
+ ldr r0, [ip], #0x04
+ ldr r3, [r1], #0x04
+ subs r2, r2, #0x04
+ cmpcs r0, r3
+ beq .Lmemcmp_word_aligned
+ sub r0, r0, r3
+
+ /* Correct for extra subtraction, and check if done */
+ adds r2, r2, #0x04
+ cmpeq r0, #0x00 /* If done, did all bytes match? */
+ RETeq /* Yup. Just return */
+
+ /* Re-do the final word byte-wise */
+ sub ip, ip, #0x04
+ sub r1, r1, #0x04
+
+.Lmemcmp_bytewise:
+ add r2, r2, #0x03
+.Lmemcmp_bytewise2:
+ ldrb r0, [ip], #0x01
+ ldrb r3, [r1], #0x01
+ subs r2, r2, #0x01
+ cmpcs r0, r3
+ beq .Lmemcmp_bytewise2
+ sub r0, r0, r3
+ RET
+
+ /*
+ * 6 byte compares are very common, thanks to the network stack.
+ * This code is hand-scheduled to reduce the number of stalls for
+ * load results. Everything else being equal, this will be ~32%
+ * faster than a byte-wise memcmp.
+ */
+ .align 5
+.Lmemcmp_6bytes:
+ ldrb r3, [r1, #0x00] /* r3 = b2#0 */
+ ldrb r0, [ip, #0x00] /* r0 = b1#0 */
+ ldrb r2, [r1, #0x01] /* r2 = b2#1 */
+ subs r0, r0, r3 /* r0 = b1#0 - b2#0 */
+ ldrbeq r3, [ip, #0x01] /* r3 = b1#1 */
+ RETne /* Return if mismatch on #0 */
+ subs r0, r3, r2 /* r0 = b1#1 - b2#1 */
+ ldrbeq r3, [r1, #0x02] /* r3 = b2#2 */
+ ldrbeq r0, [ip, #0x02] /* r0 = b1#2 */
+ RETne /* Return if mismatch on #1 */
+ ldrb r2, [r1, #0x03] /* r2 = b2#3 */
+ subs r0, r0, r3 /* r0 = b1#2 - b2#2 */
+ ldrbeq r3, [ip, #0x03] /* r3 = b1#3 */
+ RETne /* Return if mismatch on #2 */
+ subs r0, r3, r2 /* r0 = b1#3 - b2#3 */
+ ldrbeq r3, [r1, #0x04] /* r3 = b2#4 */
+ ldrbeq r0, [ip, #0x04] /* r0 = b1#4 */
+ RETne /* Return if mismatch on #3 */
+ ldrb r2, [r1, #0x05] /* r2 = b2#5 */
+ subs r0, r0, r3 /* r0 = b1#4 - b2#4 */
+ ldrbeq r3, [ip, #0x05] /* r3 = b1#5 */
+ RETne /* Return if mismatch on #4 */
+ sub r0, r3, r2 /* r0 = b1#5 - b2#5 */
+ RET
+END(bcmp)
+
+ENTRY(bcopy)
+ /* switch the source and destination registers */
+ eor r0, r1, r0
+ eor r1, r0, r1
+ eor r0, r1, r0
+EENTRY(memmove)
+ /* Do the buffers overlap? */
+ cmp r0, r1
+ RETeq /* Bail now if src/dst are the same */
+ subcc r3, r0, r1 /* if (dst > src) r3 = dst - src */
+ subcs r3, r1, r0 /* if (src > dsr) r3 = src - dst */
+ cmp r3, r2 /* if (r3 < len) we have an overlap */
+ bcc PIC_SYM(_C_LABEL(memcpy), PLT)
+
+ /* Determine copy direction */
+ cmp r1, r0
+ bcc .Lmemmove_backwards
+
+ moveq r0, #0 /* Quick abort for len=0 */
+ RETeq
+
+ stmdb sp!, {r0, lr} /* memmove() returns dest addr */
+ subs r2, r2, #4
+ blt .Lmemmove_fl4 /* less than 4 bytes */
+ ands r12, r0, #3
+ bne .Lmemmove_fdestul /* oh unaligned destination addr */
+ ands r12, r1, #3
+ bne .Lmemmove_fsrcul /* oh unaligned source addr */
+
+.Lmemmove_ft8:
+ /* We have aligned source and destination */
+ subs r2, r2, #8
+ blt .Lmemmove_fl12 /* less than 12 bytes (4 from above) */
+ subs r2, r2, #0x14
+ blt .Lmemmove_fl32 /* less than 32 bytes (12 from above) */
+ stmdb sp!, {r4} /* borrow r4 */
+
+ /* blat 32 bytes at a time */
+ /* XXX for really big copies perhaps we should use more registers */
+.Lmemmove_floop32:
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge .Lmemmove_floop32
+
+ cmn r2, #0x10
+ ldmiage r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+ stmiage r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ ldmia sp!, {r4} /* return r4 */
+
+.Lmemmove_fl32:
+ adds r2, r2, #0x14
+
+ /* blat 12 bytes at a time */
+.Lmemmove_floop12:
+ ldmiage r1!, {r3, r12, lr}
+ stmiage r0!, {r3, r12, lr}
+ subsge r2, r2, #0x0c
+ bge .Lmemmove_floop12
+
+.Lmemmove_fl12:
+ adds r2, r2, #8
+ blt .Lmemmove_fl4
+
+ subs r2, r2, #4
+ ldrlt r3, [r1], #4
+ strlt r3, [r0], #4
+ ldmiage r1!, {r3, r12}
+ stmiage r0!, {r3, r12}
+ subge r2, r2, #4
+
+.Lmemmove_fl4:
+ /* less than 4 bytes to go */
+ adds r2, r2, #4
+ ldmiaeq sp!, {r0, pc} /* done */
+
+ /* copy the crud byte at a time */
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrbge r3, [r1], #1
+ strbge r3, [r0], #1
+ ldrbgt r3, [r1], #1
+ strbgt r3, [r0], #1
+ ldmia sp!, {r0, pc}
+
+ /* erg - unaligned destination */
+.Lmemmove_fdestul:
+ rsb r12, r12, #4
+ cmp r12, #2
+
+ /* align destination with byte copies */
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrbge r3, [r1], #1
+ strbge r3, [r0], #1
+ ldrbgt r3, [r1], #1
+ strbgt r3, [r0], #1
+ subs r2, r2, r12
+ blt .Lmemmove_fl4 /* less the 4 bytes */
+
+ ands r12, r1, #3
+ beq .Lmemmove_ft8 /* we have an aligned source */
+
+ /* erg - unaligned source */
+ /* This is where it gets nasty ... */
+.Lmemmove_fsrcul:
+ bic r1, r1, #3
+ ldr lr, [r1], #4
+ cmp r12, #2
+ bgt .Lmemmove_fsrcul3
+ beq .Lmemmove_fsrcul2
+ cmp r2, #0x0c
+ blt .Lmemmove_fsrcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemmove_fsrcul1loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #8
+#else
+ mov r3, lr, lsr #8
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #24
+ mov r4, r4, lsl #8
+ orr r4, r4, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r12, lsr #24
+ mov r12, r12, lsl #8
+ orr r12, r12, lr, lsr #24
+#else
+ orr r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r12, lsl #24
+ mov r12, r12, lsr #8
+ orr r12, r12, lr, lsl #24
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemmove_fsrcul1loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_fsrcul1l4
+
+.Lmemmove_fsrcul1loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #8
+#else
+ mov r12, lr, lsr #8
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #24
+#else
+ orr r12, r12, lr, lsl #24
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemmove_fsrcul1loop4
+
+.Lmemmove_fsrcul1l4:
+ sub r1, r1, #3
+ b .Lmemmove_fl4
+
+.Lmemmove_fsrcul2:
+ cmp r2, #0x0c
+ blt .Lmemmove_fsrcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemmove_fsrcul2loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #16
+#else
+ mov r3, lr, lsr #16
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #16
+ mov r4, r4, lsl #16
+ orr r4, r4, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r12, lsr #16
+ mov r12, r12, lsl #16
+ orr r12, r12, lr, lsr #16
+#else
+ orr r3, r3, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r12, lsl #16
+ mov r12, r12, lsr #16
+ orr r12, r12, lr, lsl #16
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemmove_fsrcul2loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_fsrcul2l4
+
+.Lmemmove_fsrcul2loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #16
+#else
+ mov r12, lr, lsr #16
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #16
+#else
+ orr r12, r12, lr, lsl #16
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemmove_fsrcul2loop4
+
+.Lmemmove_fsrcul2l4:
+ sub r1, r1, #2
+ b .Lmemmove_fl4
+
+.Lmemmove_fsrcul3:
+ cmp r2, #0x0c
+ blt .Lmemmove_fsrcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemmove_fsrcul3loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #24
+#else
+ mov r3, lr, lsr #24
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #8
+ mov r4, r4, lsl #24
+ orr r4, r4, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r12, lsr #8
+ mov r12, r12, lsl #24
+ orr r12, r12, lr, lsr #8
+#else
+ orr r3, r3, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r12, lsl #8
+ mov r12, r12, lsr #24
+ orr r12, r12, lr, lsl #8
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemmove_fsrcul3loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_fsrcul3l4
+
+.Lmemmove_fsrcul3loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #24
+#else
+ mov r12, lr, lsr #24
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #8
+#else
+ orr r12, r12, lr, lsl #8
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemmove_fsrcul3loop4
+
+.Lmemmove_fsrcul3l4:
+ sub r1, r1, #1
+ b .Lmemmove_fl4
+
+.Lmemmove_backwards:
+ add r1, r1, r2
+ add r0, r0, r2
+ subs r2, r2, #4
+ blt .Lmemmove_bl4 /* less than 4 bytes */
+ ands r12, r0, #3
+ bne .Lmemmove_bdestul /* oh unaligned destination addr */
+ ands r12, r1, #3
+ bne .Lmemmove_bsrcul /* oh unaligned source addr */
+
+.Lmemmove_bt8:
+ /* We have aligned source and destination */
+ subs r2, r2, #8
+ blt .Lmemmove_bl12 /* less than 12 bytes (4 from above) */
+ stmdb sp!, {r4, lr}
+ subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */
+ blt .Lmemmove_bl32
+
+ /* blat 32 bytes at a time */
+ /* XXX for really big copies perhaps we should use more registers */
+.Lmemmove_bloop32:
+ ldmdb r1!, {r3, r4, r12, lr}
+ stmdb r0!, {r3, r4, r12, lr}
+ ldmdb r1!, {r3, r4, r12, lr}
+ stmdb r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge .Lmemmove_bloop32
+
+.Lmemmove_bl32:
+ cmn r2, #0x10
+ ldmdbge r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+ stmdbge r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ adds r2, r2, #0x14
+ ldmdbge r1!, {r3, r12, lr} /* blat a remaining 12 bytes */
+ stmdbge r0!, {r3, r12, lr}
+ subge r2, r2, #0x0c
+ ldmia sp!, {r4, lr}
+
+.Lmemmove_bl12:
+ adds r2, r2, #8
+ blt .Lmemmove_bl4
+ subs r2, r2, #4
+ ldrlt r3, [r1, #-4]!
+ strlt r3, [r0, #-4]!
+ ldmdbge r1!, {r3, r12}
+ stmdbge r0!, {r3, r12}
+ subge r2, r2, #4
+
+.Lmemmove_bl4:
+ /* less than 4 bytes to go */
+ adds r2, r2, #4
+ RETeq /* done */
+
+ /* copy the crud byte at a time */
+ cmp r2, #2
+ ldrb r3, [r1, #-1]!
+ strb r3, [r0, #-1]!
+ ldrbge r3, [r1, #-1]!
+ strbge r3, [r0, #-1]!
+ ldrbgt r3, [r1, #-1]!
+ strbgt r3, [r0, #-1]!
+ RET
+
+ /* erg - unaligned destination */
+.Lmemmove_bdestul:
+ cmp r12, #2
+
+ /* align destination with byte copies */
+ ldrb r3, [r1, #-1]!
+ strb r3, [r0, #-1]!
+ ldrbge r3, [r1, #-1]!
+ strbge r3, [r0, #-1]!
+ ldrbgt r3, [r1, #-1]!
+ strbgt r3, [r0, #-1]!
+ subs r2, r2, r12
+ blt .Lmemmove_bl4 /* less than 4 bytes to go */
+ ands r12, r1, #3
+ beq .Lmemmove_bt8 /* we have an aligned source */
+
+ /* erg - unaligned source */
+ /* This is where it gets nasty ... */
+.Lmemmove_bsrcul:
+ bic r1, r1, #3
+ ldr r3, [r1, #0]
+ cmp r12, #2
+ blt .Lmemmove_bsrcul1
+ beq .Lmemmove_bsrcul2
+ cmp r2, #0x0c
+ blt .Lmemmove_bsrcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+.Lmemmove_bsrcul3loop16:
+#ifdef __ARMEB__
+ mov lr, r3, lsr #8
+#else
+ mov lr, r3, lsl #8
+#endif
+ ldmdb r1!, {r3-r5, r12}
+#ifdef __ARMEB__
+ orr lr, lr, r12, lsl #24
+ mov r12, r12, lsr #8
+ orr r12, r12, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r3, lsl #24
+#else
+ orr lr, lr, r12, lsr #24
+ mov r12, r12, lsl #8
+ orr r12, r12, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r4, lsr #24
+ mov r4, r4, lsl #8
+ orr r4, r4, r3, lsr #24
+#endif
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge .Lmemmove_bsrcul3loop16
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_bsrcul3l4
+
+.Lmemmove_bsrcul3loop4:
+#ifdef __ARMEB__
+ mov r12, r3, lsr #8
+#else
+ mov r12, r3, lsl #8
+#endif
+ ldr r3, [r1, #-4]!
+#ifdef __ARMEB__
+ orr r12, r12, r3, lsl #24
+#else
+ orr r12, r12, r3, lsr #24
+#endif
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge .Lmemmove_bsrcul3loop4
+
+.Lmemmove_bsrcul3l4:
+ add r1, r1, #3
+ b .Lmemmove_bl4
+
+.Lmemmove_bsrcul2:
+ cmp r2, #0x0c
+ blt .Lmemmove_bsrcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+.Lmemmove_bsrcul2loop16:
+#ifdef __ARMEB__
+ mov lr, r3, lsr #16
+#else
+ mov lr, r3, lsl #16
+#endif
+ ldmdb r1!, {r3-r5, r12}
+#ifdef __ARMEB__
+ orr lr, lr, r12, lsl #16
+ mov r12, r12, lsr #16
+ orr r12, r12, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r3, lsl #16
+#else
+ orr lr, lr, r12, lsr #16
+ mov r12, r12, lsl #16
+ orr r12, r12, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r4, lsr #16
+ mov r4, r4, lsl #16
+ orr r4, r4, r3, lsr #16
+#endif
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge .Lmemmove_bsrcul2loop16
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_bsrcul2l4
+
+.Lmemmove_bsrcul2loop4:
+#ifdef __ARMEB__
+ mov r12, r3, lsr #16
+#else
+ mov r12, r3, lsl #16
+#endif
+ ldr r3, [r1, #-4]!
+#ifdef __ARMEB__
+ orr r12, r12, r3, lsl #16
+#else
+ orr r12, r12, r3, lsr #16
+#endif
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge .Lmemmove_bsrcul2loop4
+
+.Lmemmove_bsrcul2l4:
+ add r1, r1, #2
+ b .Lmemmove_bl4
+
+.Lmemmove_bsrcul1:
+ cmp r2, #0x0c
+ blt .Lmemmove_bsrcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+.Lmemmove_bsrcul1loop32:
+#ifdef __ARMEB__
+ mov lr, r3, lsr #24
+#else
+ mov lr, r3, lsl #24
+#endif
+ ldmdb r1!, {r3-r5, r12}
+#ifdef __ARMEB__
+ orr lr, lr, r12, lsl #8
+ mov r12, r12, lsr #24
+ orr r12, r12, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r3, lsl #8
+#else
+ orr lr, lr, r12, lsr #8
+ mov r12, r12, lsl #24
+ orr r12, r12, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r4, lsr #8
+ mov r4, r4, lsl #24
+ orr r4, r4, r3, lsr #8
+#endif
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge .Lmemmove_bsrcul1loop32
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_bsrcul1l4
+
+.Lmemmove_bsrcul1loop4:
+#ifdef __ARMEB__
+ mov r12, r3, lsr #24
+#else
+ mov r12, r3, lsl #24
+#endif
+ ldr r3, [r1, #-4]!
+#ifdef __ARMEB__
+ orr r12, r12, r3, lsl #8
+#else
+ orr r12, r12, r3, lsr #8
+#endif
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge .Lmemmove_bsrcul1loop4
+
+.Lmemmove_bsrcul1l4:
+ add r1, r1, #1
+ b .Lmemmove_bl4
+EEND(memmove)
+END(bcopy)
+
+#if !defined(_ARM_ARCH_5E)
+ENTRY(memcpy)
+ /* save leaf functions having to store this away */
+ /* Do not check arm_memcpy if we're running from flash */
+#if defined(FLASHADDR) && defined(PHYSADDR)
+#if FLASHADDR > PHYSADDR
+ ldr r3, =FLASHADDR
+ cmp r3, pc
+ bls .Lnormal
+#else
+ ldr r3, =FLASHADDR
+ cmp r3, pc
+ bhi .Lnormal
+#endif
+#endif
+ ldr r3, .L_arm_memcpy
+ ldr r3, [r3]
+ cmp r3, #0
+ beq .Lnormal
+ ldr r3, .L_min_memcpy_size
+ ldr r3, [r3]
+ cmp r2, r3
+ blt .Lnormal
+ stmfd sp!, {r0-r2, r4, lr}
+ mov r3, #0
+ ldr r4, .L_arm_memcpy
+ mov lr, pc
+ ldr pc, [r4]
+ cmp r0, #0
+ ldmfd sp!, {r0-r2, r4, lr}
+ RETeq
+
+.Lnormal:
+ stmdb sp!, {r0, lr} /* memcpy() returns dest addr */
+
+ subs r2, r2, #4
+ blt .Lmemcpy_l4 /* less than 4 bytes */
+ ands r12, r0, #3
+ bne .Lmemcpy_destul /* oh unaligned destination addr */
+ ands r12, r1, #3
+ bne .Lmemcpy_srcul /* oh unaligned source addr */
+
+.Lmemcpy_t8:
+ /* We have aligned source and destination */
+ subs r2, r2, #8
+ blt .Lmemcpy_l12 /* less than 12 bytes (4 from above) */
+ subs r2, r2, #0x14
+ blt .Lmemcpy_l32 /* less than 32 bytes (12 from above) */
+ stmdb sp!, {r4} /* borrow r4 */
+
+ /* blat 32 bytes at a time */
+ /* XXX for really big copies perhaps we should use more registers */
+.Lmemcpy_loop32:
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge .Lmemcpy_loop32
+
+ cmn r2, #0x10
+ ldmiage r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+ stmiage r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ ldmia sp!, {r4} /* return r4 */
+
+.Lmemcpy_l32:
+ adds r2, r2, #0x14
+
+ /* blat 12 bytes at a time */
+.Lmemcpy_loop12:
+ ldmiage r1!, {r3, r12, lr}
+ stmiage r0!, {r3, r12, lr}
+ subsge r2, r2, #0x0c
+ bge .Lmemcpy_loop12
+
+.Lmemcpy_l12:
+ adds r2, r2, #8
+ blt .Lmemcpy_l4
+
+ subs r2, r2, #4
+ ldrlt r3, [r1], #4
+ strlt r3, [r0], #4
+ ldmiage r1!, {r3, r12}
+ stmiage r0!, {r3, r12}
+ subge r2, r2, #4
+
+.Lmemcpy_l4:
+ /* less than 4 bytes to go */
+ adds r2, r2, #4
+#ifdef __APCS_26_
+ ldmiaeq sp!, {r0, pc}^ /* done */
+#else
+ ldmiaeq sp!, {r0, pc} /* done */
+#endif
+ /* copy the crud byte at a time */
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrbge r3, [r1], #1
+ strbge r3, [r0], #1
+ ldrbgt r3, [r1], #1
+ strbgt r3, [r0], #1
+ ldmia sp!, {r0, pc}
+
+ /* erg - unaligned destination */
+.Lmemcpy_destul:
+ rsb r12, r12, #4
+ cmp r12, #2
+
+ /* align destination with byte copies */
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrbge r3, [r1], #1
+ strbge r3, [r0], #1
+ ldrbgt r3, [r1], #1
+ strbgt r3, [r0], #1
+ subs r2, r2, r12
+ blt .Lmemcpy_l4 /* less the 4 bytes */
+
+ ands r12, r1, #3
+ beq .Lmemcpy_t8 /* we have an aligned source */
+
+ /* erg - unaligned source */
+ /* This is where it gets nasty ... */
+.Lmemcpy_srcul:
+ bic r1, r1, #3
+ ldr lr, [r1], #4
+ cmp r12, #2
+ bgt .Lmemcpy_srcul3
+ beq .Lmemcpy_srcul2
+ cmp r2, #0x0c
+ blt .Lmemcpy_srcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemcpy_srcul1loop16:
+ mov r3, lr, lsr #8
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r12, lsl #24
+ mov r12, r12, lsr #8
+ orr r12, r12, lr, lsl #24
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemcpy_srcul1loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemcpy_srcul1l4
+
+.Lmemcpy_srcul1loop4:
+ mov r12, lr, lsr #8
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #24
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemcpy_srcul1loop4
+
+.Lmemcpy_srcul1l4:
+ sub r1, r1, #3
+ b .Lmemcpy_l4
+
+.Lmemcpy_srcul2:
+ cmp r2, #0x0c
+ blt .Lmemcpy_srcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemcpy_srcul2loop16:
+ mov r3, lr, lsr #16
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r12, lsl #16
+ mov r12, r12, lsr #16
+ orr r12, r12, lr, lsl #16
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemcpy_srcul2loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemcpy_srcul2l4
+
+.Lmemcpy_srcul2loop4:
+ mov r12, lr, lsr #16
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #16
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemcpy_srcul2loop4
+
+.Lmemcpy_srcul2l4:
+ sub r1, r1, #2
+ b .Lmemcpy_l4
+
+.Lmemcpy_srcul3:
+ cmp r2, #0x0c
+ blt .Lmemcpy_srcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemcpy_srcul3loop16:
+ mov r3, lr, lsr #24
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r12, lsl #8
+ mov r12, r12, lsr #24
+ orr r12, r12, lr, lsl #8
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemcpy_srcul3loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemcpy_srcul3l4
+
+.Lmemcpy_srcul3loop4:
+ mov r12, lr, lsr #24
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #8
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemcpy_srcul3loop4
+
+.Lmemcpy_srcul3l4:
+ sub r1, r1, #1
+ b .Lmemcpy_l4
+END(memcpy)
+
+#else
+/* LINTSTUB: Func: void *memcpy(void *dst, const void *src, size_t len) */
+ENTRY(memcpy)
+ pld [r1]
+ cmp r2, #0x0c
+ ble .Lmemcpy_short /* <= 12 bytes */
+#ifdef FLASHADDR
+#if FLASHADDR > PHYSADDR
+ ldr r3, =FLASHADDR
+ cmp r3, pc
+ bls .Lnormal
+#else
+ ldr r3, =FLASHADDR
+ cmp r3, pc
+ bhi .Lnormal
+#endif
+#endif
+ ldr r3, .L_arm_memcpy
+ ldr r3, [r3]
+ cmp r3, #0
+ beq .Lnormal
+ ldr r3, .L_min_memcpy_size
+ ldr r3, [r3]
+ cmp r2, r3
+ blt .Lnormal
+ stmfd sp!, {r0-r2, r4, lr}
+ mov r3, #0
+ ldr r4, .L_arm_memcpy
+ mov lr, pc
+ ldr pc, [r4]
+ cmp r0, #0
+ ldmfd sp!, {r0-r2, r4, lr}
+ RETeq
+.Lnormal:
+ mov r3, r0 /* We must not clobber r0 */
+
+ /* Word-align the destination buffer */
+ ands ip, r3, #0x03 /* Already word aligned? */
+ beq .Lmemcpy_wordaligned /* Yup */
+ cmp ip, #0x02
+ ldrb ip, [r1], #0x01
+ sub r2, r2, #0x01
+ strb ip, [r3], #0x01
+ ldrble ip, [r1], #0x01
+ suble r2, r2, #0x01
+ strble ip, [r3], #0x01
+ ldrblt ip, [r1], #0x01
+ sublt r2, r2, #0x01
+ strblt ip, [r3], #0x01
+
+ /* Destination buffer is now word aligned */
+.Lmemcpy_wordaligned:
+ ands ip, r1, #0x03 /* Is src also word-aligned? */
+ bne .Lmemcpy_bad_align /* Nope. Things just got bad */
+
+ /* Quad-align the destination buffer */
+ tst r3, #0x07 /* Already quad aligned? */
+ ldrne ip, [r1], #0x04
+ stmfd sp!, {r4-r9} /* Free up some registers */
+ subne r2, r2, #0x04
+ strne ip, [r3], #0x04
+
+ /* Destination buffer quad aligned, source is at least word aligned */
+ subs r2, r2, #0x80
+ blt .Lmemcpy_w_lessthan128
+
+ /* Copy 128 bytes at a time */
+.Lmemcpy_w_loop128:
+ ldr r4, [r1], #0x04 /* LD:00-03 */
+ ldr r5, [r1], #0x04 /* LD:04-07 */
+ pld [r1, #0x18] /* Prefetch 0x20 */
+ ldr r6, [r1], #0x04 /* LD:08-0b */
+ ldr r7, [r1], #0x04 /* LD:0c-0f */
+ ldr r8, [r1], #0x04 /* LD:10-13 */
+ ldr r9, [r1], #0x04 /* LD:14-17 */
+ strd r4, [r3], #0x08 /* ST:00-07 */
+ ldr r4, [r1], #0x04 /* LD:18-1b */
+ ldr r5, [r1], #0x04 /* LD:1c-1f */
+ strd r6, [r3], #0x08 /* ST:08-0f */
+ ldr r6, [r1], #0x04 /* LD:20-23 */
+ ldr r7, [r1], #0x04 /* LD:24-27 */
+ pld [r1, #0x18] /* Prefetch 0x40 */
+ strd r8, [r3], #0x08 /* ST:10-17 */
+ ldr r8, [r1], #0x04 /* LD:28-2b */
+ ldr r9, [r1], #0x04 /* LD:2c-2f */
+ strd r4, [r3], #0x08 /* ST:18-1f */
+ ldr r4, [r1], #0x04 /* LD:30-33 */
+ ldr r5, [r1], #0x04 /* LD:34-37 */
+ strd r6, [r3], #0x08 /* ST:20-27 */
+ ldr r6, [r1], #0x04 /* LD:38-3b */
+ ldr r7, [r1], #0x04 /* LD:3c-3f */
+ strd r8, [r3], #0x08 /* ST:28-2f */
+ ldr r8, [r1], #0x04 /* LD:40-43 */
+ ldr r9, [r1], #0x04 /* LD:44-47 */
+ pld [r1, #0x18] /* Prefetch 0x60 */
+ strd r4, [r3], #0x08 /* ST:30-37 */
+ ldr r4, [r1], #0x04 /* LD:48-4b */
+ ldr r5, [r1], #0x04 /* LD:4c-4f */
+ strd r6, [r3], #0x08 /* ST:38-3f */
+ ldr r6, [r1], #0x04 /* LD:50-53 */
+ ldr r7, [r1], #0x04 /* LD:54-57 */
+ strd r8, [r3], #0x08 /* ST:40-47 */
+ ldr r8, [r1], #0x04 /* LD:58-5b */
+ ldr r9, [r1], #0x04 /* LD:5c-5f */
+ strd r4, [r3], #0x08 /* ST:48-4f */
+ ldr r4, [r1], #0x04 /* LD:60-63 */
+ ldr r5, [r1], #0x04 /* LD:64-67 */
+ pld [r1, #0x18] /* Prefetch 0x80 */
+ strd r6, [r3], #0x08 /* ST:50-57 */
+ ldr r6, [r1], #0x04 /* LD:68-6b */
+ ldr r7, [r1], #0x04 /* LD:6c-6f */
+ strd r8, [r3], #0x08 /* ST:58-5f */
+ ldr r8, [r1], #0x04 /* LD:70-73 */
+ ldr r9, [r1], #0x04 /* LD:74-77 */
+ strd r4, [r3], #0x08 /* ST:60-67 */
+ ldr r4, [r1], #0x04 /* LD:78-7b */
+ ldr r5, [r1], #0x04 /* LD:7c-7f */
+ strd r6, [r3], #0x08 /* ST:68-6f */
+ strd r8, [r3], #0x08 /* ST:70-77 */
+ subs r2, r2, #0x80
+ strd r4, [r3], #0x08 /* ST:78-7f */
+ bge .Lmemcpy_w_loop128
+
+.Lmemcpy_w_lessthan128:
+ adds r2, r2, #0x80 /* Adjust for extra sub */
+ ldmfdeq sp!, {r4-r9}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x20
+ blt .Lmemcpy_w_lessthan32
+
+ /* Copy 32 bytes at a time */
+.Lmemcpy_w_loop32:
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ pld [r1, #0x18]
+ ldr r6, [r1], #0x04
+ ldr r7, [r1], #0x04
+ ldr r8, [r1], #0x04
+ ldr r9, [r1], #0x04
+ strd r4, [r3], #0x08
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ strd r6, [r3], #0x08
+ strd r8, [r3], #0x08
+ subs r2, r2, #0x20
+ strd r4, [r3], #0x08
+ bge .Lmemcpy_w_loop32
+
+.Lmemcpy_w_lessthan32:
+ adds r2, r2, #0x20 /* Adjust for extra sub */
+ ldmfdeq sp!, {r4-r9}
+ RETeq /* Return now if done */
+
+ and r4, r2, #0x18
+ rsbs r4, r4, #0x18
+ addne pc, pc, r4, lsl #1
+ nop
+
+ /* At least 24 bytes remaining */
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ sub r2, r2, #0x08
+ strd r4, [r3], #0x08
+
+ /* At least 16 bytes remaining */
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ sub r2, r2, #0x08
+ strd r4, [r3], #0x08
+
+ /* At least 8 bytes remaining */
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ subs r2, r2, #0x08
+ strd r4, [r3], #0x08
+
+ /* Less than 8 bytes remaining */
+ ldmfd sp!, {r4-r9}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ ldrge ip, [r1], #0x04
+ strge ip, [r3], #0x04
+ RETeq /* Return now if done */
+ addlt r2, r2, #0x04
+ ldrb ip, [r1], #0x01
+ cmp r2, #0x02
+ ldrbge r2, [r1], #0x01
+ strb ip, [r3], #0x01
+ ldrbgt ip, [r1]
+ strbge r2, [r3], #0x01
+ strbgt ip, [r3]
+ RET
+/* Place a literal pool here for the above ldr instructions to use */
+.ltorg
+
+
+/*
+ * At this point, it has not been possible to word align both buffers.
+ * The destination buffer is word aligned, but the source buffer is not.
+ */
+.Lmemcpy_bad_align:
+ stmfd sp!, {r4-r7}
+ bic r1, r1, #0x03
+ cmp ip, #2
+ ldr ip, [r1], #0x04
+ bgt .Lmemcpy_bad3
+ beq .Lmemcpy_bad2
+ b .Lmemcpy_bad1
+
+.Lmemcpy_bad1_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #8
+#else
+ mov r4, ip, lsr #8
+#endif
+ ldr r5, [r1], #0x04
+ pld [r1, #0x018]
+ ldr r6, [r1], #0x04
+ ldr r7, [r1], #0x04
+ ldr ip, [r1], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r6, lsr #24
+ mov r6, r6, lsl #8
+ orr r6, r6, r7, lsr #24
+ mov r7, r7, lsl #8
+ orr r7, r7, ip, lsr #24
+#else
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ mov r6, r6, lsr #8
+ orr r6, r6, r7, lsl #24
+ mov r7, r7, lsr #8
+ orr r7, r7, ip, lsl #24
+#endif
+ str r4, [r3], #0x04
+ str r5, [r3], #0x04
+ str r6, [r3], #0x04
+ str r7, [r3], #0x04
+.Lmemcpy_bad1:
+ subs r2, r2, #0x10
+ bge .Lmemcpy_bad1_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r1, r1, #0x03
+ blt .Lmemcpy_bad_done
+
+.Lmemcpy_bad1_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #8
+#else
+ mov r4, ip, lsr #8
+#endif
+ ldr ip, [r1], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #24
+#else
+ orr r4, r4, ip, lsl #24
+#endif
+ str r4, [r3], #0x04
+ bge .Lmemcpy_bad1_loop4
+ sub r1, r1, #0x03
+ b .Lmemcpy_bad_done
+
+.Lmemcpy_bad2_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #16
+#else
+ mov r4, ip, lsr #16
+#endif
+ ldr r5, [r1], #0x04
+ pld [r1, #0x018]
+ ldr r6, [r1], #0x04
+ ldr r7, [r1], #0x04
+ ldr ip, [r1], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r6, lsr #16
+ mov r6, r6, lsl #16
+ orr r6, r6, r7, lsr #16
+ mov r7, r7, lsl #16
+ orr r7, r7, ip, lsr #16
+#else
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ mov r6, r6, lsr #16
+ orr r6, r6, r7, lsl #16
+ mov r7, r7, lsr #16
+ orr r7, r7, ip, lsl #16
+#endif
+ str r4, [r3], #0x04
+ str r5, [r3], #0x04
+ str r6, [r3], #0x04
+ str r7, [r3], #0x04
+.Lmemcpy_bad2:
+ subs r2, r2, #0x10
+ bge .Lmemcpy_bad2_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r1, r1, #0x02
+ blt .Lmemcpy_bad_done
+
+.Lmemcpy_bad2_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #16
+#else
+ mov r4, ip, lsr #16
+#endif
+ ldr ip, [r1], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #16
+#else
+ orr r4, r4, ip, lsl #16
+#endif
+ str r4, [r3], #0x04
+ bge .Lmemcpy_bad2_loop4
+ sub r1, r1, #0x02
+ b .Lmemcpy_bad_done
+
+.Lmemcpy_bad3_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #24
+#else
+ mov r4, ip, lsr #24
+#endif
+ ldr r5, [r1], #0x04
+ pld [r1, #0x018]
+ ldr r6, [r1], #0x04
+ ldr r7, [r1], #0x04
+ ldr ip, [r1], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r6, lsr #8
+ mov r6, r6, lsl #24
+ orr r6, r6, r7, lsr #8
+ mov r7, r7, lsl #24
+ orr r7, r7, ip, lsr #8
+#else
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ mov r6, r6, lsr #24
+ orr r6, r6, r7, lsl #8
+ mov r7, r7, lsr #24
+ orr r7, r7, ip, lsl #8
+#endif
+ str r4, [r3], #0x04
+ str r5, [r3], #0x04
+ str r6, [r3], #0x04
+ str r7, [r3], #0x04
+.Lmemcpy_bad3:
+ subs r2, r2, #0x10
+ bge .Lmemcpy_bad3_loop16
+
+ adds r2, r2, #0x10
+ ldmfdeq sp!, {r4-r7}
+ RETeq /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r1, r1, #0x01
+ blt .Lmemcpy_bad_done
+
+.Lmemcpy_bad3_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #24
+#else
+ mov r4, ip, lsr #24
+#endif
+ ldr ip, [r1], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #8
+#else
+ orr r4, r4, ip, lsl #8
+#endif
+ str r4, [r3], #0x04
+ bge .Lmemcpy_bad3_loop4
+ sub r1, r1, #0x01
+
+.Lmemcpy_bad_done:
+ ldmfd sp!, {r4-r7}
+ adds r2, r2, #0x04
+ RETeq
+ ldrb ip, [r1], #0x01
+ cmp r2, #0x02
+ ldrbge r2, [r1], #0x01
+ strb ip, [r3], #0x01
+ ldrbgt ip, [r1]
+ strbge r2, [r3], #0x01
+ strbgt ip, [r3]
+ RET
+
+
+/*
+ * Handle short copies (less than 16 bytes), possibly misaligned.
+ * Some of these are *very* common, thanks to the network stack,
+ * and so are handled specially.
+ */
+.Lmemcpy_short:
+ add pc, pc, r2, lsl #2
+ nop
+ RET /* 0x00 */
+ b .Lmemcpy_bytewise /* 0x01 */
+ b .Lmemcpy_bytewise /* 0x02 */
+ b .Lmemcpy_bytewise /* 0x03 */
+ b .Lmemcpy_4 /* 0x04 */
+ b .Lmemcpy_bytewise /* 0x05 */
+ b .Lmemcpy_6 /* 0x06 */
+ b .Lmemcpy_bytewise /* 0x07 */
+ b .Lmemcpy_8 /* 0x08 */
+ b .Lmemcpy_bytewise /* 0x09 */
+ b .Lmemcpy_bytewise /* 0x0a */
+ b .Lmemcpy_bytewise /* 0x0b */
+ b .Lmemcpy_c /* 0x0c */
+.Lmemcpy_bytewise:
+ mov r3, r0 /* We must not clobber r0 */
+ ldrb ip, [r1], #0x01
+1: subs r2, r2, #0x01
+ strb ip, [r3], #0x01
+ ldrbne ip, [r1], #0x01
+ bne 1b
+ RET
+
+/******************************************************************************
+ * Special case for 4 byte copies
+ */
+#define LMEMCPY_4_LOG2 6 /* 64 bytes */
+#define LMEMCPY_4_PAD .align LMEMCPY_4_LOG2
+ LMEMCPY_4_PAD
+.Lmemcpy_4:
+ and r2, r1, #0x03
+ orr r2, r2, r0, lsl #2
+ ands r2, r2, #0x0f
+ sub r3, pc, #0x14
+ addne pc, r3, r2, lsl #LMEMCPY_4_LOG2
+
+/*
+ * 0000: dst is 32-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+ str r2, [r0]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 0001: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */
+ ldr r2, [r1, #3] /* BE:r2 = 3xxx LE:r2 = xxx3 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #8 /* r3 = 012. */
+ orr r3, r3, r2, lsr #24 /* r3 = 0123 */
+#else
+ mov r3, r3, lsr #8 /* r3 = .210 */
+ orr r3, r3, r2, lsl #24 /* r3 = 3210 */
+#endif
+ str r3, [r0]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 0010: dst is 32-bit aligned, src is 16-bit aligned
+ */
+#ifdef __ARMEB__
+ ldrh r3, [r1]
+ ldrh r2, [r1, #0x02]
+#else
+ ldrh r3, [r1, #0x02]
+ ldrh r2, [r1]
+#endif
+ orr r3, r2, r3, lsl #16
+ str r3, [r0]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 0011: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #-3] /* BE:r3 = xxx0 LE:r3 = 0xxx */
+ ldr r2, [r1, #1] /* BE:r2 = 123x LE:r2 = x321 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #24 /* r3 = 0... */
+ orr r3, r3, r2, lsr #8 /* r3 = 0123 */
+#else
+ mov r3, r3, lsr #24 /* r3 = ...0 */
+ orr r3, r3, r2, lsl #8 /* r3 = 3210 */
+#endif
+ str r3, [r0]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 0100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+#ifdef __ARMEB__
+ strb r2, [r0, #0x03]
+ mov r3, r2, lsr #8
+ mov r1, r2, lsr #24
+ strb r1, [r0]
+#else
+ strb r2, [r0]
+ mov r3, r2, lsr #8
+ mov r1, r2, lsr #24
+ strb r1, [r0, #0x03]
+#endif
+ strh r3, [r0, #0x01]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 0101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrb r1, [r1, #0x03]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 0110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldrh r3, [r1, #0x02] /* LE:r3 = ..23 LE:r3 = ..32 */
+#ifdef __ARMEB__
+ mov r1, r2, lsr #8 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r2, r2, lsl #8 /* r2 = .01. */
+ orr r2, r2, r3, lsr #8 /* r2 = .012 */
+#else
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r3, lsl #8 /* r2 = .321 */
+ mov r3, r3, lsr #8 /* r3 = ...3 */
+#endif
+ strh r2, [r0, #0x01]
+ strb r3, [r0, #0x03]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 0111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrb r1, [r1, #0x03]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 1000: dst is 16-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+#ifdef __ARMEB__
+ strh r2, [r0, #0x02]
+ mov r3, r2, lsr #16
+ strh r3, [r0]
+#else
+ strh r2, [r0]
+ mov r3, r2, lsr #16
+ strh r3, [r0, #0x02]
+#endif
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 1001: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */
+ ldr r3, [r1, #3] /* BE:r3 = 3xxx LE:r3 = xxx3 */
+ mov r1, r2, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */
+ strh r1, [r0]
+#ifdef __ARMEB__
+ mov r2, r2, lsl #8 /* r2 = 012. */
+ orr r2, r2, r3, lsr #24 /* r2 = 0123 */
+#else
+ mov r2, r2, lsr #24 /* r2 = ...2 */
+ orr r2, r2, r3, lsl #8 /* r2 = xx32 */
+#endif
+ strh r2, [r0, #0x02]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 1010: dst is 16-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1]
+ ldrh r3, [r1, #0x02]
+ strh r2, [r0]
+ strh r3, [r0, #0x02]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 1011: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #1] /* BE:r3 = 123x LE:r3 = x321 */
+ ldr r2, [r1, #-3] /* BE:r2 = xxx0 LE:r2 = 0xxx */
+ mov r1, r3, lsr #8 /* BE:r1 = .123 LE:r1 = .x32 */
+ strh r1, [r0, #0x02]
+#ifdef __ARMEB__
+ mov r3, r3, lsr #24 /* r3 = ...1 */
+ orr r3, r3, r2, lsl #8 /* r3 = xx01 */
+#else
+ mov r3, r3, lsl #8 /* r3 = 321. */
+ orr r3, r3, r2, lsr #24 /* r3 = 3210 */
+#endif
+ strh r3, [r0]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 1100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+#ifdef __ARMEB__
+ strb r2, [r0, #0x03]
+ mov r3, r2, lsr #8
+ mov r1, r2, lsr #24
+ strh r3, [r0, #0x01]
+ strb r1, [r0]
+#else
+ strb r2, [r0]
+ mov r3, r2, lsr #8
+ mov r1, r2, lsr #24
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+#endif
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 1101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrb r1, [r1, #0x03]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 1110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+#ifdef __ARMEB__
+ ldrh r3, [r1, #0x02] /* BE:r3 = ..23 LE:r3 = ..32 */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ strb r3, [r0, #0x03]
+ mov r3, r3, lsr #8 /* r3 = ...2 */
+ orr r3, r3, r2, lsl #8 /* r3 = ..12 */
+ strh r3, [r0, #0x01]
+ mov r2, r2, lsr #8 /* r2 = ...0 */
+ strb r2, [r0]
+#else
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldrh r3, [r1, #0x02] /* BE:r3 = ..23 LE:r3 = ..32 */
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r3, lsl #8 /* r2 = .321 */
+ strh r2, [r0, #0x01]
+ mov r3, r3, lsr #8 /* r3 = ...3 */
+ strb r3, [r0, #0x03]
+#endif
+ RET
+ LMEMCPY_4_PAD
+
+/*
+ * 1111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrb r1, [r1, #0x03]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+ RET
+ LMEMCPY_4_PAD
+
+
+/******************************************************************************
+ * Special case for 6 byte copies
+ */
+#define LMEMCPY_6_LOG2 6 /* 64 bytes */
+#define LMEMCPY_6_PAD .align LMEMCPY_6_LOG2
+ LMEMCPY_6_PAD
+.Lmemcpy_6:
+ and r2, r1, #0x03
+ orr r2, r2, r0, lsl #2
+ ands r2, r2, #0x0f
+ sub r3, pc, #0x14
+ addne pc, r3, r2, lsl #LMEMCPY_6_LOG2
+
+/*
+ * 0000: dst is 32-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+ ldrh r3, [r1, #0x04]
+ str r2, [r0]
+ strh r3, [r0, #0x04]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 0001: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */
+ ldr r3, [r1, #0x03] /* BE:r3 = 345x LE:r3 = x543 */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #8 /* r2 = 012. */
+ orr r2, r2, r3, lsr #24 /* r2 = 0123 */
+#else
+ mov r2, r2, lsr #8 /* r2 = .210 */
+ orr r2, r2, r3, lsl #24 /* r2 = 3210 */
+#endif
+ mov r3, r3, lsr #8 /* BE:r3 = .345 LE:r3 = .x54 */
+ str r2, [r0]
+ strh r3, [r0, #0x04]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 0010: dst is 32-bit aligned, src is 16-bit aligned
+ */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+#ifdef __ARMEB__
+ mov r1, r3, lsr #16 /* r1 = ..23 */
+ orr r1, r1, r2, lsl #16 /* r1 = 0123 */
+ str r1, [r0]
+ strh r3, [r0, #0x04]
+#else
+ mov r1, r3, lsr #16 /* r1 = ..54 */
+ orr r2, r2, r3, lsl #16 /* r2 = 3210 */
+ str r2, [r0]
+ strh r1, [r0, #0x04]
+#endif
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 0011: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r2, [r1, #-3] /* BE:r2 = xxx0 LE:r2 = 0xxx */
+ ldr r3, [r1, #1] /* BE:r3 = 1234 LE:r3 = 4321 */
+ ldr r1, [r1, #5] /* BE:r1 = 5xxx LE:r3 = xxx5 */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #24 /* r2 = 0... */
+ orr r2, r2, r3, lsr #8 /* r2 = 0123 */
+ mov r3, r3, lsl #8 /* r3 = 234. */
+ orr r1, r3, r1, lsr #24 /* r1 = 2345 */
+#else
+ mov r2, r2, lsr #24 /* r2 = ...0 */
+ orr r2, r2, r3, lsl #8 /* r2 = 3210 */
+ mov r1, r1, lsl #8 /* r1 = xx5. */
+ orr r1, r1, r3, lsr #24 /* r1 = xx54 */
+#endif
+ str r2, [r0]
+ strh r1, [r0, #0x04]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 0100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r3, [r1] /* BE:r3 = 0123 LE:r3 = 3210 */
+ ldrh r2, [r1, #0x04] /* BE:r2 = ..45 LE:r2 = ..54 */
+ mov r1, r3, lsr #8 /* BE:r1 = .012 LE:r1 = .321 */
+ strh r1, [r0, #0x01]
+#ifdef __ARMEB__
+ mov r1, r3, lsr #24 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r3, r3, lsl #8 /* r3 = 123. */
+ orr r3, r3, r2, lsr #8 /* r3 = 1234 */
+#else
+ strb r3, [r0]
+ mov r3, r3, lsr #24 /* r3 = ...3 */
+ orr r3, r3, r2, lsl #8 /* r3 = .543 */
+ mov r2, r2, lsr #8 /* r2 = ...5 */
+#endif
+ strh r3, [r0, #0x03]
+ strb r2, [r0, #0x05]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 0101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrh ip, [r1, #0x03]
+ ldrb r1, [r1, #0x05]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strh ip, [r0, #0x03]
+ strb r1, [r0, #0x05]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 0110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r1, [r1, #0x02] /* BE:r1 = 2345 LE:r1 = 5432 */
+#ifdef __ARMEB__
+ mov r3, r2, lsr #8 /* r3 = ...0 */
+ strb r3, [r0]
+ strb r1, [r0, #0x05]
+ mov r3, r1, lsr #8 /* r3 = .234 */
+ strh r3, [r0, #0x03]
+ mov r3, r2, lsl #8 /* r3 = .01. */
+ orr r3, r3, r1, lsr #24 /* r3 = .012 */
+ strh r3, [r0, #0x01]
+#else
+ strb r2, [r0]
+ mov r3, r1, lsr #24
+ strb r3, [r0, #0x05]
+ mov r3, r1, lsr #8 /* r3 = .543 */
+ strh r3, [r0, #0x03]
+ mov r3, r2, lsr #8 /* r3 = ...1 */
+ orr r3, r3, r1, lsl #8 /* r3 = 4321 */
+ strh r3, [r0, #0x01]
+#endif
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 0111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrh ip, [r1, #0x03]
+ ldrb r1, [r1, #0x05]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strh ip, [r0, #0x03]
+ strb r1, [r0, #0x05]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 1000: dst is 16-bit aligned, src is 32-bit aligned
+ */
+#ifdef __ARMEB__
+ ldr r2, [r1] /* r2 = 0123 */
+ ldrh r3, [r1, #0x04] /* r3 = ..45 */
+ mov r1, r2, lsr #16 /* r1 = ..01 */
+ orr r3, r3, r2, lsl#16 /* r3 = 2345 */
+ strh r1, [r0]
+ str r3, [r0, #0x02]
+#else
+ ldrh r2, [r1, #0x04] /* r2 = ..54 */
+ ldr r3, [r1] /* r3 = 3210 */
+ mov r2, r2, lsl #16 /* r2 = 54.. */
+ orr r2, r2, r3, lsr #16 /* r2 = 5432 */
+ strh r3, [r0]
+ str r2, [r0, #0x02]
+#endif
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 1001: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */
+ ldr r2, [r1, #3] /* BE:r2 = 345x LE:r2 = x543 */
+ mov r1, r3, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */
+#ifdef __ARMEB__
+ mov r2, r2, lsr #8 /* r2 = .345 */
+ orr r2, r2, r3, lsl #24 /* r2 = 2345 */
+#else
+ mov r2, r2, lsl #8 /* r2 = 543. */
+ orr r2, r2, r3, lsr #24 /* r2 = 5432 */
+#endif
+ strh r1, [r0]
+ str r2, [r0, #0x02]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 1010: dst is 16-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1]
+ ldr r3, [r1, #0x02]
+ strh r2, [r0]
+ str r3, [r0, #0x02]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 1011: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldrb r3, [r1] /* r3 = ...0 */
+ ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */
+ ldrb r1, [r1, #0x05] /* r1 = ...5 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #8 /* r3 = ..0. */
+ orr r3, r3, r2, lsr #24 /* r3 = ..01 */
+ orr r1, r1, r2, lsl #8 /* r1 = 2345 */
+#else
+ orr r3, r3, r2, lsl #8 /* r3 = 3210 */
+ mov r1, r1, lsl #24 /* r1 = 5... */
+ orr r1, r1, r2, lsr #8 /* r1 = 5432 */
+#endif
+ strh r3, [r0]
+ str r1, [r0, #0x02]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 1100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ ldrh r1, [r1, #0x04] /* BE:r1 = ..45 LE:r1 = ..54 */
+#ifdef __ARMEB__
+ mov r3, r2, lsr #24 /* r3 = ...0 */
+ strb r3, [r0]
+ mov r2, r2, lsl #8 /* r2 = 123. */
+ orr r2, r2, r1, lsr #8 /* r2 = 1234 */
+#else
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = .321 */
+ orr r2, r2, r1, lsl #24 /* r2 = 4321 */
+ mov r1, r1, lsr #8 /* r1 = ...5 */
+#endif
+ str r2, [r0, #0x01]
+ strb r1, [r0, #0x05]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 1101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrh ip, [r1, #0x03]
+ ldrb r1, [r1, #0x05]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strh ip, [r0, #0x03]
+ strb r1, [r0, #0x05]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 1110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r1, [r1, #0x02] /* BE:r1 = 2345 LE:r1 = 5432 */
+#ifdef __ARMEB__
+ mov r3, r2, lsr #8 /* r3 = ...0 */
+ strb r3, [r0]
+ mov r2, r2, lsl #24 /* r2 = 1... */
+ orr r2, r2, r1, lsr #8 /* r2 = 1234 */
+#else
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r1, lsl #8 /* r2 = 4321 */
+ mov r1, r1, lsr #24 /* r1 = ...5 */
+#endif
+ str r2, [r0, #0x01]
+ strb r1, [r0, #0x05]
+ RET
+ LMEMCPY_6_PAD
+
+/*
+ * 1111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldr r3, [r1, #0x01]
+ ldrb r1, [r1, #0x05]
+ strb r2, [r0]
+ str r3, [r0, #0x01]
+ strb r1, [r0, #0x05]
+ RET
+ LMEMCPY_6_PAD
+
+
+/******************************************************************************
+ * Special case for 8 byte copies
+ */
+#define LMEMCPY_8_LOG2 6 /* 64 bytes */
+#define LMEMCPY_8_PAD .align LMEMCPY_8_LOG2
+ LMEMCPY_8_PAD
+.Lmemcpy_8:
+ and r2, r1, #0x03
+ orr r2, r2, r0, lsl #2
+ ands r2, r2, #0x0f
+ sub r3, pc, #0x14
+ addne pc, r3, r2, lsl #LMEMCPY_8_LOG2
+
+/*
+ * 0000: dst is 32-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+ ldr r3, [r1, #0x04]
+ str r2, [r0]
+ str r3, [r0, #0x04]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 0001: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */
+ ldr r2, [r1, #0x03] /* BE:r2 = 3456 LE:r2 = 6543 */
+ ldrb r1, [r1, #0x07] /* r1 = ...7 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #8 /* r3 = 012. */
+ orr r3, r3, r2, lsr #24 /* r3 = 0123 */
+ orr r2, r1, r2, lsl #8 /* r2 = 4567 */
+#else
+ mov r3, r3, lsr #8 /* r3 = .210 */
+ orr r3, r3, r2, lsl #24 /* r3 = 3210 */
+ mov r1, r1, lsl #24 /* r1 = 7... */
+ orr r2, r1, r2, lsr #8 /* r2 = 7654 */
+#endif
+ str r3, [r0]
+ str r2, [r0, #0x04]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 0010: dst is 32-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #16 /* r2 = 01.. */
+ orr r2, r2, r3, lsr #16 /* r2 = 0123 */
+ orr r3, r1, r3, lsl #16 /* r3 = 4567 */
+#else
+ orr r2, r2, r3, lsl #16 /* r2 = 3210 */
+ mov r3, r3, lsr #16 /* r3 = ..54 */
+ orr r3, r3, r1, lsl #16 /* r3 = 7654 */
+#endif
+ str r2, [r0]
+ str r3, [r0, #0x04]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 0011: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldrb r3, [r1] /* r3 = ...0 */
+ ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */
+ ldr r1, [r1, #0x05] /* BE:r1 = 567x LE:r1 = x765 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #24 /* r3 = 0... */
+ orr r3, r3, r2, lsr #8 /* r3 = 0123 */
+ mov r2, r2, lsl #24 /* r2 = 4... */
+ orr r2, r2, r1, lsr #8 /* r2 = 4567 */
+#else
+ orr r3, r3, r2, lsl #8 /* r3 = 3210 */
+ mov r2, r2, lsr #24 /* r2 = ...4 */
+ orr r2, r2, r1, lsl #8 /* r2 = 7654 */
+#endif
+ str r3, [r0]
+ str r2, [r0, #0x04]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 0100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r3, [r1] /* BE:r3 = 0123 LE:r3 = 3210 */
+ ldr r2, [r1, #0x04] /* BE:r2 = 4567 LE:r2 = 7654 */
+#ifdef __ARMEB__
+ mov r1, r3, lsr #24 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r1, r3, lsr #8 /* r1 = .012 */
+ strb r2, [r0, #0x07]
+ mov r3, r3, lsl #24 /* r3 = 3... */
+ orr r3, r3, r2, lsr #8 /* r3 = 3456 */
+#else
+ strb r3, [r0]
+ mov r1, r2, lsr #24 /* r1 = ...7 */
+ strb r1, [r0, #0x07]
+ mov r1, r3, lsr #8 /* r1 = .321 */
+ mov r3, r3, lsr #24 /* r3 = ...3 */
+ orr r3, r3, r2, lsl #8 /* r3 = 6543 */
+#endif
+ strh r1, [r0, #0x01]
+ str r3, [r0, #0x03]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 0101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldr ip, [r1, #0x03]
+ ldrb r1, [r1, #0x07]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ str ip, [r0, #0x03]
+ strb r1, [r0, #0x07]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 0110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */
+#ifdef __ARMEB__
+ mov ip, r2, lsr #8 /* ip = ...0 */
+ strb ip, [r0]
+ mov ip, r2, lsl #8 /* ip = .01. */
+ orr ip, ip, r3, lsr #24 /* ip = .012 */
+ strb r1, [r0, #0x07]
+ mov r3, r3, lsl #8 /* r3 = 345. */
+ orr r3, r3, r1, lsr #8 /* r3 = 3456 */
+#else
+ strb r2, [r0] /* 0 */
+ mov ip, r1, lsr #8 /* ip = ...7 */
+ strb ip, [r0, #0x07] /* 7 */
+ mov ip, r2, lsr #8 /* ip = ...1 */
+ orr ip, ip, r3, lsl #8 /* ip = 4321 */
+ mov r3, r3, lsr #8 /* r3 = .543 */
+ orr r3, r3, r1, lsl #24 /* r3 = 6543 */
+#endif
+ strh ip, [r0, #0x01]
+ str r3, [r0, #0x03]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 0111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r3, [r1] /* r3 = ...0 */
+ ldr ip, [r1, #0x01] /* BE:ip = 1234 LE:ip = 4321 */
+ ldrh r2, [r1, #0x05] /* BE:r2 = ..56 LE:r2 = ..65 */
+ ldrb r1, [r1, #0x07] /* r1 = ...7 */
+ strb r3, [r0]
+ mov r3, ip, lsr #16 /* BE:r3 = ..12 LE:r3 = ..43 */
+#ifdef __ARMEB__
+ strh r3, [r0, #0x01]
+ orr r2, r2, ip, lsl #16 /* r2 = 3456 */
+#else
+ strh ip, [r0, #0x01]
+ orr r2, r3, r2, lsl #16 /* r2 = 6543 */
+#endif
+ str r2, [r0, #0x03]
+ strb r1, [r0, #0x07]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 1000: dst is 16-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */
+ mov r1, r2, lsr #16 /* BE:r1 = ..01 LE:r1 = ..32 */
+#ifdef __ARMEB__
+ strh r1, [r0]
+ mov r1, r3, lsr #16 /* r1 = ..45 */
+ orr r2, r1 ,r2, lsl #16 /* r2 = 2345 */
+#else
+ strh r2, [r0]
+ orr r2, r1, r3, lsl #16 /* r2 = 5432 */
+ mov r3, r3, lsr #16 /* r3 = ..76 */
+#endif
+ str r2, [r0, #0x02]
+ strh r3, [r0, #0x06]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 1001: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */
+ ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */
+ ldrb ip, [r1, #0x07] /* ip = ...7 */
+ mov r1, r2, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */
+ strh r1, [r0]
+#ifdef __ARMEB__
+ mov r1, r2, lsl #24 /* r1 = 2... */
+ orr r1, r1, r3, lsr #8 /* r1 = 2345 */
+ orr r3, ip, r3, lsl #8 /* r3 = 4567 */
+#else
+ mov r1, r2, lsr #24 /* r1 = ...2 */
+ orr r1, r1, r3, lsl #8 /* r1 = 5432 */
+ mov r3, r3, lsr #24 /* r3 = ...6 */
+ orr r3, r3, ip, lsl #8 /* r3 = ..76 */
+#endif
+ str r1, [r0, #0x02]
+ strh r3, [r0, #0x06]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 1010: dst is 16-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1]
+ ldr ip, [r1, #0x02]
+ ldrh r3, [r1, #0x06]
+ strh r2, [r0]
+ str ip, [r0, #0x02]
+ strh r3, [r0, #0x06]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 1011: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #0x05] /* BE:r3 = 567x LE:r3 = x765 */
+ ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */
+ ldrb ip, [r1] /* ip = ...0 */
+ mov r1, r3, lsr #8 /* BE:r1 = .567 LE:r1 = .x76 */
+ strh r1, [r0, #0x06]
+#ifdef __ARMEB__
+ mov r3, r3, lsr #24 /* r3 = ...5 */
+ orr r3, r3, r2, lsl #8 /* r3 = 2345 */
+ mov r2, r2, lsr #24 /* r2 = ...1 */
+ orr r2, r2, ip, lsl #8 /* r2 = ..01 */
+#else
+ mov r3, r3, lsl #24 /* r3 = 5... */
+ orr r3, r3, r2, lsr #8 /* r3 = 5432 */
+ orr r2, ip, r2, lsl #8 /* r2 = 3210 */
+#endif
+ str r3, [r0, #0x02]
+ strh r2, [r0]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 1100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ mov r1, r3, lsr #8 /* BE:r1 = .456 LE:r1 = .765 */
+ strh r1, [r0, #0x05]
+#ifdef __ARMEB__
+ strb r3, [r0, #0x07]
+ mov r1, r2, lsr #24 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r2, r2, lsl #8 /* r2 = 123. */
+ orr r2, r2, r3, lsr #24 /* r2 = 1234 */
+ str r2, [r0, #0x01]
+#else
+ strb r2, [r0]
+ mov r1, r3, lsr #24 /* r1 = ...7 */
+ strb r1, [r0, #0x07]
+ mov r2, r2, lsr #8 /* r2 = .321 */
+ orr r2, r2, r3, lsl #24 /* r2 = 4321 */
+ str r2, [r0, #0x01]
+#endif
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 1101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r3, [r1] /* r3 = ...0 */
+ ldrh r2, [r1, #0x01] /* BE:r2 = ..12 LE:r2 = ..21 */
+ ldr ip, [r1, #0x03] /* BE:ip = 3456 LE:ip = 6543 */
+ ldrb r1, [r1, #0x07] /* r1 = ...7 */
+ strb r3, [r0]
+ mov r3, ip, lsr #16 /* BE:r3 = ..34 LE:r3 = ..65 */
+#ifdef __ARMEB__
+ strh ip, [r0, #0x05]
+ orr r2, r3, r2, lsl #16 /* r2 = 1234 */
+#else
+ strh r3, [r0, #0x05]
+ orr r2, r2, ip, lsl #16 /* r2 = 4321 */
+#endif
+ str r2, [r0, #0x01]
+ strb r1, [r0, #0x07]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 1110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */
+#ifdef __ARMEB__
+ mov ip, r2, lsr #8 /* ip = ...0 */
+ strb ip, [r0]
+ mov ip, r2, lsl #24 /* ip = 1... */
+ orr ip, ip, r3, lsr #8 /* ip = 1234 */
+ strb r1, [r0, #0x07]
+ mov r1, r1, lsr #8 /* r1 = ...6 */
+ orr r1, r1, r3, lsl #8 /* r1 = 3456 */
+#else
+ strb r2, [r0]
+ mov ip, r2, lsr #8 /* ip = ...1 */
+ orr ip, ip, r3, lsl #8 /* ip = 4321 */
+ mov r2, r1, lsr #8 /* r2 = ...7 */
+ strb r2, [r0, #0x07]
+ mov r1, r1, lsl #8 /* r1 = .76. */
+ orr r1, r1, r3, lsr #24 /* r1 = .765 */
+#endif
+ str ip, [r0, #0x01]
+ strh r1, [r0, #0x05]
+ RET
+ LMEMCPY_8_PAD
+
+/*
+ * 1111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldr ip, [r1, #0x01]
+ ldrh r3, [r1, #0x05]
+ ldrb r1, [r1, #0x07]
+ strb r2, [r0]
+ str ip, [r0, #0x01]
+ strh r3, [r0, #0x05]
+ strb r1, [r0, #0x07]
+ RET
+ LMEMCPY_8_PAD
+
+/******************************************************************************
+ * Special case for 12 byte copies
+ */
+#define LMEMCPY_C_LOG2 7 /* 128 bytes */
+#define LMEMCPY_C_PAD .align LMEMCPY_C_LOG2
+ LMEMCPY_C_PAD
+.Lmemcpy_c:
+ and r2, r1, #0x03
+ orr r2, r2, r0, lsl #2
+ ands r2, r2, #0x0f
+ sub r3, pc, #0x14
+ addne pc, r3, r2, lsl #LMEMCPY_C_LOG2
+
+/*
+ * 0000: dst is 32-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+ ldr r3, [r1, #0x04]
+ ldr r1, [r1, #0x08]
+ str r2, [r0]
+ str r3, [r0, #0x04]
+ str r1, [r0, #0x08]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 0001: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1, #0xb] /* r2 = ...B */
+ ldr ip, [r1, #0x07] /* BE:ip = 789A LE:ip = A987 */
+ ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */
+ ldr r1, [r1, #-1] /* BE:r1 = x012 LE:r1 = 210x */
+#ifdef __ARMEB__
+ orr r2, r2, ip, lsl #8 /* r2 = 89AB */
+ str r2, [r0, #0x08]
+ mov r2, ip, lsr #24 /* r2 = ...7 */
+ orr r2, r2, r3, lsl #8 /* r2 = 4567 */
+ mov r1, r1, lsl #8 /* r1 = 012. */
+ orr r1, r1, r3, lsr #24 /* r1 = 0123 */
+#else
+ mov r2, r2, lsl #24 /* r2 = B... */
+ orr r2, r2, ip, lsr #8 /* r2 = BA98 */
+ str r2, [r0, #0x08]
+ mov r2, ip, lsl #24 /* r2 = 7... */
+ orr r2, r2, r3, lsr #8 /* r2 = 7654 */
+ mov r1, r1, lsr #8 /* r1 = .210 */
+ orr r1, r1, r3, lsl #24 /* r1 = 3210 */
+#endif
+ str r2, [r0, #0x04]
+ str r1, [r0]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 0010: dst is 32-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldr ip, [r1, #0x06] /* BE:ip = 6789 LE:ip = 9876 */
+ ldrh r1, [r1, #0x0a] /* BE:r1 = ..AB LE:r1 = ..BA */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #16 /* r2 = 01.. */
+ orr r2, r2, r3, lsr #16 /* r2 = 0123 */
+ str r2, [r0]
+ mov r3, r3, lsl #16 /* r3 = 45.. */
+ orr r3, r3, ip, lsr #16 /* r3 = 4567 */
+ orr r1, r1, ip, lsl #16 /* r1 = 89AB */
+#else
+ orr r2, r2, r3, lsl #16 /* r2 = 3210 */
+ str r2, [r0]
+ mov r3, r3, lsr #16 /* r3 = ..54 */
+ orr r3, r3, ip, lsl #16 /* r3 = 7654 */
+ mov r1, r1, lsl #16 /* r1 = BA.. */
+ orr r1, r1, ip, lsr #16 /* r1 = BA98 */
+#endif
+ str r3, [r0, #0x04]
+ str r1, [r0, #0x08]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 0011: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1] /* r2 = ...0 */
+ ldr r3, [r1, #0x01] /* BE:r3 = 1234 LE:r3 = 4321 */
+ ldr ip, [r1, #0x05] /* BE:ip = 5678 LE:ip = 8765 */
+ ldr r1, [r1, #0x09] /* BE:r1 = 9ABx LE:r1 = xBA9 */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #24 /* r2 = 0... */
+ orr r2, r2, r3, lsr #8 /* r2 = 0123 */
+ str r2, [r0]
+ mov r3, r3, lsl #24 /* r3 = 4... */
+ orr r3, r3, ip, lsr #8 /* r3 = 4567 */
+ mov r1, r1, lsr #8 /* r1 = .9AB */
+ orr r1, r1, ip, lsl #24 /* r1 = 89AB */
+#else
+ orr r2, r2, r3, lsl #8 /* r2 = 3210 */
+ str r2, [r0]
+ mov r3, r3, lsr #24 /* r3 = ...4 */
+ orr r3, r3, ip, lsl #8 /* r3 = 7654 */
+ mov r1, r1, lsl #8 /* r1 = BA9. */
+ orr r1, r1, ip, lsr #24 /* r1 = BA98 */
+#endif
+ str r3, [r0, #0x04]
+ str r1, [r0, #0x08]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 0100: dst is 8-bit aligned (byte 1), src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */
+ ldr ip, [r1, #0x08] /* BE:ip = 89AB LE:ip = BA98 */
+ mov r1, r2, lsr #8 /* BE:r1 = .012 LE:r1 = .321 */
+ strh r1, [r0, #0x01]
+#ifdef __ARMEB__
+ mov r1, r2, lsr #24 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r1, r2, lsl #24 /* r1 = 3... */
+ orr r2, r1, r3, lsr #8 /* r1 = 3456 */
+ mov r1, r3, lsl #24 /* r1 = 7... */
+ orr r1, r1, ip, lsr #8 /* r1 = 789A */
+#else
+ strb r2, [r0]
+ mov r1, r2, lsr #24 /* r1 = ...3 */
+ orr r2, r1, r3, lsl #8 /* r1 = 6543 */
+ mov r1, r3, lsr #24 /* r1 = ...7 */
+ orr r1, r1, ip, lsl #8 /* r1 = A987 */
+ mov ip, ip, lsr #24 /* ip = ...B */
+#endif
+ str r2, [r0, #0x03]
+ str r1, [r0, #0x07]
+ strb ip, [r0, #0x0b]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 0101: dst is 8-bit aligned (byte 1), src is 8-bit aligned (byte 1)
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldr ip, [r1, #0x03]
+ strb r2, [r0]
+ ldr r2, [r1, #0x07]
+ ldrb r1, [r1, #0x0b]
+ strh r3, [r0, #0x01]
+ str ip, [r0, #0x03]
+ str r2, [r0, #0x07]
+ strb r1, [r0, #0x0b]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 0110: dst is 8-bit aligned (byte 1), src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldr ip, [r1, #0x06] /* BE:ip = 6789 LE:ip = 9876 */
+ ldrh r1, [r1, #0x0a] /* BE:r1 = ..AB LE:r1 = ..BA */
+#ifdef __ARMEB__
+ mov r2, r2, ror #8 /* r2 = 1..0 */
+ strb r2, [r0]
+ mov r2, r2, lsr #16 /* r2 = ..1. */
+ orr r2, r2, r3, lsr #24 /* r2 = ..12 */
+ strh r2, [r0, #0x01]
+ mov r2, r3, lsl #8 /* r2 = 345. */
+ orr r3, r2, ip, lsr #24 /* r3 = 3456 */
+ mov r2, ip, lsl #8 /* r2 = 789. */
+ orr r2, r2, r1, lsr #8 /* r2 = 789A */
+#else
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r3, lsl #8 /* r2 = 4321 */
+ strh r2, [r0, #0x01]
+ mov r2, r3, lsr #8 /* r2 = .543 */
+ orr r3, r2, ip, lsl #24 /* r3 = 6543 */
+ mov r2, ip, lsr #8 /* r2 = .987 */
+ orr r2, r2, r1, lsl #24 /* r2 = A987 */
+ mov r1, r1, lsr #8 /* r1 = ...B */
+#endif
+ str r3, [r0, #0x03]
+ str r2, [r0, #0x07]
+ strb r1, [r0, #0x0b]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 0111: dst is 8-bit aligned (byte 1), src is 8-bit aligned (byte 3)
+ */
+ ldrb r2, [r1]
+ ldr r3, [r1, #0x01] /* BE:r3 = 1234 LE:r3 = 4321 */
+ ldr ip, [r1, #0x05] /* BE:ip = 5678 LE:ip = 8765 */
+ ldr r1, [r1, #0x09] /* BE:r1 = 9ABx LE:r1 = xBA9 */
+ strb r2, [r0]
+#ifdef __ARMEB__
+ mov r2, r3, lsr #16 /* r2 = ..12 */
+ strh r2, [r0, #0x01]
+ mov r3, r3, lsl #16 /* r3 = 34.. */
+ orr r3, r3, ip, lsr #16 /* r3 = 3456 */
+ mov ip, ip, lsl #16 /* ip = 78.. */
+ orr ip, ip, r1, lsr #16 /* ip = 789A */
+ mov r1, r1, lsr #8 /* r1 = .9AB */
+#else
+ strh r3, [r0, #0x01]
+ mov r3, r3, lsr #16 /* r3 = ..43 */
+ orr r3, r3, ip, lsl #16 /* r3 = 6543 */
+ mov ip, ip, lsr #16 /* ip = ..87 */
+ orr ip, ip, r1, lsl #16 /* ip = A987 */
+ mov r1, r1, lsr #16 /* r1 = ..xB */
+#endif
+ str r3, [r0, #0x03]
+ str ip, [r0, #0x07]
+ strb r1, [r0, #0x0b]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 1000: dst is 16-bit aligned, src is 32-bit aligned
+ */
+ ldr ip, [r1] /* BE:ip = 0123 LE:ip = 3210 */
+ ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */
+ ldr r2, [r1, #0x08] /* BE:r2 = 89AB LE:r2 = BA98 */
+ mov r1, ip, lsr #16 /* BE:r1 = ..01 LE:r1 = ..32 */
+#ifdef __ARMEB__
+ strh r1, [r0]
+ mov r1, ip, lsl #16 /* r1 = 23.. */
+ orr r1, r1, r3, lsr #16 /* r1 = 2345 */
+ mov r3, r3, lsl #16 /* r3 = 67.. */
+ orr r3, r3, r2, lsr #16 /* r3 = 6789 */
+#else
+ strh ip, [r0]
+ orr r1, r1, r3, lsl #16 /* r1 = 5432 */
+ mov r3, r3, lsr #16 /* r3 = ..76 */
+ orr r3, r3, r2, lsl #16 /* r3 = 9876 */
+ mov r2, r2, lsr #16 /* r2 = ..BA */
+#endif
+ str r1, [r0, #0x02]
+ str r3, [r0, #0x06]
+ strh r2, [r0, #0x0a]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 1001: dst is 16-bit aligned, src is 8-bit aligned (byte 1)
+ */
+ ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */
+ ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */
+ mov ip, r2, lsr #8 /* BE:ip = .x01 LE:ip = .210 */
+ strh ip, [r0]
+ ldr ip, [r1, #0x07] /* BE:ip = 789A LE:ip = A987 */
+ ldrb r1, [r1, #0x0b] /* r1 = ...B */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #24 /* r2 = 2... */
+ orr r2, r2, r3, lsr #8 /* r2 = 2345 */
+ mov r3, r3, lsl #24 /* r3 = 6... */
+ orr r3, r3, ip, lsr #8 /* r3 = 6789 */
+ orr r1, r1, ip, lsl #8 /* r1 = 89AB */
+#else
+ mov r2, r2, lsr #24 /* r2 = ...2 */
+ orr r2, r2, r3, lsl #8 /* r2 = 5432 */
+ mov r3, r3, lsr #24 /* r3 = ...6 */
+ orr r3, r3, ip, lsl #8 /* r3 = 9876 */
+ mov r1, r1, lsl #8 /* r1 = ..B. */
+ orr r1, r1, ip, lsr #24 /* r1 = ..BA */
+#endif
+ str r2, [r0, #0x02]
+ str r3, [r0, #0x06]
+ strh r1, [r0, #0x0a]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 1010: dst is 16-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1]
+ ldr r3, [r1, #0x02]
+ ldr ip, [r1, #0x06]
+ ldrh r1, [r1, #0x0a]
+ strh r2, [r0]
+ str r3, [r0, #0x02]
+ str ip, [r0, #0x06]
+ strh r1, [r0, #0x0a]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 1011: dst is 16-bit aligned, src is 8-bit aligned (byte 3)
+ */
+ ldr r2, [r1, #0x09] /* BE:r2 = 9ABx LE:r2 = xBA9 */
+ ldr r3, [r1, #0x05] /* BE:r3 = 5678 LE:r3 = 8765 */
+ mov ip, r2, lsr #8 /* BE:ip = .9AB LE:ip = .xBA */
+ strh ip, [r0, #0x0a]
+ ldr ip, [r1, #0x01] /* BE:ip = 1234 LE:ip = 4321 */
+ ldrb r1, [r1] /* r1 = ...0 */
+#ifdef __ARMEB__
+ mov r2, r2, lsr #24 /* r2 = ...9 */
+ orr r2, r2, r3, lsl #8 /* r2 = 6789 */
+ mov r3, r3, lsr #24 /* r3 = ...5 */
+ orr r3, r3, ip, lsl #8 /* r3 = 2345 */
+ mov r1, r1, lsl #8 /* r1 = ..0. */
+ orr r1, r1, ip, lsr #24 /* r1 = ..01 */
+#else
+ mov r2, r2, lsl #24 /* r2 = 9... */
+ orr r2, r2, r3, lsr #8 /* r2 = 9876 */
+ mov r3, r3, lsl #24 /* r3 = 5... */
+ orr r3, r3, ip, lsr #8 /* r3 = 5432 */
+ orr r1, r1, ip, lsl #8 /* r1 = 3210 */
+#endif
+ str r2, [r0, #0x06]
+ str r3, [r0, #0x02]
+ strh r1, [r0]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 1100: dst is 8-bit aligned (byte 3), src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ ldr ip, [r1, #0x04] /* BE:ip = 4567 LE:ip = 7654 */
+ ldr r1, [r1, #0x08] /* BE:r1 = 89AB LE:r1 = BA98 */
+#ifdef __ARMEB__
+ mov r3, r2, lsr #24 /* r3 = ...0 */
+ strb r3, [r0]
+ mov r2, r2, lsl #8 /* r2 = 123. */
+ orr r2, r2, ip, lsr #24 /* r2 = 1234 */
+ str r2, [r0, #0x01]
+ mov r2, ip, lsl #8 /* r2 = 567. */
+ orr r2, r2, r1, lsr #24 /* r2 = 5678 */
+ str r2, [r0, #0x05]
+ mov r2, r1, lsr #8 /* r2 = ..9A */
+ strh r2, [r0, #0x09]
+ strb r1, [r0, #0x0b]
+#else
+ strb r2, [r0]
+ mov r3, r2, lsr #8 /* r3 = .321 */
+ orr r3, r3, ip, lsl #24 /* r3 = 4321 */
+ str r3, [r0, #0x01]
+ mov r3, ip, lsr #8 /* r3 = .765 */
+ orr r3, r3, r1, lsl #24 /* r3 = 8765 */
+ str r3, [r0, #0x05]
+ mov r1, r1, lsr #8 /* r1 = .BA9 */
+ strh r1, [r0, #0x09]
+ mov r1, r1, lsr #16 /* r1 = ...B */
+ strb r1, [r0, #0x0b]
+#endif
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 1101: dst is 8-bit aligned (byte 3), src is 8-bit aligned (byte 1)
+ */
+ ldrb r2, [r1, #0x0b] /* r2 = ...B */
+ ldr r3, [r1, #0x07] /* BE:r3 = 789A LE:r3 = A987 */
+ ldr ip, [r1, #0x03] /* BE:ip = 3456 LE:ip = 6543 */
+ ldr r1, [r1, #-1] /* BE:r1 = x012 LE:r1 = 210x */
+ strb r2, [r0, #0x0b]
+#ifdef __ARMEB__
+ strh r3, [r0, #0x09]
+ mov r3, r3, lsr #16 /* r3 = ..78 */
+ orr r3, r3, ip, lsl #16 /* r3 = 5678 */
+ mov ip, ip, lsr #16 /* ip = ..34 */
+ orr ip, ip, r1, lsl #16 /* ip = 1234 */
+ mov r1, r1, lsr #16 /* r1 = ..x0 */
+#else
+ mov r2, r3, lsr #16 /* r2 = ..A9 */
+ strh r2, [r0, #0x09]
+ mov r3, r3, lsl #16 /* r3 = 87.. */
+ orr r3, r3, ip, lsr #16 /* r3 = 8765 */
+ mov ip, ip, lsl #16 /* ip = 43.. */
+ orr ip, ip, r1, lsr #16 /* ip = 4321 */
+ mov r1, r1, lsr #8 /* r1 = .210 */
+#endif
+ str r3, [r0, #0x05]
+ str ip, [r0, #0x01]
+ strb r1, [r0]
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 1110: dst is 8-bit aligned (byte 3), src is 16-bit aligned
+ */
+#ifdef __ARMEB__
+ ldrh r2, [r1, #0x0a] /* r2 = ..AB */
+ ldr ip, [r1, #0x06] /* ip = 6789 */
+ ldr r3, [r1, #0x02] /* r3 = 2345 */
+ ldrh r1, [r1] /* r1 = ..01 */
+ strb r2, [r0, #0x0b]
+ mov r2, r2, lsr #8 /* r2 = ...A */
+ orr r2, r2, ip, lsl #8 /* r2 = 789A */
+ mov ip, ip, lsr #8 /* ip = .678 */
+ orr ip, ip, r3, lsl #24 /* ip = 5678 */
+ mov r3, r3, lsr #8 /* r3 = .234 */
+ orr r3, r3, r1, lsl #24 /* r3 = 1234 */
+ mov r1, r1, lsr #8 /* r1 = ...0 */
+ strb r1, [r0]
+ str r3, [r0, #0x01]
+ str ip, [r0, #0x05]
+ strh r2, [r0, #0x09]
+#else
+ ldrh r2, [r1] /* r2 = ..10 */
+ ldr r3, [r1, #0x02] /* r3 = 5432 */
+ ldr ip, [r1, #0x06] /* ip = 9876 */
+ ldrh r1, [r1, #0x0a] /* r1 = ..BA */
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r3, lsl #8 /* r2 = 4321 */
+ mov r3, r3, lsr #24 /* r3 = ...5 */
+ orr r3, r3, ip, lsl #8 /* r3 = 8765 */
+ mov ip, ip, lsr #24 /* ip = ...9 */
+ orr ip, ip, r1, lsl #8 /* ip = .BA9 */
+ mov r1, r1, lsr #8 /* r1 = ...B */
+ str r2, [r0, #0x01]
+ str r3, [r0, #0x05]
+ strh ip, [r0, #0x09]
+ strb r1, [r0, #0x0b]
+#endif
+ RET
+ LMEMCPY_C_PAD
+
+/*
+ * 1111: dst is 8-bit aligned (byte 3), src is 8-bit aligned (byte 3)
+ */
+ ldrb r2, [r1]
+ ldr r3, [r1, #0x01]
+ ldr ip, [r1, #0x05]
+ strb r2, [r0]
+ ldrh r2, [r1, #0x09]
+ ldrb r1, [r1, #0x0b]
+ str r3, [r0, #0x01]
+ str ip, [r0, #0x05]
+ strh r2, [r0, #0x09]
+ strb r1, [r0, #0x0b]
+ RET
+END(memcpy)
+#endif /* _ARM_ARCH_5E */
+
+#ifdef GPROF
+
+ENTRY(user)
+ nop
+END(user)
+ENTRY(btrap)
+ nop
+END(btrap)
+ENTRY(etrap)
+ nop
+END(etrap)
+ENTRY(bintr)
+ nop
+END(bintr)
+ENTRY(eintr)
+ nop
+END(eintr)
+#endif
Property changes on: trunk/sys/arm/arm/support.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/swtch.S
===================================================================
--- trunk/sys/arm/arm/swtch.S (rev 0)
+++ trunk/sys/arm/arm/swtch.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,443 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpuswitch.S,v 1.41 2003/11/15 08:44:18 scw Exp $ */
+
+/*-
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpuswitch.S
+ *
+ * cpu switching functions
+ *
+ * Created : 15/10/94
+ *
+ */
+
+#include "assym.s"
+#include "opt_sched.h"
+
+#include <machine/asm.h>
+#include <machine/asmacros.h>
+#include <machine/armreg.h>
+#include <machine/vfp.h>
+
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/swtch.S 283339 2015-05-23 23:27:00Z ian $");
+
+#define DOMAIN_CLIENT 0x01
+
+#if defined(_ARM_ARCH_6) && defined(SMP)
+#define GET_PCPU(tmp, tmp2) \
+ mrc p15, 0, tmp, c0, c0, 5; \
+ and tmp, tmp, #0xf; \
+ ldr tmp2, .Lcurpcpu+4; \
+ mul tmp, tmp, tmp2; \
+ ldr tmp2, .Lcurpcpu; \
+ add tmp, tmp, tmp2;
+#else
+
+#define GET_PCPU(tmp, tmp2) \
+ ldr tmp, .Lcurpcpu
+#endif
+
+#ifdef VFP
+ .fpu vfp /* allow VFP instructions */
+#endif
+
+.Lcurpcpu:
+ .word _C_LABEL(__pcpu)
+ .word PCPU_SIZE
+.Lcpufuncs:
+ .word _C_LABEL(cpufuncs)
+.Lblocked_lock:
+ .word _C_LABEL(blocked_lock)
+
+/*
+ * cpu_throw(oldtd, newtd)
+ *
+ * Remove current thread state, then select the next thread to run
+ * and load its state.
+ * r0 = oldtd
+ * r1 = newtd
+ */
+ENTRY(cpu_throw)
+ mov r5, r1
+
+ /*
+ * r0 = oldtd
+ * r5 = newtd
+ */
+
+#ifdef VFP /* This thread is dying, disable */
+ bl _C_LABEL(vfp_discard) /* VFP without preserving state. */
+#endif
+
+ GET_PCPU(r7, r9)
+ ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */
+
+ /* Switch to lwp0 context */
+
+ ldr r9, .Lcpufuncs
+#if !defined(CPU_ARM11) && !defined(CPU_CORTEXA) && !defined(CPU_MV_PJ4B) && !defined(CPU_KRAIT)
+ mov lr, pc
+ ldr pc, [r9, #CF_IDCACHE_WBINV_ALL]
+#endif
+ ldr r0, [r7, #(PCB_PL1VEC)]
+ ldr r1, [r7, #(PCB_DACR)]
+ /*
+ * r0 = Pointer to L1 slot for vector_page (or NULL)
+ * r1 = lwp0's DACR
+ * r5 = lwp0
+ * r7 = lwp0's PCB
+ * r9 = cpufuncs
+ */
+
+ /*
+ * Ensure the vector table is accessible by fixing up lwp0's L1
+ */
+ cmp r0, #0 /* No need to fixup vector table? */
+ ldrne r3, [r0] /* But if yes, fetch current value */
+ ldrne r2, [r7, #(PCB_L1VEC)] /* Fetch new vector_page value */
+ mcr p15, 0, r1, c3, c0, 0 /* Update DACR for lwp0's context */
+ cmpne r3, r2 /* Stuffing the same value? */
+ strne r2, [r0] /* Store if not. */
+
+#ifdef PMAP_INCLUDE_PTE_SYNC
+ /*
+ * Need to sync the cache to make sure that last store is
+ * visible to the MMU.
+ */
+ movne r1, #4
+ movne lr, pc
+ ldrne pc, [r9, #CF_DCACHE_WB_RANGE]
+#endif /* PMAP_INCLUDE_PTE_SYNC */
+
+ /*
+ * Note: We don't do the same optimisation as cpu_switch() with
+ * respect to avoiding flushing the TLB if we're switching to
+ * the same L1 since this process' VM space may be about to go
+ * away, so we don't want *any* turds left in the TLB.
+ */
+
+ /* Switch the memory to the new process */
+ ldr r0, [r7, #(PCB_PAGEDIR)]
+ mov lr, pc
+ ldr pc, [r9, #CF_CONTEXT_SWITCH]
+
+ GET_PCPU(r6, r4)
+ /* Hook in a new pcb */
+ str r7, [r6, #PC_CURPCB]
+ /* We have a new curthread now so make a note it */
+ str r5, [r6, #PC_CURTHREAD]
+#ifndef ARM_TP_ADDRESS
+ mcr p15, 0, r5, c13, c0, 4
+#endif
+ /* Set the new tp */
+ ldr r6, [r5, #(TD_MD + MD_TP)]
+#ifdef ARM_TP_ADDRESS
+ ldr r4, =ARM_TP_ADDRESS
+ str r6, [r4]
+ ldr r6, [r5, #(TD_MD + MD_RAS_START)]
+ str r6, [r4, #4] /* ARM_RAS_START */
+ ldr r6, [r5, #(TD_MD + MD_RAS_END)]
+ str r6, [r4, #8] /* ARM_RAS_END */
+#else
+ mcr p15, 0, r6, c13, c0, 3
+#endif
+ /* Restore all the saved registers and exit */
+ add r3, r7, #PCB_R4
+ ldmia r3, {r4-r12, sp, pc}
+END(cpu_throw)
+
+/*
+ * cpu_switch(oldtd, newtd, lock)
+ *
+ * Save the current thread state, then select the next thread to run
+ * and load its state.
+ * r0 = oldtd
+ * r1 = newtd
+ * r2 = lock (new lock for old thread)
+ */
+ENTRY(cpu_switch)
+ /* Interrupts are disabled. */
+ /* Save all the registers in the old thread's pcb. */
+ ldr r3, [r0, #(TD_PCB)]
+
+ /* Restore all the saved registers and exit */
+ add r3, #(PCB_R4)
+ stmia r3, {r4-r12, sp, lr, pc}
+
+ mov r6, r2 /* Save the mutex */
+
+ /* rem: r0 = old lwp */
+ /* rem: interrupts are disabled */
+
+ /* Process is now on a processor. */
+ /* We have a new curthread now so make a note it */
+ GET_PCPU(r7, r2)
+ str r1, [r7, #PC_CURTHREAD]
+#ifndef ARM_TP_ADDRESS
+ mcr p15, 0, r1, c13, c0, 4
+#endif
+
+ /* Hook in a new pcb */
+ ldr r2, [r1, #TD_PCB]
+ str r2, [r7, #PC_CURPCB]
+
+ /* Stage two : Save old context */
+
+ /* Get the user structure for the old thread. */
+ ldr r2, [r0, #(TD_PCB)]
+ mov r4, r0 /* Save the old thread. */
+
+#ifdef ARM_TP_ADDRESS
+ /* Store the old tp; userland can change it on armv4. */
+ ldr r3, =ARM_TP_ADDRESS
+ ldr r9, [r3]
+ str r9, [r0, #(TD_MD + MD_TP)]
+ ldr r9, [r3, #4]
+ str r9, [r0, #(TD_MD + MD_RAS_START)]
+ ldr r9, [r3, #8]
+ str r9, [r0, #(TD_MD + MD_RAS_END)]
+
+ /* Set the new tp */
+ ldr r9, [r1, #(TD_MD + MD_TP)]
+ str r9, [r3]
+ ldr r9, [r1, #(TD_MD + MD_RAS_START)]
+ str r9, [r3, #4]
+ ldr r9, [r1, #(TD_MD + MD_RAS_END)]
+ str r9, [r3, #8]
+#else
+ /*
+ * Set new tp. No need to store the old one first, userland can't
+ * change it directly on armv6.
+ */
+ ldr r9, [r1, #(TD_MD + MD_TP)]
+ mcr p15, 0, r9, c13, c0, 3
+#endif
+
+ /* Get the user structure for the new process in r9 */
+ ldr r9, [r1, #(TD_PCB)]
+
+ /* rem: r2 = old PCB */
+ /* rem: r9 = new PCB */
+ /* rem: interrupts are enabled */
+
+#ifdef VFP
+ fmrx r0, fpexc /* If the VFP is enabled */
+ tst r0, #(VFPEXC_EN) /* the current thread has */
+ movne r1, #1 /* used it, so go save */
+ addne r0, r2, #(PCB_VFPSTATE) /* the state into the PCB */
+ blne _C_LABEL(vfp_store) /* and disable the VFP. */
+#endif
+
+ /* r0-r3 now free! */
+
+ /* Third phase : restore saved context */
+
+ /* rem: r2 = old PCB */
+ /* rem: r9 = new PCB */
+
+ ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */
+ mov r2, #DOMAIN_CLIENT
+ cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */
+ beq .Lcs_context_switched /* Yup. Don't flush cache */
+ mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */
+ /*
+ * Get the new L1 table pointer into r11. If we're switching to
+ * an LWP with the same address space as the outgoing one, we can
+ * skip the cache purge and the TTB load.
+ *
+ * To avoid data dep stalls that would happen anyway, we try
+ * and get some useful work done in the mean time.
+ */
+ mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */
+ ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */
+
+ teq r10, r11 /* Same L1? */
+ cmpeq r0, r5 /* Same DACR? */
+ beq .Lcs_context_switched /* yes! */
+
+#if !defined(CPU_ARM11) && !defined(CPU_CORTEXA) && !defined(CPU_MV_PJ4B) && !defined(CPU_KRAIT)
+ /*
+ * Definately need to flush the cache.
+ */
+
+ ldr r1, .Lcpufuncs
+ mov lr, pc
+ ldr pc, [r1, #CF_IDCACHE_WBINV_ALL]
+#endif
+.Lcs_cache_purge_skipped:
+ /* rem: r6 = lock */
+ /* rem: r9 = new PCB */
+ /* rem: r10 = old L1 */
+ /* rem: r11 = new L1 */
+
+ mov r2, #0x00000000
+ ldr r7, [r9, #(PCB_PL1VEC)]
+
+ /*
+ * Ensure the vector table is accessible by fixing up the L1
+ */
+ cmp r7, #0 /* No need to fixup vector table? */
+ ldrne r2, [r7] /* But if yes, fetch current value */
+ ldrne r0, [r9, #(PCB_L1VEC)] /* Fetch new vector_page value */
+ mcr p15, 0, r5, c3, c0, 0 /* Update DACR for new context */
+ cmpne r2, r0 /* Stuffing the same value? */
+#ifndef PMAP_INCLUDE_PTE_SYNC
+ strne r0, [r7] /* Nope, update it */
+#else
+ beq .Lcs_same_vector
+ str r0, [r7] /* Otherwise, update it */
+
+ /*
+ * Need to sync the cache to make sure that last store is
+ * visible to the MMU.
+ */
+ ldr r2, .Lcpufuncs
+ mov r0, r7
+ mov r1, #4
+ mov lr, pc
+ ldr pc, [r2, #CF_DCACHE_WB_RANGE]
+
+.Lcs_same_vector:
+#endif /* PMAP_INCLUDE_PTE_SYNC */
+
+ cmp r10, r11 /* Switching to the same L1? */
+ ldr r10, .Lcpufuncs
+ beq .Lcs_same_l1 /* Yup. */
+ /*
+ * Do a full context switch, including full TLB flush.
+ */
+ mov r0, r11
+ mov lr, pc
+ ldr pc, [r10, #CF_CONTEXT_SWITCH]
+
+ b .Lcs_context_switched
+
+ /*
+ * We're switching to a different process in the same L1.
+ * In this situation, we only need to flush the TLB for the
+ * vector_page mapping, and even then only if r7 is non-NULL.
+ */
+.Lcs_same_l1:
+ cmp r7, #0
+ movne r0, #0 /* We *know* vector_page's VA is 0x0 */
+ movne lr, pc
+ ldrne pc, [r10, #CF_TLB_FLUSHID_SE]
+
+.Lcs_context_switched:
+
+ /* Release the old thread */
+ str r6, [r4, #TD_LOCK]
+#if defined(SCHED_ULE) && defined(SMP)
+ ldr r6, .Lblocked_lock
+ GET_CURTHREAD_PTR(r3)
+1:
+ ldr r4, [r3, #TD_LOCK]
+ cmp r4, r6
+ beq 1b
+#endif
+
+ /* XXXSCW: Safe to re-enable FIQs here */
+
+ /* rem: r9 = new PCB */
+
+ /* Restore all the saved registers and exit */
+ add r3, r9, #PCB_R4
+ ldmia r3, {r4-r12, sp, pc}
+END(cpu_switch)
+
+ENTRY(savectx)
+ stmfd sp!, {lr}
+ sub sp, sp, #4
+
+ /* Store all the registers in the thread's pcb */
+ add r3, r0, #(PCB_R4)
+ stmia r3, {r4-r12, sp, lr, pc}
+#ifdef VFP
+ fmrx r2, fpexc /* If the VFP is enabled */
+ tst r2, #(VFPEXC_EN) /* the current thread has */
+ movne r1, #1 /* used it, so go save */
+ addne r0, r0, #(PCB_VFPSTATE) /* the state into the PCB */
+ blne _C_LABEL(vfp_store) /* and disable the VFP. */
+#endif
+ add sp, sp, #4;
+ ldmfd sp!, {pc}
+END(savectx)
+
+ENTRY(fork_trampoline)
+ STOP_UNWINDING /* EABI: Don't unwind beyond the thread enty point. */
+ mov fp, #0 /* OABI: Stack traceback via fp stops here. */
+ mov r2, sp
+ mov r1, r5
+ mov r0, r4
+ ldr lr, =swi_exit /* Go finish forking, then return */
+ b _C_LABEL(fork_exit) /* to userland via swi_exit code. */
+END(fork_trampoline)
+
Property changes on: trunk/sys/arm/arm/swtch.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/sys_machdep.c
===================================================================
--- trunk/sys/arm/arm/sys_machdep.c (rev 0)
+++ trunk/sys/arm/arm/sys_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,158 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/sys_machdep.c 283339 2015-05-23 23:27:00Z ian $");
+
+#include "opt_capsicum.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capsicum.h>
+#include <sys/proc.h>
+#include <sys/sysproto.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+
+#include <machine/sysarch.h>
+
+#ifndef _SYS_SYSPROTO_H_
+struct sysarch_args {
+ int op;
+ char *parms;
+};
+#endif
+
+/* Prototypes */
+static int arm32_sync_icache (struct thread *, void *);
+static int arm32_drain_writebuf(struct thread *, void *);
+
+static int
+arm32_sync_icache(struct thread *td, void *args)
+{
+ struct arm_sync_icache_args ua;
+ int error;
+
+ if ((error = copyin(args, &ua, sizeof(ua))) != 0)
+ return (error);
+
+ cpu_icache_sync_range(ua.addr, ua.len);
+
+ td->td_retval[0] = 0;
+ return (0);
+}
+
+static int
+arm32_drain_writebuf(struct thread *td, void *args)
+{
+ /* No args. */
+
+ td->td_retval[0] = 0;
+ cpu_drain_writebuf();
+ return (0);
+}
+
+static int
+arm32_set_tp(struct thread *td, void *args)
+{
+
+ td->td_md.md_tp = (register_t)args;
+#ifndef ARM_TP_ADDRESS
+ set_tls(args);
+#else
+ *(register_t *)ARM_TP_ADDRESS = (register_t)args;
+#endif
+ return (0);
+}
+
+static int
+arm32_get_tp(struct thread *td, void *args)
+{
+
+#ifndef ARM_TP_ADDRESS
+ td->td_retval[0] = td->td_md.md_tp;
+#else
+ td->td_retval[0] = *(register_t *)ARM_TP_ADDRESS;
+#endif
+ return (0);
+}
+
+int
+sysarch(td, uap)
+ struct thread *td;
+ register struct sysarch_args *uap;
+{
+ int error;
+
+#ifdef CAPABILITY_MODE
+ /*
+ * When adding new operations, add a new case statement here to
+ * explicitly indicate whether or not the operation is safe to
+ * perform in capability mode.
+ */
+ if (IN_CAPABILITY_MODE(td)) {
+ switch (uap->op) {
+ case ARM_SYNC_ICACHE:
+ case ARM_DRAIN_WRITEBUF:
+ case ARM_SET_TP:
+ case ARM_GET_TP:
+ break;
+
+ default:
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_CAPFAIL))
+ ktrcapfail(CAPFAIL_SYSCALL, NULL, NULL);
+#endif
+ return (ECAPMODE);
+ }
+ }
+#endif
+
+ switch (uap->op) {
+ case ARM_SYNC_ICACHE:
+ error = arm32_sync_icache(td, uap->parms);
+ break;
+ case ARM_DRAIN_WRITEBUF:
+ error = arm32_drain_writebuf(td, uap->parms);
+ break;
+ case ARM_SET_TP:
+ error = arm32_set_tp(td, uap->parms);
+ break;
+ case ARM_GET_TP:
+ error = arm32_get_tp(td, uap->parms);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return (error);
+}
Property changes on: trunk/sys/arm/arm/sys_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/syscall.c
===================================================================
--- trunk/sys/arm/arm/syscall.c (rev 0)
+++ trunk/sys/arm/arm/syscall.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,198 @@
+/* $MidnightBSD$ */
+/* $NetBSD: fault.c,v 1.45 2003/11/20 14:44:36 scw Exp $ */
+
+/*-
+ * Copyright 2004 Olivier Houchard
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 1994-1997 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fault.c
+ *
+ * Fault handlers
+ *
+ * Created : 28/11/94
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/syscall.c 278656 2015-02-13 02:02:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/signalvar.h>
+#include <sys/ptrace.h>
+#include <sys/pioctl.h>
+
+#include <machine/frame.h>
+
+void swi_handler(struct trapframe *);
+
+static __inline void
+call_trapsignal(struct thread *td, int sig, u_long code)
+{
+ ksiginfo_t ksi;
+
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = sig;
+ ksi.ksi_code = (int)code;
+ trapsignal(td, &ksi);
+}
+
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+ struct proc *p;
+ register_t *ap;
+ int error;
+
+ sa->code = td->td_frame->tf_r7;
+ ap = &td->td_frame->tf_r0;
+ if (sa->code == SYS_syscall) {
+ sa->code = *ap++;
+ sa->nap--;
+ } else if (sa->code == SYS___syscall) {
+ sa->code = ap[_QUAD_LOWWORD];
+ sa->nap -= 2;
+ ap += 2;
+ }
+ p = td->td_proc;
+ if (p->p_sysent->sv_mask)
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
+ error = 0;
+ memcpy(sa->args, ap, sa->nap * sizeof(register_t));
+ if (sa->narg > sa->nap) {
+ error = copyin((void *)td->td_frame->tf_usr_sp, sa->args +
+ sa->nap, (sa->narg - sa->nap) * sizeof(register_t));
+ }
+ if (error == 0) {
+ td->td_retval[0] = 0;
+ td->td_retval[1] = 0;
+ }
+ return (error);
+}
+
+#include "../../kern/subr_syscall.c"
+
+static void
+syscall(struct thread *td, struct trapframe *frame)
+{
+ struct syscall_args sa;
+ int error;
+
+ sa.nap = 4;
+
+ error = syscallenter(td, &sa);
+ KASSERT(error != 0 || td->td_ar == NULL,
+ ("returning from syscall with td_ar set!"));
+ syscallret(td, error, &sa);
+}
+
+void
+swi_handler(struct trapframe *frame)
+{
+ struct thread *td = curthread;
+
+ td->td_frame = frame;
+
+ td->td_pticks = 0;
+ /*
+ * Make sure the program counter is correctly aligned so we
+ * don't take an alignment fault trying to read the opcode.
+ * XXX: Fix for Thumb mode
+ */
+ if (__predict_false(((frame->tf_pc - INSN_SIZE) & 3) != 0)) {
+ call_trapsignal(td, SIGILL, 0);
+ userret(td, frame);
+ return;
+ }
+ /*
+ * Enable interrupts if they were enabled before the exception.
+ * Since all syscalls *should* come from user mode it will always
+ * be safe to enable them, but check anyway.
+ */
+ if (td->td_md.md_spinlock_count == 0) {
+ if (__predict_true(frame->tf_spsr & PSR_I) == 0)
+ enable_interrupts(PSR_I);
+ if (__predict_true(frame->tf_spsr & PSR_F) == 0)
+ enable_interrupts(PSR_F);
+ }
+
+ syscall(td, frame);
+}
Property changes on: trunk/sys/arm/arm/syscall.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/trap-v6.c
===================================================================
--- trunk/sys/arm/arm/trap-v6.c (rev 0)
+++ trunk/sys/arm/arm/trap-v6.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,664 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Olivier Houchard <cognet at FreeBSD.org>
+ * Copyright 2014 Svatopluk Kraus <onwahe at gmail.com>
+ * Copyright 2014 Michal Meloun <meloun at miracle.cz>
+ * Copyright 2014 Andrew Turner <andrew at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_ktrace.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/trap-v6.c 278731 2015-02-13 23:32:03Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/signalvar.h>
+#include <sys/ktr.h>
+#ifdef KTRACE
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+#endif
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_param.h>
+
+#include <machine/cpu.h>
+#include <machine/cpu-v6.h>
+#include <machine/frame.h>
+#include <machine/machdep.h>
+#include <machine/pcb.h>
+#include <machine/vmparam.h>
+
+#ifdef KDB
+#include <sys/kdb.h>
+#include <machine/db_machdep.h>
+#endif
+
+extern char fusubailout[];
+
+#ifdef DEBUG
+int last_fault_code; /* For the benefit of pmap_fault_fixup() */
+#endif
+
+struct ksig {
+ int sig;
+ u_long code;
+ vm_offset_t addr;
+};
+
+typedef int abort_func_t(struct trapframe *, u_int, u_int, u_int, u_int,
+ struct thread *, struct ksig *);
+
+static abort_func_t abort_fatal;
+static abort_func_t abort_align;
+static abort_func_t abort_icache;
+
+struct abort {
+ abort_func_t *func;
+ const char *desc;
+};
+
+/*
+ * How are the aborts handled?
+ *
+ * Undefined Code:
+ * - Always fatal as we do not know what does it mean.
+ * Imprecise External Abort:
+ * - Always fatal, but can be handled somehow in the future.
+ * Now, due to PCIe buggy harware, ignored.
+ * Precise External Abort:
+ * - Always fatal, but who knows in the future???
+ * Debug Event:
+ * - Special handling.
+ * External Translation Abort (L1 & L2)
+ * - Always fatal as something is screwed up in page tables or harware.
+ * Domain Fault (L1 & L2):
+ * - Always fatal as we do not play game with domains.
+ * Alignment Fault:
+ * - Everything should be aligned in kernel including user to kernel and
+ * vice versa data copying, so we ignore pcb_onfault, and it's always fatal.
+ * We generate signal in case of abort from user mode.
+ * Instruction cache maintenance:
+ * - According to manual, this is translation fault during cache maintenance
+ * operation. So, it could be really complex in SMP case and fuzzy too
+ * for cache operations working on virtual addresses. For now, we will
+ * consider this abort as fatal. In fact, no cache maintenance on
+ * not mapped virtual addresses should be called. As cache maintenance
+ * operation (except DMB, DSB, and Flush Prefetch Buffer) are priviledged,
+ * the abort is fatal for user mode as well for now. (This is good place to
+ * note that cache maintenance on virtual address fill TLB.)
+ * Acces Bit (L1 & L2):
+ * - Fast hardware emulation for kernel and user mode.
+ * Translation Fault (L1 & L2):
+ * - Standard fault mechanism is held including vm_fault().
+ * Permission Fault (L1 & L2):
+ * - Fast harware emulation of modify bits and in other cases, standard
+ * fault mechanism is held including vm_fault().
+ */
+
+static const struct abort aborts[] = {
+ {abort_fatal, "Undefined Code (0x000)"},
+ {abort_align, "Alignment Fault"},
+ {abort_fatal, "Debug Event"},
+ {NULL, "Access Bit (L1)"},
+ {abort_icache, "Instruction cache maintenance"},
+ {NULL, "Translation Fault (L1)"},
+ {NULL, "Access Bit (L2)"},
+ {NULL, "Translation Fault (L2)"},
+
+ {abort_fatal, "External Abort"},
+ {abort_fatal, "Domain Fault (L1)"},
+ {abort_fatal, "Undefined Code (0x00A)"},
+ {abort_fatal, "Domain Fault (L2)"},
+ {abort_fatal, "External Translation Abort (L1)"},
+ {NULL, "Permission Fault (L1)"},
+ {abort_fatal, "External Translation Abort (L2)"},
+ {NULL, "Permission Fault (L2)"},
+
+ {abort_fatal, "TLB Conflict Abort"},
+ {abort_fatal, "Undefined Code (0x401)"},
+ {abort_fatal, "Undefined Code (0x402)"},
+ {abort_fatal, "Undefined Code (0x403)"},
+ {abort_fatal, "Undefined Code (0x404)"},
+ {abort_fatal, "Undefined Code (0x405)"},
+ {abort_fatal, "Asynchronous External Abort"},
+ {abort_fatal, "Undefined Code (0x407)"},
+
+ {abort_fatal, "Asynchronous Parity Error on Memory Access"},
+ {abort_fatal, "Parity Error on Memory Access"},
+ {abort_fatal, "Undefined Code (0x40A)"},
+ {abort_fatal, "Undefined Code (0x40B)"},
+ {abort_fatal, "Parity Error on Translation (L1)"},
+ {abort_fatal, "Undefined Code (0x40D)"},
+ {abort_fatal, "Parity Error on Translation (L2)"},
+ {abort_fatal, "Undefined Code (0x40F)"}
+};
+
+
+static __inline void
+call_trapsignal(struct thread *td, int sig, int code, vm_offset_t addr)
+{
+ ksiginfo_t ksi;
+
+ CTR4(KTR_TRAP, "%s: addr: %#x, sig: %d, code: %d",
+ __func__, addr, sig, code);
+
+ /*
+ * TODO: some info would be nice to know
+ * if we are serving data or prefetch abort.
+ */
+
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = sig;
+ ksi.ksi_code = code;
+ ksi.ksi_addr = (void *)addr;
+ trapsignal(td, &ksi);
+}
+
+/*
+ * abort_imprecise() handles the following abort:
+ *
+ * FAULT_EA_IMPREC - Imprecise External Abort
+ *
+ * The imprecise means that we don't know where the abort happened,
+ * thus FAR is undefined. The abort should not never fire, but hot
+ * plugging or accidental harware failure can be the cause of it.
+ * If the abort happens, it can even be on different (thread) context.
+ * Without any additional support, the abort is fatal, as we do not
+ * know what really happened.
+ *
+ * QQQ: Some additional functionality, like pcb_onfault but global,
+ * can be implemented. Imprecise handlers could be registered
+ * which tell us if the abort is caused by something they know
+ * about. They should return one of three codes like:
+ * FAULT_IS_MINE,
+ * FAULT_CAN_BE_MINE,
+ * FAULT_IS_NOT_MINE.
+ * The handlers should be called until some of them returns
+ * FAULT_IS_MINE value or all was called. If all handlers return
+ * FAULT_IS_NOT_MINE value, then the abort is fatal.
+ */
+static __inline void
+abort_imprecise(struct trapframe *tf, u_int fsr, u_int prefetch, u_int usermode)
+{
+ /* XXXX We can got imprecise abort as result of access
+ * to not-present PCI/PCIe configuration space.
+ */
+#if 0
+ goto out;
+#endif
+ abort_fatal(tf, FAULT_EA_IMPREC, fsr, 0, prefetch, curthread, NULL);
+
+ /*
+ * Returning from this function means that we ignore
+ * the abort for good reason. Note that imprecise abort
+ * could fire any time even in user mode.
+ */
+
+#if 0
+out:
+ if (usermode)
+ userret(curthread, tf);
+#endif
+}
+
+/*
+ * abort_debug() handles the following abort:
+ *
+ * FAULT_DEBUG - Debug Event
+ *
+ */
+static __inline void
+abort_debug(struct trapframe *tf, u_int fsr, u_int prefetch, u_int usermode,
+ u_int far)
+{
+ if (usermode) {
+ struct thread *td;
+
+ td = curthread;
+ call_trapsignal(td, SIGTRAP, TRAP_BRKPT, far);
+ userret(td, tf);
+ } else {
+#ifdef KDB
+ kdb_trap(T_BREAKPOINT, 0, tf);
+#else
+ printf("No debugger in kernel.\n");
+#endif
+ }
+}
+
+/*
+ * Abort handler.
+ *
+ * FAR, FSR, and everything what can be lost after enabling
+ * interrupts must be grabbed before the interrupts will be
+ * enabled. Note that when interrupts will be enabled, we
+ * could even migrate to another CPU ...
+ *
+ * TODO: move quick cases to ASM
+ */
+void
+abort_handler(struct trapframe *tf, int prefetch)
+{
+ struct thread *td;
+ vm_offset_t far, va;
+ int idx, usermode;
+ uint32_t fsr;
+ struct ksig ksig;
+ struct proc *p;
+ struct pcb *pcb;
+ struct vm_map *map;
+ struct vmspace *vm;
+ vm_prot_t ftype;
+ int rv;
+#ifdef INVARIANTS
+ void *onfault;
+#endif
+ td = curthread;
+ fsr = (prefetch) ? cp15_ifsr_get(): cp15_dfsr_get();
+ far = (prefetch) ? TRAPF_PC(tf) : cp15_dfar_get();
+
+ idx = FSR_TO_FAULT(fsr);
+ usermode = TRAPF_USERMODE(tf); /* Abort came from user mode? */
+ if (usermode)
+ td->td_frame = tf;
+
+ CTR4(KTR_TRAP, "abort_handler: fsr %#x (idx %u) far %#x prefetch %u",
+ fsr, idx, far, prefetch);
+
+ /*
+ * Firstly, handle aborts that are not directly related to mapping.
+ */
+ if (__predict_false(idx == FAULT_EA_IMPREC)) {
+ abort_imprecise(tf, fsr, prefetch, usermode);
+ return;
+ }
+
+ if (__predict_false(idx == FAULT_DEBUG)) {
+ abort_debug(tf, fsr, prefetch, usermode, far);
+ return;
+ }
+
+#ifdef ARM_NEW_PMAP
+ rv = pmap_fault(PCPU_GET(curpmap), far, fsr, idx, usermode);
+ if (rv == 0) {
+ return;
+ } else if (rv == EFAULT) {
+
+ call_trapsignal(td, SIGSEGV, SEGV_MAPERR, far);
+ userret(td, tf);
+ return;
+ }
+#endif
+ /*
+ * Now, when we handled imprecise and debug aborts, the rest of
+ * aborts should be really related to mapping.
+ *
+ */
+
+ PCPU_INC(cnt.v_trap);
+
+#ifdef KDB
+ if (kdb_active) {
+ kdb_reenter();
+ goto out;
+ }
+#endif
+ if (__predict_false((td->td_pflags & TDP_NOFAULTING) != 0)) {
+ /*
+ * Due to both processor errata and lazy TLB invalidation when
+ * access restrictions are removed from virtual pages, memory
+ * accesses that are allowed by the physical mapping layer may
+ * nonetheless cause one spurious page fault per virtual page.
+ * When the thread is executing a "no faulting" section that
+ * is bracketed by vm_fault_{disable,enable}_pagefaults(),
+ * every page fault is treated as a spurious page fault,
+ * unless it accesses the same virtual address as the most
+ * recent page fault within the same "no faulting" section.
+ */
+ if (td->td_md.md_spurflt_addr != far ||
+ (td->td_pflags & TDP_RESETSPUR) != 0) {
+ td->td_md.md_spurflt_addr = far;
+ td->td_pflags &= ~TDP_RESETSPUR;
+
+ tlb_flush_local(far & ~PAGE_MASK);
+ return;
+ }
+ } else {
+ /*
+ * If we get a page fault while in a critical section, then
+ * it is most likely a fatal kernel page fault. The kernel
+ * is already going to panic trying to get a sleep lock to
+ * do the VM lookup, so just consider it a fatal trap so the
+ * kernel can print out a useful trap message and even get
+ * to the debugger.
+ *
+ * If we get a page fault while holding a non-sleepable
+ * lock, then it is most likely a fatal kernel page fault.
+ * If WITNESS is enabled, then it's going to whine about
+ * bogus LORs with various VM locks, so just skip to the
+ * fatal trap handling directly.
+ */
+ if (td->td_critnest != 0 ||
+ WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL,
+ "Kernel page fault") != 0) {
+ abort_fatal(tf, idx, fsr, far, prefetch, td, &ksig);
+ return;
+ }
+ }
+
+ /* Re-enable interrupts if they were enabled previously. */
+ if (td->td_md.md_spinlock_count == 0) {
+ if (__predict_true(tf->tf_spsr & PSR_I) == 0)
+ enable_interrupts(PSR_I);
+ if (__predict_true(tf->tf_spsr & PSR_F) == 0)
+ enable_interrupts(PSR_F);
+ }
+
+ p = td->td_proc;
+ if (usermode) {
+ td->td_pticks = 0;
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
+ }
+
+ /* Invoke the appropriate handler, if necessary. */
+ if (__predict_false(aborts[idx].func != NULL)) {
+ if ((aborts[idx].func)(tf, idx, fsr, far, prefetch, td, &ksig))
+ goto do_trapsignal;
+ goto out;
+ }
+
+ /*
+ * At this point, we're dealing with one of the following aborts:
+ *
+ * FAULT_TRAN_xx - Translation
+ * FAULT_PERM_xx - Permission
+ *
+ * These are the main virtual memory-related faults signalled by
+ * the MMU.
+ */
+
+ /* fusubailout is used by [fs]uswintr to avoid page faulting */
+ pcb = td->td_pcb;
+ if (__predict_false(pcb->pcb_onfault == fusubailout)) {
+ tf->tf_r0 = EFAULT;
+ tf->tf_pc = (register_t)pcb->pcb_onfault;
+ return;
+ }
+
+ /*
+ * QQQ: ARM has a set of unprivileged load and store instructions
+ * (LDRT/LDRBT/STRT/STRBT ...) which are supposed to be used
+ * in other than user mode and OS should recognize their
+ * aborts and behaved appropriately. However, there is no way
+ * how to do that reasonably in general unless we restrict
+ * the handling somehow. One way is to limit the handling for
+ * aborts which come from undefined mode only.
+ *
+ * Anyhow, we do not use these instructions and do not implement
+ * any special handling for them.
+ */
+
+ va = trunc_page(far);
+ if (va >= KERNBASE) {
+ /*
+ * Don't allow user-mode faults in kernel address space.
+ */
+ if (usermode)
+ goto nogo;
+
+ map = kernel_map;
+ } else {
+ /*
+ * This is a fault on non-kernel virtual memory. If curproc
+ * is NULL or curproc->p_vmspace is NULL the fault is fatal.
+ */
+ vm = (p != NULL) ? p->p_vmspace : NULL;
+ if (vm == NULL)
+ goto nogo;
+
+ map = &vm->vm_map;
+ if (!usermode && (td->td_intr_nesting_level != 0 ||
+ pcb->pcb_onfault == NULL)) {
+ abort_fatal(tf, idx, fsr, far, prefetch, td, &ksig);
+ return;
+ }
+ }
+
+ ftype = (fsr & FSR_WNR) ? VM_PROT_WRITE : VM_PROT_READ;
+ if (prefetch)
+ ftype |= VM_PROT_EXECUTE;
+
+#ifdef DEBUG
+ last_fault_code = fsr;
+#endif
+
+#ifndef ARM_NEW_PMAP
+ if (pmap_fault_fixup(vmspace_pmap(td->td_proc->p_vmspace), va, ftype,
+ usermode)) {
+ goto out;
+ }
+#endif
+
+#ifdef INVARIANTS
+ onfault = pcb->pcb_onfault;
+ pcb->pcb_onfault = NULL;
+#endif
+ if (map != kernel_map) {
+ /*
+ * Keep swapout from messing with us during this
+ * critical time.
+ */
+ PROC_LOCK(p);
+ ++p->p_lock;
+ PROC_UNLOCK(p);
+
+ /* Fault in the user page: */
+ rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+
+ PROC_LOCK(p);
+ --p->p_lock;
+ PROC_UNLOCK(p);
+ } else {
+ /*
+ * Don't have to worry about process locking or stacks in the
+ * kernel.
+ */
+ rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+ }
+
+#ifdef INVARIANTS
+ pcb->pcb_onfault = onfault;
+#endif
+
+ if (__predict_true(rv == KERN_SUCCESS))
+ goto out;
+nogo:
+ if (!usermode) {
+ if (td->td_intr_nesting_level == 0 &&
+ pcb->pcb_onfault != NULL) {
+ tf->tf_r0 = rv;
+ tf->tf_pc = (int)pcb->pcb_onfault;
+ return;
+ }
+ CTR2(KTR_TRAP, "%s: vm_fault() failed with %d", __func__, rv);
+ abort_fatal(tf, idx, fsr, far, prefetch, td, &ksig);
+ return;
+ }
+
+ ksig.sig = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
+ ksig.code = 0;
+ ksig.addr = far;
+
+do_trapsignal:
+ call_trapsignal(td, ksig.sig, ksig.code, ksig.addr);
+out:
+ if (usermode)
+ userret(td, tf);
+}
+
+/*
+ * abort_fatal() handles the following data aborts:
+
+ * FAULT_DEBUG - Debug Event
+ * FAULT_ACCESS_xx - Acces Bit
+ * FAULT_EA_PREC - Precise External Abort
+ * FAULT_DOMAIN_xx - Domain Fault
+ * FAULT_EA_TRAN_xx - External Translation Abort
+ * FAULT_EA_IMPREC - Imprecise External Abort
+ * + all undefined codes for ABORT
+ *
+ * We should never see these on a properly functioning system.
+ *
+ * This function is also called by the other handlers if they
+ * detect a fatal problem.
+ *
+ * Note: If 'l' is NULL, we assume we're dealing with a prefetch abort.
+ */
+static int
+abort_fatal(struct trapframe *tf, u_int idx, u_int fsr, u_int far, u_int prefetch,
+ struct thread *td, struct ksig *ksig)
+{
+ u_int usermode;
+ const char *mode;
+ const char *rw_mode;
+
+ usermode = TRAPF_USERMODE(tf);
+ mode = usermode ? "user" : "kernel";
+ rw_mode = fsr & FSR_WNR ? "write" : "read";
+ disable_interrupts(PSR_I|PSR_F);
+
+ if (td != NULL) {
+ printf("Fatal %s mode data abort: '%s' on %s\n", mode,
+ aborts[idx].desc, rw_mode);
+ printf("trapframe: %p\nFSR=%08x, FAR=", tf, fsr);
+ if (idx != FAULT_EA_IMPREC)
+ printf("%08x, ", far);
+ else
+ printf("Invalid, ");
+ printf("spsr=%08x\n", tf->tf_spsr);
+ } else {
+ printf("Fatal %s mode prefetch abort at 0x%08x\n",
+ mode, tf->tf_pc);
+ printf("trapframe: %p, spsr=%08x\n", tf, tf->tf_spsr);
+ }
+
+ printf("r0 =%08x, r1 =%08x, r2 =%08x, r3 =%08x\n",
+ tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3);
+ printf("r4 =%08x, r5 =%08x, r6 =%08x, r7 =%08x\n",
+ tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7);
+ printf("r8 =%08x, r9 =%08x, r10=%08x, r11=%08x\n",
+ tf->tf_r8, tf->tf_r9, tf->tf_r10, tf->tf_r11);
+ printf("r12=%08x, ", tf->tf_r12);
+
+ if (usermode)
+ printf("usp=%08x, ulr=%08x",
+ tf->tf_usr_sp, tf->tf_usr_lr);
+ else
+ printf("ssp=%08x, slr=%08x",
+ tf->tf_svc_sp, tf->tf_svc_lr);
+ printf(", pc =%08x\n\n", tf->tf_pc);
+
+#ifdef KDB
+ if (debugger_on_panic || kdb_active)
+ kdb_trap(fsr, 0, tf);
+#endif
+ panic("Fatal abort");
+ /*NOTREACHED*/
+}
+
+/*
+ * abort_align() handles the following data abort:
+ *
+ * FAULT_ALIGN - Alignment fault
+ *
+ * Every memory access should be correctly aligned in kernel including
+ * user to kernel and vice versa data copying, so we ignore pcb_onfault,
+ * and it's always fatal. We generate a signal in case of abort from user mode.
+ */
+static int
+abort_align(struct trapframe *tf, u_int idx, u_int fsr, u_int far, u_int prefetch,
+ struct thread *td, struct ksig *ksig)
+{
+ u_int usermode;
+
+ usermode = TRAPF_USERMODE(tf);
+
+ /*
+ * Alignment faults are always fatal if they occur in any but user mode.
+ *
+ * XXX The old trap code handles pcb fault even for alignment traps.
+ * Unfortunately, we don't known why and if is this need.
+ */
+ if (!usermode) {
+ if (td->td_intr_nesting_level == 0 && td != NULL &&
+ td->td_pcb->pcb_onfault != NULL) {
+ printf("%s: Got alignment fault with pcb_onfault set"
+ ", please report this issue\n", __func__);
+ tf->tf_r0 = EFAULT;;
+ tf->tf_pc = (int)td->td_pcb->pcb_onfault;
+ return (0);
+ }
+ abort_fatal(tf, idx, fsr, far, prefetch, td, ksig);
+ }
+ /* Deliver a bus error signal to the process */
+ ksig->code = 0;
+ ksig->sig = SIGBUS;
+ ksig->addr = far;
+ return (1);
+}
+
+/*
+ * abort_icache() handles the following data abort:
+ *
+ * FAULT_ICACHE - Instruction cache maintenance
+ *
+ * According to manual, FAULT_ICACHE is translation fault during cache
+ * maintenance operation. In fact, no cache maintenance operation on
+ * not mapped virtual addresses should be called. As cache maintenance
+ * operation (except DMB, DSB, and Flush Prefetch Buffer) are priviledged,
+ * the abort is concider as fatal for now. However, all the matter with
+ * cache maintenance operation on virtual addresses could be really complex
+ * and fuzzy in SMP case, so maybe in future standard fault mechanism
+ * should be held here including vm_fault() calling.
+ */
+static int
+abort_icache(struct trapframe *tf, u_int idx, u_int fsr, u_int far, u_int prefetch,
+ struct thread *td, struct ksig *ksig)
+{
+ abort_fatal(tf, idx, fsr, far, prefetch, td, ksig);
+ return(0);
+}
Property changes on: trunk/sys/arm/arm/trap-v6.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/trap.c
===================================================================
--- trunk/sys/arm/arm/trap.c (rev 0)
+++ trunk/sys/arm/arm/trap.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,753 @@
+/* $MidnightBSD$ */
+/* $NetBSD: fault.c,v 1.45 2003/11/20 14:44:36 scw Exp $ */
+
+/*-
+ * Copyright 2004 Olivier Houchard
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 1994-1997 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fault.c
+ *
+ * Fault handlers
+ *
+ * Created : 28/11/94
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/trap.c 294681 2016-01-24 19:58:58Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/signalvar.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+#include <machine/acle-compat.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/machdep.h>
+#include <machine/pcb.h>
+#include <machine/vmparam.h>
+
+#ifdef KDB
+#include <sys/kdb.h>
+#endif
+
+extern char fusubailout[];
+
+#ifdef DEBUG
+int last_fault_code; /* For the benefit of pmap_fault_fixup() */
+#endif
+
+struct ksig {
+ int signb;
+ u_long code;
+};
+struct data_abort {
+ int (*func)(struct trapframe *, u_int, u_int, struct thread *,
+ struct ksig *);
+ const char *desc;
+};
+
+static int dab_fatal(struct trapframe *, u_int, u_int, struct thread *,
+ struct ksig *);
+static int dab_align(struct trapframe *, u_int, u_int, struct thread *,
+ struct ksig *);
+static int dab_buserr(struct trapframe *, u_int, u_int, struct thread *,
+ struct ksig *);
+static void prefetch_abort_handler(struct trapframe *);
+
+static const struct data_abort data_aborts[] = {
+ {dab_fatal, "Vector Exception"},
+ {dab_align, "Alignment Fault 1"},
+ {dab_fatal, "Terminal Exception"},
+ {dab_align, "Alignment Fault 3"},
+ {dab_buserr, "External Linefetch Abort (S)"},
+ {NULL, "Translation Fault (S)"},
+#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
+ {NULL, "Translation Flag Fault"},
+#else
+ {dab_buserr, "External Linefetch Abort (P)"},
+#endif
+ {NULL, "Translation Fault (P)"},
+ {dab_buserr, "External Non-Linefetch Abort (S)"},
+ {NULL, "Domain Fault (S)"},
+ {dab_buserr, "External Non-Linefetch Abort (P)"},
+ {NULL, "Domain Fault (P)"},
+ {dab_buserr, "External Translation Abort (L1)"},
+ {NULL, "Permission Fault (S)"},
+ {dab_buserr, "External Translation Abort (L2)"},
+ {NULL, "Permission Fault (P)"}
+};
+
+/* Determine if a fault came from user mode */
+#define TRAP_USERMODE(tf) ((tf->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
+
+/* Determine if 'x' is a permission fault */
+#define IS_PERMISSION_FAULT(x) \
+ (((1 << ((x) & FAULT_TYPE_MASK)) & \
+ ((1 << FAULT_PERM_P) | (1 << FAULT_PERM_S))) != 0)
+
+static __inline void
+call_trapsignal(struct thread *td, int sig, u_long code)
+{
+ ksiginfo_t ksi;
+
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = sig;
+ ksi.ksi_code = (int)code;
+ trapsignal(td, &ksi);
+}
+
+void
+abort_handler(struct trapframe *tf, int type)
+{
+ struct vm_map *map;
+ struct pcb *pcb;
+ struct thread *td;
+ u_int user, far, fsr;
+ vm_prot_t ftype;
+ void *onfault;
+ vm_offset_t va;
+ int error = 0;
+ struct ksig ksig;
+ struct proc *p;
+
+ if (type == 1)
+ return (prefetch_abort_handler(tf));
+
+ /* Grab FAR/FSR before enabling interrupts */
+ far = cpu_faultaddress();
+ fsr = cpu_faultstatus();
+#if 0
+ printf("data abort: fault address=%p (from pc=%p lr=%p)\n",
+ (void*)far, (void*)tf->tf_pc, (void*)tf->tf_svc_lr);
+#endif
+
+ /* Update vmmeter statistics */
+#if 0
+ vmexp.traps++;
+#endif
+
+ td = curthread;
+ p = td->td_proc;
+
+ PCPU_INC(cnt.v_trap);
+ /* Data abort came from user mode? */
+ user = TRAP_USERMODE(tf);
+
+ if (user) {
+ td->td_pticks = 0;
+ td->td_frame = tf;
+ if (td->td_ucred != td->td_proc->p_ucred)
+ cred_update_thread(td);
+
+ }
+ /* Grab the current pcb */
+ pcb = td->td_pcb;
+ /* Re-enable interrupts if they were enabled previously */
+ if (td->td_md.md_spinlock_count == 0) {
+ if (__predict_true(tf->tf_spsr & PSR_I) == 0)
+ enable_interrupts(PSR_I);
+ if (__predict_true(tf->tf_spsr & PSR_F) == 0)
+ enable_interrupts(PSR_F);
+ }
+
+
+ /* Invoke the appropriate handler, if necessary */
+ if (__predict_false(data_aborts[fsr & FAULT_TYPE_MASK].func != NULL)) {
+ if ((data_aborts[fsr & FAULT_TYPE_MASK].func)(tf, fsr, far,
+ td, &ksig)) {
+ goto do_trapsignal;
+ }
+ goto out;
+ }
+
+ /*
+ * At this point, we're dealing with one of the following data aborts:
+ *
+ * FAULT_TRANS_S - Translation -- Section
+ * FAULT_TRANS_P - Translation -- Page
+ * FAULT_DOMAIN_S - Domain -- Section
+ * FAULT_DOMAIN_P - Domain -- Page
+ * FAULT_PERM_S - Permission -- Section
+ * FAULT_PERM_P - Permission -- Page
+ *
+ * These are the main virtual memory-related faults signalled by
+ * the MMU.
+ */
+
+ /* fusubailout is used by [fs]uswintr to avoid page faulting */
+ if (__predict_false(pcb->pcb_onfault == fusubailout)) {
+ tf->tf_r0 = EFAULT;
+ tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault;
+ return;
+ }
+
+ /*
+ * Make sure the Program Counter is sane. We could fall foul of
+ * someone executing Thumb code, in which case the PC might not
+ * be word-aligned. This would cause a kernel alignment fault
+ * further down if we have to decode the current instruction.
+ * XXX: It would be nice to be able to support Thumb at some point.
+ */
+ if (__predict_false((tf->tf_pc & 3) != 0)) {
+ if (user) {
+ /*
+ * Give the user an illegal instruction signal.
+ */
+ /* Deliver a SIGILL to the process */
+ ksig.signb = SIGILL;
+ ksig.code = 0;
+ goto do_trapsignal;
+ }
+
+ /*
+ * The kernel never executes Thumb code.
+ */
+ printf("\ndata_abort_fault: Misaligned Kernel-mode "
+ "Program Counter\n");
+ dab_fatal(tf, fsr, far, td, &ksig);
+ }
+
+ va = trunc_page((vm_offset_t)far);
+
+ /*
+ * It is only a kernel address space fault iff:
+ * 1. user == 0 and
+ * 2. pcb_onfault not set or
+ * 3. pcb_onfault set and not LDRT/LDRBT/STRT/STRBT instruction.
+ */
+ if (user == 0 && (va >= VM_MIN_KERNEL_ADDRESS ||
+ (va < VM_MIN_ADDRESS && vector_page == ARM_VECTORS_LOW)) &&
+ __predict_true((pcb->pcb_onfault == NULL ||
+ (ReadWord(tf->tf_pc) & 0x05200000) != 0x04200000))) {
+ map = kernel_map;
+
+ /* Was the fault due to the FPE/IPKDB ? */
+ if (__predict_false((tf->tf_spsr & PSR_MODE)==PSR_UND32_MODE)) {
+
+ /*
+ * Force exit via userret()
+ * This is necessary as the FPE is an extension to
+ * userland that actually runs in a priveledged mode
+ * but uses USR mode permissions for its accesses.
+ */
+ user = 1;
+ ksig.signb = SIGSEGV;
+ ksig.code = 0;
+ goto do_trapsignal;
+ }
+ } else {
+ map = &td->td_proc->p_vmspace->vm_map;
+ }
+
+ /*
+ * We need to know whether the page should be mapped as R or R/W. On
+ * armv6 and later the fault status register indicates whether the
+ * access was a read or write. Prior to armv6, we know that a
+ * permission fault can only be the result of a write to a read-only
+ * location, so we can deal with those quickly. Otherwise we need to
+ * disassemble the faulting instruction to determine if it was a write.
+ */
+#if __ARM_ARCH >= 6
+ ftype = (fsr & FAULT_WNR) ? VM_PROT_READ | VM_PROT_WRITE : VM_PROT_READ;
+#else
+ if (IS_PERMISSION_FAULT(fsr))
+ ftype = VM_PROT_WRITE;
+ else {
+ u_int insn = ReadWord(tf->tf_pc);
+
+ if (((insn & 0x0c100000) == 0x04000000) || /* STR/STRB */
+ ((insn & 0x0e1000b0) == 0x000000b0) || /* STRH/STRD */
+ ((insn & 0x0a100000) == 0x08000000)) { /* STM/CDT */
+ ftype = VM_PROT_WRITE;
+ } else {
+ if ((insn & 0x0fb00ff0) == 0x01000090) /* SWP */
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
+ else
+ ftype = VM_PROT_READ;
+ }
+ }
+#endif
+
+ /*
+ * See if the fault is as a result of ref/mod emulation,
+ * or domain mismatch.
+ */
+#ifdef DEBUG
+ last_fault_code = fsr;
+#endif
+ if (pmap_fault_fixup(vmspace_pmap(td->td_proc->p_vmspace), va, ftype,
+ user)) {
+ goto out;
+ }
+
+ onfault = pcb->pcb_onfault;
+ pcb->pcb_onfault = NULL;
+ if (map != kernel_map) {
+ PROC_LOCK(p);
+ p->p_lock++;
+ PROC_UNLOCK(p);
+ }
+ error = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+ pcb->pcb_onfault = onfault;
+
+ if (map != kernel_map) {
+ PROC_LOCK(p);
+ p->p_lock--;
+ PROC_UNLOCK(p);
+ }
+ if (__predict_true(error == 0))
+ goto out;
+ if (user == 0) {
+ if (pcb->pcb_onfault) {
+ tf->tf_r0 = error;
+ tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault;
+ return;
+ }
+
+ printf("\nvm_fault(%p, %x, %x, 0) -> %x\n", map, va, ftype,
+ error);
+ dab_fatal(tf, fsr, far, td, &ksig);
+ }
+
+
+ if (error == ENOMEM) {
+ printf("VM: pid %d (%s), uid %d killed: "
+ "out of swap\n", td->td_proc->p_pid, td->td_name,
+ (td->td_proc->p_ucred) ?
+ td->td_proc->p_ucred->cr_uid : -1);
+ ksig.signb = SIGKILL;
+ } else {
+ ksig.signb = SIGSEGV;
+ }
+ ksig.code = 0;
+do_trapsignal:
+ call_trapsignal(td, ksig.signb, ksig.code);
+out:
+ /* If returning to user mode, make sure to invoke userret() */
+ if (user)
+ userret(td, tf);
+}
+
+/*
+ * dab_fatal() handles the following data aborts:
+ *
+ * FAULT_WRTBUF_0 - Vector Exception
+ * FAULT_WRTBUF_1 - Terminal Exception
+ *
+ * We should never see these on a properly functioning system.
+ *
+ * This function is also called by the other handlers if they
+ * detect a fatal problem.
+ *
+ * Note: If 'l' is NULL, we assume we're dealing with a prefetch abort.
+ */
+static int
+dab_fatal(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
+ struct ksig *ksig)
+{
+ const char *mode;
+
+ mode = TRAP_USERMODE(tf) ? "user" : "kernel";
+
+ disable_interrupts(PSR_I|PSR_F);
+ if (td != NULL) {
+ printf("Fatal %s mode data abort: '%s'\n", mode,
+ data_aborts[fsr & FAULT_TYPE_MASK].desc);
+ printf("trapframe: %p\nFSR=%08x, FAR=", tf, fsr);
+ if ((fsr & FAULT_IMPRECISE) == 0)
+ printf("%08x, ", far);
+ else
+ printf("Invalid, ");
+ printf("spsr=%08x\n", tf->tf_spsr);
+ } else {
+ printf("Fatal %s mode prefetch abort at 0x%08x\n",
+ mode, tf->tf_pc);
+ printf("trapframe: %p, spsr=%08x\n", tf, tf->tf_spsr);
+ }
+
+ printf("r0 =%08x, r1 =%08x, r2 =%08x, r3 =%08x\n",
+ tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3);
+ printf("r4 =%08x, r5 =%08x, r6 =%08x, r7 =%08x\n",
+ tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7);
+ printf("r8 =%08x, r9 =%08x, r10=%08x, r11=%08x\n",
+ tf->tf_r8, tf->tf_r9, tf->tf_r10, tf->tf_r11);
+ printf("r12=%08x, ", tf->tf_r12);
+
+ if (TRAP_USERMODE(tf))
+ printf("usp=%08x, ulr=%08x",
+ tf->tf_usr_sp, tf->tf_usr_lr);
+ else
+ printf("ssp=%08x, slr=%08x",
+ tf->tf_svc_sp, tf->tf_svc_lr);
+ printf(", pc =%08x\n\n", tf->tf_pc);
+
+#ifdef KDB
+ if (debugger_on_panic || kdb_active)
+ if (kdb_trap(fsr, 0, tf))
+ return (0);
+#endif
+ panic("Fatal abort");
+ /*NOTREACHED*/
+}
+
+/*
+ * dab_align() handles the following data aborts:
+ *
+ * FAULT_ALIGN_0 - Alignment fault
+ * FAULT_ALIGN_1 - Alignment fault
+ *
+ * These faults are fatal if they happen in kernel mode. Otherwise, we
+ * deliver a bus error to the process.
+ */
+static int
+dab_align(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
+ struct ksig *ksig)
+{
+
+ /* Alignment faults are always fatal if they occur in kernel mode */
+ if (!TRAP_USERMODE(tf)) {
+ if (!td || !td->td_pcb->pcb_onfault)
+ dab_fatal(tf, fsr, far, td, ksig);
+ tf->tf_r0 = EFAULT;
+ tf->tf_pc = (int)td->td_pcb->pcb_onfault;
+ return (0);
+ }
+
+ /* pcb_onfault *must* be NULL at this point */
+
+ /* Deliver a bus error signal to the process */
+ ksig->code = 0;
+ ksig->signb = SIGBUS;
+ td->td_frame = tf;
+
+ return (1);
+}
+
+/*
+ * dab_buserr() handles the following data aborts:
+ *
+ * FAULT_BUSERR_0 - External Abort on Linefetch -- Section
+ * FAULT_BUSERR_1 - External Abort on Linefetch -- Page
+ * FAULT_BUSERR_2 - External Abort on Non-linefetch -- Section
+ * FAULT_BUSERR_3 - External Abort on Non-linefetch -- Page
+ * FAULT_BUSTRNL1 - External abort on Translation -- Level 1
+ * FAULT_BUSTRNL2 - External abort on Translation -- Level 2
+ *
+ * If pcb_onfault is set, flag the fault and return to the handler.
+ * If the fault occurred in user mode, give the process a SIGBUS.
+ *
+ * Note: On XScale, FAULT_BUSERR_0, FAULT_BUSERR_1, and FAULT_BUSERR_2
+ * can be flagged as imprecise in the FSR. This causes a real headache
+ * since some of the machine state is lost. In this case, tf->tf_pc
+ * may not actually point to the offending instruction. In fact, if
+ * we've taken a double abort fault, it generally points somewhere near
+ * the top of "data_abort_entry" in exception.S.
+ *
+ * In all other cases, these data aborts are considered fatal.
+ */
+static int
+dab_buserr(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
+ struct ksig *ksig)
+{
+ struct pcb *pcb = td->td_pcb;
+
+#ifdef __XSCALE__
+ if ((fsr & FAULT_IMPRECISE) != 0 &&
+ (tf->tf_spsr & PSR_MODE) == PSR_ABT32_MODE) {
+ /*
+ * Oops, an imprecise, double abort fault. We've lost the
+ * r14_abt/spsr_abt values corresponding to the original
+ * abort, and the spsr saved in the trapframe indicates
+ * ABT mode.
+ */
+ tf->tf_spsr &= ~PSR_MODE;
+
+ /*
+ * We use a simple heuristic to determine if the double abort
+ * happened as a result of a kernel or user mode access.
+ * If the current trapframe is at the top of the kernel stack,
+ * the fault _must_ have come from user mode.
+ */
+ if (tf != ((struct trapframe *)pcb->pcb_regs.sf_sp) - 1) {
+ /*
+ * Kernel mode. We're either about to die a
+ * spectacular death, or pcb_onfault will come
+ * to our rescue. Either way, the current value
+ * of tf->tf_pc is irrelevant.
+ */
+ tf->tf_spsr |= PSR_SVC32_MODE;
+ if (pcb->pcb_onfault == NULL)
+ printf("\nKernel mode double abort!\n");
+ } else {
+ /*
+ * User mode. We've lost the program counter at the
+ * time of the fault (not that it was accurate anyway;
+ * it's not called an imprecise fault for nothing).
+ * About all we can do is copy r14_usr to tf_pc and
+ * hope for the best. The process is about to get a
+ * SIGBUS, so it's probably history anyway.
+ */
+ tf->tf_spsr |= PSR_USR32_MODE;
+ tf->tf_pc = tf->tf_usr_lr;
+ }
+ }
+
+ /* FAR is invalid for imprecise exceptions */
+ if ((fsr & FAULT_IMPRECISE) != 0)
+ far = 0;
+#endif /* __XSCALE__ */
+
+ if (pcb->pcb_onfault) {
+ tf->tf_r0 = EFAULT;
+ tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault;
+ return (0);
+ }
+
+ /*
+ * At this point, if the fault happened in kernel mode, we're toast
+ */
+ if (!TRAP_USERMODE(tf))
+ dab_fatal(tf, fsr, far, td, ksig);
+
+ /* Deliver a bus error signal to the process */
+ ksig->signb = SIGBUS;
+ ksig->code = 0;
+ td->td_frame = tf;
+
+ return (1);
+}
+
+/*
+ * void prefetch_abort_handler(struct trapframe *tf)
+ *
+ * Abort handler called when instruction execution occurs at
+ * a non existent or restricted (access permissions) memory page.
+ * If the address is invalid and we were in SVC mode then panic as
+ * the kernel should never prefetch abort.
+ * If the address is invalid and the page is mapped then the user process
+ * does no have read permission so send it a signal.
+ * Otherwise fault the page in and try again.
+ */
+static void
+prefetch_abort_handler(struct trapframe *tf)
+{
+ struct thread *td;
+ struct proc * p;
+ struct vm_map *map;
+ vm_offset_t fault_pc, va;
+ int error = 0;
+ struct ksig ksig;
+
+
+#if 0
+ /* Update vmmeter statistics */
+ uvmexp.traps++;
+#endif
+#if 0
+ printf("prefetch abort handler: %p %p\n", (void*)tf->tf_pc,
+ (void*)tf->tf_usr_lr);
+#endif
+
+ td = curthread;
+ p = td->td_proc;
+ PCPU_INC(cnt.v_trap);
+
+ if (TRAP_USERMODE(tf)) {
+ td->td_frame = tf;
+ if (td->td_ucred != td->td_proc->p_ucred)
+ cred_update_thread(td);
+ }
+ fault_pc = tf->tf_pc;
+ if (td->td_md.md_spinlock_count == 0) {
+ if (__predict_true(tf->tf_spsr & PSR_I) == 0)
+ enable_interrupts(PSR_I);
+ if (__predict_true(tf->tf_spsr & PSR_F) == 0)
+ enable_interrupts(PSR_F);
+ }
+
+ /* Prefetch aborts cannot happen in kernel mode */
+ if (__predict_false(!TRAP_USERMODE(tf)))
+ dab_fatal(tf, 0, tf->tf_pc, NULL, &ksig);
+ td->td_pticks = 0;
+
+
+ /* Ok validate the address, can only execute in USER space */
+ if (__predict_false(fault_pc >= VM_MAXUSER_ADDRESS ||
+ (fault_pc < VM_MIN_ADDRESS && vector_page == ARM_VECTORS_LOW))) {
+ ksig.signb = SIGSEGV;
+ ksig.code = 0;
+ goto do_trapsignal;
+ }
+
+ map = &td->td_proc->p_vmspace->vm_map;
+ va = trunc_page(fault_pc);
+
+ /*
+ * See if the pmap can handle this fault on its own...
+ */
+#ifdef DEBUG
+ last_fault_code = -1;
+#endif
+ if (pmap_fault_fixup(map->pmap, va, VM_PROT_READ, 1))
+ goto out;
+
+ if (map != kernel_map) {
+ PROC_LOCK(p);
+ p->p_lock++;
+ PROC_UNLOCK(p);
+ }
+
+ error = vm_fault(map, va, VM_PROT_READ | VM_PROT_EXECUTE,
+ VM_FAULT_NORMAL);
+ if (map != kernel_map) {
+ PROC_LOCK(p);
+ p->p_lock--;
+ PROC_UNLOCK(p);
+ }
+
+ if (__predict_true(error == 0))
+ goto out;
+
+ if (error == ENOMEM) {
+ printf("VM: pid %d (%s), uid %d killed: "
+ "out of swap\n", td->td_proc->p_pid, td->td_name,
+ (td->td_proc->p_ucred) ?
+ td->td_proc->p_ucred->cr_uid : -1);
+ ksig.signb = SIGKILL;
+ } else {
+ ksig.signb = SIGSEGV;
+ }
+ ksig.code = 0;
+
+do_trapsignal:
+ call_trapsignal(td, ksig.signb, ksig.code);
+
+out:
+ userret(td, tf);
+
+}
+
+extern int badaddr_read_1(const uint8_t *, uint8_t *);
+extern int badaddr_read_2(const uint16_t *, uint16_t *);
+extern int badaddr_read_4(const uint32_t *, uint32_t *);
+/*
+ * Tentatively read an 8, 16, or 32-bit value from 'addr'.
+ * If the read succeeds, the value is written to 'rptr' and zero is returned.
+ * Else, return EFAULT.
+ */
+int
+badaddr_read(void *addr, size_t size, void *rptr)
+{
+ union {
+ uint8_t v1;
+ uint16_t v2;
+ uint32_t v4;
+ } u;
+ int rv;
+
+ cpu_drain_writebuf();
+
+ /* Read from the test address. */
+ switch (size) {
+ case sizeof(uint8_t):
+ rv = badaddr_read_1(addr, &u.v1);
+ if (rv == 0 && rptr)
+ *(uint8_t *) rptr = u.v1;
+ break;
+
+ case sizeof(uint16_t):
+ rv = badaddr_read_2(addr, &u.v2);
+ if (rv == 0 && rptr)
+ *(uint16_t *) rptr = u.v2;
+ break;
+
+ case sizeof(uint32_t):
+ rv = badaddr_read_4(addr, &u.v4);
+ if (rv == 0 && rptr)
+ *(uint32_t *) rptr = u.v4;
+ break;
+
+ default:
+ panic("badaddr: invalid size (%lu)", (u_long) size);
+ }
+
+ /* Return EFAULT if the address was invalid, else zero */
+ return (rv);
+}
\ No newline at end of file
Property changes on: trunk/sys/arm/arm/trap.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/uio_machdep.c
===================================================================
--- trunk/sys/arm/arm/uio_machdep.c (rev 0)
+++ trunk/sys/arm/arm/uio_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,125 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Alan L. Cox <alc at cs.rice.edu>
+ * Copyright (c) 1982, 1986, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/uio_machdep.c 266312 2014-05-17 13:59:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/sf_buf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <machine/vmparam.h>
+
+/*
+ * Implement uiomove(9) from physical memory using sf_bufs to
+ * avoid the creation and destruction of ephemeral mappings.
+ */
+int
+uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
+{
+ struct thread *td = curthread;
+ struct iovec *iov;
+ void *cp;
+ vm_offset_t page_offset;
+ size_t cnt;
+ int error = 0;
+ int save = 0;
+ struct sf_buf *sf;
+
+ KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
+ ("uiomove_fromphys: mode"));
+ KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
+ ("uiomove_fromphys proc"));
+ save = td->td_pflags & TDP_DEADLKTREAT;
+ td->td_pflags |= TDP_DEADLKTREAT;
+ while (n > 0 && uio->uio_resid) {
+ iov = uio->uio_iov;
+ cnt = iov->iov_len;
+ if (cnt == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ continue;
+ }
+ if (cnt > n)
+ cnt = n;
+ page_offset = offset & PAGE_MASK;
+ cnt = min(cnt, PAGE_SIZE - page_offset);
+ sf = sf_buf_alloc(ma[offset >> PAGE_SHIFT], 0);
+ cp = (char*)sf_buf_kva(sf) + page_offset;
+ switch (uio->uio_segflg) {
+ case UIO_USERSPACE:
+ maybe_yield();
+ if (uio->uio_rw == UIO_READ)
+ error = copyout(cp, iov->iov_base, cnt);
+ else
+ error = copyin(iov->iov_base, cp, cnt);
+ if (error) {
+ sf_buf_free(sf);
+ goto out;
+ }
+ break;
+ case UIO_SYSSPACE:
+ if (uio->uio_rw == UIO_READ)
+ bcopy(cp, iov->iov_base, cnt);
+ else
+ bcopy(iov->iov_base, cp, cnt);
+ break;
+ case UIO_NOCOPY:
+ break;
+ }
+ sf_buf_free(sf);
+ iov->iov_base = (char *)iov->iov_base + cnt;
+ iov->iov_len -= cnt;
+ uio->uio_resid -= cnt;
+ uio->uio_offset += cnt;
+ offset += cnt;
+ n -= cnt;
+ }
+out:
+ if (save == 0)
+ td->td_pflags &= ~TDP_DEADLKTREAT;
+ return (error);
+}
Property changes on: trunk/sys/arm/arm/uio_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/undefined.c
===================================================================
--- trunk/sys/arm/arm/undefined.c (rev 0)
+++ trunk/sys/arm/arm/undefined.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,295 @@
+/* $MidnightBSD$ */
+/* $NetBSD: undefined.c,v 1.22 2003/11/29 22:21:29 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ben Harris.
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * undefined.c
+ *
+ * Fault handler
+ *
+ * Created : 06/01/95
+ */
+
+
+#include "opt_ddb.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/undefined.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/signal.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/syslog.h>
+#include <sys/vmmeter.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/signalvar.h>
+#include <sys/ptrace.h>
+#ifdef KDB
+#include <sys/kdb.h>
+#endif
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+
+#include <machine/armreg.h>
+#include <machine/asm.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/undefined.h>
+#include <machine/trap.h>
+
+#include <machine/disassem.h>
+
+#ifdef DDB
+#include <ddb/db_output.h>
+#endif
+
+#ifdef KDB
+#include <machine/db_machdep.h>
+#endif
+
+static int gdb_trapper(u_int, u_int, struct trapframe *, int);
+
+LIST_HEAD(, undefined_handler) undefined_handlers[MAX_COPROCS];
+
+
+void *
+install_coproc_handler(int coproc, undef_handler_t handler)
+{
+ struct undefined_handler *uh;
+
+ KASSERT(coproc >= 0 && coproc < MAX_COPROCS, ("bad coproc"));
+ KASSERT(handler != NULL, ("handler is NULL")); /* Used to be legal. */
+
+ /* XXX: M_TEMP??? */
+ uh = malloc(sizeof(*uh), M_TEMP, M_WAITOK);
+ uh->uh_handler = handler;
+ install_coproc_handler_static(coproc, uh);
+ return uh;
+}
+
+void
+install_coproc_handler_static(int coproc, struct undefined_handler *uh)
+{
+
+ LIST_INSERT_HEAD(&undefined_handlers[coproc], uh, uh_link);
+}
+
+void
+remove_coproc_handler(void *cookie)
+{
+ struct undefined_handler *uh = cookie;
+
+ LIST_REMOVE(uh, uh_link);
+ free(uh, M_TEMP);
+}
+
+
+static int
+gdb_trapper(u_int addr, u_int insn, struct trapframe *frame, int code)
+{
+ struct thread *td;
+ ksiginfo_t ksi;
+
+ td = (curthread == NULL) ? &thread0 : curthread;
+
+ if (insn == GDB_BREAKPOINT || insn == GDB5_BREAKPOINT) {
+ if (code == FAULT_USER) {
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGTRAP;
+ ksi.ksi_code = TRAP_BRKPT;
+ ksi.ksi_addr = (u_int32_t *)addr;
+ trapsignal(td, &ksi);
+ return 0;
+ }
+#if 0
+#ifdef KGDB
+ return !kgdb_trap(T_BREAKPOINT, frame);
+#endif
+#endif
+ }
+ return 1;
+}
+
+static struct undefined_handler gdb_uh;
+
+void
+undefined_init()
+{
+ int loop;
+
+ /* Not actually necessary -- the initialiser is just NULL */
+ for (loop = 0; loop < MAX_COPROCS; ++loop)
+ LIST_INIT(&undefined_handlers[loop]);
+
+ /* Install handler for GDB breakpoints */
+ gdb_uh.uh_handler = gdb_trapper;
+ install_coproc_handler_static(0, &gdb_uh);
+}
+
+
+void
+undefinedinstruction(struct trapframe *frame)
+{
+ struct thread *td;
+ u_int fault_pc;
+ int fault_instruction;
+ int fault_code;
+ int coprocessor;
+ struct undefined_handler *uh;
+#ifdef VERBOSE_ARM32
+ int s;
+#endif
+ ksiginfo_t ksi;
+
+ /* Enable interrupts if they were enabled before the exception. */
+ if (__predict_true(frame->tf_spsr & PSR_I) == 0)
+ enable_interrupts(PSR_I);
+ if (__predict_true(frame->tf_spsr & PSR_F) == 0)
+ enable_interrupts(PSR_F);
+
+ PCPU_INC(cnt.v_trap);
+
+ fault_pc = frame->tf_pc;
+
+ /*
+ * Get the current thread/proc structure or thread0/proc0 if there is
+ * none.
+ */
+ td = curthread == NULL ? &thread0 : curthread;
+
+ /*
+ * Make sure the program counter is correctly aligned so we
+ * don't take an alignment fault trying to read the opcode.
+ */
+ if (__predict_false((fault_pc & 3) != 0)) {
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGILL;
+ ksi.ksi_code = ILL_ILLADR;
+ ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
+ trapsignal(td, &ksi);
+ userret(td, frame);
+ return;
+ }
+
+ /*
+ * Should use fuword() here .. but in the interests of squeezing every
+ * bit of speed we will just use ReadWord(). We know the instruction
+ * can be read as was just executed so this will never fail unless the
+ * kernel is screwed up in which case it does not really matter does
+ * it ?
+ */
+
+ fault_instruction = *(u_int32_t *)fault_pc;
+
+ /* Update vmmeter statistics */
+#if 0
+ uvmexp.traps++;
+#endif
+ /* Check for coprocessor instruction */
+
+ /*
+ * According to the datasheets you only need to look at bit 27 of the
+ * instruction to tell the difference between and undefined
+ * instruction and a coprocessor instruction following an undefined
+ * instruction trap.
+ */
+
+ coprocessor = 0;
+ if ((fault_instruction & (1 << 27)) != 0)
+ coprocessor = (fault_instruction >> 8) & 0x0f;
+#ifdef VFP
+ else { /* check for special instructions */
+ if (((fault_instruction & 0xfe000000) == 0xf2000000) ||
+ ((fault_instruction & 0xff100000) == 0xf4000000))
+ coprocessor = 10; /* vfp / simd */
+ }
+#endif /* VFP */
+
+ if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
+ /*
+ * Modify the fault_code to reflect the USR/SVC state at
+ * time of fault.
+ */
+ fault_code = FAULT_USER;
+ td->td_frame = frame;
+ } else
+ fault_code = 0;
+
+ /* OK this is were we do something about the instruction. */
+ LIST_FOREACH(uh, &undefined_handlers[coprocessor], uh_link)
+ if (uh->uh_handler(fault_pc, fault_instruction, frame,
+ fault_code) == 0)
+ break;
+
+ if (fault_code & FAULT_USER && fault_instruction == PTRACE_BREAKPOINT) {
+ PROC_LOCK(td->td_proc);
+ _PHOLD(td->td_proc);
+ ptrace_clear_single_step(td);
+ _PRELE(td->td_proc);
+ PROC_UNLOCK(td->td_proc);
+ return;
+ }
+
+ if (uh == NULL && (fault_code & FAULT_USER)) {
+ /* Fault has not been handled */
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGILL;
+ ksi.ksi_code = ILL_ILLOPC;
+ ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
+ trapsignal(td, &ksi);
+ }
+
+ if ((fault_code & FAULT_USER) == 0) {
+ if (fault_instruction == KERNEL_BREAKPOINT) {
+#ifdef KDB
+ kdb_trap(T_BREAKPOINT, 0, frame);
+#else
+ printf("No debugger in kernel.\n");
+#endif
+ return;
+ } else
+ panic("Undefined instruction in kernel.\n");
+ }
+
+ userret(td, frame);
+}
Property changes on: trunk/sys/arm/arm/undefined.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/vfp.c
===================================================================
--- trunk/sys/arm/arm/vfp.c (rev 0)
+++ trunk/sys/arm/arm/vfp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,303 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
+ * Copyright (c) 2012 Mark Tinguely
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/vfp.c 278646 2015-02-13 00:15:13Z ian $");
+
+#ifdef VFP
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/kernel.h>
+
+#include <machine/armreg.h>
+#include <machine/frame.h>
+#include <machine/fp.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/vfp.h>
+
+/* function prototypes */
+static int vfp_bounce(u_int, u_int, struct trapframe *, int);
+static void vfp_restore(struct vfp_state *);
+
+extern int vfp_exists;
+static struct undefined_handler vfp10_uh, vfp11_uh;
+/* If true the VFP unit has 32 double registers, otherwise it has 16 */
+static int is_d32;
+
+/*
+ * About .fpu directives in this file...
+ *
+ * We should need simply .fpu vfpv3, but clang 3.5 has a quirk where setting
+ * vfpv3 doesn't imply that vfp2 features are also available -- both have to be
+ * explicitly set to get all the features of both. This is probably a bug in
+ * clang, so it may get fixed and require changes here some day. Other changes
+ * are probably coming in clang too, because there is email and open PRs
+ * indicating they want to completely disable the ability to use .fpu and
+ * similar directives in inline asm. That would be catastrophic for us,
+ * hopefully they come to their senses. There was also some discusion of a new
+ * syntax such as .push fpu=vfpv3; ...; .pop fpu; and that would be ideal for
+ * us, better than what we have now really.
+ *
+ * For gcc, each .fpu directive completely overrides the prior directive, unlike
+ * with clang, but luckily on gcc saying v3 implies all the v2 features as well.
+ */
+
+#define fmxr(reg, val) \
+ __asm __volatile(" .fpu vfpv2\n .fpu vfpv3\n" \
+ " vmsr " __STRING(reg) ", %0" :: "r"(val));
+
+#define fmrx(reg) \
+({ u_int val = 0;\
+ __asm __volatile(" .fpu vfpv2\n .fpu vfpv3\n" \
+ " vmrs %0, " __STRING(reg) : "=r"(val)); \
+ val; \
+})
+
+static u_int
+get_coprocessorACR(void)
+{
+ u_int val;
+ __asm __volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (val) : : "cc");
+ return val;
+}
+
+static void
+set_coprocessorACR(u_int val)
+{
+ __asm __volatile("mcr p15, 0, %0, c1, c0, 2\n\t"
+ : : "r" (val) : "cc");
+ isb();
+}
+
+
+ /* called for each cpu */
+void
+vfp_init(void)
+{
+ u_int fpsid, fpexc, tmp;
+ u_int coproc, vfp_arch;
+
+ coproc = get_coprocessorACR();
+ coproc |= COPROC10 | COPROC11;
+ set_coprocessorACR(coproc);
+
+ fpsid = fmrx(fpsid); /* read the vfp system id */
+ fpexc = fmrx(fpexc); /* read the vfp exception reg */
+
+ if (!(fpsid & VFPSID_HARDSOFT_IMP)) {
+ vfp_exists = 1;
+ is_d32 = 0;
+ PCPU_SET(vfpsid, fpsid); /* save the fpsid */
+
+ vfp_arch =
+ (fpsid & VFPSID_SUBVERSION2_MASK) >> VFPSID_SUBVERSION_OFF;
+
+ if (vfp_arch >= VFP_ARCH3) {
+ tmp = fmrx(mvfr0);
+ PCPU_SET(vfpmvfr0, tmp);
+
+ if ((tmp & VMVFR0_RB_MASK) == 2)
+ is_d32 = 1;
+
+ tmp = fmrx(mvfr1);
+ PCPU_SET(vfpmvfr1, tmp);
+ }
+
+ /* initialize the coprocess 10 and 11 calls
+ * These are called to restore the registers and enable
+ * the VFP hardware.
+ */
+ if (vfp10_uh.uh_handler == NULL) {
+ vfp10_uh.uh_handler = vfp_bounce;
+ vfp11_uh.uh_handler = vfp_bounce;
+ install_coproc_handler_static(10, &vfp10_uh);
+ install_coproc_handler_static(11, &vfp11_uh);
+ }
+ }
+}
+
+SYSINIT(vfp, SI_SUB_CPU, SI_ORDER_ANY, vfp_init, NULL);
+
+
+/* start VFP unit, restore the vfp registers from the PCB and retry
+ * the instruction
+ */
+static int
+vfp_bounce(u_int addr, u_int insn, struct trapframe *frame, int code)
+{
+ u_int cpu, fpexc;
+ struct pcb *curpcb;
+ ksiginfo_t ksi;
+
+ if ((code & FAULT_USER) == 0)
+ panic("undefined floating point instruction in supervisor mode");
+
+ critical_enter();
+
+ /*
+ * If the VFP is already on and we got an undefined instruction, then
+ * something tried to executate a truly invalid instruction that maps to
+ * the VFP.
+ */
+ fpexc = fmrx(fpexc);
+ if (fpexc & VFPEXC_EN) {
+ /* Clear any exceptions */
+ fmxr(fpexc, fpexc & ~(VFPEXC_EX | VFPEXC_FP2V));
+
+ /* kill the process - we do not handle emulation */
+ critical_exit();
+
+ if (fpexc & VFPEXC_EX) {
+ /* We have an exception, signal a SIGFPE */
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGFPE;
+ if (fpexc & VFPEXC_UFC)
+ ksi.ksi_code = FPE_FLTUND;
+ else if (fpexc & VFPEXC_OFC)
+ ksi.ksi_code = FPE_FLTOVF;
+ else if (fpexc & VFPEXC_IOC)
+ ksi.ksi_code = FPE_FLTINV;
+ ksi.ksi_addr = (void *)addr;
+ trapsignal(curthread, &ksi);
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /*
+ * If the last time this thread used the VFP it was on this core, and
+ * the last thread to use the VFP on this core was this thread, then the
+ * VFP state is valid, otherwise restore this thread's state to the VFP.
+ */
+ fmxr(fpexc, fpexc | VFPEXC_EN);
+ curpcb = curthread->td_pcb;
+ cpu = PCPU_GET(cpu);
+ if (curpcb->pcb_vfpcpu != cpu || curthread != PCPU_GET(fpcurthread)) {
+ vfp_restore(&curpcb->pcb_vfpstate);
+ curpcb->pcb_vfpcpu = cpu;
+ PCPU_SET(fpcurthread, curthread);
+ }
+
+ critical_exit();
+ return (0);
+}
+
+/*
+ * Restore the given state to the VFP hardware.
+ */
+static void
+vfp_restore(struct vfp_state *vfpsave)
+{
+ uint32_t fpexc;
+
+ /* On vfpv3 we may need to restore FPINST and FPINST2 */
+ fpexc = vfpsave->fpexec;
+ if (fpexc & VFPEXC_EX) {
+ fmxr(fpinst, vfpsave->fpinst);
+ if (fpexc & VFPEXC_FP2V)
+ fmxr(fpinst2, vfpsave->fpinst2);
+ }
+ fmxr(fpscr, vfpsave->fpscr);
+
+ __asm __volatile(
+ " .fpu vfpv2\n"
+ " .fpu vfpv3\n"
+ " vldmia %0!, {d0-d15}\n" /* d0-d15 */
+ " cmp %1, #0\n" /* -D16 or -D32? */
+ " vldmiane %0!, {d16-d31}\n" /* d16-d31 */
+ " addeq %0, %0, #128\n" /* skip missing regs */
+ : "+&r" (vfpsave) : "r" (is_d32) : "cc"
+ );
+
+ fmxr(fpexc, fpexc);
+}
+
+/*
+ * If the VFP is on, save its current state and turn it off if requested to do
+ * so. If the VFP is not on, does not change the values at *vfpsave. Caller is
+ * responsible for preventing a context switch while this is running.
+ */
+void
+vfp_store(struct vfp_state *vfpsave, boolean_t disable_vfp)
+{
+ uint32_t fpexc;
+
+ fpexc = fmrx(fpexc); /* Is the vfp enabled? */
+ if (fpexc & VFPEXC_EN) {
+ vfpsave->fpexec = fpexc;
+ vfpsave->fpscr = fmrx(fpscr);
+
+ /* On vfpv3 we may need to save FPINST and FPINST2 */
+ if (fpexc & VFPEXC_EX) {
+ vfpsave->fpinst = fmrx(fpinst);
+ if (fpexc & VFPEXC_FP2V)
+ vfpsave->fpinst2 = fmrx(fpinst2);
+ fpexc &= ~VFPEXC_EX;
+ }
+
+ __asm __volatile(
+ " .fpu vfpv2\n"
+ " .fpu vfpv3\n"
+ " vstmia %0!, {d0-d15}\n" /* d0-d15 */
+ " cmp %1, #0\n" /* -D16 or -D32? */
+ " vstmiane r0!, {d16-d31}\n" /* d16-d31 */
+ " addeq %0, %0, #128\n" /* skip missing regs */
+ : "+&r" (vfpsave) : "r" (is_d32) : "cc"
+ );
+
+ if (disable_vfp)
+ fmxr(fpexc , fpexc & ~VFPEXC_EN);
+ }
+}
+
+/*
+ * The current thread is dying. If the state currently in the hardware belongs
+ * to the current thread, set fpcurthread to NULL to indicate that the VFP
+ * hardware state does not belong to any thread. If the VFP is on, turn it off.
+ * Called only from cpu_throw(), so we don't have to worry about a context
+ * switch here.
+ */
+void
+vfp_discard(struct thread *td)
+{
+ u_int tmp;
+
+ if (PCPU_GET(fpcurthread) == td)
+ PCPU_SET(fpcurthread, NULL);
+
+ tmp = fmrx(fpexc);
+ if (tmp & VFPEXC_EN)
+ fmxr(fpexc, tmp & ~VFPEXC_EN);
+}
+
+#endif
+
Property changes on: trunk/sys/arm/arm/vfp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/arm/vm_machdep.c
===================================================================
--- trunk/sys/arm/arm/vm_machdep.c (rev 0)
+++ trunk/sys/arm/arm/vm_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,484 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * Copyright (c) 1989, 1990 William Jolitz
+ * Copyright (c) 1994 John Dyson
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department, and William Jolitz.
+ *
+ * Redistribution and use in source and binary :forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
+ * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/arm/vm_machdep.c 283339 2015-05-23 23:27:00Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/proc.h>
+#include <sys/socketvar.h>
+#include <sys/sf_buf.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/unistd.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/sysarch.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_param.h>
+#include <vm/vm_pageout.h>
+#include <vm/uma.h>
+#include <vm/uma_int.h>
+
+#include <machine/md_var.h>
+#include <machine/vfp.h>
+
+/*
+ * struct switchframe and trapframe must both be a multiple of 8
+ * for correct stack alignment.
+ */
+CTASSERT(sizeof(struct switchframe) == 48);
+CTASSERT(sizeof(struct trapframe) == 80);
+
+#ifndef NSFBUFS
+#define NSFBUFS (512 + maxusers * 16)
+#endif
+
+static int nsfbufs;
+static int nsfbufspeak;
+static int nsfbufsused;
+
+SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufs, CTLFLAG_RDTUN, &nsfbufs, 0,
+ "Maximum number of sendfile(2) sf_bufs available");
+SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufspeak, CTLFLAG_RD, &nsfbufspeak, 0,
+ "Number of sendfile(2) sf_bufs at peak usage");
+SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0,
+ "Number of sendfile(2) sf_bufs in use");
+
+static void sf_buf_init(void *arg);
+SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL);
+
+LIST_HEAD(sf_head, sf_buf);
+
+/*
+ * A hash table of active sendfile(2) buffers
+ */
+static struct sf_head *sf_buf_active;
+static u_long sf_buf_hashmask;
+
+#define SF_BUF_HASH(m) (((m) - vm_page_array) & sf_buf_hashmask)
+
+static TAILQ_HEAD(, sf_buf) sf_buf_freelist;
+static u_int sf_buf_alloc_want;
+
+/*
+ * A lock used to synchronize access to the hash table and free list
+ */
+static struct mtx sf_buf_lock;
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the pcb, set up the stack so that the child
+ * ready to run and return to user mode.
+ */
+void
+cpu_fork(register struct thread *td1, register struct proc *p2,
+ struct thread *td2, int flags)
+{
+ struct pcb *pcb2;
+ struct trapframe *tf;
+ struct mdproc *mdp2;
+
+ if ((flags & RFPROC) == 0)
+ return;
+
+ /* Point the pcb to the top of the stack */
+ pcb2 = (struct pcb *)
+ (td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1;
+#ifdef __XSCALE__
+#ifndef CPU_XSCALE_CORE3
+ pmap_use_minicache(td2->td_kstack, td2->td_kstack_pages * PAGE_SIZE);
+#endif
+#endif
+ td2->td_pcb = pcb2;
+
+ /* Clone td1's pcb */
+ bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
+
+ /* Point to mdproc and then copy over td1's contents */
+ mdp2 = &p2->p_md;
+ bcopy(&td1->td_proc->p_md, mdp2, sizeof(*mdp2));
+
+ /* Point the frame to the stack in front of pcb and copy td1's frame */
+ td2->td_frame = (struct trapframe *)pcb2 - 1;
+ *td2->td_frame = *td1->td_frame;
+
+ /*
+ * Create a new fresh stack for the new process.
+ * Copy the trap frame for the return to user mode as if from a
+ * syscall. This copies most of the user mode register values.
+ */
+ pmap_set_pcb_pagedir(vmspace_pmap(p2->p_vmspace), pcb2);
+ pcb2->pcb_regs.sf_r4 = (register_t)fork_return;
+ pcb2->pcb_regs.sf_r5 = (register_t)td2;
+ pcb2->pcb_regs.sf_lr = (register_t)fork_trampoline;
+ pcb2->pcb_regs.sf_sp = STACKALIGN(td2->td_frame);
+
+ pcb2->pcb_vfpcpu = -1;
+ pcb2->pcb_vfpstate.fpscr = VFPSCR_DN | VFPSCR_FZ;
+
+ tf = td2->td_frame;
+ tf->tf_spsr &= ~PSR_C;
+ tf->tf_r0 = 0;
+ tf->tf_r1 = 0;
+
+
+ /* Setup to release spin count in fork_exit(). */
+ td2->td_md.md_spinlock_count = 1;
+ td2->td_md.md_saved_cspr = PSR_SVC32_MODE;;
+#ifdef ARM_TP_ADDRESS
+ td2->td_md.md_tp = *(register_t *)ARM_TP_ADDRESS;
+#else
+ td2->td_md.md_tp = td1->td_md.md_tp;
+#endif
+}
+
+void
+cpu_thread_swapin(struct thread *td)
+{
+}
+
+void
+cpu_thread_swapout(struct thread *td)
+{
+}
+
+/*
+ * Detatch mapped page and release resources back to the system.
+ */
+void
+sf_buf_free(struct sf_buf *sf)
+{
+
+ mtx_lock(&sf_buf_lock);
+ sf->ref_count--;
+ if (sf->ref_count == 0) {
+ TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry);
+ nsfbufsused--;
+ pmap_kremove(sf->kva);
+ sf->m = NULL;
+ LIST_REMOVE(sf, list_entry);
+ if (sf_buf_alloc_want > 0)
+ wakeup(&sf_buf_freelist);
+ }
+ mtx_unlock(&sf_buf_lock);
+}
+
+/*
+ * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-))
+ */
+static void
+sf_buf_init(void *arg)
+{
+ struct sf_buf *sf_bufs;
+ vm_offset_t sf_base;
+ int i;
+
+ nsfbufs = NSFBUFS;
+ TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs);
+
+ sf_buf_active = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask);
+ TAILQ_INIT(&sf_buf_freelist);
+ sf_base = kva_alloc(nsfbufs * PAGE_SIZE);
+ sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP,
+ M_NOWAIT | M_ZERO);
+ for (i = 0; i < nsfbufs; i++) {
+ sf_bufs[i].kva = sf_base + i * PAGE_SIZE;
+ TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry);
+ }
+ sf_buf_alloc_want = 0;
+ mtx_init(&sf_buf_lock, "sf_buf", NULL, MTX_DEF);
+}
+
+/*
+ * Get an sf_buf from the freelist. Will block if none are available.
+ */
+struct sf_buf *
+sf_buf_alloc(struct vm_page *m, int flags)
+{
+ struct sf_head *hash_list;
+ struct sf_buf *sf;
+ int error;
+
+ hash_list = &sf_buf_active[SF_BUF_HASH(m)];
+ mtx_lock(&sf_buf_lock);
+ LIST_FOREACH(sf, hash_list, list_entry) {
+ if (sf->m == m) {
+ sf->ref_count++;
+ if (sf->ref_count == 1) {
+ TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
+ nsfbufsused++;
+ nsfbufspeak = imax(nsfbufspeak, nsfbufsused);
+ }
+ goto done;
+ }
+ }
+ while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) {
+ if (flags & SFB_NOWAIT)
+ goto done;
+ sf_buf_alloc_want++;
+ SFSTAT_INC(sf_allocwait);
+ error = msleep(&sf_buf_freelist, &sf_buf_lock,
+ (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0);
+ sf_buf_alloc_want--;
+
+
+ /*
+ * If we got a signal, don't risk going back to sleep.
+ */
+ if (error)
+ goto done;
+ }
+ TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
+ if (sf->m != NULL)
+ LIST_REMOVE(sf, list_entry);
+ LIST_INSERT_HEAD(hash_list, sf, list_entry);
+ sf->ref_count = 1;
+ sf->m = m;
+ nsfbufsused++;
+ nsfbufspeak = imax(nsfbufspeak, nsfbufsused);
+ pmap_kenter(sf->kva, VM_PAGE_TO_PHYS(sf->m));
+done:
+ mtx_unlock(&sf_buf_lock);
+ return (sf);
+}
+
+void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+ struct trapframe *frame;
+ int fixup;
+#ifdef __ARMEB__
+ u_int call;
+#endif
+
+ frame = td->td_frame;
+ fixup = 0;
+
+#ifdef __ARMEB__
+ /*
+ * __syscall returns an off_t while most other syscalls return an
+ * int. As an off_t is 64-bits and an int is 32-bits we need to
+ * place the returned data into r1. As the lseek and frerebsd6_lseek
+ * syscalls also return an off_t they do not need this fixup.
+ */
+#ifdef __ARM_EABI__
+ call = frame->tf_r7;
+#else
+ call = *(u_int32_t *)(frame->tf_pc - INSN_SIZE) & 0x000fffff;
+#endif
+ if (call == SYS___syscall) {
+ register_t *ap = &frame->tf_r0;
+ register_t code = ap[_QUAD_LOWWORD];
+ if (td->td_proc->p_sysent->sv_mask)
+ code &= td->td_proc->p_sysent->sv_mask;
+ fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek)
+ ? 1 : 0;
+ }
+#endif
+
+ switch (error) {
+ case 0:
+ if (fixup) {
+ frame->tf_r0 = 0;
+ frame->tf_r1 = td->td_retval[0];
+ } else {
+ frame->tf_r0 = td->td_retval[0];
+ frame->tf_r1 = td->td_retval[1];
+ }
+ frame->tf_spsr &= ~PSR_C; /* carry bit */
+ break;
+ case ERESTART:
+ /*
+ * Reconstruct the pc to point at the swi.
+ */
+ frame->tf_pc -= INSN_SIZE;
+ break;
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+ default:
+ frame->tf_r0 = error;
+ frame->tf_spsr |= PSR_C; /* carry bit */
+ break;
+ }
+}
+
+/*
+ * Initialize machine state (pcb and trap frame) for a new thread about to
+ * upcall. Put enough state in the new thread's PCB to get it to go back
+ * userret(), where we can intercept it again to set the return (upcall)
+ * Address and stack, along with those from upcals that are from other sources
+ * such as those generated in thread_userret() itself.
+ */
+void
+cpu_set_upcall(struct thread *td, struct thread *td0)
+{
+
+ bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
+ bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb));
+
+ td->td_pcb->pcb_regs.sf_r4 = (register_t)fork_return;
+ td->td_pcb->pcb_regs.sf_r5 = (register_t)td;
+ td->td_pcb->pcb_regs.sf_lr = (register_t)fork_trampoline;
+ td->td_pcb->pcb_regs.sf_sp = STACKALIGN(td->td_frame);
+
+ td->td_frame->tf_spsr &= ~PSR_C;
+ td->td_frame->tf_r0 = 0;
+
+ /* Setup to release spin count in fork_exit(). */
+ td->td_md.md_spinlock_count = 1;
+ td->td_md.md_saved_cspr = PSR_SVC32_MODE;
+}
+
+/*
+ * Set that machine state for performing an upcall that has to
+ * be done in thread_userret() so that those upcalls generated
+ * in thread_userret() itself can be done as well.
+ */
+void
+cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
+ stack_t *stack)
+{
+ struct trapframe *tf = td->td_frame;
+
+ tf->tf_usr_sp = STACKALIGN((int)stack->ss_sp + stack->ss_size);
+ tf->tf_pc = (int)entry;
+ tf->tf_r0 = (int)arg;
+ tf->tf_spsr = PSR_USR32_MODE;
+}
+
+int
+cpu_set_user_tls(struct thread *td, void *tls_base)
+{
+
+ td->td_md.md_tp = (register_t)tls_base;
+ if (td == curthread) {
+ critical_enter();
+#ifdef ARM_TP_ADDRESS
+ *(register_t *)ARM_TP_ADDRESS = (register_t)tls_base;
+#else
+ set_tls(tls_base);
+#endif
+ critical_exit();
+ }
+ return (0);
+}
+
+void
+cpu_thread_exit(struct thread *td)
+{
+}
+
+void
+cpu_thread_alloc(struct thread *td)
+{
+ td->td_pcb = (struct pcb *)(td->td_kstack + td->td_kstack_pages *
+ PAGE_SIZE) - 1;
+ /*
+ * Ensure td_frame is aligned to an 8 byte boundary as it will be
+ * placed into the stack pointer which must be 8 byte aligned in
+ * the ARM EABI.
+ */
+ td->td_frame = (struct trapframe *)((caddr_t)td->td_pcb) - 1;
+
+#ifdef __XSCALE__
+#ifndef CPU_XSCALE_CORE3
+ pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE);
+#endif
+#endif
+}
+
+void
+cpu_thread_free(struct thread *td)
+{
+}
+
+void
+cpu_thread_clean(struct thread *td)
+{
+}
+
+/*
+ * Intercept the return address from a freshly forked process that has NOT
+ * been scheduled yet.
+ *
+ * This is needed to make kernel threads stay in kernel mode.
+ */
+void
+cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg)
+{
+ td->td_pcb->pcb_regs.sf_r4 = (register_t)func; /* function */
+ td->td_pcb->pcb_regs.sf_r5 = (register_t)arg; /* first arg */
+}
+
+/*
+ * Software interrupt handler for queued VM system processing.
+ */
+void
+swi_vm(void *dummy)
+{
+
+ if (busdma_swi_pending)
+ busdma_swi();
+}
+
+void
+cpu_exit(struct thread *td)
+{
+}
+
Property changes on: trunk/sys/arm/arm/vm_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91.c
===================================================================
--- trunk/sys/arm/at91/at91.c (rev 0)
+++ trunk/sys/arm/at91/at91.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,529 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+
+#include <machine/armreg.h>
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/intr.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_aicreg.h>
+
+uint32_t at91_master_clock;
+
+static int
+at91_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ vm_paddr_t pa, endpa;
+
+ pa = trunc_page(bpa);
+ if (pa >= AT91_PA_BASE + 0xff00000) {
+ *bshp = bpa - AT91_PA_BASE + AT91_BASE;
+ return (0);
+ }
+ if (pa >= AT91_BASE + 0xff00000) {
+ *bshp = bpa;
+ return (0);
+ }
+ endpa = round_page(bpa + size);
+
+ *bshp = (vm_offset_t)pmap_mapdev(pa, endpa - pa) + (bpa - pa);
+
+ return (0);
+}
+
+static void
+at91_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
+{
+ vm_offset_t va;
+
+ va = (vm_offset_t)h;
+ if (va >= AT91_BASE && va <= AT91_BASE + 0xff00000)
+ return;
+ pmap_unmapdev(va, size);
+}
+
+static int
+at91_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t size, bus_space_handle_t *nbshp)
+{
+
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+static void
+at91_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size, bus_size_t b,
+ int a)
+{
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+ return (0);
+}
+
+bs_protos(generic);
+
+struct bus_space at91_bs_tag = {
+ /* privdata is whatever the implementer wants; unused in base tag */
+ .bs_privdata = NULL,
+
+ /* mapping/unmapping */
+ .bs_map = at91_bs_map,
+ .bs_unmap = at91_bs_unmap,
+ .bs_subregion = at91_bs_subregion,
+
+ /* allocation/deallocation */
+ .bs_alloc = generic_bs_alloc,
+ .bs_free = generic_bs_free,
+
+ /* barrier */
+ .bs_barrier = at91_barrier,
+
+ /* read (single) */
+ .bs_r_1 = NULL, /* Use inline code in bus.h */
+ .bs_r_2 = NULL, /* Use inline code in bus.h */
+ .bs_r_4 = NULL, /* Use inline code in bus.h */
+ .bs_r_8 = NULL, /* Use inline code in bus.h */
+
+ /* read multiple */
+ .bs_rm_1 = generic_bs_rm_1,
+ .bs_rm_2 = generic_bs_rm_2,
+ .bs_rm_4 = generic_bs_rm_4,
+ .bs_rm_8 = BS_UNIMPLEMENTED,
+
+ /* read region */
+ .bs_rr_1 = generic_bs_rr_1,
+ .bs_rr_2 = generic_bs_rr_2,
+ .bs_rr_4 = generic_bs_rr_4,
+ .bs_rr_8 = BS_UNIMPLEMENTED,
+
+ /* write (single) */
+ .bs_w_1 = NULL, /* Use inline code in bus.h */
+ .bs_w_2 = NULL, /* Use inline code in bus.h */
+ .bs_w_4 = NULL, /* Use inline code in bus.h */
+ .bs_w_8 = NULL, /* Use inline code in bus.h */
+
+ /* write multiple */
+ .bs_wm_1 = generic_bs_wm_1,
+ .bs_wm_2 = generic_bs_wm_2,
+ .bs_wm_4 = generic_bs_wm_4,
+ .bs_wm_8 = BS_UNIMPLEMENTED,
+
+ /* write region */
+ .bs_wr_1 = generic_bs_wr_1,
+ .bs_wr_2 = generic_bs_wr_2,
+ .bs_wr_4 = generic_bs_wr_4,
+ .bs_wr_8 = BS_UNIMPLEMENTED,
+
+ /* set multiple */
+ .bs_sm_1 = BS_UNIMPLEMENTED,
+ .bs_sm_2 = BS_UNIMPLEMENTED,
+ .bs_sm_4 = BS_UNIMPLEMENTED,
+ .bs_sm_8 = BS_UNIMPLEMENTED,
+
+ /* set region */
+ .bs_sr_1 = generic_bs_sr_1,
+ .bs_sr_2 = generic_bs_sr_2,
+ .bs_sr_4 = generic_bs_sr_4,
+ .bs_sr_8 = BS_UNIMPLEMENTED,
+
+ /* copy */
+ .bs_c_1 = BS_UNIMPLEMENTED,
+ .bs_c_2 = generic_bs_c_2,
+ .bs_c_4 = BS_UNIMPLEMENTED,
+ .bs_c_8 = BS_UNIMPLEMENTED,
+
+ /* read stream (single) */
+ .bs_r_1_s = NULL, /* Use inline code in bus.h */
+ .bs_r_2_s = NULL, /* Use inline code in bus.h */
+ .bs_r_4_s = NULL, /* Use inline code in bus.h */
+ .bs_r_8_s = NULL, /* Use inline code in bus.h */
+
+ /* read multiple stream */
+ .bs_rm_1_s = generic_bs_rm_1,
+ .bs_rm_2_s = generic_bs_rm_2,
+ .bs_rm_4_s = generic_bs_rm_4,
+ .bs_rm_8_s = BS_UNIMPLEMENTED,
+
+ /* read region stream */
+ .bs_rr_1_s = generic_bs_rr_1,
+ .bs_rr_2_s = generic_bs_rr_2,
+ .bs_rr_4_s = generic_bs_rr_4,
+ .bs_rr_8_s = BS_UNIMPLEMENTED,
+
+ /* write stream (single) */
+ .bs_w_1_s = NULL, /* Use inline code in bus.h */
+ .bs_w_2_s = NULL, /* Use inline code in bus.h */
+ .bs_w_4_s = NULL, /* Use inline code in bus.h */
+ .bs_w_8_s = NULL, /* Use inline code in bus.h */
+
+ /* write multiple stream */
+ .bs_wm_1_s = generic_bs_wm_1,
+ .bs_wm_2_s = generic_bs_wm_2,
+ .bs_wm_4_s = generic_bs_wm_4,
+ .bs_wm_8_s = BS_UNIMPLEMENTED,
+
+ /* write region stream */
+ .bs_wr_1_s = generic_bs_wr_1,
+ .bs_wr_2_s = generic_bs_wr_2,
+ .bs_wr_4_s = generic_bs_wr_4,
+ .bs_wr_8_s = BS_UNIMPLEMENTED,
+};
+
+#ifndef FDT
+
+static struct at91_softc *at91_softc;
+
+static void at91_eoi(void *);
+
+static int
+at91_probe(device_t dev)
+{
+
+ device_set_desc(dev, soc_info.name);
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+static void
+at91_identify(driver_t *drv, device_t parent)
+{
+
+ BUS_ADD_CHILD(parent, 0, "atmelarm", 0);
+}
+
+static void
+at91_cpu_add_builtin_children(device_t dev, const struct cpu_devs *walker)
+{
+ int i;
+
+ for (i = 1; walker->name; i++, walker++) {
+ at91_add_child(dev, i, walker->name, walker->unit,
+ walker->mem_base, walker->mem_len, walker->irq0,
+ walker->irq1, walker->irq2);
+ }
+}
+
+static int
+at91_attach(device_t dev)
+{
+ struct at91_softc *sc = device_get_softc(dev);
+
+ arm_post_filter = at91_eoi;
+
+ at91_softc = sc;
+ sc->sc_st = &at91_bs_tag;
+ sc->sc_sh = AT91_BASE;
+ sc->sc_aic_sh = AT91_BASE + AT91_SYS_BASE;
+ sc->dev = dev;
+
+ sc->sc_irq_rman.rm_type = RMAN_ARRAY;
+ sc->sc_irq_rman.rm_descr = "AT91 IRQs";
+ if (rman_init(&sc->sc_irq_rman) != 0 ||
+ rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
+ panic("at91_attach: failed to set up IRQ rman");
+
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "AT91 Memory";
+ if (rman_init(&sc->sc_mem_rman) != 0)
+ panic("at91_attach: failed to set up memory rman");
+ /*
+ * Manage the physical space, defined as being everything that isn't
+ * DRAM.
+ */
+ if (rman_manage_region(&sc->sc_mem_rman, 0, PHYSADDR - 1) != 0)
+ panic("at91_attach: failed to set up memory rman");
+ if (rman_manage_region(&sc->sc_mem_rman, PHYSADDR + (256 << 20),
+ 0xfffffffful) != 0)
+ panic("at91_attach: failed to set up memory rman");
+
+ /*
+ * Add this device's children...
+ */
+ at91_cpu_add_builtin_children(dev, soc_info.soc_data->soc_children);
+ soc_info.soc_data->soc_clock_init();
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+ enable_interrupts(PSR_I | PSR_F);
+ return (0);
+}
+
+static struct resource *
+at91_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct at91_softc *sc = device_get_softc(dev);
+ struct resource_list_entry *rle;
+ struct at91_ivar *ivar = device_get_ivars(child);
+ struct resource_list *rl = &ivar->resources;
+ bus_space_handle_t bsh;
+
+ if (device_get_parent(child) != dev)
+ return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+ type, rid, start, end, count, flags));
+
+ rle = resource_list_find(rl, type, *rid);
+ if (rle == NULL)
+ return (NULL);
+ if (rle->res)
+ panic("Resource rid %d type %d already in use", *rid, type);
+ if (start == 0UL && end == ~0UL) {
+ start = rle->start;
+ count = ulmax(count, rle->count);
+ end = ulmax(rle->end, start + count - 1);
+ }
+ switch (type)
+ {
+ case SYS_RES_IRQ:
+ rle->res = rman_reserve_resource(&sc->sc_irq_rman,
+ start, end, count, flags, child);
+ break;
+ case SYS_RES_MEMORY:
+ rle->res = rman_reserve_resource(&sc->sc_mem_rman,
+ start, end, count, flags, child);
+ if (rle->res != NULL) {
+ bus_space_map(&at91_bs_tag, start,
+ rman_get_size(rle->res), 0, &bsh);
+ rman_set_bustag(rle->res, &at91_bs_tag);
+ rman_set_bushandle(rle->res, bsh);
+ }
+ break;
+ }
+ if (rle->res) {
+ rle->start = rman_get_start(rle->res);
+ rle->end = rman_get_end(rle->res);
+ rle->count = count;
+ rman_set_rid(rle->res, *rid);
+ }
+ return (rle->res);
+}
+
+static struct resource_list *
+at91_get_resource_list(device_t dev, device_t child)
+{
+ struct at91_ivar *ivar;
+
+ ivar = device_get_ivars(child);
+ return (&(ivar->resources));
+}
+
+static int
+at91_release_resource(device_t dev, device_t child, int type,
+ int rid, struct resource *r)
+{
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+
+ rl = at91_get_resource_list(dev, child);
+ if (rl == NULL)
+ return (EINVAL);
+ rle = resource_list_find(rl, type, rid);
+ if (rle == NULL)
+ return (EINVAL);
+ rman_release_resource(r);
+ rle->res = NULL;
+ return (0);
+}
+
+static int
+at91_setup_intr(device_t dev, device_t child,
+ struct resource *ires, int flags, driver_filter_t *filt,
+ driver_intr_t *intr, void *arg, void **cookiep)
+{
+ int error;
+
+ if (rman_get_start(ires) == AT91_IRQ_SYSTEM && filt == NULL)
+ panic("All system interrupt ISRs must be FILTER");
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ filt, intr, arg, cookiep);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static int
+at91_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ struct at91_softc *sc = device_get_softc(dev);
+
+ bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR,
+ 1 << rman_get_start(res));
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
+static int
+at91_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+#if 0
+ u_long p;
+ int error;
+
+ if (type == SYS_RES_MEMORY) {
+ error = bus_space_map(rman_get_bustag(r),
+ rman_get_bushandle(r), rman_get_size(r), 0, &p);
+ if (error)
+ return (error);
+ rman_set_bushandle(r, p);
+ }
+#endif
+ return (rman_activate_resource(r));
+}
+
+static int
+at91_print_child(device_t dev, device_t child)
+{
+ struct at91_ivar *ivars;
+ struct resource_list *rl;
+ int retval = 0;
+
+ ivars = device_get_ivars(child);
+ rl = &ivars->resources;
+
+ retval += bus_print_child_header(dev, child);
+
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ if (device_get_flags(dev))
+ retval += printf(" flags %#x", device_get_flags(dev));
+
+ retval += bus_print_child_footer(dev, child);
+
+ return (retval);
+}
+
+static void
+at91_eoi(void *unused)
+{
+ bus_space_write_4(at91_softc->sc_st, at91_softc->sc_aic_sh,
+ IC_EOICR, 0);
+}
+
+void
+at91_add_child(device_t dev, int prio, const char *name, int unit,
+ bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2)
+{
+ device_t kid;
+ struct at91_ivar *ivar;
+
+ kid = device_add_child_ordered(dev, prio, name, unit);
+ if (kid == NULL) {
+ printf("Can't add child %s%d ordered\n", name, unit);
+ return;
+ }
+ ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (ivar == NULL) {
+ device_delete_child(dev, kid);
+ printf("Can't add alloc ivar\n");
+ return;
+ }
+ device_set_ivars(kid, ivar);
+ resource_list_init(&ivar->resources);
+ if (irq0 != -1) {
+ bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
+ if (irq0 != AT91_IRQ_SYSTEM)
+ at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0);
+ }
+ if (irq1 != 0)
+ bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
+ if (irq2 != 0)
+ bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
+ /*
+ * Special case for on-board devices. These have their address
+ * defined relative to AT91_PA_BASE in all the register files we
+ * have. We could change this, but that's a lot of effort which
+ * will be obsoleted when FDT arrives.
+ */
+ if (addr != 0 && addr < 0x10000000 && addr >= 0x0f000000)
+ addr += AT91_PA_BASE;
+ if (addr != 0)
+ bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
+}
+
+static device_method_t at91_methods[] = {
+ DEVMETHOD(device_probe, at91_probe),
+ DEVMETHOD(device_attach, at91_attach),
+ DEVMETHOD(device_identify, at91_identify),
+
+ DEVMETHOD(bus_alloc_resource, at91_alloc_resource),
+ DEVMETHOD(bus_setup_intr, at91_setup_intr),
+ DEVMETHOD(bus_teardown_intr, at91_teardown_intr),
+ DEVMETHOD(bus_activate_resource, at91_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_get_resource_list,at91_get_resource_list),
+ DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_release_resource, at91_release_resource),
+ DEVMETHOD(bus_print_child, at91_print_child),
+
+ {0, 0},
+};
+
+static driver_t at91_driver = {
+ "atmelarm",
+ at91_methods,
+ sizeof(struct at91_softc),
+};
+
+static devclass_t at91_devclass;
+
+DRIVER_MODULE(atmelarm, nexus, at91_driver, at91_devclass, 0, 0);
+#endif
Property changes on: trunk/sys/arm/at91/at91.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_aic.c
===================================================================
--- trunk/sys/arm/at91/at91_aic.c (rev 0)
+++ trunk/sys/arm/at91/at91_aic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,190 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_aic.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+#include <machine/resource.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_aicreg.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+static struct aic_softc {
+ struct resource *mem_res; /* Memory resource */
+ void *intrhand; /* Interrupt handle */
+ device_t sc_dev;
+} *sc;
+
+static inline uint32_t
+RD4(struct aic_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct aic_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+
+ WR4(sc, IC_IDCR, 1 << nb);
+}
+
+int
+arm_get_next_irq(int last __unused)
+{
+ int status;
+ int irq;
+
+ irq = RD4(sc, IC_IVR);
+ status = RD4(sc, IC_ISR);
+ if (status == 0) {
+ WR4(sc, IC_EOICR, 1);
+ return (-1);
+ }
+ return (irq);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+
+ WR4(sc, IC_IECR, 1 << nb);
+ WR4(sc, IC_EOICR, 0);
+}
+
+static int
+at91_aic_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-aic"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "AIC");
+ return (0);
+}
+
+static int
+at91_aic_attach(device_t dev)
+{
+ int i, rid, err = 0;
+
+ device_printf(dev, "Attach %d\n", bus_current_pass);
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+
+ if (sc->mem_res == NULL)
+ panic("couldn't allocate register resources");
+
+ /*
+ * Setup the interrupt table.
+ */
+ if (soc_info.soc_data == NULL || soc_info.soc_data->soc_irq_prio == NULL)
+ panic("Interrupt priority table missing\n");
+ for (i = 0; i < 32; i++) {
+ WR4(sc, IC_SVR + i * 4, i);
+ /* Priority. */
+ WR4(sc, IC_SMR + i * 4, soc_info.soc_data->soc_irq_prio[i]);
+ if (i < 8)
+ WR4(sc, IC_EOICR, 1);
+ }
+
+ WR4(sc, IC_SPU, 32);
+ /* No debug. */
+ WR4(sc, IC_DCR, 0);
+ /* Disable and clear all interrupts. */
+ WR4(sc, IC_IDCR, 0xffffffff);
+ WR4(sc, IC_ICCR, 0xffffffff);
+ enable_interrupts(PSR_I | PSR_F);
+
+ return (err);
+}
+
+static void
+at91_aic_new_pass(device_t dev)
+{
+ device_printf(dev, "Pass %d\n", bus_current_pass);
+}
+
+static device_method_t at91_aic_methods[] = {
+ DEVMETHOD(device_probe, at91_aic_probe),
+ DEVMETHOD(device_attach, at91_aic_attach),
+ DEVMETHOD(bus_new_pass, at91_aic_new_pass),
+ DEVMETHOD_END
+};
+
+static driver_t at91_aic_driver = {
+ "at91_aic",
+ at91_aic_methods,
+ sizeof(struct aic_softc),
+};
+
+static devclass_t at91_aic_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_aic, simplebus, at91_aic_driver, at91_aic_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_aic, atmelarm, at91_aic_driver, at91_aic_devclass, NULL,
+ NULL);
+#endif
+/* not yet
+EARLY_DRIVER_MODULE(at91_aic, simplebus, at91_aic_driver, at91_aic_devclass,
+ NULL, NULL, BUS_PASS_INTERRUPT);
+*/
Property changes on: trunk/sys/arm/at91/at91_aic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_aicreg.h
===================================================================
--- trunk/sys/arm/at91/at91_aicreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_aicreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_aicreg.h 210040 2010-07-14 00:48:53Z cognet $ */
+
+#ifndef ARM_AT91_AT91_AICREG_H
+#define ARM_AT91_AT91_AICREG_H
+
+/* Interrupt Controller */
+#define IC_SMR (0) /* Source mode register */
+#define IC_SVR (128) /* Source vector register */
+#define IC_IVR (256) /* IRQ vector register */
+#define IC_FVR (260) /* FIQ vector register */
+#define IC_ISR (264) /* Interrupt status register */
+#define IC_IPR (268) /* Interrupt pending register */
+#define IC_IMR (272) /* Interrupt status register */
+#define IC_CISR (276) /* Core interrupt status register */
+#define IC_IECR (288) /* Interrupt enable command register */
+#define IC_IDCR (292) /* Interrupt disable command register */
+#define IC_ICCR (296) /* Interrupt clear command register */
+#define IC_ISCR (300) /* Interrupt set command register */
+#define IC_EOICR (304) /* End of interrupt command register */
+#define IC_SPU (308) /* Spurious vector register */
+#define IC_DCR (312) /* Debug control register */
+#define IC_FFER (320) /* Fast forcing enable register */
+#define IC_FFDR (324) /* Fast forcing disable register */
+#define IC_FFSR (328) /* Fast forcing status register */
+
+#endif /*ARM_AT91_AT91_AICREG_H*/
Property changes on: trunk/sys/arm/at91/at91_aicreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_cfata.c
===================================================================
--- trunk/sys/arm/at91/at91_cfata.c (rev 0)
+++ trunk/sys/arm/at91/at91_cfata.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,282 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Deglitch Networks, Stanislav Sedov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Driver for the AT91RM9200 CompactFlash controller operating in a
+ * common memory mode. Interrupts are driven by polling. The driver
+ * implements an ATA bridge and attached ATA channel driver on top
+ * of it.
+ * NOTE WELL: this driver uses polling mode. To achive an acceptable
+ * operating speed you will probably want to use HZ=2000 in kernel
+ * config.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_cfata.c 193934 2009-06-10 17:39:19Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sema.h>
+#include <sys/taskqueue.h>
+#include <vm/uma.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <sys/ata.h>
+#include <dev/ata/ata-all.h>
+#include <ata_if.h>
+
+struct at91_cfata_softc {
+ device_t dev;
+ struct resource *mem_res;
+ struct resource irq;
+ void (*isr_cb)(void *);
+ void *isr_arg;
+ struct callout tick;
+};
+
+static int at91_cfata_detach(device_t dev);
+static void at91_cfata_callout(void *arg);
+
+static int
+at91_cfata_probe(device_t dev)
+{
+
+ device_set_desc_copy(dev, "AT91RM9200 CompactFlash controller");
+ return (0);
+}
+
+static int
+at91_cfata_attach(device_t dev)
+{
+ struct at91_cfata_softc *sc;
+ int rid, error;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ rid = 0;
+ error = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ return (ENOMEM);
+
+ /* XXX: init CF controller? */
+
+ callout_init(&sc->tick, 1); /* Callout to poll the device. */
+ device_add_child(dev, "ata", -1);
+ bus_generic_attach(dev);
+ return (0);
+}
+
+static int
+at91_cfata_detach(device_t dev)
+{
+ struct at91_cfata_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_generic_detach(sc->dev);
+ if (sc->mem_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = NULL;
+ }
+ return (0);
+}
+
+static struct resource *
+ata_at91_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct at91_cfata_softc *sc = device_get_softc(dev);
+
+ KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID,
+ ("[at91_cfata, %d]: illegal resource request (type %u rid %u)",
+ __LINE__, type, *rid));
+ return (&sc->irq);
+}
+
+static int
+ata_at91_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID,
+ ("[at91_cfata, %d]: illegal resource request (type %u rid %u)",
+ __LINE__, type, rid));
+ return (0);
+}
+
+
+static int
+ata_at91_setup_intr(device_t dev, device_t child, struct resource *irq,
+ int flags, driver_filter_t *filt,
+ driver_intr_t *function, void *argument, void **cookiep)
+{
+ struct at91_cfata_softc *sc = device_get_softc(dev);
+
+ KASSERT(sc->isr_cb == NULL,
+ ("[at91_cfata, %d]: overwriting the old handler", __LINE__));
+ sc->isr_cb = function;
+ sc->isr_arg = argument;
+ *cookiep = sc;
+ callout_reset(&sc->tick, 1, at91_cfata_callout, sc);
+ return (0);
+}
+
+static int
+ata_at91_teardown_intr(device_t dev, device_t child, struct resource *irq,
+ void *cookie)
+{
+ struct at91_cfata_softc *sc = device_get_softc(dev);
+
+ sc->isr_cb = NULL;
+ sc->isr_arg = NULL;
+ return (0);
+}
+
+static void
+at91_cfata_callout(void *arg)
+{
+ struct at91_cfata_softc *sc;
+
+ sc = (struct at91_cfata_softc *)arg;
+ if (sc->isr_cb != NULL)
+ sc->isr_cb(sc->isr_arg);
+ callout_reset(&sc->tick, 1, at91_cfata_callout, sc);
+}
+
+static int
+at91_channel_probe(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ ch->unit = 0;
+ ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE;
+ device_set_desc_copy(dev, "ATA channel 0");
+
+ return (ata_probe(dev));
+}
+
+static int
+at91_channel_attach(device_t dev)
+{
+ struct at91_cfata_softc *sc = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < ATA_MAX_RES; i++)
+ ch->r_io[i].res = sc->mem_res;
+
+ /*
+ * CF+ Specification.
+ * 6.1.3 Memory Mapped Addressing.
+ */
+ ch->r_io[ATA_DATA].offset = 0x00;
+ ch->r_io[ATA_FEATURE].offset = 0x01;
+ ch->r_io[ATA_COUNT].offset = 0x02;
+ ch->r_io[ATA_SECTOR].offset = 0x03;
+ ch->r_io[ATA_CYL_LSB].offset = 0x04;
+ ch->r_io[ATA_CYL_MSB].offset = 0x05;
+ ch->r_io[ATA_DRIVE].offset = 0x06;
+ ch->r_io[ATA_COMMAND].offset = 0x07;
+ ch->r_io[ATA_ERROR].offset = 0x01;
+ ch->r_io[ATA_IREASON].offset = 0x02;
+ ch->r_io[ATA_STATUS].offset = 0x07;
+ ch->r_io[ATA_ALTSTAT].offset = 0x0e;
+ ch->r_io[ATA_CONTROL].offset = 0x0e;
+
+ /* Should point at the base of registers. */
+ ch->r_io[ATA_IDX_ADDR].offset = 0x0;
+
+ ata_generic_hw(dev);
+ return (ata_attach(dev));
+}
+
+static device_method_t at91_cfata_methods[] = {
+ /* Device interface. */
+ DEVMETHOD(device_probe, at91_cfata_probe),
+ DEVMETHOD(device_attach, at91_cfata_attach),
+ DEVMETHOD(device_detach, at91_cfata_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* ATA bus methods. */
+ DEVMETHOD(bus_alloc_resource, ata_at91_alloc_resource),
+ DEVMETHOD(bus_release_resource, ata_at91_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource,
+ bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, ata_at91_setup_intr),
+ DEVMETHOD(bus_teardown_intr, ata_at91_teardown_intr),
+
+ { 0, 0 }
+};
+
+devclass_t at91_cfata_devclass;
+
+static driver_t at91_cfata_driver = {
+ "at91_cfata",
+ at91_cfata_methods,
+ sizeof(struct at91_cfata_softc),
+};
+
+DRIVER_MODULE(at91_cfata, atmelarm, at91_cfata_driver, at91_cfata_devclass, 0,
+ 0);
+MODULE_VERSION(at91_cfata, 1);
+MODULE_DEPEND(at91_cfata, ata, 1, 1, 1);
+
+/*
+ * ATA channel driver.
+ */
+static device_method_t at91_channel_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, at91_channel_probe),
+ DEVMETHOD(device_attach, at91_channel_attach),
+ DEVMETHOD(device_detach, ata_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, ata_suspend),
+ DEVMETHOD(device_resume, ata_resume),
+
+ { 0, 0 }
+};
+
+driver_t at91_channel_driver = {
+ "ata",
+ at91_channel_methods,
+ sizeof(struct ata_channel),
+};
+
+DRIVER_MODULE(ata, at91_cfata, at91_channel_driver, ata_devclass, 0, 0);
Property changes on: trunk/sys/arm/at91/at91_cfata.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_gpio.h
===================================================================
--- trunk/sys/arm/at91/at91_gpio.h (rev 0)
+++ trunk/sys/arm/at91/at91_gpio.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,297 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_gpio.h 266087 2014-05-14 20:31:54Z ian $ */
+
+#ifndef ARM_AT91_AT91_GPIO_H
+#define ARM_AT91_AT91_GPIO_H
+
+typedef uint32_t at91_pin_t;
+
+#define AT91_PIN_NONE 0xfffffffful /* No pin / Not GPIO controlled */
+
+/*
+ * Map Atmel PIO pins to a unique number. They are just numbered sequentially.
+ */
+
+#define AT91_PIN_PA0 (at91_pin_t)0
+#define AT91_PIN_PA1 (at91_pin_t)1
+#define AT91_PIN_PA2 (at91_pin_t)2
+#define AT91_PIN_PA3 (at91_pin_t)3
+#define AT91_PIN_PA4 (at91_pin_t)4
+#define AT91_PIN_PA5 (at91_pin_t)5
+#define AT91_PIN_PA6 (at91_pin_t)6
+#define AT91_PIN_PA7 (at91_pin_t)7
+#define AT91_PIN_PA8 (at91_pin_t)8
+#define AT91_PIN_PA9 (at91_pin_t)9
+#define AT91_PIN_PA10 (at91_pin_t)10
+#define AT91_PIN_PA11 (at91_pin_t)11
+#define AT91_PIN_PA12 (at91_pin_t)12
+#define AT91_PIN_PA13 (at91_pin_t)13
+#define AT91_PIN_PA14 (at91_pin_t)14
+#define AT91_PIN_PA15 (at91_pin_t)15
+#define AT91_PIN_PA16 (at91_pin_t)16
+#define AT91_PIN_PA17 (at91_pin_t)17
+#define AT91_PIN_PA18 (at91_pin_t)18
+#define AT91_PIN_PA19 (at91_pin_t)19
+#define AT91_PIN_PA20 (at91_pin_t)20
+#define AT91_PIN_PA21 (at91_pin_t)21
+#define AT91_PIN_PA22 (at91_pin_t)22
+#define AT91_PIN_PA23 (at91_pin_t)23
+#define AT91_PIN_PA24 (at91_pin_t)24
+#define AT91_PIN_PA25 (at91_pin_t)25
+#define AT91_PIN_PA26 (at91_pin_t)26
+#define AT91_PIN_PA27 (at91_pin_t)27
+#define AT91_PIN_PA28 (at91_pin_t)28
+#define AT91_PIN_PA29 (at91_pin_t)29
+#define AT91_PIN_PA30 (at91_pin_t)30
+#define AT91_PIN_PA31 (at91_pin_t)31
+#define AT91_PIN_PB0 (at91_pin_t)32
+#define AT91_PIN_PB1 (at91_pin_t)33
+#define AT91_PIN_PB2 (at91_pin_t)34
+#define AT91_PIN_PB3 (at91_pin_t)35
+#define AT91_PIN_PB4 (at91_pin_t)36
+#define AT91_PIN_PB5 (at91_pin_t)37
+#define AT91_PIN_PB6 (at91_pin_t)38
+#define AT91_PIN_PB7 (at91_pin_t)39
+#define AT91_PIN_PB8 (at91_pin_t)40
+#define AT91_PIN_PB9 (at91_pin_t)41
+#define AT91_PIN_PB10 (at91_pin_t)42
+#define AT91_PIN_PB11 (at91_pin_t)43
+#define AT91_PIN_PB12 (at91_pin_t)44
+#define AT91_PIN_PB13 (at91_pin_t)45
+#define AT91_PIN_PB14 (at91_pin_t)46
+#define AT91_PIN_PB15 (at91_pin_t)47
+#define AT91_PIN_PB16 (at91_pin_t)48
+#define AT91_PIN_PB17 (at91_pin_t)49
+#define AT91_PIN_PB18 (at91_pin_t)50
+#define AT91_PIN_PB19 (at91_pin_t)51
+#define AT91_PIN_PB20 (at91_pin_t)52
+#define AT91_PIN_PB21 (at91_pin_t)53
+#define AT91_PIN_PB22 (at91_pin_t)54
+#define AT91_PIN_PB23 (at91_pin_t)55
+#define AT91_PIN_PB24 (at91_pin_t)56
+#define AT91_PIN_PB25 (at91_pin_t)57
+#define AT91_PIN_PB26 (at91_pin_t)58
+#define AT91_PIN_PB27 (at91_pin_t)59
+#define AT91_PIN_PB28 (at91_pin_t)60
+#define AT91_PIN_PB29 (at91_pin_t)61
+#define AT91_PIN_PB30 (at91_pin_t)62
+#define AT91_PIN_PB31 (at91_pin_t)63
+#define AT91_PIN_PC0 (at91_pin_t)64
+#define AT91_PIN_PC1 (at91_pin_t)65
+#define AT91_PIN_PC2 (at91_pin_t)66
+#define AT91_PIN_PC3 (at91_pin_t)67
+#define AT91_PIN_PC4 (at91_pin_t)68
+#define AT91_PIN_PC5 (at91_pin_t)69
+#define AT91_PIN_PC6 (at91_pin_t)70
+#define AT91_PIN_PC7 (at91_pin_t)71
+#define AT91_PIN_PC8 (at91_pin_t)72
+#define AT91_PIN_PC9 (at91_pin_t)73
+#define AT91_PIN_PC10 (at91_pin_t)74
+#define AT91_PIN_PC11 (at91_pin_t)75
+#define AT91_PIN_PC12 (at91_pin_t)76
+#define AT91_PIN_PC13 (at91_pin_t)77
+#define AT91_PIN_PC14 (at91_pin_t)78
+#define AT91_PIN_PC15 (at91_pin_t)79
+#define AT91_PIN_PC16 (at91_pin_t)80
+#define AT91_PIN_PC17 (at91_pin_t)81
+#define AT91_PIN_PC18 (at91_pin_t)82
+#define AT91_PIN_PC19 (at91_pin_t)83
+#define AT91_PIN_PC20 (at91_pin_t)84
+#define AT91_PIN_PC21 (at91_pin_t)85
+#define AT91_PIN_PC22 (at91_pin_t)86
+#define AT91_PIN_PC23 (at91_pin_t)87
+#define AT91_PIN_PC24 (at91_pin_t)88
+#define AT91_PIN_PC25 (at91_pin_t)89
+#define AT91_PIN_PC26 (at91_pin_t)90
+#define AT91_PIN_PC27 (at91_pin_t)91
+#define AT91_PIN_PC28 (at91_pin_t)92
+#define AT91_PIN_PC29 (at91_pin_t)93
+#define AT91_PIN_PC30 (at91_pin_t)94
+#define AT91_PIN_PC31 (at91_pin_t)95
+#define AT91_PIN_PD0 (at91_pin_t)96
+#define AT91_PIN_PD1 (at91_pin_t)97
+#define AT91_PIN_PD2 (at91_pin_t)98
+#define AT91_PIN_PD3 (at91_pin_t)99
+#define AT91_PIN_PD4 (at91_pin_t)100
+#define AT91_PIN_PD5 (at91_pin_t)101
+#define AT91_PIN_PD6 (at91_pin_t)102
+#define AT91_PIN_PD7 (at91_pin_t)103
+#define AT91_PIN_PD8 (at91_pin_t)104
+#define AT91_PIN_PD9 (at91_pin_t)105
+#define AT91_PIN_PD10 (at91_pin_t)106
+#define AT91_PIN_PD11 (at91_pin_t)107
+#define AT91_PIN_PD12 (at91_pin_t)108
+#define AT91_PIN_PD13 (at91_pin_t)109
+#define AT91_PIN_PD14 (at91_pin_t)110
+#define AT91_PIN_PD15 (at91_pin_t)111
+#define AT91_PIN_PD16 (at91_pin_t)112
+#define AT91_PIN_PD17 (at91_pin_t)113
+#define AT91_PIN_PD18 (at91_pin_t)114
+#define AT91_PIN_PD19 (at91_pin_t)115
+#define AT91_PIN_PD20 (at91_pin_t)116
+#define AT91_PIN_PD21 (at91_pin_t)117
+#define AT91_PIN_PD22 (at91_pin_t)118
+#define AT91_PIN_PD23 (at91_pin_t)119
+#define AT91_PIN_PD24 (at91_pin_t)120
+#define AT91_PIN_PD25 (at91_pin_t)121
+#define AT91_PIN_PD26 (at91_pin_t)122
+#define AT91_PIN_PD27 (at91_pin_t)123
+#define AT91_PIN_PD28 (at91_pin_t)124
+#define AT91_PIN_PD29 (at91_pin_t)125
+#define AT91_PIN_PD30 (at91_pin_t)126
+#define AT91_PIN_PD31 (at91_pin_t)127
+#define AT91_PIN_PE0 (at91_pin_t)128
+#define AT91_PIN_PE1 (at91_pin_t)129
+#define AT91_PIN_PE2 (at91_pin_t)130
+#define AT91_PIN_PE3 (at91_pin_t)131
+#define AT91_PIN_PE4 (at91_pin_t)132
+#define AT91_PIN_PE5 (at91_pin_t)133
+#define AT91_PIN_PE6 (at91_pin_t)134
+#define AT91_PIN_PE7 (at91_pin_t)135
+#define AT91_PIN_PE8 (at91_pin_t)136
+#define AT91_PIN_PE9 (at91_pin_t)137
+#define AT91_PIN_PE10 (at91_pin_t)138
+#define AT91_PIN_PE11 (at91_pin_t)139
+#define AT91_PIN_PE12 (at91_pin_t)140
+#define AT91_PIN_PE13 (at91_pin_t)141
+#define AT91_PIN_PE14 (at91_pin_t)142
+#define AT91_PIN_PE15 (at91_pin_t)143
+#define AT91_PIN_PE16 (at91_pin_t)144
+#define AT91_PIN_PE17 (at91_pin_t)145
+#define AT91_PIN_PE18 (at91_pin_t)146
+#define AT91_PIN_PE19 (at91_pin_t)147
+#define AT91_PIN_PE20 (at91_pin_t)148
+#define AT91_PIN_PE21 (at91_pin_t)149
+#define AT91_PIN_PE22 (at91_pin_t)150
+#define AT91_PIN_PE23 (at91_pin_t)151
+#define AT91_PIN_PE24 (at91_pin_t)152
+#define AT91_PIN_PE25 (at91_pin_t)153
+#define AT91_PIN_PE26 (at91_pin_t)154
+#define AT91_PIN_PE27 (at91_pin_t)155
+#define AT91_PIN_PE28 (at91_pin_t)156
+#define AT91_PIN_PE29 (at91_pin_t)157
+#define AT91_PIN_PE30 (at91_pin_t)158
+#define AT91_PIN_PE31 (at91_pin_t)159
+#define AT91_PIN_PF0 (at91_pin_t)160
+#define AT91_PIN_PF1 (at91_pin_t)161
+#define AT91_PIN_PF2 (at91_pin_t)162
+#define AT91_PIN_PF3 (at91_pin_t)163
+#define AT91_PIN_PF4 (at91_pin_t)164
+#define AT91_PIN_PF5 (at91_pin_t)165
+#define AT91_PIN_PF6 (at91_pin_t)166
+#define AT91_PIN_PF7 (at91_pin_t)167
+#define AT91_PIN_PF8 (at91_pin_t)168
+#define AT91_PIN_PF9 (at91_pin_t)169
+#define AT91_PIN_PF10 (at91_pin_t)170
+#define AT91_PIN_PF11 (at91_pin_t)171
+#define AT91_PIN_PF12 (at91_pin_t)172
+#define AT91_PIN_PF13 (at91_pin_t)173
+#define AT91_PIN_PF14 (at91_pin_t)174
+#define AT91_PIN_PF15 (at91_pin_t)175
+#define AT91_PIN_PF16 (at91_pin_t)176
+#define AT91_PIN_PF17 (at91_pin_t)177
+#define AT91_PIN_PF18 (at91_pin_t)178
+#define AT91_PIN_PF19 (at91_pin_t)179
+#define AT91_PIN_PF20 (at91_pin_t)180
+#define AT91_PIN_PF21 (at91_pin_t)181
+#define AT91_PIN_PF22 (at91_pin_t)182
+#define AT91_PIN_PF23 (at91_pin_t)183
+#define AT91_PIN_PF24 (at91_pin_t)184
+#define AT91_PIN_PF25 (at91_pin_t)185
+#define AT91_PIN_PF26 (at91_pin_t)186
+#define AT91_PIN_PF27 (at91_pin_t)187
+#define AT91_PIN_PF28 (at91_pin_t)188
+#define AT91_PIN_PF29 (at91_pin_t)189
+#define AT91_PIN_PF30 (at91_pin_t)190
+#define AT91_PIN_PF31 (at91_pin_t)191
+#define AT91_PIN_PG0 (at91_pin_t)192
+#define AT91_PIN_PG1 (at91_pin_t)193
+#define AT91_PIN_PG2 (at91_pin_t)194
+#define AT91_PIN_PG3 (at91_pin_t)195
+#define AT91_PIN_PG4 (at91_pin_t)196
+#define AT91_PIN_PG5 (at91_pin_t)197
+#define AT91_PIN_PG6 (at91_pin_t)198
+#define AT91_PIN_PG7 (at91_pin_t)199
+#define AT91_PIN_PG8 (at91_pin_t)200
+#define AT91_PIN_PG9 (at91_pin_t)201
+#define AT91_PIN_PG10 (at91_pin_t)202
+#define AT91_PIN_PG11 (at91_pin_t)203
+#define AT91_PIN_PG12 (at91_pin_t)204
+#define AT91_PIN_PG13 (at91_pin_t)205
+#define AT91_PIN_PG14 (at91_pin_t)206
+#define AT91_PIN_PG15 (at91_pin_t)207
+#define AT91_PIN_PG16 (at91_pin_t)208
+#define AT91_PIN_PG17 (at91_pin_t)209
+#define AT91_PIN_PG18 (at91_pin_t)210
+#define AT91_PIN_PG19 (at91_pin_t)211
+#define AT91_PIN_PG20 (at91_pin_t)212
+#define AT91_PIN_PG21 (at91_pin_t)213
+#define AT91_PIN_PG22 (at91_pin_t)214
+#define AT91_PIN_PG23 (at91_pin_t)215
+#define AT91_PIN_PG24 (at91_pin_t)216
+#define AT91_PIN_PG25 (at91_pin_t)217
+#define AT91_PIN_PG26 (at91_pin_t)218
+#define AT91_PIN_PG27 (at91_pin_t)219
+#define AT91_PIN_PG28 (at91_pin_t)220
+#define AT91_PIN_PG29 (at91_pin_t)221
+#define AT91_PIN_PG30 (at91_pin_t)222
+#define AT91_PIN_PG31 (at91_pin_t)223
+#define AT91_PIN_PH0 (at91_pin_t)224
+#define AT91_PIN_PH1 (at91_pin_t)225
+#define AT91_PIN_PH2 (at91_pin_t)226
+#define AT91_PIN_PH3 (at91_pin_t)227
+#define AT91_PIN_PH4 (at91_pin_t)228
+#define AT91_PIN_PH5 (at91_pin_t)229
+#define AT91_PIN_PH6 (at91_pin_t)230
+#define AT91_PIN_PH7 (at91_pin_t)231
+#define AT91_PIN_PH8 (at91_pin_t)232
+#define AT91_PIN_PH9 (at91_pin_t)233
+#define AT91_PIN_PH10 (at91_pin_t)234
+#define AT91_PIN_PH11 (at91_pin_t)235
+#define AT91_PIN_PH12 (at91_pin_t)236
+#define AT91_PIN_PH13 (at91_pin_t)237
+#define AT91_PIN_PH14 (at91_pin_t)238
+#define AT91_PIN_PH15 (at91_pin_t)239
+#define AT91_PIN_PH16 (at91_pin_t)240
+#define AT91_PIN_PH17 (at91_pin_t)241
+#define AT91_PIN_PH18 (at91_pin_t)242
+#define AT91_PIN_PH19 (at91_pin_t)243
+#define AT91_PIN_PH20 (at91_pin_t)244
+#define AT91_PIN_PH21 (at91_pin_t)245
+#define AT91_PIN_PH22 (at91_pin_t)246
+#define AT91_PIN_PH23 (at91_pin_t)247
+#define AT91_PIN_PH24 (at91_pin_t)248
+#define AT91_PIN_PH25 (at91_pin_t)249
+#define AT91_PIN_PH26 (at91_pin_t)250
+#define AT91_PIN_PH27 (at91_pin_t)251
+#define AT91_PIN_PH28 (at91_pin_t)252
+#define AT91_PIN_PH29 (at91_pin_t)253
+#define AT91_PIN_PH30 (at91_pin_t)254
+#define AT91_PIN_PH31 (at91_pin_t)255
+
+#endif /* ARM_AT91_AT91_GPIO_H */
Property changes on: trunk/sys/arm/at91/at91_gpio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_machdep.c
===================================================================
--- trunk/sys/arm/at91/at91_machdep.c (rev 0)
+++ trunk/sys/arm/at91/at91_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,693 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work.
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_machdep.c 266386 2014-05-18 00:32:35Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/cons.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/kdb.h>
+#include <sys/msgbuf.h>
+#include <machine/physmem.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+#include <machine/board.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <machine/devmap.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <sys/reboot.h>
+
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91soc.h>
+#include <arm/at91/at91_usartreg.h>
+#include <arm/at91/at91rm92reg.h>
+#include <arm/at91/at91sam9g20reg.h>
+#include <arm/at91/at91sam9g45reg.h>
+
+#ifndef MAXCPU
+#define MAXCPU 1
+#endif
+
+/* Page table for mapping proc0 zero page */
+#define KERNEL_PT_SYS 0
+#define KERNEL_PT_KERN 1
+#define KERNEL_PT_KERN_NUM 22
+/* L2 table for mapping after kernel */
+#define KERNEL_PT_AFKERNEL KERNEL_PT_KERN + KERNEL_PT_KERN_NUM
+#define KERNEL_PT_AFKERNEL_NUM 5
+
+/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
+#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
+
+struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
+
+/* Static device mappings. */
+const struct arm_devmap_entry at91_devmap[] = {
+ /*
+ * Map the critical on-board devices. The interrupt vector at
+ * 0xffff0000 makes it impossible to map them PA == VA, so we map all
+ * 0xfffxxxxx addresses to 0xdffxxxxx. This covers all critical devices
+ * on all members of the AT91SAM9 and AT91RM9200 families.
+ */
+ {
+ 0xdff00000,
+ 0xfff00000,
+ 0x00100000,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ /* There's a notion that we should do the rest of these lazily. */
+ /*
+ * We can't just map the OHCI registers VA == PA, because
+ * AT91xx_xxx_BASE belongs to the userland address space.
+ * We could just choose a different virtual address, but a better
+ * solution would probably be to just use pmap_mapdev() to allocate
+ * KVA, as we don't need the OHCI controller before the vm
+ * initialization is done. However, the AT91 resource allocation
+ * system doesn't know how to use pmap_mapdev() yet.
+ * Care must be taken to ensure PA and VM address do not overlap
+ * between entries.
+ */
+ {
+ /*
+ * Add the ohci controller, and anything else that might be
+ * on this chip select for a VA/PA mapping.
+ */
+ /* Internal Memory 1MB */
+ AT91RM92_OHCI_VA_BASE,
+ AT91RM92_OHCI_BASE,
+ 0x00100000,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ /* CompactFlash controller. Portion of EBI CS4 1MB */
+ AT91RM92_CF_VA_BASE,
+ AT91RM92_CF_BASE,
+ 0x00100000,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ /*
+ * The next two should be good for the 9260, 9261 and 9G20 since
+ * addresses mapping is the same.
+ */
+ {
+ /* Internal Memory 1MB */
+ AT91SAM9G20_OHCI_VA_BASE,
+ AT91SAM9G20_OHCI_BASE,
+ 0x00100000,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ /* EBI CS3 256MB */
+ AT91SAM9G20_NAND_VA_BASE,
+ AT91SAM9G20_NAND_BASE,
+ AT91SAM9G20_NAND_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ /*
+ * The next should be good for the 9G45.
+ */
+ {
+ /* Internal Memory 1MB */
+ AT91SAM9G45_OHCI_VA_BASE,
+ AT91SAM9G45_OHCI_BASE,
+ 0x00100000,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ { 0, 0, 0, 0, 0, }
+};
+
+/* Physical and virtual addresses for some global pages */
+
+struct pv_addr systempage;
+struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+struct pv_addr kernelstack;
+
+#ifdef LINUX_BOOT_ABI
+extern int membanks;
+extern int memstart[];
+extern int memsize[];
+#endif
+
+long
+at91_ramsize(void)
+{
+ uint32_t cr, mdr, mr, *SDRAMC;
+ int banks, rows, cols, bw;
+#ifdef LINUX_BOOT_ABI
+ /*
+ * If we found any ATAGs that were for memory, return the first bank.
+ */
+ if (membanks > 0)
+ return (memsize[0]);
+#endif
+
+ if (at91_is_rm92()) {
+ SDRAMC = (uint32_t *)(AT91_BASE + AT91RM92_SDRAMC_BASE);
+ cr = SDRAMC[AT91RM92_SDRAMC_CR / 4];
+ mr = SDRAMC[AT91RM92_SDRAMC_MR / 4];
+ banks = (cr & AT91RM92_SDRAMC_CR_NB_4) ? 2 : 1;
+ rows = ((cr & AT91RM92_SDRAMC_CR_NR_MASK) >> 2) + 11;
+ cols = (cr & AT91RM92_SDRAMC_CR_NC_MASK) + 8;
+ bw = (mr & AT91RM92_SDRAMC_MR_DBW_16) ? 1 : 2;
+ } else if (at91_cpu_is(AT91_T_SAM9G45)) {
+ SDRAMC = (uint32_t *)(AT91_BASE + AT91SAM9G45_DDRSDRC0_BASE);
+ cr = SDRAMC[AT91SAM9G45_DDRSDRC_CR / 4];
+ mdr = SDRAMC[AT91SAM9G45_DDRSDRC_MDR / 4];
+ banks = 0;
+ rows = ((cr & AT91SAM9G45_DDRSDRC_CR_NR_MASK) >> 2) + 11;
+ cols = (cr & AT91SAM9G45_DDRSDRC_CR_NC_MASK) + 8;
+ bw = (mdr & AT91SAM9G45_DDRSDRC_MDR_DBW_16) ? 1 : 2;
+
+ /* Fix the calculation for DDR memory */
+ mdr &= AT91SAM9G45_DDRSDRC_MDR_MASK;
+ if (mdr & AT91SAM9G45_DDRSDRC_MDR_LPDDR1 ||
+ mdr & AT91SAM9G45_DDRSDRC_MDR_DDR2) {
+ /* The cols value is 1 higher for DDR */
+ cols += 1;
+ /* DDR has 4 internal banks. */
+ banks = 2;
+ }
+ } else {
+ /*
+ * This should be good for the 9260, 9261, 9G20, 9G35 and 9X25
+ * as addresses and registers are the same.
+ */
+ SDRAMC = (uint32_t *)(AT91_BASE + AT91SAM9G20_SDRAMC_BASE);
+ cr = SDRAMC[AT91SAM9G20_SDRAMC_CR / 4];
+ mr = SDRAMC[AT91SAM9G20_SDRAMC_MR / 4];
+ banks = (cr & AT91SAM9G20_SDRAMC_CR_NB_4) ? 2 : 1;
+ rows = ((cr & AT91SAM9G20_SDRAMC_CR_NR_MASK) >> 2) + 11;
+ cols = (cr & AT91SAM9G20_SDRAMC_CR_NC_MASK) + 8;
+ bw = (cr & AT91SAM9G20_SDRAMC_CR_DBW_16) ? 1 : 2;
+ }
+
+ return (1 << (cols + rows + banks + bw));
+}
+
+static const char *soc_type_name[] = {
+ [AT91_T_CAP9] = "at91cap9",
+ [AT91_T_RM9200] = "at91rm9200",
+ [AT91_T_SAM9260] = "at91sam9260",
+ [AT91_T_SAM9261] = "at91sam9261",
+ [AT91_T_SAM9263] = "at91sam9263",
+ [AT91_T_SAM9G10] = "at91sam9g10",
+ [AT91_T_SAM9G20] = "at91sam9g20",
+ [AT91_T_SAM9G45] = "at91sam9g45",
+ [AT91_T_SAM9N12] = "at91sam9n12",
+ [AT91_T_SAM9RL] = "at91sam9rl",
+ [AT91_T_SAM9X5] = "at91sam9x5",
+ [AT91_T_NONE] = "UNKNOWN"
+};
+
+static const char *soc_subtype_name[] = {
+ [AT91_ST_NONE] = "UNKNOWN",
+ [AT91_ST_RM9200_BGA] = "at91rm9200_bga",
+ [AT91_ST_RM9200_PQFP] = "at91rm9200_pqfp",
+ [AT91_ST_SAM9XE] = "at91sam9xe",
+ [AT91_ST_SAM9G45] = "at91sam9g45",
+ [AT91_ST_SAM9M10] = "at91sam9m10",
+ [AT91_ST_SAM9G46] = "at91sam9g46",
+ [AT91_ST_SAM9M11] = "at91sam9m11",
+ [AT91_ST_SAM9G15] = "at91sam9g15",
+ [AT91_ST_SAM9G25] = "at91sam9g25",
+ [AT91_ST_SAM9G35] = "at91sam9g35",
+ [AT91_ST_SAM9X25] = "at91sam9x25",
+ [AT91_ST_SAM9X35] = "at91sam9x35",
+};
+
+struct at91_soc_info soc_info;
+
+/*
+ * Read the SoC ID from the CIDR register and try to match it against the
+ * values we know. If we find a good one, we return true. If not, we
+ * return false. When we find a good one, we also find the subtype
+ * and CPU family.
+ */
+static int
+at91_try_id(uint32_t dbgu_base)
+{
+ uint32_t socid;
+
+ soc_info.cidr = *(volatile uint32_t *)(AT91_BASE + dbgu_base +
+ DBGU_C1R);
+ socid = soc_info.cidr & ~AT91_CPU_VERSION_MASK;
+
+ soc_info.type = AT91_T_NONE;
+ soc_info.subtype = AT91_ST_NONE;
+ soc_info.family = (soc_info.cidr & AT91_CPU_FAMILY_MASK) >> 20;
+ soc_info.exid = *(volatile uint32_t *)(AT91_BASE + dbgu_base +
+ DBGU_C2R);
+
+ switch (socid) {
+ case AT91_CPU_CAP9:
+ soc_info.type = AT91_T_CAP9;
+ break;
+ case AT91_CPU_RM9200:
+ soc_info.type = AT91_T_RM9200;
+ break;
+ case AT91_CPU_SAM9XE128:
+ case AT91_CPU_SAM9XE256:
+ case AT91_CPU_SAM9XE512:
+ case AT91_CPU_SAM9260:
+ soc_info.type = AT91_T_SAM9260;
+ if (soc_info.family == AT91_FAMILY_SAM9XE)
+ soc_info.subtype = AT91_ST_SAM9XE;
+ break;
+ case AT91_CPU_SAM9261:
+ soc_info.type = AT91_T_SAM9261;
+ break;
+ case AT91_CPU_SAM9263:
+ soc_info.type = AT91_T_SAM9263;
+ break;
+ case AT91_CPU_SAM9G10:
+ soc_info.type = AT91_T_SAM9G10;
+ break;
+ case AT91_CPU_SAM9G20:
+ soc_info.type = AT91_T_SAM9G20;
+ break;
+ case AT91_CPU_SAM9G45:
+ soc_info.type = AT91_T_SAM9G45;
+ break;
+ case AT91_CPU_SAM9N12:
+ soc_info.type = AT91_T_SAM9N12;
+ break;
+ case AT91_CPU_SAM9RL64:
+ soc_info.type = AT91_T_SAM9RL;
+ break;
+ case AT91_CPU_SAM9X5:
+ soc_info.type = AT91_T_SAM9X5;
+ break;
+ default:
+ return (0);
+ }
+
+ switch (soc_info.type) {
+ case AT91_T_SAM9G45:
+ switch (soc_info.exid) {
+ case AT91_EXID_SAM9G45:
+ soc_info.subtype = AT91_ST_SAM9G45;
+ break;
+ case AT91_EXID_SAM9G46:
+ soc_info.subtype = AT91_ST_SAM9G46;
+ break;
+ case AT91_EXID_SAM9M10:
+ soc_info.subtype = AT91_ST_SAM9M10;
+ break;
+ case AT91_EXID_SAM9M11:
+ soc_info.subtype = AT91_ST_SAM9M11;
+ break;
+ }
+ break;
+ case AT91_T_SAM9X5:
+ switch (soc_info.exid) {
+ case AT91_EXID_SAM9G15:
+ soc_info.subtype = AT91_ST_SAM9G15;
+ break;
+ case AT91_EXID_SAM9G25:
+ soc_info.subtype = AT91_ST_SAM9G25;
+ break;
+ case AT91_EXID_SAM9G35:
+ soc_info.subtype = AT91_ST_SAM9G35;
+ break;
+ case AT91_EXID_SAM9X25:
+ soc_info.subtype = AT91_ST_SAM9X25;
+ break;
+ case AT91_EXID_SAM9X35:
+ soc_info.subtype = AT91_ST_SAM9X35;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ /*
+ * Disable interrupts in the DBGU unit...
+ */
+ *(volatile uint32_t *)(AT91_BASE + dbgu_base + USART_IDR) = 0xffffffff;
+
+ /*
+ * Save the name for later...
+ */
+ snprintf(soc_info.name, sizeof(soc_info.name), "%s%s%s",
+ soc_type_name[soc_info.type],
+ soc_info.subtype == AT91_ST_NONE ? "" : " subtype ",
+ soc_info.subtype == AT91_ST_NONE ? "" :
+ soc_subtype_name[soc_info.subtype]);
+
+ /*
+ * try to get the matching CPU support.
+ */
+ soc_info.soc_data = at91_match_soc(soc_info.type, soc_info.subtype);
+ soc_info.dbgu_base = AT91_BASE + dbgu_base;
+
+ return (1);
+}
+
+static void
+at91_soc_id(void)
+{
+
+ if (!at91_try_id(AT91_DBGU0))
+ at91_try_id(AT91_DBGU1);
+}
+
+#ifdef ARM_MANY_BOARD
+/* likely belongs in arm/arm/machdep.c, but since board_init is still at91 only... */
+SET_DECLARE(arm_board_set, const struct arm_board);
+
+/* Not yet fully functional, but enough to build ATMEL config */
+static long
+board_init(void)
+{
+ return -1;
+}
+#endif
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+ struct pv_addr kernel_l1pt;
+ struct pv_addr dpcpu;
+ int i;
+ u_int l1pagetable;
+ vm_offset_t freemempos;
+ vm_offset_t afterkern;
+ uint32_t memsize;
+ vm_offset_t lastaddr;
+
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+ set_cpufuncs();
+ pcpu0_init();
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+ freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK;
+ /* Define a macro to simplify memory allocation */
+#define valloc_pages(var, np) \
+ alloc_pages((var).pv_va, (np)); \
+ (var).pv_pa = (var).pv_va + (abp->abp_physaddr - KERNVIRTADDR);
+
+#define alloc_pages(var, np) \
+ (var) = freemempos; \
+ freemempos += (np * PAGE_SIZE); \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos += PAGE_SIZE;
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+ for (i = 0; i < NUM_KERNEL_PTS; ++i) {
+ if (!(i % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[i],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ } else {
+ kernel_pt_table[i].pv_va = freemempos -
+ (i % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
+ L2_TABLE_SIZE_REAL;
+ kernel_pt_table[i].pv_pa =
+ kernel_pt_table[i].pv_va - KERNVIRTADDR +
+ abp->abp_physaddr;
+ }
+ }
+ /*
+ * Allocate a page for the system page mapped to 0x00000000
+ * or 0xffff0000. This page will just contain the system vectors
+ * and can be shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate dynamic per-cpu area. */
+ valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
+ dpcpu_init((void *)dpcpu.pv_va, 0);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE * MAXCPU);
+ valloc_pages(abtstack, ABT_STACK_SIZE * MAXCPU);
+ valloc_pages(undstack, UND_STACK_SIZE * MAXCPU);
+ valloc_pages(kernelstack, KSTACK_PAGES * MAXCPU);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+
+ /*
+ * Now we start construction of the L1 page table
+ * We start by mapping the L2 page tables into the L1.
+ * This means that we can replace L1 mappings later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /* Map the L2 pages tables in the L1 page table */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH,
+ &kernel_pt_table[KERNEL_PT_SYS]);
+ for (i = 0; i < KERNEL_PT_KERN_NUM; i++)
+ pmap_link_l2pt(l1pagetable, KERNBASE + i * L1_S_SIZE,
+ &kernel_pt_table[KERNEL_PT_KERN + i]);
+ pmap_map_chunk(l1pagetable, KERNBASE, PHYSADDR,
+ (((uint32_t)lastaddr - KERNBASE) + PAGE_SIZE) & ~(PAGE_SIZE - 1),
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ afterkern = round_page((lastaddr + L1_S_SIZE) & ~(L1_S_SIZE - 1));
+ for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
+ pmap_link_l2pt(l1pagetable, afterkern + i * L1_S_SIZE,
+ &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
+ }
+
+ /* Map the vector page. */
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ /* Map the DPCPU pages */
+ pmap_map_chunk(l1pagetable, dpcpu.pv_va, dpcpu.pv_pa, DPCPU_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ /* Map the stack pages */
+ pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa,
+ IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa,
+ ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa,
+ UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa,
+ KSTACK_PAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
+ L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ pmap_map_chunk(l1pagetable, msgbufpv.pv_va, msgbufpv.pv_pa,
+ msgbufsize, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ for (i = 0; i < NUM_KERNEL_PTS; ++i) {
+ pmap_map_chunk(l1pagetable, kernel_pt_table[i].pv_va,
+ kernel_pt_table[i].pv_pa, L2_TABLE_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ }
+
+ arm_devmap_bootstrap(l1pagetable, at91_devmap);
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT);
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2));
+
+ at91_soc_id();
+
+ /*
+ * Initialize all the clocks, so that the console can work. We can only
+ * do this if at91_soc_id() was able to fill in the support data. Even
+ * if we can't init the clocks, still try to do a console init so we can
+ * try to print the error message about missing soc support. There's a
+ * chance the printf will work if the bootloader set up the DBGU.
+ */
+ if (soc_info.soc_data != NULL) {
+ soc_info.soc_data->soc_clock_init();
+ at91_pmc_init_clock();
+ }
+
+ cninit();
+
+ if (soc_info.soc_data == NULL)
+ printf("Warning: No soc support for %s found.\n", soc_info.name);
+
+ memsize = board_init();
+ if (memsize == -1) {
+ printf("board_init() failed, cannot determine ram size; "
+ "assuming 16MB\n");
+ memsize = 16 * 1024 * 1024;
+ }
+
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+ cpu_control(CPU_CONTROL_MMU_ENABLE, CPU_CONTROL_MMU_ENABLE);
+ cpu_setup("");
+
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+
+ pmap_curmaxkvaddr = afterkern + L1_S_SIZE * (KERNEL_PT_KERN_NUM - 1);
+ /* Always use the 256MB of KVA we have available between the kernel and devices */
+ vm_max_kernel_address = KERNVIRTADDR + (256 << 20);
+ pmap_bootstrap(freemempos, &kernel_l1pt);
+ msgbufp = (void*)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+
+ /*
+ * Add the physical ram we have available.
+ *
+ * Exclude the kernel, and all the things we allocated which immediately
+ * follow the kernel, from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ arm_physmem_hardware_region(PHYSADDR, memsize);
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+}
+
+/*
+ * These functions are handled elsewhere, so make them nops here.
+ */
+void
+cpu_startprofclock(void)
+{
+
+}
+
+void
+cpu_stopprofclock(void)
+{
+
+}
+
+void
+cpu_initclocks(void)
+{
+
+}
+
+void
+DELAY(int n)
+{
+
+ if (soc_info.soc_data)
+ soc_info.soc_data->soc_delay(n);
+}
+
+void
+cpu_reset(void)
+{
+
+ if (soc_info.soc_data)
+ soc_info.soc_data->soc_reset();
+ while (1)
+ continue;
+}
Property changes on: trunk/sys/arm/at91/at91_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_mci.c
===================================================================
--- trunk/sys/arm/at91/at91_mci.c (rev 0)
+++ trunk/sys/arm/at91/at91_mci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1407 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Bernd Walter. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_mci.c 318198 2017-05-11 21:01:02Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_mcireg.h>
+#include <arm/at91/at91_pdcreg.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcbrvar.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#include "mmcbr_if.h"
+
+#include "opt_at91.h"
+
+/*
+ * About running the MCI bus above 25MHz
+ *
+ * Historically, the MCI bus has been run at 30MHz on systems with a 60MHz
+ * master clock, in part due to a bug in dev/mmc.c making always request
+ * 30MHz, and in part over clocking the bus because 15MHz was too slow.
+ * Fixing that bug causes the mmc driver to request a 25MHz clock (as it
+ * should) and the logic in at91_mci_update_ios() picks the highest speed that
+ * doesn't exceed that limit. With a 60MHz MCK that would be 15MHz, and
+ * that's a real performance buzzkill when you've been getting away with 30MHz
+ * all along.
+ *
+ * By defining AT91_MCI_ALLOW_OVERCLOCK (or setting the allow_overclock=1
+ * device hint or sysctl) you can enable logic in at91_mci_update_ios() to
+ * overlcock the SD bus a little by running it at MCK / 2 when the requested
+ * speed is 25MHz and the next highest speed is 15MHz or less. This appears
+ * to work on virtually all SD cards, since it is what this driver has been
+ * doing prior to the introduction of this option, where the overclocking vs
+ * underclocking decision was automaticly "overclock". Modern SD cards can
+ * run at 45mhz/1-bit in standard mode (high speed mode enable commands not
+ * sent) without problems.
+ *
+ * Speaking of high-speed mode, the rm9200 manual says the MCI device supports
+ * the SD v1.0 specification and can run up to 50MHz. This is interesting in
+ * that the SD v1.0 spec caps the speed at 25MHz; high speed mode was added in
+ * the v1.10 spec. Furthermore, high speed mode doesn't just crank up the
+ * clock, it alters the signal timing. The rm9200 MCI device doesn't support
+ * these altered timings. So while speeds over 25MHz may work, they only work
+ * in what the SD spec calls "default" speed mode, and it amounts to violating
+ * the spec by overclocking the bus.
+ *
+ * If you also enable 4-wire mode it's possible transfers faster than 25MHz
+ * will fail. On the AT91RM9200, due to bugs in the bus contention logic, if
+ * you have the USB host device and OHCI driver enabled will fail. Even
+ * underclocking to 15MHz, intermittant overrun and underrun errors occur.
+ * Note that you don't even need to have usb devices attached to the system,
+ * the errors begin to occur as soon as the OHCI driver sets the register bit
+ * to enable periodic transfers. It appears (based on brief investigation)
+ * that the usb host controller uses so much ASB bandwidth that sometimes the
+ * DMA for MCI transfers doesn't get a bus grant in time and data gets
+ * dropped. Adding even a modicum of network activity changes the symptom
+ * from intermittant to very frequent. Members of the AT91SAM9 family have
+ * corrected this problem, or are at least better about their use of the bus.
+ */
+#ifndef AT91_MCI_ALLOW_OVERCLOCK
+#define AT91_MCI_ALLOW_OVERCLOCK 1
+#endif
+
+/*
+ * Allocate 2 bounce buffers we'll use to endian-swap the data due to the rm9200
+ * erratum. We use a pair of buffers because when reading that lets us begin
+ * endian-swapping the data in the first buffer while the DMA is reading into
+ * the second buffer. (We can't use the same trick for writing because we might
+ * not get all the data in the 2nd buffer swapped before the hardware needs it;
+ * dealing with that would add complexity to the driver.)
+ *
+ * The buffers are sized at 16K each due to the way the busdma cache sync
+ * operations work on arm. A dcache_inv_range() operation on a range larger
+ * than 16K gets turned into a dcache_wbinv_all(). That needlessly flushes the
+ * entire data cache, impacting overall system performance.
+ */
+#define BBCOUNT 2
+#define BBSIZE (16*1024)
+#define MAX_BLOCKS ((BBSIZE*BBCOUNT)/512)
+
+static int mci_debug;
+
+struct at91_mci_softc {
+ void *intrhand; /* Interrupt handle */
+ device_t dev;
+ int sc_cap;
+#define CAP_HAS_4WIRE 1 /* Has 4 wire bus */
+#define CAP_NEEDS_BYTESWAP 2 /* broken hardware needing bounce */
+#define CAP_MCI1_REV2XX 4 /* MCI 1 rev 2.x */
+ int flags;
+#define PENDING_CMD 0x01
+#define PENDING_STOP 0x02
+#define CMD_MULTIREAD 0x10
+#define CMD_MULTIWRITE 0x20
+ int has_4wire;
+ int allow_overclock;
+ struct resource *irq_res; /* IRQ resource */
+ struct resource *mem_res; /* Memory resource */
+ struct mtx sc_mtx;
+ bus_dma_tag_t dmatag;
+ struct mmc_host host;
+ int bus_busy;
+ struct mmc_request *req;
+ struct mmc_command *curcmd;
+ bus_dmamap_t bbuf_map[BBCOUNT];
+ char * bbuf_vaddr[BBCOUNT]; /* bounce bufs in KVA space */
+ uint32_t bbuf_len[BBCOUNT]; /* len currently queued for bounce buf */
+ uint32_t bbuf_curidx; /* which bbuf is the active DMA buffer */
+ uint32_t xfer_offset; /* offset so far into caller's buf */
+};
+
+/* bus entry points */
+static int at91_mci_probe(device_t dev);
+static int at91_mci_attach(device_t dev);
+static int at91_mci_detach(device_t dev);
+static void at91_mci_intr(void *);
+
+/* helper routines */
+static int at91_mci_activate(device_t dev);
+static void at91_mci_deactivate(device_t dev);
+static int at91_mci_is_mci1rev2xx(void);
+
+#define AT91_MCI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define AT91_MCI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define AT91_MCI_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+ "mci", MTX_DEF)
+#define AT91_MCI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define AT91_MCI_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define AT91_MCI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+static inline uint32_t
+RD4(struct at91_mci_softc *sc, bus_size_t off)
+{
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct at91_mci_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->mem_res, off, val);
+}
+
+static void
+at91_bswap_buf(struct at91_mci_softc *sc, void * dptr, void * sptr, uint32_t memsize)
+{
+ uint32_t * dst = (uint32_t *)dptr;
+ uint32_t * src = (uint32_t *)sptr;
+ uint32_t i;
+
+ /*
+ * If the hardware doesn't need byte-swapping, let bcopy() do the
+ * work. Use bounce buffer even if we don't need byteswap, since
+ * buffer may straddle a page boundry, and we don't handle
+ * multi-segment transfers in hardware. Seen from 'bsdlabel -w' which
+ * uses raw geom access to the volume. Greg Ansley (gja (at)
+ * ansley.com)
+ */
+ if (!(sc->sc_cap & CAP_NEEDS_BYTESWAP)) {
+ memcpy(dptr, sptr, memsize);
+ return;
+ }
+
+ /*
+ * Nice performance boost for slightly unrolling this loop.
+ * (But very little extra boost for further unrolling it.)
+ */
+ for (i = 0; i < memsize; i += 16) {
+ *dst++ = bswap32(*src++);
+ *dst++ = bswap32(*src++);
+ *dst++ = bswap32(*src++);
+ *dst++ = bswap32(*src++);
+ }
+
+ /* Mop up the last 1-3 words, if any. */
+ for (i = 0; i < (memsize & 0x0F); i += 4) {
+ *dst++ = bswap32(*src++);
+ }
+}
+
+static void
+at91_mci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ if (error != 0)
+ return;
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+static void
+at91_mci_pdc_disable(struct at91_mci_softc *sc)
+{
+ WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS);
+ WR4(sc, PDC_RPR, 0);
+ WR4(sc, PDC_RCR, 0);
+ WR4(sc, PDC_RNPR, 0);
+ WR4(sc, PDC_RNCR, 0);
+ WR4(sc, PDC_TPR, 0);
+ WR4(sc, PDC_TCR, 0);
+ WR4(sc, PDC_TNPR, 0);
+ WR4(sc, PDC_TNCR, 0);
+}
+
+/*
+ * Reset the controller, then restore most of the current state.
+ *
+ * This is called after detecting an error. It's also called after stopping a
+ * multi-block write, to un-wedge the device so that it will handle the NOTBUSY
+ * signal correctly. See comments in at91_mci_stop_done() for more details.
+ */
+static void at91_mci_reset(struct at91_mci_softc *sc)
+{
+ uint32_t mr;
+ uint32_t sdcr;
+ uint32_t dtor;
+ uint32_t imr;
+
+ at91_mci_pdc_disable(sc);
+
+ /* save current state */
+
+ imr = RD4(sc, MCI_IMR);
+ mr = RD4(sc, MCI_MR) & 0x7fff;
+ sdcr = RD4(sc, MCI_SDCR);
+ dtor = RD4(sc, MCI_DTOR);
+
+ /* reset the controller */
+
+ WR4(sc, MCI_IDR, 0xffffffff);
+ WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST);
+
+ /* restore state */
+
+ WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN);
+ WR4(sc, MCI_MR, mr);
+ WR4(sc, MCI_SDCR, sdcr);
+ WR4(sc, MCI_DTOR, dtor);
+ WR4(sc, MCI_IER, imr);
+
+ /*
+ * Make sure sdio interrupts will fire. Not sure why reading
+ * SR ensures that, but this is in the linux driver.
+ */
+
+ RD4(sc, MCI_SR);
+}
+
+static void
+at91_mci_init(device_t dev)
+{
+ struct at91_mci_softc *sc = device_get_softc(dev);
+ uint32_t val;
+
+ WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* device into reset */
+ WR4(sc, MCI_IDR, 0xffffffff); /* Turn off interrupts */
+ WR4(sc, MCI_DTOR, MCI_DTOR_DTOMUL_1M | 1);
+ val = MCI_MR_PDCMODE;
+ val |= 0x34a; /* PWSDIV = 3; CLKDIV = 74 */
+// if (sc->sc_cap & CAP_MCI1_REV2XX)
+// val |= MCI_MR_RDPROOF | MCI_MR_WRPROOF;
+ WR4(sc, MCI_MR, val);
+#ifndef AT91_MCI_SLOT_B
+ WR4(sc, MCI_SDCR, 0); /* SLOT A, 1 bit bus */
+#else
+ /*
+ * XXX Really should add second "unit" but nobody using using
+ * a two slot card that we know of. XXX
+ */
+ WR4(sc, MCI_SDCR, 1); /* SLOT B, 1 bit bus */
+#endif
+ /*
+ * Enable controller, including power-save. The slower clock
+ * of the power-save mode is only in effect when there is no
+ * transfer in progress, so it can be left in this mode all
+ * the time.
+ */
+ WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN);
+}
+
+static void
+at91_mci_fini(device_t dev)
+{
+ struct at91_mci_softc *sc = device_get_softc(dev);
+
+ WR4(sc, MCI_IDR, 0xffffffff); /* Turn off interrupts */
+ at91_mci_pdc_disable(sc);
+ WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* device into reset */
+}
+
+static int
+at91_mci_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,hsmci"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "MCI mmc/sd host bridge");
+ return (0);
+}
+
+static int
+at91_mci_attach(device_t dev)
+{
+ struct at91_mci_softc *sc = device_get_softc(dev);
+ struct sysctl_ctx_list *sctx;
+ struct sysctl_oid *soid;
+ device_t child;
+ int err, i;
+
+ sctx = device_get_sysctl_ctx(dev);
+ soid = device_get_sysctl_tree(dev);
+
+ sc->dev = dev;
+ sc->sc_cap = 0;
+ if (at91_is_rm92())
+ sc->sc_cap |= CAP_NEEDS_BYTESWAP;
+ /*
+ * MCI1 Rev 2 controllers need some workarounds, flag if so.
+ */
+ if (at91_mci_is_mci1rev2xx())
+ sc->sc_cap |= CAP_MCI1_REV2XX;
+
+ err = at91_mci_activate(dev);
+ if (err)
+ goto out;
+
+ AT91_MCI_LOCK_INIT(sc);
+
+ at91_mci_fini(dev);
+ at91_mci_init(dev);
+
+ /*
+ * Allocate DMA tags and maps and bounce buffers.
+ *
+ * The parms in the tag_create call cause the dmamem_alloc call to
+ * create each bounce buffer as a single contiguous buffer of BBSIZE
+ * bytes aligned to a 4096 byte boundary.
+ *
+ * Do not use DMA_COHERENT for these buffers because that maps the
+ * memory as non-cachable, which prevents cache line burst fills/writes,
+ * which is something we need since we're trying to overlap the
+ * byte-swapping with the DMA operations.
+ */
+ err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BBSIZE, 1, BBSIZE, 0, NULL, NULL, &sc->dmatag);
+ if (err != 0)
+ goto out;
+
+ for (i = 0; i < BBCOUNT; ++i) {
+ err = bus_dmamem_alloc(sc->dmatag, (void **)&sc->bbuf_vaddr[i],
+ BUS_DMA_NOWAIT, &sc->bbuf_map[i]);
+ if (err != 0)
+ goto out;
+ }
+
+ /*
+ * Activate the interrupt
+ */
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, at91_mci_intr, sc, &sc->intrhand);
+ if (err) {
+ AT91_MCI_LOCK_DESTROY(sc);
+ goto out;
+ }
+
+ /*
+ * Allow 4-wire to be initially set via #define.
+ * Allow a device hint to override that.
+ * Allow a sysctl to override that.
+ */
+#if defined(AT91_MCI_HAS_4WIRE) && AT91_MCI_HAS_4WIRE != 0
+ sc->has_4wire = 1;
+#endif
+ resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "4wire", &sc->has_4wire);
+ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "4wire",
+ CTLFLAG_RW, &sc->has_4wire, 0, "has 4 wire SD Card bus");
+ if (sc->has_4wire)
+ sc->sc_cap |= CAP_HAS_4WIRE;
+
+ sc->allow_overclock = AT91_MCI_ALLOW_OVERCLOCK;
+ resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "allow_overclock", &sc->allow_overclock);
+ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "allow_overclock",
+ CTLFLAG_RW, &sc->allow_overclock, 0,
+ "Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less.");
+
+ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug",
+ CTLFLAG_RWTUN, &mci_debug, 0, "enable debug output");
+
+ /*
+ * Our real min freq is master_clock/512, but upper driver layers are
+ * going to set the min speed during card discovery, and the right speed
+ * for that is 400kHz, so advertise a safe value just under that.
+ *
+ * For max speed, while the rm9200 manual says the max is 50mhz, it also
+ * says it supports only the SD v1.0 spec, which means the real limit is
+ * 25mhz. On the other hand, historical use has been to slightly violate
+ * the standard by running the bus at 30MHz. For more information on
+ * that, see the comments at the top of this file.
+ */
+ sc->host.f_min = 375000;
+ sc->host.f_max = at91_master_clock / 2;
+ if (sc->host.f_max > 25000000)
+ sc->host.f_max = 25000000;
+ sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
+ sc->host.caps = 0;
+ if (sc->sc_cap & CAP_HAS_4WIRE)
+ sc->host.caps |= MMC_CAP_4_BIT_DATA;
+
+ child = device_add_child(dev, "mmc", 0);
+ device_set_ivars(dev, &sc->host);
+ err = bus_generic_attach(dev);
+out:
+ if (err)
+ at91_mci_deactivate(dev);
+ return (err);
+}
+
+static int
+at91_mci_detach(device_t dev)
+{
+ struct at91_mci_softc *sc = device_get_softc(dev);
+
+ at91_mci_fini(dev);
+ at91_mci_deactivate(dev);
+
+ bus_dmamem_free(sc->dmatag, sc->bbuf_vaddr[0], sc->bbuf_map[0]);
+ bus_dmamem_free(sc->dmatag, sc->bbuf_vaddr[1], sc->bbuf_map[1]);
+ bus_dma_tag_destroy(sc->dmatag);
+
+ return (EBUSY); /* XXX */
+}
+
+static int
+at91_mci_activate(device_t dev)
+{
+ struct at91_mci_softc *sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ goto errout;
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL)
+ goto errout;
+
+ return (0);
+errout:
+ at91_mci_deactivate(dev);
+ return (ENOMEM);
+}
+
+static void
+at91_mci_deactivate(device_t dev)
+{
+ struct at91_mci_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->intrhand)
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ sc->intrhand = 0;
+ bus_generic_detach(sc->dev);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = 0;
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ sc->irq_res = 0;
+ return;
+}
+
+static int
+at91_mci_is_mci1rev2xx(void)
+{
+
+ switch (soc_info.type) {
+ case AT91_T_SAM9260:
+ case AT91_T_SAM9263:
+ case AT91_T_CAP9:
+ case AT91_T_SAM9G10:
+ case AT91_T_SAM9G20:
+ case AT91_T_SAM9RL:
+ return(1);
+ default:
+ return (0);
+ }
+}
+
+static int
+at91_mci_update_ios(device_t brdev, device_t reqdev)
+{
+ struct at91_mci_softc *sc;
+ struct mmc_ios *ios;
+ uint32_t clkdiv;
+ uint32_t freq;
+
+ sc = device_get_softc(brdev);
+ ios = &sc->host.ios;
+
+ /*
+ * Calculate our closest available clock speed that doesn't exceed the
+ * requested speed.
+ *
+ * When overclocking is allowed, the requested clock is 25MHz, the
+ * computed frequency is 15MHz or smaller and clockdiv is 1, use
+ * clockdiv of 0 to double that. If less than 12.5MHz, double
+ * regardless of the overclocking setting.
+ *
+ * Whatever we come up with, store it back into ios->clock so that the
+ * upper layer drivers can report the actual speed of the bus.
+ */
+ if (ios->clock == 0) {
+ WR4(sc, MCI_CR, MCI_CR_MCIDIS);
+ clkdiv = 0;
+ } else {
+ WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN);
+ if ((at91_master_clock % (ios->clock * 2)) == 0)
+ clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
+ else
+ clkdiv = (at91_master_clock / ios->clock) / 2;
+ freq = at91_master_clock / ((clkdiv+1) * 2);
+ if (clkdiv == 1 && ios->clock == 25000000 && freq <= 15000000) {
+ if (sc->allow_overclock || freq <= 12500000) {
+ clkdiv = 0;
+ freq = at91_master_clock / ((clkdiv+1) * 2);
+ }
+ }
+ ios->clock = freq;
+ }
+ if (ios->bus_width == bus_width_4)
+ WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) | MCI_SDCR_SDCBUS);
+ else
+ WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) & ~MCI_SDCR_SDCBUS);
+ WR4(sc, MCI_MR, (RD4(sc, MCI_MR) & ~MCI_MR_CLKDIV) | clkdiv);
+ /* Do we need a settle time here? */
+ /* XXX We need to turn the device on/off here with a GPIO pin */
+ return (0);
+}
+
+static void
+at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
+{
+ uint32_t cmdr, mr;
+ struct mmc_data *data;
+
+ sc->curcmd = cmd;
+ data = cmd->data;
+
+ /* XXX Upper layers don't always set this */
+ cmd->mrq = sc->req;
+
+ /* Begin setting up command register. */
+
+ cmdr = cmd->opcode;
+
+ if (sc->host.ios.bus_mode == opendrain)
+ cmdr |= MCI_CMDR_OPDCMD;
+
+ /* Set up response handling. Allow max timeout for responses. */
+
+ if (MMC_RSP(cmd->flags) == MMC_RSP_NONE)
+ cmdr |= MCI_CMDR_RSPTYP_NO;
+ else {
+ cmdr |= MCI_CMDR_MAXLAT;
+ if (cmd->flags & MMC_RSP_136)
+ cmdr |= MCI_CMDR_RSPTYP_136;
+ else
+ cmdr |= MCI_CMDR_RSPTYP_48;
+ }
+
+ /*
+ * If there is no data transfer, just set up the right interrupt mask
+ * and start the command.
+ *
+ * The interrupt mask needs to be CMDRDY plus all non-data-transfer
+ * errors. It's important to leave the transfer-related errors out, to
+ * avoid spurious timeout or crc errors on a STOP command following a
+ * multiblock read. When a multiblock read is in progress, sending a
+ * STOP in the middle of a block occasionally triggers such errors, but
+ * we're totally disinterested in them because we've already gotten all
+ * the data we wanted without error before sending the STOP command.
+ */
+
+ if (data == NULL) {
+ uint32_t ier = MCI_SR_CMDRDY |
+ MCI_SR_RTOE | MCI_SR_RENDE |
+ MCI_SR_RCRCE | MCI_SR_RDIRE | MCI_SR_RINDE;
+
+ at91_mci_pdc_disable(sc);
+
+ if (cmd->opcode == MMC_STOP_TRANSMISSION)
+ cmdr |= MCI_CMDR_TRCMD_STOP;
+
+ /* Ignore response CRC on CMD2 and ACMD41, per standard. */
+
+ if (cmd->opcode == MMC_SEND_OP_COND ||
+ cmd->opcode == ACMD_SD_SEND_OP_COND)
+ ier &= ~MCI_SR_RCRCE;
+
+ if (mci_debug)
+ printf("CMDR %x (opcode %d) ARGR %x no data\n",
+ cmdr, cmd->opcode, cmd->arg);
+
+ WR4(sc, MCI_ARGR, cmd->arg);
+ WR4(sc, MCI_CMDR, cmdr);
+ WR4(sc, MCI_IDR, 0xffffffff);
+ WR4(sc, MCI_IER, ier);
+ return;
+ }
+
+ /* There is data, set up the transfer-related parts of the command. */
+
+ if (data->flags & MMC_DATA_READ)
+ cmdr |= MCI_CMDR_TRDIR;
+
+ if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE))
+ cmdr |= MCI_CMDR_TRCMD_START;
+
+ if (data->flags & MMC_DATA_STREAM)
+ cmdr |= MCI_CMDR_TRTYP_STREAM;
+ else if (data->flags & MMC_DATA_MULTI) {
+ cmdr |= MCI_CMDR_TRTYP_MULTIPLE;
+ sc->flags |= (data->flags & MMC_DATA_READ) ?
+ CMD_MULTIREAD : CMD_MULTIWRITE;
+ }
+
+ /*
+ * Disable PDC until we're ready.
+ *
+ * Set block size and turn on PDC mode for dma xfer.
+ * Note that the block size is the smaller of the amount of data to be
+ * transferred, or 512 bytes. The 512 size is fixed by the standard;
+ * smaller blocks are possible, but never larger.
+ */
+
+ WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS);
+
+ mr = RD4(sc,MCI_MR) & ~MCI_MR_BLKLEN;
+ mr |= min(data->len, 512) << 16;
+ WR4(sc, MCI_MR, mr | MCI_MR_PDCMODE|MCI_MR_PDCPADV);
+
+ /*
+ * Set up DMA.
+ *
+ * Use bounce buffers even if we don't need to byteswap, because doing
+ * multi-block IO with large DMA buffers is way fast (compared to
+ * single-block IO), even after incurring the overhead of also copying
+ * from/to the caller's buffers (which may be in non-contiguous physical
+ * pages).
+ *
+ * In an ideal non-byteswap world we could create a dma tag that allows
+ * for discontiguous segments and do the IO directly from/to the
+ * caller's buffer(s), using ENDRX/ENDTX interrupts to chain the
+ * discontiguous buffers through the PDC. Someday.
+ *
+ * If a read is bigger than 2k, split it in half so that we can start
+ * byte-swapping the first half while the second half is on the wire.
+ * It would be best if we could split it into 8k chunks, but we can't
+ * always keep up with the byte-swapping due to other system activity,
+ * and if an RXBUFF interrupt happens while we're still handling the
+ * byte-swap from the prior buffer (IE, we haven't returned from
+ * handling the prior interrupt yet), then data will get dropped on the
+ * floor and we can't easily recover from that. The right fix for that
+ * would be to have the interrupt handling only keep the DMA flowing and
+ * enqueue filled buffers to be byte-swapped in a non-interrupt context.
+ * Even that won't work on the write side of things though; in that
+ * context we have to have all the data ready to go before starting the
+ * dma.
+ *
+ * XXX what about stream transfers?
+ */
+ sc->xfer_offset = 0;
+ sc->bbuf_curidx = 0;
+
+ if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) {
+ uint32_t len;
+ uint32_t remaining = data->len;
+ bus_addr_t paddr;
+ int err;
+
+ if (remaining > (BBCOUNT*BBSIZE))
+ panic("IO read size exceeds MAXDATA\n");
+
+ if (data->flags & MMC_DATA_READ) {
+ if (remaining > 2048) // XXX
+ len = remaining / 2;
+ else
+ len = remaining;
+ err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0],
+ sc->bbuf_vaddr[0], len, at91_mci_getaddr,
+ &paddr, BUS_DMA_NOWAIT);
+ if (err != 0)
+ panic("IO read dmamap_load failed\n");
+ bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0],
+ BUS_DMASYNC_PREREAD);
+ WR4(sc, PDC_RPR, paddr);
+ WR4(sc, PDC_RCR, len / 4);
+ sc->bbuf_len[0] = len;
+ remaining -= len;
+ if (remaining == 0) {
+ sc->bbuf_len[1] = 0;
+ } else {
+ len = remaining;
+ err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[1],
+ sc->bbuf_vaddr[1], len, at91_mci_getaddr,
+ &paddr, BUS_DMA_NOWAIT);
+ if (err != 0)
+ panic("IO read dmamap_load failed\n");
+ bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1],
+ BUS_DMASYNC_PREREAD);
+ WR4(sc, PDC_RNPR, paddr);
+ WR4(sc, PDC_RNCR, len / 4);
+ sc->bbuf_len[1] = len;
+ remaining -= len;
+ }
+ WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
+ } else {
+ len = min(BBSIZE, remaining);
+ at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len);
+ err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0],
+ sc->bbuf_vaddr[0], len, at91_mci_getaddr,
+ &paddr, BUS_DMA_NOWAIT);
+ if (err != 0)
+ panic("IO write dmamap_load failed\n");
+ bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0],
+ BUS_DMASYNC_PREWRITE);
+ /*
+ * Erratum workaround: PDC transfer length on a write
+ * must not be smaller than 12 bytes (3 words); only
+ * blklen bytes (set above) are actually transferred.
+ */
+ WR4(sc, PDC_TPR,paddr);
+ WR4(sc, PDC_TCR, (len < 12) ? 3 : len / 4);
+ sc->bbuf_len[0] = len;
+ remaining -= len;
+ if (remaining == 0) {
+ sc->bbuf_len[1] = 0;
+ } else {
+ len = remaining;
+ at91_bswap_buf(sc, sc->bbuf_vaddr[1],
+ ((char *)data->data)+BBSIZE, len);
+ err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[1],
+ sc->bbuf_vaddr[1], len, at91_mci_getaddr,
+ &paddr, BUS_DMA_NOWAIT);
+ if (err != 0)
+ panic("IO write dmamap_load failed\n");
+ bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1],
+ BUS_DMASYNC_PREWRITE);
+ WR4(sc, PDC_TNPR, paddr);
+ WR4(sc, PDC_TNCR, (len < 12) ? 3 : len / 4);
+ sc->bbuf_len[1] = len;
+ remaining -= len;
+ }
+ /* do not enable PDC xfer until CMDRDY asserted */
+ }
+ data->xfer_len = 0; /* XXX what's this? appears to be unused. */
+ }
+
+ if (mci_debug)
+ printf("CMDR %x (opcode %d) ARGR %x with data len %d\n",
+ cmdr, cmd->opcode, cmd->arg, cmd->data->len);
+
+ WR4(sc, MCI_ARGR, cmd->arg);
+ WR4(sc, MCI_CMDR, cmdr);
+ WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_CMDRDY);
+}
+
+static void
+at91_mci_next_operation(struct at91_mci_softc *sc)
+{
+ struct mmc_request *req;
+
+ req = sc->req;
+ if (req == NULL)
+ return;
+
+ if (sc->flags & PENDING_CMD) {
+ sc->flags &= ~PENDING_CMD;
+ at91_mci_start_cmd(sc, req->cmd);
+ return;
+ } else if (sc->flags & PENDING_STOP) {
+ sc->flags &= ~PENDING_STOP;
+ at91_mci_start_cmd(sc, req->stop);
+ return;
+ }
+
+ WR4(sc, MCI_IDR, 0xffffffff);
+ sc->req = NULL;
+ sc->curcmd = NULL;
+ //printf("req done\n");
+ req->done(req);
+}
+
+static int
+at91_mci_request(device_t brdev, device_t reqdev, struct mmc_request *req)
+{
+ struct at91_mci_softc *sc = device_get_softc(brdev);
+
+ AT91_MCI_LOCK(sc);
+ if (sc->req != NULL) {
+ AT91_MCI_UNLOCK(sc);
+ return (EBUSY);
+ }
+ //printf("new req\n");
+ sc->req = req;
+ sc->flags = PENDING_CMD;
+ if (sc->req->stop)
+ sc->flags |= PENDING_STOP;
+ at91_mci_next_operation(sc);
+ AT91_MCI_UNLOCK(sc);
+ return (0);
+}
+
+static int
+at91_mci_get_ro(device_t brdev, device_t reqdev)
+{
+ return (0);
+}
+
+static int
+at91_mci_acquire_host(device_t brdev, device_t reqdev)
+{
+ struct at91_mci_softc *sc = device_get_softc(brdev);
+ int err = 0;
+
+ AT91_MCI_LOCK(sc);
+ while (sc->bus_busy)
+ msleep(sc, &sc->sc_mtx, PZERO, "mciah", hz / 5);
+ sc->bus_busy++;
+ AT91_MCI_UNLOCK(sc);
+ return (err);
+}
+
+static int
+at91_mci_release_host(device_t brdev, device_t reqdev)
+{
+ struct at91_mci_softc *sc = device_get_softc(brdev);
+
+ AT91_MCI_LOCK(sc);
+ sc->bus_busy--;
+ wakeup(sc);
+ AT91_MCI_UNLOCK(sc);
+ return (0);
+}
+
+static void
+at91_mci_read_done(struct at91_mci_softc *sc, uint32_t sr)
+{
+ struct mmc_command *cmd = sc->curcmd;
+ char * dataptr = (char *)cmd->data->data;
+ uint32_t curidx = sc->bbuf_curidx;
+ uint32_t len = sc->bbuf_len[curidx];
+
+ /*
+ * We arrive here when a DMA transfer for a read is done, whether it's
+ * a single or multi-block read.
+ *
+ * We byte-swap the buffer that just completed, and if that is the
+ * last buffer that's part of this read then we move on to the next
+ * operation, otherwise we wait for another ENDRX for the next bufer.
+ */
+
+ bus_dmamap_sync(sc->dmatag, sc->bbuf_map[curidx], BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->dmatag, sc->bbuf_map[curidx]);
+
+ at91_bswap_buf(sc, dataptr + sc->xfer_offset, sc->bbuf_vaddr[curidx], len);
+
+ if (mci_debug) {
+ printf("read done sr %x curidx %d len %d xfer_offset %d\n",
+ sr, curidx, len, sc->xfer_offset);
+ }
+
+ sc->xfer_offset += len;
+ sc->bbuf_curidx = !curidx; /* swap buffers */
+
+ /*
+ * If we've transferred all the data, move on to the next operation.
+ *
+ * If we're still transferring the last buffer, RNCR is already zero but
+ * we have to write a zero anyway to clear the ENDRX status so we don't
+ * re-interrupt until the last buffer is done.
+ */
+ if (sc->xfer_offset == cmd->data->len) {
+ WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS);
+ cmd->error = MMC_ERR_NONE;
+ at91_mci_next_operation(sc);
+ } else {
+ WR4(sc, PDC_RNCR, 0);
+ WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_ENDRX);
+ }
+}
+
+static void
+at91_mci_write_done(struct at91_mci_softc *sc, uint32_t sr)
+{
+ struct mmc_command *cmd = sc->curcmd;
+
+ /*
+ * We arrive here when the entire DMA transfer for a write is done,
+ * whether it's a single or multi-block write. If it's multi-block we
+ * have to immediately move on to the next operation which is to send
+ * the stop command. If it's a single-block transfer we need to wait
+ * for NOTBUSY, but if that's already asserted we can avoid another
+ * interrupt and just move on to completing the request right away.
+ */
+
+ WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS);
+
+ bus_dmamap_sync(sc->dmatag, sc->bbuf_map[sc->bbuf_curidx],
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->dmatag, sc->bbuf_map[sc->bbuf_curidx]);
+
+ if ((cmd->data->flags & MMC_DATA_MULTI) || (sr & MCI_SR_NOTBUSY)) {
+ cmd->error = MMC_ERR_NONE;
+ at91_mci_next_operation(sc);
+ } else {
+ WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY);
+ }
+}
+
+static void
+at91_mci_notbusy(struct at91_mci_softc *sc)
+{
+ struct mmc_command *cmd = sc->curcmd;
+
+ /*
+ * We arrive here by either completion of a single-block write, or
+ * completion of the stop command that ended a multi-block write (and,
+ * I suppose, after a card-select or erase, but I haven't tested
+ * those). Anyway, we're done and it's time to move on to the next
+ * command.
+ */
+
+ cmd->error = MMC_ERR_NONE;
+ at91_mci_next_operation(sc);
+}
+
+static void
+at91_mci_stop_done(struct at91_mci_softc *sc, uint32_t sr)
+{
+ struct mmc_command *cmd = sc->curcmd;
+
+ /*
+ * We arrive here after receiving CMDRDY for a MMC_STOP_TRANSMISSION
+ * command. Depending on the operation being stopped, we may have to
+ * do some unusual things to work around hardware bugs.
+ */
+
+ /*
+ * This is known to be true of at91rm9200 hardware; it may or may not
+ * apply to more recent chips:
+ *
+ * After stopping a multi-block write, the NOTBUSY bit in MCI_SR does
+ * not properly reflect the actual busy state of the card as signaled
+ * on the DAT0 line; it always claims the card is not-busy. If we
+ * believe that and let operations continue, following commands will
+ * fail with response timeouts (except of course MMC_SEND_STATUS -- it
+ * indicates the card is busy in the PRG state, which was the smoking
+ * gun that showed MCI_SR NOTBUSY was not tracking DAT0 correctly).
+ *
+ * The atmel docs are emphatic: "This flag [NOTBUSY] must be used only
+ * for Write Operations." I guess technically since we sent a stop
+ * it's not a write operation anymore. But then just what did they
+ * think it meant for the stop command to have "...an optional busy
+ * signal transmitted on the data line" according to the SD spec?
+ *
+ * I tried a variety of things to un-wedge the MCI and get the status
+ * register to reflect NOTBUSY correctly again, but the only thing
+ * that worked was a full device reset. It feels like an awfully big
+ * hammer, but doing a full reset after every multiblock write is
+ * still faster than doing single-block IO (by almost two orders of
+ * magnitude: 20KB/sec improves to about 1.8MB/sec best case).
+ *
+ * After doing the reset, wait for a NOTBUSY interrupt before
+ * continuing with the next operation.
+ *
+ * This workaround breaks multiwrite on the rev2xx parts, but some other
+ * workaround is needed.
+ */
+ if ((sc->flags & CMD_MULTIWRITE) && (sc->sc_cap & CAP_NEEDS_BYTESWAP)) {
+ at91_mci_reset(sc);
+ WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY);
+ return;
+ }
+
+ /*
+ * This is known to be true of at91rm9200 hardware; it may or may not
+ * apply to more recent chips:
+ *
+ * After stopping a multi-block read, loop to read and discard any
+ * data that coasts in after we sent the stop command. The docs don't
+ * say anything about it, but empirical testing shows that 1-3
+ * additional words of data get buffered up in some unmentioned
+ * internal fifo and if we don't read and discard them here they end
+ * up on the front of the next read DMA transfer we do.
+ *
+ * This appears to be unnecessary for rev2xx parts.
+ */
+ if ((sc->flags & CMD_MULTIREAD) && (sc->sc_cap & CAP_NEEDS_BYTESWAP)) {
+ uint32_t sr;
+ int count = 0;
+
+ do {
+ sr = RD4(sc, MCI_SR);
+ if (sr & MCI_SR_RXRDY) {
+ RD4(sc, MCI_RDR);
+ ++count;
+ }
+ } while (sr & MCI_SR_RXRDY);
+ at91_mci_reset(sc);
+ }
+
+ cmd->error = MMC_ERR_NONE;
+ at91_mci_next_operation(sc);
+
+}
+
+static void
+at91_mci_cmdrdy(struct at91_mci_softc *sc, uint32_t sr)
+{
+ struct mmc_command *cmd = sc->curcmd;
+ int i;
+
+ if (cmd == NULL)
+ return;
+
+ /*
+ * We get here at the end of EVERY command. We retrieve the command
+ * response (if any) then decide what to do next based on the command.
+ */
+
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ for (i = 0; i < ((cmd->flags & MMC_RSP_136) ? 4 : 1); i++) {
+ cmd->resp[i] = RD4(sc, MCI_RSPR + i * 4);
+ if (mci_debug)
+ printf("RSPR[%d] = %x sr=%x\n", i, cmd->resp[i], sr);
+ }
+ }
+
+ /*
+ * If this was a stop command, go handle the various special
+ * conditions (read: bugs) that have to be dealt with following a stop.
+ */
+ if (cmd->opcode == MMC_STOP_TRANSMISSION) {
+ at91_mci_stop_done(sc, sr);
+ return;
+ }
+
+ /*
+ * If this command can continue to assert BUSY beyond the response then
+ * we need to wait for NOTBUSY before the command is really done.
+ *
+ * Note that this may not work properly on the at91rm9200. It certainly
+ * doesn't work for the STOP command that follows a multi-block write,
+ * so post-stop CMDRDY is handled separately; see the special handling
+ * in at91_mci_stop_done().
+ *
+ * Beside STOP, there are other R1B-type commands that use the busy
+ * signal after CMDRDY: CMD7 (card select), CMD28-29 (write protect),
+ * CMD38 (erase). I haven't tested any of them, but I rather expect
+ * them all to have the same sort of problem with MCI_SR not actually
+ * reflecting the state of the DAT0-line busy indicator. So this code
+ * may need to grow some sort of special handling for them too. (This
+ * just in: CMD7 isn't a problem right now because dev/mmc.c incorrectly
+ * sets the response flags to R1 rather than R1B.) XXX
+ */
+ if ((cmd->flags & MMC_RSP_BUSY)) {
+ WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY);
+ return;
+ }
+
+ /*
+ * If there is a data transfer with this command, then...
+ * - If it's a read, we need to wait for ENDRX.
+ * - If it's a write, now is the time to enable the PDC, and we need
+ * to wait for a BLKE that follows a TXBUFE, because if we're doing
+ * a split transfer we get a BLKE after the first half (when TPR/TCR
+ * get loaded from TNPR/TNCR). So first we wait for the TXBUFE, and
+ * the handling for that interrupt will then invoke the wait for the
+ * subsequent BLKE which indicates actual completion.
+ */
+ if (cmd->data) {
+ uint32_t ier;
+ if (cmd->data->flags & MMC_DATA_READ) {
+ ier = MCI_SR_ENDRX;
+ } else {
+ ier = MCI_SR_TXBUFE;
+ WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN);
+ }
+ WR4(sc, MCI_IER, MCI_SR_ERROR | ier);
+ return;
+ }
+
+ /*
+ * If we made it to here, we don't need to wait for anything more for
+ * the current command, move on to the next command (will complete the
+ * request if there is no next command).
+ */
+ cmd->error = MMC_ERR_NONE;
+ at91_mci_next_operation(sc);
+}
+
+static void
+at91_mci_intr(void *arg)
+{
+ struct at91_mci_softc *sc = (struct at91_mci_softc*)arg;
+ struct mmc_command *cmd = sc->curcmd;
+ uint32_t sr, isr;
+
+ AT91_MCI_LOCK(sc);
+
+ sr = RD4(sc, MCI_SR);
+ isr = sr & RD4(sc, MCI_IMR);
+
+ if (mci_debug)
+ printf("i 0x%x sr 0x%x\n", isr, sr);
+
+ /*
+ * All interrupts are one-shot; disable it now.
+ * The next operation will re-enable whatever interrupts it wants.
+ */
+ WR4(sc, MCI_IDR, isr);
+ if (isr & MCI_SR_ERROR) {
+ if (isr & (MCI_SR_RTOE | MCI_SR_DTOE))
+ cmd->error = MMC_ERR_TIMEOUT;
+ else if (isr & (MCI_SR_RCRCE | MCI_SR_DCRCE))
+ cmd->error = MMC_ERR_BADCRC;
+ else if (isr & (MCI_SR_OVRE | MCI_SR_UNRE))
+ cmd->error = MMC_ERR_FIFO;
+ else
+ cmd->error = MMC_ERR_FAILED;
+ /*
+ * CMD8 is used to probe for SDHC cards, a standard SD card
+ * will get a response timeout; don't report it because it's a
+ * normal and expected condition. One might argue that all
+ * error reporting should be left to higher levels, but when
+ * they report at all it's always EIO, which isn't very
+ * helpful. XXX bootverbose?
+ */
+ if (cmd->opcode != 8) {
+ device_printf(sc->dev,
+ "IO error; status MCI_SR = 0x%x cmd opcode = %d%s\n",
+ sr, cmd->opcode,
+ (cmd->opcode != 12) ? "" :
+ (sc->flags & CMD_MULTIREAD) ? " after read" : " after write");
+ at91_mci_reset(sc);
+ }
+ at91_mci_next_operation(sc);
+ } else {
+ if (isr & MCI_SR_TXBUFE) {
+// printf("TXBUFE\n");
+ /*
+ * We need to wait for a BLKE that follows TXBUFE
+ * (intermediate BLKEs might happen after ENDTXes if
+ * we're chaining multiple buffers). If BLKE is also
+ * asserted at the time we get TXBUFE, we can avoid
+ * another interrupt and process it right away, below.
+ */
+ if (sr & MCI_SR_BLKE)
+ isr |= MCI_SR_BLKE;
+ else
+ WR4(sc, MCI_IER, MCI_SR_BLKE);
+ }
+ if (isr & MCI_SR_RXBUFF) {
+// printf("RXBUFF\n");
+ }
+ if (isr & MCI_SR_ENDTX) {
+// printf("ENDTX\n");
+ }
+ if (isr & MCI_SR_ENDRX) {
+// printf("ENDRX\n");
+ at91_mci_read_done(sc, sr);
+ }
+ if (isr & MCI_SR_NOTBUSY) {
+// printf("NOTBUSY\n");
+ at91_mci_notbusy(sc);
+ }
+ if (isr & MCI_SR_DTIP) {
+// printf("Data transfer in progress\n");
+ }
+ if (isr & MCI_SR_BLKE) {
+// printf("Block transfer end\n");
+ at91_mci_write_done(sc, sr);
+ }
+ if (isr & MCI_SR_TXRDY) {
+// printf("Ready to transmit\n");
+ }
+ if (isr & MCI_SR_RXRDY) {
+// printf("Ready to receive\n");
+ }
+ if (isr & MCI_SR_CMDRDY) {
+// printf("Command ready\n");
+ at91_mci_cmdrdy(sc, sr);
+ }
+ }
+ AT91_MCI_UNLOCK(sc);
+}
+
+static int
+at91_mci_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
+{
+ struct at91_mci_softc *sc = device_get_softc(bus);
+
+ switch (which) {
+ default:
+ return (EINVAL);
+ case MMCBR_IVAR_BUS_MODE:
+ *(int *)result = sc->host.ios.bus_mode;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ *(int *)result = sc->host.ios.bus_width;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ *(int *)result = sc->host.ios.chip_select;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ *(int *)result = sc->host.ios.clock;
+ break;
+ case MMCBR_IVAR_F_MIN:
+ *(int *)result = sc->host.f_min;
+ break;
+ case MMCBR_IVAR_F_MAX:
+ *(int *)result = sc->host.f_max;
+ break;
+ case MMCBR_IVAR_HOST_OCR:
+ *(int *)result = sc->host.host_ocr;
+ break;
+ case MMCBR_IVAR_MODE:
+ *(int *)result = sc->host.mode;
+ break;
+ case MMCBR_IVAR_OCR:
+ *(int *)result = sc->host.ocr;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ *(int *)result = sc->host.ios.power_mode;
+ break;
+ case MMCBR_IVAR_VDD:
+ *(int *)result = sc->host.ios.vdd;
+ break;
+ case MMCBR_IVAR_CAPS:
+ if (sc->has_4wire) {
+ sc->sc_cap |= CAP_HAS_4WIRE;
+ sc->host.caps |= MMC_CAP_4_BIT_DATA;
+ } else {
+ sc->sc_cap &= ~CAP_HAS_4WIRE;
+ sc->host.caps &= ~MMC_CAP_4_BIT_DATA;
+ }
+ *(int *)result = sc->host.caps;
+ break;
+ case MMCBR_IVAR_MAX_DATA:
+ /*
+ * Something is wrong with the 2x parts and multiblock, so
+ * just do 1 block at a time for now, which really kills
+ * performance.
+ */
+ if (sc->sc_cap & CAP_MCI1_REV2XX)
+ *(int *)result = 1;
+ else
+ *(int *)result = MAX_BLOCKS;
+ break;
+ }
+ return (0);
+}
+
+static int
+at91_mci_write_ivar(device_t bus, device_t child, int which, uintptr_t value)
+{
+ struct at91_mci_softc *sc = device_get_softc(bus);
+
+ switch (which) {
+ default:
+ return (EINVAL);
+ case MMCBR_IVAR_BUS_MODE:
+ sc->host.ios.bus_mode = value;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ sc->host.ios.bus_width = value;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ sc->host.ios.chip_select = value;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ sc->host.ios.clock = value;
+ break;
+ case MMCBR_IVAR_MODE:
+ sc->host.mode = value;
+ break;
+ case MMCBR_IVAR_OCR:
+ sc->host.ocr = value;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ sc->host.ios.power_mode = value;
+ break;
+ case MMCBR_IVAR_VDD:
+ sc->host.ios.vdd = value;
+ break;
+ /* These are read-only */
+ case MMCBR_IVAR_CAPS:
+ case MMCBR_IVAR_HOST_OCR:
+ case MMCBR_IVAR_F_MIN:
+ case MMCBR_IVAR_F_MAX:
+ case MMCBR_IVAR_MAX_DATA:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static device_method_t at91_mci_methods[] = {
+ /* device_if */
+ DEVMETHOD(device_probe, at91_mci_probe),
+ DEVMETHOD(device_attach, at91_mci_attach),
+ DEVMETHOD(device_detach, at91_mci_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, at91_mci_read_ivar),
+ DEVMETHOD(bus_write_ivar, at91_mci_write_ivar),
+
+ /* mmcbr_if */
+ DEVMETHOD(mmcbr_update_ios, at91_mci_update_ios),
+ DEVMETHOD(mmcbr_request, at91_mci_request),
+ DEVMETHOD(mmcbr_get_ro, at91_mci_get_ro),
+ DEVMETHOD(mmcbr_acquire_host, at91_mci_acquire_host),
+ DEVMETHOD(mmcbr_release_host, at91_mci_release_host),
+
+ DEVMETHOD_END
+};
+
+static driver_t at91_mci_driver = {
+ "at91_mci",
+ at91_mci_methods,
+ sizeof(struct at91_mci_softc),
+};
+
+static devclass_t at91_mci_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_mci, simplebus, at91_mci_driver, at91_mci_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_mci, atmelarm, at91_mci_driver, at91_mci_devclass, NULL,
+ NULL);
+#endif
+
+MMC_DECLARE_BRIDGE(at91_mci);
Property changes on: trunk/sys/arm/at91/at91_mci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_mcireg.h
===================================================================
--- trunk/sys/arm/at91/at91_mcireg.h (rev 0)
+++ trunk/sys/arm/at91/at91_mcireg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,133 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Berndt Walter. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_mcireg.h 234560 2012-04-22 00:43:32Z marius $ */
+
+#ifndef ARM_AT91_AT91_MCIREG_H
+#define ARM_AT91_AT91_MCIREG_H
+
+#define MMC_MAX 30
+
+#define MCI_CR 0x00 /* MCI Control Register */
+#define MCI_MR 0x04 /* MCI Mode Register */
+#define MCI_DTOR 0x08 /* MCI Data Timeout Register */
+#define MCI_SDCR 0x0c /* MCI SD Card Register */
+#define MCI_ARGR 0x10 /* MCI Argument Register */
+#define MCI_CMDR 0x14 /* MCI Command Register */
+#define MCI_RSPR 0x20 /* MCI Response Registers - 4 of them */
+#define MCI_RDR 0x30 /* MCI Receive Data Register */
+#define MCI_TDR 0x34 /* MCI Transmit Data Register */
+#define MCI_SR 0x40 /* MCI Status Register */
+#define MCI_IER 0x44 /* MCI Interrupt Enable Register */
+#define MCI_IDR 0x48 /* MCI Interrupt Disable Register */
+#define MCI_IMR 0x4c /* MCI Interrupt Mask Register */
+
+/* -------- MCI_CR : (MCI Offset: 0x0) MCI Control Register -------- */
+#define MCI_CR_MCIEN (0x1u << 0) /* (MCI) Multimedia Interface Enable */
+#define MCI_CR_MCIDIS (0x1u << 1) /* (MCI) Multimedia Interface Disable */
+#define MCI_CR_PWSEN (0x1u << 2) /* (MCI) Power Save Mode Enable */
+#define MCI_CR_PWSDIS (0x1u << 3) /* (MCI) Power Save Mode Disable */
+#define MCI_CR_SWRST (0x1u << 7) /* (MCI) Software Reset */
+/* -------- MCI_MR : (MCI Offset: 0x4) MCI Mode Register -------- */
+#define MCI_MR_CLKDIV (0xffu << 0) /* (MCI) Clock Divider */
+#define MCI_MR_PWSDIV (0x3fu << 8) /* (MCI) Power Saving Divider */
+#define MCI_MR_RDPROOF (0x1u << 11) /* (MCI) Read Proof Enable */
+#define MCI_MR_WRPROOF (0x1u << 12) /* (MCI) Write Proof Enable */
+#define MCI_MR_PDCFBYTE (0x1u << 13) /* (MCI) PDC Force Byte Transfer */
+#define MCI_MR_PDCPADV (0x1u << 14) /* (MCI) PDC Padding Value */
+#define MCI_MR_PDCMODE (0x1u << 15) /* (MCI) PDC Oriented Mode */
+#define MCI_MR_BLKLEN 0x3fff0000ul /* (MCI) Data Block Length */
+/* -------- MCI_DTOR : (MCI Offset: 0x8) MCI Data Timeout Register -------- */
+#define MCI_DTOR_DTOCYC (0xfu << 0) /* (MCI) Data Timeout Cycle Number */
+#define MCI_DTOR_DTOMUL (0x7u << 4) /* (MCI) Data Timeout Multiplier */
+#define MCI_DTOR_DTOMUL_1 (0x0u << 4) /* (MCI) DTOCYC x 1 */
+#define MCI_DTOR_DTOMUL_16 (0x1u << 4) /* (MCI) DTOCYC x 16 */
+#define MCI_DTOR_DTOMUL_128 (0x2u << 4) /* (MCI) DTOCYC x 128 */
+#define MCI_DTOR_DTOMUL_256 (0x3u << 4) /* (MCI) DTOCYC x 256 */
+#define MCI_DTOR_DTOMUL_1k (0x4u << 4) /* (MCI) DTOCYC x 1024 */
+#define MCI_DTOR_DTOMUL_4k (0x5u << 4) /* (MCI) DTOCYC x 4096 */
+#define MCI_DTOR_DTOMUL_64k (0x6u << 4) /* (MCI) DTOCYC x 65536 */
+#define MCI_DTOR_DTOMUL_1M (0x7u << 4) /* (MCI) DTOCYC x 1048576 */
+/* -------- MCI_SDCR : (MCI Offset: 0xc) MCI SD Card Register -------- */
+#define MCI_SDCR_SDCSEL (0x1u << 0) /* (MCI) SD Card Selector */
+#define MCI_SDCR_SDCBUS (0x1u << 7) /* (MCI) SD Card Bus Width */
+/* -------- MCI_CMDR : (MCI Offset: 0x14) MCI Command Register -------- */
+#define MCI_CMDR_CMDNB (0x1Fu << 0) /* (MCI) Command Number */
+#define MCI_CMDR_RSPTYP (0x3u << 6) /* (MCI) Response Type */
+#define MCI_CMDR_RSPTYP_NO (0x0u << 6) /* (MCI) No response */
+#define MCI_CMDR_RSPTYP_48 (0x1u << 6) /* (MCI) 48-bit response */
+#define MCI_CMDR_RSPTYP_136 (0x2u << 6) /* (MCI) 136-bit response */
+#define MCI_CMDR_SPCMD (0x7u << 8) /* (MCI) Special CMD */
+#define MCI_CMDR_SPCMD_NONE (0x0u << 8) /* (MCI) Not a special CMD */
+#define MCI_CMDR_SPCMD_INIT (0x1u << 8) /* (MCI) Initialization CMD */
+#define MCI_CMDR_SPCMD_SYNC (0x2u << 8) /* (MCI) Synchronized CMD */
+#define MCI_CMDR_SPCMD_IT_CMD (0x4u << 8) /* (MCI) Interrupt command */
+#define MCI_CMDR_SPCMD_IT_REP (0x5u << 8) /* (MCI) Interrupt response */
+#define MCI_CMDR_OPDCMD (0x1u << 11) /* (MCI) Open Drain Command */
+#define MCI_CMDR_MAXLAT (0x1u << 12) /* (MCI) Maximum Latency for Command to respond */
+#define MCI_CMDR_TRCMD (0x3u << 16) /* (MCI) Transfer CMD */
+#define MCI_CMDR_TRCMD_NO (0x0u << 16) /* (MCI) No transfer */
+#define MCI_CMDR_TRCMD_START (0x1u << 16) /* (MCI) Start transfer */
+#define MCI_CMDR_TRCMD_STOP (0x2u << 16) /* (MCI) Stop transfer */
+#define MCI_CMDR_TRDIR (0x1u << 18) /* (MCI) Transfer Direction */
+#define MCI_CMDR_TRTYP (0x3u << 19) /* (MCI) Transfer Type */
+#define MCI_CMDR_TRTYP_BLOCK (0x0u << 19) /* (MCI) Block Transfer type */
+#define MCI_CMDR_TRTYP_MULTIPLE (0x1u << 19) /* (MCI) Multiple Block transfer type */
+#define MCI_CMDR_TRTYP_STREAM (0x2u << 19) /* (MCI) Stream transfer type */
+/* -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register -------- */
+#define MCI_SR_CMDRDY (0x1u << 0) /* (MCI) Command Ready flag */
+#define MCI_SR_RXRDY (0x1u << 1) /* (MCI) RX Ready flag */
+#define MCI_SR_TXRDY (0x1u << 2) /* (MCI) TX Ready flag */
+#define MCI_SR_BLKE (0x1u << 3) /* (MCI) Data Block Transfer Ended flag */
+#define MCI_SR_DTIP (0x1u << 4) /* (MCI) Data Transfer in Progress flag */
+#define MCI_SR_NOTBUSY (0x1u << 5) /* (MCI) Data Line Not Busy flag */
+#define MCI_SR_ENDRX (0x1u << 6) /* (MCI) End of RX Buffer flag */
+#define MCI_SR_ENDTX (0x1u << 7) /* (MCI) End of TX Buffer flag */
+#define MCI_SR_RXBUFF (0x1u << 14) /* (MCI) RX Buffer Full flag */
+#define MCI_SR_TXBUFE (0x1u << 15) /* (MCI) TX Buffer Empty flag */
+#define MCI_SR_RINDE (0x1u << 16) /* (MCI) Response Index Error flag */
+#define MCI_SR_RDIRE (0x1u << 17) /* (MCI) Response Direction Error flag */
+#define MCI_SR_RCRCE (0x1u << 18) /* (MCI) Response CRC Error flag */
+#define MCI_SR_RENDE (0x1u << 19) /* (MCI) Response End Bit Error flag */
+#define MCI_SR_RTOE (0x1u << 20) /* (MCI) Response Time-out Error flag */
+#define MCI_SR_DCRCE (0x1u << 21) /* (MCI) data CRC Error flag */
+#define MCI_SR_DTOE (0x1u << 22) /* (MCI) Data timeout Error flag */
+#define MCI_SR_OVRE (0x1u << 30) /* (MCI) Overrun flag */
+#define MCI_SR_UNRE (0x1u << 31) /* (MCI) Underrun flag */
+
+/* -------- MCI_IER : (MCI Offset: 0x44) MCI Interrupt Enable Register -------- */
+/* -------- MCI_IDR : (MCI Offset: 0x48) MCI Interrupt Disable Register -------- */
+/* -------- MCI_IMR : (MCI Offset: 0x4c) MCI Interrupt Mask Register -------- */
+
+#define MCI_SR_ERROR (MCI_SR_UNRE | MCI_SR_OVRE | MCI_SR_DTOE | \
+ MCI_SR_DCRCE | MCI_SR_RTOE | MCI_SR_RENDE | \
+ MCI_SR_RCRCE | MCI_SR_RDIRE | MCI_SR_RINDE)
+
+#define AT91C_BUS_WIDTH_1BIT 0x00
+#define AT91C_BUS_WIDTH_4BITS 0x02
+
+#endif /* ARM_AT91_AT91_MCIREG_H */
Property changes on: trunk/sys/arm/at91/at91_mcireg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pdcreg.h
===================================================================
--- trunk/sys/arm/at91/at91_pdcreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_pdcreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,49 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_pdcreg.h 185265 2008-11-25 00:13:26Z imp $ */
+
+#ifndef ARM_AT91_AT91_PDCREG_H
+#define ARM_AT91_AT91_PDCREG_H
+
+#define PDC_RPR 0x100 /* PDC Receive Pointer Register */
+#define PDC_RCR 0x104 /* PDC Receive Counter Register */
+#define PDC_TPR 0x108 /* PDC Transmit Pointer Register */
+#define PDC_TCR 0x10c /* PDC Transmit Counter Register */
+#define PDC_RNPR 0x110 /* PDC Receive Next Pointer Register */
+#define PDC_RNCR 0x114 /* PDC Receive Next Counter Register */
+#define PDC_TNPR 0x118 /* PDC Transmit Next Pointer Reg */
+#define PDC_TNCR 0x11c /* PDC Transmit Next Counter Reg */
+#define PDC_PTCR 0x120 /* PDC Transfer Control Register */
+#define PDC_PTSR 0x124 /* PDC Transfer Status Register */
+
+/* PTCR/PTSR */
+#define PDC_PTCR_RXTEN (1UL << 0) /* RXTEN: Receiver Transfer Enable */
+#define PDC_PTCR_RXTDIS (1UL << 1) /* RXTDIS: Receiver Transfer Disable */
+#define PDC_PTCR_TXTEN (1UL << 8) /* TXTEN: Transmitter Transfer En */
+#define PDC_PTCR_TXTDIS (1UL << 9) /* TXTDIS: Transmitter Transmit Dis */
+
+#endif /* ARM_AT91_AT91_PDCREG_H */
Property changes on: trunk/sys/arm/at91/at91_pdcreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pinctrl.c
===================================================================
--- trunk/sys/arm/at91/at91_pinctrl.c (rev 0)
+++ trunk/sys/arm/at91/at91_pinctrl.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,525 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_pinctrl.c 273652 2014-10-26 01:30:46Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_piovar.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#define BUS_PASS_PINMUX (BUS_PASS_INTERRUPT + 1)
+
+struct pinctrl_range {
+ uint64_t bus;
+ uint64_t host;
+ uint64_t size;
+};
+
+struct pinctrl_softc {
+ device_t dev;
+ phandle_t node;
+
+ struct pinctrl_range *ranges;
+ int nranges;
+
+ pcell_t acells, scells;
+ int done_pinmux;
+};
+
+struct pinctrl_devinfo {
+ struct ofw_bus_devinfo obdinfo;
+ struct resource_list rl;
+};
+
+static int
+at91_pinctrl_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-pinctrl"))
+ return (ENXIO);
+ device_set_desc(dev, "pincontrol bus");
+ return (0);
+}
+
+/* XXX Make this a subclass of simplebus */
+
+static struct pinctrl_devinfo *
+at91_pinctrl_setup_dinfo(device_t dev, phandle_t node)
+{
+ struct pinctrl_softc *sc;
+ struct pinctrl_devinfo *ndi;
+ uint32_t *reg, *intr, icells;
+ uint64_t phys, size;
+ phandle_t iparent;
+ int i, j, k;
+ int nintr;
+ int nreg;
+
+ sc = device_get_softc(dev);
+
+ ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
+ if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
+ free(ndi, M_DEVBUF);
+ return (NULL);
+ }
+
+ resource_list_init(&ndi->rl);
+ nreg = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)®);
+ if (nreg == -1)
+ nreg = 0;
+ if (nreg % (sc->acells + sc->scells) != 0) {
+// if (bootverbose)
+ device_printf(dev, "Malformed reg property on <%s>\n",
+ ndi->obdinfo.obd_name);
+ nreg = 0;
+ }
+
+ for (i = 0, k = 0; i < nreg; i += sc->acells + sc->scells, k++) {
+ phys = size = 0;
+ for (j = 0; j < sc->acells; j++) {
+ phys <<= 32;
+ phys |= reg[i + j];
+ }
+ for (j = 0; j < sc->scells; j++) {
+ size <<= 32;
+ size |= reg[i + sc->acells + j];
+ }
+
+ resource_list_add(&ndi->rl, SYS_RES_MEMORY, k,
+ phys, phys + size - 1, size);
+ }
+ free(reg, M_OFWPROP);
+
+ nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr),
+ (void **)&intr);
+ if (nintr > 0) {
+ if (OF_searchencprop(node, "interrupt-parent", &iparent,
+ sizeof(iparent)) == -1) {
+ device_printf(dev, "No interrupt-parent found, "
+ "assuming direct parent\n");
+ iparent = OF_parent(node);
+ }
+ if (OF_searchencprop(OF_node_from_xref(iparent),
+ "#interrupt-cells", &icells, sizeof(icells)) == -1) {
+ device_printf(dev, "Missing #interrupt-cells property, "
+ "assuming <1>\n");
+ icells = 1;
+ }
+ if (icells < 1 || icells > nintr) {
+ device_printf(dev, "Invalid #interrupt-cells property "
+ "value <%d>, assuming <1>\n", icells);
+ icells = 1;
+ }
+ for (i = 0, k = 0; i < nintr; i += icells, k++) {
+ intr[i] = ofw_bus_map_intr(dev, iparent, icells,
+ &intr[i]);
+ resource_list_add(&ndi->rl, SYS_RES_IRQ, k, intr[i],
+ intr[i], 1);
+ }
+ free(intr, M_OFWPROP);
+ }
+
+ return (ndi);
+}
+
+static int
+at91_pinctrl_fill_ranges(phandle_t node, struct pinctrl_softc *sc)
+{
+ int host_address_cells;
+ cell_t *base_ranges;
+ ssize_t nbase_ranges;
+ int err;
+ int i, j, k;
+
+ err = OF_searchencprop(OF_parent(node), "#address-cells",
+ &host_address_cells, sizeof(host_address_cells));
+ if (err <= 0)
+ return (-1);
+
+ nbase_ranges = OF_getproplen(node, "ranges");
+ if (nbase_ranges < 0)
+ return (-1);
+ sc->nranges = nbase_ranges / sizeof(cell_t) /
+ (sc->acells + host_address_cells + sc->scells);
+ if (sc->nranges == 0)
+ return (0);
+
+ sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]),
+ M_DEVBUF, M_WAITOK);
+ base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
+ OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+
+ for (i = 0, j = 0; i < sc->nranges; i++) {
+ sc->ranges[i].bus = 0;
+ for (k = 0; k < sc->acells; k++) {
+ sc->ranges[i].bus <<= 32;
+ sc->ranges[i].bus |= base_ranges[j++];
+ }
+ sc->ranges[i].host = 0;
+ for (k = 0; k < host_address_cells; k++) {
+ sc->ranges[i].host <<= 32;
+ sc->ranges[i].host |= base_ranges[j++];
+ }
+ sc->ranges[i].size = 0;
+ for (k = 0; k < sc->scells; k++) {
+ sc->ranges[i].size <<= 32;
+ sc->ranges[i].size |= base_ranges[j++];
+ }
+ }
+
+ free(base_ranges, M_DEVBUF);
+ return (sc->nranges);
+}
+
+static int
+at91_pinctrl_attach(device_t dev)
+{
+ struct pinctrl_softc *sc;
+ struct pinctrl_devinfo *di;
+ phandle_t node;
+ device_t cdev;
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+
+ sc->dev = dev;
+ sc->node = node;
+
+ /*
+ * Some important numbers
+ */
+ sc->acells = 2;
+ OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
+ sc->scells = 1;
+ OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));
+
+ if (at91_pinctrl_fill_ranges(node, sc) < 0) {
+ device_printf(dev, "could not get ranges\n");
+ return (ENXIO);
+ }
+
+ for (node = OF_child(node); node > 0; node = OF_peer(node)) {
+ if ((di = at91_pinctrl_setup_dinfo(dev, node)) == NULL)
+ continue;
+ cdev = device_add_child(dev, NULL, -1);
+ if (cdev == NULL) {
+ device_printf(dev, "<%s>: device_add_child failed\n",
+ di->obdinfo.obd_name);
+ resource_list_free(&di->rl);
+ ofw_bus_gen_destroy_devinfo(&di->obdinfo);
+ free(di, M_DEVBUF);
+ continue;
+ }
+ device_set_ivars(cdev, di);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static const struct ofw_bus_devinfo *
+pinctrl_get_devinfo(device_t bus __unused, device_t child)
+{
+ struct pinctrl_devinfo *ndi;
+
+ ndi = device_get_ivars(child);
+ return (&ndi->obdinfo);
+}
+
+static struct resource *
+pinctrl_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct pinctrl_softc *sc;
+ struct pinctrl_devinfo *di;
+ struct resource_list_entry *rle;
+ int j;
+
+ sc = device_get_softc(bus);
+
+ /*
+ * Request for the default allocation with a given rid: use resource
+ * list stored in the local device info.
+ */
+ if ((start == 0UL) && (end == ~0UL)) {
+ if ((di = device_get_ivars(child)) == NULL)
+ return (NULL);
+
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ rle = resource_list_find(&di->rl, type, *rid);
+ if (rle == NULL) {
+// if (bootverbose)
+ device_printf(bus, "no default resources for "
+ "rid = %d, type = %d\n", *rid, type);
+ return (NULL);
+ }
+ start = rle->start;
+ end = rle->end;
+ count = rle->count;
+ }
+
+ if (type == SYS_RES_MEMORY) {
+ /* Remap through ranges property */
+ for (j = 0; j < sc->nranges; j++) {
+ if (start >= sc->ranges[j].bus && end <
+ sc->ranges[j].bus + sc->ranges[j].size) {
+ start -= sc->ranges[j].bus;
+ start += sc->ranges[j].host;
+ end -= sc->ranges[j].bus;
+ end += sc->ranges[j].host;
+ break;
+ }
+ }
+ if (j == sc->nranges && sc->nranges != 0) {
+// if (bootverbose)
+ device_printf(bus, "Could not map resource "
+ "%#lx-%#lx\n", start, end);
+
+ return (NULL);
+ }
+ }
+
+ return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
+}
+
+static int
+pinctrl_print_res(struct pinctrl_devinfo *di)
+{
+ int rv;
+
+ rv = 0;
+ rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#lx");
+ rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%ld");
+ return (rv);
+}
+
+static void
+pinctrl_probe_nomatch(device_t bus, device_t child)
+{
+ const char *name, *type, *compat;
+
+// if (!bootverbose)
+ return;
+
+ name = ofw_bus_get_name(child);
+ type = ofw_bus_get_type(child);
+ compat = ofw_bus_get_compat(child);
+
+ device_printf(bus, "<%s>", name != NULL ? name : "unknown");
+ pinctrl_print_res(device_get_ivars(child));
+ if (!ofw_bus_status_okay(child))
+ printf(" disabled");
+ if (type)
+ printf(" type %s", type);
+ if (compat)
+ printf(" compat %s", compat);
+ printf(" (no driver attached)\n");
+}
+
+static int
+pinctrl_print_child(device_t bus, device_t child)
+{
+ int rv;
+
+ rv = bus_print_child_header(bus, child);
+ rv += pinctrl_print_res(device_get_ivars(child));
+ if (!ofw_bus_status_okay(child))
+ rv += printf(" disabled");
+ rv += bus_print_child_footer(bus, child);
+ return (rv);
+}
+
+const char *periphs[] = {"gpio", "periph A", "periph B", "periph C", "periph D", "periph E" };
+
+static void
+pinctrl_walk_tree(device_t bus, phandle_t node)
+{
+ struct pinctrl_softc *sc;
+ char status[10];
+ char name[32];
+ phandle_t pinctrl[32], pins[32 * 4], scratch;
+ ssize_t len, npins;
+ int i, j;
+
+ sc = device_get_softc(bus);
+ for (node = OF_child(node); node > 0; node = OF_peer(node)) {
+ pinctrl_walk_tree(bus, node);
+ memset(status, 0, sizeof(status));
+ memset(name, 0, sizeof(name));
+ OF_getprop(node, "status", status, sizeof(status));
+ OF_getprop(node, "name", name, sizeof(name));
+ if (strcmp(status, "okay") != 0) {
+// printf("pinctrl: omitting node %s since it isn't active\n", name);
+ continue;
+ }
+ len = OF_getencprop(node, "pinctrl-0", pinctrl, sizeof(pinctrl));
+ if (len <= 0) {
+// printf("pinctrl: no pinctrl-0 property for node %s, omitting\n", name);
+ continue;
+ }
+ len /= sizeof(phandle_t);
+ printf("pinctrl: Found active node %s\n", name);
+ for (i = 0; i < len; i++) {
+ scratch = OF_node_from_xref(pinctrl[i]);
+ npins = OF_getencprop(scratch, "atmel,pins", pins, sizeof(pins));
+ if (npins <= 0) {
+ printf("We're doing it wrong %s\n", name);
+ continue;
+ }
+ memset(name, 0, sizeof(name));
+ OF_getprop(scratch, "name", name, sizeof(name));
+ npins /= (4 * 4);
+ printf("----> need to cope with %d more pins for %s\n", npins, name);
+ for (j = 0; j < npins; j++) {
+ uint32_t unit = pins[j * 4];
+ uint32_t pin = pins[j * 4 + 1];
+ uint32_t periph = pins[j * 4 + 2];
+ uint32_t flags = pins[j * 4 + 3];
+ uint32_t pio = (0xfffffff & sc->ranges[0].bus) + 0x200 * unit;
+ printf("P%c%d %s %#x\n", unit + 'A', pin, periphs[periph],
+ flags);
+ switch (periph) {
+ case 0:
+ at91_pio_use_gpio(pio, 1u << pin);
+ at91_pio_gpio_pullup(pio, 1u << pin, !!(flags & 1));
+ at91_pio_gpio_high_z(pio, 1u << pin, !!(flags & 2));
+ at91_pio_gpio_set_deglitch(pio, 1u << pin, !!(flags & 4));
+ // at91_pio_gpio_pulldown(pio, 1u << pin, !!(flags & 8));
+ // at91_pio_gpio_dis_schmidt(pio, 1u << pin, !!(flags & 16));
+ break;
+ case 1:
+ at91_pio_use_periph_a(pio, 1u << pin, flags);
+ break;
+ case 2:
+ at91_pio_use_periph_b(pio, 1u << pin, flags);
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void
+pinctrl_new_pass(device_t bus)
+{
+ struct pinctrl_softc *sc;
+ phandle_t node;
+
+ sc = device_get_softc(bus);
+
+ bus_generic_new_pass(bus);
+
+ if (sc->done_pinmux || bus_current_pass < BUS_PASS_PINMUX)
+ return;
+ sc->done_pinmux++;
+
+ node = OF_peer(0);
+ if (node == -1)
+ return;
+ pinctrl_walk_tree(bus, node);
+}
+
+static device_method_t at91_pinctrl_methods[] = {
+ DEVMETHOD(device_probe, at91_pinctrl_probe),
+ DEVMETHOD(device_attach, at91_pinctrl_attach),
+
+ DEVMETHOD(bus_print_child, pinctrl_print_child),
+ DEVMETHOD(bus_probe_nomatch, pinctrl_probe_nomatch),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, pinctrl_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+ DEVMETHOD(bus_new_pass, pinctrl_new_pass),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, pinctrl_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ DEVMETHOD_END
+};
+
+static driver_t at91_pinctrl_driver = {
+ "at91_pinctrl",
+ at91_pinctrl_methods,
+ sizeof(struct pinctrl_softc),
+};
+
+static devclass_t at91_pinctrl_devclass;
+
+EARLY_DRIVER_MODULE(at91_pinctrl, simplebus, at91_pinctrl_driver, at91_pinctrl_devclass,
+ NULL, NULL, BUS_PASS_BUS);
+
+/*
+ * dummy driver to force pass BUS_PASS_PINMUX to happen.
+ */
+static int
+at91_pingroup_probe(device_t dev)
+{
+ return ENXIO;
+}
+
+static device_method_t at91_pingroup_methods[] = {
+ DEVMETHOD(device_probe, at91_pingroup_probe),
+
+ DEVMETHOD_END
+};
+
+
+static driver_t at91_pingroup_driver = {
+ "at91_pingroup",
+ at91_pingroup_methods,
+ 0,
+};
+
+static devclass_t at91_pingroup_devclass;
+
+EARLY_DRIVER_MODULE(at91_pingroup, at91_pinctrl, at91_pingroup_driver, at91_pingroup_devclass,
+ NULL, NULL, BUS_PASS_PINMUX);
Property changes on: trunk/sys/arm/at91/at91_pinctrl.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pio.c
===================================================================
--- trunk/sys/arm/at91/at91_pio.c (rev 0)
+++ trunk/sys/arm/at91/at91_pio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,651 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (C) 2012 Ian Lepore. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_pio.c 273651 2014-10-26 01:26:53Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/poll.h>
+#include <sys/rman.h>
+#include <sys/selinfo.h>
+#include <sys/sx.h>
+#include <sys/uio.h>
+#include <machine/at91_gpio.h>
+#include <machine/bus.h>
+
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91_pioreg.h>
+#include <arm/at91/at91_piovar.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#define MAX_CHANGE 64
+
+struct at91_pio_softc
+{
+ device_t dev; /* Myself */
+ void *intrhand; /* Interrupt handle */
+ struct resource *irq_res; /* IRQ resource */
+ struct resource *mem_res; /* Memory resource */
+ struct sx sc_mtx; /* basically a perimeter lock */
+ struct cdev *cdev;
+ struct selinfo selp;
+ int buflen;
+ uint8_t buf[MAX_CHANGE];
+ int flags;
+#define OPENED 1
+};
+
+static inline uint32_t
+RD4(struct at91_pio_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct at91_pio_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+#define AT91_PIO_LOCK(_sc) sx_xlock(&(_sc)->sc_mtx)
+#define AT91_PIO_UNLOCK(_sc) sx_xunlock(&(_sc)->sc_mtx)
+#define AT91_PIO_LOCK_INIT(_sc) \
+ sx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev))
+#define AT91_PIO_LOCK_DESTROY(_sc) sx_destroy(&_sc->sc_mtx);
+#define AT91_PIO_ASSERT_LOCKED(_sc) sx_assert(&_sc->sc_mtx, SA_XLOCKED);
+#define AT91_PIO_ASSERT_UNLOCKED(_sc) sx_assert(&_sc->sc_mtx, SA_UNLOCKED);
+#define CDEV2SOFTC(dev) ((dev)->si_drv1)
+
+static devclass_t at91_pio_devclass;
+
+/* bus entry points */
+
+static int at91_pio_probe(device_t dev);
+static int at91_pio_attach(device_t dev);
+static int at91_pio_detach(device_t dev);
+static void at91_pio_intr(void *);
+
+/* helper routines */
+static int at91_pio_activate(device_t dev);
+static void at91_pio_deactivate(device_t dev);
+
+/* cdev routines */
+static d_open_t at91_pio_open;
+static d_close_t at91_pio_close;
+static d_read_t at91_pio_read;
+static d_poll_t at91_pio_poll;
+static d_ioctl_t at91_pio_ioctl;
+
+static struct cdevsw at91_pio_cdevsw =
+{
+ .d_version = D_VERSION,
+ .d_open = at91_pio_open,
+ .d_close = at91_pio_close,
+ .d_read = at91_pio_read,
+ .d_poll = at91_pio_poll,
+ .d_ioctl = at91_pio_ioctl
+};
+
+static int
+at91_pio_probe(device_t dev)
+{
+ const char *name;
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-gpio"))
+ return (ENXIO);
+#endif
+ switch (device_get_unit(dev)) {
+ case 0:
+ name = "PIOA";
+ break;
+ case 1:
+ name = "PIOB";
+ break;
+ case 2:
+ name = "PIOC";
+ break;
+ case 3:
+ name = "PIOD";
+ break;
+ case 4:
+ name = "PIOE";
+ break;
+ case 5:
+ name = "PIOF";
+ break;
+ default:
+ name = "PIO";
+ break;
+ }
+ device_set_desc(dev, name);
+ return (0);
+}
+
+static int
+at91_pio_attach(device_t dev)
+{
+ struct at91_pio_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ err = at91_pio_activate(dev);
+ if (err)
+ goto out;
+
+ if (bootverbose)
+ device_printf(dev, "ABSR: %#x OSR: %#x PSR:%#x ODSR: %#x\n",
+ RD4(sc, PIO_ABSR), RD4(sc, PIO_OSR), RD4(sc, PIO_PSR),
+ RD4(sc, PIO_ODSR));
+ AT91_PIO_LOCK_INIT(sc);
+
+ /*
+ * Activate the interrupt, but disable all interrupts in the hardware.
+ */
+ WR4(sc, PIO_IDR, 0xffffffff);
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
+ NULL, at91_pio_intr, sc, &sc->intrhand);
+ if (err) {
+ AT91_PIO_LOCK_DESTROY(sc);
+ goto out;
+ }
+ sc->cdev = make_dev(&at91_pio_cdevsw, device_get_unit(dev), UID_ROOT,
+ GID_WHEEL, 0600, "pio%d", device_get_unit(dev));
+ if (sc->cdev == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+ sc->cdev->si_drv1 = sc;
+out:
+ if (err)
+ at91_pio_deactivate(dev);
+ return (err);
+}
+
+static int
+at91_pio_detach(device_t dev)
+{
+
+ return (EBUSY); /* XXX */
+}
+
+static int
+at91_pio_activate(device_t dev)
+{
+ struct at91_pio_softc *sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ goto errout;
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->irq_res == NULL)
+ goto errout;
+ return (0);
+errout:
+ at91_pio_deactivate(dev);
+ return (ENOMEM);
+}
+
+static void
+at91_pio_deactivate(device_t dev)
+{
+ struct at91_pio_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->intrhand)
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ sc->intrhand = 0;
+ bus_generic_detach(sc->dev);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = 0;
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ sc->irq_res = 0;
+}
+
+static void
+at91_pio_intr(void *xsc)
+{
+ struct at91_pio_softc *sc = xsc;
+ uint32_t status;
+ int i;
+
+ /* Reading the status also clears the interrupt. */
+ status = RD4(sc, PIO_ISR) & RD4(sc, PIO_IMR);
+ if (status != 0) {
+ AT91_PIO_LOCK(sc);
+ for (i = 0; status != 0 && sc->buflen < MAX_CHANGE; ++i) {
+ if (status & 1)
+ sc->buf[sc->buflen++] = (uint8_t)i;
+ status >>= 1;
+ }
+ AT91_PIO_UNLOCK(sc);
+ wakeup(sc);
+ selwakeup(&sc->selp);
+ }
+}
+
+static int
+at91_pio_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct at91_pio_softc *sc;
+
+ sc = CDEV2SOFTC(dev);
+ AT91_PIO_LOCK(sc);
+ if (!(sc->flags & OPENED)) {
+ sc->flags |= OPENED;
+ }
+ AT91_PIO_UNLOCK(sc);
+ return (0);
+}
+
+static int
+at91_pio_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
+{
+ struct at91_pio_softc *sc;
+
+ sc = CDEV2SOFTC(dev);
+ AT91_PIO_LOCK(sc);
+ sc->flags &= ~OPENED;
+ AT91_PIO_UNLOCK(sc);
+ return (0);
+}
+
+static int
+at91_pio_poll(struct cdev *dev, int events, struct thread *td)
+{
+ struct at91_pio_softc *sc;
+ int revents = 0;
+
+ sc = CDEV2SOFTC(dev);
+ AT91_PIO_LOCK(sc);
+ if (events & (POLLIN | POLLRDNORM)) {
+ if (sc->buflen != 0)
+ revents |= events & (POLLIN | POLLRDNORM);
+ else
+ selrecord(td, &sc->selp);
+ }
+ AT91_PIO_UNLOCK(sc);
+
+ return (revents);
+}
+
+static int
+at91_pio_read(struct cdev *dev, struct uio *uio, int flag)
+{
+ struct at91_pio_softc *sc;
+ int err, ret, len;
+
+ sc = CDEV2SOFTC(dev);
+ AT91_PIO_LOCK(sc);
+ err = 0;
+ ret = 0;
+ while (uio->uio_resid) {
+ while (sc->buflen == 0 && err == 0)
+ err = msleep(sc, &sc->sc_mtx, PCATCH | PZERO, "prd", 0);
+ if (err != 0)
+ break;
+ len = MIN(sc->buflen, uio->uio_resid);
+ err = uiomove(sc->buf, len, uio);
+ if (err != 0)
+ break;
+ /*
+ * If we read the whole thing no datacopy is needed,
+ * otherwise we move the data down.
+ */
+ ret += len;
+ if (sc->buflen == len)
+ sc->buflen = 0;
+ else {
+ bcopy(sc->buf + len, sc->buf, sc->buflen - len);
+ sc->buflen -= len;
+ }
+ /* If there's no data left, end the read. */
+ if (sc->buflen == 0)
+ break;
+ }
+ AT91_PIO_UNLOCK(sc);
+ return (err);
+}
+
+static void
+at91_pio_bang32(struct at91_pio_softc *sc, uint32_t bits, uint32_t datapin,
+ uint32_t clockpin)
+{
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ if (bits & 0x80000000)
+ WR4(sc, PIO_SODR, datapin);
+ else
+ WR4(sc, PIO_CODR, datapin);
+ bits <<= 1;
+ WR4(sc, PIO_CODR, clockpin);
+ WR4(sc, PIO_SODR, clockpin);
+ }
+}
+
+static void
+at91_pio_bang(struct at91_pio_softc *sc, uint8_t bits, uint32_t bitcount,
+ uint32_t datapin, uint32_t clockpin)
+{
+ int i;
+
+ for (i = 0; i < bitcount; i++) {
+ if (bits & 0x80)
+ WR4(sc, PIO_SODR, datapin);
+ else
+ WR4(sc, PIO_CODR, datapin);
+ bits <<= 1;
+ WR4(sc, PIO_CODR, clockpin);
+ WR4(sc, PIO_SODR, clockpin);
+ }
+}
+
+static int
+at91_pio_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
+ struct thread *td)
+{
+ struct at91_pio_softc *sc;
+ struct at91_gpio_cfg *cfg;
+ struct at91_gpio_info *info;
+ struct at91_gpio_bang *bang;
+ struct at91_gpio_bang_many *bangmany;
+ uint32_t i, num;
+ uint8_t many[1024], *walker;
+ int err;
+ int bitcount;
+
+ sc = CDEV2SOFTC(dev);
+ switch(cmd) {
+ case AT91_GPIO_SET: /* turn bits on */
+ WR4(sc, PIO_SODR, *(uint32_t *)data);
+ return (0);
+ case AT91_GPIO_CLR: /* turn bits off */
+ WR4(sc, PIO_CODR, *(uint32_t *)data);
+ return (0);
+ case AT91_GPIO_READ: /* Get the status of input bits */
+ *(uint32_t *)data = RD4(sc, PIO_PDSR);
+ return (0);
+ case AT91_GPIO_CFG: /* Configure AT91_GPIO pins */
+ cfg = (struct at91_gpio_cfg *)data;
+ if (cfg->cfgmask & AT91_GPIO_CFG_INPUT) {
+ WR4(sc, PIO_OER, cfg->iomask & ~cfg->input);
+ WR4(sc, PIO_ODR, cfg->iomask & cfg->input);
+ }
+ if (cfg->cfgmask & AT91_GPIO_CFG_HI_Z) {
+ WR4(sc, PIO_MDDR, cfg->iomask & ~cfg->hi_z);
+ WR4(sc, PIO_MDER, cfg->iomask & cfg->hi_z);
+ }
+ if (cfg->cfgmask & AT91_GPIO_CFG_PULLUP) {
+ WR4(sc, PIO_PUDR, cfg->iomask & ~cfg->pullup);
+ WR4(sc, PIO_PUER, cfg->iomask & cfg->pullup);
+ }
+ if (cfg->cfgmask & AT91_GPIO_CFG_GLITCH) {
+ WR4(sc, PIO_IFDR, cfg->iomask & ~cfg->glitch);
+ WR4(sc, PIO_IFER, cfg->iomask & cfg->glitch);
+ }
+ if (cfg->cfgmask & AT91_GPIO_CFG_GPIO) {
+ WR4(sc, PIO_PDR, cfg->iomask & ~cfg->gpio);
+ WR4(sc, PIO_PER, cfg->iomask & cfg->gpio);
+ }
+ if (cfg->cfgmask & AT91_GPIO_CFG_PERIPH) {
+ WR4(sc, PIO_ASR, cfg->iomask & ~cfg->periph);
+ WR4(sc, PIO_BSR, cfg->iomask & cfg->periph);
+ }
+ if (cfg->cfgmask & AT91_GPIO_CFG_INTR) {
+ WR4(sc, PIO_IDR, cfg->iomask & ~cfg->intr);
+ WR4(sc, PIO_IER, cfg->iomask & cfg->intr);
+ }
+ return (0);
+ case AT91_GPIO_BANG:
+ bang = (struct at91_gpio_bang *)data;
+ at91_pio_bang32(sc, bang->bits, bang->datapin, bang->clockpin);
+ return (0);
+ case AT91_GPIO_BANG_MANY:
+ bangmany = (struct at91_gpio_bang_many *)data;
+ walker = (uint8_t *)bangmany->bits;
+ bitcount = bangmany->numbits;
+ while (bitcount > 0) {
+ num = MIN((bitcount + 7) / 8, sizeof(many));
+ err = copyin(walker, many, num);
+ if (err)
+ return err;
+ for (i = 0; i < num && bitcount > 0; i++, bitcount -= 8)
+ if (bitcount >= 8)
+ at91_pio_bang(sc, many[i], 8, bangmany->datapin, bangmany->clockpin);
+ else
+ at91_pio_bang(sc, many[i], bitcount, bangmany->datapin, bangmany->clockpin);
+ walker += num;
+ }
+ return (0);
+ case AT91_GPIO_INFO: /* Learn about this device's AT91_GPIO bits */
+ info = (struct at91_gpio_info *)data;
+ info->output_status = RD4(sc, PIO_ODSR);
+ info->input_status = RD4(sc, PIO_OSR);
+ info->highz_status = RD4(sc, PIO_MDSR);
+ info->pullup_status = RD4(sc, PIO_PUSR);
+ info->glitch_status = RD4(sc, PIO_IFSR);
+ info->enabled_status = RD4(sc, PIO_PSR);
+ info->periph_status = RD4(sc, PIO_ABSR);
+ info->intr_status = RD4(sc, PIO_IMR);
+ memset(info->extra_status, 0, sizeof(info->extra_status));
+ return (0);
+ }
+ return (ENOTTY);
+}
+
+/*
+ * The following functions are called early in the boot process, so
+ * don't use bus_space, as that isn't yet available when we need to use
+ * them.
+ */
+
+void
+at91_pio_use_periph_a(uint32_t pio, uint32_t periph_a_mask, int use_pullup)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ PIO[PIO_ASR / 4] = periph_a_mask;
+ PIO[PIO_PDR / 4] = periph_a_mask;
+ if (use_pullup)
+ PIO[PIO_PUER / 4] = periph_a_mask;
+ else
+ PIO[PIO_PUDR / 4] = periph_a_mask;
+}
+
+void
+at91_pio_use_periph_b(uint32_t pio, uint32_t periph_b_mask, int use_pullup)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ PIO[PIO_BSR / 4] = periph_b_mask;
+ PIO[PIO_PDR / 4] = periph_b_mask;
+ if (use_pullup)
+ PIO[PIO_PUER / 4] = periph_b_mask;
+ else
+ PIO[PIO_PUDR / 4] = periph_b_mask;
+}
+
+void
+at91_pio_use_gpio(uint32_t pio, uint32_t gpio_mask)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ PIO[PIO_PER / 4] = gpio_mask;
+}
+
+void
+at91_pio_gpio_input(uint32_t pio, uint32_t input_enable_mask)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ PIO[PIO_ODR / 4] = input_enable_mask;
+}
+
+void
+at91_pio_gpio_output(uint32_t pio, uint32_t output_enable_mask, int use_pullup)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ PIO[PIO_OER / 4] = output_enable_mask;
+ if (use_pullup)
+ PIO[PIO_PUER / 4] = output_enable_mask;
+ else
+ PIO[PIO_PUDR / 4] = output_enable_mask;
+}
+
+void
+at91_pio_gpio_high_z(uint32_t pio, uint32_t high_z_mask, int enable)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ if (enable)
+ PIO[PIO_MDER / 4] = high_z_mask;
+ else
+ PIO[PIO_MDDR / 4] = high_z_mask;
+}
+
+void
+at91_pio_gpio_set(uint32_t pio, uint32_t data_mask)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ PIO[PIO_SODR / 4] = data_mask;
+}
+
+void
+at91_pio_gpio_clear(uint32_t pio, uint32_t data_mask)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ PIO[PIO_CODR / 4] = data_mask;
+}
+
+uint32_t
+at91_pio_gpio_get(uint32_t pio, uint32_t data_mask)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ return (PIO[PIO_PDSR / 4] & data_mask);
+}
+
+void
+at91_pio_gpio_set_deglitch(uint32_t pio, uint32_t data_mask, int use_deglitch)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ if (use_deglitch)
+ PIO[PIO_IFER / 4] = data_mask;
+ else
+ PIO[PIO_IFDR / 4] = data_mask;
+}
+
+void
+at91_pio_gpio_pullup(uint32_t pio, uint32_t data_mask, int do_pullup)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ if (do_pullup)
+ PIO[PIO_PUER / 4] = data_mask;
+ else
+ PIO[PIO_PUDR / 4] = data_mask;
+}
+
+void
+at91_pio_gpio_set_interrupt(uint32_t pio, uint32_t data_mask,
+ int enable_interrupt)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ if (enable_interrupt)
+ PIO[PIO_IER / 4] = data_mask;
+ else
+ PIO[PIO_IDR / 4] = data_mask;
+}
+
+uint32_t
+at91_pio_gpio_clear_interrupt(uint32_t pio)
+{
+ uint32_t *PIO = (uint32_t *)(AT91_BASE + pio);
+
+ /* Reading this register will clear the interrupts. */
+ return (PIO[PIO_ISR / 4]);
+}
+
+static void
+at91_pio_new_pass(device_t dev)
+{
+
+ device_printf(dev, "Pass %d\n", bus_current_pass);
+}
+
+static device_method_t at91_pio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, at91_pio_probe),
+ DEVMETHOD(device_attach, at91_pio_attach),
+ DEVMETHOD(device_detach, at91_pio_detach),
+
+ DEVMETHOD(bus_new_pass, at91_pio_new_pass),
+
+ DEVMETHOD_END
+};
+
+static driver_t at91_pio_driver = {
+ "at91_pio",
+ at91_pio_methods,
+ sizeof(struct at91_pio_softc),
+};
+
+EARLY_DRIVER_MODULE(at91_pio, at91_pinctrl, at91_pio_driver, at91_pio_devclass,
+ NULL, NULL, BUS_PASS_INTERRUPT);
Property changes on: trunk/sys/arm/at91/at91_pio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pio_sam9g20.h
===================================================================
--- trunk/sys/arm/at91/at91_pio_sam9g20.h (rev 0)
+++ trunk/sys/arm/at91/at91_pio_sam9g20.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,184 @@
+/* $MidnightBSD$ */
+/*
+ * Theses defines come from an atmel file that says specifically that it
+ * has no copyright.
+ *
+ * These defines are also usable for the AT91SAM9260 which has pin multiplexing
+ * that is identical to the AT91SAM9G20.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_pio_sam9g20.h 213498 2010-10-06 22:40:27Z cognet $ */
+
+#ifndef ARM_AT91_AT91_PIO_SAM9G20_H
+#define ARM_AT91_AT91_PIO_SAM9G20_H
+
+#include <arm/at91/at91_pioreg.h>
+
+
+// *****************************************************************************
+// PIO DEFINITIONS FOR AT91SAM9G20
+// *****************************************************************************
+#define AT91C_PA0_SPI0_MISO (AT91C_PIO_PA0) // SPI 0 Master In Slave
+#define AT91C_PA0_MCDB0 (AT91C_PIO_PA0) // Multimedia Card B Data 0
+#define AT91C_PA1_SPI0_MOSI (AT91C_PIO_PA1) // SPI 0 Master Out Slave
+#define AT91C_PA1_MCCDB (AT91C_PIO_PA1) // Multimedia Card B Command
+#define AT91C_PA10_MCDA2 (AT91C_PIO_PA10) // Multimedia Card A Data 2
+#define AT91C_PA10_ETX2_0 (AT91C_PIO_PA10) // Ethernet MAC Transmit Data 2
+#define AT91C_PA11_MCDA3 (AT91C_PIO_PA11) // Multimedia Card A Data 3
+#define AT91C_PA11_ETX3_0 (AT91C_PIO_PA11) // Ethernet MAC Transmit Data 3
+#define AT91C_PA12_ETX0 (AT91C_PIO_PA12) // Ethernet MAC Transmit Data 0
+#define AT91C_PA13_ETX1 (AT91C_PIO_PA13) // Ethernet MAC Transmit Data 1
+#define AT91C_PA14_ERX0 (AT91C_PIO_PA14) // Ethernet MAC Receive Data 0
+#define AT91C_PA15_ERX1 (AT91C_PIO_PA15) // Ethernet MAC Receive Data 1
+#define AT91C_PA16_ETXEN (AT91C_PIO_PA16) // Ethernet MAC Transmit Enable
+#define AT91C_PA17_ERXDV (AT91C_PIO_PA17) // Ethernet MAC Receive Data Valid
+#define AT91C_PA18_ERXER (AT91C_PIO_PA18) // Ethernet MAC Receive Error
+#define AT91C_PA19_ETXCK (AT91C_PIO_PA19) // Ethernet MAC Transmit Clock/Reference Clock
+#define AT91C_PA2_SPI0_SPCK (AT91C_PIO_PA2) // SPI 0 Serial Clock
+#define AT91C_PA20_EMDC (AT91C_PIO_PA20) // Ethernet MAC Management Data Clock
+#define AT91C_PA21_EMDIO (AT91C_PIO_PA21) // Ethernet MAC Management Data Input/Output
+#define AT91C_PA22_ADTRG (AT91C_PIO_PA22) // ADC Trigger
+#define AT91C_PA22_ETXER (AT91C_PIO_PA22) // Ethernet MAC Transmikt Coding Error
+#define AT91C_PA23_TWD (AT91C_PIO_PA23) // TWI Two-wire Serial Data
+#define AT91C_PA23_ETX2_1 (AT91C_PIO_PA23) // Ethernet MAC Transmit Data 2
+#define AT91C_PA24_TWCK (AT91C_PIO_PA24) // TWI Two-wire Serial Clock
+#define AT91C_PA24_ETX3_1 (AT91C_PIO_PA24) // Ethernet MAC Transmit Data 3
+#define AT91C_PA25_TCLK0 (AT91C_PIO_PA25) // Timer Counter 0 external clock input
+#define AT91C_PA25_ERX2 (AT91C_PIO_PA25) // Ethernet MAC Receive Data 2
+#define AT91C_PA26_TIOA0 (AT91C_PIO_PA26) // Timer Counter 0 Multipurpose Timer I/O Pin A
+#define AT91C_PA26_ERX3 (AT91C_PIO_PA26) // Ethernet MAC Receive Data 3
+#define AT91C_PA27_TIOA1 (AT91C_PIO_PA27) // Timer Counter 1 Multipurpose Timer I/O Pin A
+#define AT91C_PA27_ERXCK (AT91C_PIO_PA27) // Ethernet MAC Receive Clock
+#define AT91C_PA28_TIOA2 (AT91C_PIO_PA28) // Timer Counter 2 Multipurpose Timer I/O Pin A
+#define AT91C_PA28_ECRS (AT91C_PIO_PA28) // Ethernet MAC Carrier Sense/Carrier Sense and Data Valid
+#define AT91C_PA29_SCK1 (AT91C_PIO_PA29) // USART 1 Serial Clock
+#define AT91C_PA29_ECOL (AT91C_PIO_PA29) // Ethernet MAC Collision Detected
+#define AT91C_PA3_SPI0_NPCS0 (AT91C_PIO_PA3) // SPI 0 Peripheral Chip Select 0
+#define AT91C_PA3_MCDB3 (AT91C_PIO_PA3) // Multimedia Card B Data 3
+#define AT91C_PA30_SCK2 (AT91C_PIO_PA30) // USART 2 Serial Clock
+#define AT91C_PA30_RXD4 (AT91C_PIO_PA30) // USART 4 Receive Data
+#define AT91C_PA31_SCK0 (AT91C_PIO_PA31) // USART 0 Serial Clock
+#define AT91C_PA31_TXD4 (AT91C_PIO_PA31) // USART 4 Transmit Data
+#define AT91C_PA4_RTS2 (AT91C_PIO_PA4) // USART 2 Ready To Send
+#define AT91C_PA4_MCDB2 (AT91C_PIO_PA4) // Multimedia Card B Data 2
+#define AT91C_PA5_CTS2 (AT91C_PIO_PA5) // USART 2 Clear To Send
+#define AT91C_PA5_MCDB1 (AT91C_PIO_PA5) // Multimedia Card B Data 1
+#define AT91C_PA6_MCDA0 (AT91C_PIO_PA6) // Multimedia Card A Data 0
+#define AT91C_PA7_MCCDA (AT91C_PIO_PA7) // Multimedia Card A Command
+#define AT91C_PA8_MCCK (AT91C_PIO_PA8) // Multimedia Card Clock
+#define AT91C_PA9_MCDA1 (AT91C_PIO_PA9) // Multimedia Card A Data 1
+#define AT91C_PB0_SPI1_MISO (AT91C_PIO_PB0) // SPI 1 Master In Slave
+#define AT91C_PB0_TIOA3 (AT91C_PIO_PB0) // Timer Counter 3 Multipurpose Timer I/O Pin A
+#define AT91C_PB1_SPI1_MOSI (AT91C_PIO_PB1) // SPI 1 Master Out Slave
+#define AT91C_PB1_TIOB3 (AT91C_PIO_PB1) // Timer Counter 3 Multipurpose Timer I/O Pin B
+#define AT91C_PB10_TXD3 (AT91C_PIO_PB10) // USART 3 Transmit Data
+#define AT91C_PB10_ISI_D8 (AT91C_PIO_PB10) // Image Sensor Data 8
+#define AT91C_PB11_RXD3 (AT91C_PIO_PB11) // USART 3 Receive Data
+#define AT91C_PB11_ISI_D9 (AT91C_PIO_PB11) // Image Sensor Data 9
+#define AT91C_PB12_TXD5 (AT91C_PIO_PB12) // USART 5 Transmit Data
+#define AT91C_PB12_ISI_D10 (AT91C_PIO_PB12) // Image Sensor Data 10
+#define AT91C_PB13_RXD5 (AT91C_PIO_PB13) // USART 5 Receive Data
+#define AT91C_PB13_ISI_D11 (AT91C_PIO_PB13) // Image Sensor Data 11
+#define AT91C_PB14_DRXD (AT91C_PIO_PB14) // DBGU Debug Receive Data
+#define AT91C_PB15_DTXD (AT91C_PIO_PB15) // DBGU Debug Transmit Data
+#define AT91C_PB16_TK0 (AT91C_PIO_PB16) // SSC0 Transmit Clock
+#define AT91C_PB16_TCLK3 (AT91C_PIO_PB16) // Timer Counter 3 external clock input
+#define AT91C_PB17_TF0 (AT91C_PIO_PB17) // SSC0 Transmit Frame Sync
+#define AT91C_PB17_TCLK4 (AT91C_PIO_PB17) // Timer Counter 4 external clock input
+#define AT91C_PB18_TD0 (AT91C_PIO_PB18) // SSC0 Transmit data
+#define AT91C_PB18_TIOB4 (AT91C_PIO_PB18) // Timer Counter 4 Multipurpose Timer I/O Pin B
+#define AT91C_PB19_RD0 (AT91C_PIO_PB19) // SSC0 Receive Data
+#define AT91C_PB19_TIOB5 (AT91C_PIO_PB19) // Timer Counter 5 Multipurpose Timer I/O Pin B
+#define AT91C_PB2_SPI1_SPCK (AT91C_PIO_PB2) // SPI 1 Serial Clock
+#define AT91C_PB2_TIOA4 (AT91C_PIO_PB2) // Timer Counter 4 Multipurpose Timer I/O Pin A
+#define AT91C_PB20_RK0 (AT91C_PIO_PB20) // SSC0 Receive Clock
+#define AT91C_PB20_ISI_D0 (AT91C_PIO_PB20) // Image Sensor Data 0
+#define AT91C_PB21_RF0 (AT91C_PIO_PB21) // SSC0 Receive Frame Sync
+#define AT91C_PB21_ISI_D1 (AT91C_PIO_PB21) // Image Sensor Data 1
+#define AT91C_PB22_DSR0 (AT91C_PIO_PB22) // USART 0 Data Set ready
+#define AT91C_PB22_ISI_D2 (AT91C_PIO_PB22) // Image Sensor Data 2
+#define AT91C_PB23_DCD0 (AT91C_PIO_PB23) // USART 0 Data Carrier Detect
+#define AT91C_PB23_ISI_D3 (AT91C_PIO_PB23) // Image Sensor Data 3
+#define AT91C_PB24_DTR0 (AT91C_PIO_PB24) // USART 0 Data Terminal ready
+#define AT91C_PB24_ISI_D4 (AT91C_PIO_PB24) // Image Sensor Data 4
+#define AT91C_PB25_RI0 (AT91C_PIO_PB25) // USART 0 Ring Indicator
+#define AT91C_PB25_ISI_D5 (AT91C_PIO_PB25) // Image Sensor Data 5
+#define AT91C_PB26_RTS0 (AT91C_PIO_PB26) // USART 0 Ready To Send
+#define AT91C_PB26_ISI_D6 (AT91C_PIO_PB26) // Image Sensor Data 6
+#define AT91C_PB27_CTS0 (AT91C_PIO_PB27) // USART 0 Clear To Send
+#define AT91C_PB27_ISI_D7 (AT91C_PIO_PB27) // Image Sensor Data 7
+#define AT91C_PB28_RTS1 (AT91C_PIO_PB28) // USART 1 Ready To Send
+#define AT91C_PB28_ISI_PCK (AT91C_PIO_PB28) // Image Sensor Data Clock
+#define AT91C_PB29_CTS1 (AT91C_PIO_PB29) // USART 1 Clear To Send
+#define AT91C_PB29_ISI_VSYNC (AT91C_PIO_PB29) // Image Sensor Vertical Synchro
+#define AT91C_PB3_SPI1_NPCS0 (AT91C_PIO_PB3) // SPI 1 Peripheral Chip Select 0
+#define AT91C_PB3_TIOA5 (AT91C_PIO_PB3) // Timer Counter 5 Multipurpose Timer I/O Pin A
+#define AT91C_PB30_PCK0_0 (AT91C_PIO_PB30) // PMC Programmable Clock Output 0
+#define AT91C_PB30_ISI_HSYNC (AT91C_PIO_PB30) // Image Sensor Horizontal Synchro
+#define AT91C_PB31_PCK1_0 (AT91C_PIO_PB31) // PMC Programmable Clock Output 1
+#define AT91C_PB31_ISI_MCK (AT91C_PIO_PB31) // Image Sensor Reference Clock
+#define AT91C_PB4_TXD0 (AT91C_PIO_PB4) // USART 0 Transmit Data
+#define AT91C_PB5_RXD0 (AT91C_PIO_PB5) // USART 0 Receive Data
+#define AT91C_PB6_TXD1 (AT91C_PIO_PB6) // USART 1 Transmit Data
+#define AT91C_PB6_TCLK1 (AT91C_PIO_PB6) // Timer Counter 1 external clock input
+#define AT91C_PB7_RXD1 (AT91C_PIO_PB7) // USART 1 Receive Data
+#define AT91C_PB7_TCLK2 (AT91C_PIO_PB7) // Timer Counter 2 external clock input
+#define AT91C_PB8_TXD2 (AT91C_PIO_PB8) // USART 2 Transmit Data
+#define AT91C_PB9_RXD2 (AT91C_PIO_PB9) // USART 2 Receive Data
+#define AT91C_PC0_AD0 (AT91C_PIO_PC0) // ADC Analog Input 0
+#define AT91C_PC0_SCK3 (AT91C_PIO_PC0) // USART 3 Serial Clock
+#define AT91C_PC1_AD1 (AT91C_PIO_PC1) // ADC Analog Input 1
+#define AT91C_PC1_PCK0_1 (AT91C_PIO_PC1) // PMC Programmable Clock Output 0
+#define AT91C_PC10_A25_CFR NW (AT91C_PIO_PC10) // Address Bus[25]
+#define AT91C_PC10_CTS3 (AT91C_PIO_PC10) // USART 3 Clear To Send
+#define AT91C_PC11_NCS2 (AT91C_PIO_PC11) // Chip Select Line 2
+#define AT91C_PC11_SPI0_NPCS1 (AT91C_PIO_PC11) // SPI 0 Peripheral Chip Select 1
+#define AT91C_PC12_IRQ0 (AT91C_PIO_PC12) // External Interrupt 0
+#define AT91C_PC12_NCS7 (AT91C_PIO_PC12) // Chip Select Line 7
+#define AT91C_PC13_FIQ (AT91C_PIO_PC13) // AIC Fast Interrupt Input
+#define AT91C_PC13_NCS6 (AT91C_PIO_PC13) // Chip Select Line 6
+#define AT91C_PC14_NCS3_NANDCS (AT91C_PIO_PC14) // Chip Select Line 3
+#define AT91C_PC14_IRQ2 (AT91C_PIO_PC14) // External Interrupt 2
+#define AT91C_PC15_NWAIT (AT91C_PIO_PC15) // External Wait Signal
+#define AT91C_PC15_IRQ1 (AT91C_PIO_PC15) // External Interrupt 1
+#define AT91C_PC16_D16 (AT91C_PIO_PC16) // Data Bus[16]
+#define AT91C_PC16_SPI0_NPCS2 (AT91C_PIO_PC16) // SPI 0 Peripheral Chip Select 2
+#define AT91C_PC17_D17 (AT91C_PIO_PC17) // Data Bus[17]
+#define AT91C_PC17_SPI0_NPCS3 (AT91C_PIO_PC17) // SPI 0 Peripheral Chip Select 3
+#define AT91C_PC18_D18 (AT91C_PIO_PC18) // Data Bus[18]
+#define AT91C_PC18_SPI1_NPCS1_1 (AT91C_PIO_PC18) // SPI 1 Peripheral Chip Select 1
+#define AT91C_PC19_D19 (AT91C_PIO_PC19) // Data Bus[19]
+#define AT91C_PC19_SPI1_NPCS2_1 (AT91C_PIO_PC19) // SPI 1 Peripheral Chip Select 2
+#define AT91C_PC2_AD2 (AT91C_PIO_PC2) // ADC Analog Input 2
+#define AT91C_PC2_PCK1_1 (AT91C_PIO_PC2) // PMC Programmable Clock Output 1
+#define AT91C_PC20_D20 (AT91C_PIO_PC20) // Data Bus[20]
+#define AT91C_PC20_SPI1_NPCS3_1 (AT91C_PIO_PC20) // SPI 1 Peripheral Chip Select 3
+#define AT91C_PC21_D21 (AT91C_PIO_PC21) // Data Bus[21]
+#define AT91C_PC21_EF100 (AT91C_PIO_PC21) // Ethernet MAC Force 100 Mbits/sec
+#define AT91C_PC22_D22 (AT91C_PIO_PC22) // Data Bus[22]
+#define AT91C_PC22_TCLK5 (AT91C_PIO_PC22) // Timer Counter 5 external clock input
+#define AT91C_PC23_D23 (AT91C_PIO_PC23) // Data Bus[23]
+#define AT91C_PC24_D24 (AT91C_PIO_PC24) // Data Bus[24]
+#define AT91C_PC25_D25 (AT91C_PIO_PC25) // Data Bus[25]
+#define AT91C_PC26_D26 (AT91C_PIO_PC26) // Data Bus[26]
+#define AT91C_PC27_D27 (AT91C_PIO_PC27) // Data Bus[27]
+#define AT91C_PC28_D28 (AT91C_PIO_PC28) // Data Bus[28]
+#define AT91C_PC29_D29 (AT91C_PIO_PC29) // Data Bus[29]
+#define AT91C_PC3_AD3 (AT91C_PIO_PC3) // ADC Analog Input 3
+#define AT91C_PC3_SPI1_NPCS3_0 (AT91C_PIO_PC3) // SPI 1 Peripheral Chip Select 3
+#define AT91C_PC30_D30 (AT91C_PIO_PC30) // Data Bus[30]
+#define AT91C_PC31_D31 (AT91C_PIO_PC31) // Data Bus[31]
+#define AT91C_PC4_A23 (AT91C_PIO_PC4) // Address Bus[23]
+#define AT91C_PC4_SPI1_NPCS2_0 (AT91C_PIO_PC4) // SPI 1 Peripheral Chip Select 2
+#define AT91C_PC5_A24 (AT91C_PIO_PC5) // Address Bus[24]
+#define AT91C_PC5_SPI1_NPCS1_0 (AT91C_PIO_PC5) // SPI 1 Peripheral Chip Select 1
+#define AT91C_PC6_TIOB2 (AT91C_PIO_PC6) // Timer Counter 2 Multipurpose Timer I/O Pin B
+#define AT91C_PC6_CFCE1 (AT91C_PIO_PC6) // Compact Flash Enable 1
+#define AT91C_PC7_TIOB1 (AT91C_PIO_PC7) // Timer Counter 1 Multipurpose Timer I/O Pin B
+#define AT91C_PC7_CFCE2 (AT91C_PIO_PC7) // Compact Flash Enable 2
+#define AT91C_PC8_NCS4_CFCS0 (AT91C_PIO_PC8) // Chip Select Line 4
+#define AT91C_PC8_RTS3 (AT91C_PIO_PC8) // USART 3 Ready To Send
+#define AT91C_PC9_NCS5_CFCS1 (AT91C_PIO_PC9) // Chip Select Line 5
+#define AT91C_PC9_TIOB0 (AT91C_PIO_PC9) // Timer Counter 0 Multipurpose Timer I/O Pin B
+
+#endif /* ARM_AT91_AT91_PIO_SAM9G20_H */
Property changes on: trunk/sys/arm/at91/at91_pio_sam9g20.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pio_sam9g45.h
===================================================================
--- trunk/sys/arm/at91/at91_pio_sam9g45.h (rev 0)
+++ trunk/sys/arm/at91/at91_pio_sam9g45.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,273 @@
+/* $MidnightBSD$ */
+/*-
+ * ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support - ROUSSET -
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2009, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * 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 disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ *
+ * From AT91LIB version 1.9 boards/at91sam9g45-ek/at91sam9g45/AT91SAM9G45.h
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_pio_sam9g45.h 238788 2012-07-26 08:01:25Z andrew $ */
+
+#ifndef ARM_AT91_AT91_PIO_SAM9G45_H
+#define ARM_AT91_AT91_PIO_SAM9G45_H
+
+#include <arm/at91/at91_pioreg.h>
+
+// *****************************************************************************
+// PIO DEFINITIONS FOR AT91SAM9G45
+// *****************************************************************************
+#define AT91C_PA0_MCI0_CK (AT91C_PIO_PA0) //
+#define AT91C_PA0_TCLK3 (AT91C_PIO_PA0) //
+#define AT91C_PA1_MCI0_CDA (AT91C_PIO_PA1) //
+#define AT91C_PA1_TIOA3 (AT91C_PIO_PA1) //
+#define AT91C_PA10_ETX0 (AT91C_PIO_PA10) // Ethernet MAC Transmit Data 0
+#define AT91C_PA11_ETX1 (AT91C_PIO_PA11) // Ethernet MAC Transmit Data 1
+#define AT91C_PA12_ERX0 (AT91C_PIO_PA12) // Ethernet MAC Receive Data 0
+#define AT91C_PA13_ERX1 (AT91C_PIO_PA13) // Ethernet MAC Receive Data 1
+#define AT91C_PA14_ETXEN (AT91C_PIO_PA14) // Ethernet MAC Transmit Enable
+#define AT91C_PA15_ERXDV (AT91C_PIO_PA15) // Ethernet MAC Receive Data Valid
+#define AT91C_PA16_ERXER (AT91C_PIO_PA16) // Ethernet MAC Receive Error
+#define AT91C_PA17_ETXCK_EREFCK (AT91C_PIO_PA17) // Ethernet MAC Transmit Clock/Reference Clock
+#define AT91C_PA18_EMDC (AT91C_PIO_PA18) // Ethernet MAC Management Data Clock
+#define AT91C_PA19_EMDIO (AT91C_PIO_PA19) // Ethernet MAC Management Data Input/Output
+#define AT91C_PA2_MCI0_DA0 (AT91C_PIO_PA2) //
+#define AT91C_PA2_TIOB3 (AT91C_PIO_PA2) //
+#define AT91C_PA20_TWD0 (AT91C_PIO_PA20) // TWI Two-wire Serial Data
+#define AT91C_PA21_TWCK0 (AT91C_PIO_PA21) // TWI Two-wire Serial Clock
+#define AT91C_PA22_MCI1_CDA (AT91C_PIO_PA22) //
+#define AT91C_PA22_SCK3 (AT91C_PIO_PA22) //
+#define AT91C_PA23_MCI1_DA0 (AT91C_PIO_PA23) //
+#define AT91C_PA23_RTS3 (AT91C_PIO_PA23) //
+#define AT91C_PA24_MCI1_DA1 (AT91C_PIO_PA24) //
+#define AT91C_PA24_CTS3 (AT91C_PIO_PA24) //
+#define AT91C_PA25_MCI1_DA2 (AT91C_PIO_PA25) //
+#define AT91C_PA25_PWM3 (AT91C_PIO_PA25) //
+#define AT91C_PA26_MCI1_DA3 (AT91C_PIO_PA26) //
+#define AT91C_PA26_TIOB2 (AT91C_PIO_PA26) //
+#define AT91C_PA27_MCI1_DA4 (AT91C_PIO_PA27) //
+#define AT91C_PA27_ETXER (AT91C_PIO_PA27) // Ethernet MAC Transmikt Coding Error
+#define AT91C_PA28_MCI1_DA5 (AT91C_PIO_PA28) //
+#define AT91C_PA28_ERXCK (AT91C_PIO_PA28) // Ethernet MAC Receive Clock
+#define AT91C_PA29_MCI1_DA6 (AT91C_PIO_PA29) //
+#define AT91C_PA29_ECRS (AT91C_PIO_PA29) // Ethernet MAC Carrier Sense/Carrier Sense and Data Valid
+#define AT91C_PA3_MCI0_DA1 (AT91C_PIO_PA3) //
+#define AT91C_PA3_TCLK4 (AT91C_PIO_PA3) //
+#define AT91C_PA30_MCI1_DA7 (AT91C_PIO_PA30) //
+#define AT91C_PA30_ECOL (AT91C_PIO_PA30) // Ethernet MAC Collision Detected
+#define AT91C_PA31_MCI1_CK (AT91C_PIO_PA31) //
+#define AT91C_PA31_PCK0 (AT91C_PIO_PA31) //
+#define AT91C_PA4_MCI0_DA2 (AT91C_PIO_PA4) //
+#define AT91C_PA4_TIOA4 (AT91C_PIO_PA4) //
+#define AT91C_PA5_MCI0_DA3 (AT91C_PIO_PA5) //
+#define AT91C_PA5_TIOB4 (AT91C_PIO_PA5) //
+#define AT91C_PA6_MCI0_DA4 (AT91C_PIO_PA6) //
+#define AT91C_PA6_ETX2 (AT91C_PIO_PA6) // Ethernet MAC Transmit Data 2
+#define AT91C_PA7_MCI0_DA5 (AT91C_PIO_PA7) //
+#define AT91C_PA7_ETX3 (AT91C_PIO_PA7) // Ethernet MAC Transmit Data 3
+#define AT91C_PA8_MCI0_DA6 (AT91C_PIO_PA8) //
+#define AT91C_PA8_ERX2 (AT91C_PIO_PA8) // Ethernet MAC Receive Data 2
+#define AT91C_PA9_MCI0_DA7 (AT91C_PIO_PA9) //
+#define AT91C_PA9_ERX3 (AT91C_PIO_PA9) // Ethernet MAC Receive Data 3
+#define AT91C_PB0_SPI0_MISO (AT91C_PIO_PB0) // SPI 0 Master In Slave
+#define AT91C_PB1_SPI0_MOSI (AT91C_PIO_PB1) // SPI 0 Master Out Slave
+#define AT91C_PB10_TWD1 (AT91C_PIO_PB10) //
+#define AT91C_PB10_ISI_D10 (AT91C_PIO_PB10) //
+#define AT91C_PB11_TWCK1 (AT91C_PIO_PB11) //
+#define AT91C_PB11_ISI_D11 (AT91C_PIO_PB11) //
+#define AT91C_PB12_DRXD (AT91C_PIO_PB12) //
+#define AT91C_PB13_DTXD (AT91C_PIO_PB13) //
+#define AT91C_PB14_SPI1_MISO (AT91C_PIO_PB14) //
+#define AT91C_PB15_SPI1_MOSI (AT91C_PIO_PB15) //
+#define AT91C_PB15_CTS0 (AT91C_PIO_PB15) //
+#define AT91C_PB16_SPI1_SPCK (AT91C_PIO_PB16) //
+#define AT91C_PB16_SCK0 (AT91C_PIO_PB16) //
+#define AT91C_PB17_SPI1_NPCS0 (AT91C_PIO_PB17) //
+#define AT91C_PB17_RTS0 (AT91C_PIO_PB17) //
+#define AT91C_PB18_RXD0 (AT91C_PIO_PB18) //
+#define AT91C_PB18_SPI0_NPCS1 (AT91C_PIO_PB18) //
+#define AT91C_PB19_TXD0 (AT91C_PIO_PB19) //
+#define AT91C_PB19_SPI0_NPCS2 (AT91C_PIO_PB19) //
+#define AT91C_PB2_SPI0_SPCK (AT91C_PIO_PB2) // SPI 0 Serial Clock
+#define AT91C_PB20_ISI_D0 (AT91C_PIO_PB20) //
+#define AT91C_PB21_ISI_D1 (AT91C_PIO_PB21) //
+#define AT91C_PB22_ISI_D2 (AT91C_PIO_PB22) //
+#define AT91C_PB23_ISI_D3 (AT91C_PIO_PB23) //
+#define AT91C_PB24_ISI_D4 (AT91C_PIO_PB24) //
+#define AT91C_PB25_ISI_D5 (AT91C_PIO_PB25) //
+#define AT91C_PB26_ISI_D6 (AT91C_PIO_PB26) //
+#define AT91C_PB27_ISI_D7 (AT91C_PIO_PB27) //
+#define AT91C_PB28_ISI_PCK (AT91C_PIO_PB28) //
+#define AT91C_PB29_ISI_VSYNC (AT91C_PIO_PB29) //
+#define AT91C_PB3_SPI0_NPCS0 (AT91C_PIO_PB3) // SPI 0 Peripheral Chip Select 0
+#define AT91C_PB30_ISI_HSYNC (AT91C_PIO_PB30) //
+#define AT91C_PB31_ (AT91C_PIO_PB31) //
+#define AT91C_PB31_PCK1 (AT91C_PIO_PB31) //
+#define AT91C_PB4_TXD1 (AT91C_PIO_PB4) // USART 1 Transmit Data
+#define AT91C_PB5_RXD1 (AT91C_PIO_PB5) // USART 1 Receive Data
+#define AT91C_PB6_TXD2 (AT91C_PIO_PB6) // USART 2 Transmit Data
+#define AT91C_PB7_RXD2 (AT91C_PIO_PB7) // USART 2 Receive Data
+#define AT91C_PB8_TXD3 (AT91C_PIO_PB8) // USART 3 Transmit Data
+#define AT91C_PB8_ISI_D8 (AT91C_PIO_PB8) //
+#define AT91C_PB9_RXD3 (AT91C_PIO_PB9) // USART 3 Receive Data
+#define AT91C_PB9_ISI_D9 (AT91C_PIO_PB9) //
+#define AT91C_PC0_DQM2 (AT91C_PIO_PC0) // DQM2
+#define AT91C_PC1_DQM3 (AT91C_PIO_PC1) // DQM3
+#define AT91C_PC10_NCS4_CFCS0 (AT91C_PIO_PC10) //
+#define AT91C_PC10_TCLK2 (AT91C_PIO_PC10) //
+#define AT91C_PC11_NCS5_CFCS1 (AT91C_PIO_PC11) //
+#define AT91C_PC11_CTS2 (AT91C_PIO_PC11) //
+#define AT91C_PC12_A25_CFRNW (AT91C_PIO_PC12) //
+#define AT91C_PC13_NCS2 (AT91C_PIO_PC13) //
+#define AT91C_PC14_NCS3_NANDCS (AT91C_PIO_PC14) //
+#define AT91C_PC15_NWAIT (AT91C_PIO_PC15) //
+#define AT91C_PC16_D16 (AT91C_PIO_PC16) //
+#define AT91C_PC17_D17 (AT91C_PIO_PC17) //
+#define AT91C_PC18_D18 (AT91C_PIO_PC18) //
+#define AT91C_PC19_D19 (AT91C_PIO_PC19) //
+#define AT91C_PC2_A19 (AT91C_PIO_PC2) //
+#define AT91C_PC20_D20 (AT91C_PIO_PC20) //
+#define AT91C_PC21_D21 (AT91C_PIO_PC21) //
+#define AT91C_PC22_D22 (AT91C_PIO_PC22) //
+#define AT91C_PC23_D23 (AT91C_PIO_PC23) //
+#define AT91C_PC24_D24 (AT91C_PIO_PC24) //
+#define AT91C_PC25_D25 (AT91C_PIO_PC25) //
+#define AT91C_PC26_D26 (AT91C_PIO_PC26) //
+#define AT91C_PC27_D27 (AT91C_PIO_PC27) //
+#define AT91C_PC28_D28 (AT91C_PIO_PC28) //
+#define AT91C_PC29_D29 (AT91C_PIO_PC29) //
+#define AT91C_PC3_A20 (AT91C_PIO_PC3) //
+#define AT91C_PC30_D30 (AT91C_PIO_PC30) //
+#define AT91C_PC31_D31 (AT91C_PIO_PC31) //
+#define AT91C_PC4_A21_NANDALE (AT91C_PIO_PC4) //
+#define AT91C_PC5_A22_NANDCLE (AT91C_PIO_PC5) //
+#define AT91C_PC6_A23 (AT91C_PIO_PC6) //
+#define AT91C_PC7_A24 (AT91C_PIO_PC7) //
+#define AT91C_PC8_CFCE1 (AT91C_PIO_PC8) //
+#define AT91C_PC9_CFCE2 (AT91C_PIO_PC9) //
+#define AT91C_PC9_RTS2 (AT91C_PIO_PC9) //
+#define AT91C_PD0_TK0 (AT91C_PIO_PD0) //
+#define AT91C_PD0_PWM3 (AT91C_PIO_PD0) //
+#define AT91C_PD1_TF0 (AT91C_PIO_PD1) //
+#define AT91C_PD10_TD1 (AT91C_PIO_PD10) //
+#define AT91C_PD11_RD1 (AT91C_PIO_PD11) //
+#define AT91C_PD12_TK1 (AT91C_PIO_PD12) //
+#define AT91C_PD12_PCK0 (AT91C_PIO_PD12) //
+#define AT91C_PD13_RK1 (AT91C_PIO_PD13) //
+#define AT91C_PD14_TF1 (AT91C_PIO_PD14) //
+#define AT91C_PD15_RF1 (AT91C_PIO_PD15) //
+#define AT91C_PD16_RTS1 (AT91C_PIO_PD16) //
+#define AT91C_PD17_CTS1 (AT91C_PIO_PD17) //
+#define AT91C_PD18_SPI1_NPCS2 (AT91C_PIO_PD18) //
+#define AT91C_PD18_IRQ (AT91C_PIO_PD18) //
+#define AT91C_PD19_SPI1_NPCS3 (AT91C_PIO_PD19) //
+#define AT91C_PD19_FIQ (AT91C_PIO_PD19) //
+#define AT91C_PD2_TD0 (AT91C_PIO_PD2) //
+#define AT91C_PD20_TIOA0 (AT91C_PIO_PD20) //
+#define AT91C_PD21_TIOA1 (AT91C_PIO_PD21) //
+#define AT91C_PD22_TIOA2 (AT91C_PIO_PD22) //
+#define AT91C_PD23_TCLK0 (AT91C_PIO_PD23) //
+#define AT91C_PD24_SPI0_NPCS1 (AT91C_PIO_PD24) //
+#define AT91C_PD24_PWM0 (AT91C_PIO_PD24) //
+#define AT91C_PD25_SPI0_NPCS2 (AT91C_PIO_PD25) //
+#define AT91C_PD25_PWM1 (AT91C_PIO_PD25) //
+#define AT91C_PD26_PCK0 (AT91C_PIO_PD26) //
+#define AT91C_PD26_PWM2 (AT91C_PIO_PD26) //
+#define AT91C_PD27_PCK1 (AT91C_PIO_PD27) //
+#define AT91C_PD27_SPI0_NPCS3 (AT91C_PIO_PD27) //
+#define AT91C_PD28_TSADTRG (AT91C_PIO_PD28) //
+#define AT91C_PD28_SPI1_NPCS1 (AT91C_PIO_PD28) //
+#define AT91C_PD29_TCLK1 (AT91C_PIO_PD29) //
+#define AT91C_PD29_SCK1 (AT91C_PIO_PD29) //
+#define AT91C_PD3_RD0 (AT91C_PIO_PD3) //
+#define AT91C_PD30_TIOB0 (AT91C_PIO_PD30) //
+#define AT91C_PD30_SCK2 (AT91C_PIO_PD30) //
+#define AT91C_PD31_TIOB1 (AT91C_PIO_PD31) //
+#define AT91C_PD31_PWM1 (AT91C_PIO_PD31) //
+#define AT91C_PD4_RK0 (AT91C_PIO_PD4) //
+#define AT91C_PD5_RF0 (AT91C_PIO_PD5) //
+#define AT91C_PD6_AC97RX (AT91C_PIO_PD6) //
+#define AT91C_PD7_AC97TX (AT91C_PIO_PD7) //
+#define AT91C_PD7_TIOA5 (AT91C_PIO_PD7) //
+#define AT91C_PD8_AC97FS (AT91C_PIO_PD8) //
+#define AT91C_PD8_TIOB5 (AT91C_PIO_PD8) //
+#define AT91C_PD9_AC97CK (AT91C_PIO_PD9) //
+#define AT91C_PD9_TCLK5 (AT91C_PIO_PD9) //
+#define AT91C_PE0_LCDPWR (AT91C_PIO_PE0) //
+#define AT91C_PE0_PCK0 (AT91C_PIO_PE0) //
+#define AT91C_PE1_LCDMOD (AT91C_PIO_PE1) //
+#define AT91C_PE10_LCDD3 (AT91C_PIO_PE10) //
+#define AT91C_PE10_LCDD5 (AT91C_PIO_PE10) //
+#define AT91C_PE11_LCDD4 (AT91C_PIO_PE11) //
+#define AT91C_PE11_LCDD6 (AT91C_PIO_PE11) //
+#define AT91C_PE12_LCDD5 (AT91C_PIO_PE12) //
+#define AT91C_PE12_LCDD7 (AT91C_PIO_PE12) //
+#define AT91C_PE13_LCDD6 (AT91C_PIO_PE13) //
+#define AT91C_PE13_LCDD10 (AT91C_PIO_PE13) //
+#define AT91C_PE14_LCDD7 (AT91C_PIO_PE14) //
+#define AT91C_PE14_LCDD11 (AT91C_PIO_PE14) //
+#define AT91C_PE15_LCDD8 (AT91C_PIO_PE15) //
+#define AT91C_PE15_LCDD12 (AT91C_PIO_PE15) //
+#define AT91C_PE16_LCDD9 (AT91C_PIO_PE16) //
+#define AT91C_PE16_LCDD13 (AT91C_PIO_PE16) //
+#define AT91C_PE17_LCDD10 (AT91C_PIO_PE17) //
+#define AT91C_PE17_LCDD14 (AT91C_PIO_PE17) //
+#define AT91C_PE18_LCDD11 (AT91C_PIO_PE18) //
+#define AT91C_PE18_LCDD15 (AT91C_PIO_PE18) //
+#define AT91C_PE19_LCDD12 (AT91C_PIO_PE19) //
+#define AT91C_PE19_LCDD18 (AT91C_PIO_PE19) //
+#define AT91C_PE2_LCDCC (AT91C_PIO_PE2) //
+#define AT91C_PE20_LCDD13 (AT91C_PIO_PE20) //
+#define AT91C_PE20_LCDD19 (AT91C_PIO_PE20) //
+#define AT91C_PE21_LCDD14 (AT91C_PIO_PE21) //
+#define AT91C_PE21_LCDD20 (AT91C_PIO_PE21) //
+#define AT91C_PE22_LCDD15 (AT91C_PIO_PE22) //
+#define AT91C_PE22_LCDD21 (AT91C_PIO_PE22) //
+#define AT91C_PE23_LCDD16 (AT91C_PIO_PE23) //
+#define AT91C_PE23_LCDD22 (AT91C_PIO_PE23) //
+#define AT91C_PE24_LCDD17 (AT91C_PIO_PE24) //
+#define AT91C_PE24_LCDD23 (AT91C_PIO_PE24) //
+#define AT91C_PE25_LCDD18 (AT91C_PIO_PE25) //
+#define AT91C_PE26_LCDD19 (AT91C_PIO_PE26) //
+#define AT91C_PE27_LCDD20 (AT91C_PIO_PE27) //
+#define AT91C_PE28_LCDD21 (AT91C_PIO_PE28) //
+#define AT91C_PE29_LCDD22 (AT91C_PIO_PE29) //
+#define AT91C_PE3_LCDVSYNC (AT91C_PIO_PE3) //
+#define AT91C_PE30_LCDD23 (AT91C_PIO_PE30) //
+#define AT91C_PE31_PWM2 (AT91C_PIO_PE31) //
+#define AT91C_PE31_PCK1 (AT91C_PIO_PE31) //
+#define AT91C_PE4_LCDHSYNC (AT91C_PIO_PE4) //
+#define AT91C_PE5_LCDDOTCK (AT91C_PIO_PE5) //
+#define AT91C_PE6_LCDDEN (AT91C_PIO_PE6) //
+#define AT91C_PE7_LCDD0 (AT91C_PIO_PE7) //
+#define AT91C_PE7_LCDD2 (AT91C_PIO_PE7) //
+#define AT91C_PE8_LCDD1 (AT91C_PIO_PE8) //
+#define AT91C_PE8_LCDD3 (AT91C_PIO_PE8) //
+#define AT91C_PE9_LCDD2 (AT91C_PIO_PE9) //
+#define AT91C_PE9_LCDD4 (AT91C_PIO_PE9) //
+
+#endif /* ARM_AT91_AT91_PIO_SAM9G45_H */
Property changes on: trunk/sys/arm/at91/at91_pio_sam9g45.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pioreg.h
===================================================================
--- trunk/sys/arm/at91/at91_pioreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_pioreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,233 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_pioreg.h 259378 2013-12-14 01:14:38Z ian $ */
+
+#ifndef ARM_AT91_AT91_PIOREG_H
+#define ARM_AT91_AT91_PIOREG_H
+
+#ifndef ATMEL_ENV
+/* Registers */
+#define PIO_PER 0x00 /* PIO Enable Register */
+#define PIO_PDR 0x04 /* PIO Disable Register */
+#define PIO_PSR 0x08 /* PIO Status Register */
+ /* 0x0c reserved */
+#define PIO_OER 0x10 /* PIO Output Enable Register */
+#define PIO_ODR 0x14 /* PIO Output Disable Register */
+#define PIO_OSR 0x18 /* PIO Output Status Register */
+ /* 0x1c reserved */
+#define PIO_IFER 0x20 /* PIO Glitch Input Enable Register */
+#define PIO_IFDR 0x24 /* PIO Glitch Input Disable Register */
+#define PIO_IFSR 0x28 /* PIO Glitch Input Status Register */
+ /* 0x2c reserved */
+#define PIO_SODR 0x30 /* PIO Set Output Data Register */
+#define PIO_CODR 0x34 /* PIO Clear Output Data Register */
+#define PIO_ODSR 0x38 /* PIO Output Data Status Register */
+#define PIO_PDSR 0x3c /* PIO Pin Data Status Register */
+#define PIO_IER 0x40 /* PIO Interrupt Enable Register */
+#define PIO_IDR 0x44 /* PIO Interrupt Disable Register */
+#define PIO_IMR 0x48 /* PIO Interrupt Mask Register */
+#define PIO_ISR 0x4c /* PIO Interrupt Status Register */
+#define PIO_MDER 0x50 /* PIO Multi-Driver Enable Register */
+#define PIO_MDDR 0x54 /* PIO Multi-Driver Disable Register */
+#define PIO_MDSR 0x58 /* PIO Multi-Driver Status Register */
+ /* 0x5c reserved */
+#define PIO_PUDR 0x60 /* PIO Pull-up Disable Register */
+#define PIO_PUER 0x64 /* PIO Pull-up Enable Register */
+#define PIO_PUSR 0x68 /* PIO Pull-up Status Register */
+ /* 0x6c reserved */
+#define PIO_ASR 0x70 /* PIO Peripheral A Select Register */
+#define PIO_BSR 0x74 /* PIO Peripheral B Select Register */
+#define PIO_ABSR 0x78 /* PIO AB Status Register */
+ /* 0x7c-0x9c reserved */
+#define PIO_OWER 0xa0 /* PIO Output Write Enable Register */
+#define PIO_OWDR 0xa4 /* PIO Output Write Disable Register */
+#define PIO_OWSR 0xa8 /* PIO Output Write Status Register */
+ /* 0xac reserved */
+#endif
+
+#define AT91C_PIO_PA0 ((unsigned int) 1 << 0) // Pin Controlled by PA0
+#define AT91C_PIO_PA1 ((unsigned int) 1 << 1) // Pin Controlled by PA1
+#define AT91C_PIO_PA2 ((unsigned int) 1 << 2) // Pin Controlled by PA2
+#define AT91C_PIO_PA3 ((unsigned int) 1 << 3) // Pin Controlled by PA3
+#define AT91C_PIO_PA4 ((unsigned int) 1 << 4) // Pin Controlled by PA4
+#define AT91C_PIO_PA5 ((unsigned int) 1 << 5) // Pin Controlled by PA5
+#define AT91C_PIO_PA6 ((unsigned int) 1 << 6) // Pin Controlled by PA6
+#define AT91C_PIO_PA7 ((unsigned int) 1 << 7) // Pin Controlled by PA7
+#define AT91C_PIO_PA8 ((unsigned int) 1 << 8) // Pin Controlled by PA8
+#define AT91C_PIO_PA9 ((unsigned int) 1 << 9) // Pin Controlled by PA9
+#define AT91C_PIO_PA10 ((unsigned int) 1 << 10) // Pin Controlled by PA10
+#define AT91C_PIO_PA11 ((unsigned int) 1 << 11) // Pin Controlled by PA11
+#define AT91C_PIO_PA12 ((unsigned int) 1 << 12) // Pin Controlled by PA12
+#define AT91C_PIO_PA13 ((unsigned int) 1 << 13) // Pin Controlled by PA13
+#define AT91C_PIO_PA14 ((unsigned int) 1 << 14) // Pin Controlled by PA14
+#define AT91C_PIO_PA15 ((unsigned int) 1 << 15) // Pin Controlled by PA15
+#define AT91C_PIO_PA16 ((unsigned int) 1 << 16) // Pin Controlled by PA16
+#define AT91C_PIO_PA17 ((unsigned int) 1 << 17) // Pin Controlled by PA17
+#define AT91C_PIO_PA18 ((unsigned int) 1 << 18) // Pin Controlled by PA18
+#define AT91C_PIO_PA19 ((unsigned int) 1 << 19) // Pin Controlled by PA19
+#define AT91C_PIO_PA20 ((unsigned int) 1 << 20) // Pin Controlled by PA20
+#define AT91C_PIO_PA21 ((unsigned int) 1 << 21) // Pin Controlled by PA21
+#define AT91C_PIO_PA22 ((unsigned int) 1 << 22) // Pin Controlled by PA22
+#define AT91C_PIO_PA23 ((unsigned int) 1 << 23) // Pin Controlled by PA23
+#define AT91C_PIO_PA24 ((unsigned int) 1 << 24) // Pin Controlled by PA24
+#define AT91C_PIO_PA25 ((unsigned int) 1 << 25) // Pin Controlled by PA25
+#define AT91C_PIO_PA26 ((unsigned int) 1 << 26) // Pin Controlled by PA26
+#define AT91C_PIO_PA27 ((unsigned int) 1 << 27) // Pin Controlled by PA27
+#define AT91C_PIO_PA28 ((unsigned int) 1 << 28) // Pin Controlled by PA28
+#define AT91C_PIO_PA29 ((unsigned int) 1 << 29) // Pin Controlled by PA29
+#define AT91C_PIO_PA30 ((unsigned int) 1 << 30) // Pin Controlled by PA30
+#define AT91C_PIO_PA31 ((unsigned int) 1 << 31) // Pin Controlled by PA31
+#define AT91C_PIO_PB0 ((unsigned int) 1 << 0) // Pin Controlled by PB0
+#define AT91C_PIO_PB1 ((unsigned int) 1 << 1) // Pin Controlled by PB1
+#define AT91C_PIO_PB2 ((unsigned int) 1 << 2) // Pin Controlled by PB2
+#define AT91C_PIO_PB3 ((unsigned int) 1 << 3) // Pin Controlled by PB3
+#define AT91C_PIO_PB4 ((unsigned int) 1 << 4) // Pin Controlled by PB4
+#define AT91C_PIO_PB5 ((unsigned int) 1 << 5) // Pin Controlled by PB5
+#define AT91C_PIO_PB6 ((unsigned int) 1 << 6) // Pin Controlled by PB6
+#define AT91C_PIO_PB7 ((unsigned int) 1 << 7) // Pin Controlled by PB7
+#define AT91C_PIO_PB8 ((unsigned int) 1 << 8) // Pin Controlled by PB8
+#define AT91C_PIO_PB9 ((unsigned int) 1 << 9) // Pin Controlled by PB9
+#define AT91C_PIO_PB10 ((unsigned int) 1 << 10) // Pin Controlled by PB10
+#define AT91C_PIO_PB11 ((unsigned int) 1 << 11) // Pin Controlled by PB11
+#define AT91C_PIO_PB12 ((unsigned int) 1 << 12) // Pin Controlled by PB12
+#define AT91C_PIO_PB13 ((unsigned int) 1 << 13) // Pin Controlled by PB13
+#define AT91C_PIO_PB14 ((unsigned int) 1 << 14) // Pin Controlled by PB14
+#define AT91C_PIO_PB15 ((unsigned int) 1 << 15) // Pin Controlled by PB15
+#define AT91C_PIO_PB16 ((unsigned int) 1 << 16) // Pin Controlled by PB16
+#define AT91C_PIO_PB17 ((unsigned int) 1 << 17) // Pin Controlled by PB17
+#define AT91C_PIO_PB18 ((unsigned int) 1 << 18) // Pin Controlled by PB18
+#define AT91C_PIO_PB19 ((unsigned int) 1 << 19) // Pin Controlled by PB19
+#define AT91C_PIO_PB20 ((unsigned int) 1 << 20) // Pin Controlled by PB20
+#define AT91C_PIO_PB21 ((unsigned int) 1 << 21) // Pin Controlled by PB21
+#define AT91C_PIO_PB22 ((unsigned int) 1 << 22) // Pin Controlled by PB22
+#define AT91C_PIO_PB23 ((unsigned int) 1 << 23) // Pin Controlled by PB23
+#define AT91C_PIO_PB24 ((unsigned int) 1 << 24) // Pin Controlled by PB24
+#define AT91C_PIO_PB25 ((unsigned int) 1 << 25) // Pin Controlled by PB25
+#define AT91C_PIO_PB26 ((unsigned int) 1 << 26) // Pin Controlled by PB26
+#define AT91C_PIO_PB27 ((unsigned int) 1 << 27) // Pin Controlled by PB27
+#define AT91C_PIO_PB28 ((unsigned int) 1 << 28) // Pin Controlled by PB28
+#define AT91C_PIO_PB29 ((unsigned int) 1 << 29) // Pin Controlled by PB29
+#define AT91C_PIO_PB30 ((unsigned int) 1 << 30) // Pin Controlled by PB30
+#define AT91C_PIO_PB31 ((unsigned int) 1 << 31) // Pin Controlled by PB31
+#define AT91C_PIO_PC0 ((unsigned int) 1 << 0) // Pin Controlled by PC0
+#define AT91C_PIO_PC1 ((unsigned int) 1 << 1) // Pin Controlled by PC1
+#define AT91C_PIO_PC2 ((unsigned int) 1 << 2) // Pin Controlled by PC2
+#define AT91C_PIO_PC3 ((unsigned int) 1 << 3) // Pin Controlled by PC3
+#define AT91C_PIO_PC4 ((unsigned int) 1 << 4) // Pin Controlled by PC4
+#define AT91C_PIO_PC5 ((unsigned int) 1 << 5) // Pin Controlled by PC5
+#define AT91C_PIO_PC6 ((unsigned int) 1 << 6) // Pin Controlled by PC6
+#define AT91C_PIO_PC7 ((unsigned int) 1 << 7) // Pin Controlled by PC7
+#define AT91C_PIO_PC8 ((unsigned int) 1 << 8) // Pin Controlled by PC8
+#define AT91C_PIO_PC9 ((unsigned int) 1 << 9) // Pin Controlled by PC9
+#define AT91C_PIO_PC10 ((unsigned int) 1 << 10) // Pin Controlled by PC10
+#define AT91C_PIO_PC11 ((unsigned int) 1 << 11) // Pin Controlled by PC11
+#define AT91C_PIO_PC12 ((unsigned int) 1 << 12) // Pin Controlled by PC12
+#define AT91C_PIO_PC13 ((unsigned int) 1 << 13) // Pin Controlled by PC13
+#define AT91C_PIO_PC14 ((unsigned int) 1 << 14) // Pin Controlled by PC14
+#define AT91C_PIO_PC15 ((unsigned int) 1 << 15) // Pin Controlled by PC15
+#define AT91C_PIO_PC16 ((unsigned int) 1 << 16) // Pin Controlled by PC16
+#define AT91C_PIO_PC17 ((unsigned int) 1 << 17) // Pin Controlled by PC17
+#define AT91C_PIO_PC18 ((unsigned int) 1 << 18) // Pin Controlled by PC18
+#define AT91C_PIO_PC19 ((unsigned int) 1 << 19) // Pin Controlled by PC19
+#define AT91C_PIO_PC20 ((unsigned int) 1 << 20) // Pin Controlled by PC20
+#define AT91C_PIO_PC21 ((unsigned int) 1 << 21) // Pin Controlled by PC21
+#define AT91C_PIO_PC22 ((unsigned int) 1 << 22) // Pin Controlled by PC22
+#define AT91C_PIO_PC23 ((unsigned int) 1 << 23) // Pin Controlled by PC23
+#define AT91C_PIO_PC24 ((unsigned int) 1 << 24) // Pin Controlled by PC24
+#define AT91C_PIO_PC25 ((unsigned int) 1 << 25) // Pin Controlled by PC25
+#define AT91C_PIO_PC26 ((unsigned int) 1 << 26) // Pin Controlled by PC26
+#define AT91C_PIO_PC27 ((unsigned int) 1 << 27) // Pin Controlled by PC27
+#define AT91C_PIO_PC28 ((unsigned int) 1 << 28) // Pin Controlled by PC28
+#define AT91C_PIO_PC29 ((unsigned int) 1 << 29) // Pin Controlled by PC29
+#define AT91C_PIO_PC30 ((unsigned int) 1 << 30) // Pin Controlled by PC30
+#define AT91C_PIO_PC31 ((unsigned int) 1 << 31) // Pin Controlled by PC31
+#define AT91C_PIO_PD0 ((unsigned int) 1 << 0) // Pin Controlled by PD0
+#define AT91C_PIO_PD1 ((unsigned int) 1 << 1) // Pin Controlled by PD1
+#define AT91C_PIO_PD2 ((unsigned int) 1 << 2) // Pin Controlled by PD2
+#define AT91C_PIO_PD3 ((unsigned int) 1 << 3) // Pin Controlled by PD3
+#define AT91C_PIO_PD4 ((unsigned int) 1 << 4) // Pin Controlled by PD4
+#define AT91C_PIO_PD5 ((unsigned int) 1 << 5) // Pin Controlled by PD5
+#define AT91C_PIO_PD6 ((unsigned int) 1 << 6) // Pin Controlled by PD6
+#define AT91C_PIO_PD7 ((unsigned int) 1 << 7) // Pin Controlled by PD7
+#define AT91C_PIO_PD8 ((unsigned int) 1 << 8) // Pin Controlled by PD8
+#define AT91C_PIO_PD9 ((unsigned int) 1 << 9) // Pin Controlled by PD9
+#define AT91C_PIO_PD10 ((unsigned int) 1 << 10) // Pin Controlled by PD10
+#define AT91C_PIO_PD11 ((unsigned int) 1 << 11) // Pin Controlled by PD11
+#define AT91C_PIO_PD12 ((unsigned int) 1 << 12) // Pin Controlled by PD12
+#define AT91C_PIO_PD13 ((unsigned int) 1 << 13) // Pin Controlled by PD13
+#define AT91C_PIO_PD14 ((unsigned int) 1 << 14) // Pin Controlled by PD14
+#define AT91C_PIO_PD15 ((unsigned int) 1 << 15) // Pin Controlled by PD15
+#define AT91C_PIO_PD16 ((unsigned int) 1 << 16) // Pin Controlled by PD16
+#define AT91C_PIO_PD17 ((unsigned int) 1 << 17) // Pin Controlled by PD17
+#define AT91C_PIO_PD18 ((unsigned int) 1 << 18) // Pin Controlled by PD18
+#define AT91C_PIO_PD19 ((unsigned int) 1 << 19) // Pin Controlled by PD19
+#define AT91C_PIO_PD20 ((unsigned int) 1 << 20) // Pin Controlled by PD20
+#define AT91C_PIO_PD21 ((unsigned int) 1 << 21) // Pin Controlled by PD21
+#define AT91C_PIO_PD22 ((unsigned int) 1 << 22) // Pin Controlled by PD22
+#define AT91C_PIO_PD23 ((unsigned int) 1 << 23) // Pin Controlled by PD23
+#define AT91C_PIO_PD24 ((unsigned int) 1 << 24) // Pin Controlled by PD24
+#define AT91C_PIO_PD25 ((unsigned int) 1 << 25) // Pin Controlled by PD25
+#define AT91C_PIO_PD26 ((unsigned int) 1 << 26) // Pin Controlled by PD26
+#define AT91C_PIO_PD27 ((unsigned int) 1 << 27) // Pin Controlled by PD27
+#define AT91C_PIO_PD28 ((unsigned int) 1 << 28) // Pin Controlled by PD28
+#define AT91C_PIO_PD29 ((unsigned int) 1 << 29) // Pin Controlled by PD29
+#define AT91C_PIO_PD30 ((unsigned int) 1 << 30) // Pin Controlled by PD30
+#define AT91C_PIO_PD31 ((unsigned int) 1 << 31) // Pin Controlled by PD31
+#define AT91C_PIO_PE0 ((unsigned int) 1 << 0) // Pin Controlled by PE0
+#define AT91C_PIO_PE1 ((unsigned int) 1 << 1) // Pin Controlled by PE1
+#define AT91C_PIO_PE2 ((unsigned int) 1 << 2) // Pin Controlled by PE2
+#define AT91C_PIO_PE3 ((unsigned int) 1 << 3) // Pin Controlled by PE3
+#define AT91C_PIO_PE4 ((unsigned int) 1 << 4) // Pin Controlled by PE4
+#define AT91C_PIO_PE5 ((unsigned int) 1 << 5) // Pin Controlled by PE5
+#define AT91C_PIO_PE6 ((unsigned int) 1 << 6) // Pin Controlled by PE6
+#define AT91C_PIO_PE7 ((unsigned int) 1 << 7) // Pin Controlled by PE7
+#define AT91C_PIO_PE8 ((unsigned int) 1 << 8) // Pin Controlled by PE8
+#define AT91C_PIO_PE9 ((unsigned int) 1 << 9) // Pin Controlled by PE9
+#define AT91C_PIO_PE10 ((unsigned int) 1 << 10) // Pin Controlled by PE10
+#define AT91C_PIO_PE11 ((unsigned int) 1 << 11) // Pin Controlled by PE11
+#define AT91C_PIO_PE12 ((unsigned int) 1 << 12) // Pin Controlled by PE12
+#define AT91C_PIO_PE13 ((unsigned int) 1 << 13) // Pin Controlled by PE13
+#define AT91C_PIO_PE14 ((unsigned int) 1 << 14) // Pin Controlled by PE14
+#define AT91C_PIO_PE15 ((unsigned int) 1 << 15) // Pin Controlled by PE15
+#define AT91C_PIO_PE16 ((unsigned int) 1 << 16) // Pin Controlled by PE16
+#define AT91C_PIO_PE17 ((unsigned int) 1 << 17) // Pin Controlled by PE17
+#define AT91C_PIO_PE18 ((unsigned int) 1 << 18) // Pin Controlled by PE18
+#define AT91C_PIO_PE19 ((unsigned int) 1 << 19) // Pin Controlled by PE19
+#define AT91C_PIO_PE20 ((unsigned int) 1 << 20) // Pin Controlled by PE20
+#define AT91C_PIO_PE21 ((unsigned int) 1 << 21) // Pin Controlled by PE21
+#define AT91C_PIO_PE22 ((unsigned int) 1 << 22) // Pin Controlled by PE22
+#define AT91C_PIO_PE23 ((unsigned int) 1 << 23) // Pin Controlled by PE23
+#define AT91C_PIO_PE24 ((unsigned int) 1 << 24) // Pin Controlled by PE24
+#define AT91C_PIO_PE25 ((unsigned int) 1 << 25) // Pin Controlled by PE25
+#define AT91C_PIO_PE26 ((unsigned int) 1 << 26) // Pin Controlled by PE26
+#define AT91C_PIO_PE27 ((unsigned int) 1 << 27) // Pin Controlled by PE27
+#define AT91C_PIO_PE28 ((unsigned int) 1 << 28) // Pin Controlled by PE28
+#define AT91C_PIO_PE29 ((unsigned int) 1 << 29) // Pin Controlled by PE29
+#define AT91C_PIO_PE30 ((unsigned int) 1 << 30) // Pin Controlled by PE30
+#define AT91C_PIO_PE31 ((unsigned int) 1 << 31) // Pin Controlled by PE31
+
+#endif /* ARM_AT91_AT91_PIOREG_H */
Property changes on: trunk/sys/arm/at91/at91_pioreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_piovar.h
===================================================================
--- trunk/sys/arm/at91/at91_piovar.h (rev 0)
+++ trunk/sys/arm/at91/at91_piovar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,51 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_piovar.h 273651 2014-10-26 01:26:53Z ian $ */
+
+#ifndef ARM_AT91_AT91_PIOVAR_H
+#define ARM_AT91_AT91_PIOVAR_H
+
+void at91_pio_use_periph_a(uint32_t pio, uint32_t periph_a_mask,
+ int use_pullup);
+void at91_pio_use_periph_b(uint32_t pio, uint32_t periph_b_mask,
+ int use_pullup);
+void at91_pio_use_gpio(uint32_t pio, uint32_t gpio_mask);
+void at91_pio_gpio_input(uint32_t pio, uint32_t input_enable_mask);
+void at91_pio_gpio_output(uint32_t pio, uint32_t output_enable_mask,
+ int use_pullup);
+void at91_pio_gpio_high_z(uint32_t pio, uint32_t high_z_mask, int enable);
+void at91_pio_gpio_set(uint32_t pio, uint32_t data_mask);
+void at91_pio_gpio_clear(uint32_t pio, uint32_t data_mask);
+uint32_t at91_pio_gpio_get(uint32_t pio, uint32_t data_mask);
+void at91_pio_gpio_set_deglitch(uint32_t pio, uint32_t data_mask,
+ int use_deglitch);
+void at91_pio_gpio_set_interrupt(uint32_t pio, uint32_t data_mask,
+ int enable_interrupt);
+uint32_t at91_pio_gpio_clear_interrupt(uint32_t pio);
+void at91_pio_gpio_pullup(uint32_t pio, uint32_t data_mask, int do_pullup);
+
+#endif /* ARM_AT91_AT91_PIOVAR_H */
Property changes on: trunk/sys/arm/at91/at91_piovar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pit.c
===================================================================
--- trunk/sys/arm/at91/at91_pit.c (rev 0)
+++ trunk/sys/arm/at91/at91_pit.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,223 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Gallon Sylvestre. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_pit.c 266196 2014-05-15 21:21:47Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+#include <machine/resource.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_pitreg.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#ifndef PIT_PRESCALE
+#define PIT_PRESCALE (16)
+#endif
+
+static struct pit_softc {
+ struct resource *mem_res; /* Memory resource */
+ void *intrhand; /* Interrupt handle */
+ device_t sc_dev;
+} *sc;
+
+static uint32_t timecount = 0;
+static unsigned at91_pit_get_timecount(struct timecounter *tc);
+static int pit_intr(void *arg);
+
+static inline uint32_t
+RD4(struct pit_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct pit_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+void
+at91_pit_delay(int us)
+{
+ int32_t cnt, last, piv;
+ uint64_t pit_freq;
+ const uint64_t mhz = 1E6;
+
+ if (sc == NULL)
+ return;
+
+ last = PIT_PIV(RD4(sc, PIT_PIIR));
+
+ /* Max delay ~= 260s. @ 133Mhz */
+ pit_freq = at91_master_clock / PIT_PRESCALE;
+ cnt = ((pit_freq * us) + (mhz -1)) / mhz;
+ cnt = (cnt <= 0) ? 1 : cnt;
+
+ while (cnt > 0) {
+ piv = PIT_PIV(RD4(sc, PIT_PIIR));
+ cnt -= piv - last ;
+ if (piv < last)
+ cnt -= PIT_PIV(~0u) - last;
+ last = piv;
+ }
+}
+
+static struct timecounter at91_pit_timecounter = {
+ at91_pit_get_timecount, /* get_timecount */
+ NULL, /* no poll_pps */
+ 0xffffffff, /* counter mask */
+ 0 / PIT_PRESCALE, /* frequency */
+ "AT91SAM9 timer", /* name */
+ 1000 /* quality */
+};
+
+static int
+at91_pit_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91sam9260-pit"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "AT91SAM9 PIT");
+ return (0);
+}
+
+static int
+at91_pit_attach(device_t dev)
+{
+ void *ih;
+ int rid, err = 0;
+ struct resource *irq;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+
+ if (sc->mem_res == NULL)
+ panic("couldn't allocate register resources");
+
+ rid = 0;
+ irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 1, 1, 1,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!irq) {
+ device_printf(dev, "could not allocate interrupt resources.\n");
+ err = ENOMEM;
+ goto out;
+ }
+
+ /* Activate the interrupt. */
+ err = bus_setup_intr(dev, irq, INTR_TYPE_CLK, pit_intr, NULL, NULL,
+ &ih);
+
+ at91_pit_timecounter.tc_frequency = at91_master_clock / PIT_PRESCALE;
+ tc_init(&at91_pit_timecounter);
+
+ /* Enable the PIT here. */
+ WR4(sc, PIT_MR, PIT_PIV(at91_master_clock / PIT_PRESCALE / hz) |
+ PIT_EN | PIT_IEN);
+out:
+ return (err);
+}
+
+
+static int
+pit_intr(void *arg)
+{
+ struct trapframe *fp = arg;
+ uint32_t icnt;
+
+ if (RD4(sc, PIT_SR) & PIT_PITS_DONE) {
+ icnt = RD4(sc, PIT_PIVR) >> 20;
+
+ /* Just add in the overflows we just read */
+ timecount += PIT_PIV(RD4(sc, PIT_MR)) * icnt;
+
+ hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp));
+ return (FILTER_HANDLED);
+ }
+ return (FILTER_STRAY);
+}
+
+static unsigned
+at91_pit_get_timecount(struct timecounter *tc)
+{
+ uint32_t piir, icnt;
+
+ piir = RD4(sc, PIT_PIIR); /* Current count | over flows */
+ icnt = piir >> 20; /* Overflows */
+ return (timecount + PIT_PIV(piir) + PIT_PIV(RD4(sc, PIT_MR)) * icnt);
+}
+
+static device_method_t at91_pit_methods[] = {
+ DEVMETHOD(device_probe, at91_pit_probe),
+ DEVMETHOD(device_attach, at91_pit_attach),
+ DEVMETHOD_END
+};
+
+static driver_t at91_pit_driver = {
+ "at91_pit",
+ at91_pit_methods,
+ sizeof(struct pit_softc),
+};
+
+static devclass_t at91_pit_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_pit, simplebus, at91_pit_driver, at91_pit_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_pit, atmelarm, at91_pit_driver, at91_pit_devclass, NULL,
+ NULL);
+#endif
Property changes on: trunk/sys/arm/at91/at91_pit.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pitreg.h
===================================================================
--- trunk/sys/arm/at91/at91_pitreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_pitreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,48 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_pitreg.h 238370 2012-07-11 17:11:54Z imp $ */
+
+#ifndef ARM_AT91_AT91_PITREG_H
+#define ARM_AT91_AT91_PITREG_H
+
+#define PIT_MR 0x0
+#define PIT_SR 0x4
+#define PIT_PIVR 0x8
+#define PIT_PIIR 0xc
+
+/* PIT_MR */
+#define PIT_PIV(x) (x & 0xfffff) /* periodic interval value */
+#define PIT_CNT(x) ((x >>20) & 0xfff) /* periodic interval counter */
+#define PIT_EN (1 << 24) /* pit enable */
+#define PIT_IEN (1 << 25) /* pit interrupt enable */
+
+/* PIT_SR */
+#define PIT_PITS_DONE 1 /* interrupt done */
+
+void at91_pit_delay(int us);
+
+#endif /* ARM_AT91_AT91_PITREG_H */
Property changes on: trunk/sys/arm/at91/at91_pitreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pmc.c
===================================================================
--- trunk/sys/arm/at91/at91_pmc.c (rev 0)
+++ trunk/sys/arm/at91/at91_pmc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,718 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_pmc.c 266196 2014-05-15 21:21:47Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91var.h>
+
+#include <arm/at91/at91_pmcreg.h>
+#include <arm/at91/at91_pmcvar.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+static struct at91_pmc_softc {
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_sh;
+ struct resource *mem_res; /* Memory resource */
+ device_t dev;
+} *pmc_softc;
+
+static uint32_t pllb_init;
+
+MALLOC_DECLARE(M_PMC);
+MALLOC_DEFINE(M_PMC, "at91_pmc_clocks", "AT91 PMC Clock descriptors");
+
+#define AT91_PMC_BASE 0xffffc00
+
+static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int);
+static void at91_pmc_set_upll_mode(struct at91_pmc_clock *, int);
+static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int);
+static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int);
+static void at91_pmc_clock_alias(const char *name, const char *alias);
+
+static struct at91_pmc_clock slck = {
+ .name = "slck", /* 32,768 Hz slow clock */
+ .hz = 32768,
+ .refcnt = 1,
+ .id = 0,
+ .primary = 1,
+};
+
+/*
+ * NOTE: Clocks for "ordinary peripheral" devices e.g. spi0, udp0, uhp0 etc.
+ * are now created automatically. Only "system" clocks need be defined here.
+ */
+static struct at91_pmc_clock main_ck = {
+ .name = "main", /* Main clock */
+ .refcnt = 0,
+ .id = 1,
+ .primary = 1,
+ .pmc_mask = PMC_IER_MOSCS,
+};
+
+static struct at91_pmc_clock plla = {
+ .name = "plla", /* PLLA Clock, used for CPU clocking */
+ .parent = &main_ck,
+ .refcnt = 1,
+ .id = 0,
+ .primary = 1,
+ .pll = 1,
+ .pmc_mask = PMC_IER_LOCKA,
+};
+
+static struct at91_pmc_clock pllb = {
+ .name = "pllb", /* PLLB Clock, used for USB functions */
+ .parent = &main_ck,
+ .refcnt = 0,
+ .id = 0,
+ .primary = 1,
+ .pll = 1,
+ .pmc_mask = PMC_IER_LOCKB,
+ .set_mode = &at91_pmc_set_pllb_mode,
+};
+
+/* Used by USB on at91sam9g45 */
+static struct at91_pmc_clock upll = {
+ .name = "upll", /* UTMI PLL, used for USB functions on 9G45 family */
+ .parent = &main_ck,
+ .refcnt = 0,
+ .id = 0,
+ .primary = 1,
+ .pll = 1,
+ .pmc_mask = (1 << 6),
+ .set_mode = &at91_pmc_set_upll_mode,
+};
+
+static struct at91_pmc_clock udpck = {
+ .name = "udpck",
+ .parent = &pllb,
+ .pmc_mask = PMC_SCER_UDP,
+ .set_mode = at91_pmc_set_sys_mode
+};
+
+static struct at91_pmc_clock uhpck = {
+ .name = "uhpck",
+ .parent = &pllb,
+ .pmc_mask = PMC_SCER_UHP,
+ .set_mode = at91_pmc_set_sys_mode
+};
+
+static struct at91_pmc_clock mck = {
+ .name = "mck", /* Master (Peripheral) Clock */
+ .pmc_mask = PMC_IER_MCKRDY,
+ .refcnt = 0,
+};
+
+static struct at91_pmc_clock cpu = {
+ .name = "cpu", /* CPU Clock */
+ .parent = &plla,
+ .pmc_mask = PMC_SCER_PCK,
+ .refcnt = 0,
+};
+
+/* "+32" or the automatic peripheral clocks */
+static struct at91_pmc_clock *clock_list[16+32] = {
+ &slck,
+ &main_ck,
+ &plla,
+ &pllb,
+ &upll,
+ &udpck,
+ &uhpck,
+ &mck,
+ &cpu
+};
+
+static inline uint32_t
+RD4(struct at91_pmc_softc *sc, bus_size_t off)
+{
+
+ if (sc == NULL) {
+ uint32_t *p = (uint32_t *)(AT91_BASE + AT91_PMC_BASE + off);
+
+ return *p;
+ }
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ if (sc == NULL) {
+ uint32_t *p = (uint32_t *)(AT91_BASE + AT91_PMC_BASE + off);
+
+ *p = val;
+ } else
+ bus_write_4(sc->mem_res, off, val);
+}
+
+/*
+ * The following is unused currently since we don't ever set the PLLA
+ * frequency of the device. If we did, we'd have to also pay attention
+ * to the ICPLLA bit in the PMC_PLLICPR register for frequencies lower
+ * than ~600MHz, which the PMC code doesn't do right now.
+ */
+uint32_t
+at91_pmc_800mhz_plla_outb(int freq)
+{
+ uint32_t outa;
+
+ /*
+ * Set OUTA, per the data sheet. See Table 46-16 titled
+ * PLLA Frequency Regarding ICPLLA and OUTA in the SAM9X25 doc,
+ * Table 46-17 in the SAM9G20 doc, or Table 46-16 in the SAM9G45 doc.
+ * Note: the frequencies overlap by 5MHz, so we add 3 here to
+ * center shoot the transition.
+ */
+
+ freq /= 1000000; /* MHz */
+ if (freq >= 800)
+ freq = 800;
+ freq += 3; /* Allow for overlap. */
+ outa = 3 - ((freq / 50) & 3); /* 750 / 50 = 7, see table */
+ return (1 << 29)| (outa << 14);
+}
+
+uint32_t
+at91_pmc_800mhz_pllb_outb(int freq)
+{
+
+ return (0);
+}
+
+void
+at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
+{
+ struct at91_pmc_softc *sc = pmc_softc;
+ uint32_t value;
+
+ value = on ? pllb_init : 0;
+
+ /*
+ * Only write to the register if the value is changing. Besides being
+ * good common sense, this works around RM9200 Errata #26 (CKGR_PLL[AB]R
+ * must not be written with the same value currently in the register).
+ */
+ if (RD4(sc, CKGR_PLLBR) != value) {
+ WR4(sc, CKGR_PLLBR, value);
+ while (on && (RD4(sc, PMC_SR) & PMC_IER_LOCKB) != PMC_IER_LOCKB)
+ continue;
+ }
+}
+
+static void
+at91_pmc_set_upll_mode(struct at91_pmc_clock *clk, int on)
+{
+ struct at91_pmc_softc *sc = pmc_softc;
+ uint32_t value;
+
+ if (on) {
+ on = PMC_IER_LOCKU;
+ value = CKGR_UCKR_UPLLEN | CKGR_UCKR_BIASEN;
+ } else
+ value = 0;
+
+ WR4(sc, CKGR_UCKR, RD4(sc, CKGR_UCKR) | value);
+ while ((RD4(sc, PMC_SR) & PMC_IER_LOCKU) != on)
+ continue;
+
+ WR4(sc, PMC_USB, PMC_USB_USBDIV(9) | PMC_USB_USBS);
+ WR4(sc, PMC_SCER, PMC_SCER_UHP_SAM9);
+}
+
+static void
+at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
+{
+ struct at91_pmc_softc *sc = pmc_softc;
+
+ WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask);
+ if (on)
+ while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask)
+ continue;
+ else
+ while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) == clk->pmc_mask)
+ continue;
+}
+
+static void
+at91_pmc_set_periph_mode(struct at91_pmc_clock *clk, int on)
+{
+ struct at91_pmc_softc *sc = pmc_softc;
+
+ WR4(sc, on ? PMC_PCER : PMC_PCDR, clk->pmc_mask);
+ if (on)
+ while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask)
+ continue;
+ else
+ while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask)
+ continue;
+}
+
+struct at91_pmc_clock *
+at91_pmc_clock_add(const char *name, uint32_t irq,
+ struct at91_pmc_clock *parent)
+{
+ struct at91_pmc_clock *clk;
+ int i, buflen;
+
+ clk = malloc(sizeof(*clk), M_PMC, M_NOWAIT | M_ZERO);
+ if (clk == NULL)
+ goto err;
+
+ buflen = strlen(name) + 1;
+ clk->name = malloc(buflen, M_PMC, M_NOWAIT);
+ if (clk->name == NULL)
+ goto err;
+
+ strlcpy(clk->name, name, buflen);
+ clk->pmc_mask = 1 << irq;
+ clk->set_mode = &at91_pmc_set_periph_mode;
+ if (parent == NULL)
+ clk->parent = &mck;
+ else
+ clk->parent = parent;
+
+ for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
+ if (clock_list[i] == NULL) {
+ clock_list[i] = clk;
+ return (clk);
+ }
+ }
+err:
+ if (clk != NULL) {
+ if (clk->name != NULL)
+ free(clk->name, M_PMC);
+ free(clk, M_PMC);
+ }
+
+ panic("could not allocate pmc clock '%s'", name);
+ return (NULL);
+}
+
+static void
+at91_pmc_clock_alias(const char *name, const char *alias)
+{
+ struct at91_pmc_clock *clk, *alias_clk;
+
+ clk = at91_pmc_clock_ref(name);
+ if (clk)
+ alias_clk = at91_pmc_clock_add(alias, 0, clk->parent);
+
+ if (clk && alias_clk) {
+ alias_clk->hz = clk->hz;
+ alias_clk->pmc_mask = clk->pmc_mask;
+ alias_clk->set_mode = clk->set_mode;
+ }
+}
+
+struct at91_pmc_clock *
+at91_pmc_clock_ref(const char *name)
+{
+ int i;
+
+ for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
+ if (clock_list[i] == NULL)
+ break;
+ if (strcmp(name, clock_list[i]->name) == 0)
+ return (clock_list[i]);
+ }
+
+ return (NULL);
+}
+
+void
+at91_pmc_clock_deref(struct at91_pmc_clock *clk)
+{
+ if (clk == NULL)
+ return;
+}
+
+void
+at91_pmc_clock_enable(struct at91_pmc_clock *clk)
+{
+ if (clk == NULL)
+ return;
+
+ /* XXX LOCKING? XXX */
+ if (clk->parent)
+ at91_pmc_clock_enable(clk->parent);
+ if (clk->refcnt++ == 0 && clk->set_mode)
+ clk->set_mode(clk, 1);
+}
+
+void
+at91_pmc_clock_disable(struct at91_pmc_clock *clk)
+{
+ if (clk == NULL)
+ return;
+
+ /* XXX LOCKING? XXX */
+ if (--clk->refcnt == 0 && clk->set_mode)
+ clk->set_mode(clk, 0);
+ if (clk->parent)
+ at91_pmc_clock_disable(clk->parent);
+}
+
+static int
+at91_pmc_pll_rate(struct at91_pmc_clock *clk, uint32_t reg)
+{
+ uint32_t mul, div, freq;
+
+ freq = clk->parent->hz;
+ div = (reg >> clk->pll_div_shift) & clk->pll_div_mask;
+ mul = (reg >> clk->pll_mul_shift) & clk->pll_mul_mask;
+
+#if 0
+ printf("pll = (%d / %d) * %d = %d\n",
+ freq, div, mul + 1, (freq/div) * (mul+1));
+#endif
+
+ if (div != 0 && mul != 0) {
+ freq /= div;
+ freq *= mul + 1;
+ } else
+ freq = 0;
+ clk->hz = freq;
+
+ return (freq);
+}
+
+static uint32_t
+at91_pmc_pll_calc(struct at91_pmc_clock *clk, uint32_t out_freq)
+{
+ uint32_t i, div = 0, mul = 0, diff = 1 << 30;
+
+ unsigned ret = 0x3e00;
+
+ if (out_freq > clk->pll_max_out)
+ goto fail;
+
+ for (i = 1; i < 256; i++) {
+ int32_t diff1;
+ uint32_t input, mul1;
+
+ input = clk->parent->hz / i;
+ if (input < clk->pll_min_in)
+ break;
+ if (input > clk->pll_max_in)
+ continue;
+
+ mul1 = out_freq / input;
+ if (mul1 > (clk->pll_mul_mask + 1))
+ continue;
+ if (mul1 == 0)
+ break;
+
+ diff1 = out_freq - input * mul1;
+ if (diff1 < 0)
+ diff1 = -diff1;
+ if (diff > diff1) {
+ diff = diff1;
+ div = i;
+ mul = mul1;
+ if (diff == 0)
+ break;
+ }
+ }
+ if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
+ goto fail;
+
+ if (clk->set_outb != NULL)
+ ret |= clk->set_outb(out_freq);
+
+ return (ret |
+ ((mul - 1) << clk->pll_mul_shift) |
+ (div << clk->pll_div_shift));
+fail:
+ return (0);
+}
+
+#if !defined(AT91C_MAIN_CLOCK)
+static const unsigned int at91_main_clock_tbl[] = {
+ 3000000, 3276800, 3686400, 3840000, 4000000,
+ 4433619, 4915200, 5000000, 5242880, 6000000,
+ 6144000, 6400000, 6553600, 7159090, 7372800,
+ 7864320, 8000000, 9830400, 10000000, 11059200,
+ 12000000, 12288000, 13560000, 14318180, 14745600,
+ 16000000, 17344700, 18432000, 20000000
+};
+#define MAIN_CLOCK_TBL_LEN (sizeof(at91_main_clock_tbl) / sizeof(*at91_main_clock_tbl))
+#endif
+
+static unsigned int
+at91_pmc_sense_main_clock(void)
+{
+#if !defined(AT91C_MAIN_CLOCK)
+ unsigned int ckgr_val;
+ unsigned int diff, matchdiff, freq;
+ int i;
+
+ ckgr_val = (RD4(NULL, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11;
+
+ /*
+ * Clocks up to 50MHz can be connected to some models. If
+ * the frequency is >= 21MHz, assume that the slow clock can
+ * measure it correctly, and that any error can be adequately
+ * compensated for by roudning to the nearest 500Hz. Users
+ * with fast, or odd-ball clocks will need to set
+ * AT91C_MAIN_CLOCK in the kernel config file.
+ */
+ if (ckgr_val >= 21000000)
+ return ((ckgr_val + 250) / 500 * 500);
+
+ /*
+ * Try to find the standard frequency that match best.
+ */
+ freq = at91_main_clock_tbl[0];
+ matchdiff = abs(ckgr_val - at91_main_clock_tbl[0]);
+ for (i = 1; i < MAIN_CLOCK_TBL_LEN; i++) {
+ diff = abs(ckgr_val - at91_main_clock_tbl[i]);
+ if (diff < matchdiff) {
+ freq = at91_main_clock_tbl[i];
+ matchdiff = diff;
+ }
+ }
+ return (freq);
+#else
+ return (AT91C_MAIN_CLOCK);
+#endif
+}
+
+void
+at91_pmc_init_clock(void)
+{
+ struct at91_pmc_softc *sc = NULL;
+ unsigned int main_clock;
+ uint32_t mckr;
+ uint32_t mdiv;
+
+ soc_info.soc_data->soc_clock_init();
+
+ main_clock = at91_pmc_sense_main_clock();
+
+ if (at91_is_sam9() || at91_is_sam9xe()) {
+ uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
+ udpck.pmc_mask = PMC_SCER_UDP_SAM9;
+ }
+
+ /* There is no pllb on AT91SAM9G45 */
+ if (at91_cpu_is(AT91_T_SAM9G45)) {
+ uhpck.parent = &upll;
+ uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
+ }
+
+ mckr = RD4(sc, PMC_MCKR);
+ main_ck.hz = main_clock;
+
+ /*
+ * Note: this means outa calc code for plla never used since
+ * we never change it. If we did, we'd also have to mind
+ * ICPLLA to get the charge pump current right.
+ */
+ at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR));
+
+ if (at91_cpu_is(AT91_T_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
+ plla.hz /= 2;
+
+ /*
+ * Initialize the usb clock. This sets up pllb, but disables the
+ * actual clock. XXX except for the if 0 :(
+ */
+ if (!at91_cpu_is(AT91_T_SAM9G45)) {
+ pllb_init = at91_pmc_pll_calc(&pllb, 48000000 * 2) | 0x10000000;
+ at91_pmc_pll_rate(&pllb, pllb_init);
+#if 0
+ /* Turn off USB clocks */
+ at91_pmc_set_periph_mode(&ohci_clk, 0);
+ at91_pmc_set_periph_mode(&udc_clk, 0);
+#endif
+ }
+
+ if (at91_is_rm92()) {
+ WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
+ WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
+ } else
+ WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9);
+
+ /*
+ * MCK and PCU derive from one of the primary clocks. Initialize
+ * this relationship.
+ */
+ mck.parent = clock_list[mckr & 0x3];
+ mck.parent->refcnt++;
+
+ cpu.hz = mck.hz = mck.parent->hz /
+ (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2));
+
+ mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8;
+ if (at91_is_sam9() || at91_is_sam9xe()) {
+ /*
+ * On AT91SAM9G45 when mdiv == 3 we need to divide
+ * MCK by 3 but not, for example, on 9g20.
+ */
+ if (!at91_cpu_is(AT91_T_SAM9G45) || mdiv <= 2)
+ mdiv *= 2;
+ if (mdiv > 0)
+ mck.hz /= mdiv;
+ } else
+ mck.hz /= (1 + mdiv);
+
+ /* Only found on SAM9G20 */
+ if (at91_cpu_is(AT91_T_SAM9G20))
+ cpu.hz /= (mckr & PMC_MCKR_PDIV) ? 2 : 1;
+
+ at91_master_clock = mck.hz;
+
+ /* These clocks refrenced by "special" names */
+ at91_pmc_clock_alias("ohci0", "ohci_clk");
+ at91_pmc_clock_alias("udp0", "udp_clk");
+
+ /* Turn off "Progamable" clocks */
+ WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
+ PMC_SCER_PCK3);
+
+ /* XXX kludge, turn on all peripherals */
+ WR4(sc, PMC_PCER, 0xffffffff);
+
+ /* Disable all interrupts for PMC */
+ WR4(sc, PMC_IDR, 0xffffffff);
+}
+
+static void
+at91_pmc_deactivate(device_t dev)
+{
+ struct at91_pmc_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_generic_detach(sc->dev);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = 0;
+}
+
+static int
+at91_pmc_activate(device_t dev)
+{
+ struct at91_pmc_softc *sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ goto errout;
+ return (0);
+errout:
+ at91_pmc_deactivate(dev);
+ return (ENOMEM);
+}
+
+static int
+at91_pmc_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-pmc"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "PMC");
+ return (0);
+}
+
+static int
+at91_pmc_attach(device_t dev)
+{
+ int err;
+
+ pmc_softc = device_get_softc(dev);
+ pmc_softc->dev = dev;
+ if ((err = at91_pmc_activate(dev)) != 0)
+ return (err);
+
+ /*
+ * Configure main clock frequency.
+ */
+ at91_pmc_init_clock();
+
+ /*
+ * Display info about clocks previously computed
+ */
+ device_printf(dev,
+ "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
+ main_ck.hz,
+ plla.hz / 1000000,
+ cpu.hz / 1000000, mck.hz / 1000000);
+
+ return (0);
+}
+
+static device_method_t at91_pmc_methods[] = {
+ DEVMETHOD(device_probe, at91_pmc_probe),
+ DEVMETHOD(device_attach, at91_pmc_attach),
+ DEVMETHOD_END
+};
+
+static driver_t at91_pmc_driver = {
+ "at91_pmc",
+ at91_pmc_methods,
+ sizeof(struct at91_pmc_softc),
+};
+static devclass_t at91_pmc_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_pmc, simplebus, at91_pmc_driver, at91_pmc_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass, NULL,
+ NULL);
+#endif
Property changes on: trunk/sys/arm/at91/at91_pmc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pmcreg.h
===================================================================
--- trunk/sys/arm/at91/at91_pmcreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_pmcreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,145 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_pmcreg.h 239167 2012-08-10 04:47:20Z imp $ */
+
+#ifndef ARM_AT91_AT91_PMCREG_H
+#define ARM_AT91_AT91_PMCREG_H
+
+/* Registers */
+#define PMC_SCER 0x00 /* System Clock Enable Register */
+#define PMC_SCDR 0x04 /* System Clock Disable Register */
+#define PMC_SCSR 0x08 /* System Clock Status Register */
+ /* 0x0c reserved */
+#define PMC_PCER 0x10 /* Peripheral Clock Enable Register */
+#define PMC_PCDR 0x14 /* Peripheral Clock Disable Register */
+#define PMC_PCSR 0x18 /* Peripheral Clock Status Register */
+#define CKGR_UCKR 0x1c /* UTMI Clock Configuration Register */
+#define CKGR_MOR 0x20 /* Main Oscillator Register */
+#define CKGR_MCFR 0x24 /* Main Clock Frequency Register */
+#define CKGR_PLLAR 0x28 /* PLL A Register */
+#define CKGR_PLLBR 0x2c /* PLL B Register */
+#define PMC_MCKR 0x30 /* Master Clock Register */
+ /* 0x34 reserved */
+#define PMC_USB 0x38 /* USB Clock Register */
+ /* 0x3c reserved */
+#define PMC_PCK0 0x40 /* Programmable Clock 0 Register */
+#define PMC_PCK1 0x44 /* Programmable Clock 1 Register */
+#define PMC_PCK2 0x48 /* Programmable Clock 2 Register */
+#define PMC_PCK3 0x4c /* Programmable Clock 3 Register */
+ /* 0x50 reserved */
+ /* 0x54 reserved */
+ /* 0x58 reserved */
+ /* 0x5c reserved */
+#define PMC_IER 0x60 /* Interrupt Enable Register */
+#define PMC_IDR 0x64 /* Interrupt Disable Register */
+#define PMC_SR 0x68 /* Status Register */
+#define PMC_IMR 0x6c /* Interrupt Mask Register */
+ /* 0x70 reserved */
+ /* 0x74 reserved */
+ /* 0x78 reserved */
+ /* 0x7c reserved */
+#define PMC_PLLICPR 0x80 /* PLL Charge Pump Current Register */
+
+/* PMC System Clock Enable Register */
+/* PMC System Clock Disable Register */
+/* PMC System Clock StatusRegister */
+#define PMC_SCER_PCK (1UL << 0) /* PCK: Processor Clock Enable */
+#define PMC_SCER_UDP (1UL << 1) /* UDP: USB Device Port Clock Enable */
+#define PMC_SCER_MCKUDP (1UL << 2) /* MCKUDP: Master disable susp/res */
+#define PMC_SCER_UHP (1UL << 4) /* UHP: USB Host Port Clock Enable */
+#define PMC_SCER_PCK0 (1UL << 8) /* PCK0: Programmable Clock out en */
+#define PMC_SCER_PCK1 (1UL << 9) /* PCK1: Programmable Clock out en */
+#define PMC_SCER_PCK2 (1UL << 10) /* PCK2: Programmable Clock out en */
+#define PMC_SCER_PCK3 (1UL << 11) /* PCK3: Programmable Clock out en */
+#define PMC_SCER_UHP_SAM9 (1UL << 6) /* UHP: USB Host Port Clock Enable */
+#define PMC_SCER_UDP_SAM9 (1UL << 7) /* UDP: USB Device Port Clock Enable */
+
+/* PMC Peripheral Clock Enable Register */
+/* PMC Peripheral Clock Disable Register */
+/* PMC Peripheral Clock Status Register */
+/* Each bit here is 1 << peripheral number to enable/disable/status */
+
+/* PMC UTMI Clock Configuration Register */
+#define CKGR_UCKR_BIASEN (1UL << 24)
+#define CKGR_UCKR_UPLLEN (1UL << 16)
+
+/* PMC Clock Generator Main Oscillator Register */
+#define CKGR_MOR_MOSCEN (1UL << 0) /* MOSCEN: Main Oscillator Enable */
+#define CKGR_MOR_OSCBYPASS (1UL << 1) /* Oscillator Bypass */
+#define CKGR_MOR_OSCOUNT(x) (x << 8) /* Main Oscillator Start-up Time */
+
+/* PMC Clock Generator Main Clock Frequency Register */
+#define CKGR_MCFR_MAINRDY (1UL << 16) /* Main Clock Ready */
+#define CKGR_MCFR_MAINF_MASK 0xfffful /* Main Clock Frequency */
+
+/* PMC Clock Generator Master Clock Register */
+#define PMC_MCKR_PDIV (1 << 12) /* SAM9G20 Only */
+#define PMC_MCKR_PLLADIV2 (1 << 12) /* SAM9G45 Only */
+#define PMC_MCKR_CSS_MASK (3 << 0)
+#define PMC_MCKR_MDIV_MASK (3 << 8)
+#define PMC_MCKR_PRES_MASK (7 << 2)
+
+/* PMC USB Clock Register */
+#define PMC_USB_USBDIV(n) (((n) & 0x0F) << 8)
+#define PMC_USB_USBS (1 << 0)
+
+/* PMC Interrupt Enable Register */
+/* PMC Interrupt Disable Register */
+/* PMC Status Register */
+/* PMC Interrupt Mask Register */
+#define PMC_IER_MOSCS (1UL << 0) /* Main Oscillator Status */
+#define PMC_IER_LOCKA (1UL << 1) /* PLL A Locked */
+#define PMC_IER_LOCKB (1UL << 2) /* PLL B Locked */
+#define PMC_IER_MCKRDY (1UL << 3) /* Master Clock Status */
+#define PMC_IER_LOCKU (1UL << 6) /* UPLL Locked */
+#define PMC_IER_PCK0RDY (1UL << 8) /* Programmable Clock 0 Ready */
+#define PMC_IER_PCK1RDY (1UL << 9) /* Programmable Clock 1 Ready */
+#define PMC_IER_PCK2RDY (1UL << 10) /* Programmable Clock 2 Ready */
+#define PMC_IER_PCK3RDY (1UL << 11) /* Programmable Clock 3 Ready */
+
+/*
+ * PLL input frequency spec sheet says it must be between 1MHz and 32MHz,
+ * but it works down as low as 100kHz, a frequency necessary for some
+ * output frequencies to work.
+ */
+#define PMC_PLL_MIN_IN_FREQ 100000
+#define PMC_PLL_MAX_IN_FREQ 32000000
+
+/*
+ * PLL Max output frequency is 240MHz. The errata says 180MHz is the max
+ * for some revisions of this part. Be more permissive and optimistic.
+ */
+#define PMC_PLL_MAX_OUT_FREQ 240000000
+
+#define PMC_PLL_MULT_MIN 2
+#define PMC_PLL_MULT_MAX 2048
+
+#define PMC_PLL_SHIFT_TOL 5 /* Allow errors 1 part in 32 */
+
+#define PMC_PLL_FAST_THRESH 155000000
+
+#endif /* ARM_AT91_AT91_PMCREG_H */
Property changes on: trunk/sys/arm/at91/at91_pmcreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_pmcvar.h
===================================================================
--- trunk/sys/arm/at91/at91_pmcvar.h (rev 0)
+++ trunk/sys/arm/at91/at91_pmcvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,68 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_pmcvar.h 239190 2012-08-11 05:45:19Z imp $ */
+
+#ifndef ARM_AT91_AT91_PMCVAR_H
+#define ARM_AT91_AT91_PMCVAR_H
+
+struct at91_pmc_clock
+{
+ char *name;
+ uint32_t hz;
+ struct at91_pmc_clock *parent;
+ uint32_t pmc_mask;
+ void (*set_mode)(struct at91_pmc_clock *, int);
+ uint32_t refcnt;
+ unsigned id:2;
+ unsigned primary:1;
+ unsigned pll:1;
+ unsigned programmable:1;
+
+ /* PLL Params */
+ uint32_t pll_min_in;
+ uint32_t pll_max_in;
+ uint32_t pll_min_out;
+ uint32_t pll_max_out;
+
+ uint32_t pll_div_shift;
+ uint32_t pll_div_mask;
+ uint32_t pll_mul_shift;
+ uint32_t pll_mul_mask;
+
+ uint32_t (*set_outb)(int);
+};
+
+struct at91_pmc_clock *at91_pmc_clock_add(const char *name, uint32_t irq,
+ struct at91_pmc_clock *parent);
+struct at91_pmc_clock *at91_pmc_clock_ref(const char *name);
+void at91_pmc_clock_deref(struct at91_pmc_clock *);
+void at91_pmc_clock_enable(struct at91_pmc_clock *);
+void at91_pmc_clock_disable(struct at91_pmc_clock *);
+
+uint32_t at91_pmc_800mhz_plla_outb(int freq);
+uint32_t at91_pmc_800mhz_pllb_outb(int freq);
+#endif /* ARM_AT91_AT91_PMCVAR_H */
Property changes on: trunk/sys/arm/at91/at91_pmcvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_reset.S
===================================================================
--- trunk/sys/arm/at91/at91_reset.S (rev 0)
+++ trunk/sys/arm/at91/at91_reset.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,58 @@
+/* $MidnightBSD$ */
+#include <machine/asm.h>
+#include <arm/at91/at91_rstreg.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91sam9g20reg.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_reset.S 238330 2012-07-10 02:14:50Z imp $");
+
+#define SDRAM_TR (AT91_BASE + \
+ AT91SAM9G20_SDRAMC_BASE + AT91SAM9G20_SDRAMC_TR)
+#define SDRAM_LPR (AT91_BASE + \
+ AT91SAM9G20_SDRAMC_BASE + AT91SAM9G20_SDRAMC_LPR)
+#define RSTC_RCR (AT91_BASE + \
+ AT91SAM9G20_RSTC_BASE + RST_CR)
+
+/*
+ * From AT91SAM9G20 Datasheet errata 44:3.5:
+ *
+ * When User Reset occurs durring SDRAM read acces, eh SDRAM clock is turned
+ * off while data are ready to be read on the data bus. The SDRAM maintains
+ * the data until the clock restarts.
+ *
+ * If the User reset is programed to assert a general reset, the data
+ * maintained by the SDRAM leads to a data bus conflict and adversly affects
+ * the boot memories connected to the EBI:
+ * + NAND Flash boot functionality, if the system boots out of internal ROM.
+ * + NOR Flash boot, if the system boots on an external memory connected to
+ * the EBI CS0.
+ *
+ * Assembly code is mandatory for the following sequnce as ARM
+ * instructions need to be piplined.
+ *
+ */
+
+ENTRY(cpu_reset_sam9g20)
+
+ /* Disable IRQs */
+ mrs r0, cpsr
+ orr r0, r0, #0x80
+ msr cpsr_c, r0
+
+ /* Change Refresh to block all data access */
+ ldr r0, =SDRAM_TR
+ ldr r1, =1
+ str r1, [r0]
+
+ /* Prepare power down command */
+ ldr r0, =SDRAM_LPR
+ ldr r1, =2
+
+ /* Prepare proc_reset and periph reset */
+ ldr r2, =RSTC_RCR
+ ldr r3, =0xA5000005
+
+ /* perform power down command */
+ str r1, [r0]
+
+ /* Perfom proc_reset and periph reset (in the ARM pipeline) */
+ str r3, [r2]
Property changes on: trunk/sys/arm/at91/at91_reset.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_rst.c
===================================================================
--- trunk/sys/arm/at91/at91_rst.c (rev 0)
+++ trunk/sys/arm/at91/at91_rst.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,236 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_rst.c 266196 2014-05-15 21:21:47Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_rstreg.h>
+#include <arm/at91/at91board.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#define FDT_HACKS 1
+#endif
+
+#define RST_TIMEOUT (5) /* Seconds to hold NRST for hard reset */
+#define RST_TICK (20) /* sample NRST at hz/RST_TICK intervals */
+
+#ifndef FDT
+static int at91_rst_intr(void *arg);
+#endif
+
+static struct at91_rst_softc {
+ struct resource *mem_res; /* Memory resource */
+ struct resource *irq_res; /* IRQ resource */
+ void *intrhand; /* Interrupt handle */
+ struct callout tick_ch; /* Tick callout */
+ device_t sc_dev;
+ u_int shutdown; /* Shutdown in progress */
+} *at91_rst_sc;
+
+static inline uint32_t
+RD4(struct at91_rst_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct at91_rst_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+void cpu_reset_sam9g20(void) __attribute__((weak));
+void cpu_reset_sam9g20(void) {}
+
+void
+at91_rst_cpu_reset(void)
+{
+
+ if (at91_rst_sc) {
+ cpu_reset_sam9g20(); /* May be null */
+
+ WR4(at91_rst_sc, RST_MR,
+ RST_MR_ERSTL(0xd) | RST_MR_URSTEN | RST_MR_KEY);
+
+ WR4(at91_rst_sc, RST_CR,
+ RST_CR_PROCRST |
+ RST_CR_PERRST |
+ RST_CR_EXTRST |
+ RST_CR_KEY);
+ }
+ while(1)
+ continue;
+}
+
+static int
+at91_rst_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91sam9260-rstc"))
+ return (ENXIO);
+#endif
+
+ device_set_desc(dev, "AT91SAM9 Reset Controller");
+ return (0);
+}
+
+static int
+at91_rst_attach(device_t dev)
+{
+ struct at91_rst_softc *sc;
+ const char *cause;
+ int rid, err = 0;
+
+ at91_rst_sc = sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ callout_init(&sc->tick_ch, 0);
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resources.\n");
+ err = ENOMEM;
+ goto out;
+ }
+
+#ifndef FDT_HACKS
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "could not allocate interrupt resources.\n");
+ err = ENOMEM;
+ goto out;
+ }
+
+ /* Activate the interrupt. */
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ at91_rst_intr, NULL, sc, &sc->intrhand);
+ if (err)
+ device_printf(dev, "could not establish interrupt handler.\n");
+#endif
+
+ WR4(at91_rst_sc, RST_MR, RST_MR_ERSTL(0xd) | RST_MR_URSIEN | RST_MR_KEY);
+
+ switch (RD4(sc, RST_SR) & RST_SR_RST_MASK) {
+ case RST_SR_RST_POW:
+ cause = "Power On";
+ break;
+ case RST_SR_RST_WAKE:
+ cause = "Wake Up";
+ break;
+ case RST_SR_RST_WDT:
+ cause = "Watchdog";
+ break;
+ case RST_SR_RST_SOFT:
+ cause = "Software Request";
+ break;
+ case RST_SR_RST_USR:
+ cause = "External (User)";
+ break;
+ default:
+ cause = "Unknown";
+ break;
+ }
+
+ device_printf(dev, "Reset cause: %s.\n", cause);
+out:
+ return (err);
+}
+
+#ifndef FDT_HACKS
+static void
+at91_rst_tick(void *argp)
+{
+ struct at91_rst_softc *sc = argp;
+
+ if (sc->shutdown++ >= RST_TIMEOUT * RST_TICK) {
+ /* User released the button in morre than RST_TIMEOUT */
+ cpu_reset();
+ } else if ((RD4(sc, RST_SR) & RST_SR_NRSTL)) {
+ /* User released the button in less than RST_TIMEOUT */
+ sc->shutdown = 0;
+ device_printf(sc->sc_dev, "shutting down...\n");
+ shutdown_nice(0);
+ } else {
+ callout_reset(&sc->tick_ch, hz/RST_TICK, at91_rst_tick, sc);
+ }
+}
+
+static int
+at91_rst_intr(void *argp)
+{
+ struct at91_rst_softc *sc = argp;
+
+ if (RD4(sc, RST_SR) & RST_SR_URSTS) {
+ if (sc->shutdown == 0)
+ callout_reset(&sc->tick_ch, hz/RST_TICK, at91_rst_tick, sc);
+ return (FILTER_HANDLED);
+ }
+ return (FILTER_STRAY);
+}
+#endif
+
+static device_method_t at91_rst_methods[] = {
+ DEVMETHOD(device_probe, at91_rst_probe),
+ DEVMETHOD(device_attach, at91_rst_attach),
+ DEVMETHOD_END
+};
+
+static driver_t at91_rst_driver = {
+ "at91_rst",
+ at91_rst_methods,
+ sizeof(struct at91_rst_softc),
+};
+
+static devclass_t at91_rst_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_rst, simplebus, at91_rst_driver, at91_rst_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_rst, atmelarm, at91_rst_driver, at91_rst_devclass, NULL,
+ NULL);
+#endif
Property changes on: trunk/sys/arm/at91/at91_rst.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_rstreg.h
===================================================================
--- trunk/sys/arm/at91/at91_rstreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_rstreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,64 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_rstreg.h 238369 2012-07-11 17:11:07Z imp $ */
+
+#ifndef ARM_AT91_AT91_RSTREG_H
+#define ARM_AT91_AT91_RSTREG_H
+
+#define RST_CR 0x0 /* Control Register */
+#define RST_SR 0x4 /* Status Register */
+#define RST_MR 0x8 /* Mode Register */
+
+/* RST_CR */
+#define RST_CR_PROCRST (1<<0)
+#define RST_CR_PERRST (1<<2)
+#define RST_CR_EXTRST (1<<3)
+#define RST_CR_KEY (0xa5<<24)
+
+/* RST_SR */
+#define RST_SR_SRCMP (1<<17) /* Software Reset in progress */
+#define RST_SR_NRSTL (1<<16) /* NRST pin level at MCK */
+#define RST_SR_URSTS (1<<0) /* NRST pin has been active */
+
+#define RST_SR_RST_POW (0<<8) /* General (Power On) reset */
+#define RST_SR_RST_WAKE (1<<8) /* Wake-up reset */
+#define RST_SR_RST_WDT (2<<8) /* Watchdog reset */
+#define RST_SR_RST_SOFT (3<<8) /* Software reset */
+#define RST_SR_RST_USR (4<<8) /* User (External) reset */
+#define RST_SR_RST_MASK (7<<8) /* User (External) reset */
+
+/* RST_MR */
+#define RST_MR_URSTEN (1<<0) /* User reset enable */
+#define RST_MR_URSIEN (1<<4) /* User interrupt enable */
+#define RST_MR_ERSTL(x) ((x)<<8) /* External reset length */
+#define RST_MR_KEY (0xa5<<24)
+
+#ifndef __ASSEMBLER__
+void at91_rst_cpu_reset(void);
+#endif
+
+#endif /* ARM_AT91_AT91_RSTREG_H */
Property changes on: trunk/sys/arm/at91/at91_rstreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_rtc.c
===================================================================
--- trunk/sys/arm/at91/at91_rtc.c (rev 0)
+++ trunk/sys/arm/at91/at91_rtc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,365 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2012 Ian Lepore. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Driver for the at91 on-chip realtime clock.
+ *
+ * This driver does not currently support alarms, just date and time.
+ *
+ * The RTC on the AT91RM9200 resets when the core rests, so it is useless as a
+ * source of time (except when the CPU clock is powered down to save power,
+ * which we don't currently do). On AT91SAM9 chips, the RTC survives chip
+ * reset, and there's provisions for it to keep time via battery backup if the
+ * system loses power. On those systems, we use it as a RTC. We tell the two
+ * apart because the century field is 19 on AT91RM9200 on reset, or on AT91SAM9
+ * chips that haven't had their time properly set.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_rtc.c 241333 2012-10-07 20:36:46Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <arm/at91/at91_rtcreg.h>
+
+#include "clock_if.h"
+
+/*
+ * The driver has all the infrastructure to use interrupts but doesn't actually
+ * have any need to do so right now. There's a non-zero cost for installing the
+ * handler because the RTC shares the system interrupt (IRQ 1), and thus will
+ * get called a lot for no reason at all.
+ */
+#define AT91_RTC_USE_INTERRUPTS_NOT
+
+struct at91_rtc_softc
+{
+ device_t dev; /* Myself */
+ void *intrhand; /* Interrupt handle */
+ struct resource *irq_res; /* IRQ resource */
+ struct resource *mem_res; /* Memory resource */
+ struct mtx sc_mtx; /* basically a perimeter lock */
+};
+
+static inline uint32_t
+RD4(struct at91_rtc_softc *sc, bus_size_t off)
+{
+ return bus_read_4(sc->mem_res, off);
+}
+
+static inline void
+WR4(struct at91_rtc_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->mem_res, off, val);
+}
+
+#define AT91_RTC_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
+#define AT91_RTC_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx)
+#define AT91_RTC_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+ "rtc", MTX_SPIN)
+#define AT91_RTC_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define AT91_RTC_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define AT91_RTC_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+static devclass_t at91_rtc_devclass;
+
+/* bus entry points */
+
+static int at91_rtc_probe(device_t dev);
+static int at91_rtc_attach(device_t dev);
+static int at91_rtc_detach(device_t dev);
+
+/* helper routines */
+static int at91_rtc_activate(device_t dev);
+static void at91_rtc_deactivate(device_t dev);
+
+#ifdef AT91_RTC_USE_INTERRUPTS
+static int
+at91_rtc_intr(void *xsc)
+{
+ struct at91_rtc_softc *sc;
+ uint32_t status;
+
+ sc = xsc;
+ /* Must clear the status bits after reading them to re-arm. */
+ status = RD4(sc, RTC_SR);
+ WR4(sc, RTC_SCCR, status);
+ if (status == 0)
+ return;
+ AT91_RTC_LOCK(sc);
+ /* Do something here */
+ AT91_RTC_UNLOCK(sc);
+ wakeup(sc);
+ return (FILTER_HANDLED);
+}
+#endif
+
+static int
+at91_rtc_probe(device_t dev)
+{
+ device_set_desc(dev, "RTC");
+ return (0);
+}
+
+static int
+at91_rtc_attach(device_t dev)
+{
+ struct at91_rtc_softc *sc = device_get_softc(dev);
+ int err;
+
+ sc->dev = dev;
+ err = at91_rtc_activate(dev);
+ if (err)
+ goto out;
+
+ AT91_RTC_LOCK_INIT(sc);
+
+ /*
+ * Disable all interrupts in the hardware.
+ * Clear all bits in the status register.
+ * Set 24-hour-clock mode.
+ */
+ WR4(sc, RTC_IDR, 0xffffffff);
+ WR4(sc, RTC_SCCR, 0x1f);
+ WR4(sc, RTC_MR, 0);
+
+#ifdef AT91_RTC_USE_INTERRUPTS
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
+ at91_rtc_intr, NULL, sc, &sc->intrhand);
+ if (err) {
+ AT91_RTC_LOCK_DESTROY(sc);
+ goto out;
+ }
+#endif
+
+ /*
+ * Read the calendar register. If the century is 19 then the clock has
+ * never been set. Try to store an invalid value into the register,
+ * which will turn on the error bit in RTC_VER, and our getclock code
+ * knows to return EINVAL if any error bits are on.
+ */
+ if (RTC_CALR_CEN(RD4(sc, RTC_CALR)) == 19)
+ WR4(sc, RTC_CALR, 0);
+
+ /*
+ * Register as a time of day clock with 1-second resolution.
+ */
+ clock_register(dev, 1000000);
+out:
+ if (err)
+ at91_rtc_deactivate(dev);
+ return (err);
+}
+
+/*
+ * Cannot support detach, since there's no clock_unregister function.
+ */
+static int
+at91_rtc_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static int
+at91_rtc_activate(device_t dev)
+{
+ struct at91_rtc_softc *sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ goto errout;
+#ifdef AT91_RTC_USE_INTERRUPTS
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->irq_res == NULL)
+ goto errout;
+#endif
+ return (0);
+errout:
+ at91_rtc_deactivate(dev);
+ return (ENOMEM);
+}
+
+static void
+at91_rtc_deactivate(device_t dev)
+{
+ struct at91_rtc_softc *sc;
+
+ sc = device_get_softc(dev);
+#ifdef AT91_RTC_USE_INTERRUPTS
+ WR4(sc, RTC_IDR, 0xffffffff);
+ if (sc->intrhand)
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ sc->intrhand = 0;
+#endif
+ bus_generic_detach(sc->dev);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = 0;
+#ifdef AT91_RTC_USE_INTERRUPTS
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ sc->irq_res = 0;
+#endif
+ return;
+}
+
+/*
+ * Get the time of day clock and return it in ts.
+ * Return 0 on success, an error number otherwise.
+ */
+static int
+at91_rtc_gettime(device_t dev, struct timespec *ts)
+{
+ struct clocktime ct;
+ uint32_t calr, calr2, timr, timr2;
+ struct at91_rtc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* If the error bits are set we can't return useful values. */
+
+ if (RD4(sc, RTC_VER) & (RTC_VER_NVTIM | RTC_VER_NVCAL))
+ return EINVAL;
+
+ /*
+ * The RTC hardware can update registers while the CPU is reading them.
+ * The manual advises reading until you obtain the same values twice.
+ * Interleaving the reads (rather than timr, timr2, calr, calr2 order)
+ * also ensures we don't miss a midnight rollover/carry between reads.
+ */
+ do {
+ timr = RD4(sc, RTC_TIMR);
+ calr = RD4(sc, RTC_CALR);
+ timr2 = RD4(sc, RTC_TIMR);
+ calr2 = RD4(sc, RTC_CALR);
+ } while (timr != timr2 || calr != calr2);
+
+ ct.nsec = 0;
+ ct.sec = RTC_TIMR_SEC(timr);
+ ct.min = RTC_TIMR_MIN(timr);
+ ct.hour = RTC_TIMR_HR(timr);
+ ct.year = RTC_CALR_CEN(calr) * 100 + RTC_CALR_YEAR(calr);
+ ct.mon = RTC_CALR_MON(calr);
+ ct.day = RTC_CALR_DAY(calr);
+ ct.dow = -1;
+ return clock_ct_to_ts(&ct, ts);
+}
+
+/*
+ * Set the time of day clock based on the value of the struct timespec arg.
+ * Return 0 on success, an error number otherwise.
+ */
+static int
+at91_rtc_settime(device_t dev, struct timespec *ts)
+{
+ struct at91_rtc_softc *sc;
+ struct clocktime ct;
+ int rv;
+
+ sc = device_get_softc(dev);
+ clock_ts_to_ct(ts, &ct);
+
+ /*
+ * Can't set the clock unless a second has elapsed since we last did so.
+ */
+ while ((RD4(sc, RTC_SR) & RTC_SR_SECEV) == 0)
+ cpu_spinwait();
+
+ /*
+ * Stop the clocks for an update; wait until hardware is ready.
+ * Clear the update-ready status after it gets asserted (the manual says
+ * to do this before updating the value registers).
+ */
+ WR4(sc, RTC_CR, RTC_CR_UPDCAL | RTC_CR_UPDTIM);
+ while ((RD4(sc, RTC_SR) & RTC_SR_ACKUPD) == 0)
+ cpu_spinwait();
+ WR4(sc, RTC_SCCR, RTC_SR_ACKUPD);
+
+ /*
+ * Set the values in the hardware, then check whether the hardware was
+ * happy with them so we can return the correct status.
+ */
+ WR4(sc, RTC_TIMR, RTC_TIMR_MK(ct.hour, ct.min, ct.sec));
+ WR4(sc, RTC_CALR, RTC_CALR_MK(ct.year, ct.mon, ct.day, ct.dow+1));
+
+ if (RD4(sc, RTC_VER) & (RTC_VER_NVTIM | RTC_VER_NVCAL))
+ rv = EINVAL;
+ else
+ rv = 0;
+
+ /*
+ * Restart the clocks (turn off the update bits).
+ * Clear the second-event bit (because the manual says to).
+ */
+ WR4(sc, RTC_CR, RD4(sc, RTC_CR) & ~(RTC_CR_UPDCAL | RTC_CR_UPDTIM));
+ WR4(sc, RTC_SCCR, RTC_SR_SECEV);
+
+ return (0);
+}
+
+static device_method_t at91_rtc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, at91_rtc_probe),
+ DEVMETHOD(device_attach, at91_rtc_attach),
+ DEVMETHOD(device_detach, at91_rtc_detach),
+
+ /* clock interface */
+ DEVMETHOD(clock_gettime, at91_rtc_gettime),
+ DEVMETHOD(clock_settime, at91_rtc_settime),
+
+ DEVMETHOD_END
+};
+
+static driver_t at91_rtc_driver = {
+ "at91_rtc",
+ at91_rtc_methods,
+ sizeof(struct at91_rtc_softc),
+};
+
+DRIVER_MODULE(at91_rtc, atmelarm, at91_rtc_driver, at91_rtc_devclass, 0, 0);
Property changes on: trunk/sys/arm/at91/at91_rtc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_rtcreg.h
===================================================================
--- trunk/sys/arm/at91/at91_rtcreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_rtcreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,104 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_rtcreg.h 241307 2012-10-07 01:58:32Z imp $ */
+
+#ifndef ARM_AT91_AT91_RTCREG_H
+#define ARM_AT91_AT91_RTCREG_H
+
+/* Registers */
+#define RTC_CR 0x00 /* RTC Control Register */
+#define RTC_MR 0x04 /* RTC Mode Register */
+#define RTC_TIMR 0x08 /* RTC Time Register */
+#define RTC_CALR 0x0c /* RTC Calendar Register */
+#define RTC_TIMALR 0x10 /* RTC Time Alarm Register */
+#define RTC_CALALR 0x14 /* RTC Calendar Alarm Register */
+#define RTC_SR 0x18 /* RTC Status Register */
+#define RTC_SCCR 0x1c /* RTC Status Command Clear Register */
+#define RTC_IER 0x20 /* RTC Interrupt Enable Register */
+#define RTC_IDR 0x24 /* RTC Interrupt Disable Register */
+#define RTC_IMR 0x28 /* RTC Interrupt Mask Register */
+#define RTC_VER 0x2c /* RTC Valid Entry Register */
+
+/* CR */
+#define RTC_CR_UPDTIM (0x1u << 0) /* Request update of time register */
+#define RTC_CR_UPDCAL (0x1u << 1) /* Request update of calendar reg. */
+
+/* TIMR */
+#define RTC_TIMR_SEC_M 0x7fUL
+#define RTC_TIMR_SEC_S 0
+#define RTC_TIMR_SEC(x) FROMBCD(((x) & RTC_TIMR_SEC_M) >> RTC_TIMR_SEC_S)
+#define RTC_TIMR_MIN_M 0x7f00UL
+#define RTC_TIMR_MIN_S 8
+#define RTC_TIMR_MIN(x) FROMBCD(((x) & RTC_TIMR_MIN_M) >> RTC_TIMR_MIN_S)
+#define RTC_TIMR_HR_M 0x3f0000UL
+#define RTC_TIMR_HR_S 16
+#define RTC_TIMR_HR(x) FROMBCD(((x) & RTC_TIMR_HR_M) >> RTC_TIMR_HR_S)
+#define RTC_TIMR_MK(hr, min, sec) \
+ ((TOBCD(hr) << RTC_TIMR_HR_S) | \
+ (TOBCD(min) << RTC_TIMR_MIN_S) | \
+ (TOBCD(sec) << RTC_TIMR_SEC_S))
+#define RTC_TIMR_PM (1UL << 22)
+
+/* CALR */
+#define RTC_CALR_CEN_M 0x0000007fUL
+#define RTC_CALR_CEN_S 0
+#define RTC_CALR_CEN(x) FROMBCD(((x) & RTC_CALR_CEN_M) >> RTC_CALR_CEN_S)
+#define RTC_CALR_YEAR_M 0x0000ff00UL
+#define RTC_CALR_YEAR_S 8
+#define RTC_CALR_YEAR(x) FROMBCD(((x) & RTC_CALR_YEAR_M) >> RTC_CALR_YEAR_S)
+#define RTC_CALR_MON_M 0x001f0000UL
+#define RTC_CALR_MON_S 16
+#define RTC_CALR_MON(x) FROMBCD(((x) & RTC_CALR_MON_M) >> RTC_CALR_MON_S)
+#define RTC_CALR_DOW_M 0x00d0000UL
+#define RTC_CALR_DOW_S 21
+#define RTC_CALR_DOW(x) FROMBCD(((x) & RTC_CALR_DOW_M) >> RTC_CALR_DOW_S)
+#define RTC_CALR_DAY_M 0x3f000000UL
+#define RTC_CALR_DAY_S 24
+#define RTC_CALR_DAY(x) FROMBCD(((x) & RTC_CALR_DAY_M) >> RTC_CALR_DAY_S)
+#define RTC_CALR_MK(yr, mon, day, dow) \
+ ((TOBCD((yr) / 100) << RTC_CALR_CEN_S) | \
+ (TOBCD((yr) % 100) << RTC_CALR_YEAR_S) | \
+ (TOBCD(mon) << RTC_CALR_MON_S) | \
+ (TOBCD(dow) << RTC_CALR_DOW_S) | \
+ (TOBCD(day) << RTC_CALR_DAY_S))
+
+/* SR */
+
+#define RTC_SR_ACKUPD (0x1u << 0) /* Acknowledge for Update */
+#define RTC_SR_ALARM (0x1u << 1) /* Alarm Flag */
+#define RTC_SR_SECEV (0x1u << 2) /* Second Event */
+#define RTC_SR_TIMEV (0x1u << 3) /* Time Event */
+#define RTC_SR_CALEV (0x1u << 4) /* Calendar event */
+
+/* VER */
+
+#define RTC_VER_NVTIM (0x1 << 0) /* Non-valid time */
+#define RTC_VER_NVCAL (0x1 << 1) /* Non-valid calendar */
+#define RTC_VER_NVTIMALR (0x1 << 2) /* Non-valid time alarm */
+#define RTC_VER_NVCALALR (0x1 << 3) /* Non-valid calendar alarm */
+
+#endif /* ARM_AT91_AT91_RTCREG_H */
Property changes on: trunk/sys/arm/at91/at91_rtcreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_sdramc.c
===================================================================
--- trunk/sys/arm/at91/at91_sdramc.c (rev 0)
+++ trunk/sys/arm/at91/at91_sdramc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,106 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_sdramc.c 266217 2014-05-16 12:43:45Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_aicreg.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+struct sdramc_softc {
+ struct resource *mem_res; /* Memory resource */
+ device_t sc_dev;
+};
+
+static int
+at91_sdramc_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91sam9260-sdramc"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "SDRAMC");
+ return (0);
+}
+
+static int
+at91_sdramc_attach(device_t dev)
+{
+ int rid, err = 0;
+ struct sdramc_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+
+ if (sc->mem_res == NULL)
+ panic("couldn't allocate register resources");
+
+ return (err);
+}
+
+static device_method_t at91_sdramc_methods[] = {
+ DEVMETHOD(device_probe, at91_sdramc_probe),
+ DEVMETHOD(device_attach, at91_sdramc_attach),
+ DEVMETHOD_END
+};
+
+static driver_t at91_sdramc_driver = {
+ "at91_sdramc",
+ at91_sdramc_methods,
+ sizeof(struct sdramc_softc),
+};
+
+static devclass_t at91_sdramc_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_sdramc, simplebus, at91_sdramc_driver, at91_sdramc_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_sdramc, atmelarm, at91_sdramc_driver, at91_sdramc_devclass, NULL,
+ NULL);
+#endif
Property changes on: trunk/sys/arm/at91/at91_sdramc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_shdwc.c
===================================================================
--- trunk/sys/arm/at91/at91_shdwc.c (rev 0)
+++ trunk/sys/arm/at91/at91_shdwc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,106 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_shdwc.c 266217 2014-05-16 12:43:45Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_aicreg.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+struct shdwc_softc {
+ struct resource *mem_res; /* Memory resource */
+ device_t sc_dev;
+};
+
+static int
+at91_shdwc_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91sam9260-shdwc"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "SHDWC");
+ return (0);
+}
+
+static int
+at91_shdwc_attach(device_t dev)
+{
+ int rid, err = 0;
+ struct shdwc_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+
+ if (sc->mem_res == NULL)
+ panic("couldn't allocate register resources");
+
+ return (err);
+}
+
+static device_method_t at91_shdwc_methods[] = {
+ DEVMETHOD(device_probe, at91_shdwc_probe),
+ DEVMETHOD(device_attach, at91_shdwc_attach),
+ DEVMETHOD_END
+};
+
+static driver_t at91_shdwc_driver = {
+ "at91_shdwc",
+ at91_shdwc_methods,
+ sizeof(struct shdwc_softc),
+};
+
+static devclass_t at91_shdwc_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_shdwc, simplebus, at91_shdwc_driver, at91_shdwc_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_shdwc, atmelarm, at91_shdwc_driver, at91_shdwc_devclass, NULL,
+ NULL);
+#endif
Property changes on: trunk/sys/arm/at91/at91_shdwc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_smc.c
===================================================================
--- trunk/sys/arm/at91/at91_smc.c (rev 0)
+++ trunk/sys/arm/at91/at91_smc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,92 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_smc.c 266087 2014-05-14 20:31:54Z ian $");
+
+#include <sys/types.h>
+
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91_smc.h>
+#include <arm/at91/at91sam9260reg.h>
+
+/*
+ * RD4HW()/WR4HW() read and write at91 hardware register space directly. They
+ * serve the same purpose as the RD4()/WR4() idiom you see in many drivers,
+ * except that those translate to bus_space calls, but in this code we need to
+ * access some devices before bus_space is ready to use. Of course for this to
+ * work the appropriate static device mappings need to be made in machdep.c.
+ */
+static inline uint32_t
+RD4HW(uint32_t devbase, uint32_t regoff)
+{
+
+ return *(volatile uint32_t *)(AT91_BASE + devbase + regoff);
+}
+
+
+static inline void
+WR4HW(uint32_t devbase, uint32_t regoff, uint32_t val)
+{
+
+ *(volatile uint32_t *)(AT91_BASE + devbase + regoff) = val;
+}
+
+
+void
+at91_smc_setup(int id, int cs, const struct at91_smc_init *smc)
+{
+ // Need a generic way to get this address for all SoCs... Assume 9260 for now...
+ uint32_t base = AT91SAM9260_SMC_BASE + SMC_CS_OFF(cs);
+
+ WR4HW(base, SMC_SETUP, SMC_SETUP_NCS_RD_SETUP(smc->ncs_rd_setup) |
+ SMC_SETUP_NRD_SETUP(smc->nrd_setup) |
+ SMC_SETUP_NCS_WR_SETUP(smc->ncs_wr_setup) |
+ SMC_SETUP_NWE_SETUP(smc->nwe_setup));
+ WR4HW(base, SMC_PULSE, SMC_PULSE_NCS_RD_PULSE(smc->ncs_rd_pulse) |
+ SMC_PULSE_NRD_PULSE(smc->nrd_pulse) |
+ SMC_PULSE_NCS_WR_PULSE(smc->ncs_wr_pulse) |
+ SMC_PULSE_NWE_PULSE(smc->nwe_pulse));
+ WR4HW(base, SMC_CYCLE, SMC_CYCLE_NRD_CYCLE(smc->nrd_cycle) |
+ SMC_CYCLE_NWE_CYCLE(smc->nwe_cycle));
+ WR4HW(base, SMC_MODE, smc->mode | SMC_MODE_TDF_CYCLES(smc->tdf_cycles));
+}
+
+void
+at91_ebi_enable(int bank)
+{
+
+ WR4HW(AT91SAM9260_MATRIX_BASE, AT91SAM9260_EBICSA, (1 << bank) |
+ RD4HW(AT91SAM9260_MATRIX_BASE, AT91SAM9260_EBICSA));
+}
+
+void
+at91_ebi_disable(int bank)
+{
+
+ WR4HW(AT91SAM9260_MATRIX_BASE, AT91SAM9260_EBICSA, ~(1 << bank) &
+ RD4HW(AT91SAM9260_MATRIX_BASE, AT91SAM9260_EBICSA));
+}
Property changes on: trunk/sys/arm/at91/at91_smc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_smc.h
===================================================================
--- trunk/sys/arm/at91/at91_smc.h (rev 0)
+++ trunk/sys/arm/at91/at91_smc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,117 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_smc.h 266087 2014-05-14 20:31:54Z ian $ */
+
+#ifndef ARM_AT91_AT91_SMC_H
+#define ARM_AT91_AT91_SMC_H
+
+/* Registers */
+#define SMC_SETUP 0x00
+#define SMC_PULSE 0x04
+#define SMC_CYCLE 0x08
+#define SMC_MODE 0x0C
+
+#define SMC_CS_OFF(cs) (0x10 * (cs))
+
+/* Setup */
+#define SMC_SETUP_NCS_RD_SETUP(x) ((x) << 24)
+#define SMC_SETUP_NRD_SETUP(x) ((x) << 16)
+#define SMC_SETUP_NCS_WR_SETUP(x) ((x) << 8)
+#define SMC_SETUP_NWE_SETUP(x) (x)
+
+/* Pulse */
+#define SMC_PULSE_NCS_RD_PULSE(x) ((x) << 24)
+#define SMC_PULSE_NRD_PULSE(x) ((x) << 16)
+#define SMC_PULSE_NCS_WR_PULSE(x) ((x) << 8)
+#define SMC_PULSE_NWE_PULSE(x) (x)
+
+/* Cycle */
+#define SMC_CYCLE_NRD_CYCLE(x) ((x) << 16)
+#define SMC_CYCLE_NWE_CYCLE(x) (x)
+
+/* Mode */
+#define SMC_MODE_READ (1 << 0)
+#define SMC_MODE_WRITE (1 << 1)
+#define SMC_MODE_EXNW_DISABLED (0 << 4)
+#define SMC_MODE_EXNW_FROZEN_MODE (2 << 4)
+#define SMC_MODE_EXNW_READY_MODE (3 << 4)
+#define SMC_MODE_BAT (1 << 8)
+#define SMC_MODE_DBW_8BIT (0 << 12)
+#define SMC_MODE_DBW_16BIT (1 << 12)
+#define SMC_MODE_DBW_32_BIT (2 << 12)
+#define SMC_MODE_TDF_CYCLES(x) ((x) << 16)
+#define SMC_MODE_TDF_MODE (1 << 20)
+#define SMC_MODE_PMEN (1 << 24)
+#define SMC_PS_4BYTE (0 << 28)
+#define SMC_PS_8BYTE (1 << 28)
+#define SMC_PS_16BYTE (2 << 28)
+#define SMC_PS_32BYTE (3 << 28)
+
+/*
+ * structure to ease init. See the SMC chapter in the datasheet for
+ * the appropriate SoC you are using for details.
+ */
+struct at91_smc_init
+{
+ /* Setup register */
+ uint8_t ncs_rd_setup;
+ uint8_t nrd_setup;
+ uint8_t ncs_wr_setup;
+ uint8_t nwe_setup;
+
+ /* Pulse register */
+ uint8_t ncs_rd_pulse;
+ uint8_t nrd_pulse;
+ uint8_t ncs_wr_pulse;
+ uint8_t nwe_pulse;
+
+ /* Cycle register */
+ uint16_t nrd_cycle;
+ uint16_t nwe_cycle;
+
+ /* Mode register */
+ uint8_t mode; /* Combo of READ/WRITE/EXNW fields */
+ uint8_t bat;
+ uint8_t dwb;
+ uint8_t tdf_cycles;
+ uint8_t tdf_mode;
+ uint8_t pmen;
+ uint8_t ps;
+};
+
+/*
+ * Convenience routine to fill in SMC registers for a given chip select.
+ */
+void at91_smc_setup(int id, int cs, const struct at91_smc_init *smc);
+
+/*
+ * Disable/Enable different External Bus Interfaces (EBI)
+ */
+void at91_ebi_enable(int cs);
+void at91_ebi_disable(int cs);
+
+#endif /* ARM_AT91_AT91_SMC_H */
Property changes on: trunk/sys/arm/at91/at91_smc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_spi.c
===================================================================
--- trunk/sys/arm/at91/at91_spi.c (rev 0)
+++ trunk/sys/arm/at91/at91_spi.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,458 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh.
+ * Copyright (c) 2011-2012 Ian Lepore.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_spi.c 266196 2014-05-15 21:21:47Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/sx.h>
+
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_spireg.h>
+#include <arm/at91/at91_pdcreg.h>
+
+#include <dev/spibus/spi.h>
+#include <dev/spibus/spibusvar.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#include "spibus_if.h"
+
+struct at91_spi_softc
+{
+ device_t dev; /* Myself */
+ void *intrhand; /* Interrupt handle */
+ struct resource *irq_res; /* IRQ resource */
+ struct resource *mem_res; /* Memory resource */
+ bus_dma_tag_t dmatag; /* bus dma tag for transfers */
+ bus_dmamap_t map[4]; /* Maps for the transaction */
+ struct sx xfer_mtx; /* Enforce one transfer at a time */
+ uint32_t xfer_done; /* interrupt<->mainthread signaling */
+};
+
+#define CS_TO_MR(cs) ((~(1 << (cs)) & 0x0f) << 16)
+
+static inline uint32_t
+RD4(struct at91_spi_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct at91_spi_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+/* bus entry points */
+static int at91_spi_attach(device_t dev);
+static int at91_spi_detach(device_t dev);
+static int at91_spi_probe(device_t dev);
+static int at91_spi_transfer(device_t dev, device_t child,
+ struct spi_command *cmd);
+
+/* helper routines */
+static void at91_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs,
+ int error);
+static int at91_spi_activate(device_t dev);
+static void at91_spi_deactivate(device_t dev);
+static void at91_spi_intr(void *arg);
+
+static int
+at91_spi_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-spi"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "AT91 SPI");
+ return (0);
+}
+
+static int
+at91_spi_attach(device_t dev)
+{
+ struct at91_spi_softc *sc;
+ int err;
+ uint32_t csr;
+
+ sc = device_get_softc(dev);
+
+ sc->dev = dev;
+ sx_init(&sc->xfer_mtx, device_get_nameunit(dev));
+
+ /*
+ * Allocate resources.
+ */
+ err = at91_spi_activate(dev);
+ if (err)
+ goto out;
+
+#ifdef FDT
+ /*
+ * Disable devices need to hold their resources, so return now and not attach
+ * the spibus, setup interrupt handlers, etc.
+ */
+ if (!ofw_bus_status_okay(dev))
+ return 0;
+#endif
+
+ /*
+ * Set up the hardware.
+ */
+
+ WR4(sc, SPI_CR, SPI_CR_SWRST);
+ /* "Software Reset must be Written Twice" erratum */
+ WR4(sc, SPI_CR, SPI_CR_SWRST);
+ WR4(sc, SPI_IDR, 0xffffffff);
+
+ WR4(sc, SPI_MR, (0xf << 24) | SPI_MR_MSTR | SPI_MR_MODFDIS |
+ CS_TO_MR(0));
+
+ /*
+ * For now, run the bus at the slowest speed possible as otherwise we
+ * may encounter data corruption on transmit as seen with ETHERNUT5
+ * and AT45DB321D even though both board and slave device can take
+ * more.
+ * This also serves as a work-around for the "NPCSx rises if no data
+ * data is to be transmitted" erratum. The ideal workaround for the
+ * latter is to take the chip select control away from the peripheral
+ * and manage it directly as a GPIO line. The easy solution is to
+ * slow down the bus so dramatically that it just never gets starved
+ * as may be seen when the OCHI controller is running and consuming
+ * memory and APB bandwidth.
+ * Also, currently we lack a way for lettting both the board and the
+ * slave devices take their maximum supported SPI clocks into account.
+ * Also, we hard-wire SPI mode to 3.
+ */
+ csr = SPI_CSR_CPOL | (4 << 16) | (0xff << 8);
+ WR4(sc, SPI_CSR0, csr);
+ WR4(sc, SPI_CSR1, csr);
+ WR4(sc, SPI_CSR2, csr);
+ WR4(sc, SPI_CSR3, csr);
+
+ WR4(sc, SPI_CR, SPI_CR_SPIEN);
+
+ WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS);
+ WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS);
+ WR4(sc, PDC_RNPR, 0);
+ WR4(sc, PDC_RNCR, 0);
+ WR4(sc, PDC_TNPR, 0);
+ WR4(sc, PDC_TNCR, 0);
+ WR4(sc, PDC_RPR, 0);
+ WR4(sc, PDC_RCR, 0);
+ WR4(sc, PDC_TPR, 0);
+ WR4(sc, PDC_TCR, 0);
+ RD4(sc, SPI_RDR);
+ RD4(sc, SPI_SR);
+
+ device_add_child(dev, "spibus", -1);
+ bus_generic_attach(dev);
+out:
+ if (err)
+ at91_spi_deactivate(dev);
+ return (err);
+}
+
+static int
+at91_spi_detach(device_t dev)
+{
+
+ return (EBUSY); /* XXX */
+}
+
+static int
+at91_spi_activate(device_t dev)
+{
+ struct at91_spi_softc *sc;
+ int err, i, rid;
+
+ sc = device_get_softc(dev);
+ err = ENOMEM;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ goto out;
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL)
+ goto out;
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, at91_spi_intr, sc, &sc->intrhand);
+ if (err != 0)
+ goto out;
+
+ err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 2048, 1,
+ 2048, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->dmatag);
+ if (err != 0)
+ goto out;
+
+ for (i = 0; i < 4; i++) {
+ err = bus_dmamap_create(sc->dmatag, 0, &sc->map[i]);
+ if (err != 0)
+ goto out;
+ }
+out:
+ if (err != 0)
+ at91_spi_deactivate(dev);
+ return (err);
+}
+
+static void
+at91_spi_deactivate(device_t dev)
+{
+ struct at91_spi_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ bus_generic_detach(dev);
+
+ for (i = 0; i < 4; i++)
+ if (sc->map[i])
+ bus_dmamap_destroy(sc->dmatag, sc->map[i]);
+
+ if (sc->dmatag)
+ bus_dma_tag_destroy(sc->dmatag);
+
+ if (sc->intrhand)
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ sc->intrhand = NULL;
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ sc->irq_res = NULL;
+
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = NULL;
+}
+
+static void
+at91_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs __unused,
+ int error)
+{
+
+ if (error != 0)
+ return;
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+static int
+at91_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
+{
+ struct at91_spi_softc *sc;
+ bus_addr_t addr;
+ int err, i, j, mode[4], cs;
+
+ KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
+ ("%s: TX/RX command sizes should be equal", __func__));
+ KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
+ ("%s: TX/RX data sizes should be equal", __func__));
+
+ /* get the proper chip select */
+ spibus_get_cs(child, &cs);
+
+ sc = device_get_softc(dev);
+ i = 0;
+
+ sx_xlock(&sc->xfer_mtx);
+
+ /*
+ * Disable transfers while we set things up.
+ */
+ WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS);
+
+ /*
+ * PSCDEC = 0 has a range of 0..3 for chip select. We
+ * don't support PSCDEC = 1 which has a range of 0..15.
+ */
+ if (cs < 0 || cs > 3) {
+ device_printf(dev,
+ "Invalid chip select %d requested by %s\n", cs,
+ device_get_nameunit(child));
+ err = EINVAL;
+ goto out;
+ }
+
+#ifdef SPI_CHIP_SELECT_HIGH_SUPPORT
+ /*
+ * The AT91RM9200 couldn't do CS high for CS 0. Other chips can, but we
+ * don't support that yet, or other spi modes.
+ */
+ if (at91_is_rm92() && cs == 0 &&
+ (cmd->flags & SPI_CHIP_SELECT_HIGH) != 0) {
+ device_printf(dev,
+ "Invalid chip select high requested by %s for cs 0.\n",
+ device_get_nameunit(child));
+ err = EINVAL;
+ goto out;
+ }
+#endif
+ err = (RD4(sc, SPI_MR) & ~0x000f0000) | CS_TO_MR(cs);
+ WR4(sc, SPI_MR, err);
+
+ /*
+ * Set up the TX side of the transfer.
+ */
+ if ((err = bus_dmamap_load(sc->dmatag, sc->map[i], cmd->tx_cmd,
+ cmd->tx_cmd_sz, at91_getaddr, &addr, 0)) != 0)
+ goto out;
+ WR4(sc, PDC_TPR, addr);
+ WR4(sc, PDC_TCR, cmd->tx_cmd_sz);
+ bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREWRITE);
+ mode[i++] = BUS_DMASYNC_POSTWRITE;
+ if (cmd->tx_data_sz > 0) {
+ if ((err = bus_dmamap_load(sc->dmatag, sc->map[i],
+ cmd->tx_data, cmd->tx_data_sz, at91_getaddr, &addr, 0)) !=
+ 0)
+ goto out;
+ WR4(sc, PDC_TNPR, addr);
+ WR4(sc, PDC_TNCR, cmd->tx_data_sz);
+ bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREWRITE);
+ mode[i++] = BUS_DMASYNC_POSTWRITE;
+ }
+
+ /*
+ * Set up the RX side of the transfer.
+ */
+ if ((err = bus_dmamap_load(sc->dmatag, sc->map[i], cmd->rx_cmd,
+ cmd->rx_cmd_sz, at91_getaddr, &addr, 0)) != 0)
+ goto out;
+ WR4(sc, PDC_RPR, addr);
+ WR4(sc, PDC_RCR, cmd->rx_cmd_sz);
+ bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREREAD);
+ mode[i++] = BUS_DMASYNC_POSTREAD;
+ if (cmd->rx_data_sz > 0) {
+ if ((err = bus_dmamap_load(sc->dmatag, sc->map[i],
+ cmd->rx_data, cmd->rx_data_sz, at91_getaddr, &addr, 0)) !=
+ 0)
+ goto out;
+ WR4(sc, PDC_RNPR, addr);
+ WR4(sc, PDC_RNCR, cmd->rx_data_sz);
+ bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREREAD);
+ mode[i++] = BUS_DMASYNC_POSTREAD;
+ }
+
+ /*
+ * Start the transfer, wait for it to complete.
+ */
+ sc->xfer_done = 0;
+ WR4(sc, SPI_IER, SPI_SR_RXBUFF);
+ WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN | PDC_PTCR_RXTEN);
+ do
+ err = tsleep(&sc->xfer_done, PCATCH | PZERO, "at91_spi", hz);
+ while (sc->xfer_done == 0 && err != EINTR);
+
+ /*
+ * Stop the transfer and clean things up.
+ */
+ WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS);
+ if (err == 0)
+ for (j = 0; j < i; j++)
+ bus_dmamap_sync(sc->dmatag, sc->map[j], mode[j]);
+out:
+ for (j = 0; j < i; j++)
+ bus_dmamap_unload(sc->dmatag, sc->map[j]);
+
+ sx_xunlock(&sc->xfer_mtx);
+
+ return (err);
+}
+
+static void
+at91_spi_intr(void *arg)
+{
+ struct at91_spi_softc *sc;
+ uint32_t sr;
+
+ sc = (struct at91_spi_softc*)arg;
+
+ sr = RD4(sc, SPI_SR) & RD4(sc, SPI_IMR);
+ if ((sr & SPI_SR_RXBUFF) != 0) {
+ sc->xfer_done = 1;
+ WR4(sc, SPI_IDR, SPI_SR_RXBUFF);
+ wakeup(&sc->xfer_done);
+ }
+ if ((sr & ~SPI_SR_RXBUFF) != 0) {
+ device_printf(sc->dev, "Unexpected ISR %#x\n", sr);
+ WR4(sc, SPI_IDR, sr & ~SPI_SR_RXBUFF);
+ }
+}
+
+static devclass_t at91_spi_devclass;
+
+static device_method_t at91_spi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, at91_spi_probe),
+ DEVMETHOD(device_attach, at91_spi_attach),
+ DEVMETHOD(device_detach, at91_spi_detach),
+
+ /* spibus interface */
+ DEVMETHOD(spibus_transfer, at91_spi_transfer),
+
+ DEVMETHOD_END
+};
+
+static driver_t at91_spi_driver = {
+ "spi",
+ at91_spi_methods,
+ sizeof(struct at91_spi_softc),
+};
+
+#ifdef FDT
+DRIVER_MODULE(at91_spi, simplebus, at91_spi_driver, at91_spi_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_spi, atmelarm, at91_spi_driver, at91_spi_devclass, NULL,
+ NULL);
+#endif
Property changes on: trunk/sys/arm/at91/at91_spi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_spireg.h
===================================================================
--- trunk/sys/arm/at91/at91_spireg.h (rev 0)
+++ trunk/sys/arm/at91/at91_spireg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_spireg.h 236495 2012-06-03 00:54:10Z marius $ */
+
+#ifndef ARM_AT91_AT91_SPIREG_H
+#define ARM_AT91_AT91_SPIREG_H
+
+#define SPI_CR 0x00 /* CR: Control Register */
+#define SPI_CR_SPIEN 0x1
+#define SPI_CR_SPIDIS 0x2
+#define SPI_CR_SWRST 0x8
+#define SPI_MR 0x04 /* MR: Mode Register */
+#define SPI_MR_MSTR 0x01
+#define SPI_MR_PS 0x02
+#define SPI_MR_PCSDEC 0x04
+#define SPI_MR_DIV32 0x08
+#define SPI_MR_MODFDIS 0x10
+#define SPI_MR_LLB 0x80
+#define SPI_MR_PSC_CS0 0xe0000
+#define SPI_MR_PSC_CS1 0xd0000
+#define SPI_MR_PSC_CS2 0xb0000
+#define SPI_MR_PSC_CS3 0x70000
+#define SPI_RDR 0x08 /* RDR: Receive Data Register */
+#define SPI_TDR 0x0c /* TDR: Transmit Data Register */
+#define SPI_SR 0x10 /* SR: Status Register */
+#define SPI_SR_RDRF 0x00001
+#define SPI_SR_TDRE 0x00002
+#define SPI_SR_MODF 0x00004
+#define SPI_SR_OVRES 0x00008
+#define SPI_SR_ENDRX 0x00010
+#define SPI_SR_ENDTX 0x00020
+#define SPI_SR_RXBUFF 0x00040
+#define SPI_SR_TXBUFE 0x00080
+#define SPI_SR_NSSR 0x00100
+#define SPI_SR_TXEMPTY 0x00200
+#define SPI_SR_SPIENS 0x10000
+#define SPI_IER 0x14 /* IER: Interrupt Enable Regsiter */
+#define SPI_IDR 0x18 /* IDR: Interrupt Disable Regsiter */
+#define SPI_IMR 0x1c /* IMR: Interrupt Mask Regsiter */
+#define SPI_CSR0 0x30 /* CS0: Chip Select 0 */
+#define SPI_CSR_CPOL 0x01
+#define SPI_CSR1 0x34 /* CS1: Chip Select 1 */
+#define SPI_CSR2 0x38 /* CS2: Chip Select 2 */
+#define SPI_CSR3 0x3c /* CS3: Chip Select 3 */
+
+#endif /* ARM_AT91_AT91_SPIREG_H */
Property changes on: trunk/sys/arm/at91/at91_spireg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_ssc.c
===================================================================
--- trunk/sys/arm/at91/at91_ssc.c (rev 0)
+++ trunk/sys/arm/at91/at91_ssc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,271 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_ssc.c 236989 2012-06-13 04:52:19Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+
+#include <arm/at91/at91_sscreg.h>
+
+struct at91_ssc_softc
+{
+ device_t dev; /* Myself */
+ void *intrhand; /* Interrupt handle */
+ struct resource *irq_res; /* IRQ resource */
+ struct resource *mem_res; /* Memory resource */
+ struct mtx sc_mtx; /* basically a perimeter lock */
+ struct cdev *cdev;
+ int flags;
+#define OPENED 1
+};
+
+static inline uint32_t
+RD4(struct at91_ssc_softc *sc, bus_size_t off)
+{
+ return bus_read_4(sc->mem_res, off);
+}
+
+static inline void
+WR4(struct at91_ssc_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->mem_res, off, val);
+}
+
+#define AT91_SSC_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define AT91_SSC_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define AT91_SSC_LOCK_INIT(_sc) \
+ mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->dev), \
+ "ssc", MTX_DEF)
+#define AT91_SSC_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx);
+#define AT91_SSC_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED);
+#define AT91_SSC_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED);
+#define CDEV2SOFTC(dev) ((dev)->si_drv1)
+
+static devclass_t at91_ssc_devclass;
+
+/* bus entry points */
+
+static int at91_ssc_probe(device_t dev);
+static int at91_ssc_attach(device_t dev);
+static int at91_ssc_detach(device_t dev);
+static void at91_ssc_intr(void *);
+
+/* helper routines */
+static int at91_ssc_activate(device_t dev);
+static void at91_ssc_deactivate(device_t dev);
+
+/* cdev routines */
+static d_open_t at91_ssc_open;
+static d_close_t at91_ssc_close;
+static d_read_t at91_ssc_read;
+static d_write_t at91_ssc_write;
+
+static struct cdevsw at91_ssc_cdevsw =
+{
+ .d_version = D_VERSION,
+ .d_open = at91_ssc_open,
+ .d_close = at91_ssc_close,
+ .d_read = at91_ssc_read,
+ .d_write = at91_ssc_write,
+};
+
+static int
+at91_ssc_probe(device_t dev)
+{
+ device_set_desc(dev, "SSC");
+ return (0);
+}
+
+static int
+at91_ssc_attach(device_t dev)
+{
+ struct at91_ssc_softc *sc = device_get_softc(dev);
+ int err;
+
+ sc->dev = dev;
+ err = at91_ssc_activate(dev);
+ if (err)
+ goto out;
+
+ AT91_SSC_LOCK_INIT(sc);
+
+ /*
+ * Activate the interrupt
+ */
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, at91_ssc_intr, sc, &sc->intrhand);
+ if (err) {
+ AT91_SSC_LOCK_DESTROY(sc);
+ goto out;
+ }
+ sc->cdev = make_dev(&at91_ssc_cdevsw, device_get_unit(dev), UID_ROOT,
+ GID_WHEEL, 0600, "ssc%d", device_get_unit(dev));
+ if (sc->cdev == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+ sc->cdev->si_drv1 = sc;
+
+ // Init for TSC needs
+ WR4(sc, SSC_CR, SSC_CR_SWRST);
+ WR4(sc, SSC_CMR, 0); // clock divider unused
+ WR4(sc, SSC_RCMR,
+ SSC_RCMR_CKS_RK | SSC_RCMR_CKO_NONE | SSC_RCMR_START_FALL_EDGE_RF);
+ WR4(sc, SSC_RFMR,
+ 0x1f | SSC_RFMR_MSFBF | SSC_RFMR_FSOS_NONE);
+ WR4(sc, SSC_TCMR,
+ SSC_TCMR_CKS_TK | SSC_TCMR_CKO_NONE | SSC_RCMR_START_CONT);
+ WR4(sc, SSC_TFMR,
+ 0x1f | SSC_TFMR_DATDEF | SSC_TFMR_MSFBF | SSC_TFMR_FSOS_NEG_PULSE);
+
+out:
+ if (err)
+ at91_ssc_deactivate(dev);
+ return (err);
+}
+
+static int
+at91_ssc_detach(device_t dev)
+{
+ return (EBUSY); /* XXX */
+}
+
+static int
+at91_ssc_activate(device_t dev)
+{
+ struct at91_ssc_softc *sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ goto errout;
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL)
+ goto errout;
+ return (0);
+errout:
+ at91_ssc_deactivate(dev);
+ return (ENOMEM);
+}
+
+static void
+at91_ssc_deactivate(device_t dev)
+{
+ struct at91_ssc_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->intrhand)
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ sc->intrhand = 0;
+ bus_generic_detach(sc->dev);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = 0;
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ sc->irq_res = 0;
+ return;
+}
+
+static void
+at91_ssc_intr(void *xsc)
+{
+ struct at91_ssc_softc *sc = xsc;
+ wakeup(sc);
+ return;
+}
+
+static int
+at91_ssc_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct at91_ssc_softc *sc;
+
+ sc = CDEV2SOFTC(dev);
+ AT91_SSC_LOCK(sc);
+ if (!(sc->flags & OPENED)) {
+ sc->flags |= OPENED;
+ }
+ AT91_SSC_UNLOCK(sc);
+ return (0);
+}
+
+static int
+at91_ssc_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
+{
+ struct at91_ssc_softc *sc;
+
+ sc = CDEV2SOFTC(dev);
+ AT91_SSC_LOCK(sc);
+ sc->flags &= ~OPENED;
+ AT91_SSC_UNLOCK(sc);
+ return (0);
+}
+
+static int
+at91_ssc_read(struct cdev *dev, struct uio *uio, int flag)
+{
+ return EIO;
+}
+
+static int
+at91_ssc_write(struct cdev *dev, struct uio *uio, int flag)
+{
+ return EIO;
+}
+
+static device_method_t at91_ssc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, at91_ssc_probe),
+ DEVMETHOD(device_attach, at91_ssc_attach),
+ DEVMETHOD(device_detach, at91_ssc_detach),
+
+ { 0, 0 }
+};
+
+static driver_t at91_ssc_driver = {
+ "at91_ssc",
+ at91_ssc_methods,
+ sizeof(struct at91_ssc_softc),
+};
+
+DRIVER_MODULE(at91_ssc, atmelarm, at91_ssc_driver, at91_ssc_devclass, 0, 0);
Property changes on: trunk/sys/arm/at91/at91_ssc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_sscreg.h
===================================================================
--- trunk/sys/arm/at91/at91_sscreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_sscreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,151 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_sscreg.h 185265 2008-11-25 00:13:26Z imp $ */
+
+#ifndef ARM_AT91_AT91_SSCREG_H
+#define ARM_AT91_AT91_SSCREG_H
+
+/* Registers */
+#define SSC_CR 0x00 /* Control Register */
+#define SSC_CMR 0x04 /* Clock Mode Register */
+ /* 0x08 Reserved */
+ /* 0x0c Reserved */
+#define SSC_RCMR 0x10 /* Receive Clock Mode Register */
+#define SSC_RFMR 0x14 /* Receive Frame Mode Register */
+#define SSC_TCMR 0x18 /* Transmit Clock Mode Register */
+#define SSC_TFMR 0x1c /* Transmit Frame Mode register */
+#define SSC_RHR 0x20 /* Receive Holding Register */
+#define SSC_THR 0x24 /* Transmit Holding Register */
+ /* 0x28 Reserved */
+ /* 0x2c Reserved */
+#define SSC_RSHR 0x30 /* Receive Sync Holding Register */
+#define SSC_TSHR 0x34 /* Transmit Sync Holding Register */
+ /* 0x38 Reserved */
+ /* 0x3c Reserved */
+#define SSC_SR 0x40 /* Status Register */
+#define SSC_IER 0x44 /* Interrupt Enable Register */
+#define SSC_IDR 0x48 /* Interrupt Disable Register */
+#define SSC_IMR 0x4c /* Interrupt Mask Register */
+/* And PDC registers */
+
+/* SSC_CR */
+#define SSC_CR_RXEN (1u << 0) /* RXEN: Receive Enable */
+#define SSC_CR_RXDIS (1u << 1) /* RXDIS: Receive Disable */
+#define SSC_CR_TXEN (1u << 8) /* TXEN: Transmit Enable */
+#define SSC_CR_TXDIS (1u << 9) /* TXDIS: Transmit Disable */
+#define SSC_CR_SWRST (1u << 15) /* SWRST: Software Reset */
+
+/* SSC_CMR */
+#define SSC_CMR_DIV 0xfffu /* DIV: Clock Divider mask */
+
+/* SSC_RCMR */
+#define SSC_RCMR_PERIOD (0xffu << 24) /* PERIOD: Receive Period Divider sel*/
+#define SSC_RCMR_STTDLY (0xffu << 16) /* STTDLY: Receive Start Delay */
+#define SSC_RCMR_START (0xfu << 8) /* START: Receive Start Sel */
+#define SSC_RCMR_START_CONT (0u << 8)
+#define SSC_RCMR_START_TX_START (1u << 8)
+#define SSC_RCMR_START_LOW_RF (2u << 8)
+#define SSC_RCMR_START_HIGH_RF (3u << 8)
+#define SSC_RCMR_START_FALL_EDGE_RF (4u << 8)
+#define SSC_RCMR_START_RISE_EDGE_RF (5u << 8)
+#define SSC_RCMR_START_LEVEL_CHANGE_RF (6u << 8)
+#define SSC_RCMR_START_ANY_EDGE_RF (7u << 8)
+#define SSC_RCMR_CKI (1u << 5) /* CKI: Receive Clock Inversion */
+#define SSC_RCMR_CKO (7u << 2) /* CKO: Receive Clock Output Mode Sel*/
+#define SSC_RCMR_CKO_NONE (0u << 2)
+#define SSC_RCMR_CKO_CONTINUOUS (1u << 2)
+#define SSC_RCMR_CKS (3u) /* CKS: Receive Clock Selection */
+#define SSC_RCMR_CKS_DIVIDED (0)
+#define SSC_RCMR_CKS_TK_CLOCK (1)
+#define SSC_RCMR_CKS_RK (2)
+
+/* SSC_RFMR */
+#define SSC_RFMR_FSEDGE (1u << 24) /* FSEDGE: Frame Sync Edge Detection */
+#define SSC_RFMR_FSOS (7u << 20) /* FSOS: Receive frame Sync Out sel */
+#define SSC_RFMR_FSOS_NONE (0u << 20)
+#define SSC_RFMR_FSOS_NEG_PULSE (1u << 20)
+#define SSC_RFMR_FSOS_POS_PULSE (2u << 20)
+#define SSC_RFMR_FSOS_LOW (3u << 20)
+#define SSC_RFMR_FSOS_HIGH (4u << 20)
+#define SSC_RFMR_FSOS_TOGGLE (5u << 20)
+#define SSC_RFMR_FSLEN (0xfu << 16) /* FSLEN: Receive Frame Sync Length */
+#define SSC_RFMR_DATNB (0xfu << 8) /* DATNB: Data Number per Frame */
+#define SSC_RFMR_MSFBF (1u << 7) /* MSBF: Most Significant Bit First */
+#define SSC_RFMR_LOOP (1u << 5) /* LOOP: Loop Mode */
+#define SSC_RFMR_DATLEN (0x1fu << 0) /* DATLEN: Data Length */
+
+/* SSC_TCMR */
+#define SSC_TCMR_PERIOD (0xffu << 24) /* PERIOD: Receive Period Divider sel*/
+#define SSC_TCMR_STTDLY (0xffu << 16) /* STTDLY: Receive Start Delay */
+#define SSC_TCMR_START (0xfu << 8) /* START: Receive Start Sel */
+#define SSC_TCMR_START_CONT (0u << 8)
+#define SSC_TCMR_START_RX_START (1u << 8)
+#define SSC_TCMR_START_LOW_RF (2u << 8)
+#define SSC_TCMR_START_HIGH_RF (3u << 8)
+#define SSC_TCMR_START_FALL_EDGE_RF (4u << 8)
+#define SSC_TCMR_START_RISE_EDGE_RF (5u << 8)
+#define SSC_TCMR_START_LEVEL_CHANGE_RF (6u << 8)
+#define SSC_TCMR_START_ANY_EDGE_RF (7u << 8)
+#define SSC_TCMR_CKI (1u << 5) /* CKI: Receive Clock Inversion */
+#define SSC_TCMR_CKO (7u << 2) /* CKO: Receive Clock Output Mode Sel*/
+#define SSC_TCMR_CKO_NONE (0u << 2)
+#define SSC_TCMR_CKO_CONTINUOUS (1u << 2)
+#define SSC_TCMR_CKS (3u) /* CKS: Receive Clock Selection */
+#define SSC_TCMR_CKS_DIVIDED (0)
+#define SSC_TCMR_CKS_RK_CLOCK (1)
+#define SSC_TCMR_CKS_TK (2)
+
+/* SSC_TFMR */
+#define SSC_TFMR_FSEDGE (1u << 24) /* FSEDGE: Frame Sync Edge Detection */
+#define SSC_TFMR_FSOS (7u << 20) /* FSOS: Receive frame Sync Out sel */
+#define SSC_TFMR_FSOS_NONE (0u << 20)
+#define SSC_TFMR_FSOS_NEG_PULSE (1u << 20)
+#define SSC_TFMR_FSOS_POS_PULSE (2u << 20)
+#define SSC_TFMR_FSOS_LOW (3u << 20)
+#define SSC_TFMR_FSOS_HIGH (4u << 20)
+#define SSC_TFMR_FSOS_TOGGLE (5u << 20)
+#define SSC_TFMR_FSLEN (0xfu << 16) /* FSLEN: Receive Frame Sync Length */
+#define SSC_TFMR_DATNB (0xfu << 8) /* DATNB: Data Number per Frame */
+#define SSC_TFMR_MSFBF (1u << 7) /* MSBF: Most Significant Bit First */
+#define SSC_TFMR_DATDEF (1u << 5) /* DATDEF: Data Default Value */
+#define SSC_TFMR_DATLEN (0x1fu << 0) /* DATLEN: Data Length */
+
+/* SSC_SR */
+#define SSC_SR_TXRDY (1u << 0)
+#define SSC_SR_TXEMPTY (1u << 1)
+#define SSC_SR_ENDTX (1u << 2)
+#define SSC_SR_TXBUFE (1u << 3)
+#define SSC_SR_RXRDY (1u << 4)
+#define SSC_SR_OVRUN (1u << 5)
+#define SSC_SR_ENDRX (1u << 6)
+#define SSC_SR_RXBUFF (1u << 7)
+#define SSC_SR_TXSYN (1u << 10)
+#define SSC_SR_RSSYN (1u << 11)
+#define SSC_SR_TXEN (1u << 16)
+#define SSC_SR_RXEN (1u << 17)
+
+#endif /* ARM_AT91_AT91_SSCREG_H */
Property changes on: trunk/sys/arm/at91/at91_sscreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_st.c
===================================================================
--- trunk/sys/arm/at91/at91_st.c (rev 0)
+++ trunk/sys/arm/at91/at91_st.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,314 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_st.c 238376 2012-07-11 20:17:14Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_streg.h>
+#include <arm/at91/at91rm92reg.h>
+
+static struct at91_st_softc {
+ struct resource * sc_irq_res;
+ struct resource * sc_mem_res;
+ void * sc_intrhand;
+ eventhandler_tag sc_wet; /* watchdog event handler tag */
+} *timer_softc;
+
+static inline uint32_t
+RD4(bus_size_t off)
+{
+
+ if (timer_softc == NULL) {
+ uint32_t *p = (uint32_t *)(AT91_BASE + AT91RM92_ST_BASE + off);
+
+ return *p;
+ }
+
+ return (bus_read_4(timer_softc->sc_mem_res, off));
+}
+
+static inline void
+WR4(bus_size_t off, uint32_t val)
+{
+
+ if (timer_softc == NULL) {
+ uint32_t *p = (uint32_t *)(AT91_BASE + AT91RM92_ST_BASE + off);
+
+ *p = val;
+ }
+ else
+ bus_write_4(timer_softc->sc_mem_res, off, val);
+}
+
+static void at91_st_watchdog(void *, u_int, int *);
+static void at91_st_initclocks(device_t , struct at91_st_softc *);
+
+static inline int
+st_crtr(void)
+{
+ int cur1, cur2;
+ do {
+ cur1 = RD4(ST_CRTR);
+ cur2 = RD4(ST_CRTR);
+ } while (cur1 != cur2);
+ return (cur1);
+}
+
+static unsigned at91_st_get_timecount(struct timecounter *tc);
+
+static struct timecounter at91_st_timecounter = {
+ at91_st_get_timecount, /* get_timecount */
+ NULL, /* no poll_pps */
+ 0xfffffu, /* counter_mask */
+ 32768, /* frequency */
+ "AT91RM9200 timer", /* name */
+ 1000 /* quality */
+};
+
+static int
+clock_intr(void *arg)
+{
+ struct trapframe *fp = arg;
+
+ /* The interrupt is shared, so we have to make sure it's for us. */
+ if (RD4(ST_SR) & ST_SR_PITS) {
+ hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp));
+ return (FILTER_HANDLED);
+ }
+ return (FILTER_STRAY);
+}
+
+void
+at91_st_delay(int n)
+{
+ uint32_t start, end, cur;
+
+ start = st_crtr();
+ n = (n * 1000) / 32768;
+ if (n <= 0)
+ n = 1;
+ end = (start + n) & ST_CRTR_MASK;
+ cur = start;
+ if (start > end) {
+ while (cur >= start || cur < end)
+ cur = st_crtr();
+ } else {
+ while (cur < end)
+ cur = st_crtr();
+ }
+}
+
+void
+at91_st_cpu_reset(void)
+{
+ /*
+ * Reset the CPU by programmig the watchdog timer to reset the
+ * CPU after 128 'slow' clocks, or about ~4ms. Loop until
+ * the reset happens for safety.
+ */
+ WR4(ST_WDMR, ST_WDMR_RSTEN | 2);
+ WR4(ST_CR, ST_CR_WDRST);
+ while (1)
+ continue;
+}
+
+static int
+at91_st_probe(device_t dev)
+{
+
+ device_set_desc(dev, "ST");
+ return (0);
+}
+
+static void
+at91_st_deactivate(device_t dev)
+{
+ struct at91_st_softc *sc = timer_softc;
+
+ if (sc->sc_intrhand)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
+ sc->sc_intrhand = NULL;
+
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->sc_mem_res), sc->sc_mem_res);
+ sc->sc_mem_res = NULL;
+}
+
+static int
+at91_st_activate(device_t dev)
+{
+ int rid;
+ int err;
+ struct at91_st_softc *sc = timer_softc;
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ err = ENOMEM;
+ if (sc->sc_mem_res == NULL)
+ goto out;
+ /* Disable all interrupts */
+ WR4(ST_IDR, 0xffffffff);
+
+ /* The system timer shares the system irq (1) */
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->sc_irq_res == NULL) {
+ printf("Unable to allocate irq for the system timer");
+ goto out;
+ }
+ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_CLK, clock_intr,
+ NULL, NULL, &sc->sc_intrhand);
+out:
+ if (err != 0)
+ at91_st_deactivate(dev);
+ return (err);
+}
+
+static int
+at91_st_attach(device_t dev)
+{
+ int err;
+
+ timer_softc = device_get_softc(dev);
+ err = at91_st_activate(dev);
+ if (err)
+ return err;
+
+ timer_softc->sc_wet = EVENTHANDLER_REGISTER(watchdog_list,
+ at91_st_watchdog, dev, 0);
+
+ device_printf(dev,
+ "watchdog registered, timeout intervall max. 64 sec\n");
+
+ at91_st_initclocks(dev, timer_softc);
+ return (0);
+}
+
+static device_method_t at91_st_methods[] = {
+ DEVMETHOD(device_probe, at91_st_probe),
+ DEVMETHOD(device_attach, at91_st_attach),
+ {0, 0},
+};
+
+static driver_t at91_st_driver = {
+ "at91_st",
+ at91_st_methods,
+ sizeof(struct at91_st_softc),
+};
+static devclass_t at91_st_devclass;
+
+DRIVER_MODULE(at91_st, atmelarm, at91_st_driver, at91_st_devclass, 0, 0);
+
+static unsigned
+at91_st_get_timecount(struct timecounter *tc)
+{
+ return (st_crtr());
+}
+
+/*
+ * t below is in a weird unit. The watchdog is set to 2^t
+ * nanoseconds. Since our watchdog timer can't really do that too
+ * well, we approximate it by assuming that the timeout interval for
+ * the lsb is 2^22 ns, which is 4.194ms. This is an overestimation of
+ * the actual time (3.906ms), but close enough for watchdogging.
+ * These approximations, though a violation of the spec, improve the
+ * performance of the application which typically specifies things as
+ * WD_TO_32SEC. In that last case, we'd wait 32s before the wdog
+ * reset. The spec says we should wait closer to 34s, but given how
+ * it is likely to be used, and the extremely coarse nature time
+ * interval, I think this is the best solution.
+ */
+static void
+at91_st_watchdog(void *argp, u_int cmd, int *error)
+{
+ uint32_t wdog;
+ int t;
+
+ t = cmd & WD_INTERVAL;
+ if (t >= 22 && t <= 37) {
+ wdog = (1 << (t - 22)) | ST_WDMR_RSTEN;
+ *error = 0;
+ } else {
+ wdog = 0;
+ }
+ WR4(ST_WDMR, wdog);
+ WR4(ST_CR, ST_CR_WDRST);
+}
+
+static void
+at91_st_initclocks(device_t dev, struct at91_st_softc *sc)
+{
+ int rel_value;
+
+ /*
+ * Real time counter increments every clock cycle, need to set before
+ * initializing clocks so that DELAY works.
+ */
+ WR4(ST_RTMR, 1);
+ /* disable watchdog timer */
+ WR4(ST_WDMR, 0);
+
+ rel_value = 32768 / hz;
+ if (rel_value < 1)
+ rel_value = 1;
+ if (32768 % hz) {
+ device_printf(dev, "Cannot get %d Hz clock; using %dHz\n", hz,
+ 32768 / rel_value);
+ hz = 32768 / rel_value;
+ tick = 1000000 / hz;
+ }
+ WR4(ST_PIMR, rel_value);
+
+ /* Enable PITS interrupts. */
+ WR4(ST_IER, ST_SR_PITS);
+ tc_init(&at91_st_timecounter);
+}
Property changes on: trunk/sys/arm/at91/at91_st.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_streg.h
===================================================================
--- trunk/sys/arm/at91/at91_streg.h (rev 0)
+++ trunk/sys/arm/at91/at91_streg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,62 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_streg.h 238376 2012-07-11 20:17:14Z imp $ */
+
+#ifndef ARM_AT91_AT91STREG_H
+#define ARM_AT91_AT91STREG_H
+
+#define ST_CR 0x00 /* Control register */
+#define ST_PIMR 0x04 /* Period interval mode register */
+#define ST_WDMR 0x08 /* Watchdog mode register */
+#define ST_RTMR 0x0c /* Real-time mode register */
+#define ST_SR 0x10 /* Status register */
+#define ST_IER 0x14 /* Interrupt enable register */
+#define ST_IDR 0x18 /* Interrupt disable register */
+#define ST_IMR 0x1c /* Interrupt mask register */
+#define ST_RTAR 0x20 /* Real-time alarm register */
+#define ST_CRTR 0x24 /* Current real-time register */
+
+/* ST_CR */
+#define ST_CR_WDRST (1U << 0) /* WDRST: Watchdog Timer Restart */
+
+/* ST_WDMR */
+#define ST_WDMR_EXTEN (1U << 17) /* EXTEN: External Signal Assert Enable */
+#define ST_WDMR_RSTEN (1U << 16) /* RSTEN: Reset Enable */
+
+/* ST_SR, ST_IER, ST_IDR, ST_IMR */
+#define ST_SR_PITS (1U << 0) /* PITS: Period Interval Timer Status */
+#define ST_SR_WDOVF (1U << 1) /* WDOVF: Watchdog Overflow */
+#define ST_SR_RTTINC (1U << 2) /* RTTINC: Real-time Timer Increment */
+#define ST_SR_ALMS (1U << 3) /* ALMS: Alarm Status */
+
+/* ST_CRTR */
+#define ST_CRTR_MASK 0xfffff /* 20-bit counter */
+
+void at91_st_delay(int n);
+void at91_st_cpu_reset(void);
+
+#endif /* ARM_AT91_AT91STREG_H */
Property changes on: trunk/sys/arm/at91/at91_streg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_tcb.c
===================================================================
--- trunk/sys/arm/at91/at91_tcb.c (rev 0)
+++ trunk/sys/arm/at91/at91_tcb.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,106 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_tcb.c 266217 2014-05-16 12:43:45Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_aicreg.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+struct tcb_softc {
+ struct resource *mem_res; /* Memory resource */
+ device_t sc_dev;
+};
+
+static int
+at91_tcb_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-tcb"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "TCB");
+ return (0);
+}
+
+static int
+at91_tcb_attach(device_t dev)
+{
+ int rid, err = 0;
+ struct tcb_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+
+ if (sc->mem_res == NULL)
+ panic("couldn't allocate register resources");
+
+ return (err);
+}
+
+static device_method_t at91_tcb_methods[] = {
+ DEVMETHOD(device_probe, at91_tcb_probe),
+ DEVMETHOD(device_attach, at91_tcb_attach),
+ DEVMETHOD_END
+};
+
+static driver_t at91_tcb_driver = {
+ "at91_tcb",
+ at91_tcb_methods,
+ sizeof(struct tcb_softc),
+};
+
+static devclass_t at91_tcb_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_tcb, simplebus, at91_tcb_driver, at91_tcb_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_tcb, atmelarm, at91_tcb_driver, at91_tcb_devclass, NULL,
+ NULL);
+#endif
Property changes on: trunk/sys/arm/at91/at91_tcb.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_twi.c
===================================================================
--- trunk/sys/arm/at91/at91_twi.c (rev 0)
+++ trunk/sys/arm/at91/at91_twi.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,430 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_twi.c 266196 2014-05-15 21:21:47Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+
+#include <arm/at91/at91_twireg.h>
+#include <arm/at91/at91var.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include "iicbus_if.h"
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#define TWI_SLOW_CLOCK 1500
+#define TWI_FAST_CLOCK 45000
+#define TWI_FASTEST_CLOCK 90000
+
+struct at91_twi_softc
+{
+ device_t dev; /* Myself */
+ void *intrhand; /* Interrupt handle */
+ struct resource *irq_res; /* IRQ resource */
+ struct resource *mem_res; /* Memory resource */
+ struct mtx sc_mtx; /* basically a perimeter lock */
+ volatile uint32_t flags;
+ uint32_t cwgr;
+ int sc_started;
+ int twi_addr;
+ device_t iicbus;
+};
+
+static inline uint32_t
+RD4(struct at91_twi_softc *sc, bus_size_t off)
+{
+
+ return bus_read_4(sc->mem_res, off);
+}
+
+static inline void
+WR4(struct at91_twi_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+#define AT91_TWI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define AT91_TWI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define AT91_TWI_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+ "twi", MTX_DEF)
+#define AT91_TWI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define AT91_TWI_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define AT91_TWI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+#define TWI_DEF_CLK 100000
+
+static devclass_t at91_twi_devclass;
+
+/* bus entry points */
+
+static int at91_twi_probe(device_t dev);
+static int at91_twi_attach(device_t dev);
+static int at91_twi_detach(device_t dev);
+static void at91_twi_intr(void *);
+
+/* helper routines */
+static int at91_twi_activate(device_t dev);
+static void at91_twi_deactivate(device_t dev);
+
+static int
+at91_twi_probe(device_t dev)
+{
+#ifdef FDT
+ /* XXXX need a whole list, since there's at least 4 different ones */
+ if (!ofw_bus_is_compatible(dev, "atmel,at91sam9g20-i2c"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "TWI");
+ return (0);
+}
+
+static int
+at91_twi_attach(device_t dev)
+{
+ struct at91_twi_softc *sc = device_get_softc(dev);
+ int err;
+
+ sc->dev = dev;
+ err = at91_twi_activate(dev);
+ if (err)
+ goto out;
+
+ AT91_TWI_LOCK_INIT(sc);
+
+#ifdef FDT
+ /*
+ * Disable devices need to hold their resources, so return now and not attach
+ * the iicbus, setup interrupt handlers, etc.
+ */
+ if (!ofw_bus_status_okay(dev))
+ return 0;
+#endif
+
+ /*
+ * Activate the interrupt
+ */
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, at91_twi_intr, sc, &sc->intrhand);
+ if (err) {
+ AT91_TWI_LOCK_DESTROY(sc);
+ goto out;
+ }
+ sc->cwgr = TWI_CWGR_CKDIV(8 * at91_master_clock / TWI_FASTEST_CLOCK) |
+ TWI_CWGR_CHDIV(TWI_CWGR_DIV(TWI_DEF_CLK)) |
+ TWI_CWGR_CLDIV(TWI_CWGR_DIV(TWI_DEF_CLK));
+ WR4(sc, TWI_CR, TWI_CR_SWRST);
+ WR4(sc, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS);
+ WR4(sc, TWI_CWGR, sc->cwgr);
+
+ if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL)
+ device_printf(dev, "could not allocate iicbus instance\n");
+ /* probe and attach the iicbus */
+ bus_generic_attach(dev);
+out:
+ if (err)
+ at91_twi_deactivate(dev);
+ return (err);
+}
+
+static int
+at91_twi_detach(device_t dev)
+{
+ struct at91_twi_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ at91_twi_deactivate(dev);
+ if (sc->iicbus && (rv = device_delete_child(dev, sc->iicbus)) != 0)
+ return (rv);
+
+ AT91_TWI_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static int
+at91_twi_activate(device_t dev)
+{
+ struct at91_twi_softc *sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ goto errout;
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL)
+ goto errout;
+ return (0);
+errout:
+ at91_twi_deactivate(dev);
+ return (ENOMEM);
+}
+
+static void
+at91_twi_deactivate(device_t dev)
+{
+ struct at91_twi_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->intrhand)
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ sc->intrhand = 0;
+ bus_generic_detach(sc->dev);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = 0;
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ sc->irq_res = 0;
+ return;
+}
+
+static void
+at91_twi_intr(void *xsc)
+{
+ struct at91_twi_softc *sc = xsc;
+ uint32_t status;
+
+ status = RD4(sc, TWI_SR);
+ if (status == 0)
+ return;
+ AT91_TWI_LOCK(sc);
+ sc->flags |= status & (TWI_SR_OVRE | TWI_SR_UNRE | TWI_SR_NACK);
+ if (status & TWI_SR_RXRDY)
+ sc->flags |= TWI_SR_RXRDY;
+ if (status & TWI_SR_TXRDY)
+ sc->flags |= TWI_SR_TXRDY;
+ if (status & TWI_SR_TXCOMP)
+ sc->flags |= TWI_SR_TXCOMP;
+ WR4(sc, TWI_IDR, status);
+ wakeup(sc);
+ AT91_TWI_UNLOCK(sc);
+ return;
+}
+
+static int
+at91_twi_wait(struct at91_twi_softc *sc, uint32_t bit)
+{
+ int err = 0;
+ int counter = 100000;
+ uint32_t sr;
+
+ AT91_TWI_ASSERT_LOCKED(sc);
+ while (!((sr = RD4(sc, TWI_SR)) & bit) && counter-- > 0 &&
+ !(sr & TWI_SR_NACK))
+ continue;
+ if (counter <= 0)
+ err = EBUSY;
+ else if (sr & TWI_SR_NACK)
+ err = ENXIO; // iic nack convention
+ return (err);
+}
+
+static int
+at91_twi_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+ struct at91_twi_softc *sc;
+ int clk;
+
+ sc = device_get_softc(dev);
+ AT91_TWI_LOCK(sc);
+ if (oldaddr)
+ *oldaddr = sc->twi_addr;
+ sc->twi_addr = addr;
+
+ /*
+ * speeds are for 1.5kb/s, 45kb/s and 90kb/s.
+ */
+ switch (speed) {
+ case IIC_SLOW:
+ clk = TWI_SLOW_CLOCK;
+ break;
+
+ case IIC_FAST:
+ clk = TWI_FAST_CLOCK;
+ break;
+
+ case IIC_UNKNOWN:
+ case IIC_FASTEST:
+ default:
+ clk = TWI_FASTEST_CLOCK;
+ break;
+ }
+ sc->cwgr = TWI_CWGR_CKDIV(1) | TWI_CWGR_CHDIV(TWI_CWGR_DIV(clk)) |
+ TWI_CWGR_CLDIV(TWI_CWGR_DIV(clk));
+ WR4(sc, TWI_CR, TWI_CR_SWRST);
+ WR4(sc, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS);
+ WR4(sc, TWI_CWGR, sc->cwgr);
+ AT91_TWI_UNLOCK(sc);
+
+ return 0;
+}
+
+static int
+at91_twi_callback(device_t dev, int index, caddr_t data)
+{
+ int error = 0;
+
+ switch (index) {
+ case IIC_REQUEST_BUS:
+ break;
+
+ case IIC_RELEASE_BUS:
+ break;
+
+ default:
+ error = EINVAL;
+ }
+
+ return (error);
+}
+
+static int
+at91_twi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+ struct at91_twi_softc *sc;
+ int i, len, err;
+ uint32_t rdwr;
+ uint8_t *buf;
+ uint32_t sr;
+
+ sc = device_get_softc(dev);
+ err = 0;
+ AT91_TWI_LOCK(sc);
+ for (i = 0; i < nmsgs; i++) {
+ /*
+ * The linux atmel driver doesn't use the internal device
+ * address feature of twi. A separate i2c message needs to
+ * be written to use this.
+ * See http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html
+ * for details. Upon reflection, we could use this as an
+ * optimization, but it is unclear the code bloat will
+ * result in faster/better operations.
+ */
+ rdwr = (msgs[i].flags & IIC_M_RD) ? TWI_MMR_MREAD : 0;
+ WR4(sc, TWI_MMR, TWI_MMR_DADR(msgs[i].slave) | rdwr);
+ len = msgs[i].len;
+ buf = msgs[i].buf;
+ /* zero byte transfers aren't allowed */
+ if (len == 0 || buf == NULL) {
+ err = EINVAL;
+ goto out;
+ }
+ if (len == 1 && msgs[i].flags & IIC_M_RD)
+ WR4(sc, TWI_CR, TWI_CR_START | TWI_CR_STOP);
+ else
+ WR4(sc, TWI_CR, TWI_CR_START);
+ if (msgs[i].flags & IIC_M_RD) {
+ sr = RD4(sc, TWI_SR);
+ while (!(sr & TWI_SR_TXCOMP)) {
+ if ((sr = RD4(sc, TWI_SR)) & TWI_SR_RXRDY) {
+ len--;
+ *buf++ = RD4(sc, TWI_RHR) & 0xff;
+ if (len == 1)
+ WR4(sc, TWI_CR, TWI_CR_STOP);
+ }
+ }
+ if (len > 0 || (sr & TWI_SR_NACK)) {
+ err = ENXIO; // iic nack convention
+ goto out;
+ }
+ } else {
+ while (len--) {
+ if ((err = at91_twi_wait(sc, TWI_SR_TXRDY)))
+ goto out;
+ WR4(sc, TWI_THR, *buf++);
+ }
+ WR4(sc, TWI_CR, TWI_CR_STOP);
+ }
+ if ((err = at91_twi_wait(sc, TWI_SR_TXCOMP)))
+ break;
+ }
+out:
+ if (err) {
+ WR4(sc, TWI_CR, TWI_CR_SWRST);
+ WR4(sc, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS);
+ WR4(sc, TWI_CWGR, sc->cwgr);
+ }
+ AT91_TWI_UNLOCK(sc);
+ return (err);
+}
+
+static device_method_t at91_twi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, at91_twi_probe),
+ DEVMETHOD(device_attach, at91_twi_attach),
+ DEVMETHOD(device_detach, at91_twi_detach),
+
+ /* iicbus interface */
+ DEVMETHOD(iicbus_callback, at91_twi_callback),
+ DEVMETHOD(iicbus_reset, at91_twi_rst_card),
+ DEVMETHOD(iicbus_transfer, at91_twi_transfer),
+ DEVMETHOD_END
+};
+
+static driver_t at91_twi_driver = {
+ "at91_twi",
+ at91_twi_methods,
+ sizeof(struct at91_twi_softc),
+};
+
+#ifdef FDT
+DRIVER_MODULE(at91_twi, simplebus, at91_twi_driver, at91_twi_devclass, NULL,
+ NULL);
+#else
+DRIVER_MODULE(at91_twi, atmelarm, at91_twi_driver, at91_twi_devclass, NULL,
+ NULL);
+#endif
+DRIVER_MODULE(iicbus, at91_twi, iicbus_driver, iicbus_devclass, NULL, NULL);
+MODULE_DEPEND(at91_twi, iicbus, 1, 1, 1);
Property changes on: trunk/sys/arm/at91/at91_twi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_twiio.h
===================================================================
--- trunk/sys/arm/at91/at91_twiio.h (rev 0)
+++ trunk/sys/arm/at91/at91_twiio.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,63 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/at91/at91_twiio.h 185265 2008-11-25 00:13:26Z imp $
+ */
+
+#ifndef _ARM_AT91_AT91_TWIIO_H
+#define _ARM_AT91_AT91_TWIIO_H
+
+#include <sys/ioccom.h>
+
+struct at91_twi_io
+{
+ int dadr; /* Device address */
+ int type; /* read/write */
+#define TWI_IO_READ_MASTER 1
+#define TWI_IO_WRITE_MASTER 2
+ int iadrsz; /* Internal addr size */
+ uint32_t iadr; /* Interbak addr */
+ size_t xfer_len; /* Size to transfer */
+ caddr_t xfer_buf; /* buffer for xfer */
+};
+
+struct at91_twi_clock
+{
+ int ckdiv; /* Clock divider */
+ int high_rate; /* rate of clock high period */
+ int low_rate; /* rate of clock low period */
+};
+
+/** TWIIOCXFER: Do a two-wire transfer
+ */
+#define TWIIOCXFER _IOW('x', 1, struct at91_twi_io)
+
+/** TWIIOCSETCLOCK: Sets the clocking parameters for this operation.
+ */
+#define TWIIOCSETCLOCK _IOW('x', 2, struct at91_twi_clock)
+
+#endif /* !_ARM_AT91_AT91_TWIIO_H */
+
+
Property changes on: trunk/sys/arm/at91/at91_twiio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_twireg.h
===================================================================
--- trunk/sys/arm/at91/at91_twireg.h (rev 0)
+++ trunk/sys/arm/at91/at91_twireg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,87 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_twireg.h 234291 2012-04-14 17:09:38Z marius $ */
+
+#ifndef ARM_AT91_AT91_TWIREG_H
+#define ARM_AT91_AT91_TWIREG_H
+
+#define TWI_CR 0x00 /* TWI Control Register */
+#define TWI_MMR 0x04 /* TWI Master Mode Register */
+#define TWI_SMR 0x08 /* TWI Master Mode Register */
+#define TWI_IADR 0x0c /* TWI Internal Address Register */
+#define TWI_CWGR 0x10 /* TWI Clock Waveform Generator Reg */
+ /* 0x14 reserved */
+ /* 0x18 reserved */
+ /* 0x1c reserved */
+#define TWI_SR 0x20 /* TWI Status Register */
+#define TWI_IER 0x24 /* TWI Interrupt Enable Register */
+#define TWI_IDR 0x28 /* TWI Interrupt Disable Register */
+#define TWI_IMR 0x2c /* TWI Interrupt Mask Register */
+#define TWI_RHR 0x30 /* TWI Receiver Holding Register */
+#define TWI_THR 0x34 /* TWI Transmit Holding Register */
+
+/* TWI_CR */
+#define TWI_CR_START (1U << 0) /* Send a start */
+#define TWI_CR_STOP (1U << 1) /* Send a stop */
+#define TWI_CR_MSEN (1U << 2) /* Master Transfer Enable */
+#define TWI_CR_MSDIS (1U << 3) /* Master Transfer Disable */
+#define TWI_CR_SVEN (1U << 4) /* Slave Transfer Enable */
+#define TWI_CR_SVDIS (1U << 5) /* Slave Transfer Disable */
+#define TWI_CR_SWRST (1U << 7) /* Software Reset */
+
+/* TWI_MMR */
+/* TWI_SMR */
+#define TWI_MMR_IADRSZ(n) ((n) << 8) /* Set size of transfer */
+#define TWI_MMR_MWRITE 0U /* Master Read Direction */
+#define TWI_MMR_MREAD (1U << 12) /* Master Read Direction */
+#define TWI_MMR_DADR(n) ((n) << 15) /* Device Address */
+
+/* TWI_CWGR */
+#define TWI_CWGR_CKDIV(x) ((x) << 16) /* Clock Divider */
+#define TWI_CWGR_CHDIV(x) ((x) << 8) /* Clock High Divider */
+#define TWI_CWGR_CLDIV(x) ((x) << 0) /* Clock Low Divider */
+#define TWI_CWGR_DIV(rate) \
+ (at91_is_sam9() || at91_is_sam9xe() ? \
+ ((at91_master_clock / (4 * (rate))) - 3) : \
+ ((at91_master_clock / (4 * (rate))) - 2))
+
+/* TWI_SR */
+/* TWI_IER */
+/* TWI_IDR */
+/* TWI_IMR */
+#define TWI_SR_TXCOMP (1U << 0) /* Transmission Completed */
+#define TWI_SR_RXRDY (1U << 1) /* Receive Holding Register Ready */
+#define TWI_SR_TXRDY (1U << 2) /* Transmit Holding Register Ready */
+#define TWI_SR_SVREAD (1U << 3) /* Slave Read */
+#define TWI_SR_SVACC (1U << 4) /* Slave Access */
+#define TWI_SR_GCACC (1U << 5) /* General Call Access */
+#define TWI_SR_OVRE (1U << 6) /* Overrun error */
+#define TWI_SR_UNRE (1U << 7) /* Underrun Error */
+#define TWI_SR_NACK (1U << 8) /* Not Acknowledged */
+#define TWI_SR_ARBLST (1U << 9) /* Arbitration Lost */
+
+#endif /* ARM_AT91_AT91_TWIREG_H */
Property changes on: trunk/sys/arm/at91/at91_twireg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_usartreg.h
===================================================================
--- trunk/sys/arm/at91/at91_usartreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_usartreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,130 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91_usartreg.h 185265 2008-11-25 00:13:26Z imp $ */
+
+#ifndef AT91USARTREG_H_
+#define AT91USARTREG_H_
+
+#define USART_CR 0x00 /* Control register */
+#define USART_CR_RSTRX (1UL << 2) /* Reset Receiver */
+#define USART_CR_RSTTX (1UL << 3) /* Reset Transmitter */
+#define USART_CR_RXEN (1UL << 4) /* Receiver Enable */
+#define USART_CR_RXDIS (1UL << 5) /* Receiver Disable */
+#define USART_CR_TXEN (1UL << 6) /* Transmitter Enable */
+#define USART_CR_TXDIS (1UL << 7) /* Transmitter Disable */
+#define USART_CR_RSTSTA (1UL << 8) /* Reset Status Bits */
+#define USART_CR_STTBRK (1UL << 9) /* Start Break */
+#define USART_CR_STPBRK (1UL << 10) /* Stop Break */
+#define USART_CR_STTTO (1UL << 11) /* Start Time-out */
+#define USART_CR_SENDA (1UL << 12) /* Send Address */
+#define USART_CR_RSTIT (1UL << 13) /* Reset Iterations */
+#define USART_CR_RSTNACK (1UL << 14) /* Reset Non Acknowledge */
+#define USART_CR_RETTO (1UL << 15) /* Rearm Time-out */
+#define USART_CR_DTREN (1UL << 16) /* Data Terminal ready Enable */
+#define USART_CR_DTRDIS (1UL << 17) /* Data Terminal ready Disable */
+#define USART_CR_RTSEN (1UL << 18) /* Request to Send enable */
+#define USART_CR_RTSDIS (1UL << 19) /* Request to Send Disable */
+
+#define USART_MR 0x04 /* Mode register */
+#define USART_MR_MODE_NORMAL 0 /* Normal/Async/3-wire rs-232 */
+#define USART_MR_MODE_RS485 1 /* RS485 */
+#define USART_MR_MODE_HWFLOW 2 /* Hardware flow control/handshake */
+#define USART_MR_MODE_MODEM 3 /* Full modem protocol */
+#define USART_MR_MODE_ISO7816T0 4 /* ISO7816 T=0 */
+#define USART_MR_MODE_ISO7816T1 6 /* ISO7816 T=1 */
+#define USART_MR_MODE_IRDA 8 /* IrDA mode */
+#define USART_MR_USCLKS_MCK (0U << 4) /* use MCK for baudclock */
+#define USART_MR_USCLKS_MCKDIV (1U << 4) /* use MCK/DIV for baudclock */
+#define USART_MR_USCLKS_SCK (3U << 4) /* use SCK (ext) for baudclock */
+#define USART_MR_CHRL_5BITS (0U << 6)
+#define USART_MR_CHRL_6BITS (1U << 6)
+#define USART_MR_CHRL_7BITS (2U << 6)
+#define USART_MR_CHRL_8BITS (3U << 6)
+#define USART_MR_SYNC (1U << 8) /* 1 -> sync 0 -> async */
+#define USART_MR_PAR_EVEN (0U << 9)
+#define USART_MR_PAR_ODD (1U << 9)
+#define USART_MR_PAR_SPACE (2U << 9)
+#define USART_MR_PAR_MARK (3U << 9)
+#define USART_MR_PAR_NONE (4U << 9)
+#define USART_MR_PAR_MULTIDROP (6U << 9)
+#define USART_MR_NBSTOP_1 (0U << 12)
+#define USART_MR_NBSTOP_1_5 (1U << 12)
+#define USART_MR_NBSTOP_2 (2U << 12)
+#define USART_MR_CHMODE_NORMAL (0U << 14)
+#define USART_MR_CHMODE_ECHO (1U << 14)
+#define USART_MR_CHMODE_LOOP (2U << 14)
+#define USART_MR_CHMODE_REMLOOP (3U << 14)
+#define USART_MR_MSBF (1U << 16)
+#define USART_MR_MODE9 (1U << 17)
+#define USART_MR_CKLO_SCK (1U << 18)
+#define USART_MR_OVER16 0
+#define USART_MR_OVER8 (1U << 19)
+#define USART_MR_INACK (1U << 20) /* Inhibit NACK generation */
+#define USART_MR_DSNACK (1U << 21) /* Disable Successive NACK */
+#define USART_MR_MAXITERATION(x) ((x) << 24)
+#define USART_MR_FILTER (1U << 28) /* Filters for Ir lines */
+
+#define USART_IER 0x08 /* Interrupt enable register */
+#define USART_IDR 0x0c /* Interrupt disable register */
+#define USART_IMR 0x10 /* Interrupt mask register */
+#define USART_CSR 0x14 /* Channel status register */
+
+#define USART_CSR_RXRDY (1UL << 0) /* Receiver ready */
+#define USART_CSR_TXRDY (1UL << 1) /* Transmitter ready */
+#define USART_CSR_RXBRK (1UL << 2) /* Break received */
+#define USART_CSR_ENDRX (1UL << 3) /* End of Transfer RX from PDC */
+#define USART_CSR_ENDTX (1UL << 4) /* End of Transfer TX from PDC */
+#define USART_CSR_OVRE (1UL << 5) /* Overrun error */
+#define USART_CSR_FRAME (1UL << 6) /* Framing error */
+#define USART_CSR_PARE (1UL << 7) /* Parity Error */
+#define USART_CSR_TIMEOUT (1UL << 8) /* Timeout since start-timeout */
+#define USART_CSR_TXEMPTY (1UL << 9) /* Transmitter empty */
+#define USART_CSR_ITERATION (1UL << 10) /* max repetitions since RSIT */
+#define USART_CSR_TXBUFE (1UL << 11) /* Buffer empty from PDC */
+#define USART_CSR_RXBUFF (1UL << 12) /* Buffer full from PDC */
+#define USART_CSR_NACK (1UL << 13) /* NACK since last RSTNACK */
+#define USART_CSR_RIIC (1UL << 16) /* RI delta since last csr read */
+#define USART_CSR_DSRIC (1UL << 17) /* DSR delta */
+#define USART_CSR_DCDIC (1UL << 18) /* DCD delta */
+#define USART_CSR_CTSIC (1UL << 19) /* CTS delta */
+#define USART_CSR_RI (1UL << 20) /* RI status */
+#define USART_CSR_DSR (1UL << 21) /* DSR status */
+#define USART_CSR_DCD (1UL << 22) /* DCD status */
+#define USART_CSR_CTS (1UL << 23) /* CTS status */
+
+#define USART_RHR 0x18 /* Receiver holding register */
+#define USART_THR 0x1c /* Transmitter holding register */
+#define USART_BRGR 0x20 /* Baud rate generator register */
+#define USART_RTOR 0x24 /* Receiver time-out register */
+#define USART_TTR 0x28 /* Transmitter timeguard register */
+/* 0x2c to 0x3c reserved */
+#define USART_FDRR 0x40 /* FI DI ratio register */
+#define USART_NER 0x44 /* Number of errors register */
+/* 0x48 reserved */
+#define USART_IFR 0x48 /* IrDA filter register */
+
+#endif /* AT91RM92REG_H_ */
Property changes on: trunk/sys/arm/at91/at91_usartreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_wdt.c
===================================================================
--- trunk/sys/arm/at91/at91_wdt.c (rev 0)
+++ trunk/sys/arm/at91/at91_wdt.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,239 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The SAM9 watchdog hardware can be programed only once. So we set the
+ * hardware watchdog to 16 s in wdt_attach and only reset it in the wdt_tick
+ * handler. The watchdog is halted in processor debug mode.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_wdt.c 266196 2014-05-15 21:21:47Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/watchdog.h>
+
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91_wdtreg.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+struct wdt_softc {
+ struct mtx sc_mtx;
+ device_t sc_dev;
+ struct resource *mem_res;
+ struct callout tick_ch;
+ eventhandler_tag sc_wet;
+ void *intrhand;
+ u_int cmd;
+ u_int interval;
+};
+
+static inline uint32_t
+RD4(struct wdt_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct wdt_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+static int
+wdt_intr(void *argp)
+{
+ struct wdt_softc *sc = argp;
+
+
+ if (RD4(sc, WDT_SR) & (WDT_WDUNF | WDT_WDERR)) {
+#if defined(KDB) && !defined(KDB_UNATTENDED)
+ kdb_backtrace();
+ kdb_enter(KDB_WHY_WATCHDOG, "watchdog timeout");
+#else
+ panic("watchdog timeout");
+#endif
+ }
+ return (FILTER_STRAY);
+}
+
+/* User interface, see watchdog(9) */
+static void
+wdt_watchdog(void *argp, u_int cmd, int *error)
+{
+ struct wdt_softc *sc = argp;
+ u_int interval;
+
+ mtx_lock(&sc->sc_mtx);
+
+ *error = 0;
+ sc->cmd = 0;
+ interval = cmd & WD_INTERVAL;
+ if (interval > WD_TO_16SEC)
+ *error = EOPNOTSUPP;
+ else if (interval > 0)
+ sc->cmd = interval | WD_ACTIVE;
+
+ /* We cannot turn off our watchdog so if user
+ * fails to turn us on go to passive mode. */
+ if ((sc->cmd & WD_ACTIVE) == 0)
+ sc->cmd = WD_PASSIVE;
+
+ mtx_unlock(&sc->sc_mtx);
+}
+
+/* This routine is called no matter what state the user sets the
+ * watchdog mode to. Called at a rate that is slightly less than
+ * half the hardware timeout. */
+static void
+wdt_tick(void *argp)
+{
+ struct wdt_softc *sc = argp;
+
+ mtx_assert(&sc->sc_mtx, MA_OWNED);
+ if (sc->cmd & (WD_ACTIVE | WD_PASSIVE))
+ WR4(sc, WDT_CR, WDT_KEY|WDT_WDRSTT);
+
+ sc->cmd &= WD_PASSIVE;
+ callout_reset(&sc->tick_ch, sc->interval, wdt_tick, sc);
+}
+
+static int
+wdt_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "atmel,at91sam9260-wdt"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "WDT");
+ return (0);
+}
+
+static int
+wdt_attach(device_t dev)
+{
+ static struct wdt_softc *sc;
+ struct resource *irq;
+ uint32_t wdt_mr;
+ int rid, err;
+
+ sc = device_get_softc(dev);
+ sc->cmd = WD_PASSIVE;
+ sc->sc_dev = dev;
+
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "at91_wdt", MTX_DEF);
+ callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+
+ if (sc->mem_res == NULL)
+ panic("couldn't allocate wdt register resources");
+
+ wdt_mr = RD4(sc, WDT_MR);
+ if ((wdt_mr & WDT_WDRSTEN) == 0)
+ device_printf(dev, "Watchdog disabled! (Boot ROM?)\n");
+ else {
+#ifdef WDT_RESET
+ /* Rude, full reset of whole system on watch dog timeout */
+ WR4(sc, WDT_MR, WDT_WDDBGHLT | WDT_WDD(0xC00)|
+ WDT_WDRSTEN| WDT_WDV(0xFFF));
+#else
+ /* Generate stack trace and panic on watchdog timeout*/
+ WR4(sc, WDT_MR, WDT_WDDBGHLT | WDT_WDD(0xC00)|
+ WDT_WDFIEN| WDT_WDV(0xFFF));
+#endif
+ /*
+ * This may have been set by Boot ROM so register value may
+ * not be what we just requested since this is a write once
+ * register.
+ */
+ wdt_mr = RD4(sc, WDT_MR);
+ if (wdt_mr & WDT_WDFIEN) {
+ rid = 0;
+ irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!irq)
+ panic("could not allocate interrupt.\n");
+
+ err = bus_setup_intr(dev, irq, INTR_TYPE_CLK, wdt_intr,
+ NULL, sc, &sc->intrhand);
+ }
+
+ /* interval * hz */
+ sc->interval = (((wdt_mr & WDT_WDV(~0)) + 1) * WDT_DIV) /
+ (WDT_CLOCK/hz);
+
+ device_printf(dev, "watchdog timeout: %d seconds\n",
+ sc->interval / hz);
+
+ /* Slightly less than 1/2 of watchdog hardware timeout */
+ sc->interval = (sc->interval/2) - (sc->interval/20);
+ callout_reset(&sc->tick_ch, sc->interval, wdt_tick, sc);
+
+ /* Register us as a watchdog */
+ sc->sc_wet = EVENTHANDLER_REGISTER(watchdog_list,
+ wdt_watchdog, sc, 0);
+ }
+ return (0);
+}
+
+static device_method_t wdt_methods[] = {
+ DEVMETHOD(device_probe, wdt_probe),
+ DEVMETHOD(device_attach, wdt_attach),
+ DEVMETHOD_END
+};
+
+static driver_t wdt_driver = {
+ "at91_wdt",
+ wdt_methods,
+ sizeof(struct wdt_softc),
+};
+
+static devclass_t wdt_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(at91_wdt, simplebus, wdt_driver, wdt_devclass, NULL, NULL);
+#else
+DRIVER_MODULE(at91_wdt, atmelarm, wdt_driver, wdt_devclass, NULL, NULL);
+#endif
Property changes on: trunk/sys/arm/at91/at91_wdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91_wdtreg.h
===================================================================
--- trunk/sys/arm/at91/at91_wdtreg.h (rev 0)
+++ trunk/sys/arm/at91/at91_wdtreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,61 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Gallon Sylvestre. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $FreeBSD: stable/10/sys/arm/at91/at91_wdtreg.h 236989 2012-06-13 04:52:19Z imp $
+ */
+
+#ifndef ARM_AT91_AT91WDTREG_H
+#define ARM_AT91_AT91WDTREG_H
+
+#ifndef WDT_CLOCK
+#define WDT_CLOCK (32768)
+#endif
+#define WDT_DIV (128) /* Clock is slow clock / 128 */
+
+#define WDT_CR 0x0 /* Control Register */
+#define WDT_MR 0x4 /* Mode Register */
+#define WDT_SR 0x8 /* Status Register */
+
+/* WDT_CR */
+#define WDT_KEY (0xa5<<24)
+#define WDT_WDRSTT 0x1
+
+/* WDT_MR */
+#define WDT_WDV(x) (x & 0xfff) /* counter value*/
+#define WDT_WDFIEN (1<<12) /* enable interrupt */
+#define WDT_WDRSTEN (1<<13) /* enable reset */
+#define WDT_WDRPROC (1<<14) /* processor reset */
+#define WDT_WDDIS (1<<15) /* disable */
+#define WDT_WDD(x) ((x & 0xfff) << 16) /* delta value */
+#define WDT_WDDBGHLT (1<<28) /* halt in debug */
+#define WDT_WDIDLEHLT (1<<29) /* halt in idle */
+
+/* WDT_SR */
+#define WDT_WDUNF 0x1
+#define WDT_WDERR 0x2
+
+#endif /* ARM_AT91_AT91WDTREG_H */
Property changes on: trunk/sys/arm/at91/at91_wdtreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91board.h
===================================================================
--- trunk/sys/arm/at91/at91board.h (rev 0)
+++ trunk/sys/arm/at91/at91board.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91board.h 238189 2012-07-07 05:02:39Z imp $ */
+
+#ifndef _ARM_AT91_AT91BOARD_H_
+#define _ARM_AT91_AT91BOARD_H_
+
+/*
+ * These routines are used by board init routines
+ */
+long at91_ramsize(void);
+
+#endif /* _ARM_AT91_AT91BOARD_H_ */
Property changes on: trunk/sys/arm/at91/at91board.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91reg.h
===================================================================
--- trunk/sys/arm/at91/at91reg.h (rev 0)
+++ trunk/sys/arm/at91/at91reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,91 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Greg Ansley All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $FreeBSD: stable/10/sys/arm/at91/at91reg.h 238331 2012-07-10 02:39:03Z imp $
+ */
+
+#ifndef _AT91REG_H_
+#define _AT91REG_H_
+
+#include "opt_at91.h"
+
+/* Where builtin peripherals start in KVM */
+#define AT91_BASE 0xd0000000
+
+/* Where builtin peripherals start PA */
+#define AT91_PA_BASE 0xf0000000
+
+/* A few things that we count on being the same
+ * throught the whole family of SOCs */
+
+/* SYSC System Controler */
+/* System Registers */
+#define AT91_SYS_BASE 0xffff000
+#define AT91_SYS_SIZE 0x1000
+
+#define AT91_DBGU0 0x0ffff200 /* Most */
+#define AT91_DBGU1 0x0fffee00 /* SAM9263, CAP9, and SAM9G45 */
+
+#define AT91_DBGU_SIZE 0x200
+#define DBGU_C1R (64) /* Chip ID1 Register */
+#define DBGU_C2R (68) /* Chip ID2 Register */
+#define DBGU_FNTR (72) /* Force NTRST Register */
+
+#define AT91_CPU_VERSION_MASK 0x0000001f
+#define AT91_CPU_FAMILY_MASK 0x0ff00000
+
+#define AT91_CPU_RM9200 0x09290780
+#define AT91_CPU_SAM9260 0x019803a0
+#define AT91_CPU_SAM9261 0x019703a0
+#define AT91_CPU_SAM9263 0x019607a0
+#define AT91_CPU_SAM9G10 0x819903a0
+#define AT91_CPU_SAM9G20 0x019905a0
+#define AT91_CPU_SAM9G45 0x819b05a0
+#define AT91_CPU_SAM9N12 0x819a07a0
+#define AT91_CPU_SAM9RL64 0x019b03a0
+#define AT91_CPU_SAM9X5 0x819a05a0
+
+#define AT91_CPU_SAM9XE128 0x329973a0
+#define AT91_CPU_SAM9XE256 0x329a93a0
+#define AT91_CPU_SAM9XE512 0x329aa3a0
+
+#define AT91_CPU_CAP9 0x039a03a0
+
+#define AT91_EXID_SAM9M11 0x00000001
+#define AT91_EXID_SAM9M10 0x00000002
+#define AT91_EXID_SAM9G46 0x00000003
+#define AT91_EXID_SAM9G45 0x00000004
+
+#define AT91_EXID_SAM9G15 0x00000000
+#define AT91_EXID_SAM9G35 0x00000001
+#define AT91_EXID_SAM9X35 0x00000002
+#define AT91_EXID_SAM9G25 0x00000003
+#define AT91_EXID_SAM9X25 0x00000004
+
+#define AT91_IRQ_SYSTEM 1
+
+#endif /* _AT91REG_H_ */
Property changes on: trunk/sys/arm/at91/at91reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91rm9200.c
===================================================================
--- trunk/sys/arm/at91/at91rm9200.c (rev 0)
+++ trunk/sys/arm/at91/at91rm9200.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,211 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91rm9200.c 266277 2014-05-17 00:53:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91rm92reg.h>
+#include <arm/at91/at91_aicreg.h>
+#include <arm/at91/at91_pmcreg.h>
+#include <arm/at91/at91_streg.h>
+#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91soc.h>
+
+/*
+ * Standard priority levels for the system. 0 is lowest and 7 is highest.
+ * These values are the ones Atmel uses for its Linux port, which differ
+ * a little form the ones that are in the standard distribution. Also,
+ * the ones marked with 'TWEEK' are different based on experience.
+ */
+static const int at91_irq_prio[32] =
+{
+ 7, /* Advanced Interrupt Controller (FIQ) */
+ 7, /* System Peripherals */
+ 1, /* Parallel IO Controller A */
+ 1, /* Parallel IO Controller B */
+ 1, /* Parallel IO Controller C */
+ 1, /* Parallel IO Controller D */
+ 5, /* USART 0 */
+ 5, /* USART 1 */
+ 5, /* USART 2 */
+ 5, /* USART 3 */
+ 0, /* Multimedia Card Interface */
+ 2, /* USB Device Port */
+ 4, /* Two-Wire Interface */ /* TWEEK */
+ 5, /* Serial Peripheral Interface */
+ 4, /* Serial Synchronous Controller 0 */
+ 6, /* Serial Synchronous Controller 1 */ /* TWEEK */
+ 4, /* Serial Synchronous Controller 2 */
+ 0, /* Timer Counter 0 */
+ 6, /* Timer Counter 1 */ /* TWEEK */
+ 0, /* Timer Counter 2 */
+ 0, /* Timer Counter 3 */
+ 0, /* Timer Counter 4 */
+ 0, /* Timer Counter 5 */
+ 2, /* USB Host port */
+ 3, /* Ethernet MAC */
+ 0, /* Advanced Interrupt Controller (IRQ0) */
+ 0, /* Advanced Interrupt Controller (IRQ1) */
+ 0, /* Advanced Interrupt Controller (IRQ2) */
+ 0, /* Advanced Interrupt Controller (IRQ3) */
+ 0, /* Advanced Interrupt Controller (IRQ4) */
+ 0, /* Advanced Interrupt Controller (IRQ5) */
+ 0 /* Advanced Interrupt Controller (IRQ6) */
+};
+
+static const uint32_t at91_pio_base[] = {
+ AT91RM92_PIOA_BASE,
+ AT91RM92_PIOB_BASE,
+ AT91RM92_PIOC_BASE,
+ AT91RM92_PIOD_BASE,
+};
+
+#define DEVICE(_name, _id, _unit) \
+ { \
+ _name, _unit, \
+ AT91RM92_ ## _id ##_BASE, \
+ AT91RM92_ ## _id ## _SIZE, \
+ AT91RM92_IRQ_ ## _id \
+ }
+
+static const struct cpu_devs at91_devs[] =
+{
+ DEVICE("at91_aic", AIC, 0),
+ DEVICE("at91_pmc", PMC, 0),
+ DEVICE("at91_st", ST, 0),
+ DEVICE("at91_pio", PIOA, 0),
+ DEVICE("at91_pio", PIOB, 1),
+ DEVICE("at91_pio", PIOC, 2),
+ DEVICE("at91_pio", PIOD, 3),
+ DEVICE("at91_rtc", RTC, 0),
+
+ DEVICE("at91_mci", MCI, 0),
+ DEVICE("at91_twi", TWI, 0),
+ DEVICE("at91_udp", UDP, 0),
+ DEVICE("ate", EMAC, 0),
+ DEVICE("at91_ssc", SSC0, 0),
+ DEVICE("at91_ssc", SSC1, 1),
+ DEVICE("at91_ssc", SSC2, 2),
+ DEVICE("spi", SPI, 0),
+
+ DEVICE("uart", DBGU, 0),
+ DEVICE("uart", USART0, 1),
+ DEVICE("uart", USART1, 2),
+ DEVICE("uart", USART2, 3),
+ DEVICE("uart", USART3, 4),
+ DEVICE("at91_aic", AIC, 0),
+ DEVICE("at91_mc", MC, 0),
+ DEVICE("at91_tc", TC0, 0),
+ DEVICE("at91_tc", TC1, 1),
+ DEVICE("ohci", OHCI, 0),
+ DEVICE("at91_cfata", CF, 0),
+ { 0, 0, 0, 0, 0 }
+};
+
+static uint32_t
+at91_pll_outb(int freq)
+{
+
+ if (freq > 155000000)
+ return (0x0000);
+ else
+ return (0x8000);
+}
+
+#if 0
+/* -- XXX are these needed? */
+ /* Disable all interrupts for RTC (0xe24 == RTC_IDR) */
+ bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff);
+
+ /* Disable all interrupts for the SDRAM controller */
+ bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff);
+#endif
+
+static void
+at91_clock_init(void)
+{
+ struct at91_pmc_clock *clk;
+
+ /* Update USB device port clock info */
+ clk = at91_pmc_clock_ref("udpck");
+ clk->pmc_mask = PMC_SCER_UDP;
+ at91_pmc_clock_deref(clk);
+
+ /* Update USB host port clock info */
+ clk = at91_pmc_clock_ref("uhpck");
+ clk->pmc_mask = PMC_SCER_UHP;
+ at91_pmc_clock_deref(clk);
+
+ /* Each SOC has different PLL contraints */
+ clk = at91_pmc_clock_ref("plla");
+ clk->pll_min_in = RM9200_PLL_A_MIN_IN_FREQ; /* 1 MHz */
+ clk->pll_max_in = RM9200_PLL_A_MAX_IN_FREQ; /* 32 MHz */
+ clk->pll_min_out = RM9200_PLL_A_MIN_OUT_FREQ; /* 80 MHz */
+ clk->pll_max_out = RM9200_PLL_A_MAX_OUT_FREQ; /* 180 MHz */
+ clk->pll_mul_shift = RM9200_PLL_A_MUL_SHIFT;
+ clk->pll_mul_mask = RM9200_PLL_A_MUL_MASK;
+ clk->pll_div_shift = RM9200_PLL_A_DIV_SHIFT;
+ clk->pll_div_mask = RM9200_PLL_A_DIV_MASK;
+ clk->set_outb = at91_pll_outb;
+ at91_pmc_clock_deref(clk);
+
+ clk = at91_pmc_clock_ref("pllb");
+ clk->pll_min_in = RM9200_PLL_B_MIN_IN_FREQ; /* 100 KHz */
+ clk->pll_max_in = RM9200_PLL_B_MAX_IN_FREQ; /* 32 MHz */
+ clk->pll_min_out = RM9200_PLL_B_MIN_OUT_FREQ; /* 30 MHz */
+ clk->pll_max_out = RM9200_PLL_B_MAX_OUT_FREQ; /* 240 MHz */
+ clk->pll_mul_shift = RM9200_PLL_B_MUL_SHIFT;
+ clk->pll_mul_mask = RM9200_PLL_B_MUL_MASK;
+ clk->pll_div_shift = RM9200_PLL_B_DIV_SHIFT;
+ clk->pll_div_mask = RM9200_PLL_B_DIV_MASK;
+ clk->set_outb = at91_pll_outb;
+ at91_pmc_clock_deref(clk);
+}
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_st_delay,
+ .soc_reset = at91_st_cpu_reset,
+ .soc_clock_init = at91_clock_init,
+ .soc_irq_prio = at91_irq_prio,
+ .soc_children = at91_devs,
+ .soc_pio_base = at91_pio_base,
+ .soc_pio_count = nitems(at91_pio_base),
+};
+
+AT91_SOC(AT91_T_RM9200, &soc_data);
Property changes on: trunk/sys/arm/at91/at91rm9200.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91rm9200_devices.c
===================================================================
--- trunk/sys/arm/at91/at91rm9200_devices.c (rev 0)
+++ trunk/sys/arm/at91/at91rm9200_devices.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,143 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 M. Warner Losh. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91rm9200_devices.c 248902 2013-03-29 18:06:54Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91rm92reg.h>
+#include <arm/at91/at91rm9200var.h>
+#include <arm/at91/at91_pioreg.h>
+#include <arm/at91/at91_piovar.h>
+
+/*
+ * The AT91RM9200 uses the same silicon for both the BGA and PQFP
+ * packages. There's no documented way to detect this at runtime,
+ * so we require the board code to register what type of SoC is on the
+ * board in question. The pinouts are not quite compatible, and we
+ * use this information to cope with the slight differences.
+ */
+void
+at91rm9200_set_subtype(enum at91_soc_subtype st)
+{
+
+ switch (st) {
+ case AT91_ST_RM9200_BGA:
+ case AT91_ST_RM9200_PQFP:
+ soc_info.subtype = st;
+ break;
+ default:
+ panic("Bad SoC subtype %d for at91rm9200_set_subtype.", st);
+ break;
+ }
+}
+
+void
+at91rm9200_config_uart(unsigned devid, unsigned unit, unsigned pinmask)
+{
+
+ /*
+ * Since the USART supports RS-485 multidrop mode, it allows the
+ * TX pins to float. However, for RS-232 operations, we don't want
+ * these pins to float. Instead, they should be pulled up to avoid
+ * mismatches. Linux does something similar when it configures the
+ * TX lines. This implies that we also allow the RX lines to float
+ * rather than be in the state they are left in by the boot loader.
+ * Since they are input pins, I think that this is the right thing
+ * to do.
+ */
+
+ /*
+ * Current boards supported don't need the extras, but they should be
+ * implemented. But that should wait until the new pin api goes in.
+ */
+ switch (devid) {
+ case AT91_ID_DBGU:
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA30, 0); /* DRXD */
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA31, 1); /* DTXD */
+ break;
+
+ case AT91RM9200_ID_USART0:
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA17, 1); /* TXD0 */
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA18, 0); /* RXD0 */
+ /* CTS PA20 */
+ /* RTS -- errata #39 PA21 */
+ break;
+
+ case AT91RM9200_ID_USART1:
+ at91_pio_use_periph_a(AT91RM92_PIOB_BASE, AT91C_PIO_PB20, 1); /* TXD1 */
+ at91_pio_use_periph_a(AT91RM92_PIOB_BASE, AT91C_PIO_PB21, 0); /* RXD1 */
+ /* RI - PB18 */
+ /* DTR - PB19 */
+ /* DCD - PB23 */
+ /* CTS - PB24 */
+ /* DSR - PB25 */
+ /* RTS - PB26 */
+ break;
+
+ case AT91RM9200_ID_USART2:
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA22, 0); /* RXD2 */
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA23, 1); /* TXD2 */
+ /* CTS - PA30 B periph */
+ /* RTS - PA31 B periph */
+ break;
+
+ case AT91RM9200_ID_USART3:
+ at91_pio_use_periph_b(AT91RM92_PIOA_BASE, AT91C_PIO_PA5, 1); /* TXD3 */
+ at91_pio_use_periph_b(AT91RM92_PIOA_BASE, AT91C_PIO_PA6, 0); /* RXD3 */
+ /* CTS - PB0 B periph */
+ /* RTS - PB1 B periph */
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+at91rm9200_config_mci(int has_4wire)
+{
+ /* XXX TODO chip changed GPIO, other slots, etc */
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA27, 0); /* MCCK */
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA28, 1); /* MCCDA */
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE, AT91C_PIO_PA29, 1); /* MCDA0 */
+ if (has_4wire) {
+ at91_pio_use_periph_b(AT91RM92_PIOB_BASE, AT91C_PIO_PB3, 1); /* MCDA1 */
+ at91_pio_use_periph_b(AT91RM92_PIOB_BASE, AT91C_PIO_PB4, 1); /* MCDA2 */
+ at91_pio_use_periph_b(AT91RM92_PIOB_BASE, AT91C_PIO_PB5, 1); /* MCDA3 */
+ }
+}
Property changes on: trunk/sys/arm/at91/at91rm9200_devices.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91rm9200var.h
===================================================================
--- trunk/sys/arm/at91/at91rm9200var.h (rev 0)
+++ trunk/sys/arm/at91/at91rm9200var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,59 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91rm9200var.h 238465 2012-07-15 05:41:43Z imp $ */
+
+#ifndef ARM_AT91_AT91RM9200VAR_H
+#define ARM_AT91_AT91RM9200VAR_H
+
+void at91rm9200_set_subtype(enum at91_soc_subtype st);
+
+#define AT91RM9200_ID_USART0 1
+#define AT91RM9200_ID_USART1 2
+#define AT91RM9200_ID_USART2 3
+#define AT91RM9200_ID_USART3 4
+
+/*
+ * Serial port convenience routines
+ */
+/* uart pins that are wired... */
+#define AT91_UART_CTS 0x01
+#define AT91_UART_RTS 0x02
+#define AT91_UART_RI 0x04
+#define AT91_UART_DTR 0x08
+#define AT91_UART_DCD 0x10
+#define AT91_UART_DSR 0x20
+
+#define AT91_ID_DBGU 0
+
+void at91rm9200_config_uart(unsigned devid, unsigned unit, unsigned pinmask);
+
+/*
+ * MCI (sd/mmc card support)
+ */
+void at91rm9200_config_mci(int has_4wire);
+
+#endif /* ARM_AT91_AT91RM9200VAR_H */
Property changes on: trunk/sys/arm/at91/at91rm9200var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91rm92reg.h
===================================================================
--- trunk/sys/arm/at91/at91rm92reg.h (rev 0)
+++ trunk/sys/arm/at91/at91rm92reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,307 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91rm92reg.h 266110 2014-05-15 02:41:23Z ian $ */
+
+#ifndef AT91RM92REG_H_
+#define AT91RM92REG_H_
+
+/* Chip Specific limits */
+#define RM9200_PLL_A_MIN_IN_FREQ 1000000 /* 1 MHz */
+#define RM9200_PLL_A_MAX_IN_FREQ 32000000 /* 32 MHz */
+#define RM9200_PLL_A_MIN_OUT_FREQ 80000000 /* 80 MHz */
+#define RM9200_PLL_A_MAX_OUT_FREQ 180000000 /* 180 MHz */
+#define RM9200_PLL_A_MUL_SHIFT 16
+#define RM9200_PLL_A_MUL_MASK 0x7FF
+#define RM9200_PLL_A_DIV_SHIFT 0
+#define RM9200_PLL_A_DIV_MASK 0xFF
+
+/*
+ * PLL B input frequency spec sheet says it must be between 1MHz and 32MHz,
+ * but it works down as low as 100kHz, a frequency necessary for some
+ * output frequencies to work.
+ *
+ * PLL Max output frequency is 240MHz. The errata says 180MHz is the max
+ * for some revisions of this part. Be more permissive and optimistic.
+ */
+#define RM9200_PLL_B_MIN_IN_FREQ 100000 /* 100 KHz */
+#define RM9200_PLL_B_MAX_IN_FREQ 32000000 /* 32 MHz */
+#define RM9200_PLL_B_MIN_OUT_FREQ 30000000 /* 30 MHz */
+#define RM9200_PLL_B_MAX_OUT_FREQ 240000000 /* 240 MHz */
+#define RM9200_PLL_B_MUL_SHIFT 16
+#define RM9200_PLL_B_MUL_MASK 0x7FF
+#define RM9200_PLL_B_DIV_SHIFT 0
+#define RM9200_PLL_B_DIV_MASK 0xFF
+
+/*
+ * Memory map, from datasheet :
+ * 0x00000000 - 0x0ffffffff : Internal Memories
+ * 0x10000000 - 0x1ffffffff : Chip Select 0
+ * 0x20000000 - 0x2ffffffff : Chip Select 1
+ * 0x30000000 - 0x3ffffffff : Chip Select 2
+ * 0x40000000 - 0x4ffffffff : Chip Select 3
+ * 0x50000000 - 0x5ffffffff : Chip Select 4
+ * 0x60000000 - 0x6ffffffff : Chip Select 5
+ * 0x70000000 - 0x7ffffffff : Chip Select 6
+ * 0x80000000 - 0x8ffffffff : Chip Select 7
+ * 0x90000000 - 0xeffffffff : Undefined (Abort)
+ * 0xf0000000 - 0xfffffffff : Peripherals
+ */
+
+/* Usart */
+
+#define AT91RM92_USART_SIZE 0x4000
+#define AT91RM92_USART0_BASE 0xffc0000
+#define AT91RM92_USART0_PDC 0xffc0100
+#define AT91RM92_USART0_SIZE AT91RM92_USART_SIZE
+#define AT91RM92_USART1_BASE 0xffc4000
+#define AT91RM92_USART1_PDC 0xffc4100
+#define AT91RM92_USART1_SIZE AT91RM92_USART_SIZE
+#define AT91RM92_USART2_BASE 0xffc8000
+#define AT91RM92_USART2_PDC 0xffc8100
+#define AT91RM92_USART2_SIZE AT91RM92_USART_SIZE
+#define AT91RM92_USART3_BASE 0xffcc000
+#define AT91RM92_USART3_PDC 0xffcc100
+#define AT91RM92_USART3_SIZE AT91RM92_USART_SIZE
+
+/* System Registers */
+
+#define AT91RM92_SYS_BASE 0xffff000
+#define AT91RM92_SYS_SIZE 0x1000
+
+/*
+ * PIO
+ */
+#define AT91RM92_PIO_SIZE 0x200
+#define AT91RM92_PIOA_BASE 0xffff400
+#define AT91RM92_PIOA_SIZE AT91RM92_PIO_SIZE
+#define AT91RM92_PIOB_BASE 0xffff600
+#define AT91RM92_PIOB_SIZE AT91RM92_PIO_SIZE
+#define AT91RM92_PIOC_BASE 0xffff800
+#define AT91RM92_PIOC_SIZE AT91RM92_PIO_SIZE
+#define AT91RM92_PIOD_BASE 0xffffa00
+#define AT91RM92_PIOD_SIZE AT91RM92_PIO_SIZE
+
+/*
+ * PMC
+ */
+#define AT91RM92_PMC_BASE 0xffffc00
+#define AT91RM92_PMC_SIZE 0x100
+
+/* IRQs : */
+/*
+ * 0: AIC
+ * 1: System peripheral (System timer, RTC, DBGU)
+ * 2: PIO Controller A
+ * 3: PIO Controller B
+ * 4: PIO Controller C
+ * 5: PIO Controller D
+ * 6: USART 0
+ * 7: USART 1
+ * 8: USART 2
+ * 9: USART 3
+ * 10: MMC Interface
+ * 11: USB device port
+ * 12: Two-wirte interface
+ * 13: SPI
+ * 14: SSC
+ * 15: SSC
+ * 16: SSC
+ * 17: Timer Counter 0
+ * 18: Timer Counter 1
+ * 19: Timer Counter 2
+ * 20: Timer Counter 3
+ * 21: Timer Counter 4
+ * 22: Timer Counter 6
+ * 23: USB Host port
+ * 24: Ethernet
+ * 25: AIC
+ * 26: AIC
+ * 27: AIC
+ * 28: AIC
+ * 29: AIC
+ * 30: AIC
+ * 31: AIC
+ */
+
+#define AT91RM92_IRQ_SYSTEM 1
+#define AT91RM92_IRQ_PIOA 2
+#define AT91RM92_IRQ_PIOB 3
+#define AT91RM92_IRQ_PIOC 4
+#define AT91RM92_IRQ_PIOD 5
+#define AT91RM92_IRQ_USART0 6
+#define AT91RM92_IRQ_USART1 7
+#define AT91RM92_IRQ_USART2 8
+#define AT91RM92_IRQ_USART3 9
+#define AT91RM92_IRQ_MCI 10
+#define AT91RM92_IRQ_UDP 11
+#define AT91RM92_IRQ_TWI 12
+#define AT91RM92_IRQ_SPI 13
+#define AT91RM92_IRQ_SSC0 14
+#define AT91RM92_IRQ_SSC1 15
+#define AT91RM92_IRQ_SSC2 16
+#define AT91RM92_IRQ_TC0 17,18,19
+#define AT91RM92_IRQ_TC0C0 17
+#define AT91RM92_IRQ_TC0C1 18
+#define AT91RM92_IRQ_TC0C2 19
+#define AT91RM92_IRQ_TC1 20,21,22
+#define AT91RM92_IRQ_TC1C1 20
+#define AT91RM92_IRQ_TC1C2 21
+#define AT91RM92_IRQ_TC1C3 22
+#define AT91RM92_IRQ_UHP 23
+#define AT91RM92_IRQ_EMAC 24
+#define AT91RM92_IRQ_AIC_IRQ0 25
+#define AT91RM92_IRQ_AIC_IRQ1 26
+#define AT91RM92_IRQ_AIC_IRQ2 27
+#define AT91RM92_IRQ_AIC_IRQ3 28
+#define AT91RM92_IRQ_AIC_IRQ4 29
+#define AT91RM92_IRQ_AIC_IRQ5 30
+#define AT91RM92_IRQ_AIC_IRQ6 31
+
+/* Alias */
+#define AT91RM92_IRQ_DBGU AT91RM92_IRQ_SYSTEM
+#define AT91RM92_IRQ_PMC AT91RM92_IRQ_SYSTEM
+#define AT91RM92_IRQ_ST AT91RM92_IRQ_SYSTEM
+#define AT91RM92_IRQ_RTC AT91RM92_IRQ_SYSTEM
+#define AT91RM92_IRQ_MC AT91RM92_IRQ_SYSTEM
+#define AT91RM92_IRQ_OHCI AT91RM92_IRQ_UHP
+#define AT91RM92_IRQ_AIC -1
+#define AT91RM92_IRQ_CF -1
+
+/* Timer */
+
+#define AT91RM92_AIC_BASE 0xffff000
+#define AT91RM92_AIC_SIZE 0x200
+
+/* DBGU */
+#define AT91RM92_DBGU_BASE 0xffff200
+#define AT91RM92_DBGU_SIZE 0x200
+
+#define AT91RM92_RTC_BASE 0xffffe00
+#define AT91RM92_RTC_SIZE 0x100
+
+#define AT91RM92_MC_BASE 0xfffff00
+#define AT91RM92_MC_SIZE 0x100
+
+#define AT91RM92_ST_BASE 0xffffd00
+#define AT91RM92_ST_SIZE 0x100
+
+#define AT91RM92_SPI_BASE 0xffe0000
+#define AT91RM92_SPI_SIZE 0x4000
+#define AT91RM92_SPI_PDC 0xffe0100
+
+#define AT91RM92_SSC_SIZE 0x4000
+#define AT91RM92_SSC0_BASE 0xffd0000
+#define AT91RM92_SSC0_PDC 0xffd0100
+#define AT91RM92_SSC0_SIZE AT91RM92_SSC_SIZE
+
+#define AT91RM92_SSC1_BASE 0xffd4000
+#define AT91RM92_SSC1_PDC 0xffd4100
+#define AT91RM92_SSC1_SIZE AT91RM92_SSC_SIZE
+
+#define AT91RM92_SSC2_BASE 0xffd8000
+#define AT91RM92_SSC2_PDC 0xffd8100
+#define AT91RM92_SSC2_SIZE AT91RM92_SSC_SIZE
+
+#define AT91RM92_EMAC_BASE 0xffbc000
+#define AT91RM92_EMAC_SIZE 0x4000
+
+#define AT91RM92_TWI_BASE 0xffb8000
+#define AT91RM92_TWI_SIZE 0x4000
+
+#define AT91RM92_MCI_BASE 0xffb4000
+#define AT91RM92_MCI_PDC 0xffb4100
+#define AT91RM92_MCI_SIZE 0x4000
+
+#define AT91RM92_UDP_BASE 0xffb0000
+#define AT91RM92_UDP_SIZE 0x4000
+
+#define AT91RM92_TC_SIZE 0x4000
+#define AT91RM92_TC0_BASE 0xffa0000
+#define AT91RM92_TC0_SIZE AT91RM92_TC_SIZE
+#define AT91RM92_TC0C0_BASE 0xffa0000
+#define AT91RM92_TC0C1_BASE 0xffa0040
+#define AT91RM92_TC0C2_BASE 0xffa0080
+
+#define AT91RM92_TC1_BASE 0xffa4000
+#define AT91RM92_TC1_SIZE AT91RM92_TC_SIZE
+#define AT91RM92_TC1C0_BASE 0xffa4000
+#define AT91RM92_TC1C1_BASE 0xffa4040
+#define AT91RM92_TC1C2_BASE 0xffa4080
+
+/* XXX Needs to be carfully coordinated with
+ * other * soc's so phyical and vm address
+ * mapping are unique. XXX
+ */
+#define AT91RM92_OHCI_VA_BASE 0xdfe00000
+#define AT91RM92_OHCI_BASE 0x00300000
+#define AT91RM92_OHCI_SIZE 0x00100000
+
+#define AT91RM92_CF_VA_BASE 0xdfd00000
+#define AT91RM92_CF_BASE 0x51400000
+#define AT91RM92_CF_SIZE 0x00100000
+
+/* SDRAMC */
+
+#define AT91RM92_SDRAMC_BASE 0xfffff90
+#define AT91RM92_SDRAMC_MR 0x00
+#define AT91RM92_SDRAMC_MR_MODE_NORMAL 0
+#define AT91RM92_SDRAMC_MR_MODE_NOP 1
+#define AT91RM92_SDRAMC_MR_MODE_PRECHARGE 2
+#define AT91RM92_SDRAMC_MR_MODE_LOAD_MODE_REGISTER 3
+#define AT91RM92_SDRAMC_MR_MODE_REFRESH 4
+#define AT91RM92_SDRAMC_MR_DBW_16 0x10
+#define AT91RM92_SDRAMC_TR 0x04
+#define AT91RM92_SDRAMC_CR 0x08
+#define AT91RM92_SDRAMC_CR_NC_8 0x0
+#define AT91RM92_SDRAMC_CR_NC_9 0x1
+#define AT91RM92_SDRAMC_CR_NC_10 0x2
+#define AT91RM92_SDRAMC_CR_NC_11 0x3
+#define AT91RM92_SDRAMC_CR_NC_MASK 0x00000003
+#define AT91RM92_SDRAMC_CR_NR_11 0x0
+#define AT91RM92_SDRAMC_CR_NR_12 0x4
+#define AT91RM92_SDRAMC_CR_NR_13 0x8
+#define AT91RM92_SDRAMC_CR_NR_RES 0xc
+#define AT91RM92_SDRAMC_CR_NR_MASK 0x0000000c
+#define AT91RM92_SDRAMC_CR_NB_2 0x00
+#define AT91RM92_SDRAMC_CR_NB_4 0x10
+#define AT91RM92_SDRAMC_CR_NB_MASK 0x00000010
+#define AT91RM92_SDRAMC_CR_NCAS_MASK 0x00000060
+#define AT91RM92_SDRAMC_CR_TWR_MASK 0x00000780
+#define AT91RM92_SDRAMC_CR_TRC_MASK 0x00007800
+#define AT91RM92_SDRAMC_CR_TRP_MASK 0x00078000
+#define AT91RM92_SDRAMC_CR_TRCD_MASK 0x00780000
+#define AT91RM92_SDRAMC_CR_TRAS_MASK 0x07800000
+#define AT91RM92_SDRAMC_CR_TXSR_MASK 0x78000000
+#define AT91RM92_SDRAMC_SRR 0x0c
+#define AT91RM92_SDRAMC_LPR 0x10
+#define AT91RM92_SDRAMC_IER 0x14
+#define AT91RM92_SDRAMC_IDR 0x18
+#define AT91RM92_SDRAMC_IMR 0x1c
+#define AT91RM92_SDRAMC_ISR 0x20
+#define AT91RM92_SDRAMC_IER_RES 0x1
+
+#endif /* AT91RM92REG_H_ */
Property changes on: trunk/sys/arm/at91/at91rm92reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91sam9260.c
===================================================================
--- trunk/sys/arm/at91/at91sam9260.c (rev 0)
+++ trunk/sys/arm/at91/at91sam9260.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,218 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91sam9260.c 266087 2014-05-14 20:31:54Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91soc.h>
+#include <arm/at91/at91_aicreg.h>
+#include <arm/at91/at91sam9260reg.h>
+#include <arm/at91/at91_pitreg.h>
+#include <arm/at91/at91_pmcreg.h>
+#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_rstreg.h>
+
+/*
+ * Standard priority levels for the system. 0 is lowest and 7 is highest.
+ * These values are the ones Atmel uses for its Linux port
+ */
+static const int at91_irq_prio[32] =
+{
+ 7, /* Advanced Interrupt Controller */
+ 7, /* System Peripherals */
+ 1, /* Parallel IO Controller A */
+ 1, /* Parallel IO Controller B */
+ 1, /* Parallel IO Controller C */
+ 0, /* Analog-to-Digital Converter */
+ 5, /* USART 0 */
+ 5, /* USART 1 */
+ 5, /* USART 2 */
+ 0, /* Multimedia Card Interface */
+ 2, /* USB Device Port */
+ 6, /* Two-Wire Interface */
+ 5, /* Serial Peripheral Interface 0 */
+ 5, /* Serial Peripheral Interface 1 */
+ 5, /* Serial Synchronous Controller */
+ 0, /* (reserved) */
+ 0, /* (reserved) */
+ 0, /* Timer Counter 0 */
+ 0, /* Timer Counter 1 */
+ 0, /* Timer Counter 2 */
+ 2, /* USB Host port */
+ 3, /* Ethernet */
+ 0, /* Image Sensor Interface */
+ 5, /* USART 3 */
+ 5, /* USART 4 */
+ 5, /* USART 5 */
+ 0, /* Timer Counter 3 */
+ 0, /* Timer Counter 4 */
+ 0, /* Timer Counter 5 */
+ 0, /* Advanced Interrupt Controller IRQ0 */
+ 0, /* Advanced Interrupt Controller IRQ1 */
+ 0, /* Advanced Interrupt Controller IRQ2 */
+};
+
+static const uint32_t at91_pio_base[] = {
+ AT91SAM9260_PIOA_BASE,
+ AT91SAM9260_PIOB_BASE,
+ AT91SAM9260_PIOC_BASE,
+};
+
+#define DEVICE(_name, _id, _unit) \
+ { \
+ _name, _unit, \
+ AT91SAM9260_ ## _id ##_BASE, \
+ AT91SAM9260_ ## _id ## _SIZE, \
+ AT91SAM9260_IRQ_ ## _id \
+ }
+
+static const struct cpu_devs at91_devs[] =
+{
+ DEVICE("at91_pmc", PMC, 0),
+ DEVICE("at91_wdt", WDT, 0),
+ DEVICE("at91_rst", RSTC, 0),
+ DEVICE("at91_pit", PIT, 0),
+ DEVICE("at91_pio", PIOA, 0),
+ DEVICE("at91_pio", PIOB, 1),
+ DEVICE("at91_pio", PIOC, 2),
+ DEVICE("at91_twi", TWI, 0),
+ DEVICE("at91_mci", MCI, 0),
+ DEVICE("uart", DBGU, 0),
+ DEVICE("uart", USART0, 1),
+ DEVICE("uart", USART1, 2),
+ DEVICE("uart", USART2, 3),
+ DEVICE("uart", USART3, 4),
+ DEVICE("uart", USART4, 5),
+ DEVICE("uart", USART5, 6),
+ DEVICE("spi", SPI0, 0),
+ DEVICE("spi", SPI1, 1),
+ DEVICE("ate", EMAC, 0),
+ DEVICE("macb", EMAC, 0),
+ DEVICE("nand", NAND, 0),
+ DEVICE("ohci", OHCI, 0),
+ { 0, 0, 0, 0, 0 }
+};
+
+/*
+ * The following is unused currently since we don't ever set the PLLA
+ * frequency of the device.
+ */
+static uint32_t
+at91_pll_outa(int freq)
+{
+ uint32_t outa = 0;
+
+ /*
+ * Set OUTA, per the data sheet. See Table 40-15 titled
+ * PLLA Characteristics in the SAM9260 doc.
+ */
+
+ if (freq > 155000000)
+ outa = 2 << 14;
+ return ((1 << 29) | outa);
+}
+
+static uint32_t
+at91_pll_outb(int freq)
+{
+
+ return (1 << 14);
+}
+
+static void
+at91_clock_init(void)
+{
+ struct at91_pmc_clock *clk;
+
+ /* Update USB device port clock info */
+ clk = at91_pmc_clock_ref("udpck");
+ clk->pmc_mask = PMC_SCER_UDP_SAM9;
+ at91_pmc_clock_deref(clk);
+
+ /* Update USB host port clock info */
+ clk = at91_pmc_clock_ref("uhpck");
+ clk->pmc_mask = PMC_SCER_UHP_SAM9;
+ at91_pmc_clock_deref(clk);
+
+ /* Each SOC has different PLL contraints */
+ clk = at91_pmc_clock_ref("plla");
+ clk->pll_min_in = SAM9260_PLL_A_MIN_IN_FREQ; /* 1 MHz */
+ clk->pll_max_in = SAM9260_PLL_A_MAX_IN_FREQ; /* 32 MHz */
+ clk->pll_min_out = SAM9260_PLL_A_MIN_OUT_FREQ; /* 80 MHz */
+ clk->pll_max_out = SAM9260_PLL_A_MAX_OUT_FREQ; /* 240 MHz */
+ clk->pll_mul_shift = SAM9260_PLL_A_MUL_SHIFT;
+ clk->pll_mul_mask = SAM9260_PLL_A_MUL_MASK;
+ clk->pll_div_shift = SAM9260_PLL_A_DIV_SHIFT;
+ clk->pll_div_mask = SAM9260_PLL_A_DIV_MASK;
+ clk->set_outb = at91_pll_outa;
+ at91_pmc_clock_deref(clk);
+
+ /*
+ * Fudge MAX pll in frequence down below 3.0 MHz to ensure
+ * PMC alogrithm choose the divisor that causes the input clock
+ * to be near the optimal 2 MHz per datasheet. We know
+ * we are going to be using this for the USB clock at 96 MHz.
+ * Causes no extra frequency deviation for all recomended crystal
+ * values. See Note 1, table 40-16 SAM9260 doc.
+ */
+ clk = at91_pmc_clock_ref("pllb");
+ clk->pll_min_in = SAM9260_PLL_B_MIN_IN_FREQ; /* 1 MHz */
+ clk->pll_max_in = SAM9260_PLL_B_MAX_IN_FREQ; /* 5 MHz */
+ clk->pll_max_in = 2999999; /* ~3 MHz */
+ clk->pll_min_out = SAM9260_PLL_B_MIN_OUT_FREQ; /* 70 MHz */
+ clk->pll_max_out = SAM9260_PLL_B_MAX_OUT_FREQ; /* 130 MHz */
+ clk->pll_mul_shift = SAM9260_PLL_B_MUL_SHIFT;
+ clk->pll_mul_mask = SAM9260_PLL_B_MUL_MASK;
+ clk->pll_div_shift = SAM9260_PLL_B_DIV_SHIFT;
+ clk->pll_div_mask = SAM9260_PLL_B_DIV_MASK;
+ clk->set_outb = at91_pll_outb;
+ at91_pmc_clock_deref(clk);
+}
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_pit_delay,
+ .soc_reset = at91_rst_cpu_reset,
+ .soc_clock_init = at91_clock_init,
+ .soc_irq_prio = at91_irq_prio,
+ .soc_children = at91_devs,
+ .soc_pio_base = at91_pio_base,
+ .soc_pio_count = nitems(at91_pio_base),
+};
+
+AT91_SOC(AT91_T_SAM9260, &soc_data);
Property changes on: trunk/sys/arm/at91/at91sam9260.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91sam9260reg.h
===================================================================
--- trunk/sys/arm/at91/at91sam9260reg.h (rev 0)
+++ trunk/sys/arm/at91/at91sam9260reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,304 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91sam9260reg.h 266110 2014-05-15 02:41:23Z ian $ */
+
+#ifndef AT91SAM9260REG_H_
+#define AT91SAM9260REG_H_
+
+/* Chip Specific limits */
+#define SAM9260_PLL_A_MIN_IN_FREQ 1000000 /* 1 Mhz */
+#define SAM9260_PLL_A_MAX_IN_FREQ 32000000 /* 32 Mhz */
+#define SAM9260_PLL_A_MIN_OUT_FREQ 80000000 /* 80 Mhz */
+#define SAM9260_PLL_A_MAX_OUT_FREQ 240000000 /* 240 Mhz */
+#define SAM9260_PLL_A_MUL_SHIFT 16
+#define SAM9260_PLL_A_MUL_MASK 0x3FF
+#define SAM9260_PLL_A_DIV_SHIFT 0
+#define SAM9260_PLL_A_DIV_MASK 0xFF
+
+#define SAM9260_PLL_B_MIN_IN_FREQ 1000000 /* 1 Mhz */
+#define SAM9260_PLL_B_MAX_IN_FREQ 5000000 /* 5 Mhz */
+#define SAM9260_PLL_B_MIN_OUT_FREQ 70000000 /* 70 Mhz */
+#define SAM9260_PLL_B_MAX_OUT_FREQ 130000000 /* 130 Mhz */
+#define SAM9260_PLL_B_MUL_SHIFT 16
+#define SAM9260_PLL_B_MUL_MASK 0x3FF
+#define SAM9260_PLL_B_DIV_SHIFT 0
+#define SAM9260_PLL_B_DIV_MASK 0xFF
+
+/*
+ * Memory map, from datasheet :
+ * 0x00000000 - 0x0ffffffff : Internal Memories
+ * 0x10000000 - 0x1ffffffff : Chip Select 0
+ * 0x20000000 - 0x2ffffffff : Chip Select 1
+ * 0x30000000 - 0x3ffffffff : Chip Select 2
+ * 0x40000000 - 0x4ffffffff : Chip Select 3
+ * 0x50000000 - 0x5ffffffff : Chip Select 4
+ * 0x60000000 - 0x6ffffffff : Chip Select 5
+ * 0x70000000 - 0x7ffffffff : Chip Select 6
+ * 0x80000000 - 0x8ffffffff : Chip Select 7
+ * 0x90000000 - 0xeffffffff : Undefined (Abort)
+ * 0xf0000000 - 0xfffffffff : Peripherals
+ */
+
+#define AT91_CHIPSELECT_0 0x10000000
+#define AT91_CHIPSELECT_1 0x20000000
+#define AT91_CHIPSELECT_2 0x30000000
+#define AT91_CHIPSELECT_3 0x40000000
+#define AT91_CHIPSELECT_4 0x50000000
+#define AT91_CHIPSELECT_5 0x60000000
+#define AT91_CHIPSELECT_6 0x70000000
+#define AT91_CHIPSELECT_7 0x80000000
+
+
+#define AT91SAM9260_EMAC_BASE 0xffc4000
+#define AT91SAM9260_EMAC_SIZE 0x4000
+
+#define AT91SAM9260_RSTC_BASE 0xffffd00
+#define AT91SAM9260_RSTC_SIZE 0x10
+
+#define RSTC_CR 0
+#define RSTC_PROCRST (1 << 0)
+#define RSTC_PERRST (1 << 2)
+#define RSTC_KEY (0xa5 << 24)
+
+/* USART*/
+
+#define AT91SAM9260_USART_SIZE 0x4000
+#define AT91SAM9260_USART0_BASE 0xffb0000
+#define AT91SAM9260_USART0_PDC 0xffb0100
+#define AT91SAM9260_USART0_SIZE AT91SAM9260_USART_SIZE
+#define AT91SAM9260_USART1_BASE 0xffb4000
+#define AT91SAM9260_USART1_PDC 0xffb4100
+#define AT91SAM9260_USART1_SIZE AT91SAM9260_USART_SIZE
+#define AT91SAM9260_USART2_BASE 0xffb8000
+#define AT91SAM9260_USART2_PDC 0xffb8100
+#define AT91SAM9260_USART2_SIZE AT91SAM9260_USART_SIZE
+#define AT91SAM9260_USART3_BASE 0xffd0000
+#define AT91SAM9260_USART3_PDC 0xffd0100
+#define AT91SAM9260_USART3_SIZE AT91SAM9260_USART_SIZE
+#define AT91SAM9260_USART4_BASE 0xffd4000
+#define AT91SAM9260_USART4_PDC 0xffd4100
+#define AT91SAM9260_USART4_SIZE AT91SAM9260_USART_SIZE
+#define AT91SAM9260_USART5_BASE 0xffd8000
+#define AT91SAM9260_USART5_PDC 0xffd8100
+#define AT91SAM9260_USART5_SIZE AT91SAM9260_USART_SIZE
+
+/*TC*/
+#define AT91SAM9260_TC0_BASE 0xffa0000
+#define AT91SAM9260_TC0_SIZE 0x4000
+#define AT91SAM9260_TC0C0_BASE 0xffa0000
+#define AT91SAM9260_TC0C1_BASE 0xffa0040
+#define AT91SAM9260_TC0C2_BASE 0xffa0080
+
+#define AT91SAM9260_TC1_BASE 0xffdc000
+#define AT91SAM9260_TC1_SIZE 0x4000
+
+/*SPI*/
+
+#define AT91SAM9260_SPI0_BASE 0xffc8000
+
+#define AT91SAM9260_SPI0_SIZE 0x4000
+#define AT91SAM9260_IRQ_SPI0 12
+
+#define AT91SAM9260_SPI1_BASE 0xffcc000
+#define AT91SAM9260_SPI1_SIZE 0x4000
+#define AT91SAM9260_IRQ_SPI1 13
+
+/* System Registers */
+#define AT91SAM9260_SYS_BASE 0xffff000
+#define AT91SAM9260_SYS_SIZE 0x1000
+
+#define AT91SAM9260_MATRIX_BASE 0xfffee00
+#define AT91SAM9260_MATRIX_SIZE 0x1000
+#define AT91SAM9260_EBICSA 0x011C
+
+#define AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA (1 << 3)
+
+#define AT91SAM9260_DBGU_BASE 0xffff200
+#define AT91SAM9260_DBGU_SIZE 0x200
+
+/*
+ * PIO
+ */
+#define AT91SAM9260_PIOA_BASE 0xffff400
+#define AT91SAM9260_PIOA_SIZE 0x200
+#define AT91SAM9260_PIOB_BASE 0xffff600
+#define AT91SAM9260_PIOB_SIZE 0x200
+#define AT91SAM9260_PIOC_BASE 0xffff800
+#define AT91SAM9260_PIOC_SIZE 0x200
+
+#define AT91RM92_PMC_BASE 0xffffc00
+#define AT91RM92_PMC_SIZE 0x100
+/* IRQs : */
+/*
+ * 0: AIC
+ * 1: System peripheral (System timer, RTC, DBGU)
+ * 2: PIO Controller A
+ * 3: PIO Controller B
+ * 4: PIO Controller C
+ * 5: ADC
+ * 6: USART 0
+ * 7: USART 1
+ * 8: USART 2
+ * 9: MMC Interface
+ * 10: USB device port
+ * 11: Two-wirte interface
+ * 12: SPI 0
+ * 13: SPI 1
+ * 14: SSC
+ * 15: - (reserved)
+ * 16: - (reserved)
+ * 17: Timer Counter 0
+ * 18: Timer Counter 1
+ * 19: Timer Counter 2
+ * 20: USB Host port
+ * 21: EMAC
+ * 22: ISI
+ * 23: USART 3
+ * 24: USART 4
+ * 25: USART 2
+ * 26: Timer Counter 3
+ * 27: Timer Counter 4
+ * 28: Timer Counter 5
+ * 29: AIC IRQ0
+ * 30: AIC IRQ1
+ * 31: AIC IRQ2
+ */
+
+#define AT91SAM9260_IRQ_SYSTEM 1
+#define AT91SAM9260_IRQ_PIOA 2
+#define AT91SAM9260_IRQ_PIOB 3
+#define AT91SAM9260_IRQ_PIOC 4
+#define AT91SAM9260_IRQ_USART0 6
+#define AT91SAM9260_IRQ_USART1 7
+#define AT91SAM9260_IRQ_USART2 8
+#define AT91SAM9260_IRQ_MCI 9
+#define AT91SAM9260_IRQ_UDP 10
+#define AT91SAM9260_IRQ_TWI 11
+#define AT91SAM9260_IRQ_SPI0 12
+#define AT91SAM9260_IRQ_SPI1 13
+#define AT91SAM9260_IRQ_SSC0 14
+#define AT91SAM9260_IRQ_SSC1 15
+#define AT91SAM9260_IRQ_SSC2 16
+#define AT91SAM9260_IRQ_TC0 17
+#define AT91SAM9260_IRQ_TC1 18
+#define AT91SAM9260_IRQ_TC2 19
+#define AT91SAM9260_IRQ_UHP 20
+#define AT91SAM9260_IRQ_EMAC 21
+#define AT91SAM9260_IRQ_USART3 23
+#define AT91SAM9260_IRQ_USART4 24
+#define AT91SAM9260_IRQ_USART5 25
+#define AT91SAM9260_IRQ_AICBASE 29
+
+/* Alias */
+#define AT91SAM9260_IRQ_DBGU AT91SAM9260_IRQ_SYSTEM
+#define AT91SAM9260_IRQ_PMC AT91SAM9260_IRQ_SYSTEM
+#define AT91SAM9260_IRQ_WDT AT91SAM9260_IRQ_SYSTEM
+#define AT91SAM9260_IRQ_PIT AT91SAM9260_IRQ_SYSTEM
+#define AT91SAM9260_IRQ_RSTC AT91SAM9260_IRQ_SYSTEM
+#define AT91SAM9260_IRQ_OHCI AT91SAM9260_IRQ_UHP
+#define AT91SAM9260_IRQ_NAND (-1)
+
+#define AT91SAM9260_AIC_BASE 0xffff000
+#define AT91SAM9260_AIC_SIZE 0x200
+
+/* Timer */
+
+#define AT91SAM9260_WDT_BASE 0xffffd40
+#define AT91SAM9260_WDT_SIZE 0x10
+
+#define AT91SAM9260_PIT_BASE 0xffffd30
+#define AT91SAM9260_PIT_SIZE 10
+
+#define AT91SAM9260_SMC_BASE 0xfffec00
+#define AT91SAM9260_SMC_SIZE 0x200
+
+#define AT91SAM9260_PMC_BASE 0xffffc00
+#define AT91SAM9260_PMC_SIZE 0x100
+
+#define AT91SAM9260_UDP_BASE 0xffa4000
+#define AT91SAM9260_UDP_SIZE 0x4000
+
+#define AT91SAM9260_MCI_BASE 0xffa8000
+#define AT91SAM9260_MCI_SIZE 0x4000
+
+#define AT91SAM9260_TWI_BASE 0xffaC000
+#define AT91SAM9260_TWI_SIZE 0x4000
+
+/* XXX Needs to be carfully coordinated with
+ * other * soc's so phyical and vm address
+ * mapping are unique. XXX
+ */
+#define AT91SAM9260_OHCI_VA_BASE 0xdfc00000
+#define AT91SAM9260_OHCI_BASE 0x00500000
+#define AT91SAM9260_OHCI_SIZE 0x00100000
+
+#define AT91SAM9260_NAND_VA_BASE 0xe0000000
+#define AT91SAM9260_NAND_BASE 0x40000000
+#define AT91SAM9260_NAND_SIZE 0x10000000
+
+
+/* SDRAMC */
+#define AT91SAM9260_SDRAMC_BASE 0xfffea00
+#define AT91SAM9260_SDRAMC_MR 0x00
+#define AT91SAM9260_SDRAMC_MR_MODE_NORMAL 0
+#define AT91SAM9260_SDRAMC_MR_MODE_NOP 1
+#define AT91SAM9260_SDRAMC_MR_MODE_PRECHARGE 2
+#define AT91SAM9260_SDRAMC_MR_MODE_LOAD_MODE_REGISTER 3
+#define AT91SAM9260_SDRAMC_MR_MODE_REFRESH 4
+#define AT91SAM9260_SDRAMC_TR 0x04
+#define AT91SAM9260_SDRAMC_CR 0x08
+#define AT91SAM9260_SDRAMC_CR_NC_8 0x0
+#define AT91SAM9260_SDRAMC_CR_NC_9 0x1
+#define AT91SAM9260_SDRAMC_CR_NC_10 0x2
+#define AT91SAM9260_SDRAMC_CR_NC_11 0x3
+#define AT91SAM9260_SDRAMC_CR_NC_MASK 0x00000003
+#define AT91SAM9260_SDRAMC_CR_NR_11 0x0
+#define AT91SAM9260_SDRAMC_CR_NR_12 0x4
+#define AT91SAM9260_SDRAMC_CR_NR_13 0x8
+#define AT91SAM9260_SDRAMC_CR_NR_RES 0xc
+#define AT91SAM9260_SDRAMC_CR_NR_MASK 0x0000000c
+#define AT91SAM9260_SDRAMC_CR_NB_2 0x00
+#define AT91SAM9260_SDRAMC_CR_NB_4 0x10
+#define AT91SAM9260_SDRAMC_CR_DBW_16 0x80
+#define AT91SAM9260_SDRAMC_CR_NB_MASK 0x00000010
+#define AT91SAM9260_SDRAMC_CR_NCAS_MASK 0x00000060
+#define AT91SAM9260_SDRAMC_CR_TWR_MASK 0x00000780
+#define AT91SAM9260_SDRAMC_CR_TRC_MASK 0x00007800
+#define AT91SAM9260_SDRAMC_CR_TRP_MASK 0x00078000
+#define AT91SAM9260_SDRAMC_CR_TRCD_MASK 0x00780000
+#define AT91SAM9260_SDRAMC_CR_TRAS_MASK 0x07800000
+#define AT91SAM9260_SDRAMC_CR_TXSR_MASK 0x78000000
+#define AT91SAM9260_SDRAMC_HSR 0x0c
+#define AT91SAM9260_SDRAMC_LPR 0x10
+#define AT91SAM9260_SDRAMC_IER 0x14
+#define AT91SAM9260_SDRAMC_IDR 0x18
+#define AT91SAM9260_SDRAMC_IMR 0x1c
+#define AT91SAM9260_SDRAMC_ISR 0x20
+#define AT91SAM9260_SDRAMC_MDR 0x24
+
+#endif /* AT91SAM9260REG_H_*/
+
Property changes on: trunk/sys/arm/at91/at91sam9260reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91sam9g20.c
===================================================================
--- trunk/sys/arm/at91/at91sam9g20.c (rev 0)
+++ trunk/sys/arm/at91/at91sam9g20.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,184 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91sam9g20.c 266277 2014-05-17 00:53:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91soc.h>
+#include <arm/at91/at91_aicreg.h>
+#include <arm/at91/at91sam9g20reg.h>
+#include <arm/at91/at91_pitreg.h>
+#include <arm/at91/at91_pmcreg.h>
+#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_rstreg.h>
+
+/*
+ * Standard priority levels for the system. 0 is lowest and 7 is highest.
+ * These values are the ones Atmel uses for its Linux port
+ */
+static const int at91_irq_prio[32] =
+{
+ 7, /* Advanced Interrupt Controller */
+ 7, /* System Peripherals */
+ 1, /* Parallel IO Controller A */
+ 1, /* Parallel IO Controller B */
+ 1, /* Parallel IO Controller C */
+ 0, /* Analog-to-Digital Converter */
+ 5, /* USART 0 */
+ 5, /* USART 1 */
+ 5, /* USART 2 */
+ 0, /* Multimedia Card Interface */
+ 2, /* USB Device Port */
+ 6, /* Two-Wire Interface */
+ 5, /* Serial Peripheral Interface 0 */
+ 5, /* Serial Peripheral Interface 1 */
+ 5, /* Serial Synchronous Controller */
+ 0, /* (reserved) */
+ 0, /* (reserved) */
+ 0, /* Timer Counter 0 */
+ 0, /* Timer Counter 1 */
+ 0, /* Timer Counter 2 */
+ 2, /* USB Host port */
+ 3, /* Ethernet */
+ 0, /* Image Sensor Interface */
+ 5, /* USART 3 */
+ 5, /* USART 4 */
+ 5, /* USART 5 */
+ 0, /* Timer Counter 3 */
+ 0, /* Timer Counter 4 */
+ 0, /* Timer Counter 5 */
+ 0, /* Advanced Interrupt Controller IRQ0 */
+ 0, /* Advanced Interrupt Controller IRQ1 */
+ 0, /* Advanced Interrupt Controller IRQ2 */
+};
+
+static const uint32_t at91_pio_base[] = {
+ AT91SAM9G20_PIOA_BASE,
+ AT91SAM9G20_PIOB_BASE,
+ AT91SAM9G20_PIOC_BASE,
+};
+
+#define DEVICE(_name, _id, _unit) \
+ { \
+ _name, _unit, \
+ AT91SAM9G20_ ## _id ##_BASE, \
+ AT91SAM9G20_ ## _id ## _SIZE, \
+ AT91SAM9G20_IRQ_ ## _id \
+ }
+
+static const struct cpu_devs at91_devs[] =
+{
+ DEVICE("at91_aic", AIC, 0),
+ DEVICE("at91_pmc", PMC, 0),
+ DEVICE("at91_wdt", WDT, 0),
+ DEVICE("at91_rst", RSTC, 0),
+ DEVICE("at91_pit", PIT, 0),
+ DEVICE("at91_pio", PIOA, 0),
+ DEVICE("at91_pio", PIOB, 1),
+ DEVICE("at91_pio", PIOC, 2),
+ DEVICE("at91_twi", TWI, 0),
+ DEVICE("at91_mci", MCI, 0),
+ DEVICE("uart", DBGU, 0),
+ DEVICE("uart", USART0, 1),
+ DEVICE("uart", USART1, 2),
+ DEVICE("uart", USART2, 3),
+ DEVICE("uart", USART3, 4),
+ DEVICE("uart", USART4, 5),
+ DEVICE("uart", USART5, 6),
+ DEVICE("spi", SPI0, 0),
+ DEVICE("spi", SPI1, 1),
+ DEVICE("ate", EMAC, 0),
+ DEVICE("macb", EMAC, 0),
+ DEVICE("nand", NAND, 0),
+ DEVICE("ohci", OHCI, 0),
+ { 0, 0, 0, 0, 0 }
+};
+
+static void
+at91_clock_init(void)
+{
+ struct at91_pmc_clock *clk;
+
+ /* Update USB device port clock info */
+ clk = at91_pmc_clock_ref("udpck");
+ clk->pmc_mask = PMC_SCER_UDP_SAM9;
+ at91_pmc_clock_deref(clk);
+
+ /* Update USB host port clock info */
+ clk = at91_pmc_clock_ref("uhpck");
+ clk->pmc_mask = PMC_SCER_UHP_SAM9;
+ at91_pmc_clock_deref(clk);
+
+ /* Each SOC has different PLL contraints */
+ clk = at91_pmc_clock_ref("plla");
+ clk->pll_min_in = SAM9G20_PLL_A_MIN_IN_FREQ; /* 2 MHz */
+ clk->pll_max_in = SAM9G20_PLL_A_MAX_IN_FREQ; /* 32 MHz */
+ clk->pll_min_out = SAM9G20_PLL_A_MIN_OUT_FREQ; /* 400 MHz */
+ clk->pll_max_out = SAM9G20_PLL_A_MAX_OUT_FREQ; /* 800 MHz */
+ clk->pll_mul_shift = SAM9G20_PLL_A_MUL_SHIFT;
+ clk->pll_mul_mask = SAM9G20_PLL_A_MUL_MASK;
+ clk->pll_div_shift = SAM9G20_PLL_A_DIV_SHIFT;
+ clk->pll_div_mask = SAM9G20_PLL_A_DIV_MASK;
+ clk->set_outb = at91_pmc_800mhz_plla_outb;
+ at91_pmc_clock_deref(clk);
+
+ clk = at91_pmc_clock_ref("pllb");
+ clk->pll_min_in = SAM9G20_PLL_B_MIN_IN_FREQ; /* 2 MHz */
+ clk->pll_max_in = SAM9G20_PLL_B_MAX_IN_FREQ; /* 32 MHz */
+ clk->pll_min_out = SAM9G20_PLL_B_MIN_OUT_FREQ; /* 30 MHz */
+ clk->pll_max_out = SAM9G20_PLL_B_MAX_OUT_FREQ; /* 100 MHz */
+ clk->pll_mul_shift = SAM9G20_PLL_B_MUL_SHIFT;
+ clk->pll_mul_mask = SAM9G20_PLL_B_MUL_MASK;
+ clk->pll_div_shift = SAM9G20_PLL_B_DIV_SHIFT;
+ clk->pll_div_mask = SAM9G20_PLL_B_DIV_MASK;
+ clk->set_outb = at91_pmc_800mhz_pllb_outb;
+ at91_pmc_clock_deref(clk);
+}
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_pit_delay,
+ .soc_reset = at91_rst_cpu_reset,
+ .soc_clock_init = at91_clock_init,
+ .soc_irq_prio = at91_irq_prio,
+ .soc_children = at91_devs,
+ .soc_pio_base = at91_pio_base,
+ .soc_pio_count = nitems(at91_pio_base),
+};
+
+AT91_SOC(AT91_T_SAM9G20, &soc_data);
Property changes on: trunk/sys/arm/at91/at91sam9g20.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91sam9g20reg.h
===================================================================
--- trunk/sys/arm/at91/at91sam9g20reg.h (rev 0)
+++ trunk/sys/arm/at91/at91sam9g20reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,305 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91sam9g20reg.h 266277 2014-05-17 00:53:12Z ian $ */
+
+#ifndef AT91SAM9G20REG_H_
+#define AT91SAM9G20REG_H_
+
+/* Chip Specific limits */
+#define SAM9G20_PLL_A_MIN_IN_FREQ 2000000 /* 2 Mhz */
+#define SAM9G20_PLL_A_MAX_IN_FREQ 32000000 /* 32 Mhz */
+#define SAM9G20_PLL_A_MIN_OUT_FREQ 400000000 /* 400 Mhz */
+#define SAM9G20_PLL_A_MAX_OUT_FREQ 800000000 /* 800 Mhz */
+#define SAM9G20_PLL_A_MUL_SHIFT 16
+#define SAM9G20_PLL_A_MUL_MASK 0xFF
+#define SAM9G20_PLL_A_DIV_SHIFT 0
+#define SAM9G20_PLL_A_DIV_MASK 0xFF
+
+#define SAM9G20_PLL_B_MIN_IN_FREQ 2000000 /* 2 Mhz */
+#define SAM9G20_PLL_B_MAX_IN_FREQ 32000000 /* 32 Mhz */
+#define SAM9G20_PLL_B_MIN_OUT_FREQ 30000000 /* 30 Mhz */
+#define SAM9G20_PLL_B_MAX_OUT_FREQ 100000000 /* 100 Mhz */
+#define SAM9G20_PLL_B_MUL_SHIFT 16
+#define SAM9G20_PLL_B_MUL_MASK 0x3F
+#define SAM9G20_PLL_B_DIV_SHIFT 0
+#define SAM9G20_PLL_B_DIV_MASK 0xFF
+
+/*
+ * Memory map, from datasheet :
+ * 0x00000000 - 0x0ffffffff : Internal Memories
+ * 0x10000000 - 0x1ffffffff : Chip Select 0
+ * 0x20000000 - 0x2ffffffff : Chip Select 1
+ * 0x30000000 - 0x3ffffffff : Chip Select 2
+ * 0x40000000 - 0x4ffffffff : Chip Select 3
+ * 0x50000000 - 0x5ffffffff : Chip Select 4
+ * 0x60000000 - 0x6ffffffff : Chip Select 5
+ * 0x70000000 - 0x7ffffffff : Chip Select 6
+ * 0x80000000 - 0x8ffffffff : Chip Select 7
+ * 0x90000000 - 0xeffffffff : Undefined (Abort)
+ * 0xf0000000 - 0xfffffffff : Peripherals
+ */
+
+#define AT91_CHIPSELECT_0 0x10000000
+#define AT91_CHIPSELECT_1 0x20000000
+#define AT91_CHIPSELECT_2 0x30000000
+#define AT91_CHIPSELECT_3 0x40000000
+#define AT91_CHIPSELECT_4 0x50000000
+#define AT91_CHIPSELECT_5 0x60000000
+#define AT91_CHIPSELECT_6 0x70000000
+#define AT91_CHIPSELECT_7 0x80000000
+
+
+#define AT91SAM9G20_EMAC_BASE 0xffc4000
+#define AT91SAM9G20_EMAC_SIZE 0x4000
+
+#define AT91SAM9G20_RSTC_BASE 0xffffd00
+#define AT91SAM9G20_RSTC_SIZE 0x10
+
+#define RSTC_CR 0
+#define RSTC_PROCRST (1 << 0)
+#define RSTC_PERRST (1 << 2)
+#define RSTC_KEY (0xa5 << 24)
+
+/* USART*/
+
+#define AT91SAM9G20_USART_SIZE 0x4000
+#define AT91SAM9G20_USART0_BASE 0xffb0000
+#define AT91SAM9G20_USART0_PDC 0xffb0100
+#define AT91SAM9G20_USART0_SIZE AT91SAM9G20_USART_SIZE
+#define AT91SAM9G20_USART1_BASE 0xffb4000
+#define AT91SAM9G20_USART1_PDC 0xffb4100
+#define AT91SAM9G20_USART1_SIZE AT91SAM9G20_USART_SIZE
+#define AT91SAM9G20_USART2_BASE 0xffb8000
+#define AT91SAM9G20_USART2_PDC 0xffb8100
+#define AT91SAM9G20_USART2_SIZE AT91SAM9G20_USART_SIZE
+#define AT91SAM9G20_USART3_BASE 0xffd0000
+#define AT91SAM9G20_USART3_PDC 0xffd0100
+#define AT91SAM9G20_USART3_SIZE AT91SAM9G20_USART_SIZE
+#define AT91SAM9G20_USART4_BASE 0xffd4000
+#define AT91SAM9G20_USART4_PDC 0xffd4100
+#define AT91SAM9G20_USART4_SIZE AT91SAM9G20_USART_SIZE
+#define AT91SAM9G20_USART5_BASE 0xffd8000
+#define AT91SAM9G20_USART5_PDC 0xffd8100
+#define AT91SAM9G20_USART5_SIZE AT91SAM9G20_USART_SIZE
+
+/*TC*/
+#define AT91SAM9G20_TC0_BASE 0xffa0000
+#define AT91SAM9G20_TC0_SIZE 0x4000
+#define AT91SAM9G20_TC0C0_BASE 0xffa0000
+#define AT91SAM9G20_TC0C1_BASE 0xffa0040
+#define AT91SAM9G20_TC0C2_BASE 0xffa0080
+
+#define AT91SAM9G20_TC1_BASE 0xffdc000
+#define AT91SAM9G20_TC1_SIZE 0x4000
+
+/*SPI*/
+
+#define AT91SAM9G20_SPI0_BASE 0xffc8000
+
+#define AT91SAM9G20_SPI0_SIZE 0x4000
+#define AT91SAM9G20_IRQ_SPI0 12
+
+#define AT91SAM9G20_SPI1_BASE 0xffcc000
+#define AT91SAM9G20_SPI1_SIZE 0x4000
+#define AT91SAM9G20_IRQ_SPI1 13
+
+/* System Registers */
+#define AT91SAM9G20_SYS_BASE 0xffff000
+#define AT91SAM9G20_SYS_SIZE 0x1000
+
+#define AT91SAM9G20_MATRIX_BASE 0xfffee00
+#define AT91SAM9G20_MATRIX_SIZE 0x1000
+#define AT91SAM9G20_EBICSA 0x011C
+
+#define AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA (1 << 3)
+
+#define AT91SAM9G20_DBGU_BASE 0xffff200
+#define AT91SAM9G20_DBGU_SIZE 0x200
+
+/*
+ * PIO
+ */
+#define AT91SAM9G20_PIOA_BASE 0xffff400
+#define AT91SAM9G20_PIOA_SIZE 0x200
+#define AT91SAM9G20_PIOB_BASE 0xffff600
+#define AT91SAM9G20_PIOB_SIZE 0x200
+#define AT91SAM9G20_PIOC_BASE 0xffff800
+#define AT91SAM9G20_PIOC_SIZE 0x200
+
+#define AT91RM92_PMC_BASE 0xffffc00
+#define AT91RM92_PMC_SIZE 0x100
+/* IRQs : */
+/*
+ * 0: AIC
+ * 1: System peripheral (System timer, RTC, DBGU)
+ * 2: PIO Controller A
+ * 3: PIO Controller B
+ * 4: PIO Controller C
+ * 5: ADC
+ * 6: USART 0
+ * 7: USART 1
+ * 8: USART 2
+ * 9: MMC Interface
+ * 10: USB device port
+ * 11: Two-wirte interface
+ * 12: SPI 0
+ * 13: SPI 1
+ * 14: SSC
+ * 15: - (reserved)
+ * 16: - (reserved)
+ * 17: Timer Counter 0
+ * 18: Timer Counter 1
+ * 19: Timer Counter 2
+ * 20: USB Host port
+ * 21: EMAC
+ * 22: ISI
+ * 23: USART 3
+ * 24: USART 4
+ * 25: USART 2
+ * 26: Timer Counter 3
+ * 27: Timer Counter 4
+ * 28: Timer Counter 5
+ * 29: AIC IRQ0
+ * 30: AIC IRQ1
+ * 31: AIC IRQ2
+ */
+
+#define AT91SAM9G20_IRQ_SYSTEM 1
+#define AT91SAM9G20_IRQ_PIOA 2
+#define AT91SAM9G20_IRQ_PIOB 3
+#define AT91SAM9G20_IRQ_PIOC 4
+#define AT91SAM9G20_IRQ_USART0 6
+#define AT91SAM9G20_IRQ_USART1 7
+#define AT91SAM9G20_IRQ_USART2 8
+#define AT91SAM9G20_IRQ_MCI 9
+#define AT91SAM9G20_IRQ_UDP 10
+#define AT91SAM9G20_IRQ_TWI 11
+#define AT91SAM9G20_IRQ_SPI0 12
+#define AT91SAM9G20_IRQ_SPI1 13
+#define AT91SAM9G20_IRQ_SSC0 14
+#define AT91SAM9G20_IRQ_SSC1 15
+#define AT91SAM9G20_IRQ_SSC2 16
+#define AT91SAM9G20_IRQ_TC0 17
+#define AT91SAM9G20_IRQ_TC1 18
+#define AT91SAM9G20_IRQ_TC2 19
+#define AT91SAM9G20_IRQ_UHP 20
+#define AT91SAM9G20_IRQ_EMAC 21
+#define AT91SAM9G20_IRQ_USART3 23
+#define AT91SAM9G20_IRQ_USART4 24
+#define AT91SAM9G20_IRQ_USART5 25
+#define AT91SAM9G20_IRQ_AICBASE 29
+
+/* Alias */
+#define AT91SAM9G20_IRQ_DBGU AT91SAM9G20_IRQ_SYSTEM
+#define AT91SAM9G20_IRQ_PMC AT91SAM9G20_IRQ_SYSTEM
+#define AT91SAM9G20_IRQ_WDT AT91SAM9G20_IRQ_SYSTEM
+#define AT91SAM9G20_IRQ_PIT AT91SAM9G20_IRQ_SYSTEM
+#define AT91SAM9G20_IRQ_RSTC AT91SAM9G20_IRQ_SYSTEM
+#define AT91SAM9G20_IRQ_OHCI AT91SAM9G20_IRQ_UHP
+#define AT91SAM9G20_IRQ_NAND (-1)
+#define AT91SAM9G20_IRQ_AIC (-1)
+
+#define AT91SAM9G20_AIC_BASE 0xffff000
+#define AT91SAM9G20_AIC_SIZE 0x200
+
+/* Timer */
+
+#define AT91SAM9G20_WDT_BASE 0xffffd40
+#define AT91SAM9G20_WDT_SIZE 0x10
+
+#define AT91SAM9G20_PIT_BASE 0xffffd30
+#define AT91SAM9G20_PIT_SIZE 0x10
+
+#define AT91SAM9G20_SMC_BASE 0xfffec00
+#define AT91SAM9G20_SMC_SIZE 0x200
+
+#define AT91SAM9G20_PMC_BASE 0xffffc00
+#define AT91SAM9G20_PMC_SIZE 0x100
+
+#define AT91SAM9G20_UDP_BASE 0xffa4000
+#define AT91SAM9G20_UDP_SIZE 0x4000
+
+#define AT91SAM9G20_MCI_BASE 0xffa8000
+#define AT91SAM9G20_MCI_SIZE 0x4000
+
+#define AT91SAM9G20_TWI_BASE 0xffaC000
+#define AT91SAM9G20_TWI_SIZE 0x4000
+
+/* XXX Needs to be carfully coordinated with
+ * other * soc's so phyical and vm address
+ * mapping are unique. XXX
+ */
+#define AT91SAM9G20_OHCI_VA_BASE 0xdfc00000
+#define AT91SAM9G20_OHCI_BASE 0x00500000
+#define AT91SAM9G20_OHCI_SIZE 0x00100000
+
+#define AT91SAM9G20_NAND_VA_BASE 0xe0000000
+#define AT91SAM9G20_NAND_BASE 0x40000000
+#define AT91SAM9G20_NAND_SIZE 0x10000000
+
+/* SDRAMC */
+#define AT91SAM9G20_SDRAMC_BASE 0xfffea00
+#define AT91SAM9G20_SDRAMC_MR 0x00
+#define AT91SAM9G20_SDRAMC_MR_MODE_NORMAL 0
+#define AT91SAM9G20_SDRAMC_MR_MODE_NOP 1
+#define AT91SAM9G20_SDRAMC_MR_MODE_PRECHARGE 2
+#define AT91SAM9G20_SDRAMC_MR_MODE_LOAD_MODE_REGISTER 3
+#define AT91SAM9G20_SDRAMC_MR_MODE_REFRESH 4
+#define AT91SAM9G20_SDRAMC_TR 0x04
+#define AT91SAM9G20_SDRAMC_CR 0x08
+#define AT91SAM9G20_SDRAMC_CR_NC_8 0x0
+#define AT91SAM9G20_SDRAMC_CR_NC_9 0x1
+#define AT91SAM9G20_SDRAMC_CR_NC_10 0x2
+#define AT91SAM9G20_SDRAMC_CR_NC_11 0x3
+#define AT91SAM9G20_SDRAMC_CR_NC_MASK 0x00000003
+#define AT91SAM9G20_SDRAMC_CR_NR_11 0x0
+#define AT91SAM9G20_SDRAMC_CR_NR_12 0x4
+#define AT91SAM9G20_SDRAMC_CR_NR_13 0x8
+#define AT91SAM9G20_SDRAMC_CR_NR_RES 0xc
+#define AT91SAM9G20_SDRAMC_CR_NR_MASK 0x0000000c
+#define AT91SAM9G20_SDRAMC_CR_NB_2 0x00
+#define AT91SAM9G20_SDRAMC_CR_NB_4 0x10
+#define AT91SAM9G20_SDRAMC_CR_DBW_16 0x80
+#define AT91SAM9G20_SDRAMC_CR_NB_MASK 0x00000010
+#define AT91SAM9G20_SDRAMC_CR_NCAS_MASK 0x00000060
+#define AT91SAM9G20_SDRAMC_CR_TWR_MASK 0x00000780
+#define AT91SAM9G20_SDRAMC_CR_TRC_MASK 0x00007800
+#define AT91SAM9G20_SDRAMC_CR_TRP_MASK 0x00078000
+#define AT91SAM9G20_SDRAMC_CR_TRCD_MASK 0x00780000
+#define AT91SAM9G20_SDRAMC_CR_TRAS_MASK 0x07800000
+#define AT91SAM9G20_SDRAMC_CR_TXSR_MASK 0x78000000
+#define AT91SAM9G20_SDRAMC_HSR 0x0c
+#define AT91SAM9G20_SDRAMC_LPR 0x10
+#define AT91SAM9G20_SDRAMC_IER 0x14
+#define AT91SAM9G20_SDRAMC_IDR 0x18
+#define AT91SAM9G20_SDRAMC_IMR 0x1c
+#define AT91SAM9G20_SDRAMC_ISR 0x20
+#define AT91SAM9G20_SDRAMC_MDR 0x24
+
+#endif /* AT91SAM9G20REG_H_*/
+
Property changes on: trunk/sys/arm/at91/at91sam9g20reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91sam9g45.c
===================================================================
--- trunk/sys/arm/at91/at91sam9g45.c (rev 0)
+++ trunk/sys/arm/at91/at91sam9g45.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,171 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ * Copyright (c) 2012 Andrew Turner. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91sam9g45.c 266087 2014-05-14 20:31:54Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91soc.h>
+#include <arm/at91/at91_aicreg.h>
+#include <arm/at91/at91sam9g45reg.h>
+#include <arm/at91/at91_pitreg.h>
+#include <arm/at91/at91_pmcreg.h>
+#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_rstreg.h>
+
+/*
+ * Standard priority levels for the system. 0 is lowest and 7 is highest.
+ * These values are the ones Atmel uses for its Linux port
+ */
+static const int at91_irq_prio[32] =
+{
+ 7, /* Advanced Interrupt Controller */
+ 7, /* System Peripherals */
+ 1, /* Parallel IO Controller A */
+ 1, /* Parallel IO Controller B */
+ 1, /* Parallel IO Controller C */
+ 1, /* Parallel IO Controller D and E */
+ 0,
+ 5, /* USART 0 */
+ 5, /* USART 1 */
+ 5, /* USART 2 */
+ 5, /* USART 3 */
+ 0, /* Multimedia Card Interface 0 */
+ 6, /* Two-Wire Interface 0 */
+ 6, /* Two-Wire Interface 1 */
+ 5, /* Serial Peripheral Interface 0 */
+ 5, /* Serial Peripheral Interface 1 */
+ 4, /* Serial Synchronous Controller 0 */
+ 4, /* Serial Synchronous Controller 1 */
+ 0, /* Timer Counter 0, 1, 2, 3, 4 and 5 */
+ 0, /* Pulse Width Modulation Controller */
+ 0, /* Touch Screen Controller */
+ 0, /* DMA Controller */
+ 2, /* USB Host High Speed port */
+ 3, /* LCD Controller */
+ 5, /* AC97 Controller */
+ 3, /* Ethernet */
+ 0, /* Image Sensor Interface */
+ 2, /* USB Device High Speed port */
+ 0, /* (reserved) */
+ 0, /* Multimedia Card Interface 1 */
+ 0, /* (reserved) */
+ 0, /* Advanced Interrupt Controller IRQ0 */
+};
+
+static const uint32_t at91_pio_base[] = {
+ AT91SAM9G45_PIOA_BASE,
+ AT91SAM9G45_PIOB_BASE,
+ AT91SAM9G45_PIOC_BASE,
+ AT91SAM9G45_PIOD_BASE,
+ AT91SAM9G45_PIOE_BASE,
+};
+
+#define DEVICE(_name, _id, _unit) \
+ { \
+ _name, _unit, \
+ AT91SAM9G45_ ## _id ##_BASE, \
+ AT91SAM9G45_ ## _id ## _SIZE, \
+ AT91SAM9G45_IRQ_ ## _id \
+ }
+
+static const struct cpu_devs at91_devs[] =
+{
+ DEVICE("at91_pmc", PMC, 0),
+ DEVICE("at91_wdt", WDT, 0),
+ DEVICE("at91_rst", RSTC, 0),
+ DEVICE("at91_pit", PIT, 0),
+ DEVICE("at91_pio", PIOA, 0),
+ DEVICE("at91_pio", PIOB, 1),
+ DEVICE("at91_pio", PIOC, 2),
+ DEVICE("at91_pio", PIOD, 3),
+ DEVICE("at91_pio", PIOE, 4),
+ DEVICE("at91_twi", TWI0, 0),
+ DEVICE("at91_twi", TWI1, 1),
+ DEVICE("at91_mci", HSMCI0, 0),
+ DEVICE("at91_mci", HSMCI1, 1),
+ DEVICE("uart", DBGU, 0),
+ DEVICE("uart", USART0, 1),
+ DEVICE("uart", USART1, 2),
+ DEVICE("uart", USART2, 3),
+ DEVICE("uart", USART3, 4),
+ DEVICE("spi", SPI0, 0),
+ DEVICE("spi", SPI1, 1),
+ DEVICE("ate", EMAC, 0),
+ DEVICE("macb", EMAC, 0),
+ DEVICE("nand", NAND, 0),
+ DEVICE("ohci", OHCI, 0),
+ { 0, 0, 0, 0, 0 }
+};
+
+static void
+at91_clock_init(void)
+{
+ struct at91_pmc_clock *clk;
+
+ /* Update USB host port clock info */
+ clk = at91_pmc_clock_ref("uhpck");
+ clk->pmc_mask = PMC_SCER_UHP_SAM9;
+ at91_pmc_clock_deref(clk);
+
+ /* Each SOC has different PLL contraints */
+ clk = at91_pmc_clock_ref("plla");
+ clk->pll_min_in = SAM9G45_PLL_A_MIN_IN_FREQ; /* 2 MHz */
+ clk->pll_max_in = SAM9G45_PLL_A_MAX_IN_FREQ; /* 32 MHz */
+ clk->pll_min_out = SAM9G45_PLL_A_MIN_OUT_FREQ; /* 400 MHz */
+ clk->pll_max_out = SAM9G45_PLL_A_MAX_OUT_FREQ; /* 800 MHz */
+ clk->pll_mul_shift = SAM9G45_PLL_A_MUL_SHIFT;
+ clk->pll_mul_mask = SAM9G45_PLL_A_MUL_MASK;
+ clk->pll_div_shift = SAM9G45_PLL_A_DIV_SHIFT;
+ clk->pll_div_mask = SAM9G45_PLL_A_DIV_MASK;
+ clk->set_outb = at91_pmc_800mhz_plla_outb;
+ at91_pmc_clock_deref(clk);
+}
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_pit_delay,
+ .soc_reset = at91_rst_cpu_reset,
+ .soc_clock_init = at91_clock_init,
+ .soc_irq_prio = at91_irq_prio,
+ .soc_children = at91_devs,
+ .soc_pio_base = at91_pio_base,
+ .soc_pio_count = nitems(at91_pio_base),
+};
+
+AT91_SOC(AT91_T_SAM9G45, &soc_data);
Property changes on: trunk/sys/arm/at91/at91sam9g45.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91sam9g45reg.h
===================================================================
--- trunk/sys/arm/at91/at91sam9g45reg.h (rev 0)
+++ trunk/sys/arm/at91/at91sam9g45reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,295 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ * Copyright (c) 2012 Andrew Turner. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91sam9g45reg.h 266110 2014-05-15 02:41:23Z ian $ */
+
+#ifndef AT91SAM9G45REG_H_
+#define AT91SAM9G45REG_H_
+
+/* Chip Specific limits */
+#define SAM9G45_PLL_A_MIN_IN_FREQ 2000000 /* 2 Mhz */
+#define SAM9G45_PLL_A_MAX_IN_FREQ 32000000 /* 32 Mhz */
+#define SAM9G45_PLL_A_MIN_OUT_FREQ 400000000 /* 400 Mhz */
+#define SAM9G45_PLL_A_MAX_OUT_FREQ 800000000 /* 800 Mhz */
+#define SAM9G45_PLL_A_MUL_SHIFT 16
+#define SAM9G45_PLL_A_MUL_MASK 0xFF
+#define SAM9G45_PLL_A_DIV_SHIFT 0
+#define SAM9G45_PLL_A_DIV_MASK 0xFF
+
+/*
+ * Memory map, from datasheet :
+ * 0x00000000 - 0x0ffffffff : Internal Memories
+ * 0x10000000 - 0x1ffffffff : Chip Select 0
+ * 0x20000000 - 0x2ffffffff : Chip Select 1
+ * 0x30000000 - 0x3ffffffff : Chip Select 2
+ * 0x40000000 - 0x4ffffffff : Chip Select 3
+ * 0x50000000 - 0x5ffffffff : Chip Select 4
+ * 0x60000000 - 0x6ffffffff : Chip Select 5
+ * 0x70000000 - 0x7ffffffff : DDR SDRC 0
+ * 0x80000000 - 0xeffffffff : Undefined (Abort)
+ * 0xf0000000 - 0xfffffffff : Peripherals
+ */
+
+#define AT91_CHIPSELECT_0 0x10000000
+#define AT91_CHIPSELECT_1 0x20000000
+#define AT91_CHIPSELECT_2 0x30000000
+#define AT91_CHIPSELECT_3 0x40000000
+#define AT91_CHIPSELECT_4 0x50000000
+#define AT91_CHIPSELECT_5 0x60000000
+
+
+#define AT91SAM9G45_EMAC_BASE 0xffbc000
+#define AT91SAM9G45_EMAC_SIZE 0x4000
+
+#define AT91SAM9G45_RSTC_BASE 0xffffd00
+#define AT91SAM9G45_RSTC_SIZE 0x10
+
+/* USART*/
+
+#define AT91SAM9G45_USART_SIZE 0x4000
+#define AT91SAM9G45_USART0_BASE 0xff8c000
+#define AT91SAM9G45_USART0_SIZE AT91SAM9G45_USART_SIZE
+#define AT91SAM9G45_USART1_BASE 0xff90000
+#define AT91SAM9G45_USART1_SIZE AT91SAM9G45_USART_SIZE
+#define AT91SAM9G45_USART2_BASE 0xff94000
+#define AT91SAM9G45_USART2_SIZE AT91SAM9G45_USART_SIZE
+#define AT91SAM9G45_USART3_BASE 0xff98000
+#define AT91SAM9G45_USART3_SIZE AT91SAM9G45_USART_SIZE
+
+/*TC*/
+#define AT91SAM9G45_TC0_BASE 0xff7c000
+#define AT91SAM9G45_TC0_SIZE 0x4000
+#define AT91SAM9G45_TC0C0_BASE 0xff7c000
+#define AT91SAM9G45_TC0C1_BASE 0xff7c040
+#define AT91SAM9G45_TC0C2_BASE 0xff7c080
+
+#define AT91SAM9G45_TC1_BASE 0xffd4000
+#define AT91SAM9G45_TC1_SIZE 0x4000
+#define AT91SAM9G45_TC1C0_BASE 0xffd4000
+#define AT91SAM9G45_TC1C1_BASE 0xffd4040
+#define AT91SAM9G45_TC1C2_BASE 0xffd4080
+
+/*SPI*/
+
+#define AT91SAM9G45_SPI0_BASE 0xffa48000
+#define AT91SAM9G45_SPI0_SIZE 0x4000
+
+#define AT91SAM9G45_SPI1_BASE 0xffa8000
+#define AT91SAM9G45_SPI1_SIZE 0x4000
+
+/* System Registers */
+#define AT91SAM9G45_SYS_BASE 0xffff000
+#define AT91SAM9G45_SYS_SIZE 0x1000
+
+#define AT91SAM9G45_MATRIX_BASE 0xfffea00
+#define AT91SAM9G45_MATRIX_SIZE 0x200
+
+#define AT91SAM9G45_DBGU_BASE 0xfffee00
+#define AT91SAM9G45_DBGU_SIZE 0x200
+
+/*
+ * PIO
+ */
+#define AT91SAM9G45_PIOA_BASE 0xffff200
+#define AT91SAM9G45_PIOA_SIZE 0x200
+#define AT91SAM9G45_PIOB_BASE 0xffff400
+#define AT91SAM9G45_PIOB_SIZE 0x200
+#define AT91SAM9G45_PIOC_BASE 0xffff600
+#define AT91SAM9G45_PIOC_SIZE 0x200
+#define AT91SAM9G45_PIOD_BASE 0xffff800
+#define AT91SAM9G45_PIOD_SIZE 0x200
+#define AT91SAM9G45_PIOE_BASE 0xffffa00
+#define AT91SAM9G45_PIOE_SIZE 0x200
+
+#define AT91SAM9G45_PMC_BASE 0xffffc00
+#define AT91SAM9G45_PMC_SIZE 0x100
+
+/* IRQs : */
+/*
+ * 0: AIC
+ * 1: System peripheral (System timer, RTC, DBGU)
+ * 2: PIO Controller A
+ * 3: PIO Controller B
+ * 4: PIO Controller C
+ * 5: PIO Controller D/E
+ * 6: TRNG
+ * 7: USART 0
+ * 8: USART 1
+ * 9: USART 2
+ * 10: USART 3
+ * 11: Multimedia Card interface 0
+ * 12: Two-wirte interface 0
+ * 13: Two-wirte interface 1
+ * 14: SPI 0
+ * 15: SPI 1
+ * 16: SSC 0
+ * 17: SSC 0
+ * 18: Timer Counter 0, 2, 3, 4, 5
+ * 19: PWM
+ * 20: Touch Screen ADC
+ * 21: DMA
+ * 22: USB Host port
+ * 23: LCD
+ * 24: AC97
+ * 25: EMAC
+ * 26: Image Sensor Interface
+ * 27: USB Device High Speed
+ * 28: -
+ * 29: Multimedia Card interface 1
+ * 30: Reserved
+ * 31: AIC
+ */
+
+#define AT91SAM9G45_IRQ_SYSTEM 1
+#define AT91SAM9G45_IRQ_PIOA 2
+#define AT91SAM9G45_IRQ_PIOB 3
+#define AT91SAM9G45_IRQ_PIOC 4
+#define AT91SAM9G45_IRQ_PIOD 5
+#define AT91SAM9G45_IRQ_PIOE 6
+#define AT91SAM9G45_IRQ_USART0 7
+#define AT91SAM9G45_IRQ_USART1 8
+#define AT91SAM9G45_IRQ_USART2 9
+#define AT91SAM9G45_IRQ_USART3 10
+#define AT91SAM9G45_IRQ_HSMCI0 11
+#define AT91SAM9G45_IRQ_TWI0 12
+#define AT91SAM9G45_IRQ_TWI1 13
+#define AT91SAM9G45_IRQ_SPI0 14
+#define AT91SAM9G45_IRQ_SPI1 15
+#define AT91SAM9G45_IRQ_SSC0 16
+#define AT91SAM9G45_IRQ_SSC1 17
+#define AT91SAM9G45_IRQ_TC0_TC5 18
+#define AT91SAM9G45_IRQ_PWM 19
+#define AT91SAM9G45_IRQ_TSADCC 20
+#define AT91SAM9G45_IRQ_DMA 21
+#define AT91SAM9G45_IRQ_UHP 22
+#define AT91SAM9G45_IRQ_LCDC 23
+#define AT91SAM9G45_IRQ_AC97C 24
+#define AT91SAM9G45_IRQ_EMAC 25
+#define AT91SAM9G45_IRQ_ISI 26
+#define AT91SAM9G45_IRQ_UDPHS 27
+/* Reserved 28 */
+#define AT91SAM9G45_IRQ_HSMCI1 29
+/* Reserved 30 */
+#define AT91SAM9G45_IRQ_AICBASE 31
+
+/* Alias */
+#define AT91SAM9G45_IRQ_DBGU AT91SAM9G45_IRQ_SYSTEM
+#define AT91SAM9G45_IRQ_PMC AT91SAM9G45_IRQ_SYSTEM
+#define AT91SAM9G45_IRQ_WDT AT91SAM9G45_IRQ_SYSTEM
+#define AT91SAM9G45_IRQ_PIT AT91SAM9G45_IRQ_SYSTEM
+#define AT91SAM9G45_IRQ_RSTC AT91SAM9G45_IRQ_SYSTEM
+#define AT91SAM9G45_IRQ_OHCI AT91SAM9G45_IRQ_UHP
+#define AT91SAM9G45_IRQ_TC0 AT91SAM9G45_IRQ_TC0_TC5
+#define AT91SAM9G45_IRQ_TC1 AT91SAM9G45_IRQ_TC0_TC5
+#define AT91SAM9G45_IRQ_TC2 AT91SAM9G45_IRQ_TC0_TC5
+#define AT91SAM9G45_IRQ_TC3 AT91SAM9G45_IRQ_TC0_TC5
+#define AT91SAM9G45_IRQ_TC4 AT91SAM9G45_IRQ_TC0_TC5
+#define AT91SAM9G45_IRQ_TC5 AT91SAM9G45_IRQ_TC0_TC5
+#define AT91SAM9G45_IRQ_NAND (-1)
+
+#define AT91SAM9G45_AIC_BASE 0xffff000
+#define AT91SAM9G45_AIC_SIZE 0x200
+
+/* Timer */
+
+#define AT91SAM9G45_WDT_BASE 0xffffd40
+#define AT91SAM9G45_WDT_SIZE 0x10
+
+#define AT91SAM9G45_PIT_BASE 0xffffd30
+#define AT91SAM9G45_PIT_SIZE 0x10
+
+#define AT91SAM9G45_SMC_BASE 0xfffe800
+#define AT91SAM9G45_SMC_SIZE 0x200
+
+#define AT91SAM9G45_PMC_BASE 0xffffc00
+#define AT91SAM9G45_PMC_SIZE 0x100
+
+#define AT91SAM9G45_HSMCI0_BASE 0xff80000
+#define AT91SAM9G45_HSMCI0_SIZE 0x4000
+
+#define AT91SAM9G45_HSMCI1_BASE 0xffd0000
+#define AT91SAM9G45_HSMCI1_SIZE 0x4000
+
+#define AT91SAM9G45_TWI0_BASE 0xff84000
+#define AT91SAM9G45_TWI0_SIZE 0x4000
+#define AT91SAM9G45_TWI1_BASE 0xff88000
+#define AT91SAM9G45_TWI1_SIZE 0x4000
+
+/* XXX Needs to be carfully coordinated with
+ * other * soc's so phyical and vm address
+ * mapping are unique. XXX
+ */
+#define AT91SAM9G45_OHCI_VA_BASE 0xdfb00000
+#define AT91SAM9G45_OHCI_BASE 0x00700000
+#define AT91SAM9G45_OHCI_SIZE 0x00100000
+
+#define AT91SAM9G45_NAND_VA_BASE 0xe0000000
+#define AT91SAM9G45_NAND_BASE 0x40000000
+#define AT91SAM9G45_NAND_SIZE 0x10000000
+
+
+/* DDRSDRC */
+#define AT91SAM9G45_DDRSDRC1_BASE 0xfffea00
+#define AT91SAM9G45_DDRSDRC0_BASE 0xfffe600
+#define AT91SAM9G45_DDRSDRC_MR 0x00
+#define AT91SAM9G45_DDRSDRC_TR 0x04
+#define AT91SAM9G45_DDRSDRC_CR 0x08
+#define AT91SAM9G45_DDRSDRC_CR_NC_8 0x0
+#define AT91SAM9G45_DDRSDRC_CR_NC_9 0x1
+#define AT91SAM9G45_DDRSDRC_CR_NC_10 0x2
+#define AT91SAM9G45_DDRSDRC_CR_NC_11 0x3
+#define AT91SAM9G45_DDRSDRC_CR_NC_MASK 0x00000003
+#define AT91SAM9G45_DDRSDRC_CR_NR_11 0x0
+#define AT91SAM9G45_DDRSDRC_CR_NR_12 0x4
+#define AT91SAM9G45_DDRSDRC_CR_NR_13 0x8
+#define AT91SAM9G45_DDRSDRC_CR_NR_14 0xc
+#define AT91SAM9G45_DDRSDRC_CR_NR_MASK 0x0000000c
+#define AT91SAM9G45_DDRSDRC_TPR0 0x0c
+#define AT91SAM9G45_DDRSDRC_TPR1 0x10
+#define AT91SAM9G45_DDRSDRC_TPR2 0x14
+/* Reserved 0x18 */
+#define AT91SAM9G45_DDRSDRC_LPR 0x1c
+#define AT91SAM9G45_DDRSDRC_MDR 0x20
+#define AT91SAM9G45_DDRSDRC_MDR_SDR 0x0
+#define AT91SAM9G45_DDRSDRC_MDR_LPSDR 0x1
+#define AT91SAM9G45_DDRSDRC_MDR_LPDDR1 0x3
+#define AT91SAM9G45_DDRSDRC_MDR_DDR2 0x6
+#define AT91SAM9G45_DDRSDRC_MDR_MASK 0x00000007
+#define AT91SAM9G45_DDRSDRC_MDR_DBW_16 0x10
+#define AT91SAM9G45_DDRSDRC_DLL 0x24
+#define AT91SAM9G45_DDRSDRC_HSR 0x2c
+#define AT91SAM9G45_DDRSDRC_DELAY1R 0x40
+#define AT91SAM9G45_DDRSDRC_DELAY2R 0x44
+#define AT91SAM9G45_DDRSDRC_DELAY3R 0x48
+#define AT91SAM9G45_DDRSDRC_DELAY4R 0x4c
+/* Reserved 0x50 - 0xe0 */
+#define AT91SAM9G45_DDRSDRC_WPMR 0xe4
+#define AT91SAM9G45_DDRSDRC_WPSR 0xe8
+
+#endif /* AT91SAM9G45REG_H_*/
+
Property changes on: trunk/sys/arm/at91/at91sam9g45reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91sam9x5.c
===================================================================
--- trunk/sys/arm/at91/at91sam9x5.c (rev 0)
+++ trunk/sys/arm/at91/at91sam9x5.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,188 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ * Copyright (c) 2012 M. Warner Losh.. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91sam9x5.c 266277 2014-05-17 00:53:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91soc.h>
+#include <arm/at91/at91_aicreg.h>
+#include <arm/at91/at91sam9x5reg.h>
+#include <arm/at91/at91_pitreg.h>
+#include <arm/at91/at91_pmcreg.h>
+#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_rstreg.h>
+
+/*
+ * Standard priority levels for the system. 0 is lowest and 7 is highest.
+ * These values are the ones Atmel uses for its Linux port
+ */
+static const int at91_irq_prio[32] =
+{
+ 7, /* Advanced Interrupt Controller (FIQ) */
+ 7, /* System Peripherals */
+ 1, /* Parallel IO Controller A and B */
+ 1, /* Parallel IO Controller C and D */
+ 4, /* Soft Modem */
+ 5, /* USART 0 */
+ 5, /* USART 1 */
+ 5, /* USART 2 */
+ 5, /* USART 3 */
+ 6, /* Two-Wire Interface 0 */
+ 6, /* Two-Wire Interface 1 */
+ 6, /* Two-Wire Interface 2 */
+ 0, /* Multimedia Card Interface 0 */
+ 5, /* Serial Peripheral Interface 0 */
+ 5, /* Serial Peripheral Interface 1 */
+ 5, /* UART 0 */
+ 5, /* UART 1 */
+ 0, /* Timer Counter 0, 1, 2, 3, 4 and 5 */
+ 0, /* Pulse Width Modulation Controller */
+ 0, /* ADC Controller */
+ 0, /* DMA Controller 0 */
+ 0, /* DMA Controller 1 */
+ 2, /* USB Host High Speed port */
+ 2, /* USB Device High speed port */
+ 3, /* Ethernet MAC 0 */
+ 3, /* LDC Controller or Image Sensor Interface */
+ 0, /* Multimedia Card Interface 1 */
+ 3, /* Ethernet MAC 1 */
+ 4, /* Synchronous Serial Interface */
+ 4, /* CAN Controller 0 */
+ 4, /* CAN Controller 1 */
+ 0, /* Advanced Interrupt Controller (IRQ0) */
+};
+
+static const uint32_t at91_pio_base[] = {
+ AT91SAM9X25_PIOA_BASE,
+ AT91SAM9X25_PIOB_BASE,
+ AT91SAM9X25_PIOC_BASE,
+ AT91SAM9X25_PIOD_BASE,
+};
+
+#define DEVICE(_name, _id, _unit) \
+ { \
+ _name, _unit, \
+ AT91SAM9X25_ ## _id ##_BASE, \
+ AT91SAM9X25_ ## _id ## _SIZE, \
+ AT91SAM9X25_IRQ_ ## _id \
+ }
+
+static const struct cpu_devs at91_devs[] =
+{
+ DEVICE("at91_aic", AIC, 0),
+ DEVICE("at91_pmc", PMC, 0),
+ DEVICE("at91_wdt", WDT, 0),
+ DEVICE("at91_rst", RSTC, 0),
+ DEVICE("at91_pit", PIT, 0),
+ DEVICE("at91_pio", PIOA, 0),
+ DEVICE("at91_pio", PIOB, 1),
+ DEVICE("at91_pio", PIOC, 2),
+ DEVICE("at91_pio", PIOD, 3),
+ DEVICE("at91_twi", TWI0, 0),
+ DEVICE("at91_twi", TWI1, 1),
+ DEVICE("at91_twi", TWI2, 2),
+ DEVICE("at91_mci", HSMCI0, 0),
+ DEVICE("at91_mci", HSMCI1, 1),
+ DEVICE("uart", DBGU, 0),
+ DEVICE("uart", USART0, 1),
+ DEVICE("uart", USART1, 2),
+ DEVICE("uart", USART2, 3),
+ DEVICE("uart", USART3, 4),
+ DEVICE("spi", SPI0, 0),
+ DEVICE("spi", SPI1, 1),
+ DEVICE("macb", EMAC0, 0),
+ DEVICE("macb", EMAC1, 0),
+ DEVICE("nand", NAND, 0),
+ DEVICE("ohci", OHCI, 0),
+ DEVICE("ehci", EHCI, 0),
+ { 0, 0, 0, 0, 0 }
+};
+
+static void
+at91_clock_init(void)
+{
+ struct at91_pmc_clock *clk;
+
+ /* Update USB device port clock info */
+ clk = at91_pmc_clock_ref("udpck");
+ clk->pmc_mask = PMC_SCER_UDP_SAM9;
+ at91_pmc_clock_deref(clk);
+
+ /* Update USB host port clock info */
+ clk = at91_pmc_clock_ref("uhpck");
+ clk->pmc_mask = PMC_SCER_UHP_SAM9;
+ at91_pmc_clock_deref(clk);
+
+ /* Each SOC has different PLL contraints */
+ clk = at91_pmc_clock_ref("plla");
+ clk->pll_min_in = SAM9X25_PLL_A_MIN_IN_FREQ; /* 2 MHz */
+ clk->pll_max_in = SAM9X25_PLL_A_MAX_IN_FREQ; /* 32 MHz */
+ clk->pll_min_out = SAM9X25_PLL_A_MIN_OUT_FREQ; /* 400 MHz */
+ clk->pll_max_out = SAM9X25_PLL_A_MAX_OUT_FREQ; /* 800 MHz */
+ clk->pll_mul_shift = SAM9X25_PLL_A_MUL_SHIFT;
+ clk->pll_mul_mask = SAM9X25_PLL_A_MUL_MASK;
+ clk->pll_div_shift = SAM9X25_PLL_A_DIV_SHIFT;
+ clk->pll_div_mask = SAM9X25_PLL_A_DIV_MASK;
+ clk->set_outb = at91_pmc_800mhz_plla_outb;
+ at91_pmc_clock_deref(clk);
+
+ clk = at91_pmc_clock_ref("pllb");
+ clk->pll_min_in = SAM9X25_PLL_B_MIN_IN_FREQ; /* 2 MHz */
+ clk->pll_max_in = SAM9X25_PLL_B_MAX_IN_FREQ; /* 32 MHz */
+ clk->pll_min_out = SAM9X25_PLL_B_MIN_OUT_FREQ; /* 30 MHz */
+ clk->pll_max_out = SAM9X25_PLL_B_MAX_OUT_FREQ; /* 100 MHz */
+ clk->pll_mul_shift = SAM9X25_PLL_B_MUL_SHIFT;
+ clk->pll_mul_mask = SAM9X25_PLL_B_MUL_MASK;
+ clk->pll_div_shift = SAM9X25_PLL_B_DIV_SHIFT;
+ clk->pll_div_mask = SAM9X25_PLL_B_DIV_MASK;
+ clk->set_outb = at91_pmc_800mhz_pllb_outb;
+ at91_pmc_clock_deref(clk);
+}
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_pit_delay,
+ .soc_reset = at91_rst_cpu_reset,
+ .soc_clock_init = at91_clock_init,
+ .soc_irq_prio = at91_irq_prio,
+ .soc_children = at91_devs,
+ .soc_pio_base = at91_pio_base,
+ .soc_pio_count = nitems(at91_pio_base),
+};
+
+AT91_SOC_SUB(AT91_T_SAM9X5, AT91_ST_SAM9X25, &soc_data);
Property changes on: trunk/sys/arm/at91/at91sam9x5.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91sam9x5reg.h
===================================================================
--- trunk/sys/arm/at91/at91sam9x5reg.h (rev 0)
+++ trunk/sys/arm/at91/at91sam9x5reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,316 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
+ * Copyright (c) 2010 Greg Ansley. All rights reserved.
+ * Copyright (c) 2012 M. Warener Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91sam9x5reg.h 238922 2012-07-30 21:30:43Z imp $ */
+
+#ifndef AT91SAM9X5REG_H_
+#define AT91SAM9X5REG_H_
+
+#ifndef AT91SAM9X25_MASTER_CLOCK
+#define AT91SAM9X25_MASTER_CLOCK ((18432000 * 43)/6)
+#endif
+
+/* Chip Specific limits */
+#define SAM9X25_PLL_A_MIN_IN_FREQ 2000000 /* 2 Mhz */
+#define SAM9X25_PLL_A_MAX_IN_FREQ 32000000 /* 32 Mhz */
+#define SAM9X25_PLL_A_MIN_OUT_FREQ 400000000 /* 400 Mhz */
+#define SAM9X25_PLL_A_MAX_OUT_FREQ 800000000 /* 800 Mhz */
+#define SAM9X25_PLL_A_MUL_SHIFT 16
+#define SAM9X25_PLL_A_MUL_MASK 0xFF
+#define SAM9X25_PLL_A_DIV_SHIFT 0
+#define SAM9X25_PLL_A_DIV_MASK 0xFF
+
+#define SAM9X25_PLL_B_MIN_IN_FREQ 2000000 /* 2 Mhz */
+#define SAM9X25_PLL_B_MAX_IN_FREQ 32000000 /* 32 Mhz */
+#define SAM9X25_PLL_B_MIN_OUT_FREQ 30000000 /* 30 Mhz */
+#define SAM9X25_PLL_B_MAX_OUT_FREQ 100000000 /* 100 Mhz */
+#define SAM9X25_PLL_B_MUL_SHIFT 16
+#define SAM9X25_PLL_B_MUL_MASK 0x3F
+#define SAM9X25_PLL_B_DIV_SHIFT 0
+#define SAM9X25_PLL_B_DIV_MASK 0xFF
+
+/*
+ * Memory map, from datasheet :
+ * 0x00000000 - 0x0ffffffff : Internal Memories
+ * 0x10000000 - 0x1ffffffff : Chip Select 0
+ * 0x20000000 - 0x2ffffffff : Chip Select 1 DDR2/LPDDR/SDR/LPSDR
+ * 0x30000000 - 0x3ffffffff : Chip Select 2
+ * 0x40000000 - 0x4ffffffff : Chip Select 3 NAND Flash
+ * 0x50000000 - 0x5ffffffff : Chip Select 4
+ * 0x60000000 - 0x6ffffffff : Chip Select 5
+ * 0x70000000 - 0xeffffffff : Undefined (Abort)
+ * 0xf0000000 - 0xfffffffff : Peripherals
+ */
+
+#define AT91_CHIPSELECT_0 0x10000000
+#define AT91_CHIPSELECT_1 0x20000000
+#define AT91_CHIPSELECT_2 0x30000000
+#define AT91_CHIPSELECT_3 0x40000000
+#define AT91_CHIPSELECT_4 0x50000000
+#define AT91_CHIPSELECT_5 0x60000000
+
+#define AT91SAM9X25_EMAC_SIZE 0x4000
+#define AT91SAM9X25_EMAC0_BASE 0x802c000
+#define AT91SAM9X25_EMAC0_SIZE AT91SAM9X25_EMAC_SIZE
+#define AT91SAM9X25_EMAC1_BASE 0x8030000
+#define AT91SAM9X25_EMAC1_SIZE AT91SAM9X25_EMAC_SIZE
+
+#define AT91SAM9X25_RSTC_BASE 0xffffe00
+#define AT91SAM9X25_RSTC_SIZE 0x10
+
+/* USART*/
+
+#define AT91SAM9X25_USART_SIZE 0x4000
+#define AT91SAM9X25_USART0_BASE 0x801c000
+#define AT91SAM9X25_USART0_PDC 0x801c100
+#define AT91SAM9X25_USART0_SIZE AT91SAM9X25_USART_SIZE
+#define AT91SAM9X25_USART1_BASE 0x8020000
+#define AT91SAM9X25_USART1_PDC 0x8020100
+#define AT91SAM9X25_USART1_SIZE AT91SAM9X25_USART_SIZE
+#define AT91SAM9X25_USART2_BASE 0x8024000
+#define AT91SAM9X25_USART2_PDC 0x8024100
+#define AT91SAM9X25_USART2_SIZE AT91SAM9X25_USART_SIZE
+#define AT91SAM9X25_USART3_BASE 0x8028000
+#define AT91SAM9X25_USART3_PDC 0x8028100
+#define AT91SAM9X25_USART3_SIZE AT91SAM9X25_USART_SIZE
+
+/*TC*/
+#define AT91SAM9X25_TC0_BASE 0x8008000
+#define AT91SAM9X25_TC0_SIZE 0x4000
+#define AT91SAM9X25_TC0C0_BASE 0x8008000
+#define AT91SAM9X25_TC0C1_BASE 0x8008040
+#define AT91SAM9X25_TC0C2_BASE 0x8008080
+
+#define AT91SAM9X25_TC1_BASE 0x800c000
+#define AT91SAM9X25_TC1_SIZE 0x4000
+
+/*SPI*/
+
+#define AT91SAM9X25_SPI0_BASE 0x0000000
+
+#define AT91SAM9X25_SPI0_SIZE 0x4000
+
+#define AT91SAM9X25_SPI1_BASE 0x0004000
+#define AT91SAM9X25_SPI1_SIZE 0x4000
+
+/* System Registers */
+#define AT91SAM9X25_SYS_BASE 0xffff000
+#define AT91SAM9X25_SYS_SIZE 0x1000
+
+#define AT91SAM9X25_MATRIX_BASE 0xfffde00
+#define AT91SAM9X25_MATRIX_SIZE 0x200
+
+#define AT91SAM9X25_DBGU_BASE 0xffff200
+#define AT91SAM9X25_DBGU_SIZE 0x200
+
+/*
+ * PIO
+ */
+#define AT91SAM9X25_PIOA_BASE 0xffff400
+#define AT91SAM9X25_PIOA_SIZE 0x200
+#define AT91SAM9X25_PIOB_BASE 0xffff600
+#define AT91SAM9X25_PIOB_SIZE 0x200
+#define AT91SAM9X25_PIOC_BASE 0xffff800
+#define AT91SAM9X25_PIOC_SIZE 0x200
+#define AT91SAM9X25_PIOD_BASE 0xffffa00
+#define AT91SAM9X25_PIOD_SIZE 0x200
+
+#define AT91RM92_PMC_BASE 0xffffc00
+#define AT91RM92_PMC_SIZE 0x100
+/* IRQs :
+ * 0: AIC
+ * 1: System peripheral (System timer, RTC, DBGU)
+ * 2: PIO Controller A,B
+ * 3: PIO Controller C,D
+ * 4: SMD Soft Modem
+ * 5: USART 0
+ * 6: USART 1
+ * 7: USART 2
+ * 8: USART 3
+ * 9: Two-wirte interface
+ * 10: Two-wirte interface
+ * 11: Two-wirte interface
+ * 12: HSMCI Interface
+ * 13: SPI 0
+ * 14: SPI 1
+ * 15: UART0
+ * 16: UART1
+ * 17: Timer Counter 0,1
+ * 18: PWM
+ * 19: ADC
+ * 20: DMAC 0
+ * 21: DMAC 1
+ * 22: UHPHS - USB Host controller
+ * 23: UDPHS - USB Device Controller
+ * 24: EMAC0
+ * 25: LCD controller or Image Sensor Interface
+ * 26: HSMCI1
+ * 27: EMAC1
+ * 28: SSC
+ * 29: CAN0
+ * 30: CAN1
+ * 31: AIC IRQ0
+ */
+
+#define AT91SAM9X25_IRQ_AIC 0
+#define AT91SAM9X25_IRQ_SYSTEM 1
+#define AT91SAM9X25_IRQ_PIOAB 2
+#define AT91SAM9X25_IRQ_PIOCD 3
+#define AT91SAM9X25_IRQ_SMD 4
+#define AT91SAM9X25_IRQ_USART0 5
+#define AT91SAM9X25_IRQ_USART1 6
+#define AT91SAM9X25_IRQ_USART2 7
+#define AT91SAM9X25_IRQ_USART3 8
+#define AT91SAM9X25_IRQ_TWI0 9
+#define AT91SAM9X25_IRQ_TWI1 10
+#define AT91SAM9X25_IRQ_TWI2 11
+#define AT91SAM9X25_IRQ_HSMCI0 12
+#define AT91SAM9X25_IRQ_SPI0 13
+#define AT91SAM9X25_IRQ_SPI1 14
+#define AT91SAM9X25_IRQ_UART0 15
+#define AT91SAM9X25_IRQ_UART1 16
+#define AT91SAM9X25_IRQ_TC01 17
+#define AT91SAM9X25_IRQ_PWM 18
+#define AT91SAM9X25_IRQ_ADC 19
+#define AT91SAM9X25_IRQ_DMAC0 20
+#define AT91SAM9X25_IRQ_DMAC1 21
+#define AT91SAM9X25_IRQ_UHPHS 22
+#define AT91SAM9X25_IRQ_UDPHS 23
+#define AT91SAM9X25_IRQ_EMAC0 24
+#define AT91SAM9X25_IRQ_HSMCI1 26
+#define AT91SAM9X25_IRQ_EMAC1 27
+#define AT91SAM9X25_IRQ_SSC 28
+#define AT91SAM9X25_IRQ_CAN0 29
+#define AT91SAM9X25_IRQ_CAN1 30
+#define AT91SAM9X25_IRQ_AICBASE 31
+
+/* Alias */
+#define AT91SAM9X25_IRQ_DBGU AT91SAM9X25_IRQ_SYSTEM
+#define AT91SAM9X25_IRQ_PMC AT91SAM9X25_IRQ_SYSTEM
+#define AT91SAM9X25_IRQ_WDT AT91SAM9X25_IRQ_SYSTEM
+#define AT91SAM9X25_IRQ_PIT AT91SAM9X25_IRQ_SYSTEM
+#define AT91SAM9X25_IRQ_RSTC AT91SAM9X25_IRQ_SYSTEM
+#define AT91SAM9X25_IRQ_OHCI AT91SAM9X25_IRQ_UHPHS
+#define AT91SAM9X25_IRQ_EHCI AT91SAM9X25_IRQ_UHPHS
+#define AT91SAM9X25_IRQ_PIOA AT91SAM9X25_IRQ_PIOAB
+#define AT91SAM9X25_IRQ_PIOB AT91SAM9X25_IRQ_PIOAB
+#define AT91SAM9X25_IRQ_PIOC AT91SAM9X25_IRQ_PIOCD
+#define AT91SAM9X25_IRQ_PIOD AT91SAM9X25_IRQ_PIOCD
+#define AT91SAM9X25_IRQ_NAND (-1)
+
+#define AT91SAM9X25_AIC_BASE 0xffff000
+#define AT91SAM9X25_AIC_SIZE 0x200
+
+/* Timer */
+
+#define AT91SAM9X25_WDT_BASE 0xffffd40
+#define AT91SAM9X25_WDT_SIZE 0x10
+
+#define AT91SAM9X25_PIT_BASE 0xffffd30
+#define AT91SAM9X25_PIT_SIZE 0x10
+
+#define AT91SAM9X25_SMC_BASE 0xfffea00
+#define AT91SAM9X25_SMC_SIZE 0x200
+
+#define AT91SAM9X25_PMC_BASE 0xffffc00
+#define AT91SAM9X25_PMC_SIZE 0x100
+
+#define AT91SAM9X25_UDPHS_BASE 0x803c000
+#define AT91SAM9X25_UDPHS_SIZE 0x4000
+
+#define AT91SAM9X25_HSMCI_SIZE 0x4000
+#define AT91SAM9X25_HSMCI0_BASE 0x0008000
+#define AT91SAM9X25_HSMCI0_SIZE AT91SAM9X25_HSMCI_SIZE
+#define AT91SAM9X25_HSMCI1_BASE 0x000c000
+#define AT91SAM9X25_HSMCI1_SIZE AT91SAM9X25_HSMCI_SIZE
+
+#define AT91SAM9X25_TWI_SIZE 0x4000
+#define AT91SAM9X25_TWI0_BASE 0xffaC000
+#define AT91SAM9X25_TWI0_SIZE AT91SAM9X25_TWI_SIZE
+#define AT91SAM9X25_TWI1_BASE 0xffaC000
+#define AT91SAM9X25_TWI1_SIZE AT91SAM9X25_TWI_SIZE
+#define AT91SAM9X25_TWI2_BASE 0xffaC000
+#define AT91SAM9X25_TWI2_SIZE AT91SAM9X25_TWI_SIZE
+
+/* XXX Needs to be carfully coordinated with
+ * other * soc's so phyical and vm address
+ * mapping are unique. XXX
+ */
+#define AT91SAM9X25_OHCI_BASE 0xdfc00000 /* SAME as 9c40 */
+#define AT91SAM9X25_OHCI_PA_BASE 0x00600000
+#define AT91SAM9X25_OHCI_SIZE 0x00100000
+
+#define AT91SAM9X25_EHCI_BASE 0xdfd00000
+#define AT91SAM9X25_EHCI_PA_BASE 0x00700000
+#define AT91SAM9X25_EHCI_SIZE 0x00100000
+
+#define AT91SAM9X25_NAND_BASE 0xe0000000
+#define AT91SAM9X25_NAND_PA_BASE 0x40000000
+#define AT91SAM9X25_NAND_SIZE 0x10000000
+
+
+/* SDRAMC */
+#define AT91SAM9X25_SDRAMC_BASE 0xfffea00 /* SAME as SMC? */
+#define AT91SAM9X25_SDRAMC_MR 0x00
+#define AT91SAM9X25_SDRAMC_MR_MODE_NORMAL 0
+#define AT91SAM9X25_SDRAMC_MR_MODE_NOP 1
+#define AT91SAM9X25_SDRAMC_MR_MODE_PRECHARGE 2
+#define AT91SAM9X25_SDRAMC_MR_MODE_LOAD_MODE_REGISTER 3
+#define AT91SAM9X25_SDRAMC_MR_MODE_REFRESH 4
+#define AT91SAM9X25_SDRAMC_TR 0x04
+#define AT91SAM9X25_SDRAMC_CR 0x08
+#define AT91SAM9X25_SDRAMC_CR_NC_8 0x0
+#define AT91SAM9X25_SDRAMC_CR_NC_9 0x1
+#define AT91SAM9X25_SDRAMC_CR_NC_10 0x2
+#define AT91SAM9X25_SDRAMC_CR_NC_11 0x3
+#define AT91SAM9X25_SDRAMC_CR_NC_MASK 0x00000003
+#define AT91SAM9X25_SDRAMC_CR_NR_11 0x0
+#define AT91SAM9X25_SDRAMC_CR_NR_12 0x4
+#define AT91SAM9X25_SDRAMC_CR_NR_13 0x8
+#define AT91SAM9X25_SDRAMC_CR_NR_RES 0xc
+#define AT91SAM9X25_SDRAMC_CR_NR_MASK 0x0000000c
+#define AT91SAM9X25_SDRAMC_CR_NB_2 0x00
+#define AT91SAM9X25_SDRAMC_CR_NB_4 0x10
+#define AT91SAM9X25_SDRAMC_CR_DBW_16 0x80
+#define AT91SAM9X25_SDRAMC_CR_NB_MASK 0x00000010
+#define AT91SAM9X25_SDRAMC_CR_NCAS_MASK 0x00000060
+#define AT91SAM9X25_SDRAMC_CR_TWR_MASK 0x00000780
+#define AT91SAM9X25_SDRAMC_CR_TRC_MASK 0x00007800
+#define AT91SAM9X25_SDRAMC_CR_TRP_MASK 0x00078000
+#define AT91SAM9X25_SDRAMC_CR_TRCD_MASK 0x00780000
+#define AT91SAM9X25_SDRAMC_CR_TRAS_MASK 0x07800000
+#define AT91SAM9X25_SDRAMC_CR_TXSR_MASK 0x78000000
+#define AT91SAM9X25_SDRAMC_HSR 0x0c
+#define AT91SAM9X25_SDRAMC_LPR 0x10
+#define AT91SAM9X25_SDRAMC_IER 0x14
+#define AT91SAM9X25_SDRAMC_IDR 0x18
+#define AT91SAM9X25_SDRAMC_IMR 0x1c
+#define AT91SAM9X25_SDRAMC_ISR 0x20
+#define AT91SAM9X25_SDRAMC_MDR 0x24
+
+#endif /* AT91SAM9X5REG_H_*/
Property changes on: trunk/sys/arm/at91/at91sam9x5reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91soc.c
===================================================================
--- trunk/sys/arm/at91/at91soc.c (rev 0)
+++ trunk/sys/arm/at91/at91soc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91soc.c 238376 2012-07-11 20:17:14Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91soc.h>
+
+SET_DECLARE(at91_socs, const struct at91_soc);
+
+struct at91_soc_data *
+at91_match_soc(enum at91_soc_type type, enum at91_soc_subtype subtype)
+{
+ const struct at91_soc **socp;
+
+ SET_FOREACH(socp, at91_socs) {
+ if ((*socp)->soc_type != type)
+ continue;
+ if ((*socp)->soc_subtype != AT91_ST_ANY &&
+ (*socp)->soc_subtype != subtype)
+ continue;
+ return (*socp)->soc_data;
+ }
+ return NULL;
+}
Property changes on: trunk/sys/arm/at91/at91soc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91soc.h
===================================================================
--- trunk/sys/arm/at91/at91soc.h (rev 0)
+++ trunk/sys/arm/at91/at91soc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,59 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91soc.h 238376 2012-07-11 20:17:14Z imp $ */
+
+#ifndef _ARM_AT91_AT91SOC_H_
+#define _ARM_AT91_AT91SOC_H_
+
+#include <sys/linker_set.h>
+
+struct at91_soc {
+ enum at91_soc_type soc_type; /* Family of mail type of SoC */
+ enum at91_soc_subtype soc_subtype; /* More specific soc, if any */
+ struct at91_soc_data *soc_data;
+};
+
+// Make varadic
+#define AT91_SOC(type, data) \
+ static struct at91_soc this_soc = { \
+ .soc_type = type, \
+ .soc_subtype = AT91_ST_ANY, \
+ .soc_data = data, \
+ }; \
+ DATA_SET(at91_socs, this_soc);
+
+#define AT91_SOC_SUB(type, subtype, data) \
+ static struct at91_soc this_soc = { \
+ .soc_type = type, \
+ .soc_subtype = subtype, \
+ .soc_data = data, \
+ }; \
+ DATA_SET(at91_socs, this_soc);
+
+struct at91_soc_data *at91_match_soc(enum at91_soc_type, enum at91_soc_subtype);
+
+#endif /* _ARM_AT91_AT91SOC_H_ */
Property changes on: trunk/sys/arm/at91/at91soc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/at91var.h
===================================================================
--- trunk/sys/arm/at91/at91var.h (rev 0)
+++ trunk/sys/arm/at91/at91var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,173 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/at91var.h 266087 2014-05-14 20:31:54Z ian $ */
+
+#ifndef _AT91VAR_H_
+#define _AT91VAR_H_
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <arm/at91/at91reg.h>
+
+struct at91_softc {
+ device_t dev;
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_sh;
+ bus_space_handle_t sc_aic_sh;
+ struct rman sc_irq_rman;
+ struct rman sc_mem_rman;
+};
+
+struct at91_ivar {
+ struct resource_list resources;
+};
+
+struct cpu_devs
+{
+ const char *name;
+ int unit;
+ bus_addr_t mem_base;
+ bus_size_t mem_len;
+ int irq0;
+ int irq1;
+ int irq2;
+ const char *parent_clk;
+};
+
+enum at91_soc_type {
+ AT91_T_NONE = 0,
+ AT91_T_CAP9,
+ AT91_T_RM9200,
+ AT91_T_SAM9260,
+ AT91_T_SAM9261,
+ AT91_T_SAM9263,
+ AT91_T_SAM9G10,
+ AT91_T_SAM9G20,
+ AT91_T_SAM9G45,
+ AT91_T_SAM9N12,
+ AT91_T_SAM9RL,
+ AT91_T_SAM9X5,
+};
+
+enum at91_soc_subtype {
+ AT91_ST_ANY = -1, /* Match any type */
+ AT91_ST_NONE = 0,
+ /* AT91RM9200 */
+ AT91_ST_RM9200_BGA,
+ AT91_ST_RM9200_PQFP,
+ /* AT91SAM9260 */
+ AT91_ST_SAM9XE,
+ /* AT91SAM9G45 */
+ AT91_ST_SAM9G45,
+ AT91_ST_SAM9M10,
+ AT91_ST_SAM9G46,
+ AT91_ST_SAM9M11,
+ /* AT91SAM9X5 */
+ AT91_ST_SAM9G15,
+ AT91_ST_SAM9G25,
+ AT91_ST_SAM9G35,
+ AT91_ST_SAM9X25,
+ AT91_ST_SAM9X35,
+};
+
+enum at91_soc_family {
+ AT91_FAMILY_SAM9 = 0x19,
+ AT91_FAMILY_SAM9XE = 0x29,
+ AT91_FAMILY_RM92 = 0x92,
+};
+
+#define AT91_SOC_NAME_MAX 50
+
+typedef void (*DELAY_t)(int);
+typedef void (*cpu_reset_t)(void);
+typedef void (*clk_init_t)(void);
+
+struct at91_soc_data {
+ DELAY_t soc_delay; /* SoC specific delay function */
+ cpu_reset_t soc_reset; /* SoC specific reset function */
+ clk_init_t soc_clock_init; /* SoC specific clock init function */
+ const int *soc_irq_prio; /* SoC specific IRQ priorities */
+ const struct cpu_devs *soc_children; /* SoC specific children list */
+ const uint32_t *soc_pio_base; /* SoC specific PIO base registers */
+ size_t soc_pio_count; /* Count of PIO units (not pins) in SoC */
+};
+
+struct at91_soc_info {
+ enum at91_soc_type type;
+ enum at91_soc_subtype subtype;
+ enum at91_soc_family family;
+ uint32_t cidr;
+ uint32_t exid;
+ char name[AT91_SOC_NAME_MAX];
+ uint32_t dbgu_base;
+ struct at91_soc_data *soc_data;
+};
+
+extern struct at91_soc_info soc_info;
+
+static inline int at91_is_rm92(void);
+static inline int at91_is_sam9(void);
+static inline int at91_is_sam9xe(void);
+static inline int at91_cpu_is(u_int cpu);
+
+static inline int
+at91_is_rm92(void)
+{
+
+ return (soc_info.type == AT91_T_RM9200);
+}
+
+static inline int
+at91_is_sam9(void)
+{
+
+ return (soc_info.family == AT91_FAMILY_SAM9);
+}
+
+static inline int
+at91_is_sam9xe(void)
+{
+
+ return (soc_info.family == AT91_FAMILY_SAM9XE);
+}
+
+static inline int
+at91_cpu_is(u_int cpu)
+{
+
+ return (soc_info.type == cpu);
+}
+
+void at91_add_child(device_t dev, int prio, const char *name, int unit,
+ bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2);
+
+extern uint32_t at91_irq_system;
+extern uint32_t at91_master_clock;
+void at91_pmc_init_clock(void);
+
+#endif /* _AT91VAR_H_ */
Property changes on: trunk/sys/arm/at91/at91var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_bwct.c
===================================================================
--- trunk/sys/arm/at91/board_bwct.c (rev 0)
+++ trunk/sys/arm/at91/board_bwct.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,55 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005-2008 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2005-2012 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_bwct.c 238465 2012-07-15 05:41:43Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91rm9200var.h>
+
+BOARD_INIT long
+board_init(void)
+{
+
+ at91rm9200_set_subtype(AT91_ST_RM9200_BGA);
+
+ /*
+ * I don't know anything at all about this board.
+ */
+ at91rm9200_config_uart(AT91_ID_DBGU, 0, 0); /* DBGU just Tx and Rx */
+
+ at91rm9200_config_mci(0);
+ /* Configure ethernet */
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(NONE, "BWCT special");
Property changes on: trunk/sys/arm/at91/board_bwct.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_eb9200.c
===================================================================
--- trunk/sys/arm/at91/board_eb9200.c (rev 0)
+++ trunk/sys/arm/at91/board_eb9200.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,69 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005-2008 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2005-2012 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_eb9200.c 266196 2014-05-15 21:21:47Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91rm9200var.h>
+
+BOARD_INIT long
+board_init(void)
+{
+
+ at91rm9200_set_subtype(AT91_ST_RM9200_BGA);
+
+ /*
+ * Setup the serial ports.
+ * DBGU and USART0 are DB9 ports.
+ * USART2 is IrDA.
+ */
+ at91rm9200_config_uart(AT91_ID_DBGU, 0, 0); /* DBGU just Tx and Rx */
+ at91rm9200_config_uart(AT91RM9200_ID_USART0, 1,
+ AT91_UART_CTS | AT91_UART_RTS | AT91_UART_DTR | AT91_UART_DSR |
+ AT91_UART_DCD | AT91_UART_RI);
+ at91rm9200_config_uart(AT91RM9200_ID_USART1, 2, 0);
+
+ at91rm9200_config_mci(1);
+
+ /* CFE interface */
+ /* SPI interface */
+ /* ethernet interface */
+ /* USB host */
+ /* USB device (gadget) */
+ /* TWI */
+ /* CF interface */
+ /* SmartMedia Interface */
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(ATEB9200, "Embest ATEB9200")
Property changes on: trunk/sys/arm/at91/board_eb9200.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_ethernut5.c
===================================================================
--- trunk/sys/arm/at91/board_ethernut5.c (rev 0)
+++ trunk/sys/arm/at91/board_ethernut5.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,150 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Marius Strobl <marius at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Ethernut 5 board support
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_ethernut5.c 238442 2012-07-14 06:00:37Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <machine/board.h>
+#include <arm/at91/at91_pioreg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91sam9260reg.h>
+
+BOARD_INIT long
+board_init(void)
+{
+
+ /*
+ * DBGU
+ */
+ /* DRXD */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB14, 0);
+ /* DTXD */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB15, 1);
+
+ /*
+ * EMAC
+ */
+ /* ETX0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA12, 0);
+ /* ETX1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA13, 0);
+ /* ERX0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA14, 0);
+ /* ERX1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA15, 0);
+ /* ETXEN */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA16, 0);
+ /* ERXDV */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA17, 0);
+ /* ERXER */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA18, 0);
+ /* ETXCK */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA19, 0);
+ /* EMDC */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA20, 0);
+ /* EMDIO */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA21, 0);
+
+ /*
+ * MMC
+ */
+ /* MCDA0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA6, 1);
+ /* MCCDA */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA7, 1);
+ /* MCCK */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA8, 1);
+ /* MCDA1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA9, 1);
+ /* MCDA2 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA10, 1);
+ /* MCDA3 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA11, 1);
+
+ /*
+ * SPI0
+ */
+ /* MISO */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA0, 0);
+ /* MOSI */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA1, 0);
+ /* SPCK */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA2, 0);
+ /* NPCS0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA3, 0);
+
+ /*
+ * TWI
+ */
+ /* TWD */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA23, 1);
+ /* TWCK */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA24, 1);
+
+ /*
+ * USART0
+ */
+ /* TXD0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB4, 1);
+ /* RXD0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB5, 0);
+ /* DSR0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB22, 0);
+ /* DCD0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB23, 0);
+ /* DTR0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB24, 1);
+ /* RI0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB25, 0);
+ /* RTS0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB26, 1);
+ /* CTS0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB27, 0);
+
+ /*
+ * USART2
+ */
+ /* RTS2 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA4, 1);
+ /* CTS2 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA5, 0);
+ /* TXD2 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB8, 1);
+ /* RXD2 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB9, 0);
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(ETHERNUT5, "Ethernut 5")
Property changes on: trunk/sys/arm/at91/board_ethernut5.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_hl200.c
===================================================================
--- trunk/sys/arm/at91/board_hl200.c (rev 0)
+++ trunk/sys/arm/at91/board_hl200.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,66 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005-2008 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2005-2012 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_hl200.c 238465 2012-07-15 05:41:43Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91rm92reg.h>
+#include <arm/at91/at91rm9200var.h>
+
+BOARD_INIT long
+board_init(void)
+{
+
+ at91rm9200_set_subtype(AT91_ST_RM9200_BGA);
+
+ /*
+ * Unsure what all is in the HOTe HL200, but I do know there's
+ * one serial port that isn't DBGU. There's many other peripherals
+ * that need to be configured here.
+ */
+ at91rm9200_config_uart(AT91_ID_DBGU, 0, 0); /* DBGU just Tx and Rx */
+ at91rm9200_config_uart(AT91RM9200_ID_USART0, 1, 0); /* Tx and Rx */
+
+ at91rm9200_config_mci(0); /* HOTe HL200 unknown 1 vs 4 wire */
+
+ /* Enable CF card slot */
+ /* Enable sound thing */
+ /* Enable VGA chip */
+ /* Enable ethernet */
+ /* Enable TWI + RTC */
+ /* Enable USB Host */
+ /* Enable USB Device (gadget) */
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(NONE, "HOTe 200");
Property changes on: trunk/sys/arm/at91/board_hl200.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_hl201.c
===================================================================
--- trunk/sys/arm/at91/board_hl201.c (rev 0)
+++ trunk/sys/arm/at91/board_hl201.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,71 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005-2008 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2005-2008 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_hl201.c 238189 2012-07-07 05:02:39Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91sam9g20reg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91_pio_sam9g20.h>
+
+BOARD_INIT long
+board_init(void)
+{
+ /* Setup Ethernet Pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, 1<<7, 0);
+
+ at91_pio_gpio_input(AT91SAM9G20_PIOA_BASE, 1<<7);
+ at91_pio_gpio_set_deglitch(AT91SAM9G20_PIOA_BASE, 1<<7, 1);
+
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA19, 0); /* ETXCK_EREFCK */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA17, 0); /* ERXDV */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA14, 0); /* ERX0 */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA15, 0); /* ERX1 */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA18, 0); /* ERXER */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA16, 0); /* ETXEN */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA12, 0); /* ETX0 */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA13, 0); /* ETX1 */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA21, 0); /* EMDIO */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA20, 0); /* EMDC */
+
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA28, 0); /* ECRS */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA29, 0); /* ECOL */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA25, 0); /* ERX2 */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA26, 0); /* ERX3 */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA27, 0); /* ERXCK */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA23, 0); /* ETX2 */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA24, 0); /* ETX3 */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA22, 0); /* ETXER */
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(NONE, "HOTe 201");
Property changes on: trunk/sys/arm/at91/board_hl201.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_kb920x.c
===================================================================
--- trunk/sys/arm/at91/board_kb920x.c (rev 0)
+++ trunk/sys/arm/at91/board_kb920x.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,67 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005-2008 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2005-2012 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_kb920x.c 238465 2012-07-15 05:41:43Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91rm9200var.h>
+
+BOARD_INIT long
+board_init(void)
+{
+
+ at91rm9200_set_subtype(AT91_ST_RM9200_PQFP);
+
+ /*
+ * Setup the serial ports.
+ * DBGU is the main one, although jumpers can make USART0 default.
+ * USART1 is IrDA, and USART3 is optional RS485.
+ */
+ at91rm9200_config_uart(AT91_ID_DBGU, 0, 0); /* DBGU just Tx and Rx */
+ at91rm9200_config_uart(AT91RM9200_ID_USART0, 1, 0); /* Tx and Rx */
+ at91rm9200_config_uart(AT91RM9200_ID_USART1, 2, 0); /* Tx and Rx - IRDA */
+ at91rm9200_config_uart(AT91RM9200_ID_USART3, 3, /* Tx, Rx, CTS, RTS - RS485 */
+ AT91_UART_CTS | AT91_UART_RTS);
+
+ at91rm9200_config_mci(1);
+
+ /* CFE interface */
+ /* ethernet interface */
+ /* lcd interface */
+ /* USB host */
+ /* USB device (gadget) */
+ /* TWI */
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(KB9200, "Kwikbyte KB920x")
Property changes on: trunk/sys/arm/at91/board_kb920x.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_qila9g20.c
===================================================================
--- trunk/sys/arm/at91/board_qila9g20.c (rev 0)
+++ trunk/sys/arm/at91/board_qila9g20.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,109 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Calao Systems QIL-9G20-Cxx
+ * http://www.calao-systems.com
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_qila9g20.c 238189 2012-07-07 05:02:39Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91sam9g20reg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91_pio_sam9g20.h>
+//#include <arm/at91/at91_led.h>
+
+#define AT91SAM9G20_LED_BASE AT91SAM9G20_PIOA_BASE
+#define AT91SAM9G20_LED_SIZE AT91SAM9G20_PIO_SIZE
+#define AT91SAM9G20_IRQ_LED AT91SAM9G20_IRQ_PIOA
+
+BOARD_INIT long
+board_init(void)
+{
+
+ //at91_led_create("power", 0, 9, 0);
+
+ /* PIOB's A periph: Turn USART 0's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB14_DRXD, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB15_DTXD, 1);
+
+ /* PIOB's A periph: Turn USART 0's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB4_TXD0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB5_RXD0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB22_DSR0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB23_DCD0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB24_DTR0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB25_RI0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB26_RTS0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB27_CTS0, 0);
+
+ /* PIOB's A periph: Turn USART 1's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB6_TXD1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB7_RXD1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB28_RTS1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB29_CTS1, 0);
+
+ /* TWI Two-wire Serial Data */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA23_TWD, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA24_TWCK, 1);
+
+ /* Multimedia Card */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA6_MCDA0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA7_MCCDA, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA8_MCCK, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA9_MCDA1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA10_MCDA2, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA11_MCDA3, 1);
+
+ /* SPI0 to DataFlash */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PA0_SPI0_MISO, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PA1_SPI0_MOSI, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PA2_SPI0_SPCK, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PA3_SPI0_NPCS0, 0);
+
+ /* EMAC */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA19_ETXCK, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA21_EMDIO, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA20_EMDC, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA17_ERXDV, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA16_ETXEN, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA12_ETX0 , 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA13_ETX1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA14_ERX0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA15_ERX1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA18_ERXER, 0);
+
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(QIL_A9G20, "Calico System QIL-9G20-Cxx");
Property changes on: trunk/sys/arm/at91/board_qila9g20.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_sam9260ek.c
===================================================================
--- trunk/sys/arm/at91/board_sam9260ek.c (rev 0)
+++ trunk/sys/arm/at91/board_sam9260ek.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,263 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Marius Strobl <marius at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Ethernut 5 board support
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_sam9260ek.c 266097 2014-05-14 23:51:07Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <machine/board.h>
+#include <arm/at91/at91_pioreg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91sam9260reg.h>
+#include <arm/at91/at91_smc.h>
+#include <arm/at91/at91_gpio.h>
+#include <dev/nand/nfc_at91.h>
+
+static struct at91_smc_init nand_smc = {
+ .ncs_rd_setup = 0,
+ .nrd_setup = 1,
+ .ncs_wr_setup = 0,
+ .nwe_setup = 1,
+
+ .ncs_rd_pulse = 3,
+ .nrd_pulse = 3,
+ .ncs_wr_pulse = 3,
+ .nwe_pulse = 3,
+
+ .nrd_cycle = 5,
+ .nwe_cycle = 5,
+
+ .mode = SMC_MODE_READ | SMC_MODE_WRITE | SMC_MODE_EXNW_DISABLED,
+ .tdf_cycles = 2,
+};
+
+static struct at91_nand_params nand_param = {
+ .ale = 1u << 21,
+ .cle = 1u << 22,
+ .width = 8,
+ .rnb_pin = AT91_PIN_PC13,
+ .nce_pin = AT91_PIN_PC14,
+ .cs = 3,
+};
+
+static void
+bi_dbgu(void)
+{
+
+ /*
+ * DBGU
+ */
+ /* DRXD */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB14, 0);
+ /* DTXD */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB15, 1);
+}
+
+static void
+bi_emac(void)
+{
+
+ /*
+ * EMAC
+ */
+ /* ETX0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA12, 0);
+ /* ETX1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA13, 0);
+ /* ERX0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA14, 0);
+ /* ERX1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA15, 0);
+ /* ETXEN */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA16, 0);
+ /* ERXDV */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA17, 0);
+ /* ERXER */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA18, 0);
+ /* ETXCK */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA19, 0);
+ /* EMDC */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA20, 0);
+ /* EMDIO */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA21, 0);
+ /* Not RMII */
+ /* ETX2 */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA10, 0);
+ /* ETX3 */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA11, 0);
+ /* ETXER */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA22, 0);
+ /* ERX2 */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA25, 0);
+ /* ERX3 */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA26, 0);
+ /* ERXCK */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA27, 0);
+ /* ECRS */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA28, 0);
+ /* ECOL */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA29, 0);
+}
+
+static void
+bi_mmc(void)
+{
+
+ /*
+ * MMC, wired to socket B.
+ */
+ /* MCDB0 */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA0, 1);
+ /* MCCDB */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA1, 1);
+ /* MCDB3 */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA3, 1);
+ /* MCDB2 */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA4, 1);
+ /* MCDB1 */
+ at91_pio_use_periph_b(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA5, 1);
+ /* MCCK */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA8, 1);
+
+ /*
+ * SPI0 and MMC are wired together, since we don't support sharing
+ * don't support the dataflash. But if you did, you'd have to
+ * use CS0 and CS1.
+ */
+}
+
+static void
+bi_iic(void)
+{
+
+ /*
+ * TWI. Only one child on the iic bus, which we take care of
+ * via hints.
+ */
+ /* TWD */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA23, 1);
+ /* TWCK */
+ at91_pio_use_periph_a(AT91SAM9260_PIOA_BASE, AT91C_PIO_PA24, 1);
+}
+
+static void
+bi_usart0(void)
+{
+
+ /*
+ * USART0
+ */
+ /* TXD0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB4, 1);
+ /* RXD0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB5, 0);
+ /* DSR0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB22, 0);
+ /* DCD0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB23, 0);
+ /* DTR0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB24, 1);
+ /* RI0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB25, 0);
+ /* RTS0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB26, 1);
+ /* CTS0 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB27, 0);
+}
+
+static void
+bi_usart1(void)
+{
+ /*
+ * USART1
+ */
+ /* RTS1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB28, 1);
+ /* CTS1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB29, 0);
+ /* TXD1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB6, 1);
+ /* RXD1 */
+ at91_pio_use_periph_a(AT91SAM9260_PIOB_BASE, AT91C_PIO_PB7, 0);
+}
+
+static void
+bi_nand(void)
+{
+ /* Samsung 256MB SLC Flash */
+
+ /* Setup Static Memory Controller */
+ at91_smc_setup(0, 3, &nand_smc);
+ at91_enable_nand(&nand_param);
+
+ /*
+ * This assumes
+ * - RNB is on pin PC13
+ * - CE is on pin PC14
+ *
+ * Nothing actually uses RNB right now.
+ *
+ * For CE, this currently asserts it during board setup and leaves it
+ * that way forever.
+ *
+ * All this can go away when the gpio pin-renumbering happens...
+ */
+ at91_pio_use_gpio(AT91SAM9260_PIOC_BASE, AT91C_PIO_PC13 | AT91C_PIO_PC14);
+ at91_pio_gpio_input(AT91SAM9260_PIOC_BASE, AT91C_PIO_PC13); /* RNB */
+ at91_pio_gpio_output(AT91SAM9260_PIOC_BASE, AT91C_PIO_PC14, 0); /* nCS */
+ at91_pio_gpio_clear(AT91SAM9260_PIOC_BASE, AT91C_PIO_PC14); /* Assert nCS */
+}
+
+BOARD_INIT long
+board_init(void)
+{
+ bi_dbgu();
+ bi_emac();
+ bi_mmc();
+
+ /*
+ * SPI1 is wired to a audio CODEC that we don't support, so
+ * give it a pass.
+ */
+
+ bi_iic();
+ bi_usart0();
+ bi_usart1();
+ /* USART2 - USART5 aren't wired up, except via PIO pins, ignore them. */
+
+ bi_nand();
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(AT91SAM9260EK, "Atmel SMA9260-EK")
Property changes on: trunk/sys/arm/at91/board_sam9260ek.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_sam9g20ek.c
===================================================================
--- trunk/sys/arm/at91/board_sam9g20ek.c (rev 0)
+++ trunk/sys/arm/at91/board_sam9g20ek.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,128 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This board file can be used for both:
+ * Atmel SAM9G20-EK Development Card
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_sam9g20ek.c 238189 2012-07-07 05:02:39Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91sam9g20reg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91_pio_sam9g20.h>
+//#include <arm/at91/at91_led.h>
+
+BOARD_INIT long
+board_init(void)
+{
+ /* PIOB's A periph: Turn USART 0's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB14_DRXD, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB15_DTXD, 1);
+
+ /* PIOB's A periph: Turn USART 0's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB4_TXD0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB5_RXD0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB22_DSR0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB23_DCD0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB24_DTR0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB25_RI0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB26_RTS0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB27_CTS0, 0);
+
+ /* PIOB's A periph: Turn USART 1's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB6_TXD1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB7_RXD1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB28_RTS1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB29_CTS1, 0);
+
+ /* TWI Two-wire Serial Data */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA23_TWD, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA24_TWCK, 1);
+
+#if 1
+ /*
+ * Turn off Clock to DataFlash, conflicts with MCI clock.
+ */
+ at91_pio_use_gpio(AT91SAM9G20_PIOA_BASE,AT91C_PIO_PA2);
+ at91_pio_gpio_input(AT91SAM9G20_PIOA_BASE,AT91C_PIO_PA2);
+
+ /* Turn off chip select to DataFlash */
+ at91_pio_gpio_output(AT91SAM9G20_PIOC_BASE,AT91C_PIO_PC11, 0);
+ at91_pio_gpio_set(AT91SAM9G20_PIOC_BASE,AT91C_PIO_PC11);
+ at91_pio_use_gpio(AT91SAM9G20_PIOC_BASE,AT91C_PIO_PC11);
+
+ /* Multimedia Card */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA0_MCDB0, 1);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA1_MCCDB, 1);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA3_MCDB3, 1);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA4_MCDB2, 1);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA5_MCDB1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA8_MCCK, 1);
+ at91_pio_use_gpio(AT91SAM9G20_PIOC_BASE, AT91C_PIO_PC9);
+#else
+ /* SPI0 to DataFlash */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA2, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOC_BASE, AT91C_PIO_PC11,0);
+
+ at91_pio_gpio_input(AT91SAM9G20_PIOA_BASE,AT91C_PIO_PA8);
+ at91_pio_use_gpio(AT91SAM9G20_PIOA_BASE,AT91C_PIO_PA8);
+#endif
+
+ /* EMAC */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA12_ETX0 , 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA13_ETX1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA14_ERX0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA15_ERX1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA16_ETXEN, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA17_ERXDV, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA18_ERXER, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA19_ETXCK, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA20_EMDC, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA21_EMDIO, 0);
+
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA10_ETX2_0, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA11_ETX3_0, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA22_ETXER, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA25_ERX2, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA26_ERX3, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA27_ERXCK, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA28_ECRS, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA29_ECOL, 0);
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(AT91SAM9G20, "Atmel SAM9G20-EK Development Card");
Property changes on: trunk/sys/arm/at91/board_sam9g20ek.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_sam9x25ek.c
===================================================================
--- trunk/sys/arm/at91/board_sam9x25ek.c (rev 0)
+++ trunk/sys/arm/at91/board_sam9x25ek.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,129 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This board file can be used for both:
+ * SAM9X26EK board
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_sam9x25ek.c 238189 2012-07-07 05:02:39Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91sam9g20reg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91_pio_sam9g20.h>
+//#include <arm/at91/at91_led.h>
+
+BOARD_INIT long
+board_init(void)
+{
+#if 0
+ /* PIOB's A periph: Turn USART 0's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB14_DRXD, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB15_DTXD, 1);
+
+ /* PIOB's A periph: Turn USART 0's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB4_TXD0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB5_RXD0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB22_DSR0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB23_DCD0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB24_DTR0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB25_RI0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB26_RTS0, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB27_CTS0, 0);
+
+ /* PIOB's A periph: Turn USART 1's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB6_TXD1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB7_RXD1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB28_RTS1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOB_BASE, AT91C_PB29_CTS1, 0);
+
+ /* TWI Two-wire Serial Data */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA23_TWD, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA24_TWCK, 1);
+
+#if 1
+ /*
+ * Turn off Clock to DataFlash, conflicts with MCI clock.
+ */
+ at91_pio_use_gpio(AT91SAM9G20_PIOA_BASE,AT91C_PIO_PA2);
+ at91_pio_gpio_input(AT91SAM9G20_PIOA_BASE,AT91C_PIO_PA2);
+
+ /* Turn off chip select to DataFlash */
+ at91_pio_gpio_output(AT91SAM9G20_PIOC_BASE,AT91C_PIO_PC11, 0);
+ at91_pio_gpio_set(AT91SAM9G20_PIOC_BASE,AT91C_PIO_PC11);
+ at91_pio_use_gpio(AT91SAM9G20_PIOC_BASE,AT91C_PIO_PC11);
+
+ /* Multimedia Card */
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA0_MCDB0, 1);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA1_MCCDB, 1);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA3_MCDB3, 1);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA4_MCDB2, 1);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA5_MCDB1, 1);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA8_MCCK, 1);
+ at91_pio_use_gpio(AT91SAM9G20_PIOC_BASE, AT91C_PIO_PC9);
+#else
+ /* SPI0 to DataFlash */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE, AT91C_PIO_PA2, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOC_BASE, AT91C_PIO_PC11,0);
+
+ at91_pio_gpio_input(AT91SAM9G20_PIOA_BASE,AT91C_PIO_PA8);
+ at91_pio_use_gpio(AT91SAM9G20_PIOA_BASE,AT91C_PIO_PA8);
+#endif
+
+ /* EMAC */
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA12_ETX0 , 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA13_ETX1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA14_ERX0, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA15_ERX1, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA16_ETXEN, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA17_ERXDV, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA18_ERXER, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA19_ETXCK, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA20_EMDC, 0);
+ at91_pio_use_periph_a(AT91SAM9G20_PIOA_BASE,AT91C_PA21_EMDIO, 0);
+
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA10_ETX2_0, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA11_ETX3_0, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA22_ETXER, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA25_ERX2, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA26_ERX3, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA27_ERXCK, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA28_ECRS, 0);
+ at91_pio_use_periph_b(AT91SAM9G20_PIOA_BASE,AT91C_PA29_ECOL, 0);
+#endif
+ return (at91_ramsize());
+}
+
+ARM_BOARD(AT91SAM9X5EK, "Atmel AT91SAM9x-EK Evaluation Board");
Property changes on: trunk/sys/arm/at91/board_sam9x25ek.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_sn9g45.c
===================================================================
--- trunk/sys/arm/at91/board_sn9g45.c (rev 0)
+++ trunk/sys/arm/at91/board_sn9g45.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,56 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * DesignA Electronics Snapper9g45
+ * http://www.designa-electronics.com/
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_sn9g45.c 238846 2012-07-27 16:38:02Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91sam9g45reg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91_pio_sam9g45.h>
+
+BOARD_INIT long
+board_init(void)
+{
+
+ /* PIOB's A periph: Turn the debug USART's TX/RX pins */
+ at91_pio_use_periph_a(AT91SAM9G45_PIOB_BASE, AT91C_PB12_DRXD, 0);
+ at91_pio_use_periph_a(AT91SAM9G45_PIOB_BASE, AT91C_PB13_DTXD, 1);
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(SNAPPER9G45, "DesignA Electronics Snapper9G45");
Property changes on: trunk/sys/arm/at91/board_sn9g45.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/board_tsc4370.c
===================================================================
--- trunk/sys/arm/at91/board_tsc4370.c (rev 0)
+++ trunk/sys/arm/at91/board_tsc4370.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,73 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005-2008 Olivier Houchard. All rights reserved.
+ * Copyright (c) 2005-2012 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/board_tsc4370.c 238465 2012-07-15 05:41:43Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/board.h>
+#include <arm/at91/at91board.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/at91rm92reg.h>
+#include <arm/at91/at91rm9200var.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91_pioreg.h>
+
+BOARD_INIT long
+board_init(void)
+{
+
+ at91rm9200_set_subtype(AT91_ST_RM9200_PQFP);
+
+ at91rm9200_config_uart(AT91_ID_DBGU, 0, 0); /* DBGU just Tx and Rx */
+ at91rm9200_config_uart(AT91RM9200_ID_USART0, 1, 0); /* Tx and Rx */
+ at91rm9200_config_uart(AT91RM9200_ID_USART1, 2, 0); /* Tx and Rx */
+ at91rm9200_config_uart(AT91RM9200_ID_USART2, 3, 0); /* Tx and Rx */
+ at91rm9200_config_uart(AT91RM9200_ID_USART3, 4, 0); /* Tx and Rx */
+
+ at91rm9200_config_mci(0); /* tsc4370 board has only 1 wire */
+ /* Newer boards may have 4 wires */
+
+ /* Configure TWI */
+ /* Configure SPI + dataflash */
+ /* Configure SSC */
+ /* Configure USB Host */
+ /* Configure FPGA attached to chip selects */
+
+ /* Pin assignment */
+ /* Assert PA24 low -- talk to rubidium */
+ at91_pio_use_gpio(AT91RM92_PIOA_BASE, AT91C_PIO_PA24);
+ at91_pio_gpio_output(AT91RM92_PIOA_BASE, AT91C_PIO_PA24, 0);
+ at91_pio_gpio_clear(AT91RM92_PIOA_BASE, AT91C_PIO_PA24);
+ at91_pio_use_gpio(AT91RM92_PIOB_BASE,
+ AT91C_PIO_PB16 | AT91C_PIO_PB17 | AT91C_PIO_PB18 | AT91C_PIO_PB19);
+
+ return (at91_ramsize());
+}
+
+ARM_BOARD(NONE, "TSC4370 Controller Board");
Property changes on: trunk/sys/arm/at91/board_tsc4370.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/files.at91
===================================================================
--- trunk/sys/arm/at91/files.at91 (rev 0)
+++ trunk/sys/arm/at91/files.at91 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,59 @@
+# $FreeBSD: stable/10/sys/arm/at91/files.at91 278727 2015-02-13 22:32:02Z ian $
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_arm9.S standard
+arm/at91/at91_machdep.c standard
+arm/at91/at91_aic.c standard
+arm/at91/at91.c standard
+arm/at91/at91_cfata.c optional at91_cfata
+arm/at91/at91_mci.c optional at91_mci
+dev/nand/nfc_at91.c optional nand
+arm/at91/at91_pio.c standard
+arm/at91/at91_pmc.c standard
+arm/at91/at91_pit.c optional at91sam9
+arm/at91/at91_reset.S optional at91sam9
+arm/at91/at91_rst.c optional at91sam9
+arm/at91/at91_rtc.c optional at91_rtc
+arm/at91/at91_smc.c standard
+arm/at91/at91_spi.c optional at91_spi \
+ dependency "spibus_if.h"
+arm/at91/at91_ssc.c optional at91_ssc
+arm/at91/at91_st.c optional at91rm9200
+arm/at91/at91_tc.c optional at91_tc
+arm/at91/at91_twi.c optional at91_twi
+arm/at91/at91_wdt.c optional at91_wdt
+arm/at91/if_ate.c optional ate
+arm/at91/if_macb.c optional macb
+arm/at91/uart_bus_at91usart.c optional uart
+arm/at91/uart_cpu_at91usart.c optional uart
+arm/at91/uart_dev_at91usart.c optional uart
+#
+# All the "systems on a chip" we support
+#
+arm/at91/at91soc.c standard
+arm/at91/at91rm9200.c optional at91rm9200
+arm/at91/at91rm9200_devices.c optional at91rm9200
+arm/at91/at91sam9260.c optional at91sam9260
+arm/at91/at91sam9g20.c optional at91sam9g20
+arm/at91/at91sam9g45.c optional at91sam9g45
+arm/at91/at91sam9x5.c optional at91sam9x5
+#
+# All the boards we support
+#
+arm/at91/board_bwct.c optional at91_board_bwct
+arm/at91/board_eb9200.c optional at91_board_eb9200
+arm/at91/board_ethernut5.c optional at91_board_ethernut5
+arm/at91/board_hl200.c optional at91_board_hl200
+arm/at91/board_hl201.c optional at91_board_hl201
+arm/at91/board_kb920x.c optional at91_board_kb920x
+arm/at91/board_qila9g20.c optional at91_board_qila9g20
+arm/at91/board_sam9260ek.c optional at91_board_sam9260ek
+arm/at91/board_sam9g20ek.c optional at91_board_sam9g20ek
+arm/at91/board_sam9x25ek.c optional at91_board_sam9x25ek
+arm/at91/board_sn9g45.c optional at91_board_sn9g45
+arm/at91/board_tsc4370.c optional at91_board_tsc4370
+#
+# usb
+#
+dev/usb/controller/at91dci.c optional at91_dci
+dev/usb/controller/at91dci_atmelarm.c optional at91_dci
+dev/usb/controller/ohci_atmelarm.c optional ohci
Property changes on: trunk/sys/arm/at91/files.at91
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/if_ate.c
===================================================================
--- trunk/sys/arm/at91/if_ate.c (rev 0)
+++ trunk/sys/arm/at91/if_ate.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1480 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2009 Greg Ansley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* TODO
+ *
+ * 1) Turn on the clock in pmc? Turn off?
+ * 2) GPIO initializtion in board setup code.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/if_ate.c 266196 2014-05-15 21:21:47Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_mib.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include "opt_at91.h"
+#include <arm/at91/at91reg.h>
+#include <arm/at91/at91var.h>
+#include <arm/at91/if_atereg.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#include "miibus_if.h"
+
+/*
+ * Driver-specific flags.
+ */
+#define ATE_FLAG_DETACHING 0x01
+#define ATE_FLAG_MULTICAST 0x02
+
+/*
+ * Old EMAC assumes whole packet fits in one buffer;
+ * new EBACB assumes all receive buffers are 128 bytes
+ */
+#define RX_BUF_SIZE(sc) (sc->is_emacb ? 128 : MCLBYTES)
+
+/*
+ * EMACB has an 11 bit counter for Rx/Tx Descriptors
+ * for max total of 1024 decriptors each.
+ */
+#define ATE_MAX_RX_DESCR 1024
+#define ATE_MAX_TX_DESCR 1024
+
+/* How many buffers to allocate */
+#define ATE_MAX_TX_BUFFERS 4 /* We have ping-pong tx buffers */
+
+/* How much memory to use for rx buffers */
+#define ATE_RX_MEMORY (ATE_MAX_RX_DESCR * 128)
+
+/* Actual number of descriptors we allocate */
+#define ATE_NUM_RX_DESCR ATE_MAX_RX_DESCR
+#define ATE_NUM_TX_DESCR ATE_MAX_TX_BUFFERS
+
+#if ATE_NUM_TX_DESCR > ATE_MAX_TX_DESCR
+#error "Can't have more TX buffers that descriptors"
+#endif
+#if ATE_NUM_RX_DESCR > ATE_MAX_RX_DESCR
+#error "Can't have more RX buffers that descriptors"
+#endif
+
+/* Wrap indexes the same way the hardware does */
+#define NEXT_RX_IDX(sc, cur) \
+ ((sc->rx_descs[cur].addr & ETH_WRAP_BIT) ? 0 : (cur + 1))
+
+#define NEXT_TX_IDX(sc, cur) \
+ ((sc->tx_descs[cur].status & ETHB_TX_WRAP) ? 0 : (cur + 1))
+
+struct ate_softc
+{
+ struct ifnet *ifp; /* ifnet pointer */
+ struct mtx sc_mtx; /* Basically a perimeter lock */
+ device_t dev; /* Myself */
+ device_t miibus; /* My child miibus */
+ struct resource *irq_res; /* IRQ resource */
+ struct resource *mem_res; /* Memory resource */
+ struct callout tick_ch; /* Tick callout */
+ struct ifmib_iso_8802_3 mibdata; /* Stuff for network mgmt */
+ bus_dma_tag_t mtag; /* bus dma tag for mbufs */
+ bus_dma_tag_t rx_tag;
+ bus_dma_tag_t rx_desc_tag;
+ bus_dmamap_t rx_desc_map;
+ bus_dmamap_t rx_map[ATE_MAX_RX_DESCR];
+ bus_addr_t rx_desc_phys; /* PA of rx descriptors */
+ eth_rx_desc_t *rx_descs; /* VA of rx descriptors */
+ void *rx_buf[ATE_NUM_RX_DESCR]; /* RX buffer space */
+ int rxhead; /* Current RX map/desc index */
+ uint32_t rx_buf_size; /* Size of Rx buffers */
+
+ bus_dma_tag_t tx_desc_tag;
+ bus_dmamap_t tx_desc_map;
+ bus_dmamap_t tx_map[ATE_MAX_TX_BUFFERS];
+ bus_addr_t tx_desc_phys; /* PA of tx descriptors */
+ eth_tx_desc_t *tx_descs; /* VA of tx descriptors */
+ int txhead; /* Current TX map/desc index */
+ int txtail; /* Current TX map/desc index */
+ struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */
+ void *intrhand; /* Interrupt handle */
+ int flags;
+ int if_flags;
+ int use_rmii;
+ int is_emacb; /* SAM9x hardware version */
+};
+
+static inline uint32_t
+RD4(struct ate_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct ate_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+static inline void
+BARRIER(struct ate_softc *sc, bus_size_t off, bus_size_t len, int flags)
+{
+
+ bus_barrier(sc->mem_res, off, len, flags);
+}
+
+#define ATE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define ATE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define ATE_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+ MTX_NETWORK_LOCK, MTX_DEF)
+#define ATE_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define ATE_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define ATE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+static devclass_t ate_devclass;
+
+/*
+ * ifnet entry points.
+ */
+static void ateinit_locked(void *);
+static void atestart_locked(struct ifnet *);
+
+static void ateinit(void *);
+static void atestart(struct ifnet *);
+static void atestop(struct ate_softc *);
+static int ateioctl(struct ifnet * ifp, u_long, caddr_t);
+
+/*
+ * Bus entry points.
+ */
+static int ate_probe(device_t dev);
+static int ate_attach(device_t dev);
+static int ate_detach(device_t dev);
+static void ate_intr(void *);
+
+/*
+ * Helper routines.
+ */
+static int ate_activate(device_t dev);
+static void ate_deactivate(struct ate_softc *sc);
+static int ate_ifmedia_upd(struct ifnet *ifp);
+static void ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
+static int ate_get_mac(struct ate_softc *sc, u_char *eaddr);
+static void ate_set_mac(struct ate_softc *sc, u_char *eaddr);
+static void ate_rxfilter(struct ate_softc *sc);
+
+static int ate_miibus_readreg(device_t dev, int phy, int reg);
+
+static int ate_miibus_writereg(device_t dev, int phy, int reg, int data);
+/*
+ * The AT91 family of products has the ethernet interface called EMAC.
+ * However, it isn't self identifying. It is anticipated that the parent bus
+ * code will take care to only add ate devices where they really are. As
+ * such, we do nothing here to identify the device and just set its name.
+ */
+static int
+ate_probe(device_t dev)
+{
+#ifdef FDT
+ if (!ofw_bus_is_compatible(dev, "cdns,at32ap7000-macb"))
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "EMAC");
+ return (0);
+}
+
+static int
+ate_attach(device_t dev)
+{
+ struct ate_softc *sc;
+ struct ifnet *ifp = NULL;
+ struct sysctl_ctx_list *sctx;
+ struct sysctl_oid *soid;
+ u_char eaddr[ETHER_ADDR_LEN];
+ uint32_t rnd;
+ int rid, err;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ ATE_LOCK_INIT(sc);
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resources.\n");
+ err = ENOMEM;
+ goto out;
+ }
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "could not allocate interrupt resources.\n");
+ err = ENOMEM;
+ goto out;
+ }
+
+ /* New or old version, chooses buffer size. */
+ sc->is_emacb = at91_is_sam9() || at91_is_sam9xe();
+ sc->rx_buf_size = RX_BUF_SIZE(sc);
+
+ err = ate_activate(dev);
+ if (err)
+ goto out;
+
+ /* Default to what boot rom did */
+ if (!sc->is_emacb)
+ sc->use_rmii =
+ (RD4(sc, ETH_CFG) & ETH_CFG_RMII) == ETH_CFG_RMII;
+ else
+ sc->use_rmii =
+ (RD4(sc, ETHB_UIO) & ETHB_UIO_RMII) == ETHB_UIO_RMII;
+
+#ifdef AT91_ATE_USE_RMII
+ /* Compile time override */
+ sc->use_rmii = 1;
+#endif
+ /* Sysctls */
+ sctx = device_get_sysctl_ctx(dev);
+ soid = device_get_sysctl_tree(dev);
+ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "rmii",
+ CTLFLAG_RW, &sc->use_rmii, 0, "rmii in use");
+
+ /* Calling atestop before ifp is set is OK. */
+ ATE_LOCK(sc);
+ atestop(sc);
+ ATE_UNLOCK(sc);
+ callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
+
+ if ((err = ate_get_mac(sc, eaddr)) != 0) {
+ /* No MAC address configured. Generate the random one. */
+ if (bootverbose)
+ device_printf(dev,
+ "Generating random ethernet address.\n");
+ rnd = arc4random();
+
+ /*
+ * Set OUI to convenient locally assigned address. 'b'
+ * is 0x62, which has the locally assigned bit set, and
+ * the broadcast/multicast bit clear.
+ */
+ eaddr[0] = 'b';
+ eaddr[1] = 's';
+ eaddr[2] = 'd';
+ eaddr[3] = (rnd >> 16) & 0xff;
+ eaddr[4] = (rnd >> 8) & 0xff;
+ eaddr[5] = (rnd >> 0) & 0xff;
+ }
+
+ sc->ifp = ifp = if_alloc(IFT_ETHER);
+ err = mii_attach(dev, &sc->miibus, ifp, ate_ifmedia_upd,
+ ate_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ if (err != 0) {
+ device_printf(dev, "attaching PHYs failed\n");
+ goto out;
+ }
+ /*
+ * XXX: Clear the isolate bit, or we won't get up,
+ * at least on the HL201
+ */
+ ate_miibus_writereg(dev, 0, 0, 0x3000);
+
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_capabilities |= IFCAP_VLAN_MTU;
+ ifp->if_capenable |= IFCAP_VLAN_MTU; /* The hw bits already set. */
+ ifp->if_start = atestart;
+ ifp->if_ioctl = ateioctl;
+ ifp->if_init = ateinit;
+ ifp->if_baudrate = 10000000;
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_linkmib = &sc->mibdata;
+ ifp->if_linkmiblen = sizeof(sc->mibdata);
+ sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS;
+ sc->if_flags = ifp->if_flags;
+
+ ether_ifattach(ifp, eaddr);
+
+ /* Activate the interrupt. */
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, ate_intr, sc, &sc->intrhand);
+ if (err) {
+ device_printf(dev, "could not establish interrupt handler.\n");
+ ether_ifdetach(ifp);
+ goto out;
+ }
+
+out:
+ if (err)
+ ate_detach(dev);
+ return (err);
+}
+
+static int
+ate_detach(device_t dev)
+{
+ struct ate_softc *sc;
+ struct ifnet *ifp;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc != NULL, ("[ate: %d]: sc is NULL", __LINE__));
+ ifp = sc->ifp;
+ if (device_is_attached(dev)) {
+ ATE_LOCK(sc);
+ sc->flags |= ATE_FLAG_DETACHING;
+ atestop(sc);
+ ATE_UNLOCK(sc);
+ callout_drain(&sc->tick_ch);
+ ether_ifdetach(ifp);
+ }
+ if (sc->miibus != NULL) {
+ device_delete_child(dev, sc->miibus);
+ sc->miibus = NULL;
+ }
+ bus_generic_detach(sc->dev);
+ ate_deactivate(sc);
+ if (sc->intrhand != NULL) {
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ sc->intrhand = NULL;
+ }
+ if (ifp != NULL) {
+ if_free(ifp);
+ sc->ifp = NULL;
+ }
+ if (sc->mem_res != NULL) {
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = NULL;
+ }
+ if (sc->irq_res != NULL) {
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ sc->irq_res = NULL;
+ }
+ ATE_LOCK_DESTROY(sc);
+ return (0);
+}
+
+static void
+ate_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+ if (error != 0)
+ return;
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+static void
+ate_load_rx_buf(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct ate_softc *sc;
+
+ if (error != 0)
+ return;
+ sc = (struct ate_softc *)arg;
+
+ bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE);
+ sc->rx_descs[sc->rxhead].addr = segs[0].ds_addr;
+ sc->rx_descs[sc->rxhead].status = 0;
+ bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_POSTWRITE);
+}
+
+static uint32_t
+ate_mac_hash(const uint8_t *buf)
+{
+ uint32_t index = 0;
+ for (int i = 0; i < 48; i++) {
+ index ^= ((buf[i >> 3] >> (i & 7)) & 1) << (i % 6);
+ }
+ return (index);
+}
+
+/*
+ * Compute the multicast filter for this device.
+ */
+static int
+ate_setmcast(struct ate_softc *sc)
+{
+ uint32_t index;
+ uint32_t mcaf[2];
+ u_char *af = (u_char *) mcaf;
+ struct ifmultiaddr *ifma;
+ struct ifnet *ifp;
+
+ ifp = sc->ifp;
+
+ if ((ifp->if_flags & IFF_PROMISC) != 0)
+ return (0);
+ if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
+ WR4(sc, ETH_HSL, 0xffffffff);
+ WR4(sc, ETH_HSH, 0xffffffff);
+ return (1);
+ }
+
+ /* Compute the multicast hash. */
+ mcaf[0] = 0;
+ mcaf[1] = 0;
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ index = ate_mac_hash(LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr));
+ af[index >> 3] |= 1 << (index & 7);
+ }
+ if_maddr_runlock(ifp);
+
+ /*
+ * Write the hash to the hash register. This card can also
+ * accept unicast packets as well as multicast packets using this
+ * register for easier bridging operations, but we don't take
+ * advantage of that. Locks here are to avoid LOR with the
+ * if_maddr_rlock, but might not be strictly necessary.
+ */
+ WR4(sc, ETH_HSL, mcaf[0]);
+ WR4(sc, ETH_HSH, mcaf[1]);
+ return (mcaf[0] || mcaf[1]);
+}
+
+static int
+ate_activate(device_t dev)
+{
+ struct ate_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ /* Allocate DMA tags and maps for TX mbufs */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
+ 1, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx, &sc->mtag))
+ goto errout;
+ for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
+ if ( bus_dmamap_create(sc->mtag, 0, &sc->tx_map[i]))
+ goto errout;
+ }
+
+
+ /* DMA tag and map for the RX descriptors. */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_rx_desc_t),
+ 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t), 1,
+ ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t), 0, busdma_lock_mutex,
+ &sc->sc_mtx, &sc->rx_desc_tag))
+ goto errout;
+ if (bus_dmamem_alloc(sc->rx_desc_tag, (void **)&sc->rx_descs,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->rx_desc_map) != 0)
+ goto errout;
+ if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map,
+ sc->rx_descs, ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t),
+ ate_getaddr, &sc->rx_desc_phys, 0) != 0)
+ goto errout;
+
+ /* Allocate DMA tags and maps for RX. buffers */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ sc->rx_buf_size, 1, sc->rx_buf_size, 0,
+ busdma_lock_mutex, &sc->sc_mtx, &sc->rx_tag))
+ goto errout;
+
+ /*
+ * Allocate our RX buffers.
+ * This chip has a RX structure that's filled in.
+ * XXX On MACB (SAM9 part) we should receive directly into mbuf
+ * to avoid the copy. XXX
+ */
+ sc->rxhead = 0;
+ for (sc->rxhead = 0; sc->rxhead < ATE_RX_MEMORY/sc->rx_buf_size;
+ sc->rxhead++) {
+ if (bus_dmamem_alloc(sc->rx_tag,
+ (void **)&sc->rx_buf[sc->rxhead], BUS_DMA_NOWAIT,
+ &sc->rx_map[sc->rxhead]) != 0)
+ goto errout;
+
+ if (bus_dmamap_load(sc->rx_tag, sc->rx_map[sc->rxhead],
+ sc->rx_buf[sc->rxhead], sc->rx_buf_size,
+ ate_load_rx_buf, sc, 0) != 0) {
+ printf("bus_dmamem_load\n");
+ goto errout;
+ }
+ bus_dmamap_sync(sc->rx_tag, sc->rx_map[sc->rxhead], BUS_DMASYNC_PREREAD);
+ }
+
+ /*
+ * For the last buffer, set the wrap bit so the controller
+ * restarts from the first descriptor.
+ */
+ sc->rx_descs[--sc->rxhead].addr |= ETH_WRAP_BIT;
+ sc->rxhead = 0;
+
+ /* Flush the memory for the EMAC rx descriptor. */
+ bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE);
+
+ /* Write the descriptor queue address. */
+ WR4(sc, ETH_RBQP, sc->rx_desc_phys);
+
+ /*
+ * DMA tag and map for the TX descriptors.
+ */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_tx_desc_t),
+ 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 1,
+ ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 0, busdma_lock_mutex,
+ &sc->sc_mtx, &sc->tx_desc_tag) != 0)
+ goto errout;
+
+ if (bus_dmamem_alloc(sc->tx_desc_tag, (void **)&sc->tx_descs,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->tx_desc_map) != 0)
+ goto errout;
+
+ if (bus_dmamap_load(sc->tx_desc_tag, sc->tx_desc_map,
+ sc->tx_descs, ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t),
+ ate_getaddr, &sc->tx_desc_phys, 0) != 0)
+ goto errout;
+
+ /* Initilize descriptors; mark all empty */
+ for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
+ sc->tx_descs[i].addr =0;
+ sc->tx_descs[i].status = ETHB_TX_USED;
+ sc->sent_mbuf[i] = NULL;
+ }
+
+ /* Mark last entry to cause wrap when indexing through */
+ sc->tx_descs[ATE_MAX_TX_BUFFERS - 1].status =
+ ETHB_TX_WRAP | ETHB_TX_USED;
+
+ /* Flush the memory for the EMAC tx descriptor. */
+ bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_PREWRITE);
+
+ sc->txhead = sc->txtail = 0;
+ if (sc->is_emacb) {
+ /* Write the descriptor queue address. */
+ WR4(sc, ETHB_TBQP, sc->tx_desc_phys);
+
+ /* EMACB: Enable transceiver input clock */
+ WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) | ETHB_UIO_CLKE);
+ }
+
+ return (0);
+
+errout:
+ return (ENOMEM);
+}
+
+static void
+ate_deactivate(struct ate_softc *sc)
+{
+ int i;
+
+ KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__));
+ if (sc->mtag != NULL) {
+ for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
+ if (sc->sent_mbuf[i] != NULL) {
+ bus_dmamap_sync(sc->mtag, sc->tx_map[i],
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->mtag, sc->tx_map[i]);
+ m_freem(sc->sent_mbuf[i]);
+ }
+ bus_dmamap_destroy(sc->mtag, sc->tx_map[i]);
+ sc->sent_mbuf[i] = NULL;
+ sc->tx_map[i] = NULL;
+ }
+ bus_dma_tag_destroy(sc->mtag);
+ }
+ if (sc->rx_desc_tag != NULL) {
+ if (sc->rx_descs != NULL) {
+ if (sc->rx_desc_phys != 0) {
+ bus_dmamap_sync(sc->rx_desc_tag,
+ sc->rx_desc_map, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->rx_desc_tag,
+ sc->rx_desc_map);
+ sc->rx_desc_phys = 0;
+ }
+ }
+ }
+ if (sc->rx_tag != NULL) {
+ for (i = 0; sc->rx_buf[i] != NULL; i++) {
+ if (sc->rx_descs[i].addr != 0) {
+ bus_dmamap_sync(sc->rx_tag,
+ sc->rx_map[i],
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->rx_tag,
+ sc->rx_map[i]);
+ sc->rx_descs[i].addr = 0;
+ }
+ bus_dmamem_free(sc->rx_tag, sc->rx_buf[i],
+ sc->rx_map[i]);
+ sc->rx_buf[i] = NULL;
+ sc->rx_map[i] = NULL;
+ }
+ bus_dma_tag_destroy(sc->rx_tag);
+ }
+ if (sc->rx_desc_tag != NULL) {
+ if (sc->rx_descs != NULL)
+ bus_dmamem_free(sc->rx_desc_tag, sc->rx_descs,
+ sc->rx_desc_map);
+ bus_dma_tag_destroy(sc->rx_desc_tag);
+ sc->rx_descs = NULL;
+ sc->rx_desc_tag = NULL;
+ }
+
+ if (sc->is_emacb)
+ WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) & ~ETHB_UIO_CLKE);
+}
+
+/*
+ * Change media according to request.
+ */
+static int
+ate_ifmedia_upd(struct ifnet *ifp)
+{
+ struct ate_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+
+ mii = device_get_softc(sc->miibus);
+ ATE_LOCK(sc);
+ mii_mediachg(mii);
+ ATE_UNLOCK(sc);
+ return (0);
+}
+
+/*
+ * Notify the world which media we're using.
+ */
+static void
+ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct ate_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+
+ mii = device_get_softc(sc->miibus);
+ ATE_LOCK(sc);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ ATE_UNLOCK(sc);
+}
+
+static void
+ate_stat_update(struct ate_softc *sc, int active)
+{
+ uint32_t reg;
+
+ /*
+ * The speed and full/half-duplex state needs to be reflected
+ * in the ETH_CFG register.
+ */
+ reg = RD4(sc, ETH_CFG);
+ reg &= ~(ETH_CFG_SPD | ETH_CFG_FD);
+ if (IFM_SUBTYPE(active) != IFM_10_T)
+ reg |= ETH_CFG_SPD;
+ if (active & IFM_FDX)
+ reg |= ETH_CFG_FD;
+ WR4(sc, ETH_CFG, reg);
+}
+
+static void
+ate_tick(void *xsc)
+{
+ struct ate_softc *sc = xsc;
+ struct ifnet *ifp = sc->ifp;
+ struct mii_data *mii;
+ int active;
+ uint32_t c;
+
+ /*
+ * The KB920x boot loader tests ETH_SR & ETH_SR_LINK and will ask
+ * the MII if there's a link if this bit is clear. Not sure if we
+ * should do the same thing here or not.
+ */
+ ATE_ASSERT_LOCKED(sc);
+ if (sc->miibus != NULL) {
+ mii = device_get_softc(sc->miibus);
+ active = mii->mii_media_active;
+ mii_tick(mii);
+ if (mii->mii_media_status & IFM_ACTIVE &&
+ active != mii->mii_media_active)
+ ate_stat_update(sc, mii->mii_media_active);
+ }
+
+ /*
+ * Update the stats as best we can. When we're done, clear
+ * the status counters and start over. We're supposed to read these
+ * registers often enough that they won't overflow. Hopefully
+ * once a second is often enough. Some don't map well to
+ * the dot3Stats mib, so for those we just count them as general
+ * errors. Stats for iframes, ibutes, oframes and obytes are
+ * collected elsewhere. These registers zero on a read to prevent
+ * races. For all the collision stats, also update the collision
+ * stats for the interface.
+ */
+ sc->mibdata.dot3StatsAlignmentErrors += RD4(sc, ETH_ALE);
+ sc->mibdata.dot3StatsFCSErrors += RD4(sc, ETH_SEQE);
+ c = RD4(sc, ETH_SCOL);
+ ifp->if_collisions += c;
+ sc->mibdata.dot3StatsSingleCollisionFrames += c;
+ c = RD4(sc, ETH_MCOL);
+ sc->mibdata.dot3StatsMultipleCollisionFrames += c;
+ ifp->if_collisions += c;
+ sc->mibdata.dot3StatsSQETestErrors += RD4(sc, ETH_SQEE);
+ sc->mibdata.dot3StatsDeferredTransmissions += RD4(sc, ETH_DTE);
+ c = RD4(sc, ETH_LCOL);
+ sc->mibdata.dot3StatsLateCollisions += c;
+ ifp->if_collisions += c;
+ c = RD4(sc, ETH_ECOL);
+ sc->mibdata.dot3StatsExcessiveCollisions += c;
+ ifp->if_collisions += c;
+ sc->mibdata.dot3StatsCarrierSenseErrors += RD4(sc, ETH_CSE);
+ sc->mibdata.dot3StatsFrameTooLongs += RD4(sc, ETH_ELR);
+ sc->mibdata.dot3StatsInternalMacReceiveErrors += RD4(sc, ETH_DRFC);
+
+ /*
+ * Not sure where to lump these, so count them against the errors
+ * for the interface.
+ */
+ sc->ifp->if_oerrors += RD4(sc, ETH_TUE);
+ sc->ifp->if_ierrors += RD4(sc, ETH_CDE) + RD4(sc, ETH_RJB) +
+ RD4(sc, ETH_USF);
+
+ /* Schedule another timeout one second from now. */
+ callout_reset(&sc->tick_ch, hz, ate_tick, sc);
+}
+
+static void
+ate_set_mac(struct ate_softc *sc, u_char *eaddr)
+{
+
+ WR4(sc, ETH_SA1L, (eaddr[3] << 24) | (eaddr[2] << 16) |
+ (eaddr[1] << 8) | eaddr[0]);
+ WR4(sc, ETH_SA1H, (eaddr[5] << 8) | (eaddr[4]));
+}
+
+static int
+ate_get_mac(struct ate_softc *sc, u_char *eaddr)
+{
+ bus_size_t sa_low_reg[] = { ETH_SA1L, ETH_SA2L, ETH_SA3L, ETH_SA4L };
+ bus_size_t sa_high_reg[] = { ETH_SA1H, ETH_SA2H, ETH_SA3H, ETH_SA4H };
+ uint32_t low, high;
+ int i;
+
+ /*
+ * The boot loader may setup the MAC with an address(es), grab the
+ * first MAC address from the SA[1-4][HL] registers.
+ */
+ for (i = 0; i < 4; i++) {
+ low = RD4(sc, sa_low_reg[i]);
+ high = RD4(sc, sa_high_reg[i]);
+ if ((low | (high & 0xffff)) != 0) {
+ eaddr[0] = low & 0xff;
+ eaddr[1] = (low >> 8) & 0xff;
+ eaddr[2] = (low >> 16) & 0xff;
+ eaddr[3] = (low >> 24) & 0xff;
+ eaddr[4] = high & 0xff;
+ eaddr[5] = (high >> 8) & 0xff;
+ return (0);
+ }
+ }
+ return (ENXIO);
+}
+
+static void
+ate_intr(void *xsc)
+{
+ struct ate_softc *sc = xsc;
+ struct ifnet *ifp = sc->ifp;
+ struct mbuf *mb;
+ eth_rx_desc_t *rxdhead;
+ uint32_t status, reg, idx;
+ int remain, count, done;
+
+ status = RD4(sc, ETH_ISR);
+ if (status == 0)
+ return;
+
+ if (status & ETH_ISR_RCOM) {
+ bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
+ BUS_DMASYNC_POSTREAD);
+
+ rxdhead = &sc->rx_descs[sc->rxhead];
+ while (rxdhead->addr & ETH_CPU_OWNER) {
+ if (!sc->is_emacb) {
+ /*
+ * Simulate SAM9 FIRST/LAST bits for RM9200.
+ * RM9200 EMAC has only on Rx buffer per packet.
+ * But sometime we are handed a zero lenght packet.
+ */
+ if ((rxdhead->status & ETH_LEN_MASK) == 0)
+ rxdhead->status = 0; /* Mark error */
+ else
+ rxdhead->status |= ETH_BUF_FIRST | ETH_BUF_LAST;
+ }
+
+ if ((rxdhead->status & ETH_BUF_FIRST) == 0) {
+ /* Something went wrong during RX so
+ release back to EMAC all buffers of invalid packets.
+ */
+ rxdhead->status = 0;
+ rxdhead->addr &= ~ETH_CPU_OWNER;
+ sc->rxhead = NEXT_RX_IDX(sc, sc->rxhead);
+ rxdhead = &sc->rx_descs[sc->rxhead];
+ continue;
+ }
+
+ /* Find end of packet or start of next */
+ idx = sc->rxhead;
+ if ((sc->rx_descs[idx].status & ETH_BUF_LAST) == 0) {
+ idx = NEXT_RX_IDX(sc, idx);
+
+ while ((sc->rx_descs[idx].addr & ETH_CPU_OWNER) &&
+ ((sc->rx_descs[idx].status &
+ (ETH_BUF_FIRST|ETH_BUF_LAST))== 0))
+ idx = NEXT_RX_IDX(sc, idx);
+ }
+
+ /* Packet NOT yet completely in memory; we are done */
+ if ((sc->rx_descs[idx].addr & ETH_CPU_OWNER) == 0 ||
+ ((sc->rx_descs[idx].status & (ETH_BUF_FIRST|ETH_BUF_LAST))== 0))
+ break;
+
+ /* Packets with no end descriptor are invalid. */
+ if ((sc->rx_descs[idx].status & ETH_BUF_LAST) == 0) {
+ rxdhead->status &= ~ETH_BUF_FIRST;
+ continue;
+ }
+
+ /* FCS is not coppied into mbuf. */
+ remain = (sc->rx_descs[idx].status & ETH_LEN_MASK) - 4;
+
+ /* Get an appropriately sized mbuf. */
+ mb = m_get2(remain + ETHER_ALIGN, M_NOWAIT, MT_DATA,
+ M_PKTHDR);
+ if (mb == NULL) {
+ sc->ifp->if_iqdrops++;
+ rxdhead->status = 0;
+ continue;
+ }
+ mb->m_data += ETHER_ALIGN;
+ mb->m_pkthdr.rcvif = ifp;
+
+ WR4(sc, ETH_RSR, RD4(sc, ETH_RSR)); /* Reset status */
+
+ /* Now we process the buffers that make up the packet */
+ do {
+
+ /* Last buffer may just be 1-4 bytes of FCS so remain
+ * may be zero for last decriptor. */
+ if (remain > 0) {
+ /* Make sure we get the current bytes */
+ bus_dmamap_sync(sc->rx_tag, sc->rx_map[sc->rxhead],
+ BUS_DMASYNC_POSTREAD);
+
+ count = MIN(remain, sc->rx_buf_size);
+
+ /* XXX Performance robbing copy. Could
+ * recieve directly to mbufs if not an
+ * RM9200. And even then we could likely
+ * copy just the protocol headers. XXX */
+ m_append(mb, count, sc->rx_buf[sc->rxhead]);
+ remain -= count;
+ }
+
+ done = (rxdhead->status & ETH_BUF_LAST) != 0;
+
+ /* Return the descriptor to the EMAC */
+ rxdhead->status = 0;
+ rxdhead->addr &= ~ETH_CPU_OWNER;
+ bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
+ BUS_DMASYNC_PREWRITE);
+
+ /* Move on to next descriptor with wrap */
+ sc->rxhead = NEXT_RX_IDX(sc, sc->rxhead);
+ rxdhead = &sc->rx_descs[sc->rxhead];
+
+ } while (!done);
+
+ ifp->if_ipackets++;
+ (*ifp->if_input)(ifp, mb);
+ }
+ }
+
+
+ if (status & ETH_ISR_TCOM) {
+ bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map,
+ BUS_DMASYNC_POSTREAD);
+
+ ATE_LOCK(sc);
+ /* XXX TSR register should be cleared */
+ if (!sc->is_emacb) {
+ /* Simulate Transmit descriptor table */
+
+ /* First packet done */
+ if (sc->txtail < sc->txhead)
+ sc->tx_descs[sc->txtail].status |= ETHB_TX_USED;
+
+ /* Second Packet done */
+ if (sc->txtail + 1 < sc->txhead &&
+ RD4(sc, ETH_TSR) & ETH_TSR_IDLE)
+ sc->tx_descs[sc->txtail + 1].status |= ETHB_TX_USED;
+ }
+
+ while ((sc->tx_descs[sc->txtail].status & ETHB_TX_USED) &&
+ sc->sent_mbuf[sc->txtail] != NULL) {
+ bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail],
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]);
+ m_freem(sc->sent_mbuf[sc->txtail]);
+ sc->tx_descs[sc->txtail].addr = 0;
+ sc->sent_mbuf[sc->txtail] = NULL;
+ ifp->if_opackets++;
+ sc->txtail = NEXT_TX_IDX(sc, sc->txtail);
+ }
+
+ /* Flush descriptors to EMAC */
+ bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_PREWRITE);
+
+ /*
+ * We're no longer busy, so clear the busy flag and call the
+ * start routine to xmit more packets.
+ */
+ sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ atestart_locked(sc->ifp);
+ ATE_UNLOCK(sc);
+ }
+
+ if (status & ETH_ISR_RBNA) {
+ /* Workaround RM9200 Errata #11 */
+ if (bootverbose)
+ device_printf(sc->dev, "RBNA workaround\n");
+ reg = RD4(sc, ETH_CTL);
+ WR4(sc, ETH_CTL, reg & ~ETH_CTL_RE);
+ BARRIER(sc, ETH_CTL, 4, BUS_SPACE_BARRIER_WRITE);
+ WR4(sc, ETH_CTL, reg | ETH_CTL_RE);
+ }
+
+ /* XXX need to work around SAM9260 errata 43.2.4.1:
+ * disable the mac, reset tx buffer, enable mac on TUND */
+}
+
+/*
+ * Reset and initialize the chip.
+ */
+static void
+ateinit_locked(void *xsc)
+{
+ struct ate_softc *sc = xsc;
+ struct ifnet *ifp = sc->ifp;
+ struct mii_data *mii;
+ uint8_t eaddr[ETHER_ADDR_LEN];
+ uint32_t reg;
+
+ ATE_ASSERT_LOCKED(sc);
+
+ /*
+ * XXX TODO(3)
+ * we need to turn on the EMAC clock in the pmc. With the
+ * default boot loader, this is already turned on. However, we
+ * need to think about how best to turn it on/off as the interface
+ * is brought up/down, as well as dealing with the mii bus...
+ *
+ * We also need to multiplex the pins correctly (in board_xxx.c).
+ */
+
+ /*
+ * There are two different ways that the mii bus is connected
+ * to this chip mii or rmii.
+ */
+ if (!sc->is_emacb) {
+ /* RM9200 */
+ reg = RD4(sc, ETH_CFG);
+ if (sc->use_rmii)
+ reg |= ETH_CFG_RMII;
+ else
+ reg &= ~ETH_CFG_RMII;
+ WR4(sc, ETH_CFG, reg);
+ } else {
+ /* SAM9 */
+ reg = ETHB_UIO_CLKE;
+ reg |= (sc->use_rmii) ? ETHB_UIO_RMII : 0;
+ WR4(sc, ETHB_UIO, reg);
+ }
+
+ ate_rxfilter(sc);
+
+ /*
+ * Set the chip MAC address.
+ */
+ bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN);
+ ate_set_mac(sc, eaddr);
+
+ /* Make sure we know state of TX queue */
+ sc->txhead = sc->txtail = 0;
+ if (sc->is_emacb) {
+ /* Write the descriptor queue address. */
+ WR4(sc, ETHB_TBQP, sc->tx_desc_phys);
+ }
+
+ /*
+ * Turn on MACs and interrupt processing.
+ */
+ WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE | ETH_CTL_RE);
+ WR4(sc, ETH_IER, ETH_ISR_RCOM | ETH_ISR_TCOM | ETH_ISR_RBNA);
+
+ /* Enable big packets. */
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG);
+
+ /*
+ * Set 'running' flag, and clear output active flag
+ * and attempt to start the output.
+ */
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ mii = device_get_softc(sc->miibus);
+ mii_pollstat(mii);
+ ate_stat_update(sc, mii->mii_media_active);
+ atestart_locked(ifp);
+
+ callout_reset(&sc->tick_ch, hz, ate_tick, sc);
+}
+
+/*
+ * Dequeue packets and transmit.
+ */
+static void
+atestart_locked(struct ifnet *ifp)
+{
+ struct ate_softc *sc = ifp->if_softc;
+ struct mbuf *m, *mdefrag;
+ bus_dma_segment_t segs[1];
+ int nseg, e;
+
+ ATE_ASSERT_LOCKED(sc);
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
+ return;
+
+ while (sc->tx_descs[sc->txhead].status & ETHB_TX_USED) {
+ /*
+ * Check to see if there's room to put another packet into the
+ * xmit queue. The old EMAC version has a ping-pong buffer for
+ * xmit packets. We use OACTIVE to indicate "we can stuff more
+ * into our buffers (clear) or not (set)."
+ */
+ /* RM9200 has only two hardware entries */
+ if (!sc->is_emacb && (RD4(sc, ETH_TSR) & ETH_TSR_BNQ) == 0) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ return;
+ }
+
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == 0)
+ break;
+
+ e = bus_dmamap_load_mbuf_sg(sc->mtag, sc->tx_map[sc->txhead], m,
+ segs, &nseg, 0);
+ if (e == EFBIG) {
+ mdefrag = m_defrag(m, M_NOWAIT);
+ if (mdefrag == NULL) {
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ return;
+ }
+ m = mdefrag;
+ e = bus_dmamap_load_mbuf_sg(sc->mtag,
+ sc->tx_map[sc->txhead], m, segs, &nseg, 0);
+ }
+ if (e != 0) {
+ m_freem(m);
+ continue;
+ }
+
+ /*
+ * There's a small race between the loop in ate_intr finishing
+ * and the check above to see if the packet was finished, as well
+ * as when atestart gets called via other paths. Lose the race
+ * gracefully and free the mbuf...
+ */
+ if (sc->sent_mbuf[sc->txhead] != NULL) {
+ bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail],
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]);
+ m_free(sc->sent_mbuf[sc->txhead]);
+ ifp->if_opackets++;
+ }
+
+ sc->sent_mbuf[sc->txhead] = m;
+
+ bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txhead],
+ BUS_DMASYNC_PREWRITE);
+
+ /* Tell the hardware to xmit the packet. */
+ if (!sc->is_emacb) {
+ WR4(sc, ETH_TAR, segs[0].ds_addr);
+ BARRIER(sc, ETH_TAR, 4, BUS_SPACE_BARRIER_WRITE);
+ WR4(sc, ETH_TCR, segs[0].ds_len);
+ } else {
+ bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map,
+ BUS_DMASYNC_POSTWRITE);
+ sc->tx_descs[sc->txhead].addr = segs[0].ds_addr;
+ sc->tx_descs[sc->txhead].status = segs[0].ds_len |
+ (sc->tx_descs[sc->txhead].status & ETHB_TX_WRAP) |
+ ETHB_TX_BUF_LAST;
+ bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map,
+ BUS_DMASYNC_PREWRITE);
+ WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETHB_CTL_TGO);
+ }
+ sc->txhead = NEXT_TX_IDX(sc, sc->txhead);
+
+ /* Tap off here if there is a bpf listener. */
+ BPF_MTAP(ifp, m);
+ }
+
+ if ((sc->tx_descs[sc->txhead].status & ETHB_TX_USED) == 0)
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+}
+
+static void
+ateinit(void *xsc)
+{
+ struct ate_softc *sc = xsc;
+
+ ATE_LOCK(sc);
+ ateinit_locked(sc);
+ ATE_UNLOCK(sc);
+}
+
+static void
+atestart(struct ifnet *ifp)
+{
+ struct ate_softc *sc = ifp->if_softc;
+
+ ATE_LOCK(sc);
+ atestart_locked(ifp);
+ ATE_UNLOCK(sc);
+}
+
+/*
+ * Turn off interrupts, and stop the NIC. Can be called with sc->ifp NULL,
+ * so be careful.
+ */
+static void
+atestop(struct ate_softc *sc)
+{
+ struct ifnet *ifp;
+ int i;
+
+ ATE_ASSERT_LOCKED(sc);
+ ifp = sc->ifp;
+ if (ifp) {
+ //ifp->if_timer = 0;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ }
+
+ callout_stop(&sc->tick_ch);
+
+ /*
+ * Enable some parts of the MAC that are needed always (like the
+ * MII bus. This turns off the RE and TE bits, which will remain
+ * off until ateinit() is called to turn them on. With RE and TE
+ * turned off, there's no DMA to worry about after this write.
+ */
+ WR4(sc, ETH_CTL, ETH_CTL_MPE);
+
+ /*
+ * Turn off all the configured options and revert to defaults.
+ */
+
+ /* Make sure thate the MDIO clk is less than
+ * 2.5 Mhz. Can no longer default to /32 since
+ * SAM9 family may have MCK > 80 Mhz */
+ if (at91_master_clock <= 2000000)
+ WR4(sc, ETH_CFG, ETH_CFG_CLK_8);
+ else if (at91_master_clock <= 4000000)
+ WR4(sc, ETH_CFG, ETH_CFG_CLK_16);
+ else if (at91_master_clock <= 800000)
+ WR4(sc, ETH_CFG, ETH_CFG_CLK_32);
+ else
+ WR4(sc, ETH_CFG, ETH_CFG_CLK_64);
+
+ /*
+ * Turn off all the interrupts, and ack any pending ones by reading
+ * the ISR.
+ */
+ WR4(sc, ETH_IDR, 0xffffffff);
+ RD4(sc, ETH_ISR);
+
+ /*
+ * Clear out the Transmit and Receiver Status registers of any
+ * errors they may be reporting
+ */
+ WR4(sc, ETH_TSR, 0xffffffff);
+ WR4(sc, ETH_RSR, 0xffffffff);
+
+ /* Release TX resources. */
+ for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
+ if (sc->sent_mbuf[i] != NULL) {
+ bus_dmamap_sync(sc->mtag, sc->tx_map[i],
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->mtag, sc->tx_map[i]);
+ m_freem(sc->sent_mbuf[i]);
+ sc->sent_mbuf[i] = NULL;
+ }
+ }
+
+ /* Turn off transeiver input clock */
+ if (sc->is_emacb)
+ WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) & ~ETHB_UIO_CLKE);
+
+ /*
+ * XXX we should power down the EMAC if it isn't in use, after
+ * putting it into loopback mode. This saves about 400uA according
+ * to the datasheet.
+ */
+}
+
+static void
+ate_rxfilter(struct ate_softc *sc)
+{
+ struct ifnet *ifp;
+ uint32_t reg;
+ int enabled;
+
+ KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__));
+ ATE_ASSERT_LOCKED(sc);
+ ifp = sc->ifp;
+
+ /* Wipe out old filter settings. */
+ reg = RD4(sc, ETH_CFG);
+ reg &= ~(ETH_CFG_CAF | ETH_CFG_MTI | ETH_CFG_UNI);
+ reg |= ETH_CFG_NBC;
+ sc->flags &= ~ATE_FLAG_MULTICAST;
+
+ /* Set new parameters. */
+ if ((ifp->if_flags & IFF_BROADCAST) != 0)
+ reg &= ~ETH_CFG_NBC;
+ if ((ifp->if_flags & IFF_PROMISC) != 0) {
+ reg |= ETH_CFG_CAF;
+ } else {
+ enabled = ate_setmcast(sc);
+ if (enabled != 0) {
+ reg |= ETH_CFG_MTI;
+ sc->flags |= ATE_FLAG_MULTICAST;
+ }
+ }
+ WR4(sc, ETH_CFG, reg);
+}
+
+static int
+ateioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct ate_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int drv_flags, flags;
+ int mask, error, enabled;
+
+ error = 0;
+ flags = ifp->if_flags;
+ drv_flags = ifp->if_drv_flags;
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ ATE_LOCK(sc);
+ if ((flags & IFF_UP) != 0) {
+ if ((drv_flags & IFF_DRV_RUNNING) != 0) {
+ if (((flags ^ sc->if_flags)
+ & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+ ate_rxfilter(sc);
+ } else {
+ if ((sc->flags & ATE_FLAG_DETACHING) == 0)
+ ateinit_locked(sc);
+ }
+ } else if ((drv_flags & IFF_DRV_RUNNING) != 0) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ atestop(sc);
+ }
+ sc->if_flags = flags;
+ ATE_UNLOCK(sc);
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if ((drv_flags & IFF_DRV_RUNNING) != 0) {
+ ATE_LOCK(sc);
+ enabled = ate_setmcast(sc);
+ if (enabled != (sc->flags & ATE_FLAG_MULTICAST))
+ ate_rxfilter(sc);
+ ATE_UNLOCK(sc);
+ }
+ break;
+
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ mii = device_get_softc(sc->miibus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ break;
+ case SIOCSIFCAP:
+ mask = ifp->if_capenable ^ ifr->ifr_reqcap;
+ if (mask & IFCAP_VLAN_MTU) {
+ ATE_LOCK(sc);
+ if (ifr->ifr_reqcap & IFCAP_VLAN_MTU) {
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG);
+ ifp->if_capenable |= IFCAP_VLAN_MTU;
+ } else {
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_BIG);
+ ifp->if_capenable &= ~IFCAP_VLAN_MTU;
+ }
+ ATE_UNLOCK(sc);
+ }
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ }
+ return (error);
+}
+
+static void
+ate_child_detached(device_t dev, device_t child)
+{
+ struct ate_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (child == sc->miibus)
+ sc->miibus = NULL;
+}
+
+/*
+ * MII bus support routines.
+ */
+static int
+ate_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct ate_softc *sc;
+ int val;
+
+ /*
+ * XXX if we implement agressive power savings, then we need
+ * XXX to make sure that the clock to the emac is on here
+ */
+
+ sc = device_get_softc(dev);
+ DELAY(1); /* Hangs w/o this delay really 30.5us atm */
+ WR4(sc, ETH_MAN, ETH_MAN_REG_RD(phy, reg));
+ while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0)
+ continue;
+ val = RD4(sc, ETH_MAN) & ETH_MAN_VALUE_MASK;
+
+ return (val);
+}
+
+static int
+ate_miibus_writereg(device_t dev, int phy, int reg, int data)
+{
+ struct ate_softc *sc;
+
+ /*
+ * XXX if we implement agressive power savings, then we need
+ * XXX to make sure that the clock to the emac is on here
+ */
+
+ sc = device_get_softc(dev);
+ WR4(sc, ETH_MAN, ETH_MAN_REG_WR(phy, reg, data));
+ while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0)
+ continue;
+ return (0);
+}
+
+static device_method_t ate_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ate_probe),
+ DEVMETHOD(device_attach, ate_attach),
+ DEVMETHOD(device_detach, ate_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_child_detached, ate_child_detached),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, ate_miibus_readreg),
+ DEVMETHOD(miibus_writereg, ate_miibus_writereg),
+
+ DEVMETHOD_END
+};
+
+static driver_t ate_driver = {
+ "ate",
+ ate_methods,
+ sizeof(struct ate_softc),
+};
+
+#ifdef FDT
+DRIVER_MODULE(ate, simplebus, ate_driver, ate_devclass, NULL, NULL);
+#else
+DRIVER_MODULE(ate, atmelarm, ate_driver, ate_devclass, NULL, NULL);
+#endif
+DRIVER_MODULE(miibus, ate, miibus_driver, miibus_devclass, NULL, NULL);
+MODULE_DEPEND(ate, miibus, 1, 1, 1);
+MODULE_DEPEND(ate, ether, 1, 1, 1);
Property changes on: trunk/sys/arm/at91/if_ate.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/if_atereg.h
===================================================================
--- trunk/sys/arm/at91/if_atereg.h (rev 0)
+++ trunk/sys/arm/at91/if_atereg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,215 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/at91/if_atereg.h 213496 2010-10-06 22:25:21Z cognet $ */
+
+#ifndef ARM_AT91_IF_ATEREG_H
+#define ARM_AT91_IF_ATEREG_H
+
+/* deines begining ETHB_ are EMACB (newer SAM9 hardware) versions only */
+
+#define ETH_CTL 0x00 /* EMAC Control Register */
+#define ETH_CFG 0x04 /* EMAC Configuration Register */
+#define ETH_SR 0x08 /* EMAC STatus Register */
+#define ETH_TAR 0x0c /* EMAC Transmit Address Register */
+#define ETH_TCR 0x10 /* EMAC Transmit Control Register */
+#define ETH_TSR 0x14 /* EMAC Transmit Status Register */
+#define ETH_RBQP 0x18 /* EMAC Receive Buffer Queue Pointer */
+#define ETHB_TBQP 0x1c /* reserved */
+#define ETH_RSR 0x20 /* EMAC Receive Status Register */
+#define ETH_ISR 0x24 /* EMAC Interrupt Status Register */
+#define ETH_IER 0x28 /* EMAC Interrupt Enable Register */
+#define ETH_IDR 0x2c /* EMAC Interrupt Disable Register */
+#define ETH_IMR 0x30 /* EMAC Interrupt Mask Register */
+#define ETH_MAN 0x34 /* EMAC PHY Maintenance Register */
+ /* 0x38 reserved */
+ /* 0x3c reserved */
+#define ETH_FRA 0x40 /* Frames Transmitted OK Register */
+#define ETH_SCOL 0x44 /* Single Collision Frame Register */
+#define ETH_MCOL 0x48 /* Multiple Collision Frame Register */
+#define ETH_OK 0x4c /* Frames Received OK Register */
+#define ETH_SEQE 0x50 /* Frame Check Sequence Error Reg */
+#define ETH_ALE 0x54 /* Alignment Error Register */
+#define ETH_DTE 0x58 /* Deferred Transmittion Frame Reg */
+#define ETH_LCOL 0x5c /* Late Collision Register */
+#define ETH_ECOL 0x60 /* Excessive Collision Register */
+#define ETH_TUE 0x64 /* Transmit Underrun Error Register */
+#define ETH_CSE 0x68 /* Carrier Sense Error Register */
+#define ETH_DRFC 0x6c /* Discarded RX Frame Register */
+#define ETH_ROV 0x68 /* Receive Overrun Register */
+#define ETH_CDE 0x64 /* Code Error Register */
+#define ETH_ELR 0x78 /* Excessive Length Error Register */
+#define ETH_RJB 0x7c /* Receive Jabber Register */
+#define ETH_USF 0x80 /* Undersize Frame Register */
+#define ETH_SQEE 0x84 /* SQE Test Error Register */
+ /* 0x88 reserved */
+ /* 0x8c reserved */
+#define ETH_HSL 0x90 /* EMAC Hash Address Low [31:0] */
+#define ETH_HSH 0x94 /* EMAC Hash Address High [63:32] */
+#define ETH_SA1L 0x98 /* EMAC Specific Address 1 Low */
+#define ETH_SA1H 0x9c /* EMAC Specific Address 1 High */
+#define ETH_SA2L 0xa0 /* EMAC Specific Address 2 Low */
+#define ETH_SA2H 0xa4 /* EMAC Specific Address 2 High */
+#define ETH_SA3L 0xa8 /* EMAC Specific Address 3 Low */
+#define ETH_SA3H 0xac /* EMAC Specific Address 3 High */
+#define ETH_SA4L 0xb0 /* EMAC Specific Address 4 Low */
+#define ETH_SA4H 0xb4 /* EMAC Specific Address 4 High */
+#define ETHB_TID 0xb8 /* EMAC Type ID Checking */
+#define ETHB_UIO 0xC0 /* EMAC User I/O Reg */
+
+
+/* ETH_CTL */
+#define ETH_CTL_LB (1U << 0) /* LB: Loopback */
+#define ETH_CTL_LBL (1U << 1) /* LBL: Loopback Local */
+#define ETH_CTL_RE (1U << 2) /* RE: Receive Enable */
+#define ETH_CTL_TE (1U << 3) /* TE: Transmit Enable */
+#define ETH_CTL_MPE (1U << 4) /* MPE: Management Port Enable */
+#define ETH_CTL_CSR (1U << 5) /* CSR: Clear Statistics Registers */
+#define ETH_CTL_ISR (1U << 6) /* ISR: Incremenet Statistics Regs */
+#define ETH_CTL_WES (1U << 7) /* WES: Write Enable Statistics regs */
+#define ETH_CTL_BP (1U << 8) /* BP: Back Pressure */
+
+#define ETHB_CTL_TGO (1U << 9) /* TGO: Transmitter Start */
+#define ETHB_CTL_TSTP (1U << 10) /* TSTP: Transmitter Stop */
+
+/* ETH_CFG */
+#define ETH_CFG_SPD (1U << 0) /* SPD: Speed 1 == 100: 0 == 10 */
+#define ETH_CFG_FD (1U << 1) /* FD: Full duplex */
+#define ETH_CFG_BR (1U << 2) /* BR: Bit Rate (optional?) */
+ /* bit 3 reserved */
+#define ETH_CFG_CAF (1U << 4) /* CAF: Copy All Frames */
+#define ETH_CFG_NBC (1U << 5) /* NBC: No Broadcast */
+#define ETH_CFG_MTI (1U << 6) /* MTI: Multicast Hash Enable */
+#define ETH_CFG_UNI (1U << 7) /* UNI: Unicast Hash Enable */
+#define ETH_CFG_BIG (1U << 8) /* BIG: Receive 1522 Bytes */
+#define ETH_CFG_EAE (1U << 9) /* EAE: External Address Match En */
+#define ETH_CFG_CLK_8 (0U << 10) /* CLK: Clock / 8 */
+#define ETH_CFG_CLK_16 (1U << 10) /* CLK: Clock / 16 */
+#define ETH_CFG_CLK_32 (2U << 10) /* CLK: Clock / 32 */
+#define ETH_CFG_CLK_64 (3U << 10) /* CLK: Clock / 64 */
+#define ETH_CFG_RTY (1U << 12) /* RTY: Retry Test*/
+#define ETH_CFG_RMII (1U << 13) /* RMII: Reduce MII */
+
+#define ETHB_CFG_JBO (1U << 3) /* JBO: Jumbo Frames */
+#define ETHB_CFG_PAE (1U << 13) /* PAE: Pause Enable */
+#define ETHB_CFG_RBOF_0 (0U << 14) /* RBOF: Rx Buffer Offset */
+#define ETHB_CFG_RBOF_1 (1U << 14) /* RBOF: Rx Buffer Offset */
+#define ETHB_CFG_RBOF_2 (3U << 14) /* RBOF: Rx Buffer Offset */
+#define ETHB_CFG_RBOF_3 (3U << 14) /* RBOF: Rx Buffer Offset */
+#define ETHB_CFG_RCLE (1U << 16) /* RCLE: Rx Length Check Enable */
+#define ETHB_CFG_DRFC (1U << 17) /* DRFC: Discard Rx FCS */
+#define ETHB_CFG_RHD (1U << 18) /* RHD: RX TX'ed frame in half-duplex */
+#define ETHB_CFG_IFCS (1U << 19) /* IFCS: Ignore bad RX FCS */
+
+/* ETH_SR */
+#define ETH_SR_LINK (1U << 0) /* Reserved! */
+#define ETH_SR_MDIO (1U << 1) /* MDIO pin status */
+#define ETH_SR_IDLE (1U << 2) /* IDLE (PHY logic) */
+
+/* ETH_TCR */
+#define ETH_TCR_NCRC (1U << 15) /* NCRC: No CRC */
+
+/* ETH_TSR */
+#define ETH_TSR_OVR (1U << 0) /* OVR: Ethernet Transmit Overrun */
+#define ETH_TSR_COL (1U << 1) /* COL: Collision Occurred */
+#define ETH_TSR_RLE (1U << 2) /* RLE: Retry Limit Exceeded */
+#define ETH_TSR_IDLE (1U << 3) /* IDLE: Transmitter Idle */
+#define ETH_TSR_BNQ (1U << 4) /* BNQ: Enet Tran Buff not Queued */
+#define ETH_TSR_COMP (1U << 5) /* COMP: Transmit Complete */
+#define ETH_TSR_UND (1U << 6) /* UND: Transmit Underrun */
+#define ETH_TSR_WR_MASK (0x67) /* write 1 to clear bits */
+
+/* ETH_RSR */
+#define ETH_RSR_BNA (1U << 0) /* BNA: Buffer Not Available */
+#define ETH_RSR_REC (1U << 1) /* REC: Frame Received */
+#define ETH_RSR_OVR (1U << 2) /* OVR: RX Overrun */
+
+/* ETH_ISR */
+#define ETH_ISR_DONE (1U << 0) /* DONE: Management Done */
+#define ETH_ISR_RCOM (1U << 1) /* RCOM: Receive Complete */
+#define ETH_ISR_RBNA (1U << 2) /* RBNA: Receive Buffer Not Avail */
+#define ETH_ISR_TOVR (1U << 3) /* TOVR: Transmit Buffer Overrun */
+#define ETH_ISR_TUND (1U << 4) /* TUND: Transmit Buffer Underrun */
+#define ETH_ISR_RTRY (1U << 5) /* RTRY: Retry Limit */
+#define ETH_ISR_TBRE (1U << 6) /* TBRE: Trasnmit Buffer Reg empty */
+#define ETH_ISR_TCOM (1U << 7) /* TCOM: Transmit Complete */
+#define ETH_ISR_TIDLE (1U << 8) /* TIDLE: Transmit Idle */
+#define ETH_ISR_LINK (1U << 9) /* LINK: Link pin delta (optional) */
+#define ETH_ISR_ROVR (1U << 10) /* ROVR: RX Overrun */
+#define ETH_ISR_ABT (1U << 11) /* ABT: Abort */
+
+/* ETHB_UIO */
+#define ETHB_UIO_RMII (1U << 0) /* RMII: Reduce MII */
+#define ETHB_UIO_CLKE (1U << 1) /* CLKE: Clock Enable */
+
+/* ETH_MAN */
+#define ETH_MAN_BITS 0x40020000 /* HIGH and CODE bits */
+#define ETH_MAN_READ (2U << 28)
+#define ETH_MAN_WRITE (1U << 28)
+#define ETH_MAN_PHYA_BIT 23
+#define ETH_MAN_REGA_BIT 18
+#define ETH_MAN_VALUE_MASK 0xffffU
+#define ETH_MAN_REG_WR(phy, reg, val) \
+ (ETH_MAN_BITS | ETH_MAN_WRITE | ((phy) << ETH_MAN_PHYA_BIT) | \
+ ((reg) << ETH_MAN_REGA_BIT) | ((val) & ETH_MAN_VALUE_MASK))
+#define ETH_MAN_REG_RD(phy, reg) \
+ (ETH_MAN_BITS | ETH_MAN_READ | ((phy) << ETH_MAN_PHYA_BIT) | \
+ ((reg) << ETH_MAN_REGA_BIT))
+
+typedef struct {
+ uint32_t addr;
+#define ETH_CPU_OWNER (1U << 0)
+#define ETH_WRAP_BIT (1U << 1)
+#define ETH_ADR_MASK ~(EHT_CPU_OWNER | ETH_WRAP_BIT)
+ uint32_t status;
+#define ETH_LEN_MASK 0x7ff
+#define ETH_BUF_FIRST (1U << 14) /* Packet matched addr 4 */
+#define ETH_BUF_LAST (1U << 15) /* Packet matched addr 4 */
+#define ETH_MAC_LOCAL_4 (1U << 23) /* Packet matched addr 4 */
+#define ETH_MAC_LOCAL_3 (1U << 24) /* Packet matched addr 3 */
+#define ETH_MAC_LOCAL_2 (1U << 25) /* Packet matched addr 2 */
+#define ETH_MAC_LOCAL_1 (1U << 26) /* Packet matched addr 1 */
+#define ETH_MAC_UNK (1U << 27) /* Unkown source address RFU */
+#define ETH_MAC_EXT (1U << 28) /* External Address */
+#define ETH_MAC_UCAST (1U << 29) /* Unicast hash match */
+#define ETH_MAC_MCAST (1U << 30) /* Multicast hash match */
+#define ETH_MAC_ONES (1U << 31) /* Global all ones bcast addr */
+} eth_rx_desc_t;
+
+typedef struct {
+ uint32_t addr;
+ uint32_t status;
+#define ETHB_TX_LEN_MASK 0x7ff
+#define ETHB_TX_BUF_LAST (1U << 15) /* Last buffer in packet */
+#define ETHB_TX_NOCRC (1U << 16) /* Don't xmit CRC*/
+#define ETHB_TX_BUFE (1U << 27) /* Buffers exhausted mid frame */
+#define ETHB_TX_TUND (1U << 28) /* Transmit Underrun */
+#define ETHB_TX_RTRYE (1U << 29) /* Re-try limit exceeded */
+#define ETHB_TX_WRAP (1U << 30) /* Last descritor in list */
+#define ETHB_TX_USED (1U << 31) /* Packet Transmitted */
+} eth_tx_desc_t;
+
+#endif /* ARM_AT91_IF_ATEREG_H */
Property changes on: trunk/sys/arm/at91/if_atereg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/if_macb.c
===================================================================
--- trunk/sys/arm/at91/if_macb.c (rev 0)
+++ trunk/sys/arm/at91/if_macb.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1554 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/if_macb.c 243882 2012-12-05 08:04:20Z glebius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/if_macbreg.h>
+#include <arm/at91/if_macbvar.h>
+#include <arm/at91/at91_piovar.h>
+
+#include <arm/at91/at91sam9g20reg.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+/* "device miibus" required. See GENERIC if you get errors here. */
+#include "miibus_if.h"
+
+
+#define MACB_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define MACB_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define MACB_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+ MTX_NETWORK_LOCK, MTX_DEF)
+#define MACB_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define MACB_LOCK_ASSERT(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define MACB_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+
+static inline uint32_t
+read_4(struct macb_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+write_4(struct macb_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+
+static devclass_t macb_devclass;
+
+/* ifnet entry points */
+
+static void macbinit_locked(void *);
+static void macbstart_locked(struct ifnet *);
+
+static void macbinit(void *);
+static void macbstart(struct ifnet *);
+static void macbstop(struct macb_softc *);
+static int macbioctl(struct ifnet * ifp, u_long, caddr_t);
+
+/* bus entry points */
+
+static int macb_probe(device_t dev);
+static int macb_attach(device_t dev);
+static int macb_detach(device_t dev);
+
+/* helper functions */
+static int
+macb_new_rxbuf(struct macb_softc *sc, int index);
+
+static void
+macb_free_desc_dma_tx(struct macb_softc *sc);
+
+static void
+macb_free_desc_dma_rx(struct macb_softc *sc);
+
+static void
+macb_init_desc_dma_tx(struct macb_softc *sc);
+
+static void
+macb_watchdog(struct macb_softc *sc);
+
+static int macb_intr_rx_locked(struct macb_softc *sc, int count);
+static void macb_intr_task(void *arg, int pending __unused);
+static void macb_intr(void *xsc);
+
+static void
+macb_tx_cleanup(struct macb_softc *sc);
+
+static inline int
+phy_write(struct macb_softc *sc, int phy, int reg, int data);
+
+static void macb_reset(struct macb_softc *sc);
+
+static void
+macb_deactivate(device_t dev)
+{
+ struct macb_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ macb_free_desc_dma_tx(sc);
+ macb_free_desc_dma_rx(sc);
+
+}
+
+static void
+macb_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ bus_addr_t *paddr;
+
+ KASSERT(nsegs == 1, ("wrong number of segments, should be 1"));
+ paddr = arg;
+ *paddr = segs->ds_addr;
+}
+
+static int
+macb_alloc_desc_dma_tx(struct macb_softc *sc)
+{
+ int error, i;
+
+ /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
+ error = bus_dma_tag_create(sc->sc_parent_tag, /* parent */
+ 16, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ sizeof(struct eth_tx_desc) * MACB_MAX_TX_BUFFERS, /* max size */
+ 1, /* nsegments */
+ sizeof(struct eth_tx_desc) * MACB_MAX_TX_BUFFERS,
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->dmatag_data_tx); /* dmat */
+ if (error != 0) {
+ device_printf(sc->dev,
+ "Couldn't create TX descriptor dma tag\n");
+ return (error);
+ }
+ /* Allocate memory for TX ring. */
+ error = bus_dmamem_alloc(sc->dmatag_data_tx,
+ (void**)&(sc->desc_tx), BUS_DMA_NOWAIT | BUS_DMA_ZERO |
+ BUS_DMA_COHERENT, &sc->dmamap_ring_tx);
+ if (error != 0) {
+ device_printf(sc->dev, "failed to allocate TX dma memory\n");
+ return (error);
+ }
+ /* Load Ring DMA. */
+ error = bus_dmamap_load(sc->dmatag_data_tx, sc->dmamap_ring_tx,
+ sc->desc_tx, sizeof(struct eth_tx_desc) * MACB_MAX_TX_BUFFERS,
+ macb_getaddr, &sc->ring_paddr_tx, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ device_printf(sc->dev, "can't load TX descriptor dma map\n");
+ return (error);
+ }
+ /* Allocate a busdma tag for mbufs. No alignment restriction applys. */
+ error = bus_dma_tag_create(sc->sc_parent_tag, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ MCLBYTES * MAX_FRAGMENT, /* maxsize */
+ MAX_FRAGMENT, /* nsegments */
+ MCLBYTES, 0, /* maxsegsz, flags */
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->dmatag_ring_tx); /* dmat */
+ if (error != 0) {
+ device_printf(sc->dev, "failed to create TX mbuf dma tag\n");
+ return (error);
+ }
+
+ for (i = 0; i < MACB_MAX_TX_BUFFERS; i++) {
+ /* Create dma map for each descriptor. */
+ error = bus_dmamap_create(sc->dmatag_ring_tx, 0,
+ &sc->tx_desc[i].dmamap);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "failed to create TX mbuf dma map\n");
+ return (error);
+ }
+ }
+ return (0);
+}
+
+static void
+macb_free_desc_dma_tx(struct macb_softc *sc)
+{
+ struct tx_desc_info *td;
+ int i;
+
+ /* TX buffers. */
+ if (sc->dmatag_ring_tx != NULL) {
+ for (i = 0; i < MACB_MAX_TX_BUFFERS; i++) {
+ td = &sc->tx_desc[i];
+ if (td->dmamap != NULL) {
+ bus_dmamap_destroy(sc->dmatag_ring_tx,
+ td->dmamap);
+ td->dmamap = NULL;
+ }
+ }
+ bus_dma_tag_destroy(sc->dmatag_ring_tx);
+ sc->dmatag_ring_tx = NULL;
+ }
+
+ /* TX descriptor ring. */
+ if (sc->dmatag_data_tx != NULL) {
+ if (sc->dmamap_ring_tx != NULL)
+ bus_dmamap_unload(sc->dmatag_data_tx,
+ sc->dmamap_ring_tx);
+ if (sc->dmamap_ring_tx != NULL && sc->desc_tx != NULL)
+ bus_dmamem_free(sc->dmatag_data_tx, sc->desc_tx,
+ sc->dmamap_ring_tx);
+ sc->dmamap_ring_tx = NULL;
+ sc->dmamap_ring_tx = NULL;
+ bus_dma_tag_destroy(sc->dmatag_data_tx);
+ sc->dmatag_data_tx = NULL;
+ }
+}
+
+static void
+macb_init_desc_dma_tx(struct macb_softc *sc)
+{
+ struct eth_tx_desc *desc;
+ int i;
+
+ MACB_LOCK_ASSERT(sc);
+
+ sc->tx_prod = 0;
+ sc->tx_cons = 0;
+ sc->tx_cnt = 0;
+
+ desc = &sc->desc_tx[0];
+ bzero(desc, sizeof(struct eth_tx_desc) * MACB_MAX_TX_BUFFERS);
+
+ for (i = 0; i < MACB_MAX_TX_BUFFERS; i++) {
+ desc = &sc->desc_tx[i];
+ if (i == MACB_MAX_TX_BUFFERS - 1)
+ desc->flags = TD_OWN | TD_WRAP_MASK;
+ else
+ desc->flags = TD_OWN;
+ }
+
+ bus_dmamap_sync(sc->dmatag_data_tx, sc->dmamap_ring_tx,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+}
+
+static int
+macb_alloc_desc_dma_rx(struct macb_softc *sc)
+{
+ int error, i;
+
+ /* Allocate a busdma tag and DMA safe memory for RX descriptors. */
+ error = bus_dma_tag_create(sc->sc_parent_tag, /* parent */
+ 16, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ /* maxsize, nsegments */
+ sizeof(struct eth_rx_desc) * MACB_MAX_RX_BUFFERS, 1,
+ /* maxsegsz, flags */
+ sizeof(struct eth_rx_desc) * MACB_MAX_RX_BUFFERS, 0,
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->dmatag_data_rx); /* dmat */
+ if (error != 0) {
+ device_printf(sc->dev,
+ "Couldn't create RX descriptor dma tag\n");
+ return (error);
+ }
+ /* Allocate RX ring. */
+ error = bus_dmamem_alloc(sc->dmatag_data_rx, (void**)&(sc->desc_rx),
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
+ &sc->dmamap_ring_rx);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "failed to allocate RX descriptor dma memory\n");
+ return (error);
+ }
+
+ /* Load dmamap. */
+ error = bus_dmamap_load(sc->dmatag_data_rx, sc->dmamap_ring_rx,
+ sc->desc_rx, sizeof(struct eth_rx_desc) * MACB_MAX_RX_BUFFERS,
+ macb_getaddr, &sc->ring_paddr_rx, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ device_printf(sc->dev, "can't load RX descriptor dma map\n");
+ return (error);
+ }
+
+ /* Allocate a busdma tag for mbufs. */
+ error = bus_dma_tag_create(sc->sc_parent_tag,/* parent */
+ 16, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ MCLBYTES, 1, /* maxsize, nsegments */
+ MCLBYTES, 0, /* maxsegsz, flags */
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->dmatag_ring_rx); /* dmat */
+
+ if (error != 0) {
+ device_printf(sc->dev, "failed to create RX mbuf dma tag\n");
+ return (error);
+ }
+
+ for (i = 0; i < MACB_MAX_RX_BUFFERS; i++) {
+ error = bus_dmamap_create(sc->dmatag_ring_rx, 0,
+ &sc->rx_desc[i].dmamap);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "failed to create RX mbuf dmamap\n");
+ return (error);
+ }
+ }
+
+ return (0);
+}
+
+static void
+macb_free_desc_dma_rx(struct macb_softc *sc)
+{
+ struct rx_desc_info *rd;
+ int i;
+
+ /* RX buffers. */
+ if (sc->dmatag_ring_rx != NULL) {
+ for (i = 0; i < MACB_MAX_RX_BUFFERS; i++) {
+ rd = &sc->rx_desc[i];
+ if (rd->dmamap != NULL) {
+ bus_dmamap_destroy(sc->dmatag_ring_rx,
+ rd->dmamap);
+ rd->dmamap = NULL;
+ }
+ }
+ bus_dma_tag_destroy(sc->dmatag_ring_rx);
+ sc->dmatag_ring_rx = NULL;
+ }
+ /* RX descriptor ring. */
+ if (sc->dmatag_data_rx != NULL) {
+ if (sc->dmamap_ring_rx != NULL)
+ bus_dmamap_unload(sc->dmatag_data_rx,
+ sc->dmamap_ring_rx);
+ if (sc->dmamap_ring_rx != NULL &&
+ sc->desc_rx != NULL)
+ bus_dmamem_free(sc->dmatag_data_rx, sc->desc_rx,
+ sc->dmamap_ring_rx);
+ sc->desc_rx = NULL;
+ sc->dmamap_ring_rx = NULL;
+ bus_dma_tag_destroy(sc->dmatag_data_rx);
+ sc->dmatag_data_rx = NULL;
+ }
+}
+
+static int
+macb_init_desc_dma_rx(struct macb_softc *sc)
+{
+ struct eth_rx_desc *desc;
+ struct rx_desc_info *rd;
+ int i;
+
+ MACB_LOCK_ASSERT(sc);
+
+ sc->rx_cons = 0;
+ desc = &sc->desc_rx[0];
+ bzero(desc, sizeof(struct eth_rx_desc) * MACB_MAX_RX_BUFFERS);
+ for (i = 0; i < MACB_MAX_RX_BUFFERS; i++) {
+ rd = &sc->rx_desc[i];
+ rd->buff = NULL;
+ if (macb_new_rxbuf(sc, i) != 0)
+ return (ENOBUFS);
+ }
+ bus_dmamap_sync(sc->dmatag_ring_rx, sc->dmamap_ring_rx,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ return (0);
+}
+
+static int
+macb_new_rxbuf(struct macb_softc *sc, int index)
+{
+ struct rx_desc_info *rd;
+ struct eth_rx_desc *desc;
+ struct mbuf *m;
+ bus_dma_segment_t seg[1];
+ int error, nsegs;
+
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL)
+ return (ENOBUFS);
+ m->m_len = m->m_pkthdr.len = MCLBYTES - ETHER_ALIGN;
+ rd = &sc->rx_desc[index];
+ bus_dmamap_unload(sc->dmatag_ring_rx, rd->dmamap);
+ error = bus_dmamap_load_mbuf_sg(sc->dmatag_ring_rx, rd->dmamap, m,
+ seg, &nsegs, 0);
+ KASSERT(nsegs == 1, ("Too many segments returned!"));
+ if (error != 0) {
+ m_free(m);
+ return (error);
+ }
+
+ bus_dmamap_sync(sc->dmatag_ring_rx, rd->dmamap, BUS_DMASYNC_PREREAD);
+ rd->buff = m;
+
+ desc = &sc->desc_rx[index];
+ desc->addr = seg[0].ds_addr;
+
+ desc->flags = DATA_SIZE;
+
+ if (index == MACB_MAX_RX_BUFFERS - 1)
+ desc->addr |= RD_WRAP_MASK;
+
+ return (0);
+}
+
+static int
+macb_allocate_dma(struct macb_softc *sc)
+{
+ int error;
+
+ /* Create parent tag for tx and rx */
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev), /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ BUS_SPACE_MAXSIZE_32BIT, 0, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->sc_parent_tag);
+ if (error != 0) {
+ device_printf(sc->dev, "Couldn't create parent DMA tag\n");
+ return (error);
+ }
+
+ if ((error = macb_alloc_desc_dma_tx(sc)) != 0)
+ return (error);
+ if ((error = macb_alloc_desc_dma_rx(sc)) != 0)
+ return (error);
+ return (0);
+}
+
+
+static void
+macb_tick(void *xsc)
+{
+ struct macb_softc *sc;
+ struct mii_data *mii;
+
+ sc = xsc;
+ mii = device_get_softc(sc->miibus);
+ mii_tick(mii);
+ macb_watchdog(sc);
+ /*
+ * Schedule another timeout one second from now.
+ */
+ callout_reset(&sc->tick_ch, hz, macb_tick, sc);
+}
+
+
+static void
+macb_watchdog(struct macb_softc *sc)
+{
+ struct ifnet *ifp;
+
+ MACB_LOCK_ASSERT(sc);
+
+ if (sc->macb_watchdog_timer == 0 || --sc->macb_watchdog_timer)
+ return;
+
+ ifp = sc->ifp;
+ if ((sc->flags & MACB_FLAG_LINK) == 0) {
+ if_printf(ifp, "watchdog timeout (missed link)\n");
+ ifp->if_oerrors++;
+ return;
+ }
+
+ if_printf(ifp, "watchdog timeout\n");
+ ifp->if_oerrors++;
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ macbinit_locked(sc);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ macbstart_locked(ifp);
+}
+
+
+
+static void
+macbinit_locked(void *xsc)
+{
+ struct macb_softc *sc;
+ struct ifnet *ifp;
+ int err;
+ uint32_t config;
+ struct mii_data *mii;
+
+ sc = xsc;
+ ifp = sc->ifp;
+
+ MACB_LOCK_ASSERT(sc);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
+ if ((err = macb_init_desc_dma_rx(sc)) != 0) {
+ device_printf(sc->dev, "no memory for RX buffers\n");
+ //ecestop(sc);
+ return;
+ }
+ macb_init_desc_dma_tx(sc);
+
+ config = read_4(sc, EMAC_NCFGR) | (sc->clock << 10); /*set clock*/
+ config |= CFG_PAE; /* PAuse Enable */
+ config |= CFG_DRFCS; /* Discard Rx FCS */
+ config |= CFG_SPD; /* 100 mbps*/
+ //config |= CFG_CAF;
+ config |= CFG_FD;
+
+ config |= CFG_RBOF_2; /*offset +2*/
+
+ write_4(sc, EMAC_NCFGR, config);
+
+ /* Initialize TX and RX buffers */
+ write_4(sc, EMAC_RBQP, sc->ring_paddr_rx);
+ write_4(sc, EMAC_TBQP, sc->ring_paddr_tx);
+
+ /* Enable TX and RX */
+ write_4(sc, EMAC_NCR, RX_ENABLE | TX_ENABLE | MPE_ENABLE);
+
+
+ /* Enable interrupts */
+ write_4(sc, EMAC_IER, (RCOMP_INTERRUPT |
+ RXUBR_INTERRUPT |
+ TUND_INTERRUPT |
+ RLE_INTERRUPT |
+ TXERR_INTERRUPT |
+ ROVR_INTERRUPT |
+ HRESP_INTERRUPT|
+ TCOMP_INTERRUPT
+ ));
+
+ /*
+ * Set 'running' flag, and clear output active flag
+ * and attempt to start the output
+ */
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ mii = device_get_softc(sc->miibus);
+
+ sc->flags |= MACB_FLAG_LINK;
+
+ mii_mediachg(mii);
+
+ callout_reset(&sc->tick_ch, hz, macb_tick, sc);
+}
+
+
+static void
+macb_tx_cleanup(struct macb_softc *sc)
+{
+ struct ifnet *ifp;
+ struct eth_tx_desc *desc;
+ struct tx_desc_info *td;
+ int flags;
+ int status;
+ int i;
+
+ MACB_LOCK_ASSERT(sc);
+
+ status = read_4(sc, EMAC_TSR);
+
+ write_4(sc, EMAC_TSR, status);
+
+ /*buffer underrun*/
+ if ((status & TSR_UND) != 0) {
+ /*reset buffers*/
+ printf("underrun\n");
+ bus_dmamap_sync(sc->dmatag_data_tx, sc->dmamap_ring_tx,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ sc->tx_cons = sc->tx_prod = 0;
+ for (i = 0; i < MACB_MAX_TX_BUFFERS; i++) {
+ desc = &sc->desc_tx[i];
+ desc->flags = TD_OWN;
+ }
+
+ for (i = 0; i < MACB_MAX_TX_BUFFERS; i++) {
+ td = &sc->tx_desc[i];
+ if (td->buff != NULL) {
+ /* We are finished with this descriptor. */
+ bus_dmamap_sync(sc->dmatag_ring_tx, td->dmamap,
+ BUS_DMASYNC_POSTWRITE);
+ /* ... and unload, so we can reuse. */
+ bus_dmamap_unload(sc->dmatag_data_tx,
+ td->dmamap);
+ m_freem(td->buff);
+ td->buff = NULL;
+ }
+ }
+ }
+
+ if ((status & TSR_COMP) == 0)
+ return;
+
+
+ if (sc->tx_cons == sc->tx_prod)
+ return;
+
+ ifp = sc->ifp;
+
+ /* Prepare to read the ring (owner bit). */
+ bus_dmamap_sync(sc->dmatag_data_tx, sc->dmamap_ring_tx,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ while (sc->tx_cons != sc->tx_prod) {
+ desc = &sc->desc_tx[sc->tx_cons];
+ if ((desc->flags & TD_OWN) == 0)
+ break;
+
+ td = &sc->tx_desc[sc->tx_cons];
+ if (td->buff != NULL) {
+ /* We are finished with this descriptor. */
+ bus_dmamap_sync(sc->dmatag_ring_tx, td->dmamap,
+ BUS_DMASYNC_POSTWRITE);
+ /* ... and unload, so we can reuse. */
+ bus_dmamap_unload(sc->dmatag_data_tx,
+ td->dmamap);
+ m_freem(td->buff);
+ td->buff = NULL;
+ ifp->if_opackets++;
+ }
+
+ do {
+ sc->tx_cnt--;
+ MACB_DESC_INC(sc->tx_cons, MACB_MAX_TX_BUFFERS);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ flags = desc->flags;
+ desc->flags = TD_OWN;
+ desc = &sc->desc_tx[sc->tx_cons];
+ if (flags & TD_LAST) {
+ break;
+ }
+ } while (sc->tx_cons != sc->tx_prod);
+ }
+
+ /* Unarm watchog timer when there is no pending descriptors in queue. */
+ if (sc->tx_cnt == 0)
+ sc->macb_watchdog_timer = 0;
+}
+
+static void
+macb_rx(struct macb_softc *sc)
+{
+ struct eth_rx_desc *rxdesc;
+ struct ifnet *ifp;
+ struct mbuf *m;
+ int rxbytes;
+ int flags;
+ int nsegs;
+ int first;
+
+ rxdesc = &(sc->desc_rx[sc->rx_cons]);
+
+ ifp = sc->ifp;
+
+ bus_dmamap_sync(sc->dmatag_ring_rx, sc->dmamap_ring_rx,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+
+ nsegs = 0;
+ while (rxdesc->addr & RD_OWN) {
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ break;
+
+ flags = rxdesc->flags;
+
+ rxbytes = flags & RD_LEN_MASK;
+
+ m = sc->rx_desc[sc->rx_cons].buff;
+
+ bus_dmamap_sync(sc->dmatag_ring_rx,
+ sc->rx_desc[sc->rx_cons].dmamap, BUS_DMASYNC_POSTREAD);
+ if (macb_new_rxbuf(sc, sc->rx_cons) != 0) {
+ ifp->if_iqdrops++;
+ first = sc->rx_cons;
+
+ do {
+ rxdesc->flags = DATA_SIZE;
+ MACB_DESC_INC(sc->rx_cons, MACB_MAX_RX_BUFFERS);
+ if ((rxdesc->flags & RD_EOF) != 0)
+ break;
+ rxdesc = &(sc->desc_rx[sc->rx_cons]);
+ } while (sc->rx_cons != first);
+
+ if (sc->macb_cdata.rxhead != NULL) {
+ m_freem(sc->macb_cdata.rxhead);
+ sc->macb_cdata.rxhead = NULL;
+ sc->macb_cdata.rxtail = NULL;
+ }
+
+ break;
+ }
+
+ nsegs++;
+
+ /* Chain received mbufs. */
+ if (sc->macb_cdata.rxhead == NULL) {
+ m->m_data += 2;
+ sc->macb_cdata.rxhead = m;
+ sc->macb_cdata.rxtail = m;
+ if (flags & RD_EOF)
+ m->m_len = rxbytes;
+ else
+ m->m_len = DATA_SIZE - 2;
+ } else {
+ m->m_flags &= ~M_PKTHDR;
+ m->m_len = DATA_SIZE;
+ sc->macb_cdata.rxtail->m_next = m;
+ sc->macb_cdata.rxtail = m;
+ }
+
+ if (flags & RD_EOF) {
+
+ if (nsegs > 1) {
+ sc->macb_cdata.rxtail->m_len = (rxbytes -
+ ((nsegs - 1) * DATA_SIZE)) + 2;
+ }
+
+ m = sc->macb_cdata.rxhead;
+ m->m_flags |= M_PKTHDR;
+ m->m_pkthdr.len = rxbytes;
+ m->m_pkthdr.rcvif = ifp;
+ ifp->if_ipackets++;
+
+ nsegs = 0;
+ MACB_UNLOCK(sc);
+ (*ifp->if_input)(ifp, m);
+ MACB_LOCK(sc);
+ sc->macb_cdata.rxhead = NULL;
+ sc->macb_cdata.rxtail = NULL;
+
+ }
+
+ rxdesc->addr &= ~RD_OWN;
+
+ MACB_DESC_INC(sc->rx_cons, MACB_MAX_RX_BUFFERS);
+
+ rxdesc = &(sc->desc_rx[sc->rx_cons]);
+ }
+
+ write_4(sc, EMAC_IER, (RCOMP_INTERRUPT|RXUBR_INTERRUPT));
+
+}
+
+static int
+macb_intr_rx_locked(struct macb_softc *sc, int count)
+{
+ macb_rx(sc);
+ return (0);
+}
+
+static void
+macb_intr_task(void *arg, int pending __unused)
+{
+ struct macb_softc *sc;
+
+ sc = arg;
+ MACB_LOCK(sc);
+ macb_intr_rx_locked(sc, -1);
+ MACB_UNLOCK(sc);
+}
+
+static void
+macb_intr(void *xsc)
+{
+ struct macb_softc *sc;
+ struct ifnet *ifp;
+ uint32_t status;
+
+ sc = xsc;
+ ifp = sc->ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ printf("not running\n");
+ return;
+ }
+
+ MACB_LOCK(sc);
+ status = read_4(sc, EMAC_ISR);
+
+ while (status) {
+ if (status & RCOMP_INTERRUPT) {
+ write_4(sc, EMAC_IDR, (RCOMP_INTERRUPT|RXUBR_INTERRUPT));
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_intr_task);
+ }
+
+ if (status & TCOMP_INTERRUPT) {
+ macb_tx_cleanup(sc);
+ }
+
+ status = read_4(sc, EMAC_ISR);
+ }
+
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ macbstart_locked(ifp);
+ MACB_UNLOCK(sc);
+}
+
+static inline int
+macb_encap(struct macb_softc *sc, struct mbuf **m_head)
+{
+ struct eth_tx_desc *desc;
+ struct tx_desc_info *txd, *txd_last;
+ struct mbuf *m;
+ bus_dma_segment_t segs[MAX_FRAGMENT];
+ bus_dmamap_t map;
+ uint32_t csum_flags;
+ int error, i, nsegs, prod, si;
+
+ M_ASSERTPKTHDR((*m_head));
+
+ prod = sc->tx_prod;
+
+ m = *m_head;
+
+ txd = txd_last = &sc->tx_desc[prod];
+ error = bus_dmamap_load_mbuf_sg(sc->dmatag_ring_tx, txd->dmamap,
+ *m_head, segs, &nsegs, 0);
+ if (error == EFBIG) {
+ m = m_collapse(*m_head, M_NOWAIT, MAX_FRAGMENT);
+ if (m == NULL) {
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (ENOMEM);
+ }
+ *m_head = m;
+ error = bus_dmamap_load_mbuf_sg(sc->dmatag_ring_tx, txd->dmamap,
+ *m_head, segs, &nsegs, 0);
+ if (error != 0) {
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (error);
+ }
+ } else if (error != 0) {
+ return (error);
+ }
+ /* Check for TX descriptor overruns. */
+ if (sc->tx_cnt + nsegs > MACB_MAX_TX_BUFFERS - 1) {
+ bus_dmamap_unload(sc->dmatag_ring_tx, txd->dmamap);
+ return (ENOBUFS);
+ }
+ bus_dmamap_sync(sc->dmatag_ring_tx, txd->dmamap, BUS_DMASYNC_PREWRITE);
+ m = *m_head;
+
+ /* TODO: VLAN hardware tag insertion. */
+
+ csum_flags = 0;
+ si = prod;
+ desc = NULL;
+
+ for (i = 0; i < nsegs; i++) {
+ desc = &sc->desc_tx[prod];
+ desc->addr = segs[i].ds_addr;
+
+ if (i == 0 ) {
+ desc->flags = segs[i].ds_len | TD_OWN;
+ } else {
+ desc->flags = segs[i].ds_len;
+ }
+
+ if (prod == MACB_MAX_TX_BUFFERS - 1)
+ desc->flags |= TD_WRAP_MASK;
+
+ sc->tx_cnt++;
+ MACB_DESC_INC(prod, MACB_MAX_TX_BUFFERS);
+ }
+ /*
+ * Set EOP on the last fragment.
+ */
+
+ desc->flags |= TD_LAST;
+ desc = &sc->desc_tx[si];
+ desc->flags &= ~TD_OWN;
+
+ sc->tx_prod = prod;
+
+ /* Swap the first dma map and the last. */
+ map = txd_last->dmamap;
+ txd_last->dmamap = txd->dmamap;
+ txd->dmamap = map;
+ txd->buff = m;
+
+ return (0);
+}
+
+
+static void
+macbstart_locked(struct ifnet *ifp)
+{
+
+
+
+ struct macb_softc *sc;
+ struct mbuf *m0;
+#if 0
+ struct mbuf *m_new;
+#endif
+ int queued = 0;
+
+ sc = ifp->if_softc;
+
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING || (sc->flags & MACB_FLAG_LINK) == 0) {
+ return;
+ }
+
+ while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+ /* Get packet from the queue */
+ IF_DEQUEUE(&ifp->if_snd, m0);
+ if (m0 == NULL)
+ break;
+#if 0
+ if (m0->m_next != NULL) {
+ /* Fragmented mbuf chain, collapse it. */
+ m_new = m_defrag(m0, M_NOWAIT);
+ if (m_new != NULL) {
+ /* Original frame freed. */
+ m0 = m_new;
+ } else {
+ /* Defragmentation failed, just use the chain. */
+ }
+ }
+#endif
+ if (macb_encap(sc, &m0)) {
+ if (m0 == NULL)
+ break;
+ IF_PREPEND(&ifp->if_snd, m0);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
+ queued++;
+ BPF_MTAP(ifp, m0);
+ }
+ if (IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ if (queued) {
+ bus_dmamap_sync(sc->dmatag_data_tx, sc->dmamap_ring_tx,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ write_4(sc, EMAC_NCR, read_4(sc, EMAC_NCR) | TRANSMIT_START);
+ sc->macb_watchdog_timer = MACB_TIMEOUT;
+ }
+}
+
+static void
+macbinit(void *xsc)
+{
+ struct macb_softc *sc = xsc;
+
+ MACB_LOCK(sc);
+ macbinit_locked(sc);
+ MACB_UNLOCK(sc);
+}
+
+static void
+macbstart(struct ifnet *ifp)
+{
+ struct macb_softc *sc = ifp->if_softc;
+ MACB_ASSERT_UNLOCKED(sc);
+ MACB_LOCK(sc);
+ macbstart_locked(ifp);
+ MACB_UNLOCK(sc);
+
+}
+
+
+static void
+macbstop(struct macb_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
+ struct rx_desc_info *rd;
+ struct tx_desc_info *td;
+ int i;
+
+ ifp = sc->ifp;
+
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+
+ macb_reset(sc);
+
+ sc->flags &= ~MACB_FLAG_LINK;
+ callout_stop(&sc->tick_ch);
+ sc->macb_watchdog_timer = 0;
+
+ /* Free TX/RX mbufs still in the queues. */
+ for (i = 0; i < MACB_MAX_TX_BUFFERS; i++) {
+ td = &sc->tx_desc[i];
+ if (td->buff != NULL) {
+ bus_dmamap_sync(sc->dmatag_ring_tx, td->dmamap,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->dmatag_data_tx, td->dmamap);
+ m_freem(td->buff);
+ td->buff = NULL;
+ }
+ }
+ for (i = 0; i < MACB_MAX_RX_BUFFERS; i++) {
+ rd = &sc->rx_desc[i];
+ if (rd->buff != NULL) {
+ bus_dmamap_sync(sc->dmatag_ring_rx, rd->dmamap,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->dmatag_data_rx, rd->dmamap);
+ m_freem(rd->buff);
+ rd->buff = NULL;
+ }
+ }
+}
+
+static int
+get_hash_index(uint8_t *mac)
+{
+ int i, j, k;
+ int result;
+ int bit;
+
+ result = 0;
+ for (i = 0; i < 6; i++) {
+ bit = 0;
+ for (j = 0; j < 8; j++) {
+ k = j * 6 + i;
+ bit ^= (mac[k/8] & (1 << (k % 8)) ) != 0;
+ }
+ result |= bit;
+ }
+ return result;
+}
+
+static void
+set_mac_filter(uint32_t *filter, uint8_t *mac)
+{
+ int bits;
+
+ bits = get_hash_index(mac);
+ filter[bits >> 5] |= 1 << (bits & 31);
+}
+
+static void
+set_filter(struct macb_softc *sc)
+{
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ int config;
+ int count;
+ uint32_t multicast_filter[2];
+
+ ifp = sc->ifp;
+
+ config = read_4(sc, EMAC_NCFGR);
+
+ config &= ~(CFG_CAF | CFG_MTI);
+ write_4(sc, EMAC_HRB, 0);
+ write_4(sc, EMAC_HRT, 0);
+
+ if ((ifp->if_flags & (IFF_ALLMULTI |IFF_PROMISC)) != 0){
+ if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
+ write_4(sc, EMAC_HRB, ~0);
+ write_4(sc, EMAC_HRT, ~0);
+ config |= CFG_MTI;
+ }
+ if ((ifp->if_flags & IFF_PROMISC) != 0) {
+ config |= CFG_CAF;
+ }
+ write_4(sc, EMAC_NCFGR, config);
+ return;
+ }
+
+ if_maddr_rlock(ifp);
+ count = 0;
+ multicast_filter[0] = 0;
+ multicast_filter[1] = 0;
+
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ count++;
+ set_mac_filter(multicast_filter,
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ }
+ if (count) {
+ write_4(sc, EMAC_HRB, multicast_filter[0]);
+ write_4(sc, EMAC_HRT, multicast_filter[1]);
+ write_4(sc, EMAC_NCFGR, config|CFG_MTI);
+ }
+ if_maddr_runlock(ifp);
+}
+
+static int
+macbioctl(struct ifnet * ifp, u_long cmd, caddr_t data)
+{
+
+ struct macb_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+ struct ifreq *ifr = (struct ifreq *)data;
+
+ int error = 0;
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ MACB_LOCK(sc);
+
+ if ((ifp->if_flags & IFF_UP) != 0) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ if (((ifp->if_flags ^ sc->if_flags)
+ & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+ set_filter(sc);
+ } else {
+ macbinit_locked(sc);
+ }
+ } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ macbstop(sc);
+ }
+ sc->if_flags = ifp->if_flags;
+ MACB_UNLOCK(sc);
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ MACB_LOCK(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ set_filter(sc);
+
+ MACB_UNLOCK(sc);
+ break;
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ mii = device_get_softc(sc->miibus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ break;
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ }
+ return (error);
+
+}
+
+/* bus entry points */
+
+static int
+macb_probe(device_t dev)
+{
+ device_set_desc(dev, "macb");
+ return (0);
+}
+
+/*
+ * Change media according to request.
+ */
+static int
+macb_ifmedia_upd(struct ifnet *ifp)
+{
+ struct macb_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+
+ mii = device_get_softc(sc->miibus);
+ MACB_LOCK(sc);
+ mii_mediachg(mii);
+ MACB_UNLOCK(sc);
+ return (0);
+}
+
+/*
+ * Notify the world which media we're using.
+ */
+static void
+macb_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct macb_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+
+ mii = device_get_softc(sc->miibus);
+
+ MACB_LOCK(sc);
+ /* Don't report link state if driver is not running. */
+ if ((ifp->if_flags & IFF_UP) == 0) {
+ MACB_UNLOCK(sc);
+ return;
+ }
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ MACB_UNLOCK(sc);
+}
+
+static void
+macb_reset(struct macb_softc *sc)
+{
+ /*
+ * Disable RX and TX
+ */
+ write_4(sc, EMAC_NCR, 0);
+
+ write_4(sc, EMAC_NCR, CLEAR_STAT);
+
+ /* Clear all status flags */
+ write_4(sc, EMAC_TSR, ~0UL);
+ write_4(sc, EMAC_RSR, ~0UL);
+
+ /* Disable all interrupts */
+ write_4(sc, EMAC_IDR, ~0UL);
+ read_4(sc, EMAC_ISR);
+
+}
+
+
+static int
+macb_get_mac(struct macb_softc *sc, u_char *eaddr)
+{
+ uint32_t bottom;
+ uint16_t top;
+
+ bottom = read_4(sc, EMAC_SA1B);
+ top = read_4(sc, EMAC_SA1T);
+
+ eaddr[0] = bottom & 0xff;
+ eaddr[1] = (bottom >> 8) & 0xff;
+ eaddr[2] = (bottom >> 16) & 0xff;
+ eaddr[3] = (bottom >> 24) & 0xff;
+ eaddr[4] = top & 0xff;
+ eaddr[5] = (top >> 8) & 0xff;
+
+ return (0);
+}
+
+
+static int
+macb_attach(device_t dev)
+{
+ struct macb_softc *sc;
+ struct ifnet *ifp = NULL;
+ struct sysctl_ctx_list *sctx;
+ struct sysctl_oid *soid;
+ int pclk_hz;
+ u_char eaddr[ETHER_ADDR_LEN];
+ int rid;
+ int err;
+ struct at91_pmc_clock *master;
+
+
+ err = 0;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ MACB_LOCK_INIT(sc);
+
+ callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
+
+ /*
+ * Allocate resources.
+ */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resources.\n");
+ err = ENOMEM;
+ goto out;
+ }
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "could not allocate interrupt resources.\n");
+ err = ENOMEM;
+ goto out;
+ }
+
+ /*setup clock*/
+ sc->clk = at91_pmc_clock_ref(device_get_nameunit(sc->dev));
+ at91_pmc_clock_enable(sc->clk);
+
+ macb_reset(sc);
+ macb_get_mac(sc, eaddr);
+
+ master = at91_pmc_clock_ref("mck");
+
+ pclk_hz = master->hz;
+
+ sc->clock = CFG_CLK_8;
+ if (pclk_hz <= 20000000)
+ sc->clock = CFG_CLK_8;
+ else if (pclk_hz <= 40000000)
+ sc->clock = CFG_CLK_16;
+ else if (pclk_hz <= 80000000)
+ sc->clock = CFG_CLK_32;
+ else
+ sc->clock = CFG_CLK_64;
+
+ sc->clock = sc->clock << 10;
+
+ write_4(sc, EMAC_NCFGR, sc->clock);
+ write_4(sc, EMAC_USRIO, USRIO_CLOCK); //enable clock
+
+ write_4(sc, EMAC_NCR, MPE_ENABLE); //enable MPE
+
+ sc->ifp = ifp = if_alloc(IFT_ETHER);
+ err = mii_attach(dev, &sc->miibus, ifp, macb_ifmedia_upd,
+ macb_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ if (err != 0) {
+ device_printf(dev, "attaching PHYs failed\n");
+ goto out;
+ }
+
+ if (macb_allocate_dma(sc) != 0)
+ goto out;
+
+ /* Sysctls */
+ sctx = device_get_sysctl_ctx(dev);
+ soid = device_get_sysctl_tree(dev);
+
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_capabilities |= IFCAP_VLAN_MTU;
+ ifp->if_capenable |= IFCAP_VLAN_MTU; /* The hw bits already set. */
+ ifp->if_start = macbstart;
+ ifp->if_ioctl = macbioctl;
+ ifp->if_init = macbinit;
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_READY(&ifp->if_snd);
+ sc->if_flags = ifp->if_flags;
+
+ TASK_INIT(&sc->sc_intr_task, 0, macb_intr_task, sc);
+
+ sc->sc_tq = taskqueue_create_fast("macb_taskq", M_WAITOK,
+ taskqueue_thread_enqueue, &sc->sc_tq);
+ if (sc->sc_tq == NULL) {
+ device_printf(sc->dev, "could not create taskqueue\n");
+ goto out;
+ }
+
+ ether_ifattach(ifp, eaddr);
+
+ /*
+ * Activate the interrupt.
+ */
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, macb_intr, sc, &sc->intrhand);
+ if (err) {
+ device_printf(dev, "could not establish interrupt handler.\n");
+ ether_ifdetach(ifp);
+ goto out;
+ }
+
+ taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
+ device_get_nameunit(sc->dev));
+
+ sc->macb_cdata.rxhead = 0;
+ sc->macb_cdata.rxtail = 0;
+
+ phy_write(sc, 0, 0, 0x3300); //force autoneg
+
+ return (0);
+out:
+
+ return (err);
+}
+
+static int
+macb_detach(device_t dev)
+{
+ struct macb_softc *sc;
+
+ sc = device_get_softc(dev);
+ ether_ifdetach(sc->ifp);
+ MACB_LOCK(sc);
+ macbstop(sc);
+ MACB_UNLOCK(sc);
+ callout_drain(&sc->tick_ch);
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ taskqueue_drain(sc->sc_tq, &sc->sc_intr_task);
+ taskqueue_free(sc->sc_tq);
+ macb_deactivate(dev);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+ MACB_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+/*PHY related functions*/
+static inline int
+phy_read(struct macb_softc *sc, int phy, int reg)
+{
+ int val;
+
+ write_4(sc, EMAC_MAN, EMAC_MAN_REG_RD(phy, reg));
+ while ((read_4(sc, EMAC_SR) & EMAC_SR_IDLE) == 0)
+ continue;
+ val = read_4(sc, EMAC_MAN) & EMAC_MAN_VALUE_MASK;
+
+ return (val);
+}
+
+static inline int
+phy_write(struct macb_softc *sc, int phy, int reg, int data)
+{
+
+ write_4(sc, EMAC_MAN, EMAC_MAN_REG_WR(phy, reg, data));
+ while ((read_4(sc, EMAC_SR) & EMAC_SR_IDLE) == 0)
+ continue;
+
+ return (0);
+}
+
+/*
+ * MII bus support routines.
+ */
+static int
+macb_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct macb_softc *sc;
+ sc = device_get_softc(dev);
+ return (phy_read(sc, phy, reg));
+}
+
+static int
+macb_miibus_writereg(device_t dev, int phy, int reg, int data)
+{
+ struct macb_softc *sc;
+ sc = device_get_softc(dev);
+ return (phy_write(sc, phy, reg, data));
+}
+
+static void
+macb_child_detached(device_t dev, device_t child)
+{
+ struct macb_softc *sc;
+ sc = device_get_softc(dev);
+
+}
+
+static void
+macb_miibus_statchg(device_t dev)
+{
+ struct macb_softc *sc;
+ struct mii_data *mii;
+ int config;
+
+ sc = device_get_softc(dev);
+
+ mii = device_get_softc(sc->miibus);
+
+ sc->flags &= ~MACB_FLAG_LINK;
+
+ config = read_4(sc, EMAC_NCFGR);
+
+ if ((mii->mii_media_status & IFM_AVALID) != 0) {
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_10_T:
+ config &= ~(CFG_SPD);
+ sc->flags |= MACB_FLAG_LINK;
+ break;
+ case IFM_100_TX:
+ config |= CFG_SPD;
+ sc->flags |= MACB_FLAG_LINK;
+ break;
+ default:
+ break;
+ }
+ }
+
+ config |= CFG_FD;
+ write_4(sc, EMAC_NCFGR, config);
+}
+
+static device_method_t macb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, macb_probe),
+ DEVMETHOD(device_attach, macb_attach),
+ DEVMETHOD(device_detach, macb_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_child_detached, macb_child_detached),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, macb_miibus_readreg),
+ DEVMETHOD(miibus_writereg, macb_miibus_writereg),
+ DEVMETHOD(miibus_statchg, macb_miibus_statchg),
+ { 0, 0 }
+};
+
+static driver_t macb_driver = {
+ "macb",
+ macb_methods,
+ sizeof(struct macb_softc),
+};
+
+
+DRIVER_MODULE(macb, atmelarm, macb_driver, macb_devclass, 0, 0);
+DRIVER_MODULE(miibus, macb, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(macb, miibus, 1, 1, 1);
+MODULE_DEPEND(macb, ether, 1, 1, 1);
Property changes on: trunk/sys/arm/at91/if_macb.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/if_macbreg.h
===================================================================
--- trunk/sys/arm/at91/if_macbreg.h (rev 0)
+++ trunk/sys/arm/at91/if_macbreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,107 @@
+/* $MidnightBSD$ */
+/*
+ * $FreeBSD: stable/10/sys/arm/at91/if_macbreg.h 210040 2010-07-14 00:48:53Z cognet $
+ */
+
+#ifndef MACB_REG_H
+#define MACB_REG_H
+
+#define EMAC_NCR 0x00
+#define EMAC_NCFGR 0x04
+#define EMAC_TSR 0x14
+#define EMAC_RSR 0x20
+#define EMAC_ISR 0x24
+#define EMAC_IER 0x28
+#define EMAC_IDR 0x2C
+#define EMAC_IMR 0x30
+
+
+
+#define EMAC_RBQP 0x18
+#define EMAC_TBQP 0x1C
+
+#define EMAC_HRB 0x90
+#define EMAC_HRT 0x94
+
+#define EMAC_SA1B 0x98
+#define EMAC_SA1T 0x9C
+
+#define EMAC_USRIO 0xC0
+
+#define EMAC_MAN 0x34 /* EMAC PHY Maintenance Register */
+#define EMAC_SR 0x08 /* EMAC STatus Register */
+#define EMAC_SR_LINK (1U << 0) /* Reserved! */
+#define EMAC_SR_MDIO (1U << 1) /* MDIO pin status */
+#define EMAC_SR_IDLE (1U << 2) /* IDLE (PHY logic) */
+
+#define RX_ENABLE (1 << 2)
+#define TX_ENABLE (1 << 3)
+#define MPE_ENABLE (1 << 4)
+
+
+/* EMAC_MAN */
+#define EMAC_MAN_BITS 0x40020000 /* HIGH and CODE bits */
+#define EMAC_MAN_READ (2U << 28)
+#define EMAC_MAN_WRITE (1U << 28)
+#define EMAC_MAN_PHYA_BIT 23
+#define EMAC_MAN_REGA_BIT 18
+#define EMAC_MAN_VALUE_MASK 0xffffU
+#define EMAC_MAN_REG_WR(phy, reg, val) \
+ (EMAC_MAN_BITS | EMAC_MAN_WRITE | ((phy) << EMAC_MAN_PHYA_BIT) | \
+ ((reg) << EMAC_MAN_REGA_BIT) | ((val) & EMAC_MAN_VALUE_MASK))
+
+#define EMAC_MAN_REG_RD(phy, reg) \
+ (EMAC_MAN_BITS | EMAC_MAN_READ | ((phy) << EMAC_MAN_PHYA_BIT) | \
+ ((reg) << EMAC_MAN_REGA_BIT))
+
+#define RCOMP_INTERRUPT (1 << 1)
+#define RXUBR_INTERRUPT (1 << 2)
+#define TUBR_INTERRUPT (1 << 3)
+#define TUND_INTERRUPT (1 << 4)
+#define RLE_INTERRUPT (1 << 5)
+#define TXERR_INTERRUPT (1 << 6)
+#define ROVR_INTERRUPT (1 << 10)
+#define HRESP_INTERRUPT (1 << 11)
+#define TCOMP_INTERRUPT (1 << 7)
+
+#define CLEAR_STAT (1 << 5)
+
+#define TRANSMIT_START (1 << 9)
+#define TRANSMIT_STOP (1 << 10)
+
+/*Transmit status register flags*/
+#define TSR_UND (1 << 6)
+#define TSR_COMP (1 << 5)
+#define TSR_BEX (1 << 4)
+#define TSR_TGO (1 << 3)
+#define TSR_RLE (1 << 2)
+#define TSR_COL (1 << 1)
+#define TSR_UBR (1 << 0)
+
+#define CFG_SPD (1 << 0)
+#define CFG_FD (1 << 1)
+#define CFG_CAF (1 << 4)
+#define CFG_NBC (1 << 5)
+#define CFG_MTI (1 << 6)
+#define CFG_UNI (1 << 7)
+#define CFG_BIG (1 << 8)
+
+#define CFG_CLK_8 (0)
+#define CFG_CLK_16 (1)
+#define CFG_CLK_32 (2)
+#define CFG_CLK_64 (3)
+
+#define CFG_PAE (1 << 13)
+
+#define CFG_RBOF_0 (0 << 14)
+#define CFG_RBOF_1 (1 << 14)
+#define CFG_RBOF_2 (2 << 14)
+#define CFG_RBOF_3 (3 << 14)
+
+#define CFG_DRFCS (1 << 17)
+
+#define USRIO_CLOCK (1 << 1)
+
+
+
+#endif
Property changes on: trunk/sys/arm/at91/if_macbreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/if_macbvar.h
===================================================================
--- trunk/sys/arm/at91/if_macbvar.h (rev 0)
+++ trunk/sys/arm/at91/if_macbvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,139 @@
+/* $MidnightBSD$ */
+/*
+ * $FreeBSD: stable/10/sys/arm/at91/if_macbvar.h 261455 2014-02-04 03:36:42Z eadler $
+ */
+
+#ifndef _IF_MACB_H
+#define _IF_MACB_H
+
+#define MACB_MAX_TX_BUFFERS 64
+#define MACB_MAX_RX_BUFFERS 256
+
+#define MAX_FRAGMENT 20
+#define DATA_SIZE 128
+
+#define MACB_DESC_INC(x, y) ((x) = ((x) + 1) % (y))
+
+#define MACB_TIMEOUT 1000
+
+struct eth_tx_desc {
+ uint32_t addr;
+ uint32_t flags;
+#define TD_OWN (1U << 31)
+#define TD_LAST (1 << 15)
+#define TD_WRAP_MASK (1 << 30)
+};
+
+struct eth_rx_desc {
+ uint32_t addr;
+#define RD_LEN_MASK 0x7ff
+#define RD_WRAP_MASK 0x00000002
+#define RD_OWN 0x00000001
+
+ uint32_t flags;
+#define RD_BROADCAST (1U << 31)
+#define RD_MULTICAST (1 << 30)
+#define RD_UNICAST (1 << 29)
+#define RD_EXTERNAL (1 << 28)
+#define RD_TYPE_ID (1 << 22)
+#define RD_PRIORITY (1 << 20)
+#define RD_VLAN (1 << 21)
+#define RD_CONCAT (1 << 16)
+#define RD_EOF (1 << 15)
+#define RD_SOF (1 << 14)
+#define RD_OFFSET_MASK (1 << 13)|(1 << 12)
+#define RD_LENGTH_MASK (0x00000FFF)
+
+};
+
+
+struct rx_desc_info {
+ struct mbuf *buff;
+ bus_dmamap_t dmamap;
+};
+
+struct tx_desc_info {
+ struct mbuf *buff;
+ bus_dmamap_t dmamap;
+};
+
+
+struct macb_chain_data{
+ struct mbuf *rxhead;
+ struct mbuf *rxtail;
+};
+
+struct macb_softc
+{
+ struct ifnet *ifp; /* ifnet pointer */
+ struct mtx sc_mtx; /* global mutex */
+
+ bus_dma_tag_t sc_parent_tag; /* parent bus DMA tag */
+
+ device_t dev; /* Myself */
+ device_t miibus; /* My child miibus */
+ void *intrhand; /* Interrupt handle */
+ void *intrhand_qf; /* queue full */
+ void *intrhand_tx; /* tx complete */
+ void *intrhand_status; /* error status */
+
+ struct resource *irq_res; /* transmit */
+ struct resource *irq_res_rec; /* receive */
+ struct resource *irq_res_qf; /* queue full */
+ struct resource *irq_res_status; /* status */
+
+ struct resource *mem_res; /* Memory resource */
+
+ struct callout tick_ch; /* Tick callout */
+
+ struct taskqueue *sc_tq;
+ struct task sc_intr_task;
+ struct task sc_tx_task;
+ struct task sc_link_task;
+
+ bus_dmamap_t dmamap_ring_tx;
+ bus_dmamap_t dmamap_ring_rx;
+
+ /*dma tag for ring*/
+ bus_dma_tag_t dmatag_ring_tx;
+ bus_dma_tag_t dmatag_ring_rx;
+
+ /*dma tag for data*/
+ bus_dma_tag_t dmatag_data_tx;
+ bus_dma_tag_t dmatag_data_rx;
+
+ /*the ring*/
+ struct eth_tx_desc *desc_tx;
+ struct eth_rx_desc *desc_rx;
+
+ /*ring physical address*/
+ bus_addr_t ring_paddr_tx;
+ bus_addr_t ring_paddr_rx;
+
+ /*index of last received descriptor*/
+ int rx_cons;
+ struct rx_desc_info rx_desc[MACB_MAX_RX_BUFFERS];
+
+ /* tx producer index */
+ uint32_t tx_prod;
+ /* tx consumer index */
+ uint32_t tx_cons;
+ int tx_cnt;
+
+ struct tx_desc_info tx_desc[MACB_MAX_TX_BUFFERS];
+
+ int macb_watchdog_timer;
+
+#define MACB_FLAG_LINK 0x0001
+
+ int flags;
+ int if_flags;
+ struct at91_pmc_clock *clk;
+
+ struct macb_chain_data macb_cdata;
+ int clock;
+};
+
+
+
+#endif
Property changes on: trunk/sys/arm/at91/if_macbvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/std.at91
===================================================================
--- trunk/sys/arm/at91/std.at91 (rev 0)
+++ trunk/sys/arm/at91/std.at91 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,11 @@
+# $FreeBSD: stable/10/sys/arm/at91/std.at91 239362 2012-08-18 05:48:19Z andrew $
+
+files "../at91/files.at91"
+cpu CPU_ARM9
+machine arm
+makeoptions CONF_CFLAGS=-mcpu=arm9
+options PHYSADDR=0x20000000
+options NO_EVENTTIMERS
+
+# For now, just do the AT91RM9200
+device at91rm9200
Property changes on: trunk/sys/arm/at91/std.at91
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.at91sam9
===================================================================
--- trunk/sys/arm/at91/std.at91sam9 (rev 0)
+++ trunk/sys/arm/at91/std.at91sam9 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,11 @@
+# $FreeBSD: stable/10/sys/arm/at91/std.at91sam9 239362 2012-08-18 05:48:19Z andrew $
+
+files "../at91/files.at91"
+cpu CPU_ARM9
+machine arm
+makeoptions CONF_CFLAGS=-mcpu=arm9
+options PHYSADDR=0x20000000
+options NO_EVENTTIMERS
+
+# bring in the sam specific timers and such
+device at91sam9
Property changes on: trunk/sys/arm/at91/std.at91sam9
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.at91sam9g45
===================================================================
--- trunk/sys/arm/at91/std.at91sam9g45 (rev 0)
+++ trunk/sys/arm/at91/std.at91sam9g45 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,16 @@
+# $FreeBSD: stable/10/sys/arm/at91/std.at91sam9g45 239362 2012-08-18 05:48:19Z andrew $
+#
+# Unlike other Atmel SoCs, which have their SDRAM at CS1, the
+# at91sam9g45 family has it on CS6, so PHYSADDR must be adjusted
+# accordingly. The at91sam9g45, at91sam9g46, at91sam9m10 and at91sam9m11
+# SoCs are members of this family.
+
+files "../at91/files.at91"
+cpu CPU_ARM9
+machine arm
+makeoptions CONF_CFLAGS=-mcpu=arm9
+options PHYSADDR=0x70000000
+options NO_EVENTTIMERS
+
+# bring in the sam specific timers and such
+device at91sam9
Property changes on: trunk/sys/arm/at91/std.at91sam9g45
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.atmel
===================================================================
--- trunk/sys/arm/at91/std.atmel (rev 0)
+++ trunk/sys/arm/at91/std.atmel 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,14 @@
+# $FreeBSD: stable/10/sys/arm/at91/std.atmel 274268 2014-11-08 03:42:19Z ian $
+
+include "../at91/std.at91sam9"
+
+# Supported SoCs for the at91 platform
+device at91rm9200
+device at91sam9260
+device at91sam9g20
+device at91sam9g45
+device at91sam9x5
+
+# bring in the sam specific timers and such
+device at91sam9
+
Property changes on: trunk/sys/arm/at91/std.atmel
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.bwct
===================================================================
--- trunk/sys/arm/at91/std.bwct (rev 0)
+++ trunk/sys/arm/at91/std.bwct 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.bwct 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91"
+
+makeoptions KERNPHYSADDR=0x20000000
+options KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_bwct
Property changes on: trunk/sys/arm/at91/std.bwct
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.eb9200
===================================================================
--- trunk/sys/arm/at91/std.eb9200 (rev 0)
+++ trunk/sys/arm/at91/std.eb9200 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.eb9200 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91"
+
+makeoptions KERNPHYSADDR=0x20000000
+options KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_eb9200
Property changes on: trunk/sys/arm/at91/std.eb9200
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.ethernut5
===================================================================
--- trunk/sys/arm/at91/std.ethernut5 (rev 0)
+++ trunk/sys/arm/at91/std.ethernut5 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+# $FreeBSD: stable/10/sys/arm/at91/std.ethernut5 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91sam9"
+
+makeoptions KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x20000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_ethernut5
+device at91sam9260
Property changes on: trunk/sys/arm/at91/std.ethernut5
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.hl200
===================================================================
--- trunk/sys/arm/at91/std.hl200 (rev 0)
+++ trunk/sys/arm/at91/std.hl200 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.hl200 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91"
+
+makeoptions KERNPHYSADDR=0x20100000
+options KERNPHYSADDR=0x20100000
+makeoptions KERNVIRTADDR=0xc0100000
+options KERNVIRTADDR=0xc0100000
+
+device at91_board_hl200
Property changes on: trunk/sys/arm/at91/std.hl200
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.hl201
===================================================================
--- trunk/sys/arm/at91/std.hl201 (rev 0)
+++ trunk/sys/arm/at91/std.hl201 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.hl201 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91sam9"
+
+makeoptions KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x20000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_hl201
+device at91sam9g20
Property changes on: trunk/sys/arm/at91/std.hl201
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.kb920x
===================================================================
--- trunk/sys/arm/at91/std.kb920x (rev 0)
+++ trunk/sys/arm/at91/std.kb920x 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.kb920x 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91"
+
+makeoptions KERNPHYSADDR=0x20000000
+options KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_kb920x
Property changes on: trunk/sys/arm/at91/std.kb920x
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.qila9g20
===================================================================
--- trunk/sys/arm/at91/std.qila9g20 (rev 0)
+++ trunk/sys/arm/at91/std.qila9g20 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.qila9g20 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91sam9"
+
+makeoptions KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x20000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_qila9g20
+device at91sam9g20
Property changes on: trunk/sys/arm/at91/std.qila9g20
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.sam9260ek
===================================================================
--- trunk/sys/arm/at91/std.sam9260ek (rev 0)
+++ trunk/sys/arm/at91/std.sam9260ek 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+# $FreeBSD: stable/10/sys/arm/at91/std.sam9260ek 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91sam9"
+
+makeoptions KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x20000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_sam9260ek
+device at91sam9260
Property changes on: trunk/sys/arm/at91/std.sam9260ek
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.sam9g20ek
===================================================================
--- trunk/sys/arm/at91/std.sam9g20ek (rev 0)
+++ trunk/sys/arm/at91/std.sam9g20ek 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.sam9g20ek 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91sam9"
+
+makeoptions KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x20000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_sam9g20ek
+device at91sam9g20
Property changes on: trunk/sys/arm/at91/std.sam9g20ek
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.sam9x25ek
===================================================================
--- trunk/sys/arm/at91/std.sam9x25ek (rev 0)
+++ trunk/sys/arm/at91/std.sam9x25ek 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.sam9x25ek 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91sam9"
+
+makeoptions KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x20000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_sam9x25ek
+device at91sam9x5
Property changes on: trunk/sys/arm/at91/std.sam9x25ek
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.sn9g45
===================================================================
--- trunk/sys/arm/at91/std.sn9g45 (rev 0)
+++ trunk/sys/arm/at91/std.sn9g45 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,11 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.sn9g45 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91sam9g45"
+
+makeoptions KERNPHYSADDR=0x70008000
+options KERNPHYSADDR=0x70008000
+makeoptions KERNVIRTADDR=0xc0008000
+options KERNVIRTADDR=0xc0008000
+
+device at91sam9g45
+device at91_board_sn9g45
+
Property changes on: trunk/sys/arm/at91/std.sn9g45
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/std.tsc4370
===================================================================
--- trunk/sys/arm/at91/std.tsc4370 (rev 0)
+++ trunk/sys/arm/at91/std.tsc4370 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+#$FreeBSD: stable/10/sys/arm/at91/std.tsc4370 266110 2014-05-15 02:41:23Z ian $
+include "../at91/std.at91"
+
+makeoptions KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x20000000
+options KERNVIRTADDR=0xc0000000
+
+device at91_board_tsc4370
Property changes on: trunk/sys/arm/at91/std.tsc4370
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/at91/uart_bus_at91usart.c
===================================================================
--- trunk/sys/arm/at91/uart_bus_at91usart.c (rev 0)
+++ trunk/sys/arm/at91/uart_bus_at91usart.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,112 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_uart.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/uart_bus_at91usart.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/at91/at91var.h>
+
+#include "uart_if.h"
+
+extern struct uart_class at91_usart_class;
+static int usart_at91_probe(device_t dev);
+
+static device_method_t usart_at91_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, usart_at91_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, uart_bus_detach),
+ { 0, 0 }
+};
+
+static driver_t usart_at91_driver = {
+ uart_driver_name,
+ usart_at91_methods,
+ sizeof(struct uart_softc),
+};
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+
+static int
+usart_at91_probe(device_t dev)
+{
+ struct uart_softc *sc;
+
+ sc = device_get_softc(dev);
+ switch (device_get_unit(dev))
+ {
+ case 0:
+ device_set_desc(dev, "DBGU");
+ /*
+ * Setting sc_sysdev makes this device a 'system device' and
+ * indirectly makes it the system console.
+ */
+ sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
+ bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
+ break;
+ case 1:
+ device_set_desc(dev, "USART0");
+ break;
+ case 2:
+ device_set_desc(dev, "USART1");
+ break;
+ case 3:
+ device_set_desc(dev, "USART2");
+ break;
+ case 4:
+ device_set_desc(dev, "USART3");
+ break;
+ case 5:
+ device_set_desc(dev, "USART4");
+ break;
+ case 6:
+ device_set_desc(dev, "USART5");
+ break;
+ }
+ sc->sc_class = &at91_usart_class;
+ if (sc->sc_class->uc_rclk == 0)
+ sc->sc_class->uc_rclk = at91_master_clock;
+ return (uart_bus_probe(dev, 0, 0, 0, device_get_unit(dev)));
+}
+
+
+DRIVER_MODULE(uart, atmelarm, usart_at91_driver, uart_devclass, 0, 0);
Property changes on: trunk/sys/arm/at91/uart_bus_at91usart.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/uart_cpu_at91usart.c
===================================================================
--- trunk/sys/arm/at91/uart_cpu_at91usart.c (rev 0)
+++ trunk/sys/arm/at91/uart_cpu_at91usart.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,92 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * Copyright (c) 2006 M. Warner Losh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+#include "opt_uart.h"
+
+#ifndef FDT
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/uart_cpu_at91usart.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/at91/at91var.h>
+
+bus_space_tag_t uart_bus_space_io;
+bus_space_tag_t uart_bus_space_mem;
+
+extern struct bus_space at91_bs_tag;
+extern struct uart_class at91_usart_class;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+ return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+ struct uart_class *class;
+
+ class = &at91_usart_class;
+ if (class->uc_rclk == 0 && at91_master_clock != 0)
+ class->uc_rclk = at91_master_clock;
+ di->ops = uart_getops(class);
+ di->bas.chan = 0;
+ di->bas.bst = &at91_bs_tag;
+ /*
+ * XXX: Not pretty, but will work because we map the needed addresses
+ * early. At least we probed this so that the console will work on
+ * all flavors of Atmel we can detect.
+ */
+ di->bas.bsh = soc_info.dbgu_base;
+ di->baudrate = 115200;
+ di->bas.regshft = 0;
+ di->bas.rclk = 0;
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ uart_bus_space_io = &at91_bs_tag;
+ uart_bus_space_mem = NULL;
+ /* Check the environment for overrides */
+ uart_getenv(devtype, di, class);
+ return (0);
+}
+#endif
Property changes on: trunk/sys/arm/at91/uart_cpu_at91usart.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/at91/uart_dev_at91usart.c
===================================================================
--- trunk/sys/arm/at91/uart_dev_at91usart.c (rev 0)
+++ trunk/sys/arm/at91/uart_dev_at91usart.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,881 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 M. Warner Losh
+ * Copyright (c) 2005 Olivier Houchard
+ * Copyright (c) 2012 Ian Lepore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/at91/uart_dev_at91usart.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/tty.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#ifdef FDT
+#include <dev/uart/uart_cpu_fdt.h>
+#endif
+#include <dev/uart/uart_bus.h>
+#include <arm/at91/at91_usartreg.h>
+#include <arm/at91/at91_pdcreg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91_pioreg.h>
+#include <arm/at91/at91rm92reg.h>
+#include <arm/at91/at91var.h>
+
+#include "uart_if.h"
+
+#define DEFAULT_RCLK at91_master_clock
+#define USART_DEFAULT_FIFO_BYTES 128
+
+#define USART_DCE_CHANGE_BITS (USART_CSR_CTSIC | USART_CSR_DCDIC | \
+ USART_CSR_DSRIC | USART_CSR_RIIC)
+
+/*
+ * High-level UART interface.
+ */
+struct at91_usart_rx {
+ bus_addr_t pa;
+ uint8_t *buffer;
+ bus_dmamap_t map;
+};
+
+struct at91_usart_softc {
+ struct uart_softc base;
+ bus_dma_tag_t tx_tag;
+ bus_dmamap_t tx_map;
+ uint32_t flags;
+#define HAS_TIMEOUT 0x1
+#define USE_RTS0_WORKAROUND 0x2
+ bus_dma_tag_t rx_tag;
+ struct at91_usart_rx ping_pong[2];
+ struct at91_usart_rx *ping;
+ struct at91_usart_rx *pong;
+};
+
+#define RD4(bas, reg) \
+ bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg))
+#define WR4(bas, reg, value) \
+ bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value)
+
+#define SIGCHG(c, i, s, d) \
+ do { \
+ if (c) { \
+ i |= (i & s) ? s : s | d; \
+ } else { \
+ i = (i & s) ? (i & ~s) | d : i; \
+ } \
+ } while (0);
+
+#define BAUD2DIVISOR(b) \
+ ((((DEFAULT_RCLK * 10) / ((b) * 16)) + 5) / 10)
+
+/*
+ * Low-level UART interface.
+ */
+static int at91_usart_probe(struct uart_bas *bas);
+static void at91_usart_init(struct uart_bas *bas, int, int, int, int);
+static void at91_usart_term(struct uart_bas *bas);
+static void at91_usart_putc(struct uart_bas *bas, int);
+static int at91_usart_rxready(struct uart_bas *bas);
+static int at91_usart_getc(struct uart_bas *bas, struct mtx *hwmtx);
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+
+static int
+at91_usart_param(struct uart_bas *bas, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ uint32_t mr;
+
+ /*
+ * Assume 3-wire RS-232 configuration.
+ * XXX Not sure how uart will present the other modes to us, so
+ * XXX they are unimplemented. maybe ioctl?
+ */
+ mr = USART_MR_MODE_NORMAL;
+ mr |= USART_MR_USCLKS_MCK; /* Assume MCK */
+
+ /*
+ * Or in the databits requested
+ */
+ if (databits < 9)
+ mr &= ~USART_MR_MODE9;
+ switch (databits) {
+ case 5:
+ mr |= USART_MR_CHRL_5BITS;
+ break;
+ case 6:
+ mr |= USART_MR_CHRL_6BITS;
+ break;
+ case 7:
+ mr |= USART_MR_CHRL_7BITS;
+ break;
+ case 8:
+ mr |= USART_MR_CHRL_8BITS;
+ break;
+ case 9:
+ mr |= USART_MR_CHRL_8BITS | USART_MR_MODE9;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /*
+ * Or in the parity
+ */
+ switch (parity) {
+ case UART_PARITY_NONE:
+ mr |= USART_MR_PAR_NONE;
+ break;
+ case UART_PARITY_ODD:
+ mr |= USART_MR_PAR_ODD;
+ break;
+ case UART_PARITY_EVEN:
+ mr |= USART_MR_PAR_EVEN;
+ break;
+ case UART_PARITY_MARK:
+ mr |= USART_MR_PAR_MARK;
+ break;
+ case UART_PARITY_SPACE:
+ mr |= USART_MR_PAR_SPACE;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /*
+ * Or in the stop bits. Note: The hardware supports 1.5 stop
+ * bits in async mode, but there's no way to specify that
+ * AFAICT. Instead, rely on the convention documented at
+ * http://www.lammertbies.nl/comm/info/RS-232_specs.html which
+ * states that 1.5 stop bits are used for 5 bit bytes and
+ * 2 stop bits only for longer bytes.
+ */
+ if (stopbits == 1)
+ mr |= USART_MR_NBSTOP_1;
+ else if (databits > 5)
+ mr |= USART_MR_NBSTOP_2;
+ else
+ mr |= USART_MR_NBSTOP_1_5;
+
+ /*
+ * We want normal plumbing mode too, none of this fancy
+ * loopback or echo mode.
+ */
+ mr |= USART_MR_CHMODE_NORMAL;
+
+ mr &= ~USART_MR_MSBF; /* lsb first */
+ mr &= ~USART_MR_CKLO_SCK; /* Don't drive SCK */
+
+ WR4(bas, USART_MR, mr);
+
+ /*
+ * Set the baud rate (only if we know our master clock rate)
+ */
+ if (DEFAULT_RCLK != 0)
+ WR4(bas, USART_BRGR, BAUD2DIVISOR(baudrate));
+
+ /*
+ * Set the receive timeout based on the baud rate. The idea is to
+ * compromise between being responsive on an interactive connection and
+ * giving a bulk data sender a bit of time to queue up a new buffer
+ * without mistaking it for a stopping point in the transmission. For
+ * 19.2kbps and below, use 20 * bit time (2 characters). For faster
+ * connections use 500 microseconds worth of bits.
+ */
+ if (baudrate <= 19200)
+ WR4(bas, USART_RTOR, 20);
+ else
+ WR4(bas, USART_RTOR, baudrate / 2000);
+ WR4(bas, USART_CR, USART_CR_STTTO);
+
+ /* XXX Need to take possible synchronous mode into account */
+ return (0);
+}
+
+static struct uart_ops at91_usart_ops = {
+ .probe = at91_usart_probe,
+ .init = at91_usart_init,
+ .term = at91_usart_term,
+ .putc = at91_usart_putc,
+ .rxready = at91_usart_rxready,
+ .getc = at91_usart_getc,
+};
+
+#ifdef EARLY_PRINTF
+/*
+ * Early printf support. This assumes that we have the SoC "system" devices
+ * mapped into AT91_BASE. To use this before we adjust the boostrap tables,
+ * you'll need to define SOCDEV_VA to be 0xdc000000 and SOCDEV_PA to be
+ * 0xfc000000 in your config file where you define EARLY_PRINTF
+ */
+volatile uint32_t *at91_dbgu = (volatile uint32_t *)(AT91_BASE + AT91_DBGU0);
+
+static void
+eputc(int c)
+{
+
+ while (!(at91_dbgu[USART_CSR / 4] & USART_CSR_TXRDY))
+ continue;
+ at91_dbgu[USART_THR / 4] = c;
+}
+
+early_putc_t * early_putc = eputc;
+#endif
+
+static int
+at91_usart_probe(struct uart_bas *bas)
+{
+
+ /* We know that this is always here */
+ return (0);
+}
+
+/*
+ * Initialize this device for use as a console.
+ */
+static void
+at91_usart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+
+#ifdef EARLY_PRINTF
+ if (early_putc != NULL) {
+ printf("Early printf yielding control to the real console.\n");
+ early_putc = NULL;
+ }
+#endif
+
+ /*
+ * This routine is called multiple times, sometimes right after writing
+ * some output, and the last byte is still shifting out. If that's the
+ * case delay briefly before resetting, but don't loop on TXRDY because
+ * we don't want to hang here forever if the hardware is in a bad state.
+ */
+ if (!(RD4(bas, USART_CSR) & USART_CSR_TXRDY))
+ DELAY(10000);
+
+ at91_usart_param(bas, baudrate, databits, stopbits, parity);
+
+ /* Reset the rx and tx buffers and turn on rx and tx */
+ WR4(bas, USART_CR, USART_CR_RSTSTA | USART_CR_RSTRX | USART_CR_RSTTX);
+ WR4(bas, USART_CR, USART_CR_RXEN | USART_CR_TXEN);
+ WR4(bas, USART_IDR, 0xffffffff);
+}
+
+/*
+ * Free resources now that we're no longer the console. This appears to
+ * be never called, and I'm unsure quite what to do if I am called.
+ */
+static void
+at91_usart_term(struct uart_bas *bas)
+{
+
+ /* XXX */
+}
+
+/*
+ * Put a character of console output (so we do it here polling rather than
+ * interrupt driven).
+ */
+static void
+at91_usart_putc(struct uart_bas *bas, int c)
+{
+
+ while (!(RD4(bas, USART_CSR) & USART_CSR_TXRDY))
+ continue;
+ WR4(bas, USART_THR, c);
+}
+
+/*
+ * Check for a character available.
+ */
+static int
+at91_usart_rxready(struct uart_bas *bas)
+{
+
+ return ((RD4(bas, USART_CSR) & USART_CSR_RXRDY) != 0 ? 1 : 0);
+}
+
+/*
+ * Block waiting for a character.
+ */
+static int
+at91_usart_getc(struct uart_bas *bas, struct mtx *hwmtx)
+{
+ int c;
+
+ uart_lock(hwmtx);
+ while (!(RD4(bas, USART_CSR) & USART_CSR_RXRDY)) {
+ uart_unlock(hwmtx);
+ DELAY(4);
+ uart_lock(hwmtx);
+ }
+ c = RD4(bas, USART_RHR) & 0xff;
+ uart_unlock(hwmtx);
+ return (c);
+}
+
+static int at91_usart_bus_probe(struct uart_softc *sc);
+static int at91_usart_bus_attach(struct uart_softc *sc);
+static int at91_usart_bus_flush(struct uart_softc *, int);
+static int at91_usart_bus_getsig(struct uart_softc *);
+static int at91_usart_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int at91_usart_bus_ipend(struct uart_softc *);
+static int at91_usart_bus_param(struct uart_softc *, int, int, int, int);
+static int at91_usart_bus_receive(struct uart_softc *);
+static int at91_usart_bus_setsig(struct uart_softc *, int);
+static int at91_usart_bus_transmit(struct uart_softc *);
+static void at91_usart_bus_grab(struct uart_softc *);
+static void at91_usart_bus_ungrab(struct uart_softc *);
+
+static kobj_method_t at91_usart_methods[] = {
+ KOBJMETHOD(uart_probe, at91_usart_bus_probe),
+ KOBJMETHOD(uart_attach, at91_usart_bus_attach),
+ KOBJMETHOD(uart_flush, at91_usart_bus_flush),
+ KOBJMETHOD(uart_getsig, at91_usart_bus_getsig),
+ KOBJMETHOD(uart_ioctl, at91_usart_bus_ioctl),
+ KOBJMETHOD(uart_ipend, at91_usart_bus_ipend),
+ KOBJMETHOD(uart_param, at91_usart_bus_param),
+ KOBJMETHOD(uart_receive, at91_usart_bus_receive),
+ KOBJMETHOD(uart_setsig, at91_usart_bus_setsig),
+ KOBJMETHOD(uart_transmit, at91_usart_bus_transmit),
+ KOBJMETHOD(uart_grab, at91_usart_bus_grab),
+ KOBJMETHOD(uart_ungrab, at91_usart_bus_ungrab),
+
+ KOBJMETHOD_END
+};
+
+int
+at91_usart_bus_probe(struct uart_softc *sc)
+{
+ int value;
+
+ value = USART_DEFAULT_FIFO_BYTES;
+ resource_int_value(device_get_name(sc->sc_dev),
+ device_get_unit(sc->sc_dev), "fifo_bytes", &value);
+ value = roundup2(value, arm_dcache_align);
+ sc->sc_txfifosz = value;
+ sc->sc_rxfifosz = value;
+ sc->sc_hwiflow = 0;
+ return (0);
+}
+
+static void
+at91_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+ if (error != 0)
+ return;
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+static int
+at91_usart_requires_rts0_workaround(struct uart_softc *sc)
+{
+ int value;
+ int unit;
+
+ unit = device_get_unit(sc->sc_dev);
+
+ /*
+ * On the rm9200 chips, the PA21/RTS0 pin is not correctly wired to the
+ * usart device interally (so-called 'erratum 39', but it's 41.14 in rev
+ * I of the manual). This prevents use of the hardware flow control
+ * feature in the usart itself. It also means that if we are to
+ * implement RTS/CTS flow via the tty layer logic, we must use pin PA21
+ * as a gpio and manually manipulate it in at91_usart_bus_setsig(). We
+ * can only safely do so if we've been given permission via a hint,
+ * otherwise we might manipulate a pin that's attached to who-knows-what
+ * and Bad Things could happen.
+ */
+ if (at91_is_rm92() && unit == 1) {
+ value = 0;
+ resource_int_value(device_get_name(sc->sc_dev), unit,
+ "use_rts0_workaround", &value);
+ if (value != 0) {
+ at91_pio_use_gpio(AT91RM92_PIOA_BASE, AT91C_PIO_PA21);
+ at91_pio_gpio_output(AT91RM92_PIOA_BASE,
+ AT91C_PIO_PA21, 1);
+ at91_pio_use_periph_a(AT91RM92_PIOA_BASE,
+ AT91C_PIO_PA20, 0);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static int
+at91_usart_bus_attach(struct uart_softc *sc)
+{
+ int err;
+ int i;
+ uint32_t cr;
+ struct at91_usart_softc *atsc;
+
+ atsc = (struct at91_usart_softc *)sc;
+
+ if (at91_usart_requires_rts0_workaround(sc))
+ atsc->flags |= USE_RTS0_WORKAROUND;
+
+ /*
+ * See if we have a TIMEOUT bit. We disable all interrupts as
+ * a side effect. Boot loaders may have enabled them. Since
+ * a TIMEOUT interrupt can't happen without other setup, the
+ * apparent race here can't actually happen.
+ */
+ WR4(&sc->sc_bas, USART_IDR, 0xffffffff);
+ WR4(&sc->sc_bas, USART_IER, USART_CSR_TIMEOUT);
+ if (RD4(&sc->sc_bas, USART_IMR) & USART_CSR_TIMEOUT)
+ atsc->flags |= HAS_TIMEOUT;
+ WR4(&sc->sc_bas, USART_IDR, 0xffffffff);
+
+ /*
+ * Allocate transmit DMA tag and map. We allow a transmit buffer
+ * to be any size, but it must map to a single contiguous physical
+ * extent.
+ */
+ err = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, 1, BUS_SPACE_MAXSIZE_32BIT, 0, NULL,
+ NULL, &atsc->tx_tag);
+ if (err != 0)
+ goto errout;
+ err = bus_dmamap_create(atsc->tx_tag, 0, &atsc->tx_map);
+ if (err != 0)
+ goto errout;
+
+ if (atsc->flags & HAS_TIMEOUT) {
+ /*
+ * Allocate receive DMA tags, maps, and buffers.
+ * The receive buffers should be aligned to arm_dcache_align,
+ * otherwise partial cache line flushes on every receive
+ * interrupt are pretty much guaranteed.
+ */
+ err = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),
+ arm_dcache_align, 0, BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR, NULL, NULL, sc->sc_rxfifosz, 1,
+ sc->sc_rxfifosz, BUS_DMA_ALLOCNOW, NULL, NULL,
+ &atsc->rx_tag);
+ if (err != 0)
+ goto errout;
+ for (i = 0; i < 2; i++) {
+ err = bus_dmamem_alloc(atsc->rx_tag,
+ (void **)&atsc->ping_pong[i].buffer,
+ BUS_DMA_NOWAIT, &atsc->ping_pong[i].map);
+ if (err != 0)
+ goto errout;
+ err = bus_dmamap_load(atsc->rx_tag,
+ atsc->ping_pong[i].map,
+ atsc->ping_pong[i].buffer, sc->sc_rxfifosz,
+ at91_getaddr, &atsc->ping_pong[i].pa, 0);
+ if (err != 0)
+ goto errout;
+ bus_dmamap_sync(atsc->rx_tag, atsc->ping_pong[i].map,
+ BUS_DMASYNC_PREREAD);
+ }
+ atsc->ping = &atsc->ping_pong[0];
+ atsc->pong = &atsc->ping_pong[1];
+ }
+
+ /* Turn on rx and tx */
+ cr = USART_CR_RSTSTA | USART_CR_RSTRX | USART_CR_RSTTX;
+ WR4(&sc->sc_bas, USART_CR, cr);
+ WR4(&sc->sc_bas, USART_CR, USART_CR_RXEN | USART_CR_TXEN);
+
+ /*
+ * Setup the PDC to receive data. We use the ping-pong buffers
+ * so that we can more easily bounce between the two and so that
+ * we get an interrupt 1/2 way through the software 'fifo' we have
+ * to avoid overruns.
+ */
+ if (atsc->flags & HAS_TIMEOUT) {
+ WR4(&sc->sc_bas, PDC_RPR, atsc->ping->pa);
+ WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz);
+ WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa);
+ WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz);
+ WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN);
+
+ /*
+ * Set the receive timeout to be 1.5 character times
+ * assuming 8N1.
+ */
+ WR4(&sc->sc_bas, USART_RTOR, 15);
+ WR4(&sc->sc_bas, USART_CR, USART_CR_STTTO);
+ WR4(&sc->sc_bas, USART_IER, USART_CSR_TIMEOUT |
+ USART_CSR_RXBUFF | USART_CSR_ENDRX);
+ } else {
+ WR4(&sc->sc_bas, USART_IER, USART_CSR_RXRDY);
+ }
+ WR4(&sc->sc_bas, USART_IER, USART_CSR_RXBRK | USART_DCE_CHANGE_BITS);
+
+ /* Prime sc->hwsig with the initial hw line states. */
+ at91_usart_bus_getsig(sc);
+
+errout:
+ return (err);
+}
+
+static int
+at91_usart_bus_transmit(struct uart_softc *sc)
+{
+ bus_addr_t addr;
+ struct at91_usart_softc *atsc;
+ int err;
+
+ err = 0;
+ atsc = (struct at91_usart_softc *)sc;
+ uart_lock(sc->sc_hwmtx);
+ if (bus_dmamap_load(atsc->tx_tag, atsc->tx_map, sc->sc_txbuf,
+ sc->sc_txdatasz, at91_getaddr, &addr, 0) != 0) {
+ err = EAGAIN;
+ goto errout;
+ }
+ bus_dmamap_sync(atsc->tx_tag, atsc->tx_map, BUS_DMASYNC_PREWRITE);
+ sc->sc_txbusy = 1;
+ /*
+ * Setup the PDC to transfer the data and interrupt us when it
+ * is done. We've already requested the interrupt.
+ */
+ WR4(&sc->sc_bas, PDC_TPR, addr);
+ WR4(&sc->sc_bas, PDC_TCR, sc->sc_txdatasz);
+ WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_TXTEN);
+ WR4(&sc->sc_bas, USART_IER, USART_CSR_ENDTX);
+errout:
+ uart_unlock(sc->sc_hwmtx);
+ return (err);
+}
+
+static int
+at91_usart_bus_setsig(struct uart_softc *sc, int sig)
+{
+ uint32_t new, old, cr;
+ struct at91_usart_softc *atsc;
+
+ atsc = (struct at91_usart_softc *)sc;
+
+ do {
+ old = sc->sc_hwsig;
+ new = old;
+ if (sig & SER_DDTR)
+ SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR);
+ if (sig & SER_DRTS)
+ SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS);
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+
+ cr = 0;
+ if (new & SER_DTR)
+ cr |= USART_CR_DTREN;
+ else
+ cr |= USART_CR_DTRDIS;
+ if (new & SER_RTS)
+ cr |= USART_CR_RTSEN;
+ else
+ cr |= USART_CR_RTSDIS;
+
+ uart_lock(sc->sc_hwmtx);
+ WR4(&sc->sc_bas, USART_CR, cr);
+ if (atsc->flags & USE_RTS0_WORKAROUND) {
+ /* Signal is active-low. */
+ if (new & SER_RTS)
+ at91_pio_gpio_clear(AT91RM92_PIOA_BASE, AT91C_PIO_PA21);
+ else
+ at91_pio_gpio_set(AT91RM92_PIOA_BASE,AT91C_PIO_PA21);
+ }
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static int
+at91_usart_bus_receive(struct uart_softc *sc)
+{
+
+ return (0);
+}
+
+static int
+at91_usart_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+
+ return (at91_usart_param(&sc->sc_bas, baudrate, databits, stopbits,
+ parity));
+}
+
+static __inline void
+at91_rx_put(struct uart_softc *sc, int key)
+{
+
+#if defined(KDB)
+ if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE)
+ kdb_alt_break(key, &sc->sc_altbrk);
+#endif
+ uart_rx_put(sc, key);
+}
+
+static int
+at91_usart_bus_ipend(struct uart_softc *sc)
+{
+ struct at91_usart_softc *atsc;
+ struct at91_usart_rx *p;
+ int i, ipend, len;
+ uint32_t csr;
+
+ ipend = 0;
+ atsc = (struct at91_usart_softc *)sc;
+ uart_lock(sc->sc_hwmtx);
+ csr = RD4(&sc->sc_bas, USART_CSR);
+
+ if (csr & USART_CSR_OVRE) {
+ WR4(&sc->sc_bas, USART_CR, USART_CR_RSTSTA);
+ ipend |= SER_INT_OVERRUN;
+ }
+
+ if (csr & USART_DCE_CHANGE_BITS)
+ ipend |= SER_INT_SIGCHG;
+
+ if (csr & USART_CSR_ENDTX) {
+ bus_dmamap_sync(atsc->tx_tag, atsc->tx_map,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(atsc->tx_tag, atsc->tx_map);
+ }
+ if (csr & (USART_CSR_TXRDY | USART_CSR_ENDTX)) {
+ if (sc->sc_txbusy)
+ ipend |= SER_INT_TXIDLE;
+ WR4(&sc->sc_bas, USART_IDR, csr & (USART_CSR_TXRDY |
+ USART_CSR_ENDTX));
+ }
+
+ /*
+ * Due to the contraints of the DMA engine present in the
+ * atmel chip, I can't just say I have a rx interrupt pending
+ * and do all the work elsewhere. I need to look at the CSR
+ * bits right now and do things based on them to avoid races.
+ */
+ if (atsc->flags & HAS_TIMEOUT) {
+ if (csr & USART_CSR_RXBUFF) {
+ /*
+ * We have a buffer overflow. Consume data from ping
+ * and give it back to the hardware before worrying
+ * about pong, to minimze data loss. Insert an overrun
+ * marker after the contents of the pong buffer.
+ */
+ WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTDIS);
+ bus_dmamap_sync(atsc->rx_tag, atsc->ping->map,
+ BUS_DMASYNC_POSTREAD);
+ for (i = 0; i < sc->sc_rxfifosz; i++)
+ at91_rx_put(sc, atsc->ping->buffer[i]);
+ bus_dmamap_sync(atsc->rx_tag, atsc->ping->map,
+ BUS_DMASYNC_PREREAD);
+ WR4(&sc->sc_bas, PDC_RPR, atsc->ping->pa);
+ WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz);
+ WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN);
+ bus_dmamap_sync(atsc->rx_tag, atsc->pong->map,
+ BUS_DMASYNC_POSTREAD);
+ for (i = 0; i < sc->sc_rxfifosz; i++)
+ at91_rx_put(sc, atsc->pong->buffer[i]);
+ uart_rx_put(sc, UART_STAT_OVERRUN);
+ bus_dmamap_sync(atsc->rx_tag, atsc->pong->map,
+ BUS_DMASYNC_PREREAD);
+ WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa);
+ WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz);
+ ipend |= SER_INT_RXREADY;
+ } else if (csr & USART_CSR_ENDRX) {
+ /*
+ * Consume data from ping of ping pong buffer, but leave
+ * current pong in place, as it has become the new ping.
+ * We need to copy data and setup the old ping as the
+ * new pong when we're done.
+ */
+ bus_dmamap_sync(atsc->rx_tag, atsc->ping->map,
+ BUS_DMASYNC_POSTREAD);
+ for (i = 0; i < sc->sc_rxfifosz; i++)
+ at91_rx_put(sc, atsc->ping->buffer[i]);
+ p = atsc->ping;
+ atsc->ping = atsc->pong;
+ atsc->pong = p;
+ bus_dmamap_sync(atsc->rx_tag, atsc->pong->map,
+ BUS_DMASYNC_PREREAD);
+ WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa);
+ WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz);
+ ipend |= SER_INT_RXREADY;
+ } else if (csr & USART_CSR_TIMEOUT) {
+ /*
+ * On a timeout, one of the following applies:
+ * 1. Two empty buffers. The last received byte exactly
+ * filled a buffer, causing an ENDTX that got
+ * processed earlier; no new bytes have arrived.
+ * 2. Ping buffer contains some data and pong is empty.
+ * This should be the most common timeout condition.
+ * 3. Ping buffer is full and pong is now being filled.
+ * This is exceedingly rare; it can happen only if
+ * the ping buffer is almost full when a timeout is
+ * signaled, and then dataflow resumes and the ping
+ * buffer filled up between the time we read the
+ * status register above and the point where the
+ * RXTDIS takes effect here. Yes, it can happen.
+ * Because dataflow can resume at any time following a
+ * timeout (it may have already resumed before we get
+ * here), it's important to minimize the time the PDC is
+ * disabled -- just long enough to take the ping buffer
+ * out of service (so we can consume it) and install the
+ * pong buffer as the active one. Note that in case 3
+ * the hardware has already done the ping-pong swap.
+ */
+ WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTDIS);
+ if (RD4(&sc->sc_bas, PDC_RNCR) == 0) {
+ len = sc->sc_rxfifosz;
+ } else {
+ len = sc->sc_rxfifosz - RD4(&sc->sc_bas, PDC_RCR);
+ WR4(&sc->sc_bas, PDC_RPR, atsc->pong->pa);
+ WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz);
+ WR4(&sc->sc_bas, PDC_RNCR, 0);
+ }
+ WR4(&sc->sc_bas, USART_CR, USART_CR_STTTO);
+ WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN);
+ bus_dmamap_sync(atsc->rx_tag, atsc->ping->map,
+ BUS_DMASYNC_POSTREAD);
+ for (i = 0; i < len; i++)
+ at91_rx_put(sc, atsc->ping->buffer[i]);
+ bus_dmamap_sync(atsc->rx_tag, atsc->ping->map,
+ BUS_DMASYNC_PREREAD);
+ p = atsc->ping;
+ atsc->ping = atsc->pong;
+ atsc->pong = p;
+ WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa);
+ WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz);
+ ipend |= SER_INT_RXREADY;
+ }
+ } else if (csr & USART_CSR_RXRDY) {
+ /*
+ * We have another charater in a device that doesn't support
+ * timeouts, so we do it one character at a time.
+ */
+ at91_rx_put(sc, RD4(&sc->sc_bas, USART_RHR) & 0xff);
+ ipend |= SER_INT_RXREADY;
+ }
+
+ if (csr & USART_CSR_RXBRK) {
+ ipend |= SER_INT_BREAK;
+ WR4(&sc->sc_bas, USART_CR, USART_CR_RSTSTA);
+ }
+ uart_unlock(sc->sc_hwmtx);
+ return (ipend);
+}
+
+static int
+at91_usart_bus_flush(struct uart_softc *sc, int what)
+{
+
+ return (0);
+}
+
+static int
+at91_usart_bus_getsig(struct uart_softc *sc)
+{
+ uint32_t csr, new, old, sig;
+
+ /*
+ * Note that the atmel channel status register DCE status bits reflect
+ * the electrical state of the lines, not the logical state. Since they
+ * are logically active-low signals, we invert the tests here.
+ */
+ do {
+ old = sc->sc_hwsig;
+ sig = old;
+ csr = RD4(&sc->sc_bas, USART_CSR);
+ SIGCHG(!(csr & USART_CSR_DSR), sig, SER_DSR, SER_DDSR);
+ SIGCHG(!(csr & USART_CSR_CTS), sig, SER_CTS, SER_DCTS);
+ SIGCHG(!(csr & USART_CSR_DCD), sig, SER_DCD, SER_DDCD);
+ SIGCHG(!(csr & USART_CSR_RI), sig, SER_RI, SER_DRI);
+ new = sig & ~SER_MASK_DELTA;
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+
+ return (sig);
+}
+
+static int
+at91_usart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+
+ switch (request) {
+ case UART_IOCTL_BREAK:
+ case UART_IOCTL_IFLOW:
+ case UART_IOCTL_OFLOW:
+ break;
+ case UART_IOCTL_BAUD:
+ /* only if we know our master clock rate */
+ if (DEFAULT_RCLK != 0)
+ WR4(&sc->sc_bas, USART_BRGR,
+ BAUD2DIVISOR(*(int *)data));
+ return (0);
+ }
+ return (EINVAL);
+}
+
+
+static void
+at91_usart_bus_grab(struct uart_softc *sc)
+{
+
+ uart_lock(sc->sc_hwmtx);
+ WR4(&sc->sc_bas, USART_IDR, USART_CSR_RXRDY);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+at91_usart_bus_ungrab(struct uart_softc *sc)
+{
+
+ uart_lock(sc->sc_hwmtx);
+ WR4(&sc->sc_bas, USART_IER, USART_CSR_RXRDY);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+struct uart_class at91_usart_class = {
+ "at91_usart",
+ at91_usart_methods,
+ sizeof(struct at91_usart_softc),
+ .uc_ops = &at91_usart_ops,
+ .uc_range = 8
+};
+
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+ {"atmel,at91rm9200-usart",(uintptr_t)&at91_usart_class},
+ {"atmel,at91sam9260-usart",(uintptr_t)&at91_usart_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+#endif
Property changes on: trunk/sys/arm/at91/uart_dev_at91usart.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_bsc.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_bsc.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_bsc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,515 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 Tsubai Masanari.
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2013 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_bsc.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_gpio.h>
+#include <arm/broadcom/bcm2835/bcm2835_bscreg.h>
+#include <arm/broadcom/bcm2835/bcm2835_bscvar.h>
+
+#include "iicbus_if.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-bsc", 1},
+ {"brcm,bcm2708-i2c", 1},
+ {"brcm,bcm2835-i2c", 1},
+ {NULL, 0}
+};
+
+static void bcm_bsc_intr(void *);
+static int bcm_bsc_detach(device_t);
+
+static void
+bcm_bsc_modifyreg(struct bcm_bsc_softc *sc, uint32_t off, uint32_t mask,
+ uint32_t value)
+{
+ uint32_t reg;
+
+ mtx_assert(&sc->sc_mtx, MA_OWNED);
+ reg = BCM_BSC_READ(sc, off);
+ reg &= ~mask;
+ reg |= value;
+ BCM_BSC_WRITE(sc, off, reg);
+}
+
+static int
+bcm_bsc_clock_proc(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm_bsc_softc *sc;
+ uint32_t clk;
+
+ sc = (struct bcm_bsc_softc *)arg1;
+ BCM_BSC_LOCK(sc);
+ clk = BCM_BSC_READ(sc, BCM_BSC_CLOCK);
+ BCM_BSC_UNLOCK(sc);
+ clk &= 0xffff;
+ if (clk == 0)
+ clk = 32768;
+ clk = BCM_BSC_CORE_CLK / clk;
+
+ return (sysctl_handle_int(oidp, &clk, 0, req));
+}
+
+static int
+bcm_bsc_clkt_proc(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm_bsc_softc *sc;
+ uint32_t clkt;
+ int error;
+
+ sc = (struct bcm_bsc_softc *)arg1;
+
+ BCM_BSC_LOCK(sc);
+ clkt = BCM_BSC_READ(sc, BCM_BSC_CLKT);
+ BCM_BSC_UNLOCK(sc);
+ clkt &= 0xffff;
+ error = sysctl_handle_int(oidp, &clkt, sizeof(clkt), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ BCM_BSC_LOCK(sc);
+ BCM_BSC_WRITE(sc, BCM_BSC_CLKT, clkt & 0xffff);
+ BCM_BSC_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_bsc_fall_proc(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm_bsc_softc *sc;
+ uint32_t clk, reg;
+ int error;
+
+ sc = (struct bcm_bsc_softc *)arg1;
+
+ BCM_BSC_LOCK(sc);
+ reg = BCM_BSC_READ(sc, BCM_BSC_DELAY);
+ BCM_BSC_UNLOCK(sc);
+ reg >>= 16;
+ error = sysctl_handle_int(oidp, ®, sizeof(reg), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ BCM_BSC_LOCK(sc);
+ clk = BCM_BSC_READ(sc, BCM_BSC_CLOCK);
+ clk = BCM_BSC_CORE_CLK / clk;
+ if (reg > clk / 2)
+ reg = clk / 2 - 1;
+ bcm_bsc_modifyreg(sc, BCM_BSC_DELAY, 0xffff0000, reg << 16);
+ BCM_BSC_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_bsc_rise_proc(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm_bsc_softc *sc;
+ uint32_t clk, reg;
+ int error;
+
+ sc = (struct bcm_bsc_softc *)arg1;
+
+ BCM_BSC_LOCK(sc);
+ reg = BCM_BSC_READ(sc, BCM_BSC_DELAY);
+ BCM_BSC_UNLOCK(sc);
+ reg &= 0xffff;
+ error = sysctl_handle_int(oidp, ®, sizeof(reg), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ BCM_BSC_LOCK(sc);
+ clk = BCM_BSC_READ(sc, BCM_BSC_CLOCK);
+ clk = BCM_BSC_CORE_CLK / clk;
+ if (reg > clk / 2)
+ reg = clk / 2 - 1;
+ bcm_bsc_modifyreg(sc, BCM_BSC_DELAY, 0xffff, reg);
+ BCM_BSC_UNLOCK(sc);
+
+ return (0);
+}
+
+static void
+bcm_bsc_sysctl_init(struct bcm_bsc_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree_node;
+ struct sysctl_oid_list *tree;
+
+ /*
+ * Add system sysctl tree/handlers.
+ */
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ tree_node = device_get_sysctl_tree(sc->sc_dev);
+ tree = SYSCTL_CHILDREN(tree_node);
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "frequency",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_bsc_clock_proc, "IU", "I2C BUS clock frequency");
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "clock_stretch",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_bsc_clkt_proc, "IU", "I2C BUS clock stretch timeout");
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "fall_edge_delay",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_bsc_fall_proc, "IU", "I2C BUS falling edge delay");
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "rise_edge_delay",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_bsc_rise_proc, "IU", "I2C BUS rising edge delay");
+}
+
+static void
+bcm_bsc_reset(struct bcm_bsc_softc *sc)
+{
+
+ /* Enable the BSC Controller, disable interrupts. */
+ BCM_BSC_WRITE(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_I2CEN);
+ /* Clear pending interrupts. */
+ BCM_BSC_WRITE(sc, BCM_BSC_STATUS, BCM_BSC_STATUS_CLKT |
+ BCM_BSC_STATUS_ERR | BCM_BSC_STATUS_DONE);
+ /* Clear the FIFO. */
+ bcm_bsc_modifyreg(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_CLEAR0,
+ BCM_BSC_CTRL_CLEAR0);
+}
+
+static int
+bcm_bsc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2708/2835 BSC controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_bsc_attach(device_t dev)
+{
+ struct bcm_bsc_softc *sc;
+ unsigned long start;
+ device_t gpio;
+ int i, rid;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
+
+ /* Check the unit we are attaching by its base address. */
+ start = rman_get_start(sc->sc_mem_res);
+ for (i = 0; i < nitems(bcm_bsc_pins); i++) {
+ if (bcm_bsc_pins[i].start == (start & BCM_BSC_BASE_MASK))
+ break;
+ }
+ if (i == nitems(bcm_bsc_pins)) {
+ device_printf(dev, "only bsc0 and bsc1 are supported\n");
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ return (ENXIO);
+ }
+
+ /*
+ * Configure the GPIO pins to ALT0 function to enable BSC control
+ * over the pins.
+ */
+ gpio = devclass_get_device(devclass_find("gpio"), 0);
+ if (!gpio) {
+ device_printf(dev, "cannot find gpio0\n");
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ return (ENXIO);
+ }
+ bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].sda, BCM_GPIO_ALT0);
+ bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].scl, BCM_GPIO_ALT0);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ /* Hook up our interrupt handler. */
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, bcm_bsc_intr, sc, &sc->sc_intrhand)) {
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot setup the interrupt handler\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->sc_mtx, "bcm_bsc", NULL, MTX_DEF);
+
+ bcm_bsc_sysctl_init(sc);
+
+ /* Enable the BSC controller. Flush the FIFO. */
+ BCM_BSC_LOCK(sc);
+ bcm_bsc_reset(sc);
+ BCM_BSC_UNLOCK(sc);
+
+ sc->sc_iicbus = device_add_child(dev, "iicbus", -1);
+ if (sc->sc_iicbus == NULL) {
+ bcm_bsc_detach(dev);
+ return (ENXIO);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+bcm_bsc_detach(device_t dev)
+{
+ struct bcm_bsc_softc *sc;
+
+ bus_generic_detach(dev);
+
+ sc = device_get_softc(dev);
+ mtx_destroy(&sc->sc_mtx);
+ if (sc->sc_intrhand)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+
+ return (0);
+}
+
+static void
+bcm_bsc_intr(void *arg)
+{
+ struct bcm_bsc_softc *sc;
+ uint32_t status;
+
+ sc = (struct bcm_bsc_softc *)arg;
+
+ BCM_BSC_LOCK(sc);
+
+ /* The I2C interrupt is shared among all the BSC controllers. */
+ if ((sc->sc_flags & BCM_I2C_BUSY) == 0) {
+ BCM_BSC_UNLOCK(sc);
+ return;
+ }
+
+ status = BCM_BSC_READ(sc, BCM_BSC_STATUS);
+
+ /* Check for errors. */
+ if (status & (BCM_BSC_STATUS_CLKT | BCM_BSC_STATUS_ERR)) {
+ /* Disable interrupts. */
+ bcm_bsc_reset(sc);
+ sc->sc_flags |= BCM_I2C_ERROR;
+ wakeup(sc->sc_dev);
+ BCM_BSC_UNLOCK(sc);
+ return;
+ }
+
+ if (sc->sc_flags & BCM_I2C_READ) {
+ while (sc->sc_resid > 0 && (status & BCM_BSC_STATUS_RXD)) {
+ *sc->sc_data++ = BCM_BSC_READ(sc, BCM_BSC_DATA);
+ sc->sc_resid--;
+ status = BCM_BSC_READ(sc, BCM_BSC_STATUS);
+ }
+ } else {
+ while (sc->sc_resid > 0 && (status & BCM_BSC_STATUS_TXD)) {
+ BCM_BSC_WRITE(sc, BCM_BSC_DATA, *sc->sc_data++);
+ sc->sc_resid--;
+ status = BCM_BSC_READ(sc, BCM_BSC_STATUS);
+ }
+ }
+
+ if (status & BCM_BSC_STATUS_DONE) {
+ /* Disable interrupts. */
+ bcm_bsc_reset(sc);
+ wakeup(sc->sc_dev);
+ }
+
+ BCM_BSC_UNLOCK(sc);
+}
+
+static int
+bcm_bsc_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+ struct bcm_bsc_softc *sc;
+ uint32_t intr, read, status;
+ int i, err;
+
+ sc = device_get_softc(dev);
+ BCM_BSC_LOCK(sc);
+
+ /* If the controller is busy wait until it is available. */
+ while (sc->sc_flags & BCM_I2C_BUSY)
+ mtx_sleep(dev, &sc->sc_mtx, 0, "bscbusw", 0);
+
+ /* Now we have control over the BSC controller. */
+ sc->sc_flags = BCM_I2C_BUSY;
+
+ /* Clear the FIFO and the pending interrupts. */
+ bcm_bsc_reset(sc);
+
+ err = 0;
+ for (i = 0; i < nmsgs; i++) {
+
+ /* Write the slave address. */
+ BCM_BSC_WRITE(sc, BCM_BSC_SLAVE, msgs[i].slave >> 1);
+
+ /* Write the data length. */
+ BCM_BSC_WRITE(sc, BCM_BSC_DLEN, msgs[i].len);
+
+ sc->sc_data = msgs[i].buf;
+ sc->sc_resid = msgs[i].len;
+ if ((msgs[i].flags & IIC_M_RD) == 0) {
+ /* Fill up the TX FIFO. */
+ status = BCM_BSC_READ(sc, BCM_BSC_STATUS);
+ while (sc->sc_resid > 0 &&
+ (status & BCM_BSC_STATUS_TXD)) {
+ BCM_BSC_WRITE(sc, BCM_BSC_DATA, *sc->sc_data);
+ sc->sc_data++;
+ sc->sc_resid--;
+ status = BCM_BSC_READ(sc, BCM_BSC_STATUS);
+ }
+ read = 0;
+ intr = BCM_BSC_CTRL_INTT;
+ sc->sc_flags &= ~BCM_I2C_READ;
+ } else {
+ sc->sc_flags |= BCM_I2C_READ;
+ read = BCM_BSC_CTRL_READ;
+ intr = BCM_BSC_CTRL_INTR;
+ }
+ intr |= BCM_BSC_CTRL_INTD;
+
+ /* Start the transfer. */
+ BCM_BSC_WRITE(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_I2CEN |
+ BCM_BSC_CTRL_ST | read | intr);
+
+ /* Wait for the transaction to complete. */
+ err = mtx_sleep(dev, &sc->sc_mtx, 0, "bsciow", hz);
+
+ /* Check for errors. */
+ if (err == 0 && (sc->sc_flags & BCM_I2C_ERROR))
+ err = EIO;
+ if (err != 0)
+ break;
+ }
+
+ /* Clean the controller flags. */
+ sc->sc_flags = 0;
+
+ /* Wake up the threads waiting for bus. */
+ wakeup(dev);
+
+ BCM_BSC_UNLOCK(sc);
+
+ return (err);
+}
+
+static int
+bcm_bsc_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+ struct bcm_bsc_softc *sc;
+ uint32_t busfreq;
+
+ sc = device_get_softc(dev);
+ BCM_BSC_LOCK(sc);
+ bcm_bsc_reset(sc);
+ if (sc->sc_iicbus == NULL)
+ busfreq = 100000;
+ else
+ busfreq = IICBUS_GET_FREQUENCY(sc->sc_iicbus, speed);
+ BCM_BSC_WRITE(sc, BCM_BSC_CLOCK, BCM_BSC_CORE_CLK / busfreq);
+ BCM_BSC_UNLOCK(sc);
+
+ return (IIC_ENOADDR);
+}
+
+static phandle_t
+bcm_bsc_get_node(device_t bus, device_t dev)
+{
+
+ /* We only have one child, the I2C bus, which needs our own node. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t bcm_bsc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bcm_bsc_probe),
+ DEVMETHOD(device_attach, bcm_bsc_attach),
+ DEVMETHOD(device_detach, bcm_bsc_detach),
+
+ /* iicbus interface */
+ DEVMETHOD(iicbus_reset, bcm_bsc_iicbus_reset),
+ DEVMETHOD(iicbus_callback, iicbus_null_callback),
+ DEVMETHOD(iicbus_transfer, bcm_bsc_transfer),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, bcm_bsc_get_node),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm_bsc_devclass;
+
+static driver_t bcm_bsc_driver = {
+ "iichb",
+ bcm_bsc_methods,
+ sizeof(struct bcm_bsc_softc),
+};
+
+DRIVER_MODULE(iicbus, bcm2835_bsc, iicbus_driver, iicbus_devclass, 0, 0);
+DRIVER_MODULE(bcm2835_bsc, simplebus, bcm_bsc_driver, bcm_bsc_devclass, 0, 0);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_bsc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_bscreg.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_bscreg.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_bscreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,62 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2013 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_bscreg.h 261078 2014-01-23 12:32:30Z loos $
+ */
+
+#ifndef _BCM2835_BSCREG_H_
+#define _BCM2835_BSCREG_H_
+
+#define BCM_BSC_CORE_CLK 150000000U
+#define BCM_BSC_CTRL 0x00
+#define BCM_BSC_CTRL_I2CEN (1 << 15)
+#define BCM_BSC_CTRL_INTR (1 << 10)
+#define BCM_BSC_CTRL_INTT (1 << 9)
+#define BCM_BSC_CTRL_INTD (1 << 8)
+#define BCM_BSC_CTRL_ST (1 << 7)
+#define BCM_BSC_CTRL_CLEAR1 (1 << 5)
+#define BCM_BSC_CTRL_CLEAR0 (1 << 4)
+#define BCM_BSC_CTRL_READ (1 << 0)
+#define BCM_BSC_STATUS 0x04
+#define BCM_BSC_STATUS_CLKT (1 << 9)
+#define BCM_BSC_STATUS_ERR (1 << 8)
+#define BCM_BSC_STATUS_RXF (1 << 7)
+#define BCM_BSC_STATUS_TXE (1 << 6)
+#define BCM_BSC_STATUS_RXD (1 << 5)
+#define BCM_BSC_STATUS_TXD (1 << 4)
+#define BCM_BSC_STATUS_RXR (1 << 3)
+#define BCM_BSC_STATUS_TXW (1 << 2)
+#define BCM_BSC_STATUS_DONE (1 << 1)
+#define BCM_BSC_STATUS_TA (1 << 0)
+#define BCM_BSC_DLEN 0x08
+#define BCM_BSC_SLAVE 0x0c
+#define BCM_BSC_DATA 0x10
+#define BCM_BSC_CLOCK 0x14
+#define BCM_BSC_DELAY 0x18
+#define BCM_BSC_CLKT 0x1c
+
+#endif /* _BCM2835_BSCREG_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_bscreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,72 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2013 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h 322724 2017-08-20 16:52:27Z marius $
+ */
+
+#ifndef _BCM2835_BSCVAR_H
+#define _BCM2835_BSCVAR_H
+
+struct {
+ uint32_t sda;
+ uint32_t scl;
+ unsigned long start;
+} bcm_bsc_pins[] = {
+ { 0, 1, 0x205000 }, /* BSC0 GPIO pins and base address. */
+ { 2, 3, 0x804000 } /* BSC1 GPIO pins and base address. */
+};
+#define BCM_BSC_BASE_MASK 0x00ffffff
+
+struct bcm_bsc_softc {
+ device_t sc_dev;
+ device_t sc_iicbus;
+ struct mtx sc_mtx;
+ struct resource * sc_mem_res;
+ struct resource * sc_irq_res;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ uint16_t sc_resid;
+ uint8_t *sc_data;
+ uint8_t sc_flags;
+ void * sc_intrhand;
+};
+
+#define BCM_I2C_BUSY 0x01
+#define BCM_I2C_READ 0x02
+#define BCM_I2C_ERROR 0x04
+
+#define BCM_BSC_WRITE(_sc, _off, _val) \
+ bus_space_write_4((_sc)->sc_bst, (_sc)->sc_bsh, _off, _val)
+#define BCM_BSC_READ(_sc, _off) \
+ bus_space_read_4((_sc)->sc_bst, (_sc)->sc_bsh, _off)
+
+#define BCM_BSC_LOCK(_sc) \
+ mtx_lock(&(_sc)->sc_mtx)
+#define BCM_BSC_UNLOCK(_sc) \
+ mtx_unlock(&(_sc)->sc_mtx)
+
+#endif /* _BCM2835_BSCVAR_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_common.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_common.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,84 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_global.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_common.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kdb.h>
+#include <sys/reboot.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (fdt_is_compatible(node, "broadcom,bcm2835-armctrl-ic") ||
+ fdt_is_compatible(node, "brcm,bcm2836-armctrl-ic")) {
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+ }
+#ifdef SOC_BCM2836
+ if (fdt_is_compatible(node, "brcm,bcm2836-l1-intc")) {
+ *interrupt = fdt32_to_cpu(intr[0]) + 72;
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+ }
+#endif
+ return (ENXIO);
+}
+
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_intc_decode_ic,
+ NULL
+};
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1614 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2013-2014 Daisuke Aoyama <aoyama at peach.ne.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/sema.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
+#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
+
+#include "cpufreq_if.h"
+#include "mbox_if.h"
+
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) do { \
+ printf("%s:%u: ", __func__, __LINE__); \
+ printf(fmt, ##__VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+#define HZ2MHZ(freq) ((freq) / (1000 * 1000))
+#define MHZ2HZ(freq) ((freq) * (1000 * 1000))
+#define OFFSET2MVOLT(val) (1200 + ((val) * 25))
+#define MVOLT2OFFSET(val) (((val) - 1200) / 25)
+
+#define DEFAULT_ARM_FREQUENCY 700
+#define DEFAULT_CORE_FREQUENCY 250
+#define DEFAULT_SDRAM_FREQUENCY 400
+#define DEFAULT_LOWEST_FREQ 300
+#define TRANSITION_LATENCY 1000
+#define MIN_OVER_VOLTAGE -16
+#define MAX_OVER_VOLTAGE 6
+#define MSG_ERROR -999999999
+#define MHZSTEP 100
+#define HZSTEP (MHZ2HZ(MHZSTEP))
+#define TZ_ZEROC 2732
+
+#define VC_LOCK(sc) do { \
+ sema_wait(&vc_sema); \
+ } while (0)
+#define VC_UNLOCK(sc) do { \
+ sema_post(&vc_sema); \
+ } while (0)
+
+/* ARM->VC mailbox property semaphore */
+static struct sema vc_sema;
+
+static struct sysctl_ctx_list bcm2835_sysctl_ctx;
+
+struct bcm2835_cpufreq_softc {
+ device_t dev;
+ int arm_max_freq;
+ int arm_min_freq;
+ int core_max_freq;
+ int core_min_freq;
+ int sdram_max_freq;
+ int sdram_min_freq;
+ int max_voltage_core;
+ int min_voltage_core;
+
+ /* the values written in mbox */
+ int voltage_core;
+ int voltage_sdram;
+ int voltage_sdram_c;
+ int voltage_sdram_i;
+ int voltage_sdram_p;
+ int turbo_mode;
+
+ /* initial hook for waiting mbox intr */
+ struct intr_config_hook init_hook;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ { "broadcom,bcm2835-vc", 1 },
+ { "broadcom,bcm2708-vc", 1 },
+ { "brcm,bcm2709", 1 },
+ { NULL, 0 }
+};
+
+static int cpufreq_verbose = 0;
+TUNABLE_INT("hw.bcm2835.cpufreq.verbose", &cpufreq_verbose);
+static int cpufreq_lowest_freq = DEFAULT_LOWEST_FREQ;
+TUNABLE_INT("hw.bcm2835.cpufreq.lowest_freq", &cpufreq_lowest_freq);
+
+#ifdef PROP_DEBUG
+static void
+bcm2835_dump(const void *data, int len)
+{
+ const uint8_t *p = (const uint8_t*)data;
+ int i;
+
+ printf("dump @ %p:\n", data);
+ for (i = 0; i < len; i++) {
+ printf("%2.2x ", p[i]);
+ if ((i % 4) == 3)
+ printf(" ");
+ if ((i % 16) == 15)
+ printf("\n");
+ }
+ printf("\n");
+}
+#endif
+
+static int
+bcm2835_cpufreq_get_clock_rate(struct bcm2835_cpufreq_softc *sc,
+ uint32_t clock_id)
+{
+ struct msg_get_clock_rate msg;
+ int rate;
+ int err;
+
+ /*
+ * Get clock rate
+ * Tag: 0x00030002
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: clock id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_CLOCK_RATE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.clock_id = clock_id;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't get clock rate (id=%u)\n",
+ clock_id);
+ return (MSG_ERROR);
+ }
+
+ /* result (Hz) */
+ rate = (int)msg.body.resp.rate_hz;
+ DPRINTF("clock = %d(Hz)\n", rate);
+ return (rate);
+}
+
+static int
+bcm2835_cpufreq_get_max_clock_rate(struct bcm2835_cpufreq_softc *sc,
+ uint32_t clock_id)
+{
+ struct msg_get_max_clock_rate msg;
+ int rate;
+ int err;
+
+ /*
+ * Get max clock rate
+ * Tag: 0x00030004
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: clock id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MAX_CLOCK_RATE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.clock_id = clock_id;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't get max clock rate (id=%u)\n",
+ clock_id);
+ return (MSG_ERROR);
+ }
+
+ /* result (Hz) */
+ rate = (int)msg.body.resp.rate_hz;
+ DPRINTF("clock = %d(Hz)\n", rate);
+ return (rate);
+}
+
+static int
+bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc,
+ uint32_t clock_id)
+{
+ struct msg_get_min_clock_rate msg;
+ int rate;
+ int err;
+
+ /*
+ * Get min clock rate
+ * Tag: 0x00030007
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: clock id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_CLOCK_RATE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.clock_id = clock_id;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't get min clock rate (id=%u)\n",
+ clock_id);
+ return (MSG_ERROR);
+ }
+
+ /* result (Hz) */
+ rate = (int)msg.body.resp.rate_hz;
+ DPRINTF("clock = %d(Hz)\n", rate);
+ return (rate);
+}
+
+static int
+bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc,
+ uint32_t clock_id, uint32_t rate_hz)
+{
+ struct msg_set_clock_rate msg;
+ int rate;
+ int err;
+
+ /*
+ * Set clock rate
+ * Tag: 0x00038002
+ * Request:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.clock_id = clock_id;
+ msg.body.req.rate_hz = rate_hz;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't set clock rate (id=%u)\n",
+ clock_id);
+ return (MSG_ERROR);
+ }
+
+ /* workaround for core clock */
+ if (clock_id == BCM2835_MBOX_CLOCK_ID_CORE) {
+ /* for safety (may change voltage without changing clock) */
+ DELAY(TRANSITION_LATENCY);
+
+ /*
+ * XXX: the core clock is unable to change at once,
+ * to change certainly, write it twice now.
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.clock_id = clock_id;
+ msg.body.req.rate_hz = rate_hz;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev,
+ "can't set clock rate (id=%u)\n", clock_id);
+ return (MSG_ERROR);
+ }
+ }
+
+ /* result (Hz) */
+ rate = (int)msg.body.resp.rate_hz;
+ DPRINTF("clock = %d(Hz)\n", rate);
+ return (rate);
+}
+
+static int
+bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc)
+{
+ struct msg_get_turbo msg;
+ int level;
+ int err;
+
+ /*
+ * Get turbo
+ * Tag: 0x00030009
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: id
+ * u32: level
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TURBO;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.id = 0;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't get turbo\n");
+ return (MSG_ERROR);
+ }
+
+ /* result 0=non-turbo, 1=turbo */
+ level = (int)msg.body.resp.level;
+ DPRINTF("level = %d\n", level);
+ return (level);
+}
+
+static int
+bcm2835_cpufreq_set_turbo(struct bcm2835_cpufreq_softc *sc, uint32_t level)
+{
+ struct msg_set_turbo msg;
+ int value;
+ int err;
+
+ /*
+ * Set turbo
+ * Tag: 0x00038009
+ * Request:
+ * Length: 8
+ * Value:
+ * u32: id
+ * u32: level
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: id
+ * u32: level
+ */
+
+ /* replace unknown value to OFF */
+ if (level != BCM2835_MBOX_TURBO_ON && level != BCM2835_MBOX_TURBO_OFF)
+ level = BCM2835_MBOX_TURBO_OFF;
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_TURBO;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.id = 0;
+ msg.body.req.level = level;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't set turbo\n");
+ return (MSG_ERROR);
+ }
+
+ /* result 0=non-turbo, 1=turbo */
+ value = (int)msg.body.resp.level;
+ DPRINTF("level = %d\n", value);
+ return (value);
+}
+
+static int
+bcm2835_cpufreq_get_voltage(struct bcm2835_cpufreq_softc *sc,
+ uint32_t voltage_id)
+{
+ struct msg_get_voltage msg;
+ int value;
+ int err;
+
+ /*
+ * Get voltage
+ * Tag: 0x00030003
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: voltage id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_VOLTAGE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.voltage_id = voltage_id;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't get voltage\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (offset from 1.2V) */
+ value = (int)msg.body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+
+static int
+bcm2835_cpufreq_get_max_voltage(struct bcm2835_cpufreq_softc *sc,
+ uint32_t voltage_id)
+{
+ struct msg_get_max_voltage msg;
+ int value;
+ int err;
+
+ /*
+ * Get voltage
+ * Tag: 0x00030005
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: voltage id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MAX_VOLTAGE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.voltage_id = voltage_id;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't get max voltage\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (offset from 1.2V) */
+ value = (int)msg.body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+static int
+bcm2835_cpufreq_get_min_voltage(struct bcm2835_cpufreq_softc *sc,
+ uint32_t voltage_id)
+{
+ struct msg_get_min_voltage msg;
+ int value;
+ int err;
+
+ /*
+ * Get voltage
+ * Tag: 0x00030008
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: voltage id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_VOLTAGE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.voltage_id = voltage_id;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't get min voltage\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (offset from 1.2V) */
+ value = (int)msg.body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+
+static int
+bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc,
+ uint32_t voltage_id, int32_t value)
+{
+ struct msg_set_voltage msg;
+ int err;
+
+ /*
+ * Set voltage
+ * Tag: 0x00038003
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ */
+
+ /*
+ * over_voltage:
+ * 0 (1.2 V). Values above 6 are only allowed when force_turbo or
+ * current_limit_override are specified (which set the warranty bit).
+ */
+ if (value > MAX_OVER_VOLTAGE || value < MIN_OVER_VOLTAGE) {
+ /* currently not supported */
+ device_printf(sc->dev, "not supported voltage: %d\n", value);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_VOLTAGE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.voltage_id = voltage_id;
+ msg.body.req.value = (uint32_t)value;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't set voltage\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (offset from 1.2V) */
+ value = (int)msg.body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+
+static int
+bcm2835_cpufreq_get_temperature(struct bcm2835_cpufreq_softc *sc)
+{
+ struct msg_get_temperature msg;
+ int value;
+ int err;
+
+ /*
+ * Get temperature
+ * Tag: 0x00030006
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: temperature id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: temperature id
+ * u32: value
+ */
+
+ /* setup single tag buffer */
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TEMPERATURE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.temperature_id = 0;
+ msg.end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err) {
+ device_printf(sc->dev, "can't get temperature\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (temperature of degree C) */
+ value = (int)msg.body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+
+
+
+static int
+sysctl_bcm2835_cpufreq_arm_freq(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
+ val);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set clock arm_freq error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_core_freq(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
+ val);
+ if (err == MSG_ERROR) {
+ VC_UNLOCK(sc);
+ device_printf(sc->dev, "set clock core_freq error\n");
+ return (EIO);
+ }
+ VC_UNLOCK(sc);
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_sdram_freq(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM,
+ val);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set clock sdram_freq error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_turbo(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_turbo(sc);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > 0)
+ sc->turbo_mode = BCM2835_MBOX_TURBO_ON;
+ else
+ sc->turbo_mode = BCM2835_MBOX_TURBO_OFF;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_turbo(sc, sc->turbo_mode);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set turbo error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_core(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_core = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE,
+ sc->voltage_core);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set voltage core error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_sdram_c(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_sdram_c = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C,
+ sc->voltage_sdram_c);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set voltage sdram_c error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_sdram_i(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_sdram_i = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I,
+ sc->voltage_sdram_i);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set voltage sdram_i error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_sdram_p(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_sdram_p = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P,
+ sc->voltage_sdram_p);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set voltage sdram_p error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_sdram(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* multiple write only */
+ if (!req->newptr)
+ return (EINVAL);
+ val = 0;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err)
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_sdram = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C,
+ val);
+ if (err == MSG_ERROR) {
+ VC_UNLOCK(sc);
+ device_printf(sc->dev, "set voltage sdram_c error\n");
+ return (EIO);
+ }
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I,
+ val);
+ if (err == MSG_ERROR) {
+ VC_UNLOCK(sc);
+ device_printf(sc->dev, "set voltage sdram_i error\n");
+ return (EIO);
+ }
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P,
+ val);
+ if (err == MSG_ERROR) {
+ VC_UNLOCK(sc);
+ device_printf(sc->dev, "set voltage sdram_p error\n");
+ return (EIO);
+ }
+ VC_UNLOCK(sc);
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_temperature(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_temperature(sc);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ return (EINVAL);
+}
+
+static int
+sysctl_bcm2835_devcpu_temperature(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_temperature(sc);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ /* 1/1000 celsius (raw) to 1/10 kelvin */
+ val = val / 100 + TZ_ZEROC;
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ return (EINVAL);
+}
+
+
+static void
+bcm2835_cpufreq_init(void *arg)
+{
+ struct bcm2835_cpufreq_softc *sc = arg;
+ struct sysctl_ctx_list *ctx;
+ device_t cpu;
+ int arm_freq, core_freq, sdram_freq;
+ int arm_max_freq, arm_min_freq, core_max_freq, core_min_freq;
+ int sdram_max_freq, sdram_min_freq;
+ int voltage_core, voltage_sdram_c, voltage_sdram_i, voltage_sdram_p;
+ int max_voltage_core, min_voltage_core;
+ int max_voltage_sdram_c, min_voltage_sdram_c;
+ int max_voltage_sdram_i, min_voltage_sdram_i;
+ int max_voltage_sdram_p, min_voltage_sdram_p;
+ int turbo, temperature;
+
+ VC_LOCK(sc);
+
+ /* current clock */
+ arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ core_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE);
+ sdram_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM);
+
+ /* max/min clock */
+ arm_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ arm_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ core_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE);
+ core_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE);
+ sdram_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM);
+ sdram_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM);
+
+ /* turbo mode */
+ turbo = bcm2835_cpufreq_get_turbo(sc);
+ if (turbo > 0)
+ sc->turbo_mode = BCM2835_MBOX_TURBO_ON;
+ else
+ sc->turbo_mode = BCM2835_MBOX_TURBO_OFF;
+
+ /* voltage */
+ voltage_core = bcm2835_cpufreq_get_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_CORE);
+ voltage_sdram_c = bcm2835_cpufreq_get_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
+ voltage_sdram_i = bcm2835_cpufreq_get_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
+ voltage_sdram_p = bcm2835_cpufreq_get_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
+
+ /* current values (offset from 1.2V) */
+ sc->voltage_core = voltage_core;
+ sc->voltage_sdram = voltage_sdram_c;
+ sc->voltage_sdram_c = voltage_sdram_c;
+ sc->voltage_sdram_i = voltage_sdram_i;
+ sc->voltage_sdram_p = voltage_sdram_p;
+
+ /* max/min voltage */
+ max_voltage_core = bcm2835_cpufreq_get_max_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_CORE);
+ min_voltage_core = bcm2835_cpufreq_get_min_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_CORE);
+ max_voltage_sdram_c = bcm2835_cpufreq_get_max_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
+ max_voltage_sdram_i = bcm2835_cpufreq_get_max_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
+ max_voltage_sdram_p = bcm2835_cpufreq_get_max_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
+ min_voltage_sdram_c = bcm2835_cpufreq_get_min_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
+ min_voltage_sdram_i = bcm2835_cpufreq_get_min_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
+ min_voltage_sdram_p = bcm2835_cpufreq_get_min_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
+
+ /* temperature */
+ temperature = bcm2835_cpufreq_get_temperature(sc);
+
+ /* show result */
+ if (cpufreq_verbose || bootverbose) {
+ device_printf(sc->dev, "Boot settings:\n");
+ device_printf(sc->dev,
+ "current ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n",
+ HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq),
+ (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) ? "ON" : "OFF");
+
+ device_printf(sc->dev,
+ "max/min ARM %d/%dMHz, Core %d/%dMHz, SDRAM %d/%dMHz\n",
+ HZ2MHZ(arm_max_freq), HZ2MHZ(arm_min_freq),
+ HZ2MHZ(core_max_freq), HZ2MHZ(core_min_freq),
+ HZ2MHZ(sdram_max_freq), HZ2MHZ(sdram_min_freq));
+
+ device_printf(sc->dev,
+ "current Core %dmV, SDRAM_C %dmV, SDRAM_I %dmV, "
+ "SDRAM_P %dmV\n",
+ OFFSET2MVOLT(voltage_core), OFFSET2MVOLT(voltage_sdram_c),
+ OFFSET2MVOLT(voltage_sdram_i),
+ OFFSET2MVOLT(voltage_sdram_p));
+
+ device_printf(sc->dev,
+ "max/min Core %d/%dmV, SDRAM_C %d/%dmV, SDRAM_I %d/%dmV, "
+ "SDRAM_P %d/%dmV\n",
+ OFFSET2MVOLT(max_voltage_core),
+ OFFSET2MVOLT(min_voltage_core),
+ OFFSET2MVOLT(max_voltage_sdram_c),
+ OFFSET2MVOLT(min_voltage_sdram_c),
+ OFFSET2MVOLT(max_voltage_sdram_i),
+ OFFSET2MVOLT(min_voltage_sdram_i),
+ OFFSET2MVOLT(max_voltage_sdram_p),
+ OFFSET2MVOLT(min_voltage_sdram_p));
+
+ device_printf(sc->dev,
+ "Temperature %d.%dC\n", (temperature / 1000),
+ (temperature % 1000) / 100);
+ } else { /* !cpufreq_verbose && !bootverbose */
+ device_printf(sc->dev,
+ "ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n",
+ HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq),
+ (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) ? "ON" : "OFF");
+ }
+
+ /* keep in softc (MHz/mV) */
+ sc->arm_max_freq = HZ2MHZ(arm_max_freq);
+ sc->arm_min_freq = HZ2MHZ(arm_min_freq);
+ sc->core_max_freq = HZ2MHZ(core_max_freq);
+ sc->core_min_freq = HZ2MHZ(core_min_freq);
+ sc->sdram_max_freq = HZ2MHZ(sdram_max_freq);
+ sc->sdram_min_freq = HZ2MHZ(sdram_min_freq);
+ sc->max_voltage_core = OFFSET2MVOLT(max_voltage_core);
+ sc->min_voltage_core = OFFSET2MVOLT(min_voltage_core);
+
+ /* if turbo is on, set to max values */
+ if (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) {
+ bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
+ arm_max_freq);
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
+ core_max_freq);
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_max_freq);
+ DELAY(TRANSITION_LATENCY);
+ } else {
+ bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
+ arm_min_freq);
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
+ core_min_freq);
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_min_freq);
+ DELAY(TRANSITION_LATENCY);
+ }
+
+ VC_UNLOCK(sc);
+
+ /* add human readable temperature to dev.cpu node */
+ cpu = device_get_parent(sc->dev);
+ if (cpu != NULL) {
+ ctx = device_get_sysctl_ctx(cpu);
+ SYSCTL_ADD_PROC(ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)), OID_AUTO,
+ "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
+ sysctl_bcm2835_devcpu_temperature, "IK",
+ "Current SoC temperature");
+ }
+
+ /* release this hook (continue boot) */
+ config_intrhook_disestablish(&sc->init_hook);
+}
+
+static void
+bcm2835_cpufreq_identify(driver_t *driver, device_t parent)
+{
+ const struct ofw_compat_data *compat;
+ phandle_t root;
+
+ root = OF_finddevice("/");
+ for (compat = compat_data; compat->ocd_str != NULL; compat++)
+ if (fdt_is_compatible(root, compat->ocd_str))
+ break;
+
+ if (compat->ocd_data == 0)
+ return;
+
+ DPRINTF("driver=%p, parent=%p\n", driver, parent);
+ if (device_find_child(parent, "bcm2835_cpufreq", -1) != NULL)
+ return;
+ if (BUS_ADD_CHILD(parent, 0, "bcm2835_cpufreq", -1) == NULL)
+ device_printf(parent, "add child failed\n");
+}
+
+static int
+bcm2835_cpufreq_probe(device_t dev)
+{
+
+ device_set_desc(dev, "CPU Frequency Control");
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_attach(device_t dev)
+{
+ struct bcm2835_cpufreq_softc *sc;
+ struct sysctl_oid *oid;
+
+ /* set self dev */
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ /* initial values */
+ sc->arm_max_freq = -1;
+ sc->arm_min_freq = -1;
+ sc->core_max_freq = -1;
+ sc->core_min_freq = -1;
+ sc->sdram_max_freq = -1;
+ sc->sdram_min_freq = -1;
+ sc->max_voltage_core = 0;
+ sc->min_voltage_core = 0;
+
+ /* setup sysctl at first device */
+ if (device_get_unit(dev) == 0) {
+ sysctl_ctx_init(&bcm2835_sysctl_ctx);
+ /* create node for hw.cpufreq */
+ oid = SYSCTL_ADD_NODE(&bcm2835_sysctl_ctx,
+ SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "cpufreq",
+ CTLFLAG_RD, NULL, "");
+
+ /* Frequency (Hz) */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "arm_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_arm_freq, "IU",
+ "ARM frequency (Hz)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "core_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_core_freq, "IU",
+ "Core frequency (Hz)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "sdram_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_sdram_freq, "IU",
+ "SDRAM frequency (Hz)");
+
+ /* Turbo state */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "turbo", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_turbo, "IU",
+ "Disables dynamic clocking");
+
+ /* Voltage (offset from 1.2V in units of 0.025V) */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_core", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_voltage_core, "I",
+ "ARM/GPU core voltage"
+ "(offset from 1.2V in units of 0.025V)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_sdram", CTLTYPE_INT | CTLFLAG_WR, sc,
+ 0, sysctl_bcm2835_cpufreq_voltage_sdram, "I",
+ "SDRAM voltage (offset from 1.2V in units of 0.025V)");
+
+ /* Voltage individual SDRAM */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_sdram_c", CTLTYPE_INT | CTLFLAG_RW, sc,
+ 0, sysctl_bcm2835_cpufreq_voltage_sdram_c, "I",
+ "SDRAM controller voltage"
+ "(offset from 1.2V in units of 0.025V)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_sdram_i", CTLTYPE_INT | CTLFLAG_RW, sc,
+ 0, sysctl_bcm2835_cpufreq_voltage_sdram_i, "I",
+ "SDRAM I/O voltage (offset from 1.2V in units of 0.025V)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_sdram_p", CTLTYPE_INT | CTLFLAG_RW, sc,
+ 0, sysctl_bcm2835_cpufreq_voltage_sdram_p, "I",
+ "SDRAM phy voltage (offset from 1.2V in units of 0.025V)");
+
+ /* Temperature */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
+ sysctl_bcm2835_cpufreq_temperature, "I",
+ "SoC temperature (thousandths of a degree C)");
+ }
+
+ /* ARM->VC lock */
+ sema_init(&vc_sema, 1, "vcsema");
+
+ /* register callback for using mbox when interrupts are enabled */
+ sc->init_hook.ich_func = bcm2835_cpufreq_init;
+ sc->init_hook.ich_arg = sc;
+
+ if (config_intrhook_establish(&sc->init_hook) != 0) {
+ device_printf(dev, "config_intrhook_establish failed\n");
+ return (ENOMEM);
+ }
+
+ /* this device is controlled by cpufreq(4) */
+ cpufreq_register(dev);
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_detach(device_t dev)
+{
+ struct bcm2835_cpufreq_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ sema_destroy(&vc_sema);
+
+ return (cpufreq_unregister(dev));
+}
+
+static int
+bcm2835_cpufreq_set(device_t dev, const struct cf_setting *cf)
+{
+ struct bcm2835_cpufreq_softc *sc;
+ uint32_t rate_hz, rem;
+ int cur_freq, resp_freq, arm_freq, min_freq, core_freq;
+
+ if (cf == NULL || cf->freq < 0)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ /* setting clock (Hz) */
+ rate_hz = (uint32_t)MHZ2HZ(cf->freq);
+ rem = rate_hz % HZSTEP;
+ rate_hz -= rem;
+ if (rate_hz == 0)
+ return (EINVAL);
+
+ /* adjust min freq */
+ min_freq = sc->arm_min_freq;
+ if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON)
+ if (min_freq > cpufreq_lowest_freq)
+ min_freq = cpufreq_lowest_freq;
+
+ if (rate_hz < MHZ2HZ(min_freq) || rate_hz > MHZ2HZ(sc->arm_max_freq))
+ return (EINVAL);
+
+ /* set new value and verify it */
+ VC_LOCK(sc);
+ cur_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ resp_freq = bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM, rate_hz);
+ DELAY(TRANSITION_LATENCY);
+ arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+
+ /*
+ * if non-turbo and lower than or equal min_freq,
+ * clock down core and sdram to default first.
+ */
+ if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON) {
+ core_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE);
+ if (rate_hz > MHZ2HZ(sc->arm_min_freq)) {
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE,
+ MHZ2HZ(sc->core_max_freq));
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM,
+ MHZ2HZ(sc->sdram_max_freq));
+ DELAY(TRANSITION_LATENCY);
+ } else {
+ if (sc->core_min_freq < DEFAULT_CORE_FREQUENCY &&
+ core_freq > DEFAULT_CORE_FREQUENCY) {
+ /* first, down to 250, then down to min */
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE,
+ MHZ2HZ(DEFAULT_CORE_FREQUENCY));
+ DELAY(TRANSITION_LATENCY);
+ /* reset core voltage */
+ bcm2835_cpufreq_set_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_CORE, 0);
+ DELAY(TRANSITION_LATENCY);
+ }
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE,
+ MHZ2HZ(sc->core_min_freq));
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM,
+ MHZ2HZ(sc->sdram_min_freq));
+ DELAY(TRANSITION_LATENCY);
+ }
+ }
+
+ VC_UNLOCK(sc);
+
+ if (resp_freq < 0 || arm_freq < 0 || resp_freq != arm_freq) {
+ device_printf(dev, "wrong freq\n");
+ return (EIO);
+ }
+ DPRINTF("cpufreq: %d -> %d\n", cur_freq, arm_freq);
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_get(device_t dev, struct cf_setting *cf)
+{
+ struct bcm2835_cpufreq_softc *sc;
+ int arm_freq;
+
+ if (cf == NULL)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
+ cf->dev = NULL;
+
+ /* get cuurent value */
+ VC_LOCK(sc);
+ arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ VC_UNLOCK(sc);
+ if (arm_freq < 0) {
+ device_printf(dev, "can't get clock\n");
+ return (EINVAL);
+ }
+
+ /* CPU clock in MHz or 100ths of a percent. */
+ cf->freq = HZ2MHZ(arm_freq);
+ /* Voltage in mV. */
+ cf->volts = CPUFREQ_VAL_UNKNOWN;
+ /* Power consumed in mW. */
+ cf->power = CPUFREQ_VAL_UNKNOWN;
+ /* Transition latency in us. */
+ cf->lat = TRANSITION_LATENCY;
+ /* Driver providing this setting. */
+ cf->dev = dev;
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets,
+ int *count)
+{
+ struct bcm2835_cpufreq_softc *sc;
+ int freq, min_freq, volts, rem;
+ int idx;
+
+ sc = device_get_softc(dev);
+ freq = sc->arm_max_freq;
+ min_freq = sc->arm_min_freq;
+
+ /* adjust head freq to STEP */
+ rem = freq % MHZSTEP;
+ freq -= rem;
+ if (freq < min_freq)
+ freq = min_freq;
+
+ /* if non-turbo, add extra low freq */
+ if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON)
+ if (min_freq > cpufreq_lowest_freq)
+ min_freq = cpufreq_lowest_freq;
+
+ /* from freq to min_freq */
+ for (idx = 0; idx < *count && freq >= min_freq; idx++) {
+ if (freq > sc->arm_min_freq)
+ volts = sc->max_voltage_core;
+ else
+ volts = sc->min_voltage_core;
+ sets[idx].freq = freq;
+ sets[idx].volts = volts;
+ sets[idx].lat = TRANSITION_LATENCY;
+ sets[idx].dev = dev;
+ freq -= MHZSTEP;
+ }
+ *count = ++idx;
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
+{
+ struct bcm2835_cpufreq_softc *sc;
+
+ if (sets == NULL || count == NULL)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ if (sc->arm_min_freq < 0 || sc->arm_max_freq < 0) {
+ printf("device is not configured\n");
+ return (EINVAL);
+ }
+
+ /* fill data with unknown value */
+ memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count));
+ /* create new array up to count */
+ bcm2835_cpufreq_make_freq_list(dev, sets, count);
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_type(device_t dev, int *type)
+{
+
+ if (type == NULL)
+ return (EINVAL);
+ *type = CPUFREQ_TYPE_ABSOLUTE;
+
+ return (0);
+}
+
+static device_method_t bcm2835_cpufreq_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, bcm2835_cpufreq_identify),
+ DEVMETHOD(device_probe, bcm2835_cpufreq_probe),
+ DEVMETHOD(device_attach, bcm2835_cpufreq_attach),
+ DEVMETHOD(device_detach, bcm2835_cpufreq_detach),
+
+ /* cpufreq interface */
+ DEVMETHOD(cpufreq_drv_set, bcm2835_cpufreq_set),
+ DEVMETHOD(cpufreq_drv_get, bcm2835_cpufreq_get),
+ DEVMETHOD(cpufreq_drv_settings, bcm2835_cpufreq_settings),
+ DEVMETHOD(cpufreq_drv_type, bcm2835_cpufreq_type),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm2835_cpufreq_devclass;
+static driver_t bcm2835_cpufreq_driver = {
+ "bcm2835_cpufreq",
+ bcm2835_cpufreq_methods,
+ sizeof(struct bcm2835_cpufreq_softc),
+};
+
+DRIVER_MODULE(bcm2835_cpufreq, cpu, bcm2835_cpufreq_driver,
+ bcm2835_cpufreq_devclass, 0, 0);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,773 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2013 Daisuke Aoyama <aoyama at peach.ne.jp>
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at bluezbox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_dma.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+
+#include "bcm2835_dma.h"
+#include "bcm2835_vcbus.h"
+
+#define MAX_REG 9
+
+/* private flags */
+#define BCM_DMA_CH_USED 0x00000001
+#define BCM_DMA_CH_FREE 0x40000000
+#define BCM_DMA_CH_UNMAP 0x80000000
+
+/* Register Map (4.2.1.2) */
+#define BCM_DMA_CS(n) (0x100*(n) + 0x00)
+#define CS_ACTIVE (1 << 0)
+#define CS_END (1 << 1)
+#define CS_INT (1 << 2)
+#define CS_DREQ (1 << 3)
+#define CS_ISPAUSED (1 << 4)
+#define CS_ISHELD (1 << 5)
+#define CS_ISWAIT (1 << 6)
+#define CS_ERR (1 << 8)
+#define CS_WAITWRT (1 << 28)
+#define CS_DISDBG (1 << 29)
+#define CS_ABORT (1 << 30)
+#define CS_RESET (1U << 31)
+#define BCM_DMA_CBADDR(n) (0x100*(n) + 0x04)
+#define BCM_DMA_INFO(n) (0x100*(n) + 0x08)
+#define INFO_INT_EN (1 << 0)
+#define INFO_TDMODE (1 << 1)
+#define INFO_WAIT_RESP (1 << 3)
+#define INFO_D_INC (1 << 4)
+#define INFO_D_WIDTH (1 << 5)
+#define INFO_D_DREQ (1 << 6)
+#define INFO_S_INC (1 << 8)
+#define INFO_S_WIDTH (1 << 9)
+#define INFO_S_DREQ (1 << 10)
+#define INFO_WAITS_SHIFT (21)
+#define INFO_PERMAP_SHIFT (16)
+#define INFO_PERMAP_MASK (0x1f << INFO_PERMAP_SHIFT)
+
+#define BCM_DMA_SRC(n) (0x100*(n) + 0x0C)
+#define BCM_DMA_DST(n) (0x100*(n) + 0x10)
+#define BCM_DMA_LEN(n) (0x100*(n) + 0x14)
+#define BCM_DMA_STRIDE(n) (0x100*(n) + 0x18)
+#define BCM_DMA_CBNEXT(n) (0x100*(n) + 0x1C)
+#define BCM_DMA_DEBUG(n) (0x100*(n) + 0x20)
+#define DEBUG_ERROR_MASK (7)
+
+#define BCM_DMA_INT_STATUS 0xfe0
+#define BCM_DMA_ENABLE 0xff0
+
+/* relative offset from BCM_VC_DMA0_BASE (p.39) */
+#define BCM_DMA_CH(n) (0x100*(n))
+
+/* channels used by GPU */
+#define BCM_DMA_CH_BULK 0
+#define BCM_DMA_CH_FAST1 2
+#define BCM_DMA_CH_FAST2 3
+
+#define BCM_DMA_CH_GPU_MASK ((1 << BCM_DMA_CH_BULK) | \
+ (1 << BCM_DMA_CH_FAST1) | \
+ (1 << BCM_DMA_CH_FAST2))
+
+/* DMA Control Block - 256bit aligned (p.40) */
+struct bcm_dma_cb {
+ uint32_t info; /* Transfer Information */
+ uint32_t src; /* Source Address */
+ uint32_t dst; /* Destination Address */
+ uint32_t len; /* Transfer Length */
+ uint32_t stride; /* 2D Mode Stride */
+ uint32_t next; /* Next Control Block Address */
+ uint32_t rsvd1; /* Reserved */
+ uint32_t rsvd2; /* Reserved */
+};
+
+#ifdef DEBUG
+static void bcm_dma_cb_dump(struct bcm_dma_cb *cb);
+static void bcm_dma_reg_dump(int ch);
+#endif
+
+/* DMA channel private info */
+struct bcm_dma_ch {
+ int ch;
+ uint32_t flags;
+ struct bcm_dma_cb * cb;
+ uint32_t vc_cb;
+ bus_dmamap_t dma_map;
+ void (*intr_func)(int, void *);
+ void * intr_arg;
+};
+
+struct bcm_dma_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ struct resource * sc_mem;
+ struct resource * sc_irq[BCM_DMA_CH_MAX];
+ void * sc_intrhand[BCM_DMA_CH_MAX];
+ struct bcm_dma_ch sc_dma_ch[BCM_DMA_CH_MAX];
+ bus_dma_tag_t sc_dma_tag;
+};
+
+static struct bcm_dma_softc *bcm_dma_sc = NULL;
+static uint32_t bcm_dma_channel_mask;
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-dma", 1},
+ {"brcm,bcm2835-dma", 1},
+ {NULL, 0}
+};
+
+static void
+bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs,
+ int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+
+ addr = (bus_addr_t*)arg;
+ *addr = PHYS_TO_VCBUS(segs[0].ds_addr);
+}
+
+static void
+bcm_dma_reset(device_t dev, int ch)
+{
+ struct bcm_dma_softc *sc = device_get_softc(dev);
+ struct bcm_dma_cb *cb;
+ uint32_t cs;
+ int count;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return;
+
+ cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch));
+
+ if (cs & CS_ACTIVE) {
+ /* pause current task */
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(ch), 0);
+
+ count = 1000;
+ do {
+ cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch));
+ } while (!(cs & CS_ISPAUSED) && (count-- > 0));
+
+ if (!(cs & CS_ISPAUSED)) {
+ device_printf(dev,
+ "Can't abort DMA transfer at channel %d\n", ch);
+ }
+
+ bus_write_4(sc->sc_mem, BCM_DMA_CBNEXT(ch), 0);
+
+ /* Complete everything, clear interrupt */
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(ch),
+ CS_ABORT | CS_INT | CS_END| CS_ACTIVE);
+ }
+
+ /* clear control blocks */
+ bus_write_4(sc->sc_mem, BCM_DMA_CBADDR(ch), 0);
+ bus_write_4(sc->sc_mem, BCM_DMA_CBNEXT(ch), 0);
+
+ /* Reset control block */
+ cb = sc->sc_dma_ch[ch].cb;
+ bzero(cb, sizeof(*cb));
+ cb->info = INFO_WAIT_RESP;
+}
+
+static int
+bcm_dma_init(device_t dev)
+{
+ struct bcm_dma_softc *sc = device_get_softc(dev);
+ uint32_t reg;
+ struct bcm_dma_ch *ch;
+ void *cb_virt;
+ vm_paddr_t cb_phys;
+ int err;
+ int i;
+
+ /*
+ * Only channels set in bcm_dma_channel_mask can be controlled by us.
+ * The others are out of our control as well as the corresponding bits
+ * in both BCM_DMA_ENABLE and BCM_DMA_INT_STATUS global registers. As
+ * these registers are RW ones, there is no safe way how to write only
+ * the bits which can be controlled by us.
+ *
+ * Fortunately, after reset, all channels are enabled in BCM_DMA_ENABLE
+ * register and all statuses are cleared in BCM_DMA_INT_STATUS one.
+ * Not touching these registers is a trade off between correct
+ * initialization which does not count on anything and not messing up
+ * something we have no control over.
+ */
+ reg = bus_read_4(sc->sc_mem, BCM_DMA_ENABLE);
+ if ((reg & bcm_dma_channel_mask) != bcm_dma_channel_mask)
+ device_printf(dev, "channels are not enabled\n");
+ reg = bus_read_4(sc->sc_mem, BCM_DMA_INT_STATUS);
+ if ((reg & bcm_dma_channel_mask) != 0)
+ device_printf(dev, "statuses are not cleared\n");
+
+ /* Allocate DMA chunks control blocks */
+ /* p.40 of spec - control block should be 32-bit aligned */
+ err = bus_dma_tag_create(bus_get_dma_tag(dev),
+ 1, 0, BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR, NULL, NULL,
+ sizeof(struct bcm_dma_cb), 1,
+ sizeof(struct bcm_dma_cb),
+ BUS_DMA_ALLOCNOW, NULL, NULL,
+ &sc->sc_dma_tag);
+
+ if (err) {
+ device_printf(dev, "failed allocate DMA tag\n");
+ return (err);
+ }
+
+ /* setup initial settings */
+ for (i = 0; i < BCM_DMA_CH_MAX; i++) {
+ ch = &sc->sc_dma_ch[i];
+
+ bzero(ch, sizeof(struct bcm_dma_ch));
+ ch->ch = i;
+ ch->flags = BCM_DMA_CH_UNMAP;
+
+ if ((bcm_dma_channel_mask & (1 << i)) == 0)
+ continue;
+
+ err = bus_dmamem_alloc(sc->sc_dma_tag, &cb_virt,
+ BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
+ &ch->dma_map);
+ if (err) {
+ device_printf(dev, "cannot allocate DMA memory\n");
+ break;
+ }
+
+ /*
+ * Least alignment for busdma-allocated stuff is cache
+ * line size, so just make sure nothing stupid happend
+ * and we got properly aligned address
+ */
+ if ((uintptr_t)cb_virt & 0x1f) {
+ device_printf(dev,
+ "DMA address is not 32-bytes aligned: %p\n",
+ (void*)cb_virt);
+ break;
+ }
+
+ err = bus_dmamap_load(sc->sc_dma_tag, ch->dma_map, cb_virt,
+ sizeof(struct bcm_dma_cb), bcm_dmamap_cb, &cb_phys,
+ BUS_DMA_WAITOK);
+ if (err) {
+ device_printf(dev, "cannot load DMA memory\n");
+ break;
+ }
+
+ ch->cb = cb_virt;
+ ch->vc_cb = cb_phys;
+ ch->flags = BCM_DMA_CH_FREE;
+ ch->cb->info = INFO_WAIT_RESP;
+
+ /* reset DMA engine */
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(i), CS_RESET);
+ }
+
+ return (0);
+}
+
+/*
+ * Allocate DMA channel for further use, returns channel # or
+ * BCM_DMA_CH_INVALID
+ */
+int
+bcm_dma_allocate(int req_ch)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ int ch = BCM_DMA_CH_INVALID;
+ int i;
+
+ if (req_ch >= BCM_DMA_CH_MAX)
+ return (BCM_DMA_CH_INVALID);
+
+ /* Auto(req_ch < 0) or CH specified */
+ mtx_lock(&sc->sc_mtx);
+
+ if (req_ch < 0) {
+ for (i = 0; i < BCM_DMA_CH_MAX; i++) {
+ if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE) {
+ ch = i;
+ sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_FREE;
+ sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_USED;
+ break;
+ }
+ }
+ }
+ else {
+ if (sc->sc_dma_ch[req_ch].flags & BCM_DMA_CH_FREE) {
+ ch = req_ch;
+ sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_FREE;
+ sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_USED;
+ }
+ }
+
+ mtx_unlock(&sc->sc_mtx);
+ return (ch);
+}
+
+/*
+ * Frees allocated channel. Returns 0 on success, -1 otherwise
+ */
+int
+bcm_dma_free(int ch)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ mtx_lock(&sc->sc_mtx);
+ if (sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED) {
+ sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_FREE;
+ sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_USED;
+ sc->sc_dma_ch[ch].intr_func = NULL;
+ sc->sc_dma_ch[ch].intr_arg = NULL;
+
+ /* reset DMA engine */
+ bcm_dma_reset(sc->sc_dev, ch);
+ }
+
+ mtx_unlock(&sc->sc_mtx);
+ return (0);
+}
+
+/*
+ * Assign handler function for channel interrupt
+ * Returns 0 on success, -1 otherwise
+ */
+int
+bcm_dma_setup_intr(int ch, void (*func)(int, void *), void *arg)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ struct bcm_dma_cb *cb;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (-1);
+
+ sc->sc_dma_ch[ch].intr_func = func;
+ sc->sc_dma_ch[ch].intr_arg = arg;
+ cb = sc->sc_dma_ch[ch].cb;
+ cb->info |= INFO_INT_EN;
+
+ return (0);
+}
+
+/*
+ * Setup DMA source parameters
+ * ch - channel number
+ * dreq - hardware DREQ # or BCM_DMA_DREQ_NONE if
+ * source is physical memory
+ * inc_addr - BCM_DMA_INC_ADDR if source address
+ * should be increased after each access or
+ * BCM_DMA_SAME_ADDR if address should remain
+ * the same
+ * width - size of read operation, BCM_DMA_32BIT
+ * for 32bit bursts, BCM_DMA_128BIT for 128 bits
+ *
+ * Returns 0 on success, -1 otherwise
+ */
+int
+bcm_dma_setup_src(int ch, int dreq, int inc_addr, int width)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ uint32_t info;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (-1);
+
+ info = sc->sc_dma_ch[ch].cb->info;
+ info &= ~INFO_PERMAP_MASK;
+ info |= (dreq << INFO_PERMAP_SHIFT) & INFO_PERMAP_MASK;
+
+ if (dreq)
+ info |= INFO_S_DREQ;
+ else
+ info &= ~INFO_S_DREQ;
+
+ if (width == BCM_DMA_128BIT)
+ info |= INFO_S_WIDTH;
+ else
+ info &= ~INFO_S_WIDTH;
+
+ if (inc_addr == BCM_DMA_INC_ADDR)
+ info |= INFO_S_INC;
+ else
+ info &= ~INFO_S_INC;
+
+ sc->sc_dma_ch[ch].cb->info = info;
+
+ return (0);
+}
+
+/*
+ * Setup DMA destination parameters
+ * ch - channel number
+ * dreq - hardware DREQ # or BCM_DMA_DREQ_NONE if
+ * destination is physical memory
+ * inc_addr - BCM_DMA_INC_ADDR if source address
+ * should be increased after each access or
+ * BCM_DMA_SAME_ADDR if address should remain
+ * the same
+ * width - size of write operation, BCM_DMA_32BIT
+ * for 32bit bursts, BCM_DMA_128BIT for 128 bits
+ *
+ * Returns 0 on success, -1 otherwise
+ */
+int
+bcm_dma_setup_dst(int ch, int dreq, int inc_addr, int width)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ uint32_t info;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (-1);
+
+ info = sc->sc_dma_ch[ch].cb->info;
+ info &= ~INFO_PERMAP_MASK;
+ info |= (dreq << INFO_PERMAP_SHIFT) & INFO_PERMAP_MASK;
+
+ if (dreq)
+ info |= INFO_D_DREQ;
+ else
+ info &= ~INFO_D_DREQ;
+
+ if (width == BCM_DMA_128BIT)
+ info |= INFO_D_WIDTH;
+ else
+ info &= ~INFO_D_WIDTH;
+
+ if (inc_addr == BCM_DMA_INC_ADDR)
+ info |= INFO_D_INC;
+ else
+ info &= ~INFO_D_INC;
+
+ sc->sc_dma_ch[ch].cb->info = info;
+
+ return (0);
+}
+
+#ifdef DEBUG
+void
+bcm_dma_cb_dump(struct bcm_dma_cb *cb)
+{
+
+ printf("DMA CB ");
+ printf("INFO: %8.8x ", cb->info);
+ printf("SRC: %8.8x ", cb->src);
+ printf("DST: %8.8x ", cb->dst);
+ printf("LEN: %8.8x ", cb->len);
+ printf("\n");
+ printf("STRIDE: %8.8x ", cb->stride);
+ printf("NEXT: %8.8x ", cb->next);
+ printf("RSVD1: %8.8x ", cb->rsvd1);
+ printf("RSVD2: %8.8x ", cb->rsvd2);
+ printf("\n");
+}
+
+void
+bcm_dma_reg_dump(int ch)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ int i;
+ uint32_t reg;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return;
+
+ printf("DMA%d: ", ch);
+ for (i = 0; i < MAX_REG; i++) {
+ reg = bus_read_4(sc->sc_mem, BCM_DMA_CH(ch) + i*4);
+ printf("%8.8x ", reg);
+ }
+ printf("\n");
+}
+#endif
+
+/*
+ * Start DMA transaction
+ * ch - channel number
+ * src, dst - source and destination address in
+ * ARM physical memory address space.
+ * len - amount of bytes to be transfered
+ *
+ * Returns 0 on success, -1 otherwise
+ */
+int
+bcm_dma_start(int ch, vm_paddr_t src, vm_paddr_t dst, int len)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ struct bcm_dma_cb *cb;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (-1);
+
+ cb = sc->sc_dma_ch[ch].cb;
+ if (BCM2835_ARM_IS_IO(src))
+ cb->src = IO_TO_VCBUS(src);
+ else
+ cb->src = PHYS_TO_VCBUS(src);
+ if (BCM2835_ARM_IS_IO(dst))
+ cb->dst = IO_TO_VCBUS(dst);
+ else
+ cb->dst = PHYS_TO_VCBUS(dst);
+ cb->len = len;
+
+ bus_dmamap_sync(sc->sc_dma_tag,
+ sc->sc_dma_ch[ch].dma_map, BUS_DMASYNC_PREWRITE);
+
+ bus_write_4(sc->sc_mem, BCM_DMA_CBADDR(ch),
+ sc->sc_dma_ch[ch].vc_cb);
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(ch), CS_ACTIVE);
+
+#ifdef DEBUG
+ bcm_dma_cb_dump(sc->sc_dma_ch[ch].cb);
+ bcm_dma_reg_dump(ch);
+#endif
+
+ return (0);
+}
+
+/*
+ * Get length requested for DMA transaction
+ * ch - channel number
+ *
+ * Returns size of transaction, 0 if channel is invalid
+ */
+uint32_t
+bcm_dma_length(int ch)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ struct bcm_dma_cb *cb;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (0);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (0);
+
+ cb = sc->sc_dma_ch[ch].cb;
+
+ return (cb->len);
+}
+
+static void
+bcm_dma_intr(void *arg)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ struct bcm_dma_ch *ch = (struct bcm_dma_ch *)arg;
+ uint32_t cs, debug;
+
+ /* my interrupt? */
+ cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch->ch));
+
+ if (!(cs & (CS_INT | CS_ERR))) {
+ device_printf(sc->sc_dev,
+ "unexpected DMA intr CH=%d, CS=%x\n", ch->ch, cs);
+ return;
+ }
+
+ /* running? */
+ if (!(ch->flags & BCM_DMA_CH_USED)) {
+ device_printf(sc->sc_dev,
+ "unused DMA intr CH=%d, CS=%x\n", ch->ch, cs);
+ return;
+ }
+
+ if (cs & CS_ERR) {
+ debug = bus_read_4(sc->sc_mem, BCM_DMA_DEBUG(ch->ch));
+ device_printf(sc->sc_dev, "DMA error %d on CH%d\n",
+ debug & DEBUG_ERROR_MASK, ch->ch);
+ bus_write_4(sc->sc_mem, BCM_DMA_DEBUG(ch->ch),
+ debug & DEBUG_ERROR_MASK);
+ bcm_dma_reset(sc->sc_dev, ch->ch);
+ }
+
+ if (cs & CS_INT) {
+ /* acknowledge interrupt */
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(ch->ch),
+ CS_INT | CS_END);
+
+ /* Prepare for possible access to len field */
+ bus_dmamap_sync(sc->sc_dma_tag, ch->dma_map,
+ BUS_DMASYNC_POSTWRITE);
+
+ /* save callback function and argument */
+ if (ch->intr_func)
+ ch->intr_func(ch->ch, ch->intr_arg);
+ }
+}
+
+static int
+bcm_dma_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2835 DMA Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_dma_attach(device_t dev)
+{
+ struct bcm_dma_softc *sc = device_get_softc(dev);
+ phandle_t node;
+ int rid, err = 0;
+ int i;
+
+ sc->sc_dev = dev;
+
+ if (bcm_dma_sc)
+ return (ENXIO);
+
+ for (i = 0; i < BCM_DMA_CH_MAX; i++) {
+ sc->sc_irq[i] = NULL;
+ sc->sc_intrhand[i] = NULL;
+ }
+
+ /* Get DMA channel mask. */
+ node = ofw_bus_get_node(sc->sc_dev);
+ if (OF_getencprop(node, "brcm,dma-channel-mask", &bcm_dma_channel_mask,
+ sizeof(bcm_dma_channel_mask)) == -1 &&
+ OF_getencprop(node, "broadcom,channels", &bcm_dma_channel_mask,
+ sizeof(bcm_dma_channel_mask)) == -1) {
+ device_printf(dev, "could not get channel mask property\n");
+ return (ENXIO);
+ }
+
+ /* Mask out channels used by GPU. */
+ bcm_dma_channel_mask &= ~BCM_DMA_CH_GPU_MASK;
+
+ /* DMA0 - DMA14 */
+ rid = 0;
+ sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->sc_mem == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ /* IRQ DMA0 - DMA11 XXX NOT USE DMA12(spurious?) */
+ for (rid = 0; rid < BCM_DMA_CH_MAX; rid++) {
+ if ((bcm_dma_channel_mask & (1 << rid)) == 0)
+ continue;
+
+ sc->sc_irq[rid] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->sc_irq[rid] == NULL) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ err = ENXIO;
+ goto fail;
+ }
+ if (bus_setup_intr(dev, sc->sc_irq[rid], INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, bcm_dma_intr, &sc->sc_dma_ch[rid],
+ &sc->sc_intrhand[rid])) {
+ device_printf(dev, "cannot setup interrupt handler\n");
+ err = ENXIO;
+ goto fail;
+ }
+ }
+
+ mtx_init(&sc->sc_mtx, "bcmdma", "bcmdma", MTX_DEF);
+ bcm_dma_sc = sc;
+
+ err = bcm_dma_init(dev);
+ if (err)
+ goto fail;
+
+ return (err);
+
+fail:
+ if (sc->sc_mem)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem);
+
+ for (i = 0; i < BCM_DMA_CH_MAX; i++) {
+ if (sc->sc_intrhand[i])
+ bus_teardown_intr(dev, sc->sc_irq[i], sc->sc_intrhand[i]);
+ if (sc->sc_irq[i])
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq[i]);
+ }
+
+ return (err);
+}
+
+static device_method_t bcm_dma_methods[] = {
+ DEVMETHOD(device_probe, bcm_dma_probe),
+ DEVMETHOD(device_attach, bcm_dma_attach),
+ { 0, 0 }
+};
+
+static driver_t bcm_dma_driver = {
+ "bcm_dma",
+ bcm_dma_methods,
+ sizeof(struct bcm_dma_softc),
+};
+
+static devclass_t bcm_dma_devclass;
+
+DRIVER_MODULE(bcm_dma, simplebus, bcm_dma_driver, bcm_dma_devclass, 0, 0);
+MODULE_VERSION(bcm_dma, 1);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,61 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2013 Daisuke Aoyama <aoyama at peach.ne.jp>
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at bluezbox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_dma.h 322724 2017-08-20 16:52:27Z marius $
+ */
+
+#ifndef _BCM2835_DMA_H_
+#define _BCM2835_DMA_H_
+
+#define BCM_DMA_BLOCK_SIZE 512
+
+/* DMA0-DMA15 but DMA15 is special */
+#define BCM_DMA_CH_MAX 12
+
+/* request CH for any nubmer */
+#define BCM_DMA_CH_INVALID (-1)
+#define BCM_DMA_CH_ANY (-1)
+
+/* Peripheral DREQ Signals (4.2.1.3) */
+#define BCM_DMA_DREQ_NONE 0
+#define BCM_DMA_DREQ_EMMC 11
+#define BCM_DMA_DREQ_SDHOST 13
+
+#define BCM_DMA_SAME_ADDR 0
+#define BCM_DMA_INC_ADDR 1
+
+#define BCM_DMA_32BIT 0
+#define BCM_DMA_128BIT 1
+
+int bcm_dma_allocate(int req_ch);
+int bcm_dma_free(int ch);
+int bcm_dma_setup_intr(int ch, void (*func)(int, void *), void *arg);
+int bcm_dma_setup_src(int ch, int dreq, int inc_addr, int width);
+int bcm_dma_setup_dst(int ch, int dreq, int inc_addr, int width);
+int bcm_dma_start(int ch, vm_paddr_t src, vm_paddr_t dst, int len);
+uint32_t bcm_dma_length(int ch);
+
+#endif /* _BCM2835_DMA_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_dma.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_fb.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_fb.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_fb.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,871 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_fb.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/syscons/syscons.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
+
+#include "mbox_if.h"
+
+struct argb {
+ uint8_t a;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+};
+
+static struct argb bcmfb_palette[16] = {
+ {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0xaa},
+ {0x00, 0x00, 0xaa, 0x00},
+ {0x00, 0x00, 0xaa, 0xaa},
+ {0x00, 0xaa, 0x00, 0x00},
+ {0x00, 0xaa, 0x00, 0xaa},
+ {0x00, 0xaa, 0x55, 0x00},
+ {0x00, 0xaa, 0xaa, 0xaa},
+ {0x00, 0x55, 0x55, 0x55},
+ {0x00, 0x55, 0x55, 0xff},
+ {0x00, 0x55, 0xff, 0x55},
+ {0x00, 0x55, 0xff, 0xff},
+ {0x00, 0xff, 0x55, 0x55},
+ {0x00, 0xff, 0x55, 0xff},
+ {0x00, 0xff, 0xff, 0x55},
+ {0x00, 0xff, 0xff, 0xff}
+};
+
+/* mouse pointer from dev/syscons/scgfbrndr.c */
+static u_char mouse_pointer[16] = {
+ 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
+ 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
+};
+
+#define BCMFB_FONT_HEIGHT 16
+#define BCMFB_FONT_WIDTH 8
+#define FB_WIDTH 640
+#define FB_HEIGHT 480
+#define FB_DEPTH 24
+
+struct bcmsc_softc {
+ /* Videoadpater part */
+ video_adapter_t va;
+
+ intptr_t fb_addr;
+ intptr_t fb_paddr;
+ unsigned int fb_size;
+
+ unsigned int height;
+ unsigned int width;
+ unsigned int depth;
+ unsigned int stride;
+
+ unsigned int xmargin;
+ unsigned int ymargin;
+
+ unsigned char *font;
+ int fbswap;
+ int initialized;
+};
+
+static struct bcmsc_softc bcmsc;
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-fb", 1},
+ {"brcm,bcm2708-fb", 1},
+ {NULL, 0}
+};
+
+static int bcm_fb_probe(device_t);
+static int bcm_fb_attach(device_t);
+static void bcmfb_update_margins(video_adapter_t *adp);
+static int bcmfb_configure(int);
+
+static int
+bcm_fb_probe(device_t dev)
+{
+ int error;
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2835 framebuffer device");
+ error = sc_probe_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD);
+ if (error != 0)
+ return (error);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_fb_attach(device_t dev)
+{
+ struct bcm2835_fb_config fb;
+ struct bcmsc_softc *sc;
+
+ sc = (struct bcmsc_softc *)vid_get_adapter(vid_find_adapter(
+ "bcmfb", 0));
+ if (sc != NULL)
+ device_set_softc(dev, sc);
+ else
+ sc = device_get_softc(dev);
+
+ memset(&fb, 0, sizeof(fb));
+ if (bcm2835_mbox_fb_get_w_h(&fb) != 0)
+ return (ENXIO);
+ fb.bpp = FB_DEPTH;
+ fb.vxres = fb.xres;
+ fb.vyres = fb.yres;
+ fb.xoffset = fb.yoffset = 0;
+ if (bcm2835_mbox_fb_init(&fb) != 0)
+ return (ENXIO);
+
+ sc->fb_addr = (intptr_t)pmap_mapdev(fb.base, fb.size);
+ sc->fb_paddr = fb.base;
+ sc->fb_size = fb.size;
+ sc->depth = fb.bpp;
+ sc->stride = fb.pitch;
+ sc->width = fb.xres;
+ sc->height = fb.yres;
+ bcmfb_update_margins(&sc->va);
+
+ if (sc_attach_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD) != 0) {
+ device_printf(dev, "failed to attach syscons\n");
+ return (ENXIO);
+ }
+
+ device_printf(dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres,
+ fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp);
+ device_printf(dev,
+ "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n",
+ sc->fbswap, fb.pitch, fb.base, fb.size);
+
+ return (0);
+}
+
+static device_method_t bcm_fb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bcm_fb_probe),
+ DEVMETHOD(device_attach, bcm_fb_attach),
+
+ { 0, 0 }
+};
+
+static devclass_t bcm_fb_devclass;
+
+static driver_t bcm_fb_driver = {
+ "fb",
+ bcm_fb_methods,
+ sizeof(struct bcmsc_softc),
+};
+
+DRIVER_MODULE(bcm2835fb, ofwbus, bcm_fb_driver, bcm_fb_devclass, 0, 0);
+DRIVER_MODULE(bcm2835fb, simplebus, bcm_fb_driver, bcm_fb_devclass, 0, 0);
+
+/*
+ * Video driver routines and glue.
+ */
+static vi_probe_t bcmfb_probe;
+static vi_init_t bcmfb_init;
+static vi_get_info_t bcmfb_get_info;
+static vi_query_mode_t bcmfb_query_mode;
+static vi_set_mode_t bcmfb_set_mode;
+static vi_save_font_t bcmfb_save_font;
+static vi_load_font_t bcmfb_load_font;
+static vi_show_font_t bcmfb_show_font;
+static vi_save_palette_t bcmfb_save_palette;
+static vi_load_palette_t bcmfb_load_palette;
+static vi_set_border_t bcmfb_set_border;
+static vi_save_state_t bcmfb_save_state;
+static vi_load_state_t bcmfb_load_state;
+static vi_set_win_org_t bcmfb_set_win_org;
+static vi_read_hw_cursor_t bcmfb_read_hw_cursor;
+static vi_set_hw_cursor_t bcmfb_set_hw_cursor;
+static vi_set_hw_cursor_shape_t bcmfb_set_hw_cursor_shape;
+static vi_blank_display_t bcmfb_blank_display;
+static vi_mmap_t bcmfb_mmap;
+static vi_ioctl_t bcmfb_ioctl;
+static vi_clear_t bcmfb_clear;
+static vi_fill_rect_t bcmfb_fill_rect;
+static vi_bitblt_t bcmfb_bitblt;
+static vi_diag_t bcmfb_diag;
+static vi_save_cursor_palette_t bcmfb_save_cursor_palette;
+static vi_load_cursor_palette_t bcmfb_load_cursor_palette;
+static vi_copy_t bcmfb_copy;
+static vi_putp_t bcmfb_putp;
+static vi_putc_t bcmfb_putc;
+static vi_puts_t bcmfb_puts;
+static vi_putm_t bcmfb_putm;
+
+static video_switch_t bcmfbvidsw = {
+ .probe = bcmfb_probe,
+ .init = bcmfb_init,
+ .get_info = bcmfb_get_info,
+ .query_mode = bcmfb_query_mode,
+ .set_mode = bcmfb_set_mode,
+ .save_font = bcmfb_save_font,
+ .load_font = bcmfb_load_font,
+ .show_font = bcmfb_show_font,
+ .save_palette = bcmfb_save_palette,
+ .load_palette = bcmfb_load_palette,
+ .set_border = bcmfb_set_border,
+ .save_state = bcmfb_save_state,
+ .load_state = bcmfb_load_state,
+ .set_win_org = bcmfb_set_win_org,
+ .read_hw_cursor = bcmfb_read_hw_cursor,
+ .set_hw_cursor = bcmfb_set_hw_cursor,
+ .set_hw_cursor_shape = bcmfb_set_hw_cursor_shape,
+ .blank_display = bcmfb_blank_display,
+ .mmap = bcmfb_mmap,
+ .ioctl = bcmfb_ioctl,
+ .clear = bcmfb_clear,
+ .fill_rect = bcmfb_fill_rect,
+ .bitblt = bcmfb_bitblt,
+ .diag = bcmfb_diag,
+ .save_cursor_palette = bcmfb_save_cursor_palette,
+ .load_cursor_palette = bcmfb_load_cursor_palette,
+ .copy = bcmfb_copy,
+ .putp = bcmfb_putp,
+ .putc = bcmfb_putc,
+ .puts = bcmfb_puts,
+ .putm = bcmfb_putm,
+};
+
+VIDEO_DRIVER(bcmfb, bcmfbvidsw, bcmfb_configure);
+
+static vr_init_t bcmrend_init;
+static vr_clear_t bcmrend_clear;
+static vr_draw_border_t bcmrend_draw_border;
+static vr_draw_t bcmrend_draw;
+static vr_set_cursor_t bcmrend_set_cursor;
+static vr_draw_cursor_t bcmrend_draw_cursor;
+static vr_blink_cursor_t bcmrend_blink_cursor;
+static vr_set_mouse_t bcmrend_set_mouse;
+static vr_draw_mouse_t bcmrend_draw_mouse;
+
+/*
+ * We use our own renderer; this is because we must emulate a hardware
+ * cursor.
+ */
+static sc_rndr_sw_t bcmrend = {
+ bcmrend_init,
+ bcmrend_clear,
+ bcmrend_draw_border,
+ bcmrend_draw,
+ bcmrend_set_cursor,
+ bcmrend_draw_cursor,
+ bcmrend_blink_cursor,
+ bcmrend_set_mouse,
+ bcmrend_draw_mouse
+};
+
+RENDERER(bcmfb, 0, bcmrend, gfb_set);
+RENDERER_MODULE(bcmfb, gfb_set);
+
+static void
+bcmrend_init(scr_stat* scp)
+{
+}
+
+static void
+bcmrend_clear(scr_stat* scp, int c, int attr)
+{
+}
+
+static void
+bcmrend_draw_border(scr_stat* scp, int color)
+{
+}
+
+static void
+bcmrend_draw(scr_stat* scp, int from, int count, int flip)
+{
+ video_adapter_t* adp = scp->sc->adp;
+ int i, c, a;
+
+ if (!flip) {
+ /* Normal printing */
+ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count);
+ } else {
+ /* This is for selections and such: invert the color attribute */
+ for (i = count; i-- > 0; ++from) {
+ c = sc_vtb_getc(&scp->vtb, from);
+ a = sc_vtb_geta(&scp->vtb, from) >> 8;
+ vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4));
+ }
+ }
+}
+
+static void
+bcmrend_set_cursor(scr_stat* scp, int base, int height, int blink)
+{
+}
+
+static void
+bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip)
+{
+ int bytes, col, i, j, row;
+ struct bcmsc_softc *sc;
+ uint8_t *addr;
+ video_adapter_t *adp;
+
+ adp = scp->sc->adp;
+ sc = (struct bcmsc_softc *)adp;
+
+ if (scp->curs_attr.height <= 0)
+ return;
+
+ if (sc->fb_addr == 0)
+ return;
+
+ if (off >= adp->va_info.vi_width * adp->va_info.vi_height)
+ return;
+
+ /* calculate the coordinates in the video buffer */
+ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+ col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+
+ addr = (uint8_t *)sc->fb_addr
+ + (row + sc->ymargin)*(sc->stride)
+ + (sc->depth/8) * (col + sc->xmargin);
+
+ bytes = sc->depth / 8;
+ /* our cursor consists of simply inverting the char under it */
+ for (i = 0; i < adp->va_info.vi_cheight; i++) {
+ for (j = 0; j < adp->va_info.vi_cwidth; j++) {
+ switch (sc->depth) {
+ case 32:
+ case 24:
+ addr[bytes*j + 2] ^= 0xff;
+ /* FALLTHROUGH */
+ case 16:
+ addr[bytes*j + 1] ^= 0xff;
+ addr[bytes*j] ^= 0xff;
+ break;
+ default:
+ break;
+ }
+ }
+
+ addr += sc->stride;
+ }
+}
+
+static void
+bcmrend_blink_cursor(scr_stat* scp, int at, int flip)
+{
+}
+
+static void
+bcmrend_set_mouse(scr_stat* scp)
+{
+}
+
+static void
+bcmrend_draw_mouse(scr_stat* scp, int x, int y, int on)
+{
+ vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8);
+}
+
+static uint16_t bcmfb_static_window[ROW*COL];
+extern u_char dflt_font_16[];
+
+/*
+ * Update videoadapter settings after changing resolution
+ */
+static void
+bcmfb_update_margins(video_adapter_t *adp)
+{
+ struct bcmsc_softc *sc;
+ video_info_t *vi;
+
+ sc = (struct bcmsc_softc *)adp;
+ vi = &adp->va_info;
+
+ sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2;
+}
+
+static int
+bcmfb_configure(int flags)
+{
+ char bootargs[2048], *n, *p, *v;
+ pcell_t cell;
+ phandle_t chosen, display, root;
+ struct bcmsc_softc *sc;
+
+ sc = &bcmsc;
+ if (sc->initialized)
+ return (0);
+
+ sc->width = 0;
+ sc->height = 0;
+
+ /*
+ * It seems there is no way to let syscons framework know
+ * that framebuffer resolution has changed. So just try
+ * to fetch data from FDT bootargs, FDT display data and
+ * finally go with defaults if everything else has failed.
+ */
+ chosen = OF_finddevice("/chosen");
+ if (chosen != 0 &&
+ OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) {
+ p = bootargs;
+ while ((v = strsep(&p, " ")) != NULL) {
+ if (*v == '\0')
+ continue;
+ n = strsep(&v, "=");
+ if (strcmp(n, "bcm2708_fb.fbwidth") == 0 && v != NULL)
+ sc->width = (unsigned int)strtol(v, NULL, 0);
+ else if (strcmp(n, "bcm2708_fb.fbheight") == 0 &&
+ v != NULL)
+ sc->height = (unsigned int)strtol(v, NULL, 0);
+ else if (strcmp(n, "bcm2708_fb.fbswap") == 0 &&
+ v != NULL)
+ if (*v == '1')
+ sc->fbswap = 1;
+ }
+ }
+
+ root = OF_finddevice("/");
+ if ((root != 0) &&
+ (display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) {
+ if (sc->width == 0) {
+ if ((OF_getprop(display, "broadcom,width",
+ &cell, sizeof(cell))) > 0)
+ sc->width = (int)fdt32_to_cpu(cell);
+ }
+
+ if (sc->height == 0) {
+ if ((OF_getprop(display, "broadcom,height",
+ &cell, sizeof(cell))) > 0)
+ sc->height = (int)fdt32_to_cpu(cell);
+ }
+ }
+
+ if (sc->width == 0)
+ sc->width = FB_WIDTH;
+ if (sc->height == 0)
+ sc->height = FB_HEIGHT;
+
+ bcmfb_init(0, &sc->va, 0);
+ sc->initialized = 1;
+
+ return (0);
+}
+
+static int
+bcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
+{
+
+ return (0);
+}
+
+static int
+bcmfb_init(int unit, video_adapter_t *adp, int flags)
+{
+ struct bcmsc_softc *sc;
+ video_info_t *vi;
+
+ sc = (struct bcmsc_softc *)adp;
+ vi = &adp->va_info;
+
+ vid_init_struct(adp, "bcmfb", -1, unit);
+
+ sc->font = dflt_font_16;
+ vi->vi_cheight = BCMFB_FONT_HEIGHT;
+ vi->vi_cwidth = BCMFB_FONT_WIDTH;
+ vi->vi_width = sc->width / vi->vi_cwidth;
+ vi->vi_height = sc->height / vi->vi_cheight;
+
+ /*
+ * Clamp width/height to syscons maximums
+ */
+ if (vi->vi_width > COL)
+ vi->vi_width = COL;
+ if (vi->vi_height > ROW)
+ vi->vi_height = ROW;
+
+ sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2;
+
+ adp->va_window = (vm_offset_t) bcmfb_static_window;
+ adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
+
+ vid_register(&sc->va);
+
+ return (0);
+}
+
+static int
+bcmfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
+{
+ bcopy(&adp->va_info, info, sizeof(*info));
+ return (0);
+}
+
+static int
+bcmfb_query_mode(video_adapter_t *adp, video_info_t *info)
+{
+ return (0);
+}
+
+static int
+bcmfb_set_mode(video_adapter_t *adp, int mode)
+{
+ return (0);
+}
+
+static int
+bcmfb_save_font(video_adapter_t *adp, int page, int size, int width,
+ u_char *data, int c, int count)
+{
+ return (0);
+}
+
+static int
+bcmfb_load_font(video_adapter_t *adp, int page, int size, int width,
+ u_char *data, int c, int count)
+{
+ struct bcmsc_softc *sc;
+
+ sc = (struct bcmsc_softc *)adp;
+ sc->font = data;
+
+ return (0);
+}
+
+static int
+bcmfb_show_font(video_adapter_t *adp, int page)
+{
+ return (0);
+}
+
+static int
+bcmfb_save_palette(video_adapter_t *adp, u_char *palette)
+{
+ return (0);
+}
+
+static int
+bcmfb_load_palette(video_adapter_t *adp, u_char *palette)
+{
+ return (0);
+}
+
+static int
+bcmfb_set_border(video_adapter_t *adp, int border)
+{
+ return (bcmfb_blank_display(adp, border));
+}
+
+static int
+bcmfb_save_state(video_adapter_t *adp, void *p, size_t size)
+{
+ return (0);
+}
+
+static int
+bcmfb_load_state(video_adapter_t *adp, void *p)
+{
+ return (0);
+}
+
+static int
+bcmfb_set_win_org(video_adapter_t *adp, off_t offset)
+{
+ return (0);
+}
+
+static int
+bcmfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
+{
+ *col = *row = 0;
+
+ return (0);
+}
+
+static int
+bcmfb_set_hw_cursor(video_adapter_t *adp, int col, int row)
+{
+ return (0);
+}
+
+static int
+bcmfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
+ int celsize, int blink)
+{
+ return (0);
+}
+
+static int
+bcmfb_blank_display(video_adapter_t *adp, int mode)
+{
+
+ struct bcmsc_softc *sc;
+
+ sc = (struct bcmsc_softc *)adp;
+ if (sc && sc->fb_addr)
+ memset((void*)sc->fb_addr, 0, sc->fb_size);
+
+ return (0);
+}
+
+static int
+bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int prot, vm_memattr_t *memattr)
+{
+ struct bcmsc_softc *sc;
+
+ sc = (struct bcmsc_softc *)adp;
+
+ /*
+ * This might be a legacy VGA mem request: if so, just point it at the
+ * framebuffer, since it shouldn't be touched
+ */
+ if (offset < sc->stride*sc->height) {
+ *paddr = sc->fb_paddr + offset;
+ return (0);
+ }
+
+ return (EINVAL);
+}
+
+static int
+bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
+{
+ struct bcmsc_softc *sc;
+ struct fbtype *fb;
+
+ sc = (struct bcmsc_softc *)adp;
+
+ switch (cmd) {
+ case FBIOGTYPE:
+ fb = (struct fbtype *)data;
+ fb->fb_type = FBTYPE_PCIMISC;
+ fb->fb_height = sc->height;
+ fb->fb_width = sc->width;
+ fb->fb_depth = sc->depth;
+ if (sc->depth <= 1 || sc->depth > 8)
+ fb->fb_cmsize = 0;
+ else
+ fb->fb_cmsize = 1 << sc->depth;
+ fb->fb_size = sc->fb_size;
+ break;
+ default:
+ return (fb_commonioctl(adp, cmd, data));
+ }
+
+ return (0);
+}
+
+static int
+bcmfb_clear(video_adapter_t *adp)
+{
+
+ return (bcmfb_blank_display(adp, 0));
+}
+
+static int
+bcmfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+
+ return (0);
+}
+
+static int
+bcmfb_bitblt(video_adapter_t *adp, ...)
+{
+
+ return (0);
+}
+
+static int
+bcmfb_diag(video_adapter_t *adp, int level)
+{
+
+ return (0);
+}
+
+static int
+bcmfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+bcmfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+bcmfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
+{
+
+ return (0);
+}
+
+static int
+bcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
+ int size, int bpp, int bit_ltor, int byte_ltor)
+{
+
+ return (0);
+}
+
+static int
+bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+{
+ int bytes, col, i, j, k, row;
+ struct bcmsc_softc *sc;
+ u_char *p;
+ uint8_t *addr, fg, bg, color;
+ uint16_t rgb;
+
+ sc = (struct bcmsc_softc *)adp;
+
+ if (sc->fb_addr == 0)
+ return (0);
+
+ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+ col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+ p = sc->font + c*BCMFB_FONT_HEIGHT;
+ addr = (uint8_t *)sc->fb_addr
+ + (row + sc->ymargin)*(sc->stride)
+ + (sc->depth/8) * (col + sc->xmargin);
+
+ fg = a & 0xf ;
+ bg = (a >> 4) & 0xf;
+
+ bytes = sc->depth / 8;
+ for (i = 0; i < BCMFB_FONT_HEIGHT; i++) {
+ for (j = 0, k = 7; j < 8; j++, k--) {
+ if ((p[i] & (1 << k)) == 0)
+ color = bg;
+ else
+ color = fg;
+
+ switch (sc->depth) {
+ case 32:
+ case 24:
+ if (sc->fbswap) {
+ addr[bytes * j + 0] =
+ bcmfb_palette[color].b;
+ addr[bytes * j + 1] =
+ bcmfb_palette[color].g;
+ addr[bytes * j + 2] =
+ bcmfb_palette[color].r;
+ } else {
+ addr[bytes * j + 0] =
+ bcmfb_palette[color].r;
+ addr[bytes * j + 1] =
+ bcmfb_palette[color].g;
+ addr[bytes * j + 2] =
+ bcmfb_palette[color].b;
+ }
+ if (sc->depth == 32)
+ addr[bytes * j + 3] =
+ bcmfb_palette[color].a;
+ break;
+ case 16:
+ rgb = (bcmfb_palette[color].r >> 3) << 11;
+ rgb |= (bcmfb_palette[color].g >> 2) << 5;
+ rgb |= (bcmfb_palette[color].b >> 3);
+ addr[bytes * j] = rgb & 0xff;
+ addr[bytes * j + 1] = (rgb >> 8) & 0xff;
+ default:
+ /* Not supported yet */
+ break;
+ }
+ }
+
+ addr += (sc->stride);
+ }
+
+ return (0);
+}
+
+static int
+bcmfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ bcmfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
+
+ return (0);
+}
+
+static int
+bcmfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+ uint32_t pixel_mask, int size, int width)
+{
+
+ return (0);
+}
+
+/*
+ * Define a stub keyboard driver in case one hasn't been
+ * compiled into the kernel
+ */
+#include <sys/kbio.h>
+#include <dev/kbd/kbdreg.h>
+
+static int dummy_kbd_configure(int flags);
+
+keyboard_switch_t bcmdummysw;
+
+static int
+dummy_kbd_configure(int flags)
+{
+
+ return (0);
+}
+KEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_fb.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_fbd.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_fbd.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,278 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_fbd.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/fbio.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/vt/vt.h>
+#include <dev/vt/colors/vt_termcolors.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
+
+#include "fb_if.h"
+#include "mbox_if.h"
+
+#define FB_DEPTH 24
+
+struct bcmsc_softc {
+ struct fb_info info;
+ int fbswap;
+ struct bcm2835_fb_config fb;
+ device_t dev;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-fb", 1},
+ {"brcm,bcm2708-fb", 1},
+ {NULL, 0}
+};
+
+static int bcm_fb_probe(device_t);
+static int bcm_fb_attach(device_t);
+
+static int
+bcm_fb_init(struct bcmsc_softc *sc, struct bcm2835_fb_config *fb)
+{
+ int err;
+
+ err = 0;
+
+ memset(fb, 0, sizeof(*fb));
+ if (bcm2835_mbox_fb_get_w_h(fb) != 0)
+ return (ENXIO);
+ fb->bpp = FB_DEPTH;
+
+ fb->vxres = fb->xres;
+ fb->vyres = fb->yres;
+ fb->xoffset = fb->yoffset = 0;
+
+ if ((err = bcm2835_mbox_fb_init(fb)) != 0) {
+ device_printf(sc->dev, "bcm2835_mbox_fb_init failed, err=%d\n", err);
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+bcm_fb_setup_fbd(struct bcmsc_softc *sc)
+{
+ struct bcm2835_fb_config fb;
+ device_t fbd;
+ int err;
+
+ err = bcm_fb_init(sc, &fb);
+ if (err)
+ return (err);
+
+ memset(&sc->info, 0, sizeof(sc->info));
+ sc->info.fb_name = device_get_nameunit(sc->dev);
+
+ sc->info.fb_vbase = (intptr_t)pmap_mapdev(fb.base, fb.size);
+ sc->info.fb_pbase = fb.base;
+ sc->info.fb_size = fb.size;
+ sc->info.fb_bpp = sc->info.fb_depth = fb.bpp;
+ sc->info.fb_stride = fb.pitch;
+ sc->info.fb_width = fb.xres;
+ sc->info.fb_height = fb.yres;
+#ifdef VM_MEMATTR_WRITE_COMBINING
+ sc->info.fb_flags = FB_FLAG_MEMATTR;
+ sc->info.fb_memattr = VM_MEMATTR_WRITE_COMBINING;
+#endif
+
+ if (sc->fbswap) {
+ switch (sc->info.fb_bpp) {
+ case 24:
+ vt_generate_cons_palette(sc->info.fb_cmap,
+ COLOR_FORMAT_RGB, 0xff, 0, 0xff, 8, 0xff, 16);
+ sc->info.fb_cmsize = 16;
+ break;
+ case 32:
+ vt_generate_cons_palette(sc->info.fb_cmap,
+ COLOR_FORMAT_RGB, 0xff, 16, 0xff, 8, 0xff, 0);
+ sc->info.fb_cmsize = 16;
+ break;
+ }
+ }
+
+ fbd = device_add_child(sc->dev, "fbd", device_get_unit(sc->dev));
+ if (fbd == NULL) {
+ device_printf(sc->dev, "Failed to add fbd child\n");
+ pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size);
+ return (ENXIO);
+ } else if (device_probe_and_attach(fbd) != 0) {
+ device_printf(sc->dev, "Failed to attach fbd device\n");
+ device_delete_child(sc->dev, fbd);
+ pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size);
+ return (ENXIO);
+ }
+
+ device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres,
+ fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp);
+ device_printf(sc->dev,
+ "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n",
+ sc->fbswap, fb.pitch, fb.base, fb.size);
+
+ return (0);
+}
+
+static int
+bcm_fb_resync_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct bcmsc_softc *sc = arg1;
+ struct bcm2835_fb_config fb;
+ int val;
+ int err;
+
+ val = 0;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ bcm_fb_init(sc, &fb);
+
+ return (0);
+}
+
+static void
+bcm_fb_sysctl_init(struct bcmsc_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree_node;
+ struct sysctl_oid_list *tree;
+
+ /*
+ * Add system sysctl tree/handlers.
+ */
+ ctx = device_get_sysctl_ctx(sc->dev);
+ tree_node = device_get_sysctl_tree(sc->dev);
+ tree = SYSCTL_CHILDREN(tree_node);
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "resync",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_fb_resync_sysctl, "IU", "Set to resync framebuffer with VC");
+}
+
+static int
+bcm_fb_probe(device_t dev)
+{
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2835 VT framebuffer driver");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_fb_attach(device_t dev)
+{
+ char bootargs[2048], *n, *p, *v;
+ int err;
+ phandle_t chosen;
+ struct bcmsc_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ /* Newer firmware versions needs an inverted color palette. */
+ sc->fbswap = 0;
+ chosen = OF_finddevice("/chosen");
+ if (chosen != 0 &&
+ OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) {
+ p = bootargs;
+ while ((v = strsep(&p, " ")) != NULL) {
+ if (*v == '\0')
+ continue;
+ n = strsep(&v, "=");
+ if (strcmp(n, "bcm2708_fb.fbswap") == 0 && v != NULL)
+ if (*v == '1')
+ sc->fbswap = 1;
+ }
+ }
+
+ bcm_fb_sysctl_init(sc);
+
+ err = bcm_fb_setup_fbd(sc);
+ if (err)
+ return (err);
+
+ return (0);
+}
+
+static struct fb_info *
+bcm_fb_helper_getinfo(device_t dev)
+{
+ struct bcmsc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (&sc->info);
+}
+
+static device_method_t bcm_fb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bcm_fb_probe),
+ DEVMETHOD(device_attach, bcm_fb_attach),
+
+ /* Framebuffer service methods */
+ DEVMETHOD(fb_getinfo, bcm_fb_helper_getinfo),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm_fb_devclass;
+
+static driver_t bcm_fb_driver = {
+ "fb",
+ bcm_fb_methods,
+ sizeof(struct bcmsc_softc),
+};
+
+DRIVER_MODULE(bcm2835fb, ofwbus, bcm_fb_driver, bcm_fb_devclass, 0, 0);
+DRIVER_MODULE(bcm2835fb, simplebus, bcm_fb_driver, bcm_fb_devclass, 0, 0);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,787 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012 Luiz Otavio O Souza.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_gpio.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_gpio.h>
+
+#include "gpio_if.h"
+
+#ifdef DEBUG
+#define dprintf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+#define BCM_GPIO_PINS 54
+#define BCM_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+ GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
+
+struct bcm_gpio_sysctl {
+ struct bcm_gpio_softc *sc;
+ uint32_t pin;
+};
+
+struct bcm_gpio_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ struct resource * sc_mem_res;
+ struct resource * sc_irq_res;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ void * sc_intrhand;
+ int sc_gpio_npins;
+ int sc_ro_npins;
+ int sc_ro_pins[BCM_GPIO_PINS];
+ struct gpio_pin sc_gpio_pins[BCM_GPIO_PINS];
+ struct bcm_gpio_sysctl sc_sysctl[BCM_GPIO_PINS];
+};
+
+enum bcm_gpio_pud {
+ BCM_GPIO_NONE,
+ BCM_GPIO_PULLDOWN,
+ BCM_GPIO_PULLUP,
+};
+
+#define BCM_GPIO_LOCK(_sc) mtx_lock(&_sc->sc_mtx)
+#define BCM_GPIO_UNLOCK(_sc) mtx_unlock(&_sc->sc_mtx)
+#define BCM_GPIO_LOCK_ASSERT(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
+
+#define BCM_GPIO_GPFSEL(_bank) 0x00 + _bank * 4
+#define BCM_GPIO_GPSET(_bank) 0x1c + _bank * 4
+#define BCM_GPIO_GPCLR(_bank) 0x28 + _bank * 4
+#define BCM_GPIO_GPLEV(_bank) 0x34 + _bank * 4
+#define BCM_GPIO_GPPUD(_bank) 0x94
+#define BCM_GPIO_GPPUDCLK(_bank) 0x98 + _bank * 4
+
+#define BCM_GPIO_WRITE(_sc, _off, _val) \
+ bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
+#define BCM_GPIO_READ(_sc, _off) \
+ bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-gpio", 1},
+ {"brcm,bcm2835-gpio", 1},
+ {NULL, 0}
+};
+
+static int
+bcm_gpio_pin_is_ro(struct bcm_gpio_softc *sc, int pin)
+{
+ int i;
+
+ for (i = 0; i < sc->sc_ro_npins; i++)
+ if (pin == sc->sc_ro_pins[i])
+ return (1);
+ return (0);
+}
+
+static uint32_t
+bcm_gpio_get_function(struct bcm_gpio_softc *sc, uint32_t pin)
+{
+ uint32_t bank, func, offset;
+
+ /* Five banks, 10 pins per bank, 3 bits per pin. */
+ bank = pin / 10;
+ offset = (pin - bank * 10) * 3;
+
+ BCM_GPIO_LOCK(sc);
+ func = (BCM_GPIO_READ(sc, BCM_GPIO_GPFSEL(bank)) >> offset) & 7;
+ BCM_GPIO_UNLOCK(sc);
+
+ return (func);
+}
+
+static void
+bcm_gpio_func_str(uint32_t nfunc, char *buf, int bufsize)
+{
+
+ switch (nfunc) {
+ case BCM_GPIO_INPUT:
+ strncpy(buf, "input", bufsize);
+ break;
+ case BCM_GPIO_OUTPUT:
+ strncpy(buf, "output", bufsize);
+ break;
+ case BCM_GPIO_ALT0:
+ strncpy(buf, "alt0", bufsize);
+ break;
+ case BCM_GPIO_ALT1:
+ strncpy(buf, "alt1", bufsize);
+ break;
+ case BCM_GPIO_ALT2:
+ strncpy(buf, "alt2", bufsize);
+ break;
+ case BCM_GPIO_ALT3:
+ strncpy(buf, "alt3", bufsize);
+ break;
+ case BCM_GPIO_ALT4:
+ strncpy(buf, "alt4", bufsize);
+ break;
+ case BCM_GPIO_ALT5:
+ strncpy(buf, "alt5", bufsize);
+ break;
+ default:
+ strncpy(buf, "invalid", bufsize);
+ }
+}
+
+static int
+bcm_gpio_str_func(char *func, uint32_t *nfunc)
+{
+
+ if (strcasecmp(func, "input") == 0)
+ *nfunc = BCM_GPIO_INPUT;
+ else if (strcasecmp(func, "output") == 0)
+ *nfunc = BCM_GPIO_OUTPUT;
+ else if (strcasecmp(func, "alt0") == 0)
+ *nfunc = BCM_GPIO_ALT0;
+ else if (strcasecmp(func, "alt1") == 0)
+ *nfunc = BCM_GPIO_ALT1;
+ else if (strcasecmp(func, "alt2") == 0)
+ *nfunc = BCM_GPIO_ALT2;
+ else if (strcasecmp(func, "alt3") == 0)
+ *nfunc = BCM_GPIO_ALT3;
+ else if (strcasecmp(func, "alt4") == 0)
+ *nfunc = BCM_GPIO_ALT4;
+ else if (strcasecmp(func, "alt5") == 0)
+ *nfunc = BCM_GPIO_ALT5;
+ else
+ return (-1);
+
+ return (0);
+}
+
+static uint32_t
+bcm_gpio_func_flag(uint32_t nfunc)
+{
+
+ switch (nfunc) {
+ case BCM_GPIO_INPUT:
+ return (GPIO_PIN_INPUT);
+ case BCM_GPIO_OUTPUT:
+ return (GPIO_PIN_OUTPUT);
+ }
+ return (0);
+}
+
+static void
+bcm_gpio_set_function(struct bcm_gpio_softc *sc, uint32_t pin, uint32_t f)
+{
+ uint32_t bank, data, offset;
+
+ /* Must be called with lock held. */
+ BCM_GPIO_LOCK_ASSERT(sc);
+
+ /* Five banks, 10 pins per bank, 3 bits per pin. */
+ bank = pin / 10;
+ offset = (pin - bank * 10) * 3;
+
+ data = BCM_GPIO_READ(sc, BCM_GPIO_GPFSEL(bank));
+ data &= ~(7 << offset);
+ data |= (f << offset);
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPFSEL(bank), data);
+}
+
+static void
+bcm_gpio_set_pud(struct bcm_gpio_softc *sc, uint32_t pin, uint32_t state)
+{
+ uint32_t bank, offset;
+
+ /* Must be called with lock held. */
+ BCM_GPIO_LOCK_ASSERT(sc);
+
+ bank = pin / 32;
+ offset = pin - 32 * bank;
+
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUD(0), state);
+ DELAY(10);
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), (1 << offset));
+ DELAY(10);
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUD(0), 0);
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), 0);
+}
+
+void
+bcm_gpio_set_alternate(device_t dev, uint32_t pin, uint32_t nfunc)
+{
+ struct bcm_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ BCM_GPIO_LOCK(sc);
+
+ /* Disable pull-up or pull-down on pin. */
+ bcm_gpio_set_pud(sc, pin, BCM_GPIO_NONE);
+
+ /* And now set the pin function. */
+ bcm_gpio_set_function(sc, pin, nfunc);
+
+ /* Update the pin flags. */
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+ if (i < sc->sc_gpio_npins)
+ sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(nfunc);
+
+ BCM_GPIO_UNLOCK(sc);
+}
+
+static void
+bcm_gpio_pin_configure(struct bcm_gpio_softc *sc, struct gpio_pin *pin,
+ unsigned int flags)
+{
+
+ BCM_GPIO_LOCK(sc);
+
+ /*
+ * Manage input/output.
+ */
+ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
+ pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
+ if (flags & GPIO_PIN_OUTPUT) {
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+ bcm_gpio_set_function(sc, pin->gp_pin,
+ BCM_GPIO_OUTPUT);
+ } else {
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ bcm_gpio_set_function(sc, pin->gp_pin,
+ BCM_GPIO_INPUT);
+ }
+ }
+
+ /* Manage Pull-up/pull-down. */
+ pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
+ if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
+ if (flags & GPIO_PIN_PULLUP) {
+ pin->gp_flags |= GPIO_PIN_PULLUP;
+ bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLUP);
+ } else {
+ pin->gp_flags |= GPIO_PIN_PULLDOWN;
+ bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLDOWN);
+ }
+ } else
+ bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_NONE);
+
+ BCM_GPIO_UNLOCK(sc);
+}
+
+static int
+bcm_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = BCM_GPIO_PINS - 1;
+ return (0);
+}
+
+static int
+bcm_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct bcm_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ BCM_GPIO_LOCK(sc);
+ *caps = sc->sc_gpio_pins[i].gp_caps;
+ BCM_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct bcm_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ BCM_GPIO_LOCK(sc);
+ *flags = sc->sc_gpio_pins[i].gp_flags;
+ BCM_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct bcm_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ BCM_GPIO_LOCK(sc);
+ memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME);
+ BCM_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct bcm_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ /* We never touch on read-only/reserved pins. */
+ if (bcm_gpio_pin_is_ro(sc, pin))
+ return (EINVAL);
+
+ bcm_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
+
+ return (0);
+}
+
+static int
+bcm_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct bcm_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, offset;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ /* We never write to read-only/reserved pins. */
+ if (bcm_gpio_pin_is_ro(sc, pin))
+ return (EINVAL);
+
+ bank = pin / 32;
+ offset = pin - 32 * bank;
+
+ BCM_GPIO_LOCK(sc);
+ if (value)
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPSET(bank), (1 << offset));
+ else
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPCLR(bank), (1 << offset));
+ BCM_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct bcm_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, offset, reg_data;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ bank = pin / 32;
+ offset = pin - 32 * bank;
+
+ BCM_GPIO_LOCK(sc);
+ reg_data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
+ BCM_GPIO_UNLOCK(sc);
+ *val = (reg_data & (1 << offset)) ? 1 : 0;
+
+ return (0);
+}
+
+static int
+bcm_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct bcm_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, data, offset;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ /* We never write to read-only/reserved pins. */
+ if (bcm_gpio_pin_is_ro(sc, pin))
+ return (EINVAL);
+
+ bank = pin / 32;
+ offset = pin - 32 * bank;
+
+ BCM_GPIO_LOCK(sc);
+ data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
+ if (data & (1 << offset))
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPCLR(bank), (1 << offset));
+ else
+ BCM_GPIO_WRITE(sc, BCM_GPIO_GPSET(bank), (1 << offset));
+ BCM_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_gpio_func_proc(SYSCTL_HANDLER_ARGS)
+{
+ char buf[16];
+ struct bcm_gpio_softc *sc;
+ struct bcm_gpio_sysctl *sc_sysctl;
+ uint32_t nfunc;
+ int error;
+
+ sc_sysctl = arg1;
+ sc = sc_sysctl->sc;
+
+ /* Get the current pin function. */
+ nfunc = bcm_gpio_get_function(sc, sc_sysctl->pin);
+ bcm_gpio_func_str(nfunc, buf, sizeof(buf));
+
+ error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ /* Ignore changes on read-only pins. */
+ if (bcm_gpio_pin_is_ro(sc, sc_sysctl->pin))
+ return (0);
+ /* Parse the user supplied string and check for a valid pin function. */
+ if (bcm_gpio_str_func(buf, &nfunc) != 0)
+ return (EINVAL);
+
+ /* Update the pin alternate function. */
+ bcm_gpio_set_alternate(sc->sc_dev, sc_sysctl->pin, nfunc);
+
+ return (0);
+}
+
+static void
+bcm_gpio_sysctl_init(struct bcm_gpio_softc *sc)
+{
+ char pinbuf[3];
+ struct bcm_gpio_sysctl *sc_sysctl;
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree_node, *pin_node, *pinN_node;
+ struct sysctl_oid_list *tree, *pin_tree, *pinN_tree;
+ int i;
+
+ /*
+ * Add per-pin sysctl tree/handlers.
+ */
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ tree_node = device_get_sysctl_tree(sc->sc_dev);
+ tree = SYSCTL_CHILDREN(tree_node);
+ pin_node = SYSCTL_ADD_NODE(ctx, tree, OID_AUTO, "pin",
+ CTLFLAG_RD, NULL, "GPIO Pins");
+ pin_tree = SYSCTL_CHILDREN(pin_node);
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+
+ snprintf(pinbuf, sizeof(pinbuf), "%d", i);
+ pinN_node = SYSCTL_ADD_NODE(ctx, pin_tree, OID_AUTO, pinbuf,
+ CTLFLAG_RD, NULL, "GPIO Pin");
+ pinN_tree = SYSCTL_CHILDREN(pinN_node);
+
+ sc->sc_sysctl[i].sc = sc;
+ sc_sysctl = &sc->sc_sysctl[i];
+ sc_sysctl->sc = sc;
+ sc_sysctl->pin = sc->sc_gpio_pins[i].gp_pin;
+ SYSCTL_ADD_PROC(ctx, pinN_tree, OID_AUTO, "function",
+ CTLFLAG_RW | CTLTYPE_STRING, sc_sysctl,
+ sizeof(struct bcm_gpio_sysctl), bcm_gpio_func_proc,
+ "A", "Pin Function");
+ }
+}
+
+static int
+bcm_gpio_get_ro_pins(struct bcm_gpio_softc *sc, phandle_t node,
+ const char *propname, const char *label)
+{
+ int i, need_comma, npins, range_start, range_stop;
+ pcell_t *pins;
+
+ /* Get the property data. */
+ npins = OF_getencprop_alloc(node, propname, sizeof(*pins),
+ (void **)&pins);
+ if (npins < 0)
+ return (-1);
+ if (npins == 0) {
+ free(pins, M_OFWPROP);
+ return (0);
+ }
+ for (i = 0; i < npins; i++)
+ sc->sc_ro_pins[i + sc->sc_ro_npins] = pins[i];
+ sc->sc_ro_npins += npins;
+ need_comma = 0;
+ device_printf(sc->sc_dev, "%s pins: ", label);
+ range_start = range_stop = pins[0];
+ for (i = 1; i < npins; i++) {
+ if (pins[i] != range_stop + 1) {
+ if (need_comma)
+ printf(",");
+ if (range_start != range_stop)
+ printf("%d-%d", range_start, range_stop);
+ else
+ printf("%d", range_start);
+ range_start = range_stop = pins[i];
+ need_comma = 1;
+ } else
+ range_stop++;
+ }
+ if (need_comma)
+ printf(",");
+ if (range_start != range_stop)
+ printf("%d-%d.\n", range_start, range_stop);
+ else
+ printf("%d.\n", range_start);
+ free(pins, M_OFWPROP);
+
+ return (0);
+}
+
+static int
+bcm_gpio_get_reserved_pins(struct bcm_gpio_softc *sc)
+{
+ char *name;
+ phandle_t gpio, node, reserved;
+ ssize_t len;
+
+ /* Get read-only pins if they're provided */
+ gpio = ofw_bus_get_node(sc->sc_dev);
+ if (bcm_gpio_get_ro_pins(sc, gpio, "broadcom,read-only",
+ "read-only") != 0)
+ return (0);
+ /* Traverse the GPIO subnodes to find the reserved pins node. */
+ reserved = 0;
+ node = OF_child(gpio);
+ while ((node != 0) && (reserved == 0)) {
+ len = OF_getprop_alloc(node, "name", 1, (void **)&name);
+ if (len == -1)
+ return (-1);
+ if (strcmp(name, "reserved") == 0)
+ reserved = node;
+ free(name, M_OFWPROP);
+ node = OF_peer(node);
+ }
+ if (reserved == 0)
+ return (-1);
+ /* Get the reserved pins. */
+ if (bcm_gpio_get_ro_pins(sc, reserved, "broadcom,pins",
+ "reserved") != 0)
+ return (-1);
+
+ return (0);
+}
+
+static int
+bcm_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2708/2835 GPIO controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_gpio_attach(device_t dev)
+{
+ struct bcm_gpio_softc *sc = device_get_softc(dev);
+ uint32_t func;
+ int i, j, rid;
+ phandle_t gpio;
+
+ sc->sc_dev = dev;
+
+ mtx_init(&sc->sc_mtx, "bcm gpio", "gpio", MTX_DEF);
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ /* Find our node. */
+ gpio = ofw_bus_get_node(sc->sc_dev);
+
+ if (!OF_hasprop(gpio, "gpio-controller"))
+ /* Node is not a GPIO controller. */
+ goto fail;
+
+ /*
+ * Find the read-only pins. These are pins we never touch or bad
+ * things could happen.
+ */
+ if (bcm_gpio_get_reserved_pins(sc) == -1)
+ goto fail;
+
+ /* Initialize the software controlled pins. */
+ for (i = 0, j = 0; j < BCM_GPIO_PINS; j++) {
+ snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
+ "pin %d", j);
+ func = bcm_gpio_get_function(sc, j);
+ sc->sc_gpio_pins[i].gp_pin = j;
+ sc->sc_gpio_pins[i].gp_caps = BCM_GPIO_DEFAULT_CAPS;
+ sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(func);
+ i++;
+ }
+ sc->sc_gpio_npins = i;
+
+ bcm_gpio_sysctl_init(sc);
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+
+fail:
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ return (ENXIO);
+}
+
+static int
+bcm_gpio_detach(device_t dev)
+{
+
+ return (EBUSY);
+}
+
+static phandle_t
+bcm_gpio_get_node(device_t bus, device_t dev)
+{
+
+ /* We only have one child, the GPIO bus, which needs our own node. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t bcm_gpio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bcm_gpio_probe),
+ DEVMETHOD(device_attach, bcm_gpio_attach),
+ DEVMETHOD(device_detach, bcm_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, bcm_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, bcm_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, bcm_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, bcm_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, bcm_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, bcm_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, bcm_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, bcm_gpio_pin_toggle),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, bcm_gpio_get_node),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm_gpio_devclass;
+
+static driver_t bcm_gpio_driver = {
+ "gpio",
+ bcm_gpio_methods,
+ sizeof(struct bcm_gpio_softc),
+};
+
+DRIVER_MODULE(bcm_gpio, simplebus, bcm_gpio_driver, bcm_gpio_devclass, 0, 0);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,45 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at bluezbox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_gpio.h 255370 2013-09-07 18:48:15Z loos $
+ */
+
+#ifndef _BCM2835_GPIO_H_
+#define _BCM2835_GPIO_H_
+
+enum bcm_gpio_fsel {
+ BCM_GPIO_INPUT,
+ BCM_GPIO_OUTPUT,
+ BCM_GPIO_ALT5,
+ BCM_GPIO_ALT4,
+ BCM_GPIO_ALT0,
+ BCM_GPIO_ALT1,
+ BCM_GPIO_ALT2,
+ BCM_GPIO_ALT3,
+};
+
+void bcm_gpio_set_alternate(device_t, uint32_t, uint32_t);
+
+#endif /* _BCM2835_GPIO_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_gpio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_intr.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_intr.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_intr.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,243 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Based on OMAP3 INTC code by Ben Gray
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_intr.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#ifdef SOC_BCM2836
+#include <arm/broadcom/bcm2835/bcm2836.h>
+#endif
+
+#define INTC_PENDING_BASIC 0x00
+#define INTC_PENDING_BANK1 0x04
+#define INTC_PENDING_BANK2 0x08
+#define INTC_FIQ_CONTROL 0x0C
+#define INTC_ENABLE_BANK1 0x10
+#define INTC_ENABLE_BANK2 0x14
+#define INTC_ENABLE_BASIC 0x18
+#define INTC_DISABLE_BANK1 0x1C
+#define INTC_DISABLE_BANK2 0x20
+#define INTC_DISABLE_BASIC 0x24
+
+#define BANK1_START 8
+#define BANK1_END (BANK1_START + 32 - 1)
+#define BANK2_START (BANK1_START + 32)
+#define BANK2_END (BANK2_START + 32 - 1)
+#define BANK3_START (BANK2_START + 32)
+#define BANK3_END (BANK3_START + 32 - 1)
+
+#define IS_IRQ_BASIC(n) (((n) >= 0) && ((n) < BANK1_START))
+#define IS_IRQ_BANK1(n) (((n) >= BANK1_START) && ((n) <= BANK1_END))
+#define IS_IRQ_BANK2(n) (((n) >= BANK2_START) && ((n) <= BANK2_END))
+#define ID_IRQ_BCM2836(n) (((n) >= BANK3_START) && ((n) <= BANK3_END))
+#define IRQ_BANK1(n) ((n) - BANK1_START)
+#define IRQ_BANK2(n) ((n) - BANK2_START)
+
+#ifdef DEBUG
+#define dprintf(fmt, args...) printf(fmt, ##args)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+struct bcm_intc_softc {
+ device_t sc_dev;
+ struct resource * intc_res;
+ bus_space_tag_t intc_bst;
+ bus_space_handle_t intc_bsh;
+};
+
+static struct bcm_intc_softc *bcm_intc_sc = NULL;
+
+#define intc_read_4(_sc, reg) \
+ bus_space_read_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg))
+#define intc_write_4(_sc, reg, val) \
+ bus_space_write_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg), (val))
+
+static int
+bcm_intc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-armctrl-ic") &&
+ !ofw_bus_is_compatible(dev, "brcm,bcm2836-armctrl-ic"))
+ return (ENXIO);
+ device_set_desc(dev, "BCM2835 Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_intc_attach(device_t dev)
+{
+ struct bcm_intc_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ sc->sc_dev = dev;
+
+ if (bcm_intc_sc)
+ return (ENXIO);
+
+ sc->intc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->intc_res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->intc_bst = rman_get_bustag(sc->intc_res);
+ sc->intc_bsh = rman_get_bushandle(sc->intc_res);
+
+ bcm_intc_sc = sc;
+
+ return (0);
+}
+
+static device_method_t bcm_intc_methods[] = {
+ DEVMETHOD(device_probe, bcm_intc_probe),
+ DEVMETHOD(device_attach, bcm_intc_attach),
+ { 0, 0 }
+};
+
+static driver_t bcm_intc_driver = {
+ "intc",
+ bcm_intc_methods,
+ sizeof(struct bcm_intc_softc),
+};
+
+static devclass_t bcm_intc_devclass;
+
+EARLY_DRIVER_MODULE(intc, simplebus, bcm_intc_driver, bcm_intc_devclass,
+ 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
+
+int
+arm_get_next_irq(int last_irq)
+{
+ struct bcm_intc_softc *sc = bcm_intc_sc;
+ uint32_t pending;
+ int32_t irq = last_irq + 1;
+#ifdef SOC_BCM2836
+ int ret;
+#endif
+
+ /* Sanity check */
+ if (irq < 0)
+ irq = 0;
+
+#ifdef SOC_BCM2836
+ if ((ret = bcm2836_get_next_irq(irq)) >= 0)
+ return (ret + BANK3_START);
+#endif
+
+ /* TODO: should we mask last_irq? */
+ if (irq < BANK1_START) {
+ pending = intc_read_4(sc, INTC_PENDING_BASIC);
+ if ((pending & 0xFF) == 0) {
+ irq = BANK1_START; /* skip to next bank */
+ } else do {
+ if (pending & (1 << irq))
+ return irq;
+ irq++;
+ } while (irq < BANK1_START);
+ }
+ if (irq < BANK2_START) {
+ pending = intc_read_4(sc, INTC_PENDING_BANK1);
+ if (pending == 0) {
+ irq = BANK2_START; /* skip to next bank */
+ } else do {
+ if (pending & (1 << IRQ_BANK1(irq)))
+ return irq;
+ irq++;
+ } while (irq < BANK2_START);
+ }
+ if (irq < BANK3_START) {
+ pending = intc_read_4(sc, INTC_PENDING_BANK2);
+ if (pending != 0) do {
+ if (pending & (1 << IRQ_BANK2(irq)))
+ return irq;
+ irq++;
+ } while (irq < BANK3_START);
+ }
+ return (-1);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ struct bcm_intc_softc *sc = bcm_intc_sc;
+ dprintf("%s: %d\n", __func__, nb);
+
+ if (IS_IRQ_BASIC(nb))
+ intc_write_4(sc, INTC_DISABLE_BASIC, (1 << nb));
+ else if (IS_IRQ_BANK1(nb))
+ intc_write_4(sc, INTC_DISABLE_BANK1, (1 << IRQ_BANK1(nb)));
+ else if (IS_IRQ_BANK2(nb))
+ intc_write_4(sc, INTC_DISABLE_BANK2, (1 << IRQ_BANK2(nb)));
+#ifdef SOC_BCM2836
+ else if (ID_IRQ_BCM2836(nb))
+ bcm2836_mask_irq(nb - BANK3_START);
+#endif
+ else
+ printf("arm_mask_irq: Invalid IRQ number: %d\n", nb);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ struct bcm_intc_softc *sc = bcm_intc_sc;
+ dprintf("%s: %d\n", __func__, nb);
+
+ if (IS_IRQ_BASIC(nb))
+ intc_write_4(sc, INTC_ENABLE_BASIC, (1 << nb));
+ else if (IS_IRQ_BANK1(nb))
+ intc_write_4(sc, INTC_ENABLE_BANK1, (1 << IRQ_BANK1(nb)));
+ else if (IS_IRQ_BANK2(nb))
+ intc_write_4(sc, INTC_ENABLE_BANK2, (1 << IRQ_BANK2(nb)));
+#ifdef SOC_BCM2836
+ else if (ID_IRQ_BCM2836(nb))
+ bcm2836_unmask_irq(nb - BANK3_START);
+#endif
+ else
+ printf("arm_mask_irq: Invalid IRQ number: %d\n", nb);
+}
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_intr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_machdep.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,145 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko.
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/at91/kb920x_machdep.c, rev 45
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+#include "opt_global.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_machdep.c 322724 2017-08-20 16:52:27Z marius $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_wdog.h>
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+
+}
+
+void
+initarm_gpio_init(void)
+{
+}
+
+void
+initarm_late_init(void)
+{
+ phandle_t system;
+ pcell_t cells[2];
+ int len;
+
+ system = OF_finddevice("/system");
+ if (system != 0) {
+ len = OF_getprop(system, "linux,serial", &cells, sizeof(cells));
+ if (len > 0)
+ board_set_serial(fdt64_to_cpu(*((uint64_t *)cells)));
+
+ len = OF_getprop(system, "linux,revision", &cells, sizeof(cells));
+ if (len > 0)
+ board_set_revision(fdt32_to_cpu(*((uint32_t *)cells)));
+ }
+}
+
+#ifdef SOC_BCM2835
+/*
+ * Set up static device mappings.
+ * All on-chip peripherals exist in a 16MB range starting at 0x20000000.
+ * Map the entire range using 1MB section mappings.
+ */
+int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(0x20000000, 0x01000000);
+ return (0);
+}
+#endif
+
+#ifdef SOC_BCM2836
+static int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(0x3f000000, 0x01000000);
+ return (0);
+}
+#endif
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+void
+cpu_reset()
+{
+ bcmwd_watchdog_reset();
+ while (1);
+}
+
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,537 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_mbox.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
+#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
+
+#include "mbox_if.h"
+
+#define REG_READ 0x00
+#define REG_POL 0x10
+#define REG_SENDER 0x14
+#define REG_STATUS 0x18
+#define STATUS_FULL 0x80000000
+#define STATUS_EMPTY 0x40000000
+#define REG_CONFIG 0x1C
+#define CONFIG_DATA_IRQ 0x00000001
+#define REG_WRITE 0x20 /* This is Mailbox 1 address */
+
+#define MBOX_MSG(chan, data) (((data) & ~0xf) | ((chan) & 0xf))
+#define MBOX_CHAN(msg) ((msg) & 0xf)
+#define MBOX_DATA(msg) ((msg) & ~0xf)
+
+#define MBOX_LOCK(sc) do { \
+ mtx_lock(&(sc)->lock); \
+} while(0)
+
+#define MBOX_UNLOCK(sc) do { \
+ mtx_unlock(&(sc)->lock); \
+} while(0)
+
+#ifdef DEBUG
+#define dprintf(fmt, args...) printf(fmt, ##args)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+struct bcm_mbox_softc {
+ struct mtx lock;
+ struct resource * mem_res;
+ struct resource * irq_res;
+ void* intr_hl;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ int msg[BCM2835_MBOX_CHANS];
+ int have_message[BCM2835_MBOX_CHANS];
+ struct sx property_chan_lock;
+};
+
+#define mbox_read_4(sc, reg) \
+ bus_space_read_4((sc)->bst, (sc)->bsh, reg)
+#define mbox_write_4(sc, reg, val) \
+ bus_space_write_4((sc)->bst, (sc)->bsh, reg, val)
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-mbox", 1},
+ {"brcm,bcm2835-mbox", 1},
+ {NULL, 0}
+};
+
+static int
+bcm_mbox_read_msg(struct bcm_mbox_softc *sc, int *ochan)
+{
+ uint32_t data;
+ uint32_t msg;
+ int chan;
+
+ msg = mbox_read_4(sc, REG_READ);
+ dprintf("bcm_mbox_intr: raw data %08x\n", msg);
+ chan = MBOX_CHAN(msg);
+ data = MBOX_DATA(msg);
+ if (sc->msg[chan]) {
+ printf("bcm_mbox_intr: channel %d oveflow\n", chan);
+ return (1);
+ }
+ dprintf("bcm_mbox_intr: chan %d, data %08x\n", chan, data);
+ sc->msg[chan] = msg;
+
+ if (ochan != NULL)
+ *ochan = chan;
+
+ return (0);
+}
+
+static void
+bcm_mbox_intr(void *arg)
+{
+ struct bcm_mbox_softc *sc = arg;
+ int chan;
+
+ MBOX_LOCK(sc);
+ while (!(mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY))
+ if (bcm_mbox_read_msg(sc, &chan) == 0) {
+ sc->have_message[chan] = 1;
+ wakeup(&sc->have_message[chan]);
+ }
+ MBOX_UNLOCK(sc);
+}
+
+static int
+bcm_mbox_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2835 VideoCore Mailbox");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_mbox_attach(device_t dev)
+{
+ struct bcm_mbox_softc *sc = device_get_softc(dev);
+ int i;
+ int rid = 0;
+
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->mem_res);
+ sc->bsh = rman_get_bushandle(sc->mem_res);
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "could not allocate interrupt resource\n");
+ return (ENXIO);
+ }
+
+ /* Setup and enable the timer */
+ if (bus_setup_intr(dev, sc->irq_res, INTR_MPSAFE | INTR_TYPE_MISC,
+ NULL, bcm_mbox_intr, sc, &sc->intr_hl) != 0) {
+ bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq_res);
+ device_printf(dev, "Unable to setup the clock irq handler.\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->lock, "vcio mbox", NULL, MTX_DEF);
+ for (i = 0; i < BCM2835_MBOX_CHANS; i++) {
+ sc->msg[i] = 0;
+ sc->have_message[i] = 0;
+ }
+
+ sx_init(&sc->property_chan_lock, "mboxprop");
+
+ /* Read all pending messages */
+ while ((mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY) == 0)
+ (void)mbox_read_4(sc, REG_READ);
+
+ mbox_write_4(sc, REG_CONFIG, CONFIG_DATA_IRQ);
+
+ return (0);
+}
+
+/*
+ * Mailbox API
+ */
+static int
+bcm_mbox_write(device_t dev, int chan, uint32_t data)
+{
+ int limit = 1000;
+ struct bcm_mbox_softc *sc = device_get_softc(dev);
+
+ dprintf("bcm_mbox_write: chan %d, data %08x\n", chan, data);
+ MBOX_LOCK(sc);
+ sc->have_message[chan] = 0;
+ while ((mbox_read_4(sc, REG_STATUS) & STATUS_FULL) && --limit)
+ DELAY(5);
+ if (limit == 0) {
+ printf("bcm_mbox_write: STATUS_FULL stuck");
+ MBOX_UNLOCK(sc);
+ return (EAGAIN);
+ }
+ mbox_write_4(sc, REG_WRITE, MBOX_MSG(chan, data));
+ MBOX_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_mbox_read(device_t dev, int chan, uint32_t *data)
+{
+ struct bcm_mbox_softc *sc = device_get_softc(dev);
+ int err, read_chan;
+
+ dprintf("bcm_mbox_read: chan %d\n", chan);
+
+ err = 0;
+ MBOX_LOCK(sc);
+ if (!cold) {
+ if (sc->have_message[chan] == 0) {
+ if (mtx_sleep(&sc->have_message[chan], &sc->lock, 0,
+ "mbox", 10*hz) != 0) {
+ device_printf(dev, "timeout waiting for message on chan %d\n", chan);
+ err = ETIMEDOUT;
+ }
+ }
+ } else {
+ do {
+ /* Wait for a message */
+ while ((mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY))
+ ;
+ /* Read the message */
+ if (bcm_mbox_read_msg(sc, &read_chan) != 0) {
+ err = EINVAL;
+ goto out;
+ }
+ } while (read_chan != chan);
+ }
+ /*
+ * get data from intr handler, the same channel is never coming
+ * because of holding sc lock.
+ */
+ *data = MBOX_DATA(sc->msg[chan]);
+ sc->msg[chan] = 0;
+ sc->have_message[chan] = 0;
+out:
+ MBOX_UNLOCK(sc);
+ dprintf("bcm_mbox_read: chan %d, data %08x\n", chan, *data);
+
+ return (err);
+}
+
+static device_method_t bcm_mbox_methods[] = {
+ DEVMETHOD(device_probe, bcm_mbox_probe),
+ DEVMETHOD(device_attach, bcm_mbox_attach),
+
+ DEVMETHOD(mbox_read, bcm_mbox_read),
+ DEVMETHOD(mbox_write, bcm_mbox_write),
+
+ DEVMETHOD_END
+};
+
+static driver_t bcm_mbox_driver = {
+ "mbox",
+ bcm_mbox_methods,
+ sizeof(struct bcm_mbox_softc),
+};
+
+static devclass_t bcm_mbox_devclass;
+
+DRIVER_MODULE(mbox, simplebus, bcm_mbox_driver, bcm_mbox_devclass, 0, 0);
+
+static void
+bcm2835_mbox_dma_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+ addr = (bus_addr_t *)arg;
+ *addr = PHYS_TO_VCBUS(segs[0].ds_addr);
+}
+
+static void *
+bcm2835_mbox_init_dma(device_t dev, size_t len, bus_dma_tag_t *tag,
+ bus_dmamap_t *map, bus_addr_t *phys)
+{
+ void *buf;
+ int err;
+
+ err = bus_dma_tag_create(bus_get_dma_tag(dev), 16, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ len, 1, len, 0, NULL, NULL, tag);
+ if (err != 0) {
+ device_printf(dev, "can't create DMA tag\n");
+ return (NULL);
+ }
+
+ err = bus_dmamem_alloc(*tag, &buf, 0, map);
+ if (err != 0) {
+ bus_dma_tag_destroy(*tag);
+ device_printf(dev, "can't allocate dmamem\n");
+ return (NULL);
+ }
+
+ err = bus_dmamap_load(*tag, *map, buf, len, bcm2835_mbox_dma_cb,
+ phys, 0);
+ if (err != 0) {
+ bus_dmamem_free(*tag, buf, *map);
+ bus_dma_tag_destroy(*tag);
+ device_printf(dev, "can't load DMA map\n");
+ return (NULL);
+ }
+
+ return (buf);
+}
+
+static int
+bcm2835_mbox_err(device_t dev, bus_addr_t msg_phys, uint32_t resp_phys,
+ struct bcm2835_mbox_hdr *msg, size_t len)
+{
+ int idx;
+ struct bcm2835_mbox_tag_hdr *tag;
+ uint8_t *last;
+
+ if ((uint32_t)msg_phys != resp_phys) {
+ device_printf(dev, "response channel mismatch\n");
+ return (EIO);
+ }
+ if (msg->code != BCM2835_MBOX_CODE_RESP_SUCCESS) {
+ device_printf(dev, "mbox response error\n");
+ return (EIO);
+ }
+
+ /* Loop until the end tag. */
+ tag = (struct bcm2835_mbox_tag_hdr *)(msg + 1);
+ last = (uint8_t *)msg + len;
+ for (idx = 0; tag->tag != 0; idx++) {
+ if ((tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) == 0) {
+ device_printf(dev, "tag %d response error\n", idx);
+ return (EIO);
+ }
+ /* Clear the response bit. */
+ tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
+
+ /* Next tag. */
+ tag = (struct bcm2835_mbox_tag_hdr *)((uint8_t *)tag +
+ sizeof(*tag) + tag->val_buf_size);
+
+ if ((uint8_t *)tag > last) {
+ device_printf(dev, "mbox buffer size error\n");
+ return (EIO);
+ }
+ }
+
+ return (0);
+}
+
+int
+bcm2835_mbox_property(void *msg, size_t msg_size)
+{
+ struct bcm_mbox_softc *sc;
+ struct msg_set_power_state *buf;
+ bus_dma_tag_t msg_tag;
+ bus_dmamap_t msg_map;
+ bus_addr_t msg_phys;
+ uint32_t reg;
+ device_t mbox;
+ int err;
+
+ /* get mbox device */
+ mbox = devclass_get_device(devclass_find("mbox"), 0);
+ if (mbox == NULL)
+ return (ENXIO);
+
+ sc = device_get_softc(mbox);
+ sx_xlock(&sc->property_chan_lock);
+
+ /* Allocate memory for the message */
+ buf = bcm2835_mbox_init_dma(mbox, msg_size, &msg_tag, &msg_map,
+ &msg_phys);
+ if (buf == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ memcpy(buf, msg, msg_size);
+
+ bus_dmamap_sync(msg_tag, msg_map,
+ BUS_DMASYNC_PREWRITE);
+
+ MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys);
+ MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, ®);
+
+ bus_dmamap_sync(msg_tag, msg_map,
+ BUS_DMASYNC_PREREAD);
+
+ memcpy(msg, buf, msg_size);
+
+ err = bcm2835_mbox_err(mbox, msg_phys, reg,
+ (struct bcm2835_mbox_hdr *)msg, msg_size);
+
+ bus_dmamap_unload(msg_tag, msg_map);
+ bus_dmamem_free(msg_tag, buf, msg_map);
+ bus_dma_tag_destroy(msg_tag);
+out:
+ sx_xunlock(&sc->property_chan_lock);
+ return (err);
+}
+
+int
+bcm2835_mbox_set_power_state(uint32_t device_id, boolean_t on)
+{
+ struct msg_set_power_state msg;
+ int err;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_POWER_STATE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.device_id = device_id;
+ msg.body.req.state = (on ? BCM2835_MBOX_POWER_ON : 0) |
+ BCM2835_MBOX_POWER_WAIT;
+ msg.end_tag = 0;
+
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+
+ return (err);
+}
+
+int
+bcm2835_mbox_get_clock_rate(uint32_t clock_id, uint32_t *hz)
+{
+ struct msg_get_clock_rate msg;
+ int err;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_CLOCK_RATE;
+ msg.tag_hdr.val_buf_size = sizeof(msg.body);
+ msg.tag_hdr.val_len = sizeof(msg.body.req);
+ msg.body.req.clock_id = clock_id;
+ msg.end_tag = 0;
+
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ *hz = msg.body.resp.rate_hz;
+
+ return (err);
+}
+
+int
+bcm2835_mbox_fb_get_w_h(struct bcm2835_fb_config *fb)
+{
+ int err;
+ struct msg_fb_get_w_h msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ BCM2835_MBOX_INIT_TAG(&msg.physical_w_h, GET_PHYSICAL_W_H);
+ msg.physical_w_h.tag_hdr.val_len = 0;
+ msg.end_tag = 0;
+
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err == 0) {
+ fb->xres = msg.physical_w_h.body.resp.width;
+ fb->yres = msg.physical_w_h.body.resp.height;
+ }
+
+ return (err);
+}
+
+int
+bcm2835_mbox_fb_init(struct bcm2835_fb_config *fb)
+{
+ int err;
+ struct msg_fb_setup msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.buf_size = sizeof(msg);
+ msg.hdr.code = BCM2835_MBOX_CODE_REQ;
+ BCM2835_MBOX_INIT_TAG(&msg.physical_w_h, SET_PHYSICAL_W_H);
+ msg.physical_w_h.body.req.width = fb->xres;
+ msg.physical_w_h.body.req.height = fb->yres;
+ BCM2835_MBOX_INIT_TAG(&msg.virtual_w_h, SET_VIRTUAL_W_H);
+ msg.virtual_w_h.body.req.width = fb->vxres;
+ msg.virtual_w_h.body.req.height = fb->vyres;
+ BCM2835_MBOX_INIT_TAG(&msg.offset, SET_VIRTUAL_OFFSET);
+ msg.offset.body.req.x = fb->xoffset;
+ msg.offset.body.req.y = fb->yoffset;
+ BCM2835_MBOX_INIT_TAG(&msg.depth, SET_DEPTH);
+ msg.depth.body.req.bpp = fb->bpp;
+ BCM2835_MBOX_INIT_TAG(&msg.alpha, SET_ALPHA_MODE);
+ msg.alpha.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED;
+ BCM2835_MBOX_INIT_TAG(&msg.buffer, ALLOCATE_BUFFER);
+ msg.buffer.body.req.alignment = PAGE_SIZE;
+ BCM2835_MBOX_INIT_TAG(&msg.pitch, GET_PITCH);
+ msg.end_tag = 0;
+
+ err = bcm2835_mbox_property(&msg, sizeof(msg));
+ if (err == 0) {
+ fb->xres = msg.physical_w_h.body.resp.width;
+ fb->yres = msg.physical_w_h.body.resp.height;
+ fb->vxres = msg.virtual_w_h.body.resp.width;
+ fb->vyres = msg.virtual_w_h.body.resp.height;
+ fb->xoffset = msg.offset.body.resp.x;
+ fb->yoffset = msg.offset.body.resp.y;
+ fb->pitch = msg.pitch.body.resp.pitch;
+ fb->base = VCBUS_TO_PHYS(msg.buffer.body.resp.fb_address);
+ fb->size = msg.buffer.body.resp.fb_size;
+ }
+
+ return (err);
+}
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,43 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_mbox.h 278608 2015-02-12 00:25:33Z ian $
+ */
+
+#ifndef _BCM2835_MBOX_H_
+#define _BCM2835_MBOX_H_
+
+#define BCM2835_MBOX_CHAN_POWER 0
+#define BCM2835_MBOX_CHAN_FB 1
+#define BCM2835_MBOX_CHAN_VUART 2
+#define BCM2835_MBOX_CHAN_VCHIQ 3
+#define BCM2835_MBOX_CHAN_LEDS 4
+#define BCM2835_MBOX_CHAN_BUTTONS 5
+#define BCM2835_MBOX_CHAN_TS 6
+#define BCM2835_MBOX_CHAN_PROP 8
+#define BCM2835_MBOX_CHANS 9
+
+#endif /* _BCM2835_MBOX_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,479 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2013-2014 Daisuke Aoyama <aoyama at peach.ne.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h 322724 2017-08-20 16:52:27Z marius $
+ */
+
+#ifndef _BCM2835_MBOX_PROP_H_
+#define _BCM2835_MBOX_PROP_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/*
+ * Mailbox property interface:
+ * https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
+ */
+#define BCM2835_MBOX_CODE_REQ 0
+#define BCM2835_MBOX_CODE_RESP_SUCCESS 0x80000000
+#define BCM2835_MBOX_CODE_RESP_ERROR 0x80000001
+#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE 0x80000000
+
+struct bcm2835_mbox_hdr {
+ uint32_t buf_size;
+ uint32_t code;
+};
+
+struct bcm2835_mbox_tag_hdr {
+ uint32_t tag;
+ uint32_t val_buf_size;
+ uint32_t val_len;
+};
+
+#define BCM2835_MBOX_INIT_TAG(tag_, tagid_) do { \
+ (tag_)->tag_hdr.tag = BCM2835_MBOX_TAG_##tagid_; \
+ (tag_)->tag_hdr.val_buf_size = sizeof((tag_)->body); \
+ (tag_)->tag_hdr.val_len = sizeof((tag_)->body.req); \
+} while (0)
+
+#define BCM2835_MBOX_POWER_ID_EMMC 0x00000000
+#define BCM2835_MBOX_POWER_ID_UART0 0x00000001
+#define BCM2835_MBOX_POWER_ID_UART1 0x00000002
+#define BCM2835_MBOX_POWER_ID_USB_HCD 0x00000003
+#define BCM2835_MBOX_POWER_ID_I2C0 0x00000004
+#define BCM2835_MBOX_POWER_ID_I2C1 0x00000005
+#define BCM2835_MBOX_POWER_ID_I2C2 0x00000006
+#define BCM2835_MBOX_POWER_ID_SPI 0x00000007
+#define BCM2835_MBOX_POWER_ID_CCP2TX 0x00000008
+
+#define BCM2835_MBOX_POWER_ON (1 << 0)
+#define BCM2835_MBOX_POWER_WAIT (1 << 1)
+
+#define BCM2835_MBOX_TAG_GET_POWER_STATE 0x00020001
+#define BCM2835_MBOX_TAG_SET_POWER_STATE 0x00028001
+
+struct msg_get_power_state {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t device_id;
+ } req;
+ struct {
+ uint32_t device_id;
+ uint32_t state;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_set_power_state {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t device_id;
+ uint32_t state;
+ } req;
+ struct {
+ uint32_t device_id;
+ uint32_t state;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+/* Sets the power state for a given device */
+int bcm2835_mbox_set_power_state(uint32_t, boolean_t);
+
+#define BCM2835_MBOX_CLOCK_ID_EMMC 0x00000001
+#define BCM2835_MBOX_CLOCK_ID_UART 0x00000002
+#define BCM2835_MBOX_CLOCK_ID_ARM 0x00000003
+#define BCM2835_MBOX_CLOCK_ID_CORE 0x00000004
+#define BCM2835_MBOX_CLOCK_ID_V3D 0x00000005
+#define BCM2835_MBOX_CLOCK_ID_H264 0x00000006
+#define BCM2835_MBOX_CLOCK_ID_ISP 0x00000007
+#define BCM2835_MBOX_CLOCK_ID_SDRAM 0x00000008
+#define BCM2835_MBOX_CLOCK_ID_PIXEL 0x00000009
+#define BCM2835_MBOX_CLOCK_ID_PWM 0x0000000a
+
+#define BCM2835_MBOX_TAG_GET_CLOCK_RATE 0x00030002
+#define BCM2835_MBOX_TAG_SET_CLOCK_RATE 0x00038002
+#define BCM2835_MBOX_TAG_GET_MAX_CLOCK_RATE 0x00030004
+#define BCM2835_MBOX_TAG_GET_MIN_CLOCK_RATE 0x00030007
+
+struct msg_get_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t clock_id;
+ } req;
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_set_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } req;
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_max_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t clock_id;
+ } req;
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_min_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t clock_id;
+ } req;
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+int bcm2835_mbox_get_clock_rate(uint32_t, uint32_t *);
+
+#define BCM2835_MBOX_TURBO_ON 1
+#define BCM2835_MBOX_TURBO_OFF 0
+
+#define BCM2835_MBOX_TAG_GET_TURBO 0x00030009
+#define BCM2835_MBOX_TAG_SET_TURBO 0x00038009
+
+struct msg_get_turbo {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t id;
+ } req;
+ struct {
+ uint32_t id;
+ uint32_t level;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_set_turbo {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t id;
+ uint32_t level;
+ } req;
+ struct {
+ uint32_t id;
+ uint32_t level;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+#define BCM2835_MBOX_VOLTAGE_ID_CORE 0x00000001
+#define BCM2835_MBOX_VOLTAGE_ID_SDRAM_C 0x00000002
+#define BCM2835_MBOX_VOLTAGE_ID_SDRAM_P 0x00000003
+#define BCM2835_MBOX_VOLTAGE_ID_SDRAM_I 0x00000004
+
+#define BCM2835_MBOX_TAG_GET_VOLTAGE 0x00030003
+#define BCM2835_MBOX_TAG_SET_VOLTAGE 0x00038003
+#define BCM2835_MBOX_TAG_GET_MAX_VOLTAGE 0x00030005
+#define BCM2835_MBOX_TAG_GET_MIN_VOLTAGE 0x00030008
+
+struct msg_get_voltage {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t voltage_id;
+ } req;
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_set_voltage {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } req;
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_max_voltage {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t voltage_id;
+ } req;
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_min_voltage {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t voltage_id;
+ } req;
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+#define BCM2835_MBOX_TAG_GET_TEMPERATURE 0x00030006
+#define BCM2835_MBOX_TAG_GET_MAX_TEMPERATURE 0x0003000a
+
+struct msg_get_temperature {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t temperature_id;
+ } req;
+ struct {
+ uint32_t temperature_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_max_temperature {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t temperature_id;
+ } req;
+ struct {
+ uint32_t temperature_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H 0x00040003
+#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H 0x00048003
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H 0x00040004
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H 0x00048004
+
+struct bcm2835_mbox_tag_fb_w_h {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t width;
+ uint32_t height;
+ } req;
+ struct {
+ uint32_t width;
+ uint32_t height;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_DEPTH 0x00040005
+#define BCM2835_MBOX_TAG_SET_DEPTH 0x00048005
+
+struct bcm2835_mbox_tag_depth {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t bpp;
+ } req;
+ struct {
+ uint32_t bpp;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_ALPHA_MODE 0x00040007
+#define BCM2835_MBOX_TAG_SET_ALPHA_MODE 0x00048007
+
+#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE 0
+#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT 1
+#define BCM2835_MBOX_ALPHA_MODE_IGNORED 2
+
+struct bcm2835_mbox_tag_alpha_mode {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t alpha;
+ } req;
+ struct {
+ uint32_t alpha;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET 0x00040009
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET 0x00048009
+
+struct bcm2835_mbox_tag_virtual_offset {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t x;
+ uint32_t y;
+ } req;
+ struct {
+ uint32_t x;
+ uint32_t y;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PITCH 0x00040008
+
+struct bcm2835_mbox_tag_pitch {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ uint32_t pitch;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER 0x00040001
+
+struct bcm2835_mbox_tag_allocate_buffer {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t alignment;
+ } req;
+ struct {
+ uint32_t fb_address;
+ uint32_t fb_size;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_RELEASE_BUFFER 0x00048001
+
+struct bcm2835_mbox_tag_release_buffer {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ } resp;
+ } body;
+};
+
+struct bcm2835_fb_config {
+ uint32_t xres;
+ uint32_t yres;
+ uint32_t vxres;
+ uint32_t vyres;
+ uint32_t xoffset;
+ uint32_t yoffset;
+ uint32_t bpp;
+ uint32_t pitch;
+ uint32_t base;
+ uint32_t size;
+};
+
+struct msg_fb_get_w_h {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_fb_w_h physical_w_h;
+ uint32_t end_tag;
+};
+
+int bcm2835_mbox_fb_get_w_h(struct bcm2835_fb_config *);
+
+struct msg_fb_setup {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_fb_w_h physical_w_h;
+ struct bcm2835_mbox_tag_fb_w_h virtual_w_h;
+ struct bcm2835_mbox_tag_virtual_offset offset;
+ struct bcm2835_mbox_tag_depth depth;
+ struct bcm2835_mbox_tag_alpha_mode alpha;
+ struct bcm2835_mbox_tag_allocate_buffer buffer;
+ struct bcm2835_mbox_tag_pitch pitch;
+ uint32_t end_tag;
+};
+
+int bcm2835_mbox_fb_init(struct bcm2835_fb_config *);
+
+int bcm2835_mbox_property(void *, size_t);
+
+#endif /* _BCM2835_MBOX_PROP_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,683 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
+
+#include <dev/sdhci/sdhci.h>
+
+#include "mmcbr_if.h"
+#include "sdhci_if.h"
+
+#include "bcm2835_dma.h"
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
+#include "bcm2835_vcbus.h"
+
+#define BCM2835_DEFAULT_SDHCI_FREQ 50
+
+#define BCM_SDHCI_BUFFER_SIZE 512
+#define NUM_DMA_SEGS 2
+
+#ifdef DEBUG
+#define dprintf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+static int bcm2835_sdhci_hs = 1;
+static int bcm2835_sdhci_pio_mode = 0;
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-sdhci", 1},
+ {"brcm,bcm2835-mmc", 1},
+ {NULL, 0}
+};
+
+TUNABLE_INT("hw.bcm2835.sdhci.hs", &bcm2835_sdhci_hs);
+TUNABLE_INT("hw.bcm2835.sdhci.pio_mode", &bcm2835_sdhci_pio_mode);
+
+struct bcm_sdhci_softc {
+ device_t sc_dev;
+ struct resource * sc_mem_res;
+ struct resource * sc_irq_res;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ void * sc_intrhand;
+ struct mmc_request * sc_req;
+ struct sdhci_slot sc_slot;
+ int sc_dma_ch;
+ bus_dma_tag_t sc_dma_tag;
+ bus_dmamap_t sc_dma_map;
+ vm_paddr_t sc_sdhci_buffer_phys;
+ uint32_t cmd_and_mode;
+ bus_addr_t dmamap_seg_addrs[NUM_DMA_SEGS];
+ bus_size_t dmamap_seg_sizes[NUM_DMA_SEGS];
+ int dmamap_seg_count;
+ int dmamap_seg_index;
+ int dmamap_status;
+};
+
+static int bcm_sdhci_probe(device_t);
+static int bcm_sdhci_attach(device_t);
+static int bcm_sdhci_detach(device_t);
+static void bcm_sdhci_intr(void *);
+
+static int bcm_sdhci_get_ro(device_t, device_t);
+static void bcm_sdhci_dma_intr(int ch, void *arg);
+
+static void
+bcm_sdhci_dmacb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ struct bcm_sdhci_softc *sc = arg;
+ int i;
+
+ sc->dmamap_status = err;
+ sc->dmamap_seg_count = nseg;
+
+ /* Note nseg is guaranteed to be zero if err is non-zero. */
+ for (i = 0; i < nseg; i++) {
+ sc->dmamap_seg_addrs[i] = segs[i].ds_addr;
+ sc->dmamap_seg_sizes[i] = segs[i].ds_len;
+ }
+}
+
+static int
+bcm_sdhci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Broadcom 2708 SDHCI controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_sdhci_attach(device_t dev)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+ int rid, err;
+ phandle_t node;
+ pcell_t cell;
+ u_int default_freq;
+
+ sc->sc_dev = dev;
+ sc->sc_req = NULL;
+
+ err = bcm2835_mbox_set_power_state(BCM2835_MBOX_POWER_ID_EMMC,
+ TRUE);
+ if (err != 0) {
+ if (bootverbose)
+ device_printf(dev, "Unable to enable the power\n");
+ return (err);
+ }
+
+ default_freq = 0;
+ err = bcm2835_mbox_get_clock_rate(BCM2835_MBOX_CLOCK_ID_EMMC,
+ &default_freq);
+ if (err == 0) {
+ /* Convert to MHz */
+ default_freq /= 1000000;
+ }
+ if (default_freq == 0) {
+ node = ofw_bus_get_node(sc->sc_dev);
+ if ((OF_getencprop(node, "clock-frequency", &cell,
+ sizeof(cell))) > 0)
+ default_freq = cell / 1000000;
+ }
+ if (default_freq == 0)
+ default_freq = BCM2835_DEFAULT_SDHCI_FREQ;
+
+ if (bootverbose)
+ device_printf(dev, "SDHCI frequency: %dMHz\n", default_freq);
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, bcm_sdhci_intr, sc, &sc->sc_intrhand)) {
+ device_printf(dev, "cannot setup interrupt handler\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ if (!bcm2835_sdhci_pio_mode)
+ sc->sc_slot.opt = SDHCI_PLATFORM_TRANSFER;
+
+ sc->sc_slot.caps = SDHCI_CAN_VDD_330 | SDHCI_CAN_VDD_180;
+ if (bcm2835_sdhci_hs)
+ sc->sc_slot.caps |= SDHCI_CAN_DO_HISPD;
+ sc->sc_slot.caps |= (default_freq << SDHCI_CLOCK_BASE_SHIFT);
+ sc->sc_slot.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
+ | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
+ | SDHCI_QUIRK_DONT_SET_HISPD_BIT
+ | SDHCI_QUIRK_MISSING_CAPS;
+
+ sdhci_init_slot(dev, &sc->sc_slot, 0);
+
+ sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY);
+ if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
+ goto fail;
+
+ bcm_dma_setup_intr(sc->sc_dma_ch, bcm_sdhci_dma_intr, sc);
+
+ /* Allocate bus_dma resources. */
+ err = bus_dma_tag_create(bus_get_dma_tag(dev),
+ 1, 0, BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR, NULL, NULL,
+ BCM_SDHCI_BUFFER_SIZE, NUM_DMA_SEGS, BCM_SDHCI_BUFFER_SIZE,
+ BUS_DMA_ALLOCNOW, NULL, NULL,
+ &sc->sc_dma_tag);
+
+ if (err) {
+ device_printf(dev, "failed allocate DMA tag");
+ goto fail;
+ }
+
+ err = bus_dmamap_create(sc->sc_dma_tag, 0, &sc->sc_dma_map);
+ if (err) {
+ device_printf(dev, "bus_dmamap_create failed\n");
+ goto fail;
+ }
+
+ sc->sc_sdhci_buffer_phys = BUS_SPACE_PHYSADDR(sc->sc_mem_res,
+ SDHCI_BUFFER);
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ sdhci_start_slot(&sc->sc_slot);
+
+ return (0);
+
+fail:
+ if (sc->sc_intrhand)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+
+ return (err);
+}
+
+static int
+bcm_sdhci_detach(device_t dev)
+{
+
+ return (EBUSY);
+}
+
+static void
+bcm_sdhci_intr(void *arg)
+{
+ struct bcm_sdhci_softc *sc = arg;
+
+ sdhci_generic_intr(&sc->sc_slot);
+}
+
+static int
+bcm_sdhci_get_ro(device_t bus, device_t child)
+{
+
+ return (0);
+}
+
+static inline uint32_t
+RD4(struct bcm_sdhci_softc *sc, bus_size_t off)
+{
+ uint32_t val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
+ return val;
+}
+
+static inline void
+WR4(struct bcm_sdhci_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
+ /*
+ * The Arasan HC has a bug where it may lose the content of
+ * consecutive writes to registers that are within two SD-card
+ * clock cycles of each other (a clock domain crossing problem).
+ */
+ if (sc->sc_slot.clock > 0)
+ DELAY(((2 * 1000000) / sc->sc_slot.clock) + 1);
+}
+
+static uint8_t
+bcm_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val = RD4(sc, off & ~3);
+
+ return ((val >> (off & 3)*8) & 0xff);
+}
+
+static uint16_t
+bcm_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val = RD4(sc, off & ~3);
+
+ /*
+ * Standard 32-bit handling of command and transfer mode.
+ */
+ if (off == SDHCI_TRANSFER_MODE) {
+ return (sc->cmd_and_mode >> 16);
+ } else if (off == SDHCI_COMMAND_FLAGS) {
+ return (sc->cmd_and_mode & 0x0000ffff);
+ }
+ return ((val >> (off & 3)*8) & 0xffff);
+}
+
+static uint32_t
+bcm_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+
+ return RD4(sc, off);
+}
+
+static void
+bcm_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t *data, bus_size_t count)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+
+ bus_space_read_multi_4(sc->sc_bst, sc->sc_bsh, off, data, count);
+}
+
+static void
+bcm_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint8_t val)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32 = RD4(sc, off & ~3);
+ val32 &= ~(0xff << (off & 3)*8);
+ val32 |= (val << (off & 3)*8);
+ WR4(sc, off & ~3, val32);
+}
+
+static void
+bcm_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32;
+ if (off == SDHCI_COMMAND_FLAGS)
+ val32 = sc->cmd_and_mode;
+ else
+ val32 = RD4(sc, off & ~3);
+ val32 &= ~(0xffff << (off & 3)*8);
+ val32 |= (val << (off & 3)*8);
+ if (off == SDHCI_TRANSFER_MODE)
+ sc->cmd_and_mode = val32;
+ else {
+ WR4(sc, off & ~3, val32);
+ if (off == SDHCI_COMMAND_FLAGS)
+ sc->cmd_and_mode = val32;
+ }
+}
+
+static void
+bcm_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+ WR4(sc, off, val);
+}
+
+static void
+bcm_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t *data, bus_size_t count)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(dev);
+
+ bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh, off, data, count);
+}
+
+static void
+bcm_sdhci_start_dma_seg(struct bcm_sdhci_softc *sc)
+{
+ struct sdhci_slot *slot;
+ vm_paddr_t pdst, psrc;
+ int err, idx, len, sync_op;
+
+ slot = &sc->sc_slot;
+ idx = sc->dmamap_seg_index++;
+ len = sc->dmamap_seg_sizes[idx];
+ slot->offset += len;
+
+ if (slot->curcmd->data->flags & MMC_DATA_READ) {
+ bcm_dma_setup_src(sc->sc_dma_ch, BCM_DMA_DREQ_EMMC,
+ BCM_DMA_SAME_ADDR, BCM_DMA_32BIT);
+ bcm_dma_setup_dst(sc->sc_dma_ch, BCM_DMA_DREQ_NONE,
+ BCM_DMA_INC_ADDR,
+ (len & 0xf) ? BCM_DMA_32BIT : BCM_DMA_128BIT);
+ psrc = sc->sc_sdhci_buffer_phys;
+ pdst = sc->dmamap_seg_addrs[idx];
+ sync_op = BUS_DMASYNC_PREREAD;
+ } else {
+ bcm_dma_setup_src(sc->sc_dma_ch, BCM_DMA_DREQ_NONE,
+ BCM_DMA_INC_ADDR,
+ (len & 0xf) ? BCM_DMA_32BIT : BCM_DMA_128BIT);
+ bcm_dma_setup_dst(sc->sc_dma_ch, BCM_DMA_DREQ_EMMC,
+ BCM_DMA_SAME_ADDR, BCM_DMA_32BIT);
+ psrc = sc->dmamap_seg_addrs[idx];
+ pdst = sc->sc_sdhci_buffer_phys;
+ sync_op = BUS_DMASYNC_PREWRITE;
+ }
+
+ /*
+ * When starting a new DMA operation do the busdma sync operation, and
+ * disable SDCHI data interrrupts because we'll be driven by DMA
+ * interrupts (or SDHCI error interrupts) until the IO is done.
+ */
+ if (idx == 0) {
+ bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, sync_op);
+ slot->intmask &= ~(SDHCI_INT_DATA_AVAIL |
+ SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_END);
+ bcm_sdhci_write_4(sc->sc_dev, &sc->sc_slot, SDHCI_SIGNAL_ENABLE,
+ slot->intmask);
+ }
+
+ /*
+ * Start the DMA transfer. Only programming errors (like failing to
+ * allocate a channel) cause a non-zero return from bcm_dma_start().
+ */
+ err = bcm_dma_start(sc->sc_dma_ch, psrc, pdst, len);
+ KASSERT((err == 0), ("bcm2835_sdhci: failed DMA start"));
+}
+
+static void
+bcm_sdhci_dma_intr(int ch, void *arg)
+{
+ struct bcm_sdhci_softc *sc = (struct bcm_sdhci_softc *)arg;
+ struct sdhci_slot *slot = &sc->sc_slot;
+ uint32_t reg, mask;
+ int left, sync_op;
+
+ mtx_lock(&slot->mtx);
+
+ /*
+ * If there are more segments for the current dma, start the next one.
+ * Otherwise unload the dma map and decide what to do next based on the
+ * status of the sdhci controller and whether there's more data left.
+ */
+ if (sc->dmamap_seg_index < sc->dmamap_seg_count) {
+ bcm_sdhci_start_dma_seg(sc);
+ mtx_unlock(&slot->mtx);
+ return;
+ }
+
+ if (slot->curcmd->data->flags & MMC_DATA_READ) {
+ sync_op = BUS_DMASYNC_POSTREAD;
+ mask = SDHCI_INT_DATA_AVAIL;
+ } else {
+ sync_op = BUS_DMASYNC_POSTWRITE;
+ mask = SDHCI_INT_SPACE_AVAIL;
+ }
+ bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, sync_op);
+ bus_dmamap_unload(sc->sc_dma_tag, sc->sc_dma_map);
+
+ sc->dmamap_seg_count = 0;
+ sc->dmamap_seg_index = 0;
+
+ left = min(BCM_SDHCI_BUFFER_SIZE,
+ slot->curcmd->data->len - slot->offset);
+
+ /* DATA END? */
+ reg = bcm_sdhci_read_4(slot->bus, slot, SDHCI_INT_STATUS);
+
+ if (reg & SDHCI_INT_DATA_END) {
+ /* ACK for all outstanding interrupts */
+ bcm_sdhci_write_4(slot->bus, slot, SDHCI_INT_STATUS, reg);
+
+ /* enable INT */
+ slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL
+ | SDHCI_INT_DATA_END;
+ bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE,
+ slot->intmask);
+
+ /* finish this data */
+ sdhci_finish_data(slot);
+ }
+ else {
+ /* already available? */
+ if (reg & mask) {
+
+ /* ACK for DATA_AVAIL or SPACE_AVAIL */
+ bcm_sdhci_write_4(slot->bus, slot,
+ SDHCI_INT_STATUS, mask);
+
+ /* continue next DMA transfer */
+ if (bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map,
+ (uint8_t *)slot->curcmd->data->data +
+ slot->offset, left, bcm_sdhci_dmacb, sc,
+ BUS_DMA_NOWAIT) != 0 || sc->dmamap_status != 0) {
+ slot->curcmd->error = MMC_ERR_NO_MEMORY;
+ sdhci_finish_data(slot);
+ } else {
+ bcm_sdhci_start_dma_seg(sc);
+ }
+ } else {
+ /* wait for next data by INT */
+
+ /* enable INT */
+ slot->intmask |= SDHCI_INT_DATA_AVAIL |
+ SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_END;
+ bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE,
+ slot->intmask);
+ }
+ }
+
+ mtx_unlock(&slot->mtx);
+}
+
+static void
+bcm_sdhci_read_dma(device_t dev, struct sdhci_slot *slot)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(slot->bus);
+ size_t left;
+
+ if (sc->dmamap_seg_count != 0) {
+ device_printf(sc->sc_dev, "DMA in use\n");
+ return;
+ }
+
+ left = min(BCM_SDHCI_BUFFER_SIZE,
+ slot->curcmd->data->len - slot->offset);
+
+ KASSERT((left & 3) == 0,
+ ("%s: len = %d, not word-aligned", __func__, left));
+
+ if (bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map,
+ (uint8_t *)slot->curcmd->data->data + slot->offset, left,
+ bcm_sdhci_dmacb, sc, BUS_DMA_NOWAIT) != 0 ||
+ sc->dmamap_status != 0) {
+ slot->curcmd->error = MMC_ERR_NO_MEMORY;
+ return;
+ }
+
+ /* DMA start */
+ bcm_sdhci_start_dma_seg(sc);
+}
+
+static void
+bcm_sdhci_write_dma(device_t dev, struct sdhci_slot *slot)
+{
+ struct bcm_sdhci_softc *sc = device_get_softc(slot->bus);
+ size_t left;
+
+ if (sc->dmamap_seg_count != 0) {
+ device_printf(sc->sc_dev, "DMA in use\n");
+ return;
+ }
+
+ left = min(BCM_SDHCI_BUFFER_SIZE,
+ slot->curcmd->data->len - slot->offset);
+
+ KASSERT((left & 3) == 0,
+ ("%s: len = %d, not word-aligned", __func__, left));
+
+ if (bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map,
+ (uint8_t *)slot->curcmd->data->data + slot->offset, left,
+ bcm_sdhci_dmacb, sc, BUS_DMA_NOWAIT) != 0 ||
+ sc->dmamap_status != 0) {
+ slot->curcmd->error = MMC_ERR_NO_MEMORY;
+ return;
+ }
+
+ /* DMA start */
+ bcm_sdhci_start_dma_seg(sc);
+}
+
+static int
+bcm_sdhci_will_handle_transfer(device_t dev, struct sdhci_slot *slot)
+{
+ size_t left;
+
+ /*
+ * Do not use DMA for transfers less than block size or with a length
+ * that is not a multiple of four.
+ */
+ left = min(BCM_DMA_BLOCK_SIZE,
+ slot->curcmd->data->len - slot->offset);
+ if (left < BCM_DMA_BLOCK_SIZE)
+ return (0);
+ if (left & 0x03)
+ return (0);
+
+ return (1);
+}
+
+static void
+bcm_sdhci_start_transfer(device_t dev, struct sdhci_slot *slot,
+ uint32_t *intmask)
+{
+
+ /* DMA transfer FIFO 1KB */
+ if (slot->curcmd->data->flags & MMC_DATA_READ)
+ bcm_sdhci_read_dma(dev, slot);
+ else
+ bcm_sdhci_write_dma(dev, slot);
+}
+
+static void
+bcm_sdhci_finish_transfer(device_t dev, struct sdhci_slot *slot)
+{
+
+ sdhci_finish_data(slot);
+}
+
+static device_method_t bcm_sdhci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bcm_sdhci_probe),
+ DEVMETHOD(device_attach, bcm_sdhci_attach),
+ DEVMETHOD(device_detach, bcm_sdhci_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
+ DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
+
+ /* MMC bridge interface */
+ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios),
+ DEVMETHOD(mmcbr_request, sdhci_generic_request),
+ DEVMETHOD(mmcbr_get_ro, bcm_sdhci_get_ro),
+ DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host),
+ DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
+
+ /* Platform transfer methods */
+ DEVMETHOD(sdhci_platform_will_handle, bcm_sdhci_will_handle_transfer),
+ DEVMETHOD(sdhci_platform_start_transfer, bcm_sdhci_start_transfer),
+ DEVMETHOD(sdhci_platform_finish_transfer, bcm_sdhci_finish_transfer),
+ /* SDHCI registers accessors */
+ DEVMETHOD(sdhci_read_1, bcm_sdhci_read_1),
+ DEVMETHOD(sdhci_read_2, bcm_sdhci_read_2),
+ DEVMETHOD(sdhci_read_4, bcm_sdhci_read_4),
+ DEVMETHOD(sdhci_read_multi_4, bcm_sdhci_read_multi_4),
+ DEVMETHOD(sdhci_write_1, bcm_sdhci_write_1),
+ DEVMETHOD(sdhci_write_2, bcm_sdhci_write_2),
+ DEVMETHOD(sdhci_write_4, bcm_sdhci_write_4),
+ DEVMETHOD(sdhci_write_multi_4, bcm_sdhci_write_multi_4),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm_sdhci_devclass;
+
+static driver_t bcm_sdhci_driver = {
+ "sdhci_bcm",
+ bcm_sdhci_methods,
+ sizeof(struct bcm_sdhci_softc),
+};
+
+DRIVER_MODULE(sdhci_bcm, simplebus, bcm_sdhci_driver, bcm_sdhci_devclass,
+ NULL, NULL);
+MODULE_DEPEND(sdhci_bcm, sdhci, 1, 1, 1);
+MMC_DECLARE_BRIDGE(sdhci_bcm);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_spi.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_spi.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_spi.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,529 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2013 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_spi.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/spibus/spi.h>
+#include <dev/spibus/spibusvar.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_gpio.h>
+#include <arm/broadcom/bcm2835/bcm2835_spireg.h>
+#include <arm/broadcom/bcm2835/bcm2835_spivar.h>
+
+#include "spibus_if.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-spi", 1},
+ {"brcm,bcm2835-spi", 1},
+ {NULL, 0}
+};
+
+static void bcm_spi_intr(void *);
+
+#ifdef BCM_SPI_DEBUG
+static void
+bcm_spi_printr(device_t dev)
+{
+ struct bcm_spi_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+ reg = BCM_SPI_READ(sc, SPI_CS);
+ device_printf(dev, "CS=%b\n", reg,
+ "\20\1CS0\2CS1\3CPHA\4CPOL\7CSPOL"
+ "\10TA\11DMAEN\12INTD\13INTR\14ADCS\15REN\16LEN"
+ "\21DONE\22RXD\23TXD\24RXR\25RXF\26CSPOL0\27CSPOL1"
+ "\30CSPOL2\31DMA_LEN\32LEN_LONG");
+ reg = BCM_SPI_READ(sc, SPI_CLK) & SPI_CLK_MASK;
+ if (reg % 2)
+ reg--;
+ if (reg == 0)
+ reg = 65536;
+ device_printf(dev, "CLK=%uMhz/%d=%luhz\n",
+ SPI_CORE_CLK / 1000000, reg, SPI_CORE_CLK / reg);
+ reg = BCM_SPI_READ(sc, SPI_DLEN) & SPI_DLEN_MASK;
+ device_printf(dev, "DLEN=%d\n", reg);
+ reg = BCM_SPI_READ(sc, SPI_LTOH) & SPI_LTOH_MASK;
+ device_printf(dev, "LTOH=%d\n", reg);
+ reg = BCM_SPI_READ(sc, SPI_DC);
+ device_printf(dev, "DC=RPANIC=%#x RDREQ=%#x TPANIC=%#x TDREQ=%#x\n",
+ (reg & SPI_DC_RPANIC_MASK) >> SPI_DC_RPANIC_SHIFT,
+ (reg & SPI_DC_RDREQ_MASK) >> SPI_DC_RDREQ_SHIFT,
+ (reg & SPI_DC_TPANIC_MASK) >> SPI_DC_TPANIC_SHIFT,
+ (reg & SPI_DC_TDREQ_MASK) >> SPI_DC_TDREQ_SHIFT);
+}
+#endif
+
+static void
+bcm_spi_modifyreg(struct bcm_spi_softc *sc, uint32_t off, uint32_t mask,
+ uint32_t value)
+{
+ uint32_t reg;
+
+ mtx_assert(&sc->sc_mtx, MA_OWNED);
+ reg = BCM_SPI_READ(sc, off);
+ reg &= ~mask;
+ reg |= value;
+ BCM_SPI_WRITE(sc, off, reg);
+}
+
+static int
+bcm_spi_clock_proc(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm_spi_softc *sc;
+ uint32_t clk;
+ int error;
+
+ sc = (struct bcm_spi_softc *)arg1;
+
+ BCM_SPI_LOCK(sc);
+ clk = BCM_SPI_READ(sc, SPI_CLK);
+ BCM_SPI_UNLOCK(sc);
+ clk &= 0xffff;
+ if (clk == 0)
+ clk = 65536;
+ clk = SPI_CORE_CLK / clk;
+
+ error = sysctl_handle_int(oidp, &clk, sizeof(clk), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ clk = SPI_CORE_CLK / clk;
+ if (clk <= 1)
+ clk = 2;
+ else if (clk % 2)
+ clk--;
+ if (clk > 0xffff)
+ clk = 0;
+ BCM_SPI_LOCK(sc);
+ BCM_SPI_WRITE(sc, SPI_CLK, clk);
+ BCM_SPI_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_spi_cs_bit_proc(SYSCTL_HANDLER_ARGS, uint32_t bit)
+{
+ struct bcm_spi_softc *sc;
+ uint32_t reg;
+ int error;
+
+ sc = (struct bcm_spi_softc *)arg1;
+ BCM_SPI_LOCK(sc);
+ reg = BCM_SPI_READ(sc, SPI_CS);
+ BCM_SPI_UNLOCK(sc);
+ reg = (reg & bit) ? 1 : 0;
+
+ error = sysctl_handle_int(oidp, ®, sizeof(reg), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (reg)
+ reg = bit;
+ BCM_SPI_LOCK(sc);
+ bcm_spi_modifyreg(sc, SPI_CS, bit, reg);
+ BCM_SPI_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+bcm_spi_cpol_proc(SYSCTL_HANDLER_ARGS)
+{
+
+ return (bcm_spi_cs_bit_proc(oidp, arg1, arg2, req, SPI_CS_CPOL));
+}
+
+static int
+bcm_spi_cpha_proc(SYSCTL_HANDLER_ARGS)
+{
+
+ return (bcm_spi_cs_bit_proc(oidp, arg1, arg2, req, SPI_CS_CPHA));
+}
+
+static int
+bcm_spi_cspol0_proc(SYSCTL_HANDLER_ARGS)
+{
+
+ return (bcm_spi_cs_bit_proc(oidp, arg1, arg2, req, SPI_CS_CSPOL0));
+}
+
+static int
+bcm_spi_cspol1_proc(SYSCTL_HANDLER_ARGS)
+{
+
+ return (bcm_spi_cs_bit_proc(oidp, arg1, arg2, req, SPI_CS_CSPOL1));
+}
+
+static void
+bcm_spi_sysctl_init(struct bcm_spi_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree_node;
+ struct sysctl_oid_list *tree;
+
+ /*
+ * Add system sysctl tree/handlers.
+ */
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ tree_node = device_get_sysctl_tree(sc->sc_dev);
+ tree = SYSCTL_CHILDREN(tree_node);
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "clock",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_spi_clock_proc, "IU", "SPI BUS clock frequency");
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "cpol",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_spi_cpol_proc, "IU", "SPI BUS clock polarity");
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "cpha",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_spi_cpha_proc, "IU", "SPI BUS clock phase");
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "cspol0",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_spi_cspol0_proc, "IU", "SPI BUS chip select 0 polarity");
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "cspol1",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc),
+ bcm_spi_cspol1_proc, "IU", "SPI BUS chip select 1 polarity");
+}
+
+static int
+bcm_spi_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2708/2835 SPI controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_spi_attach(device_t dev)
+{
+ struct bcm_spi_softc *sc;
+ device_t gpio;
+ int i, rid;
+
+ if (device_get_unit(dev) != 0) {
+ device_printf(dev, "only one SPI controller supported\n");
+ return (ENXIO);
+ }
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ /* Configure the GPIO pins to ALT0 function to enable SPI the pins. */
+ gpio = devclass_get_device(devclass_find("gpio"), 0);
+ if (!gpio) {
+ device_printf(dev, "cannot find gpio0\n");
+ return (ENXIO);
+ }
+ for (i = 0; i < nitems(bcm_spi_pins); i++)
+ bcm_gpio_set_alternate(gpio, bcm_spi_pins[i], BCM_GPIO_ALT0);
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ /* Hook up our interrupt handler. */
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, bcm_spi_intr, sc, &sc->sc_intrhand)) {
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot setup the interrupt handler\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->sc_mtx, "bcm_spi", NULL, MTX_DEF);
+
+ /* Add sysctl nodes. */
+ bcm_spi_sysctl_init(sc);
+
+#ifdef BCM_SPI_DEBUG
+ bcm_spi_printr(dev);
+#endif
+
+ /*
+ * Enable the SPI controller. Clear the rx and tx FIFO.
+ * Defaults to SPI mode 0.
+ */
+ BCM_SPI_WRITE(sc, SPI_CS, SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO);
+
+ /* Set the SPI clock to 500Khz. */
+ BCM_SPI_WRITE(sc, SPI_CLK, SPI_CORE_CLK / 500000);
+
+#ifdef BCM_SPI_DEBUG
+ bcm_spi_printr(dev);
+#endif
+
+ device_add_child(dev, "spibus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+bcm_spi_detach(device_t dev)
+{
+ struct bcm_spi_softc *sc;
+
+ bus_generic_detach(dev);
+
+ sc = device_get_softc(dev);
+ mtx_destroy(&sc->sc_mtx);
+ if (sc->sc_intrhand)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+
+ return (0);
+}
+
+static void
+bcm_spi_fill_fifo(struct bcm_spi_softc *sc)
+{
+ struct spi_command *cmd;
+ uint32_t cs, written;
+ uint8_t *data;
+
+ cmd = sc->sc_cmd;
+ cs = BCM_SPI_READ(sc, SPI_CS) & (SPI_CS_TA | SPI_CS_TXD);
+ while (sc->sc_written < sc->sc_len &&
+ cs == (SPI_CS_TA | SPI_CS_TXD)) {
+ data = (uint8_t *)cmd->tx_cmd;
+ written = sc->sc_written++;
+ if (written >= cmd->tx_cmd_sz) {
+ data = (uint8_t *)cmd->tx_data;
+ written -= cmd->tx_cmd_sz;
+ }
+ BCM_SPI_WRITE(sc, SPI_FIFO, data[written]);
+ cs = BCM_SPI_READ(sc, SPI_CS) & (SPI_CS_TA | SPI_CS_TXD);
+ }
+}
+
+static void
+bcm_spi_drain_fifo(struct bcm_spi_softc *sc)
+{
+ struct spi_command *cmd;
+ uint32_t cs, read;
+ uint8_t *data;
+
+ cmd = sc->sc_cmd;
+ cs = BCM_SPI_READ(sc, SPI_CS) & SPI_CS_RXD;
+ while (sc->sc_read < sc->sc_len && cs == SPI_CS_RXD) {
+ data = (uint8_t *)cmd->rx_cmd;
+ read = sc->sc_read++;
+ if (read >= cmd->rx_cmd_sz) {
+ data = (uint8_t *)cmd->rx_data;
+ read -= cmd->rx_cmd_sz;
+ }
+ data[read] = BCM_SPI_READ(sc, SPI_FIFO) & 0xff;
+ cs = BCM_SPI_READ(sc, SPI_CS) & SPI_CS_RXD;
+ }
+}
+
+static void
+bcm_spi_intr(void *arg)
+{
+ struct bcm_spi_softc *sc;
+
+ sc = (struct bcm_spi_softc *)arg;
+ BCM_SPI_LOCK(sc);
+
+ /* Filter stray interrupts. */
+ if ((sc->sc_flags & BCM_SPI_BUSY) == 0) {
+ BCM_SPI_UNLOCK(sc);
+ return;
+ }
+
+ /* TX - Fill up the FIFO. */
+ bcm_spi_fill_fifo(sc);
+
+ /* RX - Drain the FIFO. */
+ bcm_spi_drain_fifo(sc);
+
+ /* Check for end of transfer. */
+ if (sc->sc_written == sc->sc_len && sc->sc_read == sc->sc_len) {
+ /* Disable interrupts and the SPI engine. */
+ bcm_spi_modifyreg(sc, SPI_CS,
+ SPI_CS_TA | SPI_CS_INTR | SPI_CS_INTD, 0);
+ wakeup(sc->sc_dev);
+ }
+
+ BCM_SPI_UNLOCK(sc);
+}
+
+static int
+bcm_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
+{
+ struct bcm_spi_softc *sc;
+ int cs, err;
+
+ sc = device_get_softc(dev);
+
+ KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
+ ("TX/RX command sizes should be equal"));
+ KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
+ ("TX/RX data sizes should be equal"));
+
+ /* Get the proper chip select for this child. */
+ spibus_get_cs(child, &cs);
+ if (cs < 0 || cs > 2) {
+ device_printf(dev,
+ "Invalid chip select %d requested by %s\n", cs,
+ device_get_nameunit(child));
+ return (EINVAL);
+ }
+
+ BCM_SPI_LOCK(sc);
+
+ /* If the controller is in use wait until it is available. */
+ while (sc->sc_flags & BCM_SPI_BUSY)
+ mtx_sleep(dev, &sc->sc_mtx, 0, "bcm_spi", 0);
+
+ /* Now we have control over SPI controller. */
+ sc->sc_flags = BCM_SPI_BUSY;
+
+ /* Clear the FIFO. */
+ bcm_spi_modifyreg(sc, SPI_CS,
+ SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO,
+ SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO);
+
+ /* Save a pointer to the SPI command. */
+ sc->sc_cmd = cmd;
+ sc->sc_read = 0;
+ sc->sc_written = 0;
+ sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz;
+
+ /*
+ * Set the CS for this transaction, enable interrupts and announce
+ * we're ready to tx. This will kick off the first interrupt.
+ */
+ bcm_spi_modifyreg(sc, SPI_CS,
+ SPI_CS_MASK | SPI_CS_TA | SPI_CS_INTR | SPI_CS_INTD,
+ cs | SPI_CS_TA | SPI_CS_INTR | SPI_CS_INTD);
+
+ /* Wait for the transaction to complete. */
+ err = mtx_sleep(dev, &sc->sc_mtx, 0, "bcm_spi", hz * 2);
+
+ /* Make sure the SPI engine and interrupts are disabled. */
+ bcm_spi_modifyreg(sc, SPI_CS, SPI_CS_TA | SPI_CS_INTR | SPI_CS_INTD, 0);
+
+ /* Release the controller and wakeup the next thread waiting for it. */
+ sc->sc_flags = 0;
+ wakeup_one(dev);
+ BCM_SPI_UNLOCK(sc);
+
+ /*
+ * Check for transfer timeout. The SPI controller doesn't
+ * return errors.
+ */
+ if (err == EWOULDBLOCK) {
+ device_printf(sc->sc_dev, "SPI error\n");
+ err = EIO;
+ }
+
+ return (err);
+}
+
+static phandle_t
+bcm_spi_get_node(device_t bus, device_t dev)
+{
+
+ /* We only have one child, the SPI bus, which needs our own node. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t bcm_spi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bcm_spi_probe),
+ DEVMETHOD(device_attach, bcm_spi_attach),
+ DEVMETHOD(device_detach, bcm_spi_detach),
+
+ /* SPI interface */
+ DEVMETHOD(spibus_transfer, bcm_spi_transfer),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, bcm_spi_get_node),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm_spi_devclass;
+
+static driver_t bcm_spi_driver = {
+ "spi",
+ bcm_spi_methods,
+ sizeof(struct bcm_spi_softc),
+};
+
+DRIVER_MODULE(bcm2835_spi, simplebus, bcm_spi_driver, bcm_spi_devclass, 0, 0);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_spi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_spireg.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_spireg.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_spireg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,76 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2013 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_spireg.h 259325 2013-12-13 19:27:23Z ian $
+ */
+
+#ifndef _BCM2835_SPIREG_H_
+#define _BCM2835_SPIREG_H_
+
+#define SPI_CORE_CLK 250000000U
+#define SPI_CS 0x00
+#define SPI_CS_LEN_LONG (1 << 25)
+#define SPI_CS_DMA_LEN (1 << 24)
+#define SPI_CS_CSPOL2 (1 << 23)
+#define SPI_CS_CSPOL1 (1 << 22)
+#define SPI_CS_CSPOL0 (1 << 21)
+#define SPI_CS_RXF (1 << 20)
+#define SPI_CS_RXR (1 << 19)
+#define SPI_CS_TXD (1 << 18)
+#define SPI_CS_RXD (1 << 17)
+#define SPI_CS_DONE (1 << 16)
+#define SPI_CS_LEN (1 << 13)
+#define SPI_CS_REN (1 << 12)
+#define SPI_CS_ADCS (1 << 11)
+#define SPI_CS_INTR (1 << 10)
+#define SPI_CS_INTD (1 << 9)
+#define SPI_CS_DMAEN (1 << 8)
+#define SPI_CS_TA (1 << 7)
+#define SPI_CS_CSPOL (1 << 6)
+#define SPI_CS_CLEAR_RXFIFO (1 << 5)
+#define SPI_CS_CLEAR_TXFIFO (1 << 4)
+#define SPI_CS_CPOL (1 << 3)
+#define SPI_CS_CPHA (1 << 2)
+#define SPI_CS_MASK 0x3
+#define SPI_FIFO 0x04
+#define SPI_CLK 0x08
+#define SPI_CLK_MASK 0xffff
+#define SPI_DLEN 0x0c
+#define SPI_DLEN_MASK 0xffff
+#define SPI_LTOH 0x10
+#define SPI_LTOH_MASK 0xf
+#define SPI_DC 0x14
+#define SPI_DC_RPANIC_SHIFT 24
+#define SPI_DC_RPANIC_MASK (0xff << SPI_DC_RPANIC_SHIFT)
+#define SPI_DC_RDREQ_SHIFT 16
+#define SPI_DC_RDREQ_MASK (0xff << SPI_DC_RDREQ_SHIFT)
+#define SPI_DC_TPANIC_SHIFT 8
+#define SPI_DC_TPANIC_MASK (0xff << SPI_DC_TPANIC_SHIFT)
+#define SPI_DC_TDREQ_SHIFT 0
+#define SPI_DC_TDREQ_MASK 0xff
+
+#endif /* _BCM2835_SPIREG_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_spireg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_spivar.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_spivar.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_spivar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,73 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2013 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_spivar.h 259325 2013-12-13 19:27:23Z ian $
+ */
+
+#ifndef _BCM2835_SPIVAR_H_
+#define _BCM2835_SPIVAR_H_
+
+/*
+ * Only the available pins are listed here.
+ * i.e. CS2 isn't available.
+ */
+uint32_t bcm_spi_pins[] = {
+ 7, /* CS1 */
+ 8, /* CS0 */
+ 9, /* MISO */
+ 10, /* MOSI */
+ 11 /* SCLK */
+};
+
+struct bcm_spi_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ struct resource * sc_mem_res;
+ struct resource * sc_irq_res;
+ struct spi_command *sc_cmd;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ uint32_t sc_len;
+ uint32_t sc_read;
+ uint32_t sc_flags;
+ uint32_t sc_written;
+ void * sc_intrhand;
+};
+
+#define BCM_SPI_BUSY 0x1
+
+#define BCM_SPI_WRITE(_sc, _off, _val) \
+ bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
+#define BCM_SPI_READ(_sc, _off) \
+ bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
+
+#define BCM_SPI_LOCK(_sc) \
+ mtx_lock(&(_sc)->sc_mtx)
+#define BCM_SPI_UNLOCK(_sc) \
+ mtx_unlock(&(_sc)->sc_mtx)
+
+#endif /* _BCM2835_SPIVAR_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_spivar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_systimer.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_systimer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,311 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012 Damjan Marion <dmarion at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_systimer.c 266207 2014-05-16 02:21:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#define BCM2835_NUM_TIMERS 4
+
+#define DEFAULT_TIMER 3
+#define DEFAULT_FREQUENCY 1000000
+#define MIN_PERIOD 5LLU
+
+#define SYSTIMER_CS 0x00
+#define SYSTIMER_CLO 0x04
+#define SYSTIMER_CHI 0x08
+#define SYSTIMER_C0 0x0C
+#define SYSTIMER_C1 0x10
+#define SYSTIMER_C2 0x14
+#define SYSTIMER_C3 0x18
+
+struct systimer {
+ int index;
+ bool enabled;
+ struct eventtimer et;
+};
+
+struct bcm_systimer_softc {
+ struct resource* mem_res;
+ struct resource* irq_res[BCM2835_NUM_TIMERS];
+ void* intr_hl[BCM2835_NUM_TIMERS];
+ uint32_t sysclk_freq;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ struct systimer st[BCM2835_NUM_TIMERS];
+};
+
+static struct resource_spec bcm_systimer_irq_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+static struct bcm_systimer_softc *bcm_systimer_sc = NULL;
+
+/* Read/Write macros for Timer used as timecounter */
+#define bcm_systimer_tc_read_4(reg) \
+ bus_space_read_4(bcm_systimer_sc->bst, \
+ bcm_systimer_sc->bsh, reg)
+
+#define bcm_systimer_tc_write_4(reg, val) \
+ bus_space_write_4(bcm_systimer_sc->bst, \
+ bcm_systimer_sc->bsh, reg, val)
+
+static unsigned bcm_systimer_tc_get_timecount(struct timecounter *);
+
+static struct timecounter bcm_systimer_tc = {
+ .tc_name = "BCM2835 Timecounter",
+ .tc_get_timecount = bcm_systimer_tc_get_timecount,
+ .tc_poll_pps = NULL,
+ .tc_counter_mask = ~0u,
+ .tc_frequency = 0,
+ .tc_quality = 1000,
+};
+
+static unsigned
+bcm_systimer_tc_get_timecount(struct timecounter *tc)
+{
+ return bcm_systimer_tc_read_4(SYSTIMER_CLO);
+}
+
+static int
+bcm_systimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct systimer *st = et->et_priv;
+ uint32_t clo, clo1;
+ uint32_t count;
+ register_t s;
+
+ if (first != 0) {
+
+ count = ((uint32_t)et->et_frequency * first) >> 32;
+
+ s = intr_disable();
+ clo = bcm_systimer_tc_read_4(SYSTIMER_CLO);
+restart:
+ clo += count;
+ /*
+ * Clear pending interrupts
+ */
+ bcm_systimer_tc_write_4(SYSTIMER_CS, (1 << st->index));
+ bcm_systimer_tc_write_4(SYSTIMER_C0 + st->index*4, clo);
+ clo1 = bcm_systimer_tc_read_4(SYSTIMER_CLO);
+ if ((int32_t)(clo1 - clo) >= 0) {
+ count *= 2;
+ clo = clo1;
+ goto restart;
+ }
+ st->enabled = 1;
+ intr_restore(s);
+
+ return (0);
+ }
+
+ return (EINVAL);
+}
+
+static int
+bcm_systimer_stop(struct eventtimer *et)
+{
+ struct systimer *st = et->et_priv;
+ st->enabled = 0;
+
+ return (0);
+}
+
+static int
+bcm_systimer_intr(void *arg)
+{
+ struct systimer *st = (struct systimer *)arg;
+ uint32_t cs;
+
+ cs = bcm_systimer_tc_read_4(SYSTIMER_CS);
+ if ((cs & (1 << st->index)) == 0)
+ return (FILTER_STRAY);
+
+ /* ACK interrupt */
+ bcm_systimer_tc_write_4(SYSTIMER_CS, (1 << st->index));
+ if (st->enabled) {
+ if (st->et.et_active) {
+ st->et.et_event_cb(&st->et, st->et.et_arg);
+ }
+ }
+
+ return (FILTER_HANDLED);
+}
+
+static int
+bcm_systimer_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "broadcom,bcm2835-system-timer")) {
+ device_set_desc(dev, "BCM2835 System Timer");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+bcm_systimer_attach(device_t dev)
+{
+ struct bcm_systimer_softc *sc = device_get_softc(dev);
+ int err;
+ int rid = 0;
+
+ if (bcm_systimer_sc != NULL)
+ return (EINVAL);
+
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->mem_res);
+ sc->bsh = rman_get_bushandle(sc->mem_res);
+
+ /* Request the IRQ resources */
+ err = bus_alloc_resources(dev, bcm_systimer_irq_spec,
+ sc->irq_res);
+ if (err) {
+ device_printf(dev, "Error: could not allocate irq resources\n");
+ return (ENXIO);
+ }
+
+ /* TODO: get frequency from FDT */
+ sc->sysclk_freq = DEFAULT_FREQUENCY;
+
+ /* Setup and enable the timer */
+ if (bus_setup_intr(dev, sc->irq_res[DEFAULT_TIMER], INTR_TYPE_CLK,
+ bcm_systimer_intr, NULL, &sc->st[DEFAULT_TIMER],
+ &sc->intr_hl[DEFAULT_TIMER]) != 0) {
+ bus_release_resources(dev, bcm_systimer_irq_spec,
+ sc->irq_res);
+ device_printf(dev, "Unable to setup the clock irq handler.\n");
+ return (ENXIO);
+ }
+
+ sc->st[DEFAULT_TIMER].index = DEFAULT_TIMER;
+ sc->st[DEFAULT_TIMER].enabled = 0;
+ sc->st[DEFAULT_TIMER].et.et_name = malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
+ sprintf(sc->st[DEFAULT_TIMER].et.et_name, "BCM2835 Event Timer %d", DEFAULT_TIMER);
+ sc->st[DEFAULT_TIMER].et.et_flags = ET_FLAGS_ONESHOT;
+ sc->st[DEFAULT_TIMER].et.et_quality = 1000;
+ sc->st[DEFAULT_TIMER].et.et_frequency = sc->sysclk_freq;
+ sc->st[DEFAULT_TIMER].et.et_min_period =
+ (MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency + 1;
+ sc->st[DEFAULT_TIMER].et.et_max_period =
+ (0x7ffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency;
+ sc->st[DEFAULT_TIMER].et.et_start = bcm_systimer_start;
+ sc->st[DEFAULT_TIMER].et.et_stop = bcm_systimer_stop;
+ sc->st[DEFAULT_TIMER].et.et_priv = &sc->st[DEFAULT_TIMER];
+ et_register(&sc->st[DEFAULT_TIMER].et);
+
+ bcm_systimer_sc = sc;
+
+ bcm_systimer_tc.tc_frequency = DEFAULT_FREQUENCY;
+ tc_init(&bcm_systimer_tc);
+
+ return (0);
+}
+
+static device_method_t bcm_systimer_methods[] = {
+ DEVMETHOD(device_probe, bcm_systimer_probe),
+ DEVMETHOD(device_attach, bcm_systimer_attach),
+ { 0, 0 }
+};
+
+static driver_t bcm_systimer_driver = {
+ "systimer",
+ bcm_systimer_methods,
+ sizeof(struct bcm_systimer_softc),
+};
+
+static devclass_t bcm_systimer_devclass;
+
+DRIVER_MODULE(bcm_systimer, simplebus, bcm_systimer_driver, bcm_systimer_devclass, 0, 0);
+
+void
+DELAY(int usec)
+{
+ int32_t counts;
+ uint32_t first, last;
+
+ if (bcm_systimer_sc == NULL) {
+ for (; usec > 0; usec--)
+ for (counts = 200; counts > 0; counts--)
+ /* Prevent gcc from optimizing out the loop */
+ cpufunc_nullop();
+ return;
+ }
+
+ /* Get the number of times to count */
+ counts = usec * (bcm_systimer_tc.tc_frequency / 1000000) + 1;
+
+ first = bcm_systimer_tc_read_4(SYSTIMER_CLO);
+
+ while (counts > 0) {
+ last = bcm_systimer_tc_read_4(SYSTIMER_CLO);
+ if (last == first)
+ continue;
+ if (last>first) {
+ counts -= (int32_t)(last - first);
+ } else {
+ counts -= (int32_t)((0xFFFFFFFF - first) + last);
+ }
+ first = last;
+ }
+}
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,73 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h 322724 2017-08-20 16:52:27Z marius $
+ */
+
+/*
+ * Defines for converting physical address to VideoCore bus address and back
+ */
+
+#ifndef _BCM2835_VCBUS_H_
+#define _BCM2835_VCBUS_H_
+
+#define BCM2835_VCBUS_SDRAM_CACHED 0x40000000
+#define BCM2835_VCBUS_IO_BASE 0x7E000000
+#define BCM2835_VCBUS_SDRAM_UNCACHED 0xC0000000
+
+#ifdef SOC_BCM2836
+#define BCM2835_ARM_IO_BASE 0x3f000000
+#define BCM2835_VCBUS_SDRAM_BASE BCM2835_VCBUS_SDRAM_UNCACHED
+#else
+#define BCM2835_ARM_IO_BASE 0x20000000
+#define BCM2835_VCBUS_SDRAM_BASE BCM2835_VCBUS_SDRAM_CACHED
+#endif
+#define BCM2835_ARM_IO_SIZE 0x01000000
+
+/*
+ * Convert physical address to VC bus address. Should be used
+ * when submitting address over mailbox interface
+ */
+#define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_BASE)
+
+/* Check whether pa bellong top IO window */
+#define BCM2835_ARM_IS_IO(pa) (((pa) >= BCM2835_ARM_IO_BASE) && \
+ ((pa) < BCM2835_ARM_IO_BASE + BCM2835_ARM_IO_SIZE))
+
+/*
+ * Convert physical address in IO space to VC bus address.
+ */
+#define IO_TO_VCBUS(pa) ((pa - BCM2835_ARM_IO_BASE) + \
+ BCM2835_VCBUS_IO_BASE)
+
+/*
+ * Convert address from VC bus space to physical. Should be used
+ * when address is returned by VC over mailbox interface. e.g.
+ * framebuffer base
+ */
+#define VCBUS_TO_PHYS(vca) ((vca) & ~(BCM2835_VCBUS_SDRAM_BASE))
+
+#endif /* _BCM2835_VCBUS_H_ */
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,226 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Alexander Rybalko <ray at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_wdog.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/watchdog.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <machine/machdep.h>
+#include <machine/fdt.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_wdog.h>
+
+#define BCM2835_PASSWORD 0x5a
+
+#define BCM2835_WDOG_RESET 0
+#define BCM2835_PASSWORD_MASK 0xff000000
+#define BCM2835_PASSWORD_SHIFT 24
+#define BCM2835_WDOG_TIME_MASK 0x000fffff
+#define BCM2835_WDOG_TIME_SHIFT 0
+
+#define READ(_sc, _r) bus_space_read_4((_sc)->bst, (_sc)->bsh, (_r) + (_sc)->regs_offset)
+#define WRITE(_sc, _r, _v) bus_space_write_4((_sc)->bst, (_sc)->bsh, (_r) + (_sc)->regs_offset, (_v))
+
+#define BCM2835_RSTC_WRCFG_CLR 0xffffffcf
+#define BCM2835_RSTC_WRCFG_SET 0x00000030
+#define BCM2835_RSTC_WRCFG_FULL_RESET 0x00000020
+#define BCM2835_RSTC_RESET 0x00000102
+
+#define BCM2835_RSTC_REG 0x00
+#define BCM2835_RSTS_REG 0x04
+#define BCM2835_WDOG_REG 0x08
+
+static struct bcmwd_softc *bcmwd_lsc = NULL;
+
+struct bcmwd_softc {
+ device_t dev;
+ struct resource * res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ int wdog_armed;
+ int wdog_period;
+ char wdog_passwd;
+ struct mtx mtx;
+ int regs_offset;
+};
+
+#define BSD_DTB 1
+#define UPSTREAM_DTB 2
+#define UPSTREAM_DTB_REGS_OFFSET 0x1c
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-wdt", BSD_DTB},
+ {"brcm,bcm2835-pm-wdt", UPSTREAM_DTB},
+ {NULL, 0}
+};
+
+static void bcmwd_watchdog_fn(void *private, u_int cmd, int *error);
+
+static int
+bcmwd_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2708/2835 Watchdog");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcmwd_attach(device_t dev)
+{
+ struct bcmwd_softc *sc;
+ int rid;
+
+ if (bcmwd_lsc != NULL)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->wdog_period = 7;
+ sc->wdog_passwd = BCM2835_PASSWORD;
+ sc->wdog_armed = 0;
+ sc->dev = dev;
+
+ rid = 0;
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res);
+ sc->bsh = rman_get_bushandle(sc->res);
+
+ /* compensate base address difference */
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data
+ == UPSTREAM_DTB)
+ sc->regs_offset = UPSTREAM_DTB_REGS_OFFSET;
+
+ bcmwd_lsc = sc;
+ mtx_init(&sc->mtx, "BCM2835 Watchdog", "bcmwd", MTX_DEF);
+ EVENTHANDLER_REGISTER(watchdog_list, bcmwd_watchdog_fn, sc, 0);
+
+ return (0);
+}
+
+static void
+bcmwd_watchdog_fn(void *private, u_int cmd, int *error)
+{
+ struct bcmwd_softc *sc;
+ uint64_t sec;
+ uint32_t ticks, reg;
+
+ sc = private;
+ mtx_lock(&sc->mtx);
+
+ cmd &= WD_INTERVAL;
+
+ if (cmd > 0) {
+ sec = ((uint64_t)1 << (cmd & WD_INTERVAL)) / 1000000000;
+ if (sec == 0 || sec > 15) {
+ /*
+ * Can't arm
+ * disable watchdog as watchdog(9) requires
+ */
+ device_printf(sc->dev,
+ "Can't arm, timeout must be between 1-15 seconds\n");
+ WRITE(sc, BCM2835_RSTC_REG,
+ (BCM2835_PASSWORD << BCM2835_PASSWORD_SHIFT) |
+ BCM2835_RSTC_RESET);
+ mtx_unlock(&sc->mtx);
+ return;
+ }
+
+ ticks = (sec << 16) & BCM2835_WDOG_TIME_MASK;
+ reg = (BCM2835_PASSWORD << BCM2835_PASSWORD_SHIFT) | ticks;
+ WRITE(sc, BCM2835_WDOG_REG, reg);
+
+ reg = READ(sc, BCM2835_RSTC_REG);
+ reg &= BCM2835_RSTC_WRCFG_CLR;
+ reg |= BCM2835_RSTC_WRCFG_FULL_RESET;
+ reg |= (BCM2835_PASSWORD << BCM2835_PASSWORD_SHIFT);
+ WRITE(sc, BCM2835_RSTC_REG, reg);
+
+ *error = 0;
+ }
+ else
+ WRITE(sc, BCM2835_RSTC_REG,
+ (BCM2835_PASSWORD << BCM2835_PASSWORD_SHIFT) |
+ BCM2835_RSTC_RESET);
+
+ mtx_unlock(&sc->mtx);
+}
+
+void
+bcmwd_watchdog_reset()
+{
+
+ if (bcmwd_lsc == NULL)
+ return;
+
+ WRITE(bcmwd_lsc, BCM2835_WDOG_REG,
+ (BCM2835_PASSWORD << BCM2835_PASSWORD_SHIFT) | 10);
+
+ WRITE(bcmwd_lsc, BCM2835_RSTC_REG,
+ (READ(bcmwd_lsc, BCM2835_RSTC_REG) & BCM2835_RSTC_WRCFG_CLR) |
+ (BCM2835_PASSWORD << BCM2835_PASSWORD_SHIFT) |
+ BCM2835_RSTC_WRCFG_FULL_RESET);
+}
+
+static device_method_t bcmwd_methods[] = {
+ DEVMETHOD(device_probe, bcmwd_probe),
+ DEVMETHOD(device_attach, bcmwd_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t bcmwd_driver = {
+ "bcmwd",
+ bcmwd_methods,
+ sizeof(struct bcmwd_softc),
+};
+static devclass_t bcmwd_devclass;
+
+DRIVER_MODULE(bcmwd, simplebus, bcmwd_driver, bcmwd_devclass, 0, 0);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,33 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Alexander Rybalko <ray at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_wdog.h 239922 2012-08-30 20:59:37Z gonzo $
+ */
+#ifndef _BCM2835_WDOG_H_
+#define _BCM2835_WDOG_H_
+
+void bcmwd_watchdog_reset(void);
+#endif
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2835_wdog.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2836.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2836.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2836.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,185 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 2015 Andrew Turner.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2836.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_bus.h>
+
+#include <arm/broadcom/bcm2835/bcm2836.h>
+
+#define ARM_LOCAL_BASE 0x40000000
+#define ARM_LOCAL_SIZE 0x00001000
+
+#define ARM_LOCAL_CONTROL 0x00
+#define ARM_LOCAL_PRESCALER 0x08
+#define PRESCALER_19_2 0x80000000 /* 19.2 MHz */
+#define ARM_LOCAL_INT_TIMER(n) (0x40 + (n) * 4)
+#define ARM_LOCAL_INT_MAILBOX(n) (0x50 + (n) * 4)
+#define ARM_LOCAL_INT_PENDING(n) (0x60 + (n) * 4)
+#define INT_PENDING_MASK 0x0f
+
+/*
+ * A driver for features of the bcm2836.
+ */
+
+struct bcm2836_softc {
+ device_t sc_dev;
+ struct resource *sc_mem;
+};
+
+static device_identify_t bcm2836_identify;
+static device_probe_t bcm2836_probe;
+static device_attach_t bcm2836_attach;
+
+struct bcm2836_softc *softc;
+
+static void
+bcm2836_identify(driver_t *driver, device_t parent)
+{
+
+ if (BUS_ADD_CHILD(parent, 0, "bcm2836", -1) == NULL)
+ device_printf(parent, "add child failed\n");
+}
+
+static int
+bcm2836_probe(device_t dev)
+{
+
+ if (softc != NULL)
+ return (ENXIO);
+
+ device_set_desc(dev, "Broadcom bcm2836");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm2836_attach(device_t dev)
+{
+ int i, rid;
+
+ softc = device_get_softc(dev);
+ softc->sc_dev = dev;
+
+ rid = 0;
+ softc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ ARM_LOCAL_BASE, ARM_LOCAL_BASE + ARM_LOCAL_SIZE, ARM_LOCAL_SIZE,
+ RF_ACTIVE);
+ if (softc->sc_mem == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ bus_write_4(softc->sc_mem, ARM_LOCAL_CONTROL, 0);
+ bus_write_4(softc->sc_mem, ARM_LOCAL_PRESCALER, PRESCALER_19_2);
+
+ for (i = 0; i < 4; i++)
+ bus_write_4(softc->sc_mem, ARM_LOCAL_INT_TIMER(i), 0);
+
+ for (i = 0; i < 4; i++)
+ bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(i), 1);
+
+ return (0);
+}
+
+int
+bcm2836_get_next_irq(int last_irq)
+{
+ uint32_t reg;
+ int cpu;
+ int irq;
+
+ cpu = PCPU_GET(cpuid);
+
+ reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_PENDING(cpu));
+ reg &= INT_PENDING_MASK;
+ if (reg == 0)
+ return (-1);
+
+ irq = ffs(reg) - 1;
+
+ return (irq);
+}
+
+void
+bcm2836_mask_irq(uintptr_t irq)
+{
+ uint32_t reg;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_TIMER(i));
+ reg &= ~(1 << irq);
+ bus_write_4(softc->sc_mem, ARM_LOCAL_INT_TIMER(i), reg);
+ }
+}
+
+void
+bcm2836_unmask_irq(uintptr_t irq)
+{
+ uint32_t reg;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_TIMER(i));
+ reg |= (1 << irq);
+ bus_write_4(softc->sc_mem, ARM_LOCAL_INT_TIMER(i), reg);
+ }
+}
+
+static device_method_t bcm2836_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, bcm2836_identify),
+ DEVMETHOD(device_probe, bcm2836_probe),
+ DEVMETHOD(device_attach, bcm2836_attach),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm2836_devclass;
+
+static driver_t bcm2836_driver = {
+ "bcm2836",
+ bcm2836_methods,
+ sizeof(struct bcm2836_softc),
+};
+
+EARLY_DRIVER_MODULE(bcm2836, nexus, bcm2836_driver, bcm2836_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2836.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm2836.h
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm2836.h (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm2836.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,38 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 2015 Andrew Turner.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2836.h 322724 2017-08-20 16:52:27Z marius $
+ */
+
+#ifndef _BCM2815_BCM2836_H
+#define _BCM2815_BCM2836_H
+
+int bcm2836_get_next_irq(int);
+void bcm2836_mask_irq(uintptr_t);
+void bcm2836_unmask_irq(uintptr_t);
+
+#endif
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm2836.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/bcm283x_dwc_fdt.c
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/bcm283x_dwc_fdt.c (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/bcm283x_dwc_fdt.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,105 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 2015 Andrew Turner.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm283x_dwc_fdt.c 322724 2017-08-20 16:52:27Z marius $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/callout.h>
+#include <sys/condvar.h>
+#include <sys/module.h>
+
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+
+#include <dev/usb/controller/dwc_otg.h>
+#include <dev/usb/controller/dwc_otg_fdt.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
+
+static struct ofw_compat_data compat_data[] = {
+ {"broadcom,bcm2835-usb", 1},
+ {"brcm,bcm2708-usb", 1},
+ {NULL, 0}
+};
+
+static device_probe_t bcm283x_dwc_otg_probe;
+static device_attach_t bcm283x_dwc_otg_attach;
+
+static int
+bcm283x_dwc_otg_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "DWC OTG 2.0 integrated USB controller (bcm283x)");
+
+ return (BUS_PROBE_VENDOR);
+}
+
+static int
+bcm283x_dwc_otg_attach(device_t dev)
+{
+ int err;
+
+ err = bcm2835_mbox_set_power_state(BCM2835_MBOX_POWER_ID_USB_HCD, TRUE);
+ if (err)
+ device_printf(dev, "failed to set power state, err=%d\n", err);
+
+ return (dwc_otg_attach(dev));
+}
+
+static device_method_t bcm283x_dwc_otg_methods[] = {
+ /* bus interface */
+ DEVMETHOD(device_probe, bcm283x_dwc_otg_probe),
+ DEVMETHOD(device_attach, bcm283x_dwc_otg_attach),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm283x_dwc_otg_devclass;
+
+DEFINE_CLASS_1(bcm283x_dwcotg, bcm283x_dwc_otg_driver, bcm283x_dwc_otg_methods,
+ sizeof(struct dwc_otg_fdt_softc), dwc_otg_driver);
+DRIVER_MODULE(bcm283x_dwcotg, simplebus, bcm283x_dwc_otg_driver,
+ bcm283x_dwc_otg_devclass, 0, 0);
+MODULE_DEPEND(bcm283x_dwcotg, usb, 1, 1, 1);
Property changes on: trunk/sys/arm/broadcom/bcm2835/bcm283x_dwc_fdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/files.bcm2835
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/files.bcm2835 (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/files.bcm2835 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,32 @@
+# $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/files.bcm2835 322724 2017-08-20 16:52:27Z marius $
+
+arm/broadcom/bcm2835/bcm2835_bsc.c optional bcm2835_bsc
+arm/broadcom/bcm2835/bcm2835_common.c optional fdt
+arm/broadcom/bcm2835/bcm2835_cpufreq.c standard
+arm/broadcom/bcm2835/bcm2835_dma.c standard
+arm/broadcom/bcm2835/bcm2835_fb.c optional sc
+arm/broadcom/bcm2835/bcm2835_fbd.c optional vt
+arm/broadcom/bcm2835/bcm2835_gpio.c optional gpio
+arm/broadcom/bcm2835/bcm2835_intr.c standard
+arm/broadcom/bcm2835/bcm2835_machdep.c standard
+arm/broadcom/bcm2835/bcm2835_mbox.c standard
+arm/broadcom/bcm2835/bcm2835_sdhci.c optional sdhci
+arm/broadcom/bcm2835/bcm2835_spi.c optional bcm2835_spi
+arm/broadcom/bcm2835/bcm2835_systimer.c standard
+arm/broadcom/bcm2835/bcm2835_wdog.c standard
+dev/usb/controller/dwc_otg_fdt.c optional dwcotg
+
+arm/broadcom/bcm2835/bcm283x_dwc_fdt.c optional dwcotg fdt
+
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_arm11x6.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_armv6.S standard
+
+kern/kern_clocksource.c standard
+
+dev/mbox/mbox_if.m standard
+dev/ofw/ofw_cpu.c standard
Property changes on: trunk/sys/arm/broadcom/bcm2835/files.bcm2835
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/files.bcm2836
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/files.bcm2836 (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/files.bcm2836 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,6 @@
+# $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/files.bcm2836 322724 2017-08-20 16:52:27Z marius $
+
+arm/arm/cpufunc_asm_armv7.S standard
+arm/arm/generic_timer.c standard
+
+arm/broadcom/bcm2835/bcm2836.c standard
Property changes on: trunk/sys/arm/broadcom/bcm2835/files.bcm2836
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/std.bcm2835
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/std.bcm2835 (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/std.bcm2835 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+# $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/std.bcm2835 322724 2017-08-20 16:52:27Z marius $
+
+machine arm armv6
+cpu CPU_ARM1176
+makeoptions CONF_CFLAGS="-mcpu=arm1176jzf-s -Wa,-mcpu=arm1176jzf-s"
+options SOC_BCM2835
+
+files "../broadcom/bcm2835/files.bcm2835"
+
Property changes on: trunk/sys/arm/broadcom/bcm2835/std.bcm2835
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/std.bcm2836
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/std.bcm2836 (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/std.bcm2836 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+# $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/std.bcm2836 322724 2017-08-20 16:52:27Z marius $
+
+machine arm armv6
+cpu CPU_CORTEXA
+makeoptions CONF_CFLAGS="-march=armv7a"
+options SOC_BCM2836
+
+files "../broadcom/bcm2835/files.bcm2836"
+files "../broadcom/bcm2835/files.bcm283x"
+
Property changes on: trunk/sys/arm/broadcom/bcm2835/std.bcm2836
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/broadcom/bcm2835/std.rpi
===================================================================
--- trunk/sys/arm/broadcom/bcm2835/std.rpi (rev 0)
+++ trunk/sys/arm/broadcom/bcm2835/std.rpi 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,11 @@
+# $FreeBSD: stable/10/sys/arm/broadcom/bcm2835/std.rpi 266110 2014-05-15 02:41:23Z ian $
+
+include "../broadcom/bcm2835/std.bcm2835"
+
+options KERNVIRTADDR=0xc0100000
+makeoptions KERNVIRTADDR=0xc0100000
+options KERNPHYSADDR=0x00100000
+makeoptions KERNPHYSADDR=0x00100000
+options PHYSADDR=0x00000000
+options FREEBSD_BOOT_LOADER
+options LINUX_BOOT_ABI
Property changes on: trunk/sys/arm/broadcom/bcm2835/std.rpi
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/cfi_bus_econa.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/cfi_bus_econa.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/cfi_bus_econa.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,68 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/cfi_bus_econa.c 264219 2014-04-07 05:33:30Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <dev/cfi/cfi_var.h>
+
+#include <arm/cavium/cns11xx/econa_reg.h>
+#include <arm/cavium/cns11xx/econa_var.h>
+
+static int
+cfi_econa_probe(device_t dev)
+{
+
+ return cfi_probe(dev);
+}
+
+static device_method_t cfi_econa_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, cfi_econa_probe),
+ DEVMETHOD(device_attach, cfi_attach),
+ DEVMETHOD(device_detach, cfi_detach),
+
+ {0, 0}
+};
+
+static driver_t cfi_econa_driver = {
+ cfi_driver_name,
+ cfi_econa_methods,
+ sizeof(struct cfi_softc),
+};
+DRIVER_MODULE(cfi, econaarm, cfi_econa_driver, cfi_devclass, 0, 0);
Property changes on: trunk/sys/arm/cavium/cns11xx/cfi_bus_econa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/econa.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/econa.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/econa.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,653 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/econa.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/resource.h>
+
+#include "econa_reg.h"
+#include "econa_var.h"
+
+static struct econa_softc *econa_softc;
+
+unsigned int CPU_clock = 200000000;
+unsigned int AHB_clock;
+unsigned int APB_clock;
+
+bus_space_tag_t obio_tag;
+
+static int
+econa_probe(device_t dev)
+{
+
+ device_set_desc(dev, "ECONA device bus");
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+static void
+econa_identify(driver_t *drv, device_t parent)
+{
+
+ BUS_ADD_CHILD(parent, 0, "econaarm", 0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+extern void irq_entry(void);
+
+static void
+econa_add_child(device_t dev, int prio, const char *name, int unit,
+ bus_addr_t addr, bus_size_t size,
+ int irq0, int irq1,
+ int irq2, int irq3, int irq4)
+{
+ device_t kid;
+ struct econa_ivar *ivar;
+
+ kid = device_add_child_ordered(dev, prio, name, unit);
+ if (kid == NULL) {
+ printf("Can't add child %s%d ordered\n", name, unit);
+ return;
+ }
+ ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (ivar == NULL) {
+ device_delete_child(dev, kid);
+ return;
+ }
+ device_set_ivars(kid, ivar);
+ resource_list_init(&ivar->resources);
+ if (irq0 != -1)
+ bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
+ if (irq1 != 0)
+ bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
+ if (irq2 != 0)
+ bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
+ if (irq3 != 0)
+ bus_set_resource(kid, SYS_RES_IRQ, 3, irq3, 1);
+ if (irq4 != 0)
+ bus_set_resource(kid, SYS_RES_IRQ, 4, irq4, 1);
+
+ if (addr != 0)
+ bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
+
+}
+
+struct cpu_devs
+{
+ const char *name;
+ int unit;
+ bus_addr_t mem_base;
+ bus_size_t mem_len;
+ int irq0;
+ int irq1;
+ int irq2;
+ int irq3;
+ int irq4;
+};
+
+struct cpu_devs econarm_devs[] =
+{
+ {
+ "econa_ic", 0,
+ ECONA_IO_BASE + ECONA_PIC_BASE, ECONA_PIC_SIZE,
+ 0
+ },
+ {
+ "system", 0,
+ ECONA_IO_BASE + ECONA_SYSTEM_BASE, ECONA_SYSTEM_SIZE,
+ 0
+ },
+ {
+ "uart", 0,
+ ECONA_IO_BASE + ECONA_UART_BASE, ECONA_UART_SIZE,
+ ECONA_IRQ_UART
+ },
+ {
+ "timer", 0,
+ ECONA_IO_BASE + ECONA_TIMER_BASE, ECONA_TIMER_SIZE,
+ ECONA_IRQ_TIMER_1, ECONA_IRQ_TIMER_2
+ },
+ {
+ "ohci", 0,
+ ECONA_OHCI_VBASE, ECONA_OHCI_SIZE,
+ ECONA_IRQ_OHCI
+ },
+ {
+ "ehci", 0,
+ ECONA_EHCI_VBASE, ECONA_EHCI_SIZE,
+ ECONA_IRQ_EHCI
+ },
+ {
+ "cfi", 0,
+ ECONA_CFI_VBASE, ECONA_CFI_SIZE,
+ 0
+ },
+ {
+ "ece", 0,
+ ECONA_IO_BASE + ECONA_NET_BASE, ECONA_NET_SIZE,
+ ECONA_IRQ_STATUS,
+ ECONA_IRQ_TSTC, ECONA_IRQ_FSRC,
+ ECONA_IRQ_TSQE, ECONA_IRQ_FSQF,
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+};
+
+static void
+econa_cpu_add_builtin_children(device_t dev, struct econa_softc *sc)
+{
+ int i;
+ struct cpu_devs *walker;
+
+ for (i = 0, walker = econarm_devs; walker->name; i++, walker++) {
+ econa_add_child(dev, i, walker->name, walker->unit,
+ walker->mem_base, walker->mem_len,
+ walker->irq0,walker->irq1, walker->irq2,
+ walker->irq3, walker->irq4);
+ }
+
+}
+
+struct intc_trigger_t {
+ int mode;
+ int level;
+};
+
+static struct intc_trigger_t intc_trigger_table[] = {
+ {INTC_EDGE_TRIGGER, INTC_RISING_EDGE},
+ {INTC_EDGE_TRIGGER, INTC_RISING_EDGE},
+ {INTC_EDGE_TRIGGER, INTC_FALLING_EDGE},
+ {INTC_EDGE_TRIGGER, INTC_RISING_EDGE},
+ {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH},
+ {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH},
+ {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH},
+ {INTC_EDGE_TRIGGER, INTC_FALLING_EDGE},
+ {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN},
+ {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH},
+ {INTC_EDGE_TRIGGER, INTC_RISING_EDGE},
+ {INTC_EDGE_TRIGGER, INTC_RISING_EDGE},
+ {INTC_EDGE_TRIGGER, INTC_RISING_EDGE},
+ {INTC_EDGE_TRIGGER, INTC_RISING_EDGE},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW},
+ {INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW},
+};
+
+static inline uint32_t
+read_4(struct econa_softc *sc, bus_size_t off)
+{
+
+ return bus_space_read_4(sc->ec_st, sc->ec_sys_sh, off);
+}
+
+static inline void
+write_4(struct econa_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ return bus_space_write_4(sc->ec_st, sc->ec_sys_sh, off, val);
+}
+
+static inline uint32_t
+system_read_4(struct econa_softc *sc, bus_size_t off)
+{
+
+ return bus_space_read_4(sc->ec_st, sc->ec_system_sh, off);
+}
+
+static inline void
+system_write_4(struct econa_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ return bus_space_write_4(sc->ec_st, sc->ec_system_sh, off, val);
+}
+
+
+
+static inline void
+econa_set_irq_mode(struct econa_softc * sc, unsigned int irq,
+ unsigned int mode)
+{
+ unsigned int val;
+
+ if ((mode != INTC_LEVEL_TRIGGER) && (mode != INTC_EDGE_TRIGGER))
+ return;
+
+ val = read_4(sc, INTC_INTERRUPT_TRIGGER_MODE_REG_OFFSET);
+
+ if (mode == INTC_LEVEL_TRIGGER) {
+ if (val & (1UL << irq)) {
+ val &= ~(1UL << irq);
+ write_4(sc, INTC_INTERRUPT_TRIGGER_MODE_REG_OFFSET,
+ val);
+ }
+ } else {
+ if (!(val & (1UL << irq))) {
+ val |= (1UL << irq);
+ write_4(sc, INTC_INTERRUPT_TRIGGER_MODE_REG_OFFSET,
+ val);
+ }
+ }
+}
+
+/*
+ * Configure interrupt trigger level to be Active High/Low
+ * or Rising/Falling Edge
+ */
+static inline void
+econa_set_irq_level(struct econa_softc * sc,
+ unsigned int irq, unsigned int level)
+{
+ unsigned int val;
+
+ if ((level != INTC_ACTIVE_HIGH) &&
+ (level != INTC_ACTIVE_LOW) &&
+ (level != INTC_RISING_EDGE) &&
+ (level != INTC_FALLING_EDGE)) {
+ return;
+ }
+
+ val = read_4(sc, INTC_INTERRUPT_TRIGGER_LEVEL_REG_OFFSET);
+
+ if ((level == INTC_ACTIVE_HIGH) || (level == INTC_RISING_EDGE)) {
+ if (val & (1UL << irq)) {
+ val &= ~(1UL << irq);
+ write_4(sc, INTC_INTERRUPT_TRIGGER_LEVEL_REG_OFFSET,
+ val);
+ }
+ } else {
+ if (!(val & (1UL << irq))) {
+ val |= (1UL << irq);
+ write_4(sc, INTC_INTERRUPT_TRIGGER_LEVEL_REG_OFFSET,
+ val);
+ }
+ }
+}
+
+static void
+get_system_clock(void)
+{
+ uint32_t sclock = system_read_4(econa_softc, SYSTEM_CLOCK);
+
+ sclock = (sclock >> 6) & 0x03;
+
+ switch (sclock) {
+ case 0:
+ CPU_clock = 175000000;
+ break;
+ case 1:
+ CPU_clock = 200000000;
+ break;
+ case 2:
+ CPU_clock = 225000000;
+ break;
+ case 3:
+ CPU_clock = 250000000;
+ break;
+ }
+ AHB_clock = CPU_clock >> 1;
+ APB_clock = AHB_clock >> 1;
+}
+
+static int
+econa_attach(device_t dev)
+{
+ struct econa_softc *sc = device_get_softc(dev);
+ int i;
+
+ obio_tag = arm_base_bs_tag;
+
+ econa_softc = sc;
+ sc->ec_st = arm_base_bs_tag;
+ sc->ec_sh = ECONA_IO_BASE;
+ sc->dev = dev;
+ if (bus_space_subregion(sc->ec_st, sc->ec_sh, ECONA_PIC_BASE,
+ ECONA_PIC_SIZE, &sc->ec_sys_sh) != 0)
+ panic("Unable to map IRQ registers");
+
+ if (bus_space_subregion(sc->ec_st, sc->ec_sh, ECONA_SYSTEM_BASE,
+ ECONA_SYSTEM_SIZE, &sc->ec_system_sh) != 0)
+ panic("Unable to map IRQ registers");
+
+ sc->ec_irq_rman.rm_type = RMAN_ARRAY;
+ sc->ec_irq_rman.rm_descr = "ECONA IRQs";
+ sc->ec_mem_rman.rm_type = RMAN_ARRAY;
+ sc->ec_mem_rman.rm_descr = "ECONA Memory";
+ if (rman_init(&sc->ec_irq_rman) != 0 ||
+ rman_manage_region(&sc->ec_irq_rman, 0, 31) != 0)
+ panic("econa_attach: failed to set up IRQ rman");
+ if (rman_init(&sc->ec_mem_rman) != 0 ||
+ rman_manage_region(&sc->ec_mem_rman, 0,
+ ~0) != 0)
+ panic("econa_attach: failed to set up memory rman");
+
+ write_4(sc, INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET, 0xffffffff);
+
+ write_4(sc, INTC_INTERRUPT_MASK_REG_OFFSET, 0xffffffff);
+
+ write_4(sc, INTC_FIQ_MODE_SELECT_REG_OFFSET, 0);
+
+ /*initialize irq*/
+ for (i = 0; i < 32; i++) {
+ if (intc_trigger_table[i].mode != INTC_TRIGGER_UNKNOWN) {
+ econa_set_irq_mode(sc,i, intc_trigger_table[i].mode);
+ econa_set_irq_level(sc, i, intc_trigger_table[i].level);
+ }
+ }
+
+ get_system_clock();
+
+ econa_cpu_add_builtin_children(dev, sc);
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+ enable_interrupts(PSR_I | PSR_F);
+
+ return (0);
+}
+
+static struct resource *
+econa_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct econa_softc *sc = device_get_softc(dev);
+ struct resource_list_entry *rle;
+ struct econa_ivar *ivar = device_get_ivars(child);
+ struct resource_list *rl = &ivar->resources;
+
+ if (device_get_parent(child) != dev)
+ return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+ type, rid, start, end, count, flags));
+
+ rle = resource_list_find(rl, type, *rid);
+ if (rle == NULL) {
+ return (NULL);
+ }
+ if (rle->res)
+ panic("Resource rid %d type %d already in use", *rid, type);
+ if (start == 0UL && end == ~0UL) {
+ start = rle->start;
+ count = ulmax(count, rle->count);
+ end = ulmax(rle->end, start + count - 1);
+ }
+ switch (type)
+ {
+ case SYS_RES_IRQ:
+ rle->res = rman_reserve_resource(&sc->ec_irq_rman,
+ start, end, count, flags, child);
+ break;
+ case SYS_RES_MEMORY:
+ rle->res = rman_reserve_resource(&sc->ec_mem_rman,
+ start, end, count, flags, child);
+ if (rle->res != NULL) {
+ rman_set_bustag(rle->res, arm_base_bs_tag);
+ rman_set_bushandle(rle->res, start);
+ }
+ break;
+ }
+ if (rle->res) {
+ rle->start = rman_get_start(rle->res);
+ rle->end = rman_get_end(rle->res);
+ rle->count = count;
+ rman_set_rid(rle->res, *rid);
+ }
+ return (rle->res);
+}
+
+static struct resource_list *
+econa_get_resource_list(device_t dev, device_t child)
+{
+ struct econa_ivar *ivar;
+ ivar = device_get_ivars(child);
+ return (&(ivar->resources));
+}
+
+static int
+econa_release_resource(device_t dev, device_t child, int type,
+ int rid, struct resource *r)
+{
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+
+ rl = econa_get_resource_list(dev, child);
+ if (rl == NULL)
+ return (EINVAL);
+ rle = resource_list_find(rl, type, rid);
+ if (rle == NULL)
+ return (EINVAL);
+ rman_release_resource(r);
+ rle->res = NULL;
+ return (0);
+}
+
+static int
+econa_setup_intr(device_t dev, device_t child,
+ struct resource *ires, int flags, driver_filter_t *filt,
+ driver_intr_t *intr, void *arg, void **cookiep)
+{
+ int error;
+
+ if (rman_get_start(ires) == ECONA_IRQ_SYSTEM && filt == NULL)
+ panic("All system interrupt ISRs must be FILTER");
+
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ filt, intr, arg, cookiep);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static int
+econa_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
+static int
+econa_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ return (rman_activate_resource(r));
+}
+
+static int
+econa_print_child(device_t dev, device_t child)
+{
+ struct econa_ivar *ivars;
+ struct resource_list *rl;
+ int retval = 0;
+
+ ivars = device_get_ivars(child);
+ rl = &ivars->resources;
+
+ retval += bus_print_child_header(dev, child);
+
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ if (device_get_flags(dev))
+ retval += printf(" flags %#x", device_get_flags(dev));
+
+ retval += bus_print_child_footer(dev, child);
+
+ return (retval);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ unsigned int value;
+
+ value = read_4(econa_softc,INTC_INTERRUPT_MASK_REG_OFFSET) | 1<<nb;
+ write_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET, value);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ unsigned int value;
+
+ value = read_4(econa_softc,
+ INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET) | (1 << nb);
+ write_4(econa_softc,
+ INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET, value);
+ value = read_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET)& ~(1 << nb);
+ write_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET, value);
+}
+
+int
+arm_get_next_irq(int x)
+{
+ int irq;
+
+ irq = read_4(econa_softc, INTC_INTERRUPT_STATUS_REG_OFFSET) &
+ ~(read_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET));
+
+ if (irq!=0) {
+ return (ffs(irq) - 1);
+ }
+
+ return (-1);
+}
+
+void
+cpu_reset(void)
+{
+ uint32_t control;
+
+ control = system_read_4(econa_softc, RESET_CONTROL);
+ control |= GLOBAL_RESET;
+ system_write_4(econa_softc, RESET_CONTROL, control);
+ control = system_read_4(econa_softc, RESET_CONTROL);
+ control &= (~(GLOBAL_RESET));
+ system_write_4(econa_softc, RESET_CONTROL, control);
+ while (1);
+}
+
+
+
+void
+power_on_network_interface(void)
+{
+ uint32_t cfg_reg;
+ int ii;
+
+ cfg_reg = system_read_4(econa_softc, RESET_CONTROL);
+ cfg_reg |= NET_INTERFACE_RESET;
+ /* set reset bit to HIGH active; */
+ system_write_4(econa_softc, RESET_CONTROL, cfg_reg);
+
+ /*pulse delay */
+ for (ii = 0; ii < 0xFFF; ii++)
+ DELAY(100);
+ /* set reset bit to LOW active; */
+ cfg_reg = system_read_4(econa_softc, RESET_CONTROL);
+ cfg_reg &= ~(NET_INTERFACE_RESET);
+ system_write_4(econa_softc, RESET_CONTROL, cfg_reg);
+
+ /*pulse delay */
+ for (ii = 0; ii < 0xFFF; ii++)
+ DELAY(100);
+ cfg_reg = system_read_4(econa_softc, RESET_CONTROL);
+ cfg_reg |= NET_INTERFACE_RESET;
+ /* set reset bit to HIGH active; */
+ system_write_4(econa_softc, RESET_CONTROL, cfg_reg);
+}
+
+unsigned int
+get_tclk(void)
+{
+
+ return CPU_clock;
+}
+
+static device_method_t econa_methods[] = {
+ DEVMETHOD(device_probe, econa_probe),
+ DEVMETHOD(device_attach, econa_attach),
+ DEVMETHOD(device_identify, econa_identify),
+ DEVMETHOD(bus_alloc_resource, econa_alloc_resource),
+ DEVMETHOD(bus_setup_intr, econa_setup_intr),
+ DEVMETHOD(bus_teardown_intr, econa_teardown_intr),
+ DEVMETHOD(bus_activate_resource, econa_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_get_resource_list, econa_get_resource_list),
+ DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_release_resource, econa_release_resource),
+ DEVMETHOD(bus_print_child, econa_print_child),
+ {0, 0},
+};
+
+static driver_t econa_driver = {
+ "econaarm",
+ econa_methods,
+ sizeof(struct econa_softc),
+};
+static devclass_t econa_devclass;
+
+DRIVER_MODULE(econaarm, nexus, econa_driver, econa_devclass, 0, 0);
Property changes on: trunk/sys/arm/cavium/cns11xx/econa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/econa_machdep.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/econa_machdep.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/econa_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,344 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/econa_machdep.c 266386 2014-05-18 00:32:35Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/cons.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/kdb.h>
+#include <sys/msgbuf.h>
+#include <machine/physmem.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <machine/devmap.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <sys/reboot.h>
+#include "econa_reg.h"
+
+/* Page table for mapping proc0 zero page */
+#define KERNEL_PT_SYS 0
+#define KERNEL_PT_KERN 1
+#define KERNEL_PT_KERN_NUM 22
+/* L2 table for mapping after kernel */
+#define KERNEL_PT_AFKERNEL KERNEL_PT_KERN + KERNEL_PT_KERN_NUM
+#define KERNEL_PT_AFKERNEL_NUM 5
+
+/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
+#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
+
+struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
+
+/* Physical and virtual addresses for some global pages */
+
+struct pv_addr systempage;
+struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+struct pv_addr kernelstack;
+
+/* Static device mappings. */
+static const struct arm_devmap_entry econa_devmap[] = {
+ {
+ /*
+ * This maps DDR SDRAM
+ */
+ ECONA_SDRAM_BASE, /*virtual*/
+ ECONA_SDRAM_BASE, /*physical*/
+ ECONA_SDRAM_SIZE, /*size*/
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ /*
+ * Map the on-board devices VA == PA so that we can access them
+ * with the MMU on or off.
+ */
+ {
+ /*
+ * This maps the interrupt controller, the UART
+ * and the timer.
+ */
+ ECONA_IO_BASE, /*virtual*/
+ ECONA_IO_BASE, /*physical*/
+ ECONA_IO_SIZE, /*size*/
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ /*
+ * OHCI + EHCI
+ */
+ ECONA_OHCI_VBASE, /*virtual*/
+ ECONA_OHCI_PBASE, /*physical*/
+ ECONA_USB_SIZE, /*size*/
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ /*
+ * CFI
+ */
+ ECONA_CFI_VBASE, /*virtual*/
+ ECONA_CFI_PBASE, /*physical*/
+ ECONA_CFI_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ }
+};
+
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+ struct pv_addr kernel_l1pt;
+ volatile uint32_t * ddr = (uint32_t *)0x4000000C;
+ int loop, i;
+ u_int l1pagetable;
+ vm_offset_t afterkern;
+ vm_offset_t freemempos;
+ vm_offset_t lastaddr;
+ uint32_t memsize;
+ int mem_info;
+
+ boothowto = RB_VERBOSE;
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+ set_cpufuncs();
+ pcpu0_init();
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+
+ freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK;
+ /* Define a macro to simplify memory allocation */
+#define valloc_pages(var, np) \
+ alloc_pages((var).pv_va, (np)); \
+ (var).pv_pa = (var).pv_va + (abp->abp_physaddr - KERNVIRTADDR);
+
+#define alloc_pages(var, np) \
+ (var) = freemempos; \
+ freemempos += (np * PAGE_SIZE); \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos += PAGE_SIZE;
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[loop],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ } else {
+ kernel_pt_table[loop].pv_va = freemempos -
+ (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
+ L2_TABLE_SIZE_REAL;
+ kernel_pt_table[loop].pv_pa =
+ kernel_pt_table[loop].pv_va - KERNVIRTADDR +
+ abp->abp_physaddr;
+ }
+ }
+ /*
+ * Allocate a page for the system page mapped to V0x00000000
+ * This page will just contain the system vectors and can be
+ * shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE);
+ valloc_pages(abtstack, ABT_STACK_SIZE);
+ valloc_pages(undstack, UND_STACK_SIZE);
+ valloc_pages(kernelstack, KSTACK_PAGES);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+
+ /*
+ * Now we start construction of the L1 page table
+ * We start by mapping the L2 page tables into the L1.
+ * This means that we can replace L1 mappings later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /* Map the L2 pages tables in the L1 page table */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH,
+ &kernel_pt_table[KERNEL_PT_SYS]);
+ for (i = 0; i < KERNEL_PT_KERN_NUM; i++)
+ pmap_link_l2pt(l1pagetable, KERNBASE + i * L1_S_SIZE,
+ &kernel_pt_table[KERNEL_PT_KERN + i]);
+ pmap_map_chunk(l1pagetable, KERNBASE, PHYSADDR,
+ (((uint32_t)lastaddr - KERNBASE) + PAGE_SIZE) & ~(PAGE_SIZE - 1),
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ afterkern = round_page((lastaddr + L1_S_SIZE) & ~(L1_S_SIZE - 1));
+ for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
+ pmap_link_l2pt(l1pagetable, afterkern + i * L1_S_SIZE,
+ &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
+ }
+
+ /* Map the vector page. */
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+
+ /* Map the stack pages */
+ pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa,
+ IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa,
+ ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa,
+ UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa,
+ KSTACK_PAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
+ L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ pmap_map_chunk(l1pagetable, msgbufpv.pv_va, msgbufpv.pv_pa,
+ msgbufsize, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va,
+ kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ }
+
+ arm_devmap_bootstrap(l1pagetable, econa_devmap);
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
+ cninit();
+ mem_info = ((*ddr) >> 4) & 0x3;
+ memsize = (8<<mem_info)*1024*1024;
+
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+ cpu_control(CPU_CONTROL_MMU_ENABLE, CPU_CONTROL_MMU_ENABLE);
+
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+ cpu_setup("");
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+
+ pmap_curmaxkvaddr = afterkern + L1_S_SIZE * (KERNEL_PT_KERN_NUM - 1);
+ vm_max_kernel_address = KERNVIRTADDR + 3 * memsize;
+ pmap_bootstrap(freemempos, &kernel_l1pt);
+
+ msgbufp = (void*)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+
+ mutex_init();
+
+ /*
+ * Add the physical ram we have available.
+ *
+ * Exclude the kernel, and all the things we allocated which immediately
+ * follow the kernel, from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ arm_physmem_hardware_region(PHYSADDR, memsize);
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+}
Property changes on: trunk/sys/arm/cavium/cns11xx/econa_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/econa_reg.h
===================================================================
--- trunk/sys/arm/cavium/cns11xx/econa_reg.h (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/econa_reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,181 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/cavium/cns11xx/econa_reg.h 201468 2010-01-04 03:35:45Z rpaulo $
+ */
+#ifndef _ARM_ECONA_REG_H
+#define _ARM_ECONA_REG_H
+
+#define ECONA_SRAM_SIZE 0x10000000
+#define ECONA_DRAM_BASE 0x00000000 /* DRAM (via DDR Control Module) */
+
+#define ECONA_SDRAM_BASE 0x40000000
+#define ECONA_SDRAM_SIZE 0x1000000
+
+
+#define ECONA_IO_BASE 0x70000000
+#define ECONA_IO_SIZE 0x0E000000
+#define ECONA_PIC_BASE 0x0D000000
+#define ECONA_PIC_SIZE 0x01000000
+
+#define ECONA_UART_BASE 0x08000000
+#define ECONA_UART_SIZE 0x01000000
+#define ECONA_IRQ_UART 0xA
+
+#define ECONA_TIMER_BASE 0x09000000
+#define ECONA_TIMER_SIZE 0x01000000
+#define ECONA_IRQ_TIMER_1 0
+#define ECONA_IRQ_TIMER_2 1
+#define ECONA_IRQ_OHCI 23
+#define ECONA_IRQ_EHCI 24
+
+#define ECONA_NET_BASE 0x00000000
+
+#define ECONA_SYSTEM_BASE 0x07000000
+#define ECONA_SYSTEM_SIZE 0x01000000
+
+#define ECONA_NET_SIZE 0x01000000
+
+#define ECONA_CFI_PBASE 0x10000000
+#define ECONA_CFI_VBASE 0xD0000000
+#define ECONA_CFI_SIZE 0x10000000
+
+#define ECONA_IRQ_STATUS 18
+#define ECONA_IRQ_TSTC 19
+#define ECONA_IRQ_FSRC 20
+#define ECONA_IRQ_TSQE 21
+#define ECONA_IRQ_FSQF 22
+
+#define ECONA_IRQ_SYSTEM 0
+
+#define ECONA_EHCI_PBASE 0xC8000000
+#define ECONA_EHCI_VBASE 0xF8000000
+#define ECONA_EHCI_SIZE 0x8000000
+
+#define ECONA_OHCI_PBASE 0xC0000000
+#define ECONA_OHCI_VBASE 0xF0000000
+#define ECONA_OHCI_SIZE 0x8000000
+
+#define ECONA_USB_SIZE 0xf000000
+
+/*Interrupt controller*/
+#define INTC_LEVEL_TRIGGER 0
+#define INTC_EDGE_TRIGGER 1
+#define INTC_ACTIVE_HIGH 0
+#define INTC_ACTIVE_LOW 1
+/*
+ * define rising/falling edge for edge trigger mode
+ */
+#define INTC_RISING_EDGE 0
+#define INTC_FALLING_EDGE 1
+
+#define INTC_INTERRUPT_SOURCE_REG_OFFSET 0x00
+#define INTC_INTERRUPT_MASK_REG_OFFSET 0x04
+#define INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET 0x08
+#define INTC_INTERRUPT_TRIGGER_MODE_REG_OFFSET 0x0C
+#define INTC_INTERRUPT_TRIGGER_LEVEL_REG_OFFSET 0x10
+#define INTC_INTERRUPT_STATUS_REG_OFFSET 0x14
+#define INTC_FIQ_MODE_SELECT_REG_OFFSET 0x18
+#define INTC_SOFTWARE_INTERRUPT_REG_OFFSET 0x1C
+
+
+/*
+ * define rising/falling edge for edge trigger mode
+ */
+#define INTC_RISING_EDGE 0
+#define INTC_FALLING_EDGE 1
+
+
+#define TIMER_TM1_COUNTER_REG 0x00
+#define TIMER_TM1_LOAD_REG 0x04
+#define TIMER_TM1_MATCH1_REG 0x08
+#define TIMER_TM1_MATCH2_REG 0x0C
+
+#define TIMER_TM2_COUNTER_REG 0x10
+#define TIMER_TM2_LOAD_REG 0x14
+#define TIMER_TM2_MATCH1_REG 0x18
+#define TIMER_TM2_MATCH2_REG 0x1C
+
+#define TIMER_TM_CR_REG 0x30
+#define TIMER_TM_INTR_STATUS_REG 0x34
+#define TIMER_TM_INTR_MASK_REG 0x38
+
+#define TIMER_TM_REVISION_REG 0x3C
+
+
+#define INTC_TIMER1_BIT_INDEX 0
+
+#define TIMER1_UP_DOWN_COUNT (1<<9)
+#define TIMER2_UP_DOWN_COUNT (1<<10)
+
+#define TIMER1_MATCH1_INTR (1<<0)
+#define TIMER1_MATCH2_INTR (1<<1)
+#define TIMER1_OVERFLOW_INTR (1<<2)
+
+
+#define TIMER2_MATCH1_INTR (1<<3)
+#define TIMER2_MATCH2_INTR (1<<4)
+#define TIMER2_OVERFLOW_INTR (1<<5)
+
+
+#define TIMER_CLOCK_SOURCE_PCLK 0
+#define TIMER_CLOCK_SOURCE_EXT_CLK 1
+
+/*
+ * define interrupt trigger mode
+ */
+#define INTC_LEVEL_TRIGGER 0
+#define INTC_EDGE_TRIGGER 1
+
+
+#define INTC_TRIGGER_UNKNOWN -1
+
+#define TIMER1_OVERFLOW_INTERRUPT (1<<2)
+#define TIMER2_OVERFLOW_INTERRUPT (1<<5)
+#define TIMER_INTERRUPT_STATUS_REG 0x34
+
+
+#define TIMER1_ENABLE (1<<0)
+#define TIMER1_CLOCK_SOURCE (1<<1)
+#define TIMER1_OVERFLOW_ENABLE (1<<2)
+
+
+#define TIMER2_ENABLE (1<<3)
+#define TIMER2_CLOCK_SOURCE (1<<4)
+#define TIMER2_OVERFLOW_ENABLE (1<<5)
+
+
+#define TIMER_1 1
+
+#define EC_UART_CLOCK 14769200
+#define EC_UART_REGSHIFT 2
+
+#define SYSTEM_CLOCK 0x14
+#define RESET_CONTROL 0x4
+#define GLOBAL_RESET 0x1
+#define NET_INTERFACE_RESET (0x1 << 4)
+
+#endif
Property changes on: trunk/sys/arm/cavium/cns11xx/econa_reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/econa_var.h
===================================================================
--- trunk/sys/arm/cavium/cns11xx/econa_var.h (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/econa_var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,53 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/cavium/cns11xx/econa_var.h 201468 2010-01-04 03:35:45Z rpaulo $
+ */
+
+#ifndef _ARM_ECONA_VAR_H
+#define _ARM_ECONA_VAR_H
+
+extern bus_space_tag_t obio_tag;
+
+struct econa_softc {
+ device_t dev;
+ bus_space_tag_t ec_st;
+ bus_space_handle_t ec_sh;
+ bus_space_handle_t ec_sys_sh;
+ bus_space_handle_t ec_system_sh;
+ struct rman ec_irq_rman;
+ struct rman ec_mem_rman;
+};
+
+struct econa_ivar {
+ struct resource_list resources;
+};
+
+void power_on_network_interface (void);
+unsigned int get_tclk (void);
+
+
+#endif
Property changes on: trunk/sys/arm/cavium/cns11xx/econa_var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/ehci_ebus.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/ehci_ebus.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/ehci_ebus.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,249 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * based on ehci_mbus.c
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/ehci_ebus.c 308402 2016-11-07 09:19:04Z hselasky $");
+
+#include "opt_bus.h"
+
+#include <machine/resource.h>
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <sys/rman.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+
+static device_attach_t ehci_ebus_attach;
+static device_detach_t ehci_ebus_detach;
+
+static void *ih_err;
+
+#define EHCI_HC_DEVSTR "CNS11XX USB EHCI"
+#define USB_BRIDGE_INTR_MASK 0x214
+
+static int
+ehci_ebus_probe(device_t self)
+{
+
+ device_set_desc(self, EHCI_HC_DEVSTR);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ehci_ebus_attach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ bus_space_handle_t bsh;
+ int err;
+ int rid;
+
+ /* initialise some bus fields */
+ sc->sc_bus.parent = self;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus,
+ USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
+ return (ENOMEM);
+ }
+
+ sc->sc_bus.usbrev = USB_REV_2_0;
+
+ rid = 0;
+ sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE);
+ if (!sc->sc_io_res) {
+ device_printf(self, "Could not map memory\n");
+ goto error;
+ }
+ sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+ bsh = rman_get_bushandle(sc->sc_io_res);
+
+ /*magic, undocumented initialization*/
+ bus_space_write_4((sc)->sc_io_tag, bsh, 0x04, 0x106);
+
+ bus_space_write_4((sc)->sc_io_tag, bsh, 0x40, (3 << 5)|0x2000);
+
+ DELAY(1000);
+
+ sc->sc_io_size = 4096;
+
+ if (bus_space_subregion(sc->sc_io_tag, bsh, 0x4000000,
+ sc->sc_io_size, &sc->sc_io_hdl) != 0)
+ panic("%s: unable to subregion USB host registers",
+ device_get_name(self));
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(self, "Could not allocate irq\n");
+ ehci_ebus_detach(self);
+ return (ENXIO);
+ }
+
+ sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(self, "Could not add USB device\n");
+ goto error;
+ }
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+ device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);
+
+ sprintf(sc->sc_vendor, "Cavium");
+
+ err = bus_setup_intr(self,sc->sc_irq_res,
+ INTR_TYPE_BIO | INTR_MPSAFE, NULL,
+ (driver_intr_t *)ehci_interrupt, sc,
+ &sc->sc_intr_hdl);
+ if (err) {
+ device_printf(self, "Could not setup error irq, %d\n", err);
+ ih_err = NULL;
+ goto error;
+ }
+
+ err = ehci_init(sc);
+ if (!err) {
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ }
+ if (err) {
+ device_printf(self, "USB init failed err=%d\n", err);
+ goto error;
+ }
+ return (0);
+
+error:
+ ehci_ebus_detach(self);
+ return (ENXIO);
+}
+
+static int
+ehci_ebus_detach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ int err;
+
+ /* during module unload there are lots of children leftover */
+ device_delete_children(self);
+
+ /*
+ * disable interrupts that might have been switched on in
+ * ehci_ebus_attach()
+ */
+ if (sc->sc_io_res) {
+ EWRITE4(sc, USB_BRIDGE_INTR_MASK, 0);
+ }
+ if (sc->sc_irq_res && sc->sc_intr_hdl) {
+ /*
+ * only call ehci_detach() after ehci_init()
+ */
+ ehci_detach(sc);
+
+ err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
+
+ if (err)
+ /* XXX or should we panic? */
+ device_printf(self, "Could not tear down irq, %d\n",
+ err);
+ sc->sc_intr_hdl = NULL;
+ }
+ if (sc->sc_irq_res) {
+ bus_release_resource(self, SYS_RES_IRQ, 1, sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+ if (sc->sc_io_res) {
+ bus_release_resource(self, SYS_RES_MEMORY, 0,
+ sc->sc_io_res);
+ sc->sc_io_res = NULL;
+ }
+ usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
+
+ return (0);
+}
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ehci_ebus_probe),
+ DEVMETHOD(device_attach, ehci_ebus_attach),
+ DEVMETHOD(device_detach, ehci_ebus_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD_END
+};
+
+static driver_t ehci_driver = {
+ .name = "ehci",
+ .methods = ehci_methods,
+ .size = sizeof(ehci_softc_t),
+};
+
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, econaarm, ehci_driver, ehci_devclass, 0, 0);
+MODULE_DEPEND(ehci, usb, 1, 1, 1);
Property changes on: trunk/sys/arm/cavium/cns11xx/ehci_ebus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/files.econa
===================================================================
--- trunk/sys/arm/cavium/cns11xx/files.econa (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/files.econa 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,14 @@
+# $FreeBSD: stable/10/sys/arm/cavium/cns11xx/files.econa 278727 2015-02-13 22:32:02Z ian $
+arm/arm/cpufunc_asm_fa526.S standard
+arm/cavium/cns11xx/econa_machdep.c standard
+arm/cavium/cns11xx/econa.c standard
+arm/cavium/cns11xx/timer.c standard
+arm/cavium/cns11xx/uart_bus_ec.c optional uart
+arm/cavium/cns11xx/uart_cpu_ec.c optional uart
+dev/uart/uart_dev_ns8250.c optional uart
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/cavium/cns11xx/ehci_ebus.c optional ehci
+arm/cavium/cns11xx/ohci_ec.c optional ohci
+arm/cavium/cns11xx/if_ece.c standard
+arm/cavium/cns11xx/cfi_bus_econa.c optional cfi
Property changes on: trunk/sys/arm/cavium/cns11xx/files.econa
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/if_ece.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/if_ece.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/if_ece.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1948 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/if_ece.c 264219 2014-04-07 05:33:30Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+#include <net/if_vlan_var.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <arm/cavium/cns11xx/if_ecereg.h>
+#include <arm/cavium/cns11xx/if_ecevar.h>
+#include <arm/cavium/cns11xx/econa_var.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+/* "device miibus" required. See GENERIC if you get errors here. */
+#include "miibus_if.h"
+
+static uint8_t
+vlan0_mac[ETHER_ADDR_LEN] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x19};
+
+/*
+ * Boot loader expects the hardware state to be the same when we
+ * restart the device (warm boot), so we need to save the initial
+ * config values.
+ */
+int initial_switch_config;
+int initial_cpu_config;
+int initial_port0_config;
+int initial_port1_config;
+
+static inline uint32_t
+read_4(struct ece_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+write_4(struct ece_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+#define ECE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define ECE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define ECE_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+ MTX_NETWORK_LOCK, MTX_DEF)
+
+#define ECE_TXLOCK(_sc) mtx_lock(&(_sc)->sc_mtx_tx)
+#define ECE_TXUNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx_tx)
+#define ECE_TXLOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx_tx, device_get_nameunit(_sc->dev), \
+ "ECE TX Lock", MTX_DEF)
+
+#define ECE_CLEANUPLOCK(_sc) mtx_lock(&(_sc)->sc_mtx_cleanup)
+#define ECE_CLEANUPUNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx_cleanup)
+#define ECE_CLEANUPLOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx_cleanup, device_get_nameunit(_sc->dev), \
+ "ECE cleanup Lock", MTX_DEF)
+
+#define ECE_RXLOCK(_sc) mtx_lock(&(_sc)->sc_mtx_rx)
+#define ECE_RXUNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx_rx)
+#define ECE_RXLOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx_rx, device_get_nameunit(_sc->dev), \
+ "ECE RX Lock", MTX_DEF)
+
+#define ECE_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define ECE_TXLOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx_tx);
+#define ECE_RXLOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx_rx);
+#define ECE_CLEANUPLOCK_DESTROY(_sc) \
+ mtx_destroy(&_sc->sc_mtx_cleanup);
+
+#define ECE_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define ECE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+static devclass_t ece_devclass;
+
+/* ifnet entry points */
+
+static void eceinit_locked(void *);
+static void ecestart_locked(struct ifnet *);
+
+static void eceinit(void *);
+static void ecestart(struct ifnet *);
+static void ecestop(struct ece_softc *);
+static int eceioctl(struct ifnet * ifp, u_long, caddr_t);
+
+/* bus entry points */
+
+static int ece_probe(device_t dev);
+static int ece_attach(device_t dev);
+static int ece_detach(device_t dev);
+static void ece_intr(void *);
+static void ece_intr_qf(void *);
+static void ece_intr_status(void *xsc);
+
+/* helper routines */
+static int ece_activate(device_t dev);
+static void ece_deactivate(device_t dev);
+static int ece_ifmedia_upd(struct ifnet *ifp);
+static void ece_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
+static int ece_get_mac(struct ece_softc *sc, u_char *eaddr);
+static void ece_set_mac(struct ece_softc *sc, u_char *eaddr);
+static int configure_cpu_port(struct ece_softc *sc);
+static int configure_lan_port(struct ece_softc *sc, int phy_type);
+static void set_pvid(struct ece_softc *sc, int port0, int port1, int cpu);
+static void set_vlan_vid(struct ece_softc *sc, int vlan);
+static void set_vlan_member(struct ece_softc *sc, int vlan);
+static void set_vlan_tag(struct ece_softc *sc, int vlan);
+static int hardware_init(struct ece_softc *sc);
+static void ece_intr_rx_locked(struct ece_softc *sc, int count);
+
+static void ece_free_desc_dma_tx(struct ece_softc *sc);
+static void ece_free_desc_dma_rx(struct ece_softc *sc);
+
+static void ece_intr_task(void *arg, int pending __unused);
+static void ece_tx_task(void *arg, int pending __unused);
+static void ece_cleanup_task(void *arg, int pending __unused);
+
+static int ece_allocate_dma(struct ece_softc *sc);
+
+static void ece_intr_tx(void *xsc);
+
+static void clear_mac_entries(struct ece_softc *ec, int include_this_mac);
+
+static uint32_t read_mac_entry(struct ece_softc *ec,
+ uint8_t *mac_result,
+ int first);
+
+/*PHY related functions*/
+static inline int
+phy_read(struct ece_softc *sc, int phy, int reg)
+{
+ int val;
+ int ii;
+ int status;
+
+ write_4(sc, PHY_CONTROL, PHY_RW_OK);
+ write_4(sc, PHY_CONTROL,
+ (PHY_ADDRESS(phy)|PHY_READ_COMMAND |
+ PHY_REGISTER(reg)));
+
+ for (ii = 0; ii < 0x1000; ii++) {
+ status = read_4(sc, PHY_CONTROL);
+ if (status & PHY_RW_OK) {
+ /* Clear the rw_ok status, and clear other
+ * bits value. */
+ write_4(sc, PHY_CONTROL, PHY_RW_OK);
+ val = PHY_GET_DATA(status);
+ return (val);
+ }
+ }
+ return (0);
+}
+
+static inline void
+phy_write(struct ece_softc *sc, int phy, int reg, int data)
+{
+ int ii;
+
+ write_4(sc, PHY_CONTROL, PHY_RW_OK);
+ write_4(sc, PHY_CONTROL,
+ PHY_ADDRESS(phy) | PHY_REGISTER(reg) |
+ PHY_WRITE_COMMAND | PHY_DATA(data));
+ for (ii = 0; ii < 0x1000; ii++) {
+ if (read_4(sc, PHY_CONTROL) & PHY_RW_OK) {
+ /* Clear the rw_ok status, and clear other
+ * bits value.
+ */
+ write_4(sc, PHY_CONTROL, PHY_RW_OK);
+ return;
+ }
+ }
+}
+
+static int get_phy_type(struct ece_softc *sc)
+{
+ uint16_t phy0_id = 0, phy1_id = 0;
+
+ /*
+ * Use SMI (MDC/MDIO) to read Link Partner's PHY Identifier
+ * Register 1.
+ */
+ phy0_id = phy_read(sc, 0, 0x2);
+ phy1_id = phy_read(sc, 1, 0x2);
+
+ if ((phy0_id == 0xFFFF) && (phy1_id == 0x000F))
+ return (ASIX_GIGA_PHY);
+ else if ((phy0_id == 0x0243) && (phy1_id == 0x0243))
+ return (TWO_SINGLE_PHY);
+ else if ((phy0_id == 0xFFFF) && (phy1_id == 0x0007))
+ return (VSC8601_GIGA_PHY);
+ else if ((phy0_id == 0x0243) && (phy1_id == 0xFFFF))
+ return (IC_PLUS_PHY);
+
+ return (NOT_FOUND_PHY);
+}
+
+static int
+ece_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Econa Ethernet Controller");
+ return (0);
+}
+
+
+static int
+ece_attach(device_t dev)
+{
+ struct ece_softc *sc;
+ struct ifnet *ifp = NULL;
+ struct sysctl_ctx_list *sctx;
+ struct sysctl_oid *soid;
+ u_char eaddr[ETHER_ADDR_LEN];
+ int err;
+ int i, rid;
+ uint32_t rnd;
+
+ err = 0;
+
+ sc = device_get_softc(dev);
+
+ sc->dev = dev;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ goto out;
+
+ power_on_network_interface();
+
+ rid = 0;
+ sc->irq_res_status = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res_status == NULL)
+ goto out;
+
+ rid = 1;
+ /*TSTC: Fm-Switch-Tx-Complete*/
+ sc->irq_res_tx = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res_tx == NULL)
+ goto out;
+
+ rid = 2;
+ /*FSRC: Fm-Switch-Rx-Complete*/
+ sc->irq_res_rec = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res_rec == NULL)
+ goto out;
+
+ rid = 4;
+ /*FSQF: Fm-Switch-Queue-Full*/
+ sc->irq_res_qf = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res_qf == NULL)
+ goto out;
+
+ err = ece_activate(dev);
+ if (err)
+ goto out;
+
+ /* Sysctls */
+ sctx = device_get_sysctl_ctx(dev);
+ soid = device_get_sysctl_tree(dev);
+
+ ECE_LOCK_INIT(sc);
+
+ callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
+
+ if ((err = ece_get_mac(sc, eaddr)) != 0) {
+ /* No MAC address configured. Generate the random one. */
+ if (bootverbose)
+ device_printf(dev,
+ "Generating random ethernet address.\n");
+ rnd = arc4random();
+
+ /*from if_ae.c/if_ate.c*/
+ /*
+ * Set OUI to convenient locally assigned address. 'b'
+ * is 0x62, which has the locally assigned bit set, and
+ * the broadcast/multicast bit clear.
+ */
+ eaddr[0] = 'b';
+ eaddr[1] = 's';
+ eaddr[2] = 'd';
+ eaddr[3] = (rnd >> 16) & 0xff;
+ eaddr[4] = (rnd >> 8) & 0xff;
+ eaddr[5] = rnd & 0xff;
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ eaddr[i] = vlan0_mac[i];
+ }
+ ece_set_mac(sc, eaddr);
+ sc->ifp = ifp = if_alloc(IFT_ETHER);
+ /* Only one PHY at address 0 in this device. */
+ err = mii_attach(dev, &sc->miibus, ifp, ece_ifmedia_upd,
+ ece_ifmedia_sts, BMSR_DEFCAPMASK, 0, MII_OFFSET_ANY, 0);
+ if (err != 0) {
+ device_printf(dev, "attaching PHYs failed\n");
+ goto out;
+ }
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+
+ ifp->if_capabilities = IFCAP_HWCSUM;
+
+ ifp->if_hwassist = (CSUM_IP | CSUM_TCP | CSUM_UDP);
+ ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_start = ecestart;
+ ifp->if_ioctl = eceioctl;
+ ifp->if_init = eceinit;
+ ifp->if_snd.ifq_drv_maxlen = ECE_MAX_TX_BUFFERS - 1;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ECE_MAX_TX_BUFFERS - 1);
+ IFQ_SET_READY(&ifp->if_snd);
+
+ /* Create local taskq. */
+
+ TASK_INIT(&sc->sc_intr_task, 0, ece_intr_task, sc);
+ TASK_INIT(&sc->sc_tx_task, 1, ece_tx_task, ifp);
+ TASK_INIT(&sc->sc_cleanup_task, 2, ece_cleanup_task, sc);
+ sc->sc_tq = taskqueue_create_fast("ece_taskq", M_WAITOK,
+ taskqueue_thread_enqueue,
+ &sc->sc_tq);
+ if (sc->sc_tq == NULL) {
+ device_printf(sc->dev, "could not create taskqueue\n");
+ goto out;
+ }
+
+ ether_ifattach(ifp, eaddr);
+
+ /*
+ * Activate interrupts
+ */
+ err = bus_setup_intr(dev, sc->irq_res_rec, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, ece_intr, sc, &sc->intrhand);
+ if (err) {
+ ether_ifdetach(ifp);
+ ECE_LOCK_DESTROY(sc);
+ goto out;
+ }
+
+ err = bus_setup_intr(dev, sc->irq_res_status,
+ INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, ece_intr_status, sc, &sc->intrhand_status);
+ if (err) {
+ ether_ifdetach(ifp);
+ ECE_LOCK_DESTROY(sc);
+ goto out;
+ }
+
+ err = bus_setup_intr(dev, sc->irq_res_qf, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL,ece_intr_qf, sc, &sc->intrhand_qf);
+
+ if (err) {
+ ether_ifdetach(ifp);
+ ECE_LOCK_DESTROY(sc);
+ goto out;
+ }
+
+ err = bus_setup_intr(dev, sc->irq_res_tx, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, ece_intr_tx, sc, &sc->intrhand_tx);
+
+ if (err) {
+ ether_ifdetach(ifp);
+ ECE_LOCK_DESTROY(sc);
+ goto out;
+ }
+
+ ECE_TXLOCK_INIT(sc);
+ ECE_RXLOCK_INIT(sc);
+ ECE_CLEANUPLOCK_INIT(sc);
+
+ /* Enable all interrupt sources. */
+ write_4(sc, INTERRUPT_MASK, 0x00000000);
+
+ /* Enable port 0. */
+ write_4(sc, PORT_0_CONFIG, read_4(sc, PORT_0_CONFIG) & ~(PORT_DISABLE));
+
+ taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
+ device_get_nameunit(sc->dev));
+
+out:
+ if (err)
+ ece_deactivate(dev);
+ if (err && ifp)
+ if_free(ifp);
+ return (err);
+}
+
+static int
+ece_detach(device_t dev)
+{
+ struct ece_softc *sc = device_get_softc(dev);
+ struct ifnet *ifp = sc->ifp;
+
+ ecestop(sc);
+ if (ifp != NULL) {
+ ether_ifdetach(ifp);
+ if_free(ifp);
+ }
+ ece_deactivate(dev);
+ return (0);
+}
+
+static void
+ece_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ u_int32_t *paddr;
+ KASSERT(nsegs == 1, ("wrong number of segments, should be 1"));
+ paddr = arg;
+ *paddr = segs->ds_addr;
+}
+
+static int
+ece_alloc_desc_dma_tx(struct ece_softc *sc)
+{
+ int i;
+ int error;
+
+ /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
+ error = bus_dma_tag_create(sc->sc_parent_tag, /* parent */
+ 16, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ sizeof(eth_tx_desc_t)*ECE_MAX_TX_BUFFERS, /* max size */
+ 1, /*nsegments */
+ sizeof(eth_tx_desc_t)*ECE_MAX_TX_BUFFERS,
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->dmatag_data_tx); /* dmat */
+
+ /* Allocate memory for TX ring. */
+ error = bus_dmamem_alloc(sc->dmatag_data_tx,
+ (void**)&(sc->desc_tx),
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO |
+ BUS_DMA_COHERENT,
+ &(sc->dmamap_ring_tx));
+
+ if (error) {
+ if_printf(sc->ifp, "failed to allocate DMA memory\n");
+ bus_dma_tag_destroy(sc->dmatag_data_tx);
+ sc->dmatag_data_tx = 0;
+ return (ENXIO);
+ }
+
+ /* Load Ring DMA. */
+ error = bus_dmamap_load(sc->dmatag_data_tx, sc->dmamap_ring_tx,
+ sc->desc_tx,
+ sizeof(eth_tx_desc_t)*ECE_MAX_TX_BUFFERS,
+ ece_getaddr,
+ &(sc->ring_paddr_tx), BUS_DMA_NOWAIT);
+
+ if (error) {
+ if_printf(sc->ifp, "can't load descriptor\n");
+ bus_dmamem_free(sc->dmatag_data_tx, sc->desc_tx,
+ sc->dmamap_ring_tx);
+ sc->desc_tx = NULL;
+ bus_dma_tag_destroy(sc->dmatag_data_tx);
+ sc->dmatag_data_tx = 0;
+ return (ENXIO);
+ }
+
+ /* Allocate a busdma tag for mbufs. Alignment is 2 bytes */
+ error = bus_dma_tag_create(sc->sc_parent_tag, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ MCLBYTES*MAX_FRAGMENT, /* maxsize */
+ MAX_FRAGMENT, /* nsegments */
+ MCLBYTES, 0, /* maxsegsz, flags */
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->dmatag_ring_tx); /* dmat */
+
+ if (error) {
+ if_printf(sc->ifp, "failed to create busdma tag for mbufs\n");
+ return (ENXIO);
+ }
+
+ for (i = 0; i < ECE_MAX_TX_BUFFERS; i++) {
+ /* Create dma map for each descriptor. */
+ error = bus_dmamap_create(sc->dmatag_ring_tx, 0,
+ &(sc->tx_desc[i].dmamap));
+ if (error) {
+ if_printf(sc->ifp, "failed to create map for mbuf\n");
+ return (ENXIO);
+ }
+ }
+ return (0);
+}
+
+static void
+ece_free_desc_dma_tx(struct ece_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < ECE_MAX_TX_BUFFERS; i++) {
+ if (sc->tx_desc[i].buff) {
+ m_freem(sc->tx_desc[i].buff);
+ sc->tx_desc[i].buff= 0;
+ }
+ }
+
+ if (sc->dmamap_ring_tx) {
+ bus_dmamap_unload(sc->dmatag_data_tx, sc->dmamap_ring_tx);
+ if (sc->desc_tx) {
+ bus_dmamem_free(sc->dmatag_data_tx,
+ sc->desc_tx, sc->dmamap_ring_tx);
+ }
+ sc->dmamap_ring_tx = 0;
+ }
+
+ if (sc->dmatag_data_tx) {
+ bus_dma_tag_destroy(sc->dmatag_data_tx);
+ sc->dmatag_data_tx = 0;
+ }
+
+ if (sc->dmatag_ring_tx) {
+ for (i = 0; i<ECE_MAX_TX_BUFFERS; i++) {
+ bus_dmamap_destroy(sc->dmatag_ring_tx,
+ sc->tx_desc[i].dmamap);
+ sc->tx_desc[i].dmamap = 0;
+ }
+ bus_dma_tag_destroy(sc->dmatag_ring_tx);
+ sc->dmatag_ring_tx = 0;
+ }
+}
+
+static int
+ece_alloc_desc_dma_rx(struct ece_softc *sc)
+{
+ int error;
+ int i;
+
+ /* Allocate a busdma tag and DMA safe memory for RX descriptors. */
+ error = bus_dma_tag_create(sc->sc_parent_tag, /* parent */
+ 16, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ /* maxsize, nsegments */
+ sizeof(eth_rx_desc_t)*ECE_MAX_RX_BUFFERS, 1,
+ /* maxsegsz, flags */
+ sizeof(eth_rx_desc_t)*ECE_MAX_RX_BUFFERS, 0,
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->dmatag_data_rx); /* dmat */
+
+ /* Allocate RX ring. */
+ error = bus_dmamem_alloc(sc->dmatag_data_rx,
+ (void**)&(sc->desc_rx),
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO |
+ BUS_DMA_COHERENT,
+ &(sc->dmamap_ring_rx));
+
+ if (error) {
+ if_printf(sc->ifp, "failed to allocate DMA memory\n");
+ return (ENXIO);
+ }
+
+ /* Load dmamap. */
+ error = bus_dmamap_load(sc->dmatag_data_rx, sc->dmamap_ring_rx,
+ sc->desc_rx,
+ sizeof(eth_rx_desc_t)*ECE_MAX_RX_BUFFERS,
+ ece_getaddr,
+ &(sc->ring_paddr_rx), BUS_DMA_NOWAIT);
+
+ if (error) {
+ if_printf(sc->ifp, "can't load descriptor\n");
+ bus_dmamem_free(sc->dmatag_data_rx, sc->desc_rx,
+ sc->dmamap_ring_rx);
+ bus_dma_tag_destroy(sc->dmatag_data_rx);
+ sc->desc_rx = NULL;
+ return (ENXIO);
+ }
+
+ /* Allocate a busdma tag for mbufs. */
+ error = bus_dma_tag_create(sc->sc_parent_tag,/* parent */
+ 16, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ MCLBYTES, 1, /* maxsize, nsegments */
+ MCLBYTES, 0, /* maxsegsz, flags */
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->dmatag_ring_rx); /* dmat */
+
+ if (error) {
+ if_printf(sc->ifp, "failed to create busdma tag for mbufs\n");
+ return (ENXIO);
+ }
+
+ for (i = 0; i<ECE_MAX_RX_BUFFERS; i++) {
+ error = bus_dmamap_create(sc->dmatag_ring_rx, 0,
+ &sc->rx_desc[i].dmamap);
+ if (error) {
+ if_printf(sc->ifp, "failed to create map for mbuf\n");
+ return (ENXIO);
+ }
+ }
+
+ error = bus_dmamap_create(sc->dmatag_ring_rx, 0, &sc->rx_sparemap);
+ if (error) {
+ if_printf(sc->ifp, "failed to create spare map\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static void
+ece_free_desc_dma_rx(struct ece_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < ECE_MAX_RX_BUFFERS; i++) {
+ if (sc->rx_desc[i].buff) {
+ m_freem(sc->rx_desc[i].buff);
+ sc->rx_desc[i].buff= 0;
+ }
+ }
+
+ if (sc->dmatag_data_rx) {
+ bus_dmamap_unload(sc->dmatag_data_rx, sc->dmamap_ring_rx);
+ bus_dmamem_free(sc->dmatag_data_rx, sc->desc_rx,
+ sc->dmamap_ring_rx);
+ bus_dma_tag_destroy(sc->dmatag_data_rx);
+ sc->dmatag_data_rx = 0;
+ sc->dmamap_ring_rx = 0;
+ sc->desc_rx = 0;
+ }
+
+ if (sc->dmatag_ring_rx) {
+ for (i = 0; i < ECE_MAX_RX_BUFFERS; i++)
+ bus_dmamap_destroy(sc->dmatag_ring_rx,
+ sc->rx_desc[i].dmamap);
+ bus_dmamap_destroy(sc->dmatag_ring_rx, sc->rx_sparemap);
+ bus_dma_tag_destroy(sc->dmatag_ring_rx);
+ sc->dmatag_ring_rx = 0;
+ }
+}
+
+static int
+ece_new_rxbuf(struct ece_softc *sc, struct rx_desc_info* descinfo)
+{
+ struct mbuf *new_mbuf;
+ bus_dma_segment_t seg[1];
+ bus_dmamap_t map;
+ int error;
+ int nsegs;
+ bus_dma_tag_t tag;
+
+ tag = sc->dmatag_ring_rx;
+
+ new_mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+
+ if (new_mbuf == NULL)
+ return (ENOBUFS);
+
+ new_mbuf->m_len = new_mbuf->m_pkthdr.len = MCLBYTES;
+
+ error = bus_dmamap_load_mbuf_sg(tag, sc->rx_sparemap, new_mbuf,
+ seg, &nsegs, BUS_DMA_NOWAIT);
+
+ KASSERT(nsegs == 1, ("Too many segments returned!"));
+
+ if (nsegs != 1 || error) {
+ m_free(new_mbuf);
+ return (ENOBUFS);
+ }
+
+ if (descinfo->buff != NULL) {
+ bus_dmamap_sync(tag, descinfo->dmamap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(tag, descinfo->dmamap);
+ }
+
+ map = descinfo->dmamap;
+ descinfo->dmamap = sc->rx_sparemap;
+ sc->rx_sparemap = map;
+
+ bus_dmamap_sync(tag, descinfo->dmamap, BUS_DMASYNC_PREREAD);
+
+ descinfo->buff = new_mbuf;
+ descinfo->desc->data_ptr = seg->ds_addr;
+ descinfo->desc->length = seg->ds_len - 2;
+
+ return (0);
+}
+
+static int
+ece_allocate_dma(struct ece_softc *sc)
+{
+ eth_tx_desc_t *desctx;
+ eth_rx_desc_t *descrx;
+ int i;
+ int error;
+
+ /* Create parent tag for tx and rx */
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev),/* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ BUS_SPACE_MAXSIZE_32BIT, 0,/* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->sc_parent_tag);
+
+ ece_alloc_desc_dma_tx(sc);
+
+ for (i = 0; i < ECE_MAX_TX_BUFFERS; i++) {
+ desctx = (eth_tx_desc_t *)(&sc->desc_tx[i]);
+ memset(desctx, 0, sizeof(eth_tx_desc_t));
+ desctx->length = MAX_PACKET_LEN;
+ desctx->cown = 1;
+ if (i == ECE_MAX_TX_BUFFERS - 1)
+ desctx->eor = 1;
+ }
+
+ ece_alloc_desc_dma_rx(sc);
+
+ for (i = 0; i < ECE_MAX_RX_BUFFERS; i++) {
+ descrx = &(sc->desc_rx[i]);
+ memset(descrx, 0, sizeof(eth_rx_desc_t));
+ sc->rx_desc[i].desc = descrx;
+ sc->rx_desc[i].buff = 0;
+ ece_new_rxbuf(sc, &(sc->rx_desc[i]));
+
+ if (i == ECE_MAX_RX_BUFFERS - 1)
+ descrx->eor = 1;
+ }
+ sc->tx_prod = 0;
+ sc->tx_cons = 0;
+ sc->last_rx = 0;
+ sc->desc_curr_tx = 0;
+
+ return (0);
+}
+
+static int
+ece_activate(device_t dev)
+{
+ struct ece_softc *sc;
+ int err;
+ uint32_t mac_port_config;
+ struct ifnet *ifp;
+
+ sc = device_get_softc(dev);
+ ifp = sc->ifp;
+
+ initial_switch_config = read_4(sc, SWITCH_CONFIG);
+ initial_cpu_config = read_4(sc, CPU_PORT_CONFIG);
+ initial_port0_config = read_4(sc, MAC_PORT_0_CONFIG);
+ initial_port1_config = read_4(sc, MAC_PORT_1_CONFIG);
+
+ /* Disable Port 0 */
+ mac_port_config = read_4(sc, MAC_PORT_0_CONFIG);
+ mac_port_config |= (PORT_DISABLE);
+ write_4(sc, MAC_PORT_0_CONFIG, mac_port_config);
+
+ /* Disable Port 1 */
+ mac_port_config = read_4(sc, MAC_PORT_1_CONFIG);
+ mac_port_config |= (PORT_DISABLE);
+ write_4(sc, MAC_PORT_1_CONFIG, mac_port_config);
+
+ err = ece_allocate_dma(sc);
+ if (err) {
+ if_printf(sc->ifp, "failed allocating dma\n");
+ goto out;
+ }
+
+ write_4(sc, TS_DESCRIPTOR_POINTER, sc->ring_paddr_tx);
+ write_4(sc, TS_DESCRIPTOR_BASE_ADDR, sc->ring_paddr_tx);
+
+ write_4(sc, FS_DESCRIPTOR_POINTER, sc->ring_paddr_rx);
+ write_4(sc, FS_DESCRIPTOR_BASE_ADDR, sc->ring_paddr_rx);
+
+ write_4(sc, FS_DMA_CONTROL, 1);
+
+ return (0);
+out:
+ return (ENXIO);
+
+}
+
+static void
+ece_deactivate(device_t dev)
+{
+ struct ece_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->intrhand)
+ bus_teardown_intr(dev, sc->irq_res_rec, sc->intrhand);
+
+ sc->intrhand = 0;
+
+ if (sc->intrhand_qf)
+ bus_teardown_intr(dev, sc->irq_res_qf, sc->intrhand_qf);
+
+ sc->intrhand_qf = 0;
+
+ bus_generic_detach(sc->dev);
+ if (sc->miibus)
+ device_delete_child(sc->dev, sc->miibus);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ sc->mem_res = 0;
+
+ if (sc->irq_res_rec)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res_rec), sc->irq_res_rec);
+
+ if (sc->irq_res_qf)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res_qf), sc->irq_res_qf);
+
+ if (sc->irq_res_qf)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res_status), sc->irq_res_status);
+
+ sc->irq_res_rec = 0;
+ sc->irq_res_qf = 0;
+ sc->irq_res_status = 0;
+ ECE_TXLOCK_DESTROY(sc);
+ ECE_RXLOCK_DESTROY(sc);
+
+ ece_free_desc_dma_tx(sc);
+ ece_free_desc_dma_rx(sc);
+
+ return;
+}
+
+/*
+ * Change media according to request.
+ */
+static int
+ece_ifmedia_upd(struct ifnet *ifp)
+{
+ struct ece_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+ int error;
+
+ mii = device_get_softc(sc->miibus);
+ ECE_LOCK(sc);
+ error = mii_mediachg(mii);
+ ECE_UNLOCK(sc);
+ return (error);
+}
+
+/*
+ * Notify the world which media we're using.
+ */
+static void
+ece_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct ece_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+
+ mii = device_get_softc(sc->miibus);
+ ECE_LOCK(sc);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ ECE_UNLOCK(sc);
+}
+
+static void
+ece_tick(void *xsc)
+{
+ struct ece_softc *sc = xsc;
+ struct mii_data *mii;
+ int active;
+
+ mii = device_get_softc(sc->miibus);
+ active = mii->mii_media_active;
+ mii_tick(mii);
+
+ /*
+ * Schedule another timeout one second from now.
+ */
+ callout_reset(&sc->tick_ch, hz, ece_tick, sc);
+}
+
+static uint32_t
+read_mac_entry(struct ece_softc *ec,
+ uint8_t *mac_result,
+ int first)
+{
+ uint32_t ii;
+ struct arl_table_entry_t entry;
+ uint32_t *entry_val;
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_0, 0);
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_1, 0);
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_2, 0);
+ if (first)
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_0, 0x1);
+ else
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_0, 0x2);
+
+ for (ii = 0; ii < 0x1000; ii++)
+ if (read_4(ec, ARL_TABLE_ACCESS_CONTROL_1) & (0x1))
+ break;
+
+ entry_val = (uint32_t*) (&entry);
+ entry_val[0] = read_4(ec, ARL_TABLE_ACCESS_CONTROL_1);
+ entry_val[1] = read_4(ec, ARL_TABLE_ACCESS_CONTROL_2);
+
+ if (mac_result)
+ memcpy(mac_result, entry.mac_addr, ETHER_ADDR_LEN);
+
+ return (entry.table_end);
+}
+
+static uint32_t
+write_arl_table_entry(struct ece_softc *ec,
+ uint32_t filter,
+ uint32_t vlan_mac,
+ uint32_t vlan_gid,
+ uint32_t age_field,
+ uint32_t port_map,
+ const uint8_t *mac_addr)
+{
+ uint32_t ii;
+ uint32_t *entry_val;
+ struct arl_table_entry_t entry;
+
+ memset(&entry, 0, sizeof(entry));
+
+ entry.filter = filter;
+ entry.vlan_mac = vlan_mac;
+ entry.vlan_gid = vlan_gid;
+ entry.age_field = age_field;
+ entry.port_map = port_map;
+ memcpy(entry.mac_addr, mac_addr, ETHER_ADDR_LEN);
+
+ entry_val = (uint32_t*) (&entry);
+
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_0, 0);
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_1, 0);
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_2, 0);
+
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_1, entry_val[0]);
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_2, entry_val[1]);
+
+ write_4(ec, ARL_TABLE_ACCESS_CONTROL_0, ARL_WRITE_COMMAND);
+
+ for (ii = 0; ii < 0x1000; ii++)
+ if (read_4(ec, ARL_TABLE_ACCESS_CONTROL_1) &
+ ARL_COMMAND_COMPLETE)
+ return (1); /* Write OK. */
+
+ /* Write failed. */
+ return (0);
+}
+
+static void
+remove_mac_entry(struct ece_softc *sc,
+ uint8_t *mac)
+{
+
+ /* Invalid age_field mean erase this entry. */
+ write_arl_table_entry(sc, 0, 1, VLAN0_GROUP_ID,
+ INVALID_ENTRY, VLAN0_GROUP,
+ mac);
+}
+
+static void
+add_mac_entry(struct ece_softc *sc,
+ uint8_t *mac)
+{
+
+ write_arl_table_entry(sc, 0, 1, VLAN0_GROUP_ID,
+ NEW_ENTRY, VLAN0_GROUP,
+ mac);
+}
+
+/**
+ * The behavior of ARL table reading and deletion is not well defined
+ * in the documentation. To be safe, all mac addresses are put to a
+ * list, then deleted.
+ *
+ */
+static void
+clear_mac_entries(struct ece_softc *ec, int include_this_mac)
+{
+ int table_end;
+ struct mac_list * temp;
+ struct mac_list * mac_list_header;
+ struct mac_list * current;
+ char mac[ETHER_ADDR_LEN];
+
+ current = 0;
+ mac_list_header = 0;
+
+ table_end = read_mac_entry(ec, mac, 1);
+ while (!table_end) {
+ if (!include_this_mac &&
+ memcmp(mac, vlan0_mac, ETHER_ADDR_LEN) == 0) {
+ /* Read next entry. */
+ table_end = read_mac_entry(ec, mac, 0);
+ continue;
+ }
+
+ temp = (struct mac_list*)malloc(sizeof(struct mac_list),
+ M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ memcpy(temp->mac_addr, mac, ETHER_ADDR_LEN);
+ temp->next = 0;
+ if (mac_list_header) {
+ current->next = temp;
+ current = temp;
+ } else {
+ mac_list_header = temp;
+ current = temp;
+ }
+ /* Read next Entry */
+ table_end = read_mac_entry(ec, mac, 0);
+ }
+
+ current = mac_list_header;
+
+ while (current) {
+ remove_mac_entry(ec, current->mac_addr);
+ temp = current;
+ current = current->next;
+ free(temp, M_DEVBUF);
+ }
+}
+
+static int
+configure_lan_port(struct ece_softc *sc, int phy_type)
+{
+ uint32_t sw_config;
+ uint32_t mac_port_config;
+
+ /*
+ * Configure switch
+ */
+ sw_config = read_4(sc, SWITCH_CONFIG);
+ /* Enable fast aging. */
+ sw_config |= FAST_AGING;
+ /* Enable IVL learning. */
+ sw_config |= IVL_LEARNING;
+ /* Disable hardware NAT. */
+ sw_config &= ~(HARDWARE_NAT);
+
+ sw_config |= SKIP_L2_LOOKUP_PORT_0 | SKIP_L2_LOOKUP_PORT_1| NIC_MODE;
+
+ write_4(sc, SWITCH_CONFIG, sw_config);
+
+ sw_config = read_4(sc, SWITCH_CONFIG);
+
+ mac_port_config = read_4(sc, MAC_PORT_0_CONFIG);
+
+ if (!(mac_port_config & 0x1) || (mac_port_config & 0x2))
+ if_printf(sc->ifp, "Link Down\n");
+ else
+ write_4(sc, MAC_PORT_0_CONFIG, mac_port_config);
+ return (0);
+}
+
+static void
+set_pvid(struct ece_softc *sc, int port0, int port1, int cpu)
+{
+ uint32_t val;
+ val = read_4(sc, VLAN_PORT_PVID) & (~(0x7 << 0));
+ write_4(sc, VLAN_PORT_PVID, val);
+ val = read_4(sc, VLAN_PORT_PVID) | ((port0) & 0x07);
+ write_4(sc, VLAN_PORT_PVID, val);
+ val = read_4(sc, VLAN_PORT_PVID) & (~(0x7 << 4));
+ write_4(sc, VLAN_PORT_PVID, val);
+ val = read_4(sc, VLAN_PORT_PVID) | (((port1) & 0x07) << 4);
+ write_4(sc, VLAN_PORT_PVID, val);
+
+ val = read_4(sc, VLAN_PORT_PVID) & (~(0x7 << 8));
+ write_4(sc, VLAN_PORT_PVID, val);
+ val = read_4(sc, VLAN_PORT_PVID) | (((cpu) & 0x07) << 8);
+ write_4(sc, VLAN_PORT_PVID, val);
+
+}
+
+/* VLAN related functions */
+static void
+set_vlan_vid(struct ece_softc *sc, int vlan)
+{
+ const uint32_t regs[] = {
+ VLAN_VID_0_1,
+ VLAN_VID_0_1,
+ VLAN_VID_2_3,
+ VLAN_VID_2_3,
+ VLAN_VID_4_5,
+ VLAN_VID_4_5,
+ VLAN_VID_6_7,
+ VLAN_VID_6_7
+ };
+
+ const int vids[] = {
+ VLAN0_VID,
+ VLAN1_VID,
+ VLAN2_VID,
+ VLAN3_VID,
+ VLAN4_VID,
+ VLAN5_VID,
+ VLAN6_VID,
+ VLAN7_VID
+ };
+
+ uint32_t val;
+ uint32_t reg;
+ int vid;
+
+ reg = regs[vlan];
+ vid = vids[vlan];
+
+ if (vlan & 1) {
+ val = read_4(sc, reg);
+ write_4(sc, reg, val & (~(0xFFF << 0)));
+ val = read_4(sc, reg);
+ write_4(sc, reg, val|((vid & 0xFFF) << 0));
+ } else {
+ val = read_4(sc, reg);
+ write_4(sc, reg, val & (~(0xFFF << 12)));
+ val = read_4(sc, reg);
+ write_4(sc, reg, val|((vid & 0xFFF) << 12));
+ }
+}
+
+static void
+set_vlan_member(struct ece_softc *sc, int vlan)
+{
+ unsigned char shift;
+ uint32_t val;
+ int group;
+ const int groups[] = {
+ VLAN0_GROUP,
+ VLAN1_GROUP,
+ VLAN2_GROUP,
+ VLAN3_GROUP,
+ VLAN4_GROUP,
+ VLAN5_GROUP,
+ VLAN6_GROUP,
+ VLAN7_GROUP
+ };
+
+ group = groups[vlan];
+
+ shift = vlan*3;
+ val = read_4(sc, VLAN_MEMBER_PORT_MAP) & (~(0x7 << shift));
+ write_4(sc, VLAN_MEMBER_PORT_MAP, val);
+ val = read_4(sc, VLAN_MEMBER_PORT_MAP);
+ write_4(sc, VLAN_MEMBER_PORT_MAP, val | ((group & 0x7) << shift));
+}
+
+static void
+set_vlan_tag(struct ece_softc *sc, int vlan)
+{
+ unsigned char shift;
+ uint32_t val;
+
+ int tag = 0;
+
+ shift = vlan*3;
+ val = read_4(sc, VLAN_TAG_PORT_MAP) & (~(0x7 << shift));
+ write_4(sc, VLAN_TAG_PORT_MAP, val);
+ val = read_4(sc, VLAN_TAG_PORT_MAP);
+ write_4(sc, VLAN_TAG_PORT_MAP, val | ((tag & 0x7) << shift));
+}
+
+static int
+configure_cpu_port(struct ece_softc *sc)
+{
+ uint32_t cpu_port_config;
+ int i;
+
+ cpu_port_config = read_4(sc, CPU_PORT_CONFIG);
+ /* SA learning Disable */
+ cpu_port_config |= (SA_LEARNING_DISABLE);
+ /* set data offset + 2 */
+ cpu_port_config &= ~(1U << 31);
+
+ write_4(sc, CPU_PORT_CONFIG, cpu_port_config);
+
+ if (!write_arl_table_entry(sc, 0, 1, VLAN0_GROUP_ID,
+ STATIC_ENTRY, VLAN0_GROUP,
+ vlan0_mac))
+ return (1);
+
+ set_pvid(sc, PORT0_PVID, PORT1_PVID, CPU_PORT_PVID);
+
+ for (i = 0; i < 8; i++) {
+ set_vlan_vid(sc, i);
+ set_vlan_member(sc, i);
+ set_vlan_tag(sc, i);
+ }
+
+ /* disable all interrupt status sources */
+ write_4(sc, INTERRUPT_MASK, 0xffff1fff);
+
+ /* clear previous interrupt sources */
+ write_4(sc, INTERRUPT_STATUS, 0x00001FFF);
+
+ write_4(sc, TS_DMA_CONTROL, 0);
+ write_4(sc, FS_DMA_CONTROL, 0);
+ return (0);
+}
+
+static int
+hardware_init(struct ece_softc *sc)
+{
+ int status = 0;
+ static int gw_phy_type;
+
+ gw_phy_type = get_phy_type(sc);
+ /* Currently only ic_plus phy is supported. */
+ if (gw_phy_type != IC_PLUS_PHY) {
+ device_printf(sc->dev, "PHY type is not supported (%d)\n",
+ gw_phy_type);
+ return (-1);
+ }
+ status = configure_lan_port(sc, gw_phy_type);
+ configure_cpu_port(sc);
+ return (0);
+}
+
+static void
+set_mac_address(struct ece_softc *sc, const char *mac, int mac_len)
+{
+
+ /* Invalid age_field mean erase this entry. */
+ write_arl_table_entry(sc, 0, 1, VLAN0_GROUP_ID,
+ INVALID_ENTRY, VLAN0_GROUP,
+ mac);
+ memcpy(vlan0_mac, mac, ETHER_ADDR_LEN);
+
+ write_arl_table_entry(sc, 0, 1, VLAN0_GROUP_ID,
+ STATIC_ENTRY, VLAN0_GROUP,
+ mac);
+}
+
+static void
+ece_set_mac(struct ece_softc *sc, u_char *eaddr)
+{
+ memcpy(vlan0_mac, eaddr, ETHER_ADDR_LEN);
+ set_mac_address(sc, eaddr, ETHER_ADDR_LEN);
+}
+
+/*
+ * TODO: the device doesn't have MAC stored, we should read the
+ * configuration stored in FLASH, but the format depends on the
+ * bootloader used.*
+ */
+static int
+ece_get_mac(struct ece_softc *sc, u_char *eaddr)
+{
+ return (ENXIO);
+}
+
+static void
+ece_intr_rx_locked(struct ece_softc *sc, int count)
+{
+ struct ifnet *ifp = sc->ifp;
+ struct mbuf *mb;
+ struct rx_desc_info *rxdesc;
+ eth_rx_desc_t *desc;
+
+ int fssd_curr;
+ int fssd;
+ int i;
+ int idx;
+ int rxcount;
+ uint32_t status;
+
+ fssd_curr = read_4(sc, FS_DESCRIPTOR_POINTER);
+
+ fssd = (fssd_curr - (uint32_t)sc->ring_paddr_rx)>>4;
+
+ desc = sc->rx_desc[sc->last_rx].desc;
+
+ /* Prepare to read the data in the ring. */
+ bus_dmamap_sync(sc->dmatag_ring_rx,
+ sc->dmamap_ring_rx,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ if (fssd > sc->last_rx)
+ rxcount = fssd - sc->last_rx;
+ else if (fssd < sc->last_rx)
+ rxcount = (ECE_MAX_RX_BUFFERS - sc->last_rx) + fssd;
+ else {
+ if (desc->cown == 0)
+ return;
+ else
+ rxcount = ECE_MAX_RX_BUFFERS;
+ }
+
+ for (i= 0; i < rxcount; i++) {
+ status = desc->cown;
+ if (!status)
+ break;
+
+ idx = sc->last_rx;
+ rxdesc = &sc->rx_desc[idx];
+ mb = rxdesc->buff;
+
+ if (desc->length < ETHER_MIN_LEN - ETHER_CRC_LEN ||
+ desc->length > ETHER_MAX_LEN - ETHER_CRC_LEN +
+ ETHER_VLAN_ENCAP_LEN) {
+ ifp->if_ierrors++;
+ desc->cown = 0;
+ desc->length = MCLBYTES - 2;
+ /* Invalid packet, skip and process next
+ * packet.
+ */
+ continue;
+ }
+
+ if (ece_new_rxbuf(sc, rxdesc) != 0) {
+ ifp->if_iqdrops++;
+ desc->cown = 0;
+ desc->length = MCLBYTES - 2;
+ break;
+ }
+
+ /**
+ * The device will write to addrress + 2 So we need to adjust
+ * the address after the packet is received.
+ */
+ mb->m_data += 2;
+ mb->m_len = mb->m_pkthdr.len = desc->length;
+
+ mb->m_flags |= M_PKTHDR;
+ mb->m_pkthdr.rcvif = ifp;
+ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
+ /*check for valid checksum*/
+ if ( (!desc->l4f) && (desc->prot != 3)) {
+ mb->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
+ mb->m_pkthdr.csum_flags |= CSUM_IP_VALID;
+ mb->m_pkthdr.csum_data = 0xffff;
+ }
+ }
+ ECE_RXUNLOCK(sc);
+ (*ifp->if_input)(ifp, mb);
+ ECE_RXLOCK(sc);
+
+ desc->cown = 0;
+ desc->length = MCLBYTES - 2;
+
+ bus_dmamap_sync(sc->dmatag_ring_rx,
+ sc->dmamap_ring_rx,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ if (sc->last_rx == ECE_MAX_RX_BUFFERS - 1)
+ sc->last_rx = 0;
+ else
+ sc->last_rx++;
+
+ desc = sc->rx_desc[sc->last_rx].desc;
+ }
+
+ /* Sync updated flags. */
+ bus_dmamap_sync(sc->dmatag_ring_rx,
+ sc->dmamap_ring_rx,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ return;
+}
+
+static void
+ece_intr_task(void *arg, int pending __unused)
+{
+ struct ece_softc *sc = arg;
+ ECE_RXLOCK(sc);
+ ece_intr_rx_locked(sc, -1);
+ ECE_RXUNLOCK(sc);
+}
+
+static void
+ece_intr(void *xsc)
+{
+ struct ece_softc *sc = xsc;
+ struct ifnet *ifp = sc->ifp;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ write_4(sc, FS_DMA_CONTROL, 0);
+ return;
+ }
+
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_intr_task);
+
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_tx_task);
+}
+
+static void
+ece_intr_status(void *xsc)
+{
+ struct ece_softc *sc = xsc;
+ struct ifnet *ifp = sc->ifp;
+ int stat;
+
+ stat = read_4(sc, INTERRUPT_STATUS);
+
+ write_4(sc, INTERRUPT_STATUS, stat);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ if ((stat & ERROR_MASK) != 0)
+ ifp->if_iqdrops++;
+ }
+}
+
+static void
+ece_cleanup_locked(struct ece_softc *sc)
+{
+ eth_tx_desc_t *desc;
+
+ if (sc->tx_cons == sc->tx_prod) return;
+
+ /* Prepare to read the ring (owner bit). */
+ bus_dmamap_sync(sc->dmatag_ring_tx,
+ sc->dmamap_ring_tx,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ while (sc->tx_cons != sc->tx_prod) {
+ desc = sc->tx_desc[sc->tx_cons].desc;
+ if (desc->cown != 0) {
+ struct tx_desc_info *td = &(sc->tx_desc[sc->tx_cons]);
+ /* We are finished with this descriptor ... */
+ bus_dmamap_sync(sc->dmatag_data_tx, td->dmamap,
+ BUS_DMASYNC_POSTWRITE);
+ /* ... and unload, so we can reuse. */
+ bus_dmamap_unload(sc->dmatag_data_tx, td->dmamap);
+ m_freem(td->buff);
+ td->buff = 0;
+ sc->tx_cons = (sc->tx_cons + 1) % ECE_MAX_TX_BUFFERS;
+ } else {
+ break;
+ }
+ }
+
+}
+
+static void
+ece_cleanup_task(void *arg, int pending __unused)
+{
+ struct ece_softc *sc = arg;
+ ECE_CLEANUPLOCK(sc);
+ ece_cleanup_locked(sc);
+ ECE_CLEANUPUNLOCK(sc);
+}
+
+static void
+ece_intr_tx(void *xsc)
+{
+ struct ece_softc *sc = xsc;
+ struct ifnet *ifp = sc->ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ /* This should not happen, stop DMA. */
+ write_4(sc, FS_DMA_CONTROL, 0);
+ return;
+ }
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_cleanup_task);
+}
+
+static void
+ece_intr_qf(void *xsc)
+{
+ struct ece_softc *sc = xsc;
+ struct ifnet *ifp = sc->ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ /* This should not happen, stop DMA. */
+ write_4(sc, FS_DMA_CONTROL, 0);
+ return;
+ }
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_intr_task);
+ write_4(sc, FS_DMA_CONTROL, 1);
+}
+
+/*
+ * Reset and initialize the chip
+ */
+static void
+eceinit_locked(void *xsc)
+{
+ struct ece_softc *sc = xsc;
+ struct ifnet *ifp = sc->ifp;
+ struct mii_data *mii;
+ uint32_t cfg_reg;
+ uint32_t cpu_port_config;
+ uint32_t mac_port_config;
+
+ while (1) {
+ cfg_reg = read_4(sc, BIST_RESULT_TEST_0);
+ if ((cfg_reg & (1<<17)))
+ break;
+ DELAY(100);
+ }
+ /* Set to default values. */
+ write_4(sc, SWITCH_CONFIG, 0x007AA7A1);
+ write_4(sc, MAC_PORT_0_CONFIG, 0x00423D00);
+ write_4(sc, MAC_PORT_1_CONFIG, 0x00423D80);
+ write_4(sc, CPU_PORT_CONFIG, 0x004C0000);
+
+ hardware_init(sc);
+
+ mac_port_config = read_4(sc, MAC_PORT_0_CONFIG);
+
+ /* Enable Port 0 */
+ mac_port_config &= (~(PORT_DISABLE));
+ write_4(sc, MAC_PORT_0_CONFIG, mac_port_config);
+
+ cpu_port_config = read_4(sc, CPU_PORT_CONFIG);
+ /* Enable CPU. */
+ cpu_port_config &= ~(PORT_DISABLE);
+ write_4(sc, CPU_PORT_CONFIG, cpu_port_config);
+
+ /*
+ * Set 'running' flag, and clear output active flag
+ * and attempt to start the output
+ */
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ mii = device_get_softc(sc->miibus);
+ mii_pollstat(mii);
+ /* Enable DMA. */
+ write_4(sc, FS_DMA_CONTROL, 1);
+
+ callout_reset(&sc->tick_ch, hz, ece_tick, sc);
+}
+
+static inline int
+ece_encap(struct ece_softc *sc, struct mbuf *m0)
+{
+ struct ifnet *ifp;
+ bus_dma_segment_t segs[MAX_FRAGMENT];
+ bus_dmamap_t mapp;
+ eth_tx_desc_t *desc = 0;
+ int csum_flags;
+ int desc_no;
+ int error;
+ int nsegs;
+ int seg;
+
+ ifp = sc->ifp;
+
+ /* Fetch unused map */
+ mapp = sc->tx_desc[sc->tx_prod].dmamap;
+
+ error = bus_dmamap_load_mbuf_sg(sc->dmatag_ring_tx, mapp,
+ m0, segs, &nsegs,
+ BUS_DMA_NOWAIT);
+
+ if (error != 0) {
+ bus_dmamap_unload(sc->dmatag_ring_tx, mapp);
+ return ((error != 0) ? error : -1);
+ }
+
+ desc = &(sc->desc_tx[sc->desc_curr_tx]);
+ sc->tx_desc[sc->tx_prod].desc = desc;
+ sc->tx_desc[sc->tx_prod].buff = m0;
+ desc_no = sc->desc_curr_tx;
+
+ for (seg = 0; seg < nsegs; seg++) {
+ if (desc->cown == 0 ) {
+ if_printf(ifp, "ERROR: descriptor is still used\n");
+ return (-1);
+ }
+
+ desc->length = segs[seg].ds_len;
+ desc->data_ptr = segs[seg].ds_addr;
+
+ if (seg == 0) {
+ desc->fs = 1;
+ } else {
+ desc->fs = 0;
+ }
+ if (seg == nsegs - 1) {
+ desc->ls = 1;
+ } else {
+ desc->ls = 0;
+ }
+
+ csum_flags = m0->m_pkthdr.csum_flags;
+
+ desc->fr = 1;
+ desc->pmap = 1;
+ desc->insv = 0;
+ desc->ico = 0;
+ desc->tco = 0;
+ desc->uco = 0;
+ desc->interrupt = 1;
+
+ if (csum_flags & CSUM_IP) {
+ desc->ico = 1;
+ if (csum_flags & CSUM_TCP)
+ desc->tco = 1;
+ if (csum_flags & CSUM_UDP)
+ desc->uco = 1;
+ }
+
+ desc++;
+ sc->desc_curr_tx = (sc->desc_curr_tx + 1) % ECE_MAX_TX_BUFFERS;
+ if (sc->desc_curr_tx == 0) {
+ desc = (eth_tx_desc_t *)&(sc->desc_tx[0]);
+ }
+ }
+
+ desc = sc->tx_desc[sc->tx_prod].desc;
+
+ sc->tx_prod = (sc->tx_prod + 1) % ECE_MAX_TX_BUFFERS;
+
+ /*
+ * After all descriptors are set, we set the flags to start the
+ * sending proces.
+ */
+ for (seg = 0; seg < nsegs; seg++) {
+ desc->cown = 0;
+ desc++;
+ desc_no = (desc_no + 1) % ECE_MAX_TX_BUFFERS;
+ if (desc_no == 0)
+ desc = (eth_tx_desc_t *)&(sc->desc_tx[0]);
+ }
+
+ bus_dmamap_sync(sc->dmatag_data_tx, mapp, BUS_DMASYNC_PREWRITE);
+ return (0);
+}
+
+/*
+ * dequeu packets and transmit
+ */
+static void
+ecestart_locked(struct ifnet *ifp)
+{
+ struct ece_softc *sc;
+ struct mbuf *m0;
+ uint32_t queued = 0;
+
+ sc = ifp->if_softc;
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING)
+ return;
+
+ bus_dmamap_sync(sc->dmatag_ring_tx,
+ sc->dmamap_ring_tx,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ for (;;) {
+ /* Get packet from the queue */
+ IF_DEQUEUE(&ifp->if_snd, m0);
+ if (m0 == NULL)
+ break;
+ if (ece_encap(sc, m0)) {
+ IF_PREPEND(&ifp->if_snd, m0);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
+ queued++;
+ BPF_MTAP(ifp, m0);
+ }
+ if (queued) {
+ bus_dmamap_sync(sc->dmatag_ring_tx, sc->dmamap_ring_tx,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+ write_4(sc, TS_DMA_CONTROL, 1);
+ }
+}
+
+static void
+eceinit(void *xsc)
+{
+ struct ece_softc *sc = xsc;
+ ECE_LOCK(sc);
+ eceinit_locked(sc);
+ ECE_UNLOCK(sc);
+}
+
+static void
+ece_tx_task(void *arg, int pending __unused)
+{
+ struct ifnet *ifp;
+ ifp = (struct ifnet *)arg;
+ ecestart(ifp);
+}
+
+static void
+ecestart(struct ifnet *ifp)
+{
+ struct ece_softc *sc = ifp->if_softc;
+ ECE_TXLOCK(sc);
+ ecestart_locked(ifp);
+ ECE_TXUNLOCK(sc);
+}
+
+/*
+ * Turn off interrupts, and stop the nic. Can be called with sc->ifp
+ * NULL so be careful.
+ */
+static void
+ecestop(struct ece_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
+ uint32_t mac_port_config;
+
+ write_4(sc, TS_DMA_CONTROL, 0);
+ write_4(sc, FS_DMA_CONTROL, 0);
+
+ if (ifp)
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+
+ callout_stop(&sc->tick_ch);
+
+ /*Disable Port 0 */
+ mac_port_config = read_4(sc, MAC_PORT_0_CONFIG);
+ mac_port_config |= (PORT_DISABLE);
+ write_4(sc, MAC_PORT_0_CONFIG, mac_port_config);
+
+ /*Disable Port 1 */
+ mac_port_config = read_4(sc, MAC_PORT_1_CONFIG);
+ mac_port_config |= (PORT_DISABLE);
+ write_4(sc, MAC_PORT_1_CONFIG, mac_port_config);
+
+ /* Disable all interrupt status sources. */
+ write_4(sc, INTERRUPT_MASK, 0x00001FFF);
+
+ /* Clear previous interrupt sources. */
+ write_4(sc, INTERRUPT_STATUS, 0x00001FFF);
+
+ write_4(sc, SWITCH_CONFIG, initial_switch_config);
+ write_4(sc, CPU_PORT_CONFIG, initial_cpu_config);
+ write_4(sc, MAC_PORT_0_CONFIG, initial_port0_config);
+ write_4(sc, MAC_PORT_1_CONFIG, initial_port1_config);
+
+ clear_mac_entries(sc, 1);
+}
+
+static void
+ece_restart(struct ece_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ /* Enable port 0. */
+ write_4(sc, PORT_0_CONFIG,
+ read_4(sc, PORT_0_CONFIG) & ~(PORT_DISABLE));
+ write_4(sc, INTERRUPT_MASK, 0x00000000);
+ write_4(sc, FS_DMA_CONTROL, 1);
+ callout_reset(&sc->tick_ch, hz, ece_tick, sc);
+}
+
+static void
+set_filter(struct ece_softc *sc)
+{
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ uint32_t mac_port_config;
+
+ ifp = sc->ifp;
+
+ clear_mac_entries(sc, 0);
+ if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
+ mac_port_config = read_4(sc, MAC_PORT_0_CONFIG);
+ mac_port_config &= ~(DISABLE_BROADCAST_PACKET);
+ mac_port_config &= ~(DISABLE_MULTICAST_PACKET);
+ write_4(sc, MAC_PORT_0_CONFIG, mac_port_config);
+ return;
+ }
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ add_mac_entry(sc,
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ }
+ if_maddr_runlock(ifp);
+}
+
+static int
+eceioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct ece_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int mask, error = 0;
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ ECE_LOCK(sc);
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ ecestop(sc);
+ } else {
+ /* Reinitialize card on any parameter change. */
+ if ((ifp->if_flags & IFF_UP) &&
+ !(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ ece_restart(sc);
+ }
+ ECE_UNLOCK(sc);
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ ECE_LOCK(sc);
+ set_filter(sc);
+ ECE_UNLOCK(sc);
+ break;
+
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ mii = device_get_softc(sc->miibus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ break;
+ case SIOCSIFCAP:
+ mask = ifp->if_capenable ^ ifr->ifr_reqcap;
+ if (mask & IFCAP_VLAN_MTU) {
+ ECE_LOCK(sc);
+ ECE_UNLOCK(sc);
+ }
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ }
+ return (error);
+}
+
+static void
+ece_child_detached(device_t dev, device_t child)
+{
+ struct ece_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (child == sc->miibus)
+ sc->miibus = NULL;
+}
+
+/*
+ * MII bus support routines.
+ */
+static int
+ece_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct ece_softc *sc;
+ sc = device_get_softc(dev);
+ return (phy_read(sc, phy, reg));
+}
+
+static int
+ece_miibus_writereg(device_t dev, int phy, int reg, int data)
+{
+ struct ece_softc *sc;
+ sc = device_get_softc(dev);
+ phy_write(sc, phy, reg, data);
+ return (0);
+}
+
+static device_method_t ece_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ece_probe),
+ DEVMETHOD(device_attach, ece_attach),
+ DEVMETHOD(device_detach, ece_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_child_detached, ece_child_detached),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, ece_miibus_readreg),
+ DEVMETHOD(miibus_writereg, ece_miibus_writereg),
+
+ { 0, 0 }
+};
+
+static driver_t ece_driver = {
+ "ece",
+ ece_methods,
+ sizeof(struct ece_softc),
+};
+
+DRIVER_MODULE(ece, econaarm, ece_driver, ece_devclass, 0, 0);
+DRIVER_MODULE(miibus, ece, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(ece, miibus, 1, 1, 1);
+MODULE_DEPEND(ece, ether, 1, 1, 1);
Property changes on: trunk/sys/arm/cavium/cns11xx/if_ece.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/if_ecereg.h
===================================================================
--- trunk/sys/arm/cavium/cns11xx/if_ecereg.h (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/if_ecereg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,155 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009, Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/cavium/cns11xx/if_ecereg.h 201468 2010-01-04 03:35:45Z rpaulo $
+ */
+
+#ifndef _IF_ECEREG_H
+#define _IF_ECEREG_H
+
+#define ETH_CFG 0x08
+#define ETH_CFG_RMII (1 << 15)
+#define PHY_CONTROL 0x00
+#define PHY_RW_OK (1<<15)
+
+#define PHY_ADDRESS(x) ((x) & 0x1)
+#define PHY_REGISTER(r) (((r) & 0x1F) << 8)
+#define PHY_WRITE_COMMAND (1<<13)
+#define PHY_READ_COMMAND (1<<14)
+#define PHY_GET_DATA(d) (((d) >> 16) & 0xFFFF)
+#define PHY_DATA(d) (((d) & 0xFFFF) << 16)
+
+#define PORT_0_CONFIG 0x08
+
+#define ARL_TABLE_ACCESS_CONTROL_0 0x050
+#define ARL_TABLE_ACCESS_CONTROL_1 0x054
+#define ARL_TABLE_ACCESS_CONTROL_2 0x058
+
+#define ARL_WRITE_COMMAND (1<<3)
+#define ARL_LOOKUP_COMMAND (1<<2)
+#define ARL_COMMAND_COMPLETE (1)
+
+
+#define PORT0 (1 << 0)
+#define PORT1 (1 << 1)
+#define CPU_PORT (1 << 2)
+
+
+#define VLAN0_GROUP_ID (0)
+#define VLAN1_GROUP_ID (1)
+#define VLAN2_GROUP_ID (2)
+#define VLAN3_GROUP_ID (3)
+#define VLAN4_GROUP_ID (4)
+#define VLAN5_GROUP_ID (5)
+#define VLAN6_GROUP_ID (6)
+#define VLAN7_GROUP_ID (7)
+
+#define PORT0_PVID (VLAN1_GROUP_ID)
+#define PORT1_PVID (VLAN2_GROUP_ID)
+#define CPU_PORT_PVID (VLAN0_GROUP_ID)
+
+#define VLAN0_VID (0x111)
+#define VLAN1_VID (0x222)
+#define VLAN2_VID (0x333)
+#define VLAN3_VID (0x444)
+#define VLAN4_VID (0x555)
+#define VLAN5_VID (0x666)
+#define VLAN6_VID (0x777)
+#define VLAN7_VID (0x888)
+
+#define VLAN0_GROUP (PORT0 | PORT1 | CPU_PORT)
+#define VLAN1_GROUP (PORT0 | CPU_PORT)
+#define VLAN2_GROUP (PORT1 | CPU_PORT)
+#define VLAN3_GROUP (0)
+#define VLAN4_GROUP (0)
+#define VLAN5_GROUP (0)
+#define VLAN6_GROUP (0)
+#define VLAN7_GROUP (0)
+
+#define SWITCH_CONFIG 0x004
+#define MAC_PORT_0_CONFIG 0x008
+#define MAC_PORT_1_CONFIG 0x00C
+#define CPU_PORT_CONFIG 0x010
+#define BIST_RESULT_TEST_0 0x094
+
+#define FS_DMA_CONTROL 0x104
+#define TS_DMA_CONTROL 0x100
+
+#define INTERRUPT_MASK 0x08C
+#define INTERRUPT_STATUS 0x088
+
+#define TS_DESCRIPTOR_POINTER 0x108
+#define TS_DESCRIPTOR_BASE_ADDR 0x110
+#define FS_DESCRIPTOR_POINTER 0x10C
+#define FS_DESCRIPTOR_BASE_ADDR 0x114
+
+
+#define VLAN_VID_0_1 0x060
+#define VLAN_VID_2_3 0x064
+#define VLAN_VID_4_5 0x068
+#define VLAN_VID_6_7 0x06C
+
+#define VLAN_PORT_PVID 0x05C
+#define VLAN_MEMBER_PORT_MAP 0x070
+#define VLAN_TAG_PORT_MAP 0x074
+
+
+#define ASIX_GIGA_PHY 1
+#define TWO_SINGLE_PHY 2
+#define AGERE_GIGA_PHY 3
+#define VSC8601_GIGA_PHY 4
+#define IC_PLUS_PHY 5
+#define NOT_FOUND_PHY (-1)
+
+#define MAX_PACKET_LEN (1536)
+
+#define INVALID_ENTRY 0
+#define NEW_ENTRY 0x1
+#define STATIC_ENTRY 0x7
+
+/*mask status except for link change*/
+#define ERROR_MASK 0xFFFFFF7F
+
+/*hardware interface flags*/
+
+#define FAST_AGING (0xf)
+#define IVL_LEARNING (0x1 << 22)
+/*hardware NAT accelerator*/
+#define HARDWARE_NAT (0x1 << 23)
+/*aging time setting*/
+
+/*skip lookup*/
+#define SKIP_L2_LOOKUP_PORT_1 (1 << 29)
+#define SKIP_L2_LOOKUP_PORT_0 (1 << 28)
+
+#define NIC_MODE (1 << 30)
+#define PORT_DISABLE (1 << 18)
+#define SA_LEARNING_DISABLE (1 << 19)
+#define DISABLE_BROADCAST_PACKET (1 << 27)
+#define DISABLE_MULTICAST_PACKET ( 1 << 26)
+
+#endif
Property changes on: trunk/sys/arm/cavium/cns11xx/if_ecereg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/if_ecevar.h
===================================================================
--- trunk/sys/arm/cavium/cns11xx/if_ecevar.h (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/if_ecevar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,194 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/cavium/cns11xx/if_ecevar.h 201468 2010-01-04 03:35:45Z rpaulo $
+ */
+
+#ifndef _IFECEVAR_H
+#define _IFECEVAR_H
+
+#define ECE_MAX_TX_BUFFERS 128
+#define ECE_MAX_RX_BUFFERS 128
+#define MAX_FRAGMENT 32
+
+typedef struct {
+ /* 1st 32Bits */
+ uint32_t data_ptr;
+ /* 2nd 32Bits*/
+ uint32_t length:16;
+
+ uint32_t tco:1; /*tcp checksum offload*/
+ uint32_t uco:1; /*udp checksum offload*/
+ uint32_t ico:1; /*ip checksum offload*/
+ /* force_route_port_map*/
+ uint32_t pmap:3;
+ /* force_route */
+ uint32_t fr:1;
+ /* force_priority_value */
+ uint32_t pri:3;
+ /* force_priority */
+ uint32_t fp:1;
+ /*interrupt_bit*/
+ uint32_t interrupt:1;
+ /*last_seg*/
+ uint32_t ls:1;
+ /*first_seg*/
+ uint32_t fs:1;
+ /* end_bit */
+ uint32_t eor:1;
+ /* c_bit */
+ uint32_t cown:1;
+ /* 3rd 32Bits*/
+ /*vid_index*/
+ uint32_t vid:3;
+ /*insert_vid_tag*/
+ uint32_t insv:1;
+ /*pppoe_section_index*/
+ uint32_t sid:3;
+ /*insert_pppoe_section*/
+ uint32_t inss:1;
+ uint32_t unused:24;
+ /* 4th 32Bits*/
+ uint32_t unused2;
+
+} eth_tx_desc_t;
+
+typedef struct{
+ uint32_t data_ptr;
+ uint32_t length:16;
+ uint32_t l4f:1;
+ uint32_t ipf:1;
+ uint32_t prot:2;
+ uint32_t hr:6;
+ uint32_t sp:2;
+ uint32_t ls:1;
+ uint32_t fs:1;
+ uint32_t eor:1;
+ uint32_t cown:1;
+ uint32_t unused;
+ uint32_t unused2;
+} eth_rx_desc_t;
+
+
+struct rx_desc_info {
+ struct mbuf*buff;
+ bus_dmamap_t dmamap;
+ eth_rx_desc_t *desc;
+};
+
+struct tx_desc_info {
+ struct mbuf*buff;
+ bus_dmamap_t dmamap;
+ eth_tx_desc_t *desc;
+};
+
+
+struct ece_softc
+{
+ struct ifnet *ifp; /* ifnet pointer */
+ struct mtx sc_mtx; /* global mutex */
+ struct mtx sc_mtx_tx; /* tx mutex */
+ struct mtx sc_mtx_rx; /* rx mutex */
+ struct mtx sc_mtx_cleanup; /* rx mutex */
+
+ bus_dma_tag_t sc_parent_tag; /* parent bus DMA tag */
+
+ device_t dev; /* Myself */
+ device_t miibus; /* My child miibus */
+ void *intrhand; /* Interrupt handle */
+ void *intrhand_qf; /* queue full */
+ void *intrhand_tx; /* tx complete */
+ void *intrhand_status; /* error status */
+
+ struct resource *irq_res_tx; /* transmit */
+ struct resource *irq_res_rec; /* receive */
+ struct resource *irq_res_qf; /* queue full */
+ struct resource *irq_res_status; /* status */
+
+ struct resource *mem_res; /* Memory resource */
+
+ struct callout tick_ch; /* Tick callout */
+
+ struct taskqueue *sc_tq;
+ struct task sc_intr_task;
+ struct task sc_cleanup_task;
+ struct task sc_tx_task;
+
+ bus_dmamap_t dmamap_ring_tx;
+ bus_dmamap_t dmamap_ring_rx;
+ bus_dmamap_t rx_sparemap;
+
+ /*dma tag for ring*/
+ bus_dma_tag_t dmatag_ring_tx;
+ bus_dma_tag_t dmatag_ring_rx;
+
+ /*dma tag for data*/
+ bus_dma_tag_t dmatag_data_tx;
+ bus_dma_tag_t dmatag_data_rx;
+
+ /*the ring*/
+ eth_tx_desc_t* desc_tx;
+ eth_rx_desc_t* desc_rx;
+
+ /*ring physical address*/
+ bus_addr_t ring_paddr_tx;
+ bus_addr_t ring_paddr_rx;
+
+ /*index of last received descriptor*/
+ uint32_t last_rx;
+ struct rx_desc_info rx_desc[ECE_MAX_RX_BUFFERS];
+
+ /* tx producer index */
+ uint32_t tx_prod;
+ /* tx consumer index */
+ uint32_t tx_cons;
+ /* tx ring index*/
+ uint32_t desc_curr_tx;
+
+ struct tx_desc_info tx_desc[ECE_MAX_TX_BUFFERS];
+};
+
+
+struct arl_table_entry_t {
+ uint32_t cmd_complete: 1;
+ uint32_t table_end: 1;
+ uint32_t search_match: 1;
+ uint32_t filter:1; /*if set, packet will be dropped */
+ uint32_t vlan_mac:1; /*indicates that this is the gateway mac address*/
+ uint32_t vlan_gid:3; /*vlan id*/
+ uint32_t age_field:3;
+ uint32_t port_map:3;
+ /*48 bit mac address*/
+ uint8_t mac_addr[6];
+ uint8_t pad[2];
+};
+
+struct mac_list{
+ char mac_addr[6];
+ struct mac_list *next;
+};
+
+#endif
Property changes on: trunk/sys/arm/cavium/cns11xx/if_ecevar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/ohci_ec.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/ohci_ec.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/ohci_ec.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,235 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/ohci_ec.c 308402 2016-11-07 09:19:04Z hselasky $");
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ohci.h>
+#include <dev/usb/controller/ohcireg.h>
+
+#include <sys/rman.h>
+
+#include <arm/cavium/cns11xx/econa_reg.h>
+
+#define MEM_RID 0
+
+static device_probe_t ohci_ec_probe;
+static device_attach_t ohci_ec_attach;
+static device_detach_t ohci_ec_detach;
+
+struct ec_ohci_softc {
+ struct ohci_softc sc_ohci; /* must be first */
+};
+
+static int
+ohci_ec_probe(device_t dev)
+{
+ device_set_desc(dev, "Econa integrated OHCI controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ohci_ec_attach(device_t dev)
+{
+ struct ec_ohci_softc *sc = device_get_softc(dev);
+ bus_space_handle_t bsh;
+ int err;
+ int rid;
+
+ /* initialise some bus fields */
+ sc->sc_ohci.sc_bus.parent = dev;
+ sc->sc_ohci.sc_bus.devices = sc->sc_ohci.sc_devices;
+ sc->sc_ohci.sc_bus.devices_max = OHCI_MAX_DEVICES;
+ sc->sc_ohci.sc_bus.dma_bits = 32;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_ohci.sc_bus,
+ USB_GET_DMA_TAG(dev), &ohci_iterate_hw_softc)) {
+ return (ENOMEM);
+ }
+ sc->sc_ohci.sc_dev = dev;
+
+ rid = MEM_RID;
+
+ sc->sc_ohci.sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE);
+
+ if (!(sc->sc_ohci.sc_io_res)) {
+ err = ENOMEM;
+ goto error;
+ }
+ sc->sc_ohci.sc_io_tag = rman_get_bustag(sc->sc_ohci.sc_io_res);
+ bsh = rman_get_bushandle(sc->sc_ohci.sc_io_res);
+ /* Undocumented magic initialization */
+ bus_space_write_4((sc)->sc_ohci.sc_io_tag, bsh,0x04, 0x146);
+
+ bus_space_write_4((sc)->sc_ohci.sc_io_tag, bsh,0x44, 0x0200);
+
+ DELAY(1000);
+
+ sc->sc_ohci.sc_io_size = rman_get_size(sc->sc_ohci.sc_io_res);
+
+ if (bus_space_subregion(sc->sc_ohci.sc_io_tag, bsh, 0x4000000,
+ sc->sc_ohci.sc_io_size, &sc->sc_ohci.sc_io_hdl) != 0)
+ panic("%s: unable to subregion USB host registers",
+ device_get_name(dev));
+
+ rid = 0;
+ sc->sc_ohci.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!(sc->sc_ohci.sc_irq_res)) {
+ goto error;
+ }
+ sc->sc_ohci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (!(sc->sc_ohci.sc_bus.bdev)) {
+ goto error;
+ }
+ device_set_ivars(sc->sc_ohci.sc_bus.bdev, &sc->sc_ohci.sc_bus);
+
+ strlcpy(sc->sc_ohci.sc_vendor, "Cavium",
+ sizeof(sc->sc_ohci.sc_vendor));
+
+#if (__FreeBSD_version >= 700031)
+ err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res,
+ INTR_TYPE_BIO | INTR_MPSAFE, NULL,
+ (driver_intr_t *)ohci_interrupt, sc,
+ &sc->sc_ohci.sc_intr_hdl);
+#else
+ err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res,
+ INTR_TYPE_BIO | INTR_MPSAFE,
+ (driver_intr_t *)ohci_interrupt, sc,
+ &sc->sc_ohci.sc_intr_hdl);
+#endif
+ if (err) {
+ sc->sc_ohci.sc_intr_hdl = NULL;
+ goto error;
+ }
+
+ bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl,
+ OHCI_CONTROL, 0);
+
+ err = ohci_init(&sc->sc_ohci);
+ if (!err) {
+ err = device_probe_and_attach(sc->sc_ohci.sc_bus.bdev);
+ }
+ if (err) {
+ goto error;
+ }
+ return (0);
+
+error:
+ ohci_ec_detach(dev);
+ return (ENXIO);
+}
+
+static int
+ohci_ec_detach(device_t dev)
+{
+ struct ec_ohci_softc *sc = device_get_softc(dev);
+ int err;
+
+ /* during module unload there are lots of children leftover */
+ device_delete_children(dev);
+
+ bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl,
+ OHCI_CONTROL, 0);
+
+ if (sc->sc_ohci.sc_irq_res && sc->sc_ohci.sc_intr_hdl) {
+ /*
+ * only call ohci_detach() after ohci_init()
+ */
+ ohci_detach(&sc->sc_ohci);
+
+ err = bus_teardown_intr(dev, sc->sc_ohci.sc_irq_res,
+ sc->sc_ohci.sc_intr_hdl);
+ sc->sc_ohci.sc_intr_hdl = NULL;
+ }
+ if (sc->sc_ohci.sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_IRQ, 0,
+ sc->sc_ohci.sc_irq_res);
+ sc->sc_ohci.sc_irq_res = NULL;
+ }
+ if (sc->sc_ohci.sc_io_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, MEM_RID,
+ sc->sc_ohci.sc_io_res);
+ sc->sc_ohci.sc_io_res = NULL;
+ }
+ usb_bus_mem_free_all(&sc->sc_ohci.sc_bus, &ohci_iterate_hw_softc);
+
+ return (0);
+}
+
+static device_method_t ohci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ohci_ec_probe),
+ DEVMETHOD(device_attach, ohci_ec_attach),
+ DEVMETHOD(device_detach, ohci_ec_detach),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD_END
+};
+
+static driver_t ohci_driver = {
+ .name = "ohci",
+ .methods = ohci_methods,
+ .size = sizeof(struct ec_ohci_softc),
+};
+
+static devclass_t ohci_devclass;
+
+DRIVER_MODULE(ohci, econaarm, ohci_driver, ohci_devclass, 0, 0);
+MODULE_DEPEND(ohci, usb, 1, 1, 1);
Property changes on: trunk/sys/arm/cavium/cns11xx/ohci_ec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/std.econa
===================================================================
--- trunk/sys/arm/cavium/cns11xx/std.econa (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/std.econa 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,16 @@
+# $FreeBSD: stable/10/sys/arm/cavium/cns11xx/std.econa 264219 2014-04-07 05:33:30Z rpaulo $
+
+files "../cavium/cns11xx/files.econa"
+cpu CPU_FA526
+machine arm
+makeoptions CONF_CFLAGS=-march=armv4
+options PHYSADDR=0x00000000
+makeoptions KERNPHYSADDR=0x01000000
+makeoptions KERNVIRTADDR=0xc1000000
+
+options KERNPHYSADDR=0x01000000
+options KERNVIRTADDR=0xc1000000 # Used in ldscript.arm
+options FLASHADDR=0xD0000000
+options LOADERRAMADDR=0x00000000
+
+options NO_EVENTTIMERS
Property changes on: trunk/sys/arm/cavium/cns11xx/std.econa
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/timer.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/timer.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,382 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Yohanes Nugroho <yohanes at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/timer.c 257200 2013-10-27 01:34:10Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include "econa_reg.h"
+#include "econa_var.h"
+
+#define INITIAL_TIMECOUNTER (0xffffffff)
+
+static int timers_initialized = 0;
+
+#define HZ 100
+
+extern unsigned int CPU_clock;
+extern unsigned int AHB_clock;
+extern unsigned int APB_clock;
+
+static unsigned long timer_counter = 0;
+
+struct ec_timer_softc {
+ struct resource * timer_res[3];
+ bus_space_tag_t timer_bst;
+ bus_space_handle_t timer_bsh;
+ struct mtx timer_mtx;
+};
+
+static struct resource_spec ec_timer_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static unsigned ec_timer_get_timecount(struct timecounter *);
+
+static struct timecounter ec_timecounter = {
+ .tc_get_timecount = ec_timer_get_timecount,
+ .tc_name = "CPU Timer",
+ /* This is assigned on the fly in the init sequence */
+ .tc_frequency = 0,
+ .tc_counter_mask = ~0u,
+ .tc_quality = 1000,
+};
+
+static struct ec_timer_softc *timer_softc = NULL;
+
+static inline
+void write_4(unsigned int val, unsigned int addr)
+{
+ bus_space_write_4(timer_softc->timer_bst,
+ timer_softc->timer_bsh, addr, val);
+
+}
+
+static inline
+unsigned int read_4(unsigned int addr)
+{
+
+ return bus_space_read_4(timer_softc->timer_bst,
+ timer_softc->timer_bsh, addr);
+}
+
+#define uSECS_PER_TICK (1000000 / APB_clock)
+#define TICKS2USECS(x) ((x) * uSECS_PER_TICK)
+
+static unsigned
+read_timer_counter_noint(void)
+{
+
+ arm_mask_irq(0);
+ unsigned int v = read_4(TIMER_TM1_COUNTER_REG);
+ arm_unmask_irq(0);
+ return v;
+}
+
+void
+DELAY(int usec)
+{
+ uint32_t val, val_temp;
+ int nticks;
+
+ if (!timers_initialized) {
+ for (; usec > 0; usec--)
+ for (val = 100; val > 0; val--)
+ ;
+ return;
+ }
+
+ val = read_timer_counter_noint();
+ nticks = (((APB_clock / 1000) * usec) / 1000) + 100;
+
+ while (nticks > 0) {
+ val_temp = read_timer_counter_noint();
+ if (val > val_temp)
+ nticks -= (val - val_temp);
+ else
+ nticks -= (val + (timer_counter - val_temp));
+
+ val = val_temp;
+ }
+
+}
+
+/*
+ * Setup timer
+ */
+static inline void
+setup_timer(unsigned int counter_value)
+{
+ unsigned int control_value;
+ unsigned int mask_value;
+
+ control_value = read_4(TIMER_TM_CR_REG);
+
+ mask_value = read_4(TIMER_TM_INTR_MASK_REG);
+ write_4(counter_value, TIMER_TM1_COUNTER_REG);
+ write_4(counter_value, TIMER_TM1_LOAD_REG);
+ write_4(0, TIMER_TM1_MATCH1_REG);
+ write_4(0,TIMER_TM1_MATCH2_REG);
+
+ control_value &= ~(TIMER1_CLOCK_SOURCE);
+ control_value |= TIMER1_UP_DOWN_COUNT;
+
+ write_4(0, TIMER_TM2_COUNTER_REG);
+ write_4(0, TIMER_TM2_LOAD_REG);
+ write_4(~0u, TIMER_TM2_MATCH1_REG);
+ write_4(~0u,TIMER_TM2_MATCH2_REG);
+
+ control_value &= ~(TIMER2_CLOCK_SOURCE);
+ control_value &= ~(TIMER2_UP_DOWN_COUNT);
+
+ mask_value &= ~(63);
+
+ write_4(control_value, TIMER_TM_CR_REG);
+ write_4(mask_value, TIMER_TM_INTR_MASK_REG);
+}
+
+/*
+ * Enable timer
+ */
+static inline void
+timer_enable(void)
+{
+ unsigned int control_value;
+
+ control_value = read_4(TIMER_TM_CR_REG);
+
+ control_value |= TIMER1_OVERFLOW_ENABLE;
+ control_value |= TIMER1_ENABLE;
+ control_value |= TIMER2_OVERFLOW_ENABLE;
+ control_value |= TIMER2_ENABLE;
+
+ write_4(control_value, TIMER_TM_CR_REG);
+}
+
+static inline unsigned int
+read_second_timer_counter(void)
+{
+
+ return read_4(TIMER_TM2_COUNTER_REG);
+}
+
+/*
+ * Get timer interrupt status
+ */
+static inline unsigned int
+read_timer_interrupt_status(void)
+{
+
+ return read_4(TIMER_TM_INTR_STATUS_REG);
+}
+
+/*
+ * Clear timer interrupt status
+ */
+static inline void
+clear_timer_interrupt_status(unsigned int irq)
+{
+ unsigned int interrupt_status;
+
+ interrupt_status = read_4(TIMER_TM_INTR_STATUS_REG);
+ if (irq == 0) {
+ if (interrupt_status & (TIMER1_MATCH1_INTR))
+ interrupt_status &= ~(TIMER1_MATCH1_INTR);
+ if (interrupt_status & (TIMER1_MATCH2_INTR))
+ interrupt_status &= ~(TIMER1_MATCH2_INTR);
+ if (interrupt_status & (TIMER1_OVERFLOW_INTR))
+ interrupt_status &= ~(TIMER1_OVERFLOW_INTR);
+ }
+ if (irq == 1) {
+ if (interrupt_status & (TIMER2_MATCH1_INTR))
+ interrupt_status &= ~(TIMER2_MATCH1_INTR);
+ if (interrupt_status & (TIMER2_MATCH2_INTR))
+ interrupt_status &= ~(TIMER2_MATCH2_INTR);
+ if (interrupt_status & (TIMER2_OVERFLOW_INTR))
+ interrupt_status &= ~(TIMER2_OVERFLOW_INTR);
+ }
+
+ write_4(interrupt_status, TIMER_TM_INTR_STATUS_REG);
+}
+
+static unsigned
+ec_timer_get_timecount(struct timecounter *a)
+{
+ unsigned int ticks1;
+ arm_mask_irq(1);
+ ticks1 = read_second_timer_counter();
+ arm_unmask_irq(1);
+ return ticks1;
+}
+
+/*
+ * Setup timer
+ */
+static inline void
+do_setup_timer(void)
+{
+
+ timer_counter = APB_clock/HZ;
+ /*
+ * setup timer-related values
+ */
+ setup_timer(timer_counter);
+}
+
+void
+cpu_initclocks(void)
+{
+
+ ec_timecounter.tc_frequency = APB_clock;
+ tc_init(&ec_timecounter);
+ timer_enable();
+ timers_initialized = 1;
+}
+
+void
+cpu_startprofclock(void)
+{
+
+}
+
+void
+cpu_stopprofclock(void)
+{
+
+}
+
+static int
+ec_timer_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Econa CPU Timer");
+ return (0);
+}
+
+static int
+ec_reset(void *arg)
+{
+
+ arm_mask_irq(1);
+ clear_timer_interrupt_status(1);
+ arm_unmask_irq(1);
+ return (FILTER_HANDLED);
+}
+
+static int
+ec_hardclock(void *arg)
+{
+ struct trapframe *frame;
+ unsigned int val;
+ /*clear timer interrupt status*/
+
+ arm_mask_irq(0);
+
+ val = read_4(TIMER_INTERRUPT_STATUS_REG);
+ val &= ~(TIMER1_OVERFLOW_INTERRUPT);
+ write_4(val, TIMER_INTERRUPT_STATUS_REG);
+
+ frame = (struct trapframe *)arg;
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+
+ arm_unmask_irq(0);
+
+ return (FILTER_HANDLED);
+}
+
+static int
+ec_timer_attach(device_t dev)
+{
+ struct ec_timer_softc *sc;
+ int error;
+ void *ihl;
+
+
+ if (timer_softc != NULL)
+ return (ENXIO);
+
+ sc = (struct ec_timer_softc *)device_get_softc(dev);
+
+ timer_softc = sc;
+
+ error = bus_alloc_resources(dev, ec_timer_spec, sc->timer_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->timer_bst = rman_get_bustag(sc->timer_res[0]);
+ sc->timer_bsh = rman_get_bushandle(sc->timer_res[0]);
+
+ do_setup_timer();
+
+ if (bus_setup_intr(dev, sc->timer_res[1], INTR_TYPE_CLK,
+ ec_hardclock, NULL, NULL, &ihl) != 0) {
+ bus_release_resources(dev, ec_timer_spec, sc->timer_res);
+ device_printf(dev, "could not setup hardclock interrupt\n");
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->timer_res[2], INTR_TYPE_CLK,
+ ec_reset, NULL, NULL, &ihl) != 0) {
+ bus_release_resources(dev, ec_timer_spec, sc->timer_res);
+ device_printf(dev, "could not setup timer interrupt\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static device_method_t ec_timer_methods[] = {
+ DEVMETHOD(device_probe, ec_timer_probe),
+ DEVMETHOD(device_attach, ec_timer_attach),
+ { 0, 0 }
+};
+
+static driver_t ec_timer_driver = {
+ "timer",
+ ec_timer_methods,
+ sizeof(struct ec_timer_softc),
+};
+
+static devclass_t ec_timer_devclass;
+
+DRIVER_MODULE(timer, econaarm, ec_timer_driver, ec_timer_devclass, 0, 0);
Property changes on: trunk/sys/arm/cavium/cns11xx/timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/uart_bus_ec.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/uart_bus_ec.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/uart_bus_ec.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,77 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/uart_bus_ec.c 264219 2014-04-07 05:33:30Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/cavium/cns11xx/econa_reg.h>
+
+static int uart_ec_probe(device_t dev);
+
+static device_method_t uart_ec_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uart_ec_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, uart_bus_detach),
+ { 0, 0 }
+};
+
+static driver_t uart_ec_driver = {
+ uart_driver_name,
+ uart_ec_methods,
+ sizeof(struct uart_softc),
+};
+
+static int
+uart_ec_probe(device_t dev)
+{
+ struct uart_softc *sc;
+ int status;
+
+ sc = device_get_softc(dev);
+ sc->sc_class = &uart_ns8250_class;
+ status = uart_bus_probe(dev, EC_UART_REGSHIFT, EC_UART_CLOCK, 0, 0);
+ return (status);
+}
+
+DRIVER_MODULE(uart, econaarm, uart_ec_driver, uart_devclass, 0, 0);
Property changes on: trunk/sys/arm/cavium/cns11xx/uart_bus_ec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/cavium/cns11xx/uart_cpu_ec.c
===================================================================
--- trunk/sys/arm/cavium/cns11xx/uart_cpu_ec.c (rev 0)
+++ trunk/sys/arm/cavium/cns11xx/uart_cpu_ec.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,85 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2009 Yohanes Nugroho <yohanes at gmail.com>
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_uart.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/cavium/cns11xx/uart_cpu_ec.c 264219 2014-04-07 05:33:30Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <sys/rman.h>
+
+#include <arm/cavium/cns11xx/econa_reg.h>
+#include <arm/cavium/cns11xx//econa_var.h>
+
+bus_space_tag_t uart_bus_space_io;
+bus_space_tag_t uart_bus_space_mem;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+
+ return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+ struct uart_class *class = &uart_ns8250_class;
+
+ di->ops = uart_getops(class);
+ di->bas.chan = 0;
+ di->bas.bst = obio_tag;
+
+ if (bus_space_map(di->bas.bst, ECONA_IO_BASE + ECONA_UART_BASE,
+ ECONA_UART_SIZE,
+ 0, &di->bas.bsh) != 0) {
+ return (ENXIO);
+ }
+
+ di->baudrate = 0;
+ di->bas.regshft = EC_UART_REGSHIFT;
+ di->bas.rclk = EC_UART_CLOCK ;
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ uart_bus_space_mem = obio_tag;
+ uart_bus_space_io = NULL;
+
+ return (0);
+}
Property changes on: trunk/sys/arm/cavium/cns11xx/uart_cpu_ec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/conf/APALIS-IMX6
===================================================================
--- trunk/sys/arm/conf/APALIS-IMX6 (rev 0)
+++ trunk/sys/arm/conf/APALIS-IMX6 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,31 @@
+# Kernel configuration for Toradex Apalis i.MX6
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/APALIS-IMX6 283500 2015-05-24 18:59:45Z ian $
+
+#NO_UNIVERSE
+
+include "IMX6"
+ident APALIS-IMX6
+
+makeoptions MODULES_OVERRIDE=""
+makeoptions WITHOUT_MODULES="ahc"
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=apalis-imx6.dts
Property changes on: trunk/sys/arm/conf/APALIS-IMX6
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/ARMADAXP
===================================================================
--- trunk/sys/arm/conf/ARMADAXP (rev 0)
+++ trunk/sys/arm/conf/ARMADAXP 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,136 @@
+#
+# Custom kernel for Marvell Armada XP
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/ARMADAXP 283387 2015-05-24 14:57:17Z ian $
+
+ident MV-88F78XX0
+include "../mv/armadaxp/std.mv78x60"
+
+options SOC_MV_ARMADAXP
+
+makeoptions WERROR="-Werror"
+
+options HZ=1000
+#options SCHED_ULE # ULE scheduler
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options ALT_BREAK_TO_DEBUGGER
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+options GDB
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+#options DIAGNOSTIC
+#options KTR
+#options KTR_VERBOSE=0
+#options KTR_ENTRIES=16384
+#options KTR_MASK=(KTR_SPARE2)
+#options KTR_COMPILE=KTR_ALL
+
+# NFS root from boopt/dhcp
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=mge0
+
+options ROOTDEVNAME=\"ufs:/dev/da0p1\"
+
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Pseudo devices
+device random
+device pty
+device loop
+device md
+
+# USB
+options USB_DEBUG # enable debug msgs
+device usb
+device ehci
+device umass
+device scbus
+device pass
+device da
+
+# SATA
+device mvs
+
+# Serial ports
+device uart
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+#Network
+device ether
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+device bpf
+options DEVICE_POLLING
+device vlan
+
+#PCI/PCIE
+device pci
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=db78460.dts
Property changes on: trunk/sys/arm/conf/ARMADAXP
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/ARNDALE
===================================================================
--- trunk/sys/arm/conf/ARNDALE (rev 0)
+++ trunk/sys/arm/conf/ARNDALE 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,28 @@
+# Kernel configuration for Arndale Board (Exynos5 Dual development platform).
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/ARNDALE 278599 2015-02-11 22:35:32Z ian $
+
+#NO_UNIVERSE
+
+include "EXYNOS5250"
+ident ARNDALE
+
+#FDT
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=exynos5250-arndale.dts
Property changes on: trunk/sys/arm/conf/ARNDALE
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/ARNDALE-OCTA
===================================================================
--- trunk/sys/arm/conf/ARNDALE-OCTA (rev 0)
+++ trunk/sys/arm/conf/ARNDALE-OCTA 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,28 @@
+# Kernel configuration for Arndale Octa Board (Exynos 5420)
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/ARNDALE-OCTA 278599 2015-02-11 22:35:32Z ian $
+
+#NO_UNIVERSE
+
+include "EXYNOS5420"
+ident ARNDALE-OCTA
+
+#FDT
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=exynos5420-arndale-octa.dts
Property changes on: trunk/sys/arm/conf/ARNDALE-OCTA
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/ATMEL
===================================================================
--- trunk/sys/arm/conf/ATMEL (rev 0)
+++ trunk/sys/arm/conf/ATMEL 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,181 @@
+# Kernel configuration to test compile all the atmel bits with one
+# configuration. This kernel will not (presently) boot. Do not copy
+# it to create your own custom config file.
+#
+# $FreeBSD: stable/10/sys/arm/conf/ATMEL 283930 2015-06-02 21:24:47Z imp $
+
+ident ATMEL
+
+include "../at91/std.atmel"
+
+# Typical values for most SoCs and board configurations. Will not work for
+# at91sam9g45 or on some boards with non u-boot boot loaders.
+makeoptions KERNPHYSADDR=0x20000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x20000000
+options KERNVIRTADDR=0xc0000000
+
+makeoptions MODULES_OVERRIDE="dtb/atmel"
+
+# list all boards here, but not just yet (no multiboard in mainline).
+options ARM_MANY_BOARD
+device at91_board_bwct
+device at91_board_ethernut5
+device at91_board_hl200
+device at91_board_hl201
+device at91_board_kb920x
+device at91_board_qila9g20
+device at91_board_sam9260ek
+device at91_board_sam9g20ek
+device at91_board_sam9x25ek
+device at91_board_sn9g45
+device at91_board_tsc4370
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+
+options SCHED_4BSD # 4BSD scheduler
+#options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options MD_ROOT # MD is a potential root device
+options NFSCL # New Network Filesystem Client
+options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options TMPFS # Efficient memory filesystem
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_PART_GPT # GUID Partition Tables.
+options GEOM_LABEL # Provides labelization
+options COMPAT_FREEBSD5 # Compatible with FreeBSD5
+options COMPAT_FREEBSD6 # Compatible with FreeBSD6
+options COMPAT_FREEBSD7 # Compatible with FreeBSD7
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options STACK # stack(9) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed.
+#options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4)
+#options AUDIT # Security event auditing
+#options CAPABILITY_MODE # Capsicum capability mode
+#options CAPABILITIES # Capsicum capabilities
+#options MAC # TrustedBSD MAC Framework
+#options INCLUDE_CONFIG_FILE # Include this file in kernel
+
+# required for netbooting
+options BOOTP
+options BOOTP_COMPAT
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=ate0
+
+# alternatively, boot from a MMC/SD memory card
+#options ROOTDEVNAME=\"ufs:/dev/mmcsd0a\"
+
+# kernel/memory size reduction
+options MUTEX_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+options NO_SYSCTL_DESCR
+options RWLOCK_NOINLINE
+
+# Debugging support. Always need this:
+options KDB # Enable kernel debugger support.
+# For minimum debugger support (stable branch) use:
+options KDB_TRACE # Print a stack trace for a panic.
+# For full debugger support use this instead:
+options DDB # Support DDB.
+options GDB # Support remote GDB.
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device bpf # Berkeley packet filter
+
+# Ethernet
+device mii # Minimal MII support
+device ate # Atmel AT91 Ethernet friver
+
+# I2C
+device at91_twi # Atmel AT91 Two-wire Interface
+device iic # I2C generic I/O device driver
+device iicbus # I2C bus system
+device pcf8563 # NXP PCF8563 clock/calendar
+
+# MMC/SD
+device at91_mci # Atmel AT91 Multimedia Card Interface
+options AT91_MCI_HAS_4WIRE
+device mmc # MMC/SD bus
+device mmcsd # MMC/SD memory card
+
+# DataFlash
+device at91_spi # Atmel AT91 Serial Peripheral Interface
+device spibus # SPI bus
+device at45d # Atmel AT45D
+device geom_map # GEOM partition mapping
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+device vlan # 802.1Q VLAN support
+device tun # Packet tunnel.
+device md # Memory "disks"
+device gif # IPv6 and IPv4 tunneling
+device faith # IPv6-to-IPv4 relaying (translation)
+#device firmware # firmware assist module
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device ch # SCSI media changers
+device da # Direct Access (disks)
+device sa # Sequential Access (tape etc)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+device ses # Enclosure Services (SES and SAF-TE)
+#device ctl # CAM Target Layer
+
+# Serial (COM) ports
+device uart # Multi-uart driver
+options ALT_BREAK_TO_DEBUGGER
+
+# USB support
+options USB_DEBUG # enable debug msgs
+device ohci # OHCI USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+
+# USB device (gadget) support
+device at91_dci # Atmel's usb device
+device usfs # emulate a flash
+device cdce # emulate an ethernet
+device usb_template # Control of the gadget
+
+# watchdog
+device at91_wdt # Atmel AT91 Watchdog Timer
+
+device at91_rtc
+device at91_ssc
+#device at91_tc # missing?
+
+# NAND Flash - Reference design has Samsung 256MB but others possible
+device nand # NAND interface on CS3
Property changes on: trunk/sys/arm/conf/ATMEL
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/AVILA
===================================================================
--- trunk/sys/arm/conf/AVILA (rev 0)
+++ trunk/sys/arm/conf/AVILA 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,158 @@
+# AVILA -- Gateworks Avila XScale board
+# kernel configuration file for FreeBSD/arm
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/AVILA 271428 2014-09-11 15:36:36Z ian $
+
+ident AVILA
+
+include "../xscale/ixp425/std.ixp425"
+# NB: memory mapping is defined in std.avila
+include "../xscale/ixp425/std.avila"
+options XSCALE_CACHE_READ_WRITE_ALLOCATE
+#To statically compile in device wiring instead of /boot/device.hints
+hints "AVILA.hints" # Default places to look for devices.
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions CONF_CFLAGS=-mcpu=xscale
+#options HZ=1000
+options HZ=100
+options DEVICE_POLLING
+
+# Debugging for use in -current
+options KDB
+#options GDB
+options DDB # Enable the kernel debugger
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options NFSCL # New Network Filesystem Client
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=npe0
+#options BOOTP_WIRED_TO=ath0
+#options BOOTP_WIRED_TO=rl0
+options BOOTP_COMPAT
+#options PREEMPTION
+#options VERBOSE_SYSINIT
+
+# Hardware performance counters
+options HWPMC_HOOKS
+device hwpmc
+
+#device saarm
+
+device pci
+device uart
+
+device ixpwdog # watchdog timer
+device cfi # flash support
+device cfid # flash disk support
+device geom_redboot # redboot fis parser
+
+# I2C Bus
+device iicbus
+device iicbb
+device iic
+
+device ixpiic # I2C bus glue
+device ds1672 # DS1672 on I2C bus
+device ad7418 # AD7418 on I2C bus
+
+device avila_led
+
+device gpio
+device gpioled
+device avila_gpio # GPIO pins on J8
+
+device ata
+device avila_ata # Gateworks CF/IDE support
+
+device npe # Network Processing Engine
+device npe_fw
+device firmware
+device qmgr # Q Manager (required by npe)
+device mii # NB: required by npe
+device ether
+device bpf
+
+device loop
+device if_bridge
+
+device md
+device random # Entropy device
+
+# Wireless NIC cards
+device wlan # 802.11 support
+options IEEE80211_DEBUG
+options IEEE80211_SUPPORT_TDMA
+options IEEE80211_SUPPORT_MESH
+device wlan_wep # 802.11 WEP support
+device wlan_ccmp # 802.11 CCMP support
+device wlan_tkip # 802.11 TKIP support
+device wlan_xauth
+
+device ath # Atheros NICs
+device ath_pci # Atheros pci/cardbus glue
+options ATH_DEBUG
+options ATH_DIAGAPI
+#options ATH_TX99_DIAG
+device ath_rate_sample # SampleRate tx rate control for ath
+
+#options AH_DEBUG
+#options AH_ASSERT
+#device ath_ar5210
+#device ath_ar5211
+device ath_ar5212
+device ath_rf2413
+device ath_rf2417
+device ath_rf2425
+device ath_rf5111
+device ath_rf5112
+device ath_rf5413
+#
+device ath_ar5416
+options AH_SUPPORT_AR5416
+device ath_ar9160
+device ath_ar9280
+
+device usb
+#options USB_DEBUG
+device ohci
+device ehci
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass # Passthrough device (direct ATA/SCSI access)
+
+#device ural
+#device zyd
+#device wlan_amrr
Property changes on: trunk/sys/arm/conf/AVILA
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/AVILA.hints
===================================================================
--- trunk/sys/arm/conf/AVILA.hints (rev 0)
+++ trunk/sys/arm/conf/AVILA.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,53 @@
+# $FreeBSD: stable/10/sys/arm/conf/AVILA.hints 239699 2012-08-26 01:21:02Z gjb $
+
+#
+# Device wiring for the Gateworks Avila 2384.
+#
+
+# DBGU is unit 0
+hint.uart.0.at="ixp0"
+hint.uart.0.addr=0xc8000000
+hint.uart.0.irq=15
+hint.uart.0.flags=0x10
+hint.uart.0.ier_rxbits=0x5d # NB: need UUE+RTOIE
+# USART0 is unit 1
+hint.uart.1.at="ixp0"
+hint.uart.1.addr=0xc8001000
+hint.uart.1.irq=13
+hint.uart.1.ier_rxbits=0x5d # NB: need UUE+RTOIE
+
+# NPE Hardware Queue Manager
+hint.ixpqmgr.0.at="ixp0"
+
+# NPE wired NICs, requires ixpqmgr
+hint.npe.0.at="ixp0"
+hint.npe.0.npeid="B"
+hint.npe.0.mac="B"
+hint.npe.0.mii="B"
+hint.npe.0.phy=0
+hint.npe.1.at="ixp0"
+hint.npe.1.npeid="C"
+hint.npe.1.mac="C"
+hint.npe.1.mii="B"
+hint.npe.1.phy=1
+
+# FLASH
+hint.cfi.0.at="ixp0"
+hint.cfi.0.addr=0x50000000
+
+# CF IDE controller
+hint.ata_avila.0.at="ixp0"
+
+# Front Panel LED
+hint.led_avila.0.at="ixp0"
+
+# GPIO pins
+hint.gpio_avila.0.at="ixp0"
+
+# Analog Devices AD7418 temperature sensor
+hint.ad7418.0.at="iicbus0"
+hint.ad7418.0.addr=0x50
+
+# Dallas Semiconductor DS1672 RTC
+hint.ds1672_rtc.0.at="iicbus0"
+hint.ds1672_rtc.0.addr=0xd0
Property changes on: trunk/sys/arm/conf/AVILA.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/BEAGLEBONE
===================================================================
--- trunk/sys/arm/conf/BEAGLEBONE (rev 0)
+++ trunk/sys/arm/conf/BEAGLEBONE 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,161 @@
+#
+# BEAGLEBONE -- Custom configuration for the BeagleBone ARM development
+# platforms, check out http://www.beagleboard.org/bone and
+# http://www.beagleboard.org/black. This kernel config file is used for the
+# original BeagleBone and the BeagleBone Black.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/BEAGLEBONE 287082 2015-08-23 20:50:22Z ian $
+
+ident BEAGLEBONE
+
+include "../ti/am335x/std.am335x"
+
+makeoptions MODULES_EXTRA="dtb/am335x"
+
+options HZ=100
+options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_LABEL # Provides labelization
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS server support
+#options NFSD
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=cpsw0
+
+# Boot device is 2nd slice on MMC/SD card
+options ROOTDEVNAME=\"ufs:mmcsd0s2\"
+
+# MMC/SD/SDIO Card slot support
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+device sdhci # mmc/sd host controller
+
+# I2C support
+device iicbus
+device iic
+device ti_i2c
+device am335x_pmic # AM335x Power Management IC (TPC65217)
+
+device am335x_rtc # RTC support (power management only)
+
+# Console and misc
+device uart
+device uart_ns8250
+device pty
+device snp
+device md
+device random # Entropy device
+
+# GPIO
+device gpio
+device gpioled
+
+# ADC support
+device ti_adc
+
+# Watchdog support
+# If we don't enable the watchdog driver, the system could potentially
+# reboot automatically because the boot loader might have enabled the
+# watchdog.
+device ti_wdt
+
+# TI Programmable Realtime Unit support
+device ti_pruss
+
+# Mailbox support
+device ti_mbox
+
+# USB support
+device usb
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+device musb
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+
+# Ethernet
+device loop
+device ether
+device mii
+device smscphy
+device cpsw
+device bpf
+
+# USB Ethernet support, requires miibus
+device miibus
+device axe # ASIX Electronics USB Ethernet
+
+# Device mode support and USFS template
+device usb_template # Control of the gadget
+device usfs
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
Property changes on: trunk/sys/arm/conf/BEAGLEBONE
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/BWCT
===================================================================
--- trunk/sys/arm/conf/BWCT (rev 0)
+++ trunk/sys/arm/conf/BWCT 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,114 @@
+# BWCT -- Custom kernel configuration for the AT91RM9200 boards from bwct.de.
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/BWCT 266383 2014-05-18 00:21:14Z ian $
+
+#NO_UNIVERSE
+
+ident BWCT
+
+options VERBOSE_INIT_ARM
+
+include "../at91/std.bwct"
+
+#To statically compile in device wiring instead of /boot/device.hints
+hints "BWCT.hints"
+makeoptions MODULES_OVERRIDE=""
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+options BREAK_TO_DEBUGGER
+options ALT_BREAK_TO_DEBUGGER
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+#options ROOTDEVNAME=\"ufs:md0\"
+#options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP_NFSROOT
+options BOOTP
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+#options NO_SYSCTL_DESCR
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+device loop
+device random
+device ether
+device vlan
+device uart
+device ate
+device mii
+device rlswitch
+
+# Debugging for use in -current
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+device md
+device at91_twi # TWI: Two Wire Interface
+device at91_spi # SPI:
+device at91_ssc
+device at91_mci
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+# iic
+device iic
+device iicbus
+device ds1672 # DS1672 on I2C bus
+#device iicsmb # smb over i2c bridge
+#device smbus # Bus support, required for smb below.
+#device smb
+# SPI bus
+device spibus
+#device at45d # at45db642 and maybe others
+
+device bpf # Berkeley packet filter
+
+#options USB_DEBUG
+#device ohci
+#device usb
+#device umass # Disks/Mass storage - Requires scbus and da
Property changes on: trunk/sys/arm/conf/BWCT
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/BWCT.hints
===================================================================
--- trunk/sys/arm/conf/BWCT.hints (rev 0)
+++ trunk/sys/arm/conf/BWCT.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,13 @@
+# $FreeBSD: stable/10/sys/arm/conf/BWCT.hints 215124 2010-11-11 15:02:14Z ticso $
+
+# Dallas Semiconductor DS1672 RTC sitting on the I2C bus
+hint.ds1672_rtc.0.at="iicbus0"
+hint.ds1672_rtc.0.addr=0xd0
+
+# National Semiconductor LM75 temperature sensor sitting on the I2C bus
+hint.lm75.0.at="iicbus0"
+hint.lm75.0.addr=0x9e
+
+# Atmel SPIflash sitting on the spibus
+hint.at45d.0.at="spibus0"
+hint.at45d.0.addr=0x00
Property changes on: trunk/sys/arm/conf/BWCT.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/CAMBRIA
===================================================================
--- trunk/sys/arm/conf/CAMBRIA (rev 0)
+++ trunk/sys/arm/conf/CAMBRIA 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,152 @@
+# CAMBRIA -- Gateworks Cambria 235x boards
+# kernel configuration file for FreeBSD/arm
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/CAMBRIA 271428 2014-09-11 15:36:36Z ian $
+
+ident CAMBRIA
+
+include "../xscale/ixp425/std.ixp435"
+# NB: memory mapping is defined in std.avila
+include "../xscale/ixp425/std.avila"
+options XSCALE_CACHE_READ_WRITE_ALLOCATE
+#To statically compile in device wiring instead of /boot/device.hints
+hints "CAMBRIA.hints" # Default places to look for devices.
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions CONF_CFLAGS=-mcpu=xscale
+makeoptions MODULES_OVERRIDE=""
+#options HZ=1000
+options HZ=100
+options DEVICE_POLLING
+
+# Debugging for use in -current
+options KDB
+#options GDB
+options DDB # Enable the kernel debugger
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+options SCHED_4BSD # 4BSD scheduler
+#options PREEMPTION
+options INET # InterNETworking
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options NFSCL # New Network Filesystem Client
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=npe0
+options BOOTP_COMPAT
+
+# Hardware performance counters
+options HWPMC_HOOKS
+device hwpmc
+
+#options VERBOSE_SYSINIT
+options VERBOSE_INIT_ARM
+
+#device saarm
+
+device pci
+device uart
+
+device ixpwdog # watchdog timer
+
+options IXP4XX_FLASH_SIZE=0x02000000 # stock 2358 comes w/ 32M
+device cfi # flash support
+device cfid # flash disk support
+device geom_redboot # redboot fis parser
+
+# I2C Bus
+device iicbus
+device iicbb
+device iic
+
+device ixpiic # I2C bus glue
+device ds1672 # DS1672 on I2C bus
+device ad7418 # AD7418 on I2C bus
+
+device cambria_fled # Font Panel LED on I2C bus
+device cambria_led # 8-LED latch
+
+device gpio
+device gpioled
+device cambria_gpio # GPIO pins on J11
+
+device ata
+device avila_ata # Gateworks CF/IDE support
+
+device npe # Network Processing Engine
+device npe_fw
+device firmware
+device qmgr # Q Manager (required by npe)
+device mii # NB: required by npe
+device ether
+device bpf
+
+device loop
+device if_bridge
+
+device md
+device random # Entropy device
+
+# Wireless NIC cards
+device wlan # 802.11 support
+options IEEE80211_DEBUG
+options IEEE80211_SUPPORT_TDMA
+options IEEE80211_SUPPORT_MESH
+device wlan_wep # 802.11 WEP support
+device wlan_ccmp # 802.11 CCMP support
+device wlan_tkip # 802.11 TKIP support
+device wlan_xauth
+
+device ath # Atheros NICs
+device ath_pci # Atheros pci/cardbus glue
+options ATH_DEBUG
+options ATH_DIAGAPI
+options ATH_ENABLE_DFS
+options ATH_ENABLE_11N
+#options ATH_TX99_DIAG
+device ath_rate_sample # SampleRate tx rate control for ath
+
+options AH_DEBUG
+options AH_PRIVATE_DIAG
+options AH_SUPPORT_AR5416 # NB: for 11n descriptor format
+device ath_hal
+
+# NB: 2 USB 2.0 ports standard
+device usb
+options USB_EHCI_BIG_ENDIAN_DESC # handle big-endian byte order
+#options USB_DEBUG
+device ehci
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass # Passthrough device (direct ATA/SCSI access)
+
+#device ural
+#device zyd
+#device wlan_amrr
Property changes on: trunk/sys/arm/conf/CAMBRIA
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/CAMBRIA.hints
===================================================================
--- trunk/sys/arm/conf/CAMBRIA.hints (rev 0)
+++ trunk/sys/arm/conf/CAMBRIA.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,75 @@
+# $FreeBSD: stable/10/sys/arm/conf/CAMBRIA.hints 239699 2012-08-26 01:21:02Z gjb $
+
+#
+# Device wiring for the Gateworks Cambria 2358.
+#
+
+# DBGU is unit 0
+hint.uart.0.at="ixp0"
+hint.uart.0.addr=0xc8000000
+hint.uart.0.irq=15
+hint.uart.0.flags=0x10
+hint.uart.0.ier_rxbits=0x5d # NB: need UUE+RTOIE
+
+# NB: no UART1 on ixp435
+
+# optional GPS serial port
+#hint.uart.1.at="ixp0"
+#hint.uart.1.addr=0x53fc0000
+#hint.uart.1.irq=20
+#hint.uart.1.ier_rxbits=0x1
+#hint.uart.1.rclk=1843200
+# optional RS485 serial port
+#hint.uart.2.at="ixp0"
+#hint.uart.2.addr=0x53f80000
+#hint.uart.2.irq=21
+#hint.uart.2.rclk=1843200
+
+# NPE Hardware Queue Manager
+hint.ixpqmgr.0.at="ixp0"
+
+# NPE wired NICs, requires ixpqmgr
+hint.npe.0.at="ixp0"
+hint.npe.0.npeid="C"
+hint.npe.0.mac="C"
+hint.npe.0.mii="C"
+hint.npe.0.phy=1
+hint.npe.1.at="ixp0"
+hint.npe.1.npeid="A"
+hint.npe.1.mac="A"
+hint.npe.1.mii="C"
+hint.npe.1.phy=2
+
+# FLASH
+hint.cfi.0.at="ixp0"
+hint.cfi.0.addr=0x50000000
+
+# CF IDE controller
+hint.ata_avila.0.at="ixp0"
+
+# Front Panel LED
+hint.fled.0.at="iicbus0"
+hint.fled.0.addr=0x5a
+
+# Octal LED Latch
+hint.led_cambria.0.at="ixp0"
+
+# GPIO pins
+hint.gpio_cambria.0.at="iicbus0"
+hint.gpio_cambria.0.addr=0x56
+
+# Analog Devices AD7418 temperature sensor
+hint.ad7418.0.at="iicbus0"
+hint.ad7418.0.addr=0x50
+
+# Dallas Semiconductor DS1672 RTC
+hint.ds1672_rtc.0.at="iicbus0"
+hint.ds1672_rtc.0.addr=0xd0
+
+# USB is part of the chip
+hint.ehci.0.at="ixp0"
+hint.ehci.0.addr=0xcd000000
+hint.ehci.0.irq=32
+hint.ehci.1.at="ixp0"
+hint.ehci.1.addr=0xce000000
+hint.ehci.1.irq=33
Property changes on: trunk/sys/arm/conf/CAMBRIA.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/CHROMEBOOK
===================================================================
--- trunk/sys/arm/conf/CHROMEBOOK (rev 0)
+++ trunk/sys/arm/conf/CHROMEBOOK 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,38 @@
+# Kernel configuration for Samsung Chromebook (Exynos5 Dual machine).
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/CHROMEBOOK 278599 2015-02-11 22:35:32Z ian $
+
+include "EXYNOS5250"
+ident CHROMEBOOK
+
+hints "CHROMEBOOK.hints"
+
+device chrome_ec # Chrome Embedded Controller
+device chrome_kb # Chrome Keyboard
+
+# Framebuffer
+device vt
+device kbdmux
+options SC_DFLT_FONT # compile font in
+makeoptions SC_DFLT_FONT=cp437
+device ukbd
+
+#FDT
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=exynos5250-chromebook.dts
Property changes on: trunk/sys/arm/conf/CHROMEBOOK
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/CHROMEBOOK.hints
===================================================================
--- trunk/sys/arm/conf/CHROMEBOOK.hints (rev 0)
+++ trunk/sys/arm/conf/CHROMEBOOK.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+# $FreeBSD: stable/10/sys/arm/conf/CHROMEBOOK.hints 266341 2014-05-17 19:37:04Z ian $
+
+# Chrome Embedded Controller
+hint.chrome_ec.0.at="iicbus0"
+hint.chrome_ec.0.addr=0x1e
Property changes on: trunk/sys/arm/conf/CHROMEBOOK.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/CNS11XXNAS
===================================================================
--- trunk/sys/arm/conf/CNS11XXNAS (rev 0)
+++ trunk/sys/arm/conf/CNS11XXNAS 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,125 @@
+# CNS11XXNAS - StarSemi STR9104/Cavium CNS1102 NAS
+# kernel configuration file for FreeBSD/arm
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/CNS11XXNAS 283368 2015-05-24 14:25:03Z ian $
+
+ident CNS11XXNAS
+
+#options PHYSADDR=0x10000000
+#options KERNPHYSADDR=0x10200000
+#options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+#options FLASHADDR=0x50000000
+#options LOADERRAMADDR=0x00000000
+
+include "../cavium/cns11xx/std.econa"
+
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options HZ=100
+options DEVICE_POLLING
+
+# Debugging for use in -current
+options KDB
+#options GDB
+options DDB # Enable the kernel debugger
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+##options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+
+#options COMPAT_FREEBSD5
+#options COMPAT_FREEBSD6
+#options COMPAT_FREEBSD7n
+
+
+options SCHED_ULE # ULE scheduler
+#options SCHED_4BSD # 4BSD scheduler
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_PART_GPT # GUID Partition Tables.
+#options GEOM_PART_EBR
+#options GEOM_PART_EBR_COMPAT
+options GEOM_LABEL # Provides labelization
+
+
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options TMPFS # Efficient memory filesystem
+options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE # Mutex inlines are space hogs
+options RWLOCK_NOINLINE # rwlock inlines are space hogs
+options SX_NOINLINE # sx inliens are space hogs
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=npe0
+#options BOOTP_COMPAT
+
+#device pci
+device uart
+
+
+device firmware
+device mii # Minimal mii routines
+device ether
+device bpf
+
+device loop
+
+device md
+device random # Entropy device
+
+
+device usb
+#options USB_DEBUG
+device ohci
+device ehci
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass
+device cfi
+
+#device udav # Davicom DM9601E USB
+
+device geom_label
+device geom_journal
+device geom_part_bsd
+
+options ROOTDEVNAME=\"ufs:da0s1a\"
Property changes on: trunk/sys/arm/conf/CNS11XXNAS
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/COLIBRI-VF50
===================================================================
--- trunk/sys/arm/conf/COLIBRI-VF50 (rev 0)
+++ trunk/sys/arm/conf/COLIBRI-VF50 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,28 @@
+# Kernel configuration for Toradex Colibri VF50 Evaluation Board.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/COLIBRI-VF50 266383 2014-05-18 00:21:14Z ian $
+
+#NO_UNIVERSE
+
+include "VYBRID"
+ident COLIBRI-VF50
+
+#FDT
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=vybrid-colibri-vf50.dts
Property changes on: trunk/sys/arm/conf/COLIBRI-VF50
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/COSMIC
===================================================================
--- trunk/sys/arm/conf/COSMIC (rev 0)
+++ trunk/sys/arm/conf/COSMIC 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,28 @@
+# Kernel configuration for Cosmic Board (Freescale Vybrid Family development board).
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/COSMIC 266383 2014-05-18 00:21:14Z ian $
+
+#NO_UNIVERSE
+
+include "VYBRID"
+ident COSMIC
+
+#FDT
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=vybrid-cosmic.dts
Property changes on: trunk/sys/arm/conf/COSMIC
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/CRB
===================================================================
--- trunk/sys/arm/conf/CRB (rev 0)
+++ trunk/sys/arm/conf/CRB 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,110 @@
+# GENERIC -- Generic kernel configuration file for FreeBSD/arm
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/CRB 278677 2015-02-13 15:32:31Z ian $
+
+ident CRB
+
+options PHYSADDR=0x00000000
+options KERNPHYSADDR=0x00200000
+options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+
+options COUNTS_PER_SEC=400000000
+include "../xscale/i8134x/std.crb"
+makeoptions MODULES_OVERRIDE=""
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions CONF_CFLAGS=-mcpu=xscale
+options HZ=100
+options BREAK_TO_DEBUGGER
+#options DEVICE_POLLING
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options NFSCL # New Network Filesystem Client
+options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+#options MSDOSFS # MSDOS Filesystem
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options INTR_FILTER
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=em0
+options BOOTP_COMPAT
+#options PREEMPTION
+device loop
+device ether
+#device saarm
+device miibus
+device rl
+device em
+device uart
+device pci
+
+device ata
+options ATA_STATIC_ID # Static device numbering
+
+device scbus # SCSI bus (required for ATA/SCSI)
+device cd # CD
+device da # Direct Access (disks)
+device pass # Passthrough device (direct ATA/SCSI access)
+
+device "7seg"
+
+# SCSI Controllers
+
+#options AHC_REG_PRETTY_PRINT # Print register bitfields in debug
+ # output. Adds ~128k to driver.
+#options AHD_REG_PRETTY_PRINT # Print register bitfields in debug
+ # output. Adds ~215k to driver.
+
+# Debugging for use in -current
+options KDB
+options DDB # Enable the kernel debugger
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+options XSCALE_CACHE_READ_WRITE_ALLOCATE
+device md
+device random # Entropy device
+
+device iopwdog
+# Floppy drives
+
Property changes on: trunk/sys/arm/conf/CRB
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/CUBIEBOARD
===================================================================
--- trunk/sys/arm/conf/CUBIEBOARD (rev 0)
+++ trunk/sys/arm/conf/CUBIEBOARD 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,142 @@
+#
+# CUBIEBOARD -- Custom configuration for the CUBIEBOARD ARM development
+# platform, check out http://www.cubieboard.org
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/CUBIEBOARD 287082 2015-08-23 20:50:22Z ian $
+
+ident CUBIEBOARD
+
+include "../allwinner/std.a10"
+
+options HZ=100
+options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=cpsw0
+
+# Boot device is 2nd slice on MMC/SD card
+options ROOTDEVNAME=\"ufs:/dev/da0s2\"
+
+# MMC/SD/SDIO Card slot support
+#device mmc # mmc/sd bus
+#device mmcsd # mmc/sd flash cards
+
+# ATA controllers
+#device ahci # AHCI-compatible SATA controllers
+#device ata # Legacy ATA/SATA controllers
+#options ATA_STATIC_ID # Static device numbering
+
+# Console and misc
+device uart
+device uart_ns8250
+device pty
+device snp
+device md
+device random # Entropy device
+
+# I2C support
+#device iicbus
+#device iic
+
+# GPIO
+device gpio
+
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+#device uhci
+#device ohci
+device ehci
+
+device umass
+
+# Ethernet
+device loop
+device ether
+device mii
+device smscphy
+#device cpsw
+device bpf
+
+device emac
+
+# USB ethernet support, requires miibus
+device miibus
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=cubieboard.dts
+
Property changes on: trunk/sys/arm/conf/CUBIEBOARD
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/CUBIEBOARD2
===================================================================
--- trunk/sys/arm/conf/CUBIEBOARD2 (rev 0)
+++ trunk/sys/arm/conf/CUBIEBOARD2 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,143 @@
+#
+# CUBIEBOARD2 -- Custom configuration for the CUBIEBOARD2 ARM development
+# platform, check out http://www.cubieboard.org
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/CUBIEBOARD2 287082 2015-08-23 20:50:22Z ian $
+
+ident CUBIEBOARD2
+
+include "../allwinner/a20/std.a20"
+
+options HZ=100
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=cpsw0
+
+# Boot device is 2nd slice on MMC/SD card
+options ROOTDEVNAME=\"ufs:/dev/da0s2\"
+
+# MMC/SD/SDIO Card slot support
+#device mmc # mmc/sd bus
+#device mmcsd # mmc/sd flash cards
+
+# ATA controllers
+#device ahci # AHCI-compatible SATA controllers
+#device ata # Legacy ATA/SATA controllers
+#options ATA_STATIC_ID # Static device numbering
+
+# Console and misc
+device uart
+device uart_ns8250
+device pty
+device snp
+device md
+device random # Entropy device
+
+# I2C support
+#device iicbus
+#device iic
+
+# GPIO
+device gpio
+
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+#device uhci
+#device ohci
+device ehci
+
+device umass
+
+# Ethernet
+device loop
+device ether
+device mii
+device smscphy
+#device cpsw
+device bpf
+
+device emac
+
+# USB ethernet support, requires miibus
+device miibus
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=cubieboard2.dts
+
Property changes on: trunk/sys/arm/conf/CUBIEBOARD2
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/DB-78XXX
===================================================================
--- trunk/sys/arm/conf/DB-78XXX (rev 0)
+++ trunk/sys/arm/conf/DB-78XXX 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,94 @@
+#
+# Custom kernel for Marvell DB-78xx boards.
+#
+# $FreeBSD: stable/10/sys/arm/conf/DB-78XXX 283404 2015-05-24 15:21:47Z ian $
+#
+
+ident DB-88F78XX
+include "../mv/discovery/std.db78xxx"
+
+options SOC_MV_DISCOVERY
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions WERROR="-Werror"
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+options NANDFS # NAND Filesystem
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=mge0
+
+#options ROOTDEVNAME=\"ufs:/dev/da0a\"
+
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+#options DEADLKRES # Enable the deadlock resolver
+#options DIAGNOSTIC
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options KDB
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+
+device pci
+
+# Pseudo devices
+device loop
+device md
+device random
+
+# Serial ports
+device uart
+
+# Networking
+device ether
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+device bpf
+
+# USB
+options USB_DEBUG # enable debug msgs
+device usb
+device ehci
+device umass
+device scbus
+device pass
+device da
+
+# I2C (TWSI)
+device iic
+device iicbus
+device ds133x
+
+# SATA
+device mvs
+
+# NAND
+device nand
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=db78100.dts
Property changes on: trunk/sys/arm/conf/DB-78XXX
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/DB-88F5XXX
===================================================================
--- trunk/sys/arm/conf/DB-88F5XXX (rev 0)
+++ trunk/sys/arm/conf/DB-88F5XXX 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,91 @@
+#
+# Custom kernel for Marvell DB-88F5xxx boards.
+#
+# $FreeBSD: stable/10/sys/arm/conf/DB-88F5XXX 283404 2015-05-24 15:21:47Z ian $
+#
+
+ident DB-88F5XXX
+include "../mv/orion/std.db88f5xxx"
+
+options SOC_MV_ORION
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions WERROR="-Werror"
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=mge0
+
+#options ROOTDEVNAME=\"ufs:/dev/da0a\"
+
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+#options DEADLKRES # Enable the deadlock resolver
+#options DIAGNOSTIC
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options KDB
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+
+device pci
+
+# Pseudo devices
+device md
+device loop
+device random
+
+# Serial ports
+device uart
+
+# Networking
+device ether
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+device bpf
+options DEVICE_POLLING
+options HZ=1000
+
+# I2C (TWSI)
+device iic
+device iicbus
+device ds133x
+
+# USB
+options USB_DEBUG # enable debug msgs
+device usb
+device ehci
+device umass
+device scbus
+device pass
+device da
+
+# SATA
+device mvs
+
+# Flattened Device Tree
+options FDT
+makeoptions FDT_DTS_FILE=db88f5281.dts
Property changes on: trunk/sys/arm/conf/DB-88F5XXX
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/DB-88F6XXX
===================================================================
--- trunk/sys/arm/conf/DB-88F6XXX (rev 0)
+++ trunk/sys/arm/conf/DB-88F6XXX 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,97 @@
+#
+# Custom kernel for Marvell DB-88F6xxx boards.
+#
+# $FreeBSD: stable/10/sys/arm/conf/DB-88F6XXX 283404 2015-05-24 15:21:47Z ian $
+#
+
+ident DB-88F6XXX
+include "../mv/kirkwood/std.db88f6xxx"
+
+options SOC_MV_KIRKWOOD
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions WERROR="-Werror"
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+options NANDFS # NAND Filesystem
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=mge0
+
+#options ROOTDEVNAME=\"ufs:/dev/da0a\"
+
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+#options DEADLKRES # Enable the deadlock resolver
+#options DIAGNOSTIC
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options KDB
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+
+device pci
+
+# Pseudo devices
+device loop
+device md
+device random
+
+# Serial ports
+device uart
+
+# Networking
+device ether
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+device bpf
+
+device cesa # Marvell security engine
+device crypto
+device cryptodev
+
+# USB
+options USB_DEBUG # enable debug msgs
+device usb
+device ehci
+device umass
+device scbus
+device pass
+device da
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+# SATA
+device mvs
+
+# NAND
+device nand
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=db88f6281.dts
Property changes on: trunk/sys/arm/conf/DB-88F6XXX
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/DEFAULTS
===================================================================
--- trunk/sys/arm/conf/DEFAULTS (rev 0)
+++ trunk/sys/arm/conf/DEFAULTS 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,7 @@
+#
+# DEFAULTS -- Default kernel configuration file for FreeBSD/arm
+#
+# $FreeBSD: stable/10/sys/arm/conf/DEFAULTS 266277 2014-05-17 00:53:12Z ian $
+
+device mem
+
Property changes on: trunk/sys/arm/conf/DEFAULTS
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/DIGI-CCWMX53
===================================================================
--- trunk/sys/arm/conf/DIGI-CCWMX53 (rev 0)
+++ trunk/sys/arm/conf/DIGI-CCWMX53 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,38 @@
+# Kernel configuration for Digi ConnectCore Wi-i.MX53 boards
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/DIGI-CCWMX53 283368 2015-05-24 14:25:03Z ian $
+
+#NO_UNIVERSE
+
+include "IMX53"
+ident DIGI-CCWMX53
+
+makeoptions WITHOUT_MODULES="ahc"
+
+# required for netbooting
+#options BOOTP
+#options BOOTP_COMPAT
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ffec0
+
+#options ROOTDEVNAME=\"ufs:ada0s2a\"
+
+# Flattened Device Tree
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=digi-ccwmx53.dts
Property changes on: trunk/sys/arm/conf/DIGI-CCWMX53
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/DOCKSTAR
===================================================================
--- trunk/sys/arm/conf/DOCKSTAR (rev 0)
+++ trunk/sys/arm/conf/DOCKSTAR 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,167 @@
+#
+# Custom kernel for Seagate DockStar (Marvell SheevaPlug based) devices.
+#
+# $FreeBSD: stable/10/sys/arm/conf/DOCKSTAR 287082 2015-08-23 20:50:22Z ian $
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/DOCKSTAR 287082 2015-08-23 20:50:22Z ian $
+#
+#NO_UNIVERSE
+
+ident DOCKSTAR
+
+include "../mv/kirkwood/std.db88f6xxx"
+
+makeoptions FDT_DTS_FILE=dockstar.dts
+
+options SOC_MV_KIRKWOOD
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SOFTUPDATES
+options CD9660 # ISO 9660 filesystem
+options FFS # Berkeley Fast Filesystem
+options TMPFS # Efficient memory filesystem
+options MSDOSFS # MS DOS File System (FAT, FAT32)
+options NULLFS # NULL filesystem
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_ELI # Disk encryption.
+options GEOM_LABEL # Providers labelization.
+options GEOM_PART_GPT # GPT partitioning
+
+# Flattened Device Tree
+device fdt
+options FDT
+options FDT_DTB_STATIC
+
+# Misc pseudo devices
+device bpf # Required for DHCP
+device faith # IPv6-to-IPv4 relaying (translation)
+device firmware # firmware(9) required for USB wlan
+device gif # IPv6 and IPv4 tunneling
+device loop # Network loopback
+device md # Memory/malloc disk
+device pty # BSD-style compatibility pseudo ttys
+device random # Entropy device
+device tun # Packet tunnel.
+device ether # Required for all ethernet devices
+device vlan # 802.1Q VLAN support
+device wlan # 802.11 WLAN support
+
+# cam support for umass and ahci
+device scbus
+device pass
+device da
+
+# Serial ports
+device uart
+
+# Networking
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+
+# USB
+options USB_HOST_ALIGN=32 # Align DMA to cacheline
+#options USB_DEBUG # Compile in USB debug support
+device usb # Basic usb support
+device ehci # USB host controller
+device umass # Mass storage
+device uhid # Human-interface devices
+device rum # Ralink Technology RT2501USB wireless NICs
+device uath # Atheros AR5523 wireless NICs
+device ural # Ralink Technology RT2500USB wireless NICs
+device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device urtw # Realtek RTL8187B/L USB
+device upgt # Conexant/Intersil PrismGT SoftMAC USB
+device u3g # USB-based 3G modems (Option, Huawei, Sierra)
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+# Sound
+device sound
+device snd_uaudio
+
+#crypto
+device cesa # Marvell security engine
+device crypto
+device cryptodev
+
+# IPSec
+device enc
+options IPSEC
+options IPSEC_NAT_T
+options TCP_SIGNATURE # include support for RFC 2385
+
+# IPFW
+options IPFIREWALL
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+options IPFIREWALL_VERBOSE
+options IPFIREWALL_VERBOSE_LIMIT=100
+options IPFIREWALL_NAT
+options LIBALIAS
+options DUMMYNET
+options IPDIVERT
+
+#PF
+device pf
+device pflog
+device pfsync
+
+# ALTQ, required for PF
+options ALTQ # Basic ALTQ support
+options ALTQ_CBQ # Class Based Queueing
+options ALTQ_RED # Random Early Detection
+options ALTQ_RIO # RED In/Out
+options ALTQ_HFSC # Hierarchical Packet Scheduler
+options ALTQ_CDNR # Traffic conditioner
+options ALTQ_PRIQ # Priority Queueing
+options ALTQ_NOPCC # Required if the TSC is unusable
+#options ALTQ_DEBUG
+
+# Debugging
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+options KDB
+#options DIAGNOSTIC
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+
+# Enable these options for nfs root configured via BOOTP.
+options NFSCL # Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=mge0
+
+# If not using BOOTP, use something like one of these...
+#options ROOTDEVNAME=\"ufs:/dev/da0a\"
+options ROOTDEVNAME=\"ufs:/dev/da0s1a\"
+#options ROOTDEVNAME=\"ufs:/dev/da0p10\"
+#options ROOTDEVNAME=\"nfs:192.168.0.254/dreamplug\"
+
Property changes on: trunk/sys/arm/conf/DOCKSTAR
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/DREAMPLUG-1001
===================================================================
--- trunk/sys/arm/conf/DREAMPLUG-1001 (rev 0)
+++ trunk/sys/arm/conf/DREAMPLUG-1001 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,183 @@
+# Kernel config for GlobalScale Technologies DreamPlug version 1001.
+#
+# This is for units that are version 10, revision 01, with NOR SPI flash.
+# These units are identified with the number "1001" on the S/N label.
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/DREAMPLUG-1001 287082 2015-08-23 20:50:22Z ian $
+#
+#NO_UNIVERSE
+
+ident DREAMPLUG-1001
+
+include "../mv/kirkwood/std.db88f6xxx"
+
+makeoptions FDT_DTS_FILE=dreamplug-1001.dts
+
+options SOC_MV_KIRKWOOD
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SOFTUPDATES
+options TMPFS # Efficient memory filesystem
+options CD9660 # ISO 9660 filesystem
+options FFS # Berkeley Fast Filesystem
+options MSDOSFS # MS DOS File System (FAT, FAT32)
+options NULLFS # NULL filesystem
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_ELI # Disk encryption.
+options GEOM_LABEL # Providers labelization.
+options GEOM_PART_GPT # GPT partitioning
+
+# Flattened Device Tree
+device fdt
+options FDT
+options FDT_DTB_STATIC
+
+# Misc pseudo devices
+device bpf # Required for DHCP
+device faith # IPv6-to-IPv4 relaying (translation)
+device firmware # firmware(9) required for USB wlan
+device gif # IPv6 and IPv4 tunneling
+device loop # Network loopback
+device md # Memory/malloc disk
+device pty # BSD-style compatibility pseudo ttys
+device random # Entropy device
+device tun # Packet tunnel.
+device ether # Required for all ethernet devices
+device vlan # 802.1Q VLAN support
+device wlan # 802.11 WLAN support
+
+# cam support for umass and ahci
+device scbus
+device pass
+device da
+device cd
+
+# Serial ports
+device uart
+
+# Networking
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+
+# USB
+options USB_HOST_ALIGN=32 # Align DMA to cacheline
+#options USB_DEBUG # Compile in USB debug support
+device usb # Basic usb support
+device ehci # USB host controller
+device umass # Mass storage
+device uhid # Human-interface devices
+device rum # Ralink Technology RT2501USB wireless NICs
+device uath # Atheros AR5523 wireless NICs
+device ural # Ralink Technology RT2500USB wireless NICs
+device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device urtw # Realtek RTL8187B/L USB
+device upgt # Conexant/Intersil PrismGT SoftMAC USB
+device u3g # USB-based 3G modems (Option, Huawei, Sierra)
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+# SATA
+device mvs
+device ahci
+
+# Sound
+device sound
+device snd_uaudio
+
+#crypto
+device cesa # Marvell security engine
+device crypto
+device cryptodev
+
+# IPSec
+device enc
+options IPSEC
+options IPSEC_NAT_T
+options TCP_SIGNATURE # include support for RFC 2385
+
+# IPFW
+options IPFIREWALL
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+options IPFIREWALL_VERBOSE
+options IPFIREWALL_VERBOSE_LIMIT=100
+options IPFIREWALL_NAT
+options LIBALIAS
+options DUMMYNET
+options IPDIVERT
+
+#PF
+device pf
+device pflog
+device pfsync
+
+# ALTQ, required for PF
+options ALTQ # Basic ALTQ support
+options ALTQ_CBQ # Class Based Queueing
+options ALTQ_RED # Random Early Detection
+options ALTQ_RIO # RED In/Out
+options ALTQ_HFSC # Hierarchical Packet Scheduler
+options ALTQ_CDNR # Traffic conditioner
+options ALTQ_PRIQ # Priority Queueing
+options ALTQ_NOPCC # Required if the TSC is unusable
+#options ALTQ_DEBUG
+
+# Debugging
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+options KDB
+#options DIAGNOSTIC
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+
+# Enable these options for nfs root configured via BOOTP.
+options NFSCL # Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=mge0
+
+# If not using BOOTP, use something like one of these...
+#options ROOTDEVNAME=\"ufs:/dev/da1a\"
+options ROOTDEVNAME=\"ufs:/dev/da1s1a\"
+#options ROOTDEVNAME=\"ufs:/dev/da1p10\"
+#options ROOTDEVNAME=\"nfs:192.168.0.254/dreamplug\"
+
+# To use this configuration with the (rare) model 1001N (nand flash),
+# create a kernel config file that looks like this:
+#
+# include DREAMPLUG-1001
+# nomakeoptions FDT_DTS_FILE
+# makeoptions FDT_DTS_FILE=dreamplug-1001N.dts
+# device nand
+
Property changes on: trunk/sys/arm/conf/DREAMPLUG-1001
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EA3250
===================================================================
--- trunk/sys/arm/conf/EA3250 (rev 0)
+++ trunk/sys/arm/conf/EA3250 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,99 @@
+#
+# Custom kernel for EA3250 boards.
+#
+# $FreeBSD: stable/10/sys/arm/conf/EA3250 271428 2014-09-11 15:36:36Z ian $
+#
+
+ident EA3250
+include "../lpc/std.lpc"
+hints "EA3250.hints"
+
+makeoptions MODULES_OVERRIDE=""
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions WERROR="-Werror"
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options NFSCL # Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options MSDOSFS
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=lpe0
+
+#options ROOTDEVNAME=\"ufs:/dev/da0a\"
+
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+#options DEADLKRES # Enable the deadlock resolver
+#options DIAGNOSTIC
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options KDB
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+
+# Pseudo devices
+device loop
+device md
+device pty
+device random
+
+# Serial ports
+device uart
+
+# Networking
+device ether
+device mii
+device bpf
+device lpe
+
+# USB
+options USB_DEBUG
+device usb
+device ohci
+device umass
+device scbus
+device pass
+device da
+
+device mmc
+device mmcsd
+device lpcmmc
+
+device gpio
+device gpioled
+device lpcgpio
+
+device spibus
+device lpcspi
+device ssd1289
+
+device lpcfb
+
+# DMAC
+device dmac
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=ea3250.dts
Property changes on: trunk/sys/arm/conf/EA3250
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EA3250.hints
===================================================================
--- trunk/sys/arm/conf/EA3250.hints (rev 0)
+++ trunk/sys/arm/conf/EA3250.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,4 @@
+# $FreeBSD: stable/10/sys/arm/conf/EA3250.hints 239279 2012-08-15 05:55:16Z gonzo $
+
+hint.ssd1289.0.at="spibus0"
+hint.ssd1289.0.cs=26
Property changes on: trunk/sys/arm/conf/EA3250.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EB9200
===================================================================
--- trunk/sys/arm/conf/EB9200 (rev 0)
+++ trunk/sys/arm/conf/EB9200 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,114 @@
+# EB9200 - Custom kernel for the Embest ATEB9200 AT91RM9200 evaluation board.
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/EB9200 278676 2015-02-13 15:27:46Z ian $
+
+#NO_UNIVERSE
+
+ident EB9200
+
+include "../at91/std.eb9200"
+# The AT91 platform doesn't use /boot/loader, so we have to statically wire
+# hints.
+hints "EB9200.hints"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+#options ROOTDEVNAME=\"ufs:/dev/da0s1a\"
+options NFSCL # New Network Filesystem Client
+options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP_NFSROOT
+options BOOTP
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+#options NO_SYSCTL_DESCR
+# Disable the inlining of mutex, rwlock and sx locks. These eat up a lot
+# of space.
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options SX_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+device random
+device loop
+device ether
+device uart
+device ate
+device miibus
+#device lxtphy
+
+device at91_cfata
+device ata
+
+# Debugging for use in -current
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+
+device md
+device at91_twi # TWI: Two Wire Interface
+device at91_spi # SPI:
+device spibus
+# MMC/SD
+device at91_mci
+device mmc
+device mmcsd
+# iic
+device iic
+device iicbus
+device icee
+
+device bpf
+# USB support
+options USB_DEBUG # enable debug msgs
+device ohci # OHCI localbus->USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB device (gadget) support
+#device at91_dci # Atmel's usb device
+#device usfs # emulate a flash
+#device cdce # emulate an ethernet
+#device usb_template # Control of the gadget
Property changes on: trunk/sys/arm/conf/EB9200
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EB9200.hints
===================================================================
--- trunk/sys/arm/conf/EB9200.hints (rev 0)
+++ trunk/sys/arm/conf/EB9200.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,6 @@
+# $FreeBSD: stable/10/sys/arm/conf/EB9200.hints 239324 2012-08-16 05:03:59Z imp $
+
+# should likely list CF here since its address isn't fixed.
+# but since it is at an external chip select, do we use that or the address
+# to configure it as its bus address? Need to fix arbitrary bus mapping
+# before I can list it here.
Property changes on: trunk/sys/arm/conf/EB9200.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EFIKA_MX
===================================================================
--- trunk/sys/arm/conf/EFIKA_MX (rev 0)
+++ trunk/sys/arm/conf/EFIKA_MX 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,193 @@
+#
+# Kernel configuration for Efika MX Smarttop/Smartbook boards
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/EFIKA_MX 287082 2015-08-23 20:50:22Z ian $
+
+ident EFIKA_MX
+
+include "../freescale/imx/std.imx51"
+
+makeoptions WITHOUT_MODULES="ahc"
+
+options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+#options MD_ROOT # MD is a potential root device
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_LABEL # Provides labelization
+#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
+#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
+#options COMPAT_FREEBSD7 # Compatible with FreeBSD7
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options INCLUDE_CONFIG_FILE # Include this file in kernel
+options VFP # Enable floating point hardware support
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options GDB # Support remote GDB
+options DEADLKRES # Enable the deadlock resolver
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
+
+options ROOTDEVNAME=\"ufs:ada0s2a\"
+
+
+# kernel/memory size reduction
+#options MUTEX_NOINLINE
+#options NO_FFS_SNAPSHOT
+#options NO_SWAPPING
+#options NO_SYSCTL_DESCR
+#options RWLOCK_NOINLINE
+
+# Debugging support. Always need this:
+options KDB # Enable kernel debugger support.
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic.
+# For full debugger support use this instead:
+options DDB # Support DDB.
+#options GDB # Support remote GDB.
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device bpf # Berkeley packet filter
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+#device vlan # 802.1Q VLAN support
+#device tun # Packet tunnel.
+#device md # Memory "disks"
+#device gif # IPv6 and IPv4 tunneling
+#device faith # IPv6-to-IPv4 relaying (translation)
+#device firmware # firmware assist module
+
+# Serial (COM) ports
+device uart # Multi-uart driver
+options ALT_BREAK_TO_DEBUGGER
+
+device ata
+device atapci # Only for helper functions
+device imxata
+options ATA_STATIC_ID # Static device numbering
+
+device gpio
+device gpioled
+
+device fsliic
+device iic
+device iicbus
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+#options USB_DEBUG # enable debug msgs
+device ehci # OHCI USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+device u3g
+
+# USB Ethernet, requires miibus
+device miibus
+device aue # ADMtek USB Ethernet
+device axe # ASIX Electronics USB Ethernet
+device cdce # Generic USB over Ethernet
+device cue # CATC USB Ethernet
+device kue # Kawasaki LSI USB Ethernet
+device rue # RealTek RTL8150 USB Ethernet
+device udav # Davicom DM9601E USB
+
+# USB Wireless
+device rum # Ralink Technology RT2501USB wireless NICs
+
+# Watchdog timer.
+# WARNING: can't be disabled!!!
+device imxwdt # Watchdog
+
+# Wireless NIC cards
+device wlan # 802.11 support
+device wlan_wep # 802.11 WEP support
+device wlan_ccmp # 802.11 CCMP support
+device wlan_tkip # 802.11 TKIP support
+device wlan_amrr # AMRR transmit rate control algorithm
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=efikamx.dts
+
+# NOTE: serial console will be disabled if syscons enabled
+# Uncomment following lines for framebuffer/syscons support
+device sc
+device kbdmux
+options SC_DFLT_FONT # compile font in
+makeoptions SC_DFLT_FONT=cp437
+device ukbd # Allow keyboard like HIDs to control console
+device ums
Property changes on: trunk/sys/arm/conf/EFIKA_MX
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EP80219
===================================================================
--- trunk/sys/arm/conf/EP80219 (rev 0)
+++ trunk/sys/arm/conf/EP80219 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,111 @@
+# EP80219 -- Custom kernel configuration file for FreeBSD/arm on the EP80219
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/EP80219 278677 2015-02-13 15:32:31Z ian $
+
+ident EP80219
+
+options PHYSADDR=0xa0000000
+options KERNPHYSADDR=0xa0200000
+options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+
+#options ARM32_NEW_VM_LAYOUT
+include "../xscale/i80321/std.ep80219"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions CONF_CFLAGS=-mcpu=xscale
+options HZ=100
+#options DEVICE_POLLING
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options NFSCL # New Network Filesystem Client
+options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_PART_GPT # GUID Partition Tables.
+options GEOM_LABEL # Providers labelization.
+
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=fxp0
+options BOOTP_COMPAT
+#options PREEMPTION
+device loop
+device ether
+#device saarm
+device miibus
+device fxp
+device uart
+device pci
+
+device ata
+options ATA_STATIC_ID # Static device numbering
+
+device scbus # SCSI bus (required for ATA/SCSI)
+device cd # CD
+device da # Direct Access (disks)
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# SCSI Controllers
+
+device iopwdog # I80321 Watchdog
+device dma # I80321 DMA Controller
+
+# Debugging for use in -current
+options KDB
+options DDB # Enable the kernel debugger
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+options XSCALE_CACHE_READ_WRITE_ALLOCATE
+device md
+device random # Entropy device
+
+# Floppy drives
+
+options INCLUDE_CONFIG_FILE # Include this file in kernel
+#options VERBOSE_SYSINIT
+options VERBOSE_INIT_ARM
+
+device bpf
+#options ROOTDEVNAME=\"ufs:ada0s1a\"
Property changes on: trunk/sys/arm/conf/EP80219
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/ETHERNUT5
===================================================================
--- trunk/sys/arm/conf/ETHERNUT5 (rev 0)
+++ trunk/sys/arm/conf/ETHERNUT5 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,163 @@
+# Kernel configuration for Ethernut 5 boards
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/ETHERNUT5 266383 2014-05-18 00:21:14Z ian $
+
+#NO_UNIVERSE
+
+ident ETHERNUT5
+
+include "../at91/std.ethernut5"
+
+# To statically compile in device wiring instead of /boot/device.hints
+hints "ETHERNUT5.hints"
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+
+options SCHED_4BSD # 4BSD scheduler
+#options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+#options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+#options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+#options MD_ROOT # MD is a potential root device
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+#options PSEUDOFS # Pseudo-filesystem framework
+#options GEOM_PART_GPT # GUID Partition Tables.
+#options GEOM_LABEL # Provides labelization
+#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
+#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
+#options COMPAT_FREEBSD7 # Compatible with FreeBSD7
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+#options STACK # stack(9) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed.
+#options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4)
+#options AUDIT # Security event auditing
+#options CAPABILITY_MODE # Capsicum capability mode
+#options CAPABILITIES # Capsicum capabilities
+#options MAC # TrustedBSD MAC Framework
+#options INCLUDE_CONFIG_FILE # Include this file in kernel
+
+# required for netbooting
+options BOOTP
+options BOOTP_COMPAT
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=ate0
+
+# alternatively, boot from a MMC/SD memory card
+#options ROOTDEVNAME=\"ufs:/dev/mmcsd0a\"
+
+# kernel/memory size reduction
+options MUTEX_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+options NO_SYSCTL_DESCR
+options RWLOCK_NOINLINE
+
+# Debugging support. Always need this:
+#options KDB # Enable kernel debugger support.
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic.
+# For full debugger support use this instead:
+#options DDB # Support DDB.
+#options GDB # Support remote GDB.
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device bpf # Berkeley packet filter
+
+# Ethernet
+device mii # Minimal MII support
+device ate # Atmel AT91 Ethernet driver
+
+# I2C
+device at91_twi # Atmel AT91 Two-wire Interface
+device iic # I2C generic I/O device driver
+device iicbus # I2C bus system
+device pcf8563 # NXP PCF8563 clock/calendar
+
+# MMC/SD
+device at91_mci # Atmel AT91 Multimedia Card Interface
+options AT91_MCI_HAS_4WIRE
+device mmc # MMC/SD bus
+device mmcsd # MMC/SD memory card
+
+# DataFlash
+device at91_spi # Atmel AT91 Serial Peripheral Interface
+device spibus # SPI bus
+device at45d # Atmel AT45D
+device geom_map # GEOM partition mapping
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+#device vlan # 802.1Q VLAN support
+#device tun # Packet tunnel.
+#device md # Memory "disks"
+#device gif # IPv6 and IPv4 tunneling
+#device faith # IPv6-to-IPv4 relaying (translation)
+#device firmware # firmware assist module
+
+# SCSI peripherals
+#device scbus # SCSI bus (required for ATA/SCSI)
+#device ch # SCSI media changers
+#device da # Direct Access (disks)
+#device sa # Sequential Access (tape etc)
+#device cd # CD
+#device pass # Passthrough device (direct ATA/SCSI access)
+#device ses # Enclosure Services (SES and SAF-TE)
+#device ctl # CAM Target Layer
+
+# Serial (COM) ports
+device uart # Multi-uart driver
+options ALT_BREAK_TO_DEBUGGER
+
+# USB support
+#options USB_DEBUG # enable debug msgs
+device ohci # OHCI USB interface
+device usb # USB Bus (required)
+#device umass # Disks/Mass storage - Requires scbus and da
+
+# watchdog
+device at91_wdt # Atmel AT91 Watchdog Timer
Property changes on: trunk/sys/arm/conf/ETHERNUT5
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/ETHERNUT5.hints
===================================================================
--- trunk/sys/arm/conf/ETHERNUT5.hints (rev 0)
+++ trunk/sys/arm/conf/ETHERNUT5.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,51 @@
+# $FreeBSD: stable/10/sys/arm/conf/ETHERNUT5.hints 238786 2012-07-26 05:37:36Z imp $
+
+# Atmel AT45DB21D
+hint.at45d.0.at="spibus0"
+hint.at45d.0.cs=0
+# user 132 kbytes
+hint.map.0.at="flash/spi0"
+hint.map.0.start=0x00000000
+hint.map.0.end=0x00020fff
+hint.map.0.name="user"
+hint.map.0.readonly=1
+# setup 132 kbytes
+hint.map.1.at="flash/spi0"
+hint.map.1.start=0x00021000
+hint.map.1.end=0x00041fff
+hint.map.1.name="setup"
+hint.map.1.readonly=1
+# uboot 528 kbytes
+hint.map.2.at="flash/spi0"
+hint.map.2.start=0x00042000
+hint.map.2.end=0x000c5fff
+hint.map.2.name="uboot"
+hint.map.2.readonly=1
+# kernel 2640 kbytes
+hint.map.3.at="flash/spi0"
+hint.map.3.start=0x000c6000
+hint.map.3.end=0x00359fff
+hint.map.3.name="kernel"
+#hint.map.3.readonly=1
+# nutos 528 kbytes
+hint.map.4.at="flash/spi0"
+hint.map.4.start=0x0035a000
+hint.map.4.end=0x003ddfff
+hint.map.4.name="nutos"
+hint.map.4.readonly=1
+# env 132 kbytes
+hint.map.5.at="flash/spi0"
+hint.map.5.start=0x003de000
+hint.map.5.end=0x003fefff
+hint.map.5.name="env"
+hint.map.5.readonly=1
+# env 132 kbytes
+hint.map.6.at="flash/spi0"
+hint.map.6.start=0x003ff000
+hint.map.6.end=0x0041ffff
+hint.map.6.name="nutoscfg"
+hint.map.6.readonly=1
+
+# NXP PCF8563 clock/calendar
+hint.pcf8563_rtc.0.at="iicbus0"
+hint.pcf8563_rtc.0.addr=0xa2
Property changes on: trunk/sys/arm/conf/ETHERNUT5.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EXYNOS5.common
===================================================================
--- trunk/sys/arm/conf/EXYNOS5.common (rev 0)
+++ trunk/sys/arm/conf/EXYNOS5.common 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,131 @@
+#
+# Kernel configuration for Samsung Exynos 5 SoC.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/EXYNOS5.common 287082 2015-08-23 20:50:22Z ian $
+
+makeoptions WERROR="-Werror"
+
+options HZ=100
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
+
+options ROOTDEVNAME=\"ufs:/dev/da0\"
+
+# MMC/SD/SDIO Card slot support
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+device sdhci # generic sdhci
+
+# Pseudo devices
+
+device loop
+device random
+device pty
+device md
+device gpio
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+#device musb
+device ehci
+#device ohci
+
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass
+
+# SATA
+#device ata
+#device atadisk
+#device mvs
+
+# Serial ports
+device uart
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+# Ethernet
+device ether
+device mii
+device smsc
+device smscphy
+
+# USB ethernet support, requires miibus
+device miibus
+device axe # ASIX Electronics USB Ethernet
+device bpf # Berkeley packet filter
Property changes on: trunk/sys/arm/conf/EXYNOS5.common
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EXYNOS5250
===================================================================
--- trunk/sys/arm/conf/EXYNOS5250 (rev 0)
+++ trunk/sys/arm/conf/EXYNOS5250 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,25 @@
+# Kernel configuration for Samsung Exynos 5250 boards.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/EXYNOS5250 278599 2015-02-11 22:35:32Z ian $
+
+ident EXYNOS5250
+include "EXYNOS5.common"
+include "../samsung/exynos/std.exynos5250"
+
+#FDT
+options FDT
Property changes on: trunk/sys/arm/conf/EXYNOS5250
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EXYNOS5250.common
===================================================================
--- trunk/sys/arm/conf/EXYNOS5250.common (rev 0)
+++ trunk/sys/arm/conf/EXYNOS5250.common 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,132 @@
+# Kernel configuration for Samsung Exynos 5250 boards.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/EXYNOS5250.common 266341 2014-05-17 19:37:04Z ian $
+
+include "../samsung/exynos/std.exynos5"
+
+makeoptions MODULES_OVERRIDE=""
+makeoptions WITHOUT_MODULES="ahc"
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions WERROR="-Werror"
+
+options HZ=100
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options KBD_INSTALL_CDEV
+options PREEMPTION
+options FREEBSD_BOOT_LOADER
+options VFP # vfp/neon
+
+# Debugging
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS support
+options NFSCL # Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+
+# Uncomment this for NFS root
+#options NFS_ROOT # NFS usable as /, requires NFSCL
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
+
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+device sdhci # generic sdhci
+
+options ROOTDEVNAME=\"ufs:/dev/da0\"
+
+#options SMP
+
+# Pseudo devices
+
+device loop
+device random
+device pty
+device md
+device gpio
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+#device musb
+device ehci
+#device ohci
+
+device umass
+device scbus # SCSI bus (required for SCSI)
+device da # Direct Access (disks)
+device pass
+
+# SATA
+#device ata
+#device atadisk
+#device mvs
+
+# Serial ports
+device uart
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+# Ethernet
+device ether
+device mii
+device smsc
+device smscphy
+
+# USB ethernet support, requires miibus
+device miibus
+device axe # ASIX Electronics USB Ethernet
+device bpf # Berkeley packet filter
Property changes on: trunk/sys/arm/conf/EXYNOS5250.common
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/EXYNOS5420
===================================================================
--- trunk/sys/arm/conf/EXYNOS5420 (rev 0)
+++ trunk/sys/arm/conf/EXYNOS5420 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,25 @@
+# Kernel configuration for Samsung Exynos 5420 boards.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/EXYNOS5420 278599 2015-02-11 22:35:32Z ian $
+
+ident EXYNOS5420
+include "EXYNOS5.common"
+include "../samsung/exynos/std.exynos5420"
+
+#FDT
+options FDT
Property changes on: trunk/sys/arm/conf/EXYNOS5420
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/GUMSTIX
===================================================================
--- trunk/sys/arm/conf/GUMSTIX (rev 0)
+++ trunk/sys/arm/conf/GUMSTIX 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,94 @@
+# GUMSTIX -- Custom configuration for the Gumstix Basix and Connex boards from
+# gumstix.com
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/GUMSTIX 285365 2015-07-10 22:10:00Z gjb $
+
+ident GUMSTIX
+cpu CPU_XSCALE_PXA2X0
+
+# This probably wants to move somewhere else. Maybe we can create a basic
+# PXA2X0 config, then make a GUMSTIX config that includes the basic one,
+# adds the smc and smcphy devices and pulls in this hints file.
+hints "GUMSTIX.hints"
+
+options PHYSADDR=0xa0000000
+options KERNPHYSADDR=0xa0200000
+options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+
+include "../xscale/pxa/std.pxa"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options HZ=100
+#options DEVICE_POLLING
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_LABEL # Provides labelization
+options TMPFS # Efficient memory filesystem
+options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_WIRED_TO=smc0
+options BOOTP_COMPAT
+options BOOTP_NFSV3
+options BOOTP_BLOCKSIZE=4096
+options PREEMPTION
+device loop
+device ether
+device mii
+device mii_bitbang
+device smc
+device smcphy
+device uart
+device uart_ns8250
+
+# Debugging for use in -current
+options KDB
+options DDB # Enable the kernel debugger
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+device md
+device random # Entropy device
Property changes on: trunk/sys/arm/conf/GUMSTIX
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/GUMSTIX-QEMU
===================================================================
--- trunk/sys/arm/conf/GUMSTIX-QEMU (rev 0)
+++ trunk/sys/arm/conf/GUMSTIX-QEMU 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,25 @@
+# GUMSTIX-QEMU -- Custom configuration for the QEMU emulated Gumstix target
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/GUMSTIX-QEMU 240572 2012-09-16 19:48:48Z jmg $
+
+include GUMSTIX
+
+ident GUMSTIX-QEMU
+
+options QEMU_WORKAROUNDS
+nooptions ARM_CACHE_LOCK_ENABLE # QEMU does not implement this
Property changes on: trunk/sys/arm/conf/GUMSTIX-QEMU
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/GUMSTIX.hints
===================================================================
--- trunk/sys/arm/conf/GUMSTIX.hints (rev 0)
+++ trunk/sys/arm/conf/GUMSTIX.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,19 @@
+# $FreeBSD: stable/10/sys/arm/conf/GUMSTIX.hints 179595 2008-06-06 05:08:09Z benno $
+
+# Make sure we don't trample important bits in the UART registers.
+hint.uart.0.ier_mask="0xe0"
+hint.uart.0.ier_rxbits="0x1d"
+hint.uart.1.ier_mask="0xe0"
+hint.uart.1.ier_rxbits="0x1d"
+hint.uart.2.ier_mask="0xe0"
+hint.uart.2.ier_rxbits="0x1d"
+
+# SMSC LAN91C111s found on the netCF, netMMC and netDUO boards.
+hint.smc.0.at="smi0"
+hint.smc.0.mem="0x04000300"
+hint.smc.0.size="0x10"
+hint.smc.0.irq="100"
+hint.smc.1.at="smi0"
+hint.smc.1.mem="0x08000300"
+hint.smc.1.size="0x10"
+hint.smc.1.irq="91"
Property changes on: trunk/sys/arm/conf/GUMSTIX.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/HL200
===================================================================
--- trunk/sys/arm/conf/HL200 (rev 0)
+++ trunk/sys/arm/conf/HL200 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,144 @@
+# Kernel configuration for the AT91RM9200 based Hot-e configuration file
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/HL200 278676 2015-02-13 15:27:46Z ian $
+
+#NO_UNIVERSE
+
+ident HL200
+
+include "../at91/std.hl200"
+
+#To statically compile in device wiring instead of /boot/device.hints
+hints "KB920X.hints"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+#options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP_NFSROOT
+options BOOTP
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=ate0
+options BOOTP_COMPAT
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+#options NO_SYSCTL_DESCR
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+device random
+device loop
+device ether
+device uart
+device ate
+device mii
+device lxtphy
+
+# Debugging for use in -current
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+
+device md
+device at91_twi # TWI: Two Wire Interface
+device at91_spi # SPI:
+device spibus
+# MMC/SD
+device at91_mci
+device mmc
+device mmcsd
+# iic
+device iic
+device iicbus
+device icee
+
+device bpf
+# USB support
+options USB_DEBUG # enable debug msgs
+device ohci # OHCI localbus->USB interface
+device usb # USB Bus (required)
+#device udbp # USB Double Bulk Pipe devices
+device uhid # "Human Interface Devices"
+device ulpt # Printer
+device umass # Disks/Mass storage - Requires scbus and da
+device urio # Diamond Rio 500 MP3 player
+# USB Serial devices
+device uark # Technologies ARK3116 based serial adapters
+device ubsa # Belkin F5U103 and compatible serial adapters
+#device ubser # not yet converted.
+device uftdi # For FTDI usb serial adapters
+device uipaq # Some WinCE based devices
+device uplcom # Prolific PL-2303 serial adapters
+device uslcom # SI Labs CP2101/CP2102 serial adapters
+device uvisor # Visor and Palm devices
+device uvscom # USB serial support for DDI pocket's PHS
+# USB Ethernet, requires miibus
+device miibus
+device aue # ADMtek USB Ethernet
+device axe # ASIX Electronics USB Ethernet
+device cdce # Generic USB over Ethernet
+device cue # CATC USB Ethernet
+device kue # Kawasaki LSI USB Ethernet
+device rue # RealTek RTL8150 USB Ethernet
+device udav # Davicom DM9601E USB
+# USB Wireless
+device rum # Ralink Technology RT2501USB wireless NICs
+device uath # Atheros AR5523 wireless NICs
+device ural # Ralink Technology RT2500USB wireless NICs
+device zyd # ZyDAS zd1211/zd1211b wireless NICs
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+# Wireless NIC cards
+device wlan # 802.11 support
+device wlan_wep # 802.11 WEP support
+device wlan_ccmp # 802.11 CCMP support
+device wlan_tkip # 802.11 TKIP support
+device wlan_amrr # AMRR transmit rate control algorithm
Property changes on: trunk/sys/arm/conf/HL200
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/HL201
===================================================================
--- trunk/sys/arm/conf/HL201 (rev 0)
+++ trunk/sys/arm/conf/HL201 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,137 @@
+# Kernel configuration for the AT91SAM9G20 based Hot-e configuration file
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/HL201 283368 2015-05-24 14:25:03Z ian $
+
+#NO_UNIVERSE
+
+ident HL201
+
+include "../at91/std.hl201"
+
+#To statically compile in device wiring instead of /boot/device.hints
+hints "HL201.hints"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+options NANDFS # NAND file system
+options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+#options BOOTP_NFSROOT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ate0
+#options BOOTP_COMPAT
+
+options ALT_BREAK_TO_DEBUGGER
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+device random
+device loop
+device ether
+device uart
+device ate
+device mii
+#device lxtphy
+
+# Debugging for use in -current
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+device md
+device bpf
+
+# USB support
+device ohci # OHCI localbus->USB interface
+device usb # USB Bus (required)
+#device udbp # USB Double Bulk Pipe devices
+device uhid # "Human Interface Devices"
+#device ulpt # Printer
+device umass # Disks/Mass storage - Requires scbus and da
+
+# USB Ethernet, requires miibus
+device miibus
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+device udav # Davicom DM9601E USB
+# USB Wireless
+#device rum # Ralink Technology RT2501USB wireless NICs
+#device uath # Atheros AR5523 wireless NICs
+#device ural # Ralink Technology RT2500USB wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+# Wireless NIC cards
+#device wlan # 802.11 support
+#device wlan_wep # 802.11 WEP support
+#device wlan_ccmp # 802.11 CCMP support
+#device wlan_tkip # 802.11 TKIP support
+#device wlan_amrr # AMRR transmit rate control algorithm
+options ROOTDEVNAME=\"ufs:da0s1a\"
+
+# NAND Flash - my board as 128MB Samsung part, YMMV.
+device nand # NAND interface on CS3
+
+# Coming soon, but not yet
+#options FDT
+#options FDT_DTB_STATIC
+#makeoptions FDT_DTS_FILE=hl201.dts
+
+options EARLY_PRINTF
+options SOCDEV_PA=0xfc000000
+options SOCDEV_VA=0xdc000000
Property changes on: trunk/sys/arm/conf/HL201
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/HL201.hints
===================================================================
--- trunk/sys/arm/conf/HL201.hints (rev 0)
+++ trunk/sys/arm/conf/HL201.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,48 @@
+# $FreeBSD: stable/10/sys/arm/conf/HL201.hints 239323 2012-08-16 04:53:30Z imp $
+
+# Atmel AT45DB21D
+hint.at45d.0.at="spibus0"
+hint.at45d.0.cs=0
+# Area 0: 00000000 to 000041FF (RO) Bootstrap
+# Area 1: 00004200 to 000083FF Environment
+# Area 2: 00008400 to 00041FFF (RO) U-Boot
+# Area 3: 00042000 to 00251FFF Kernel
+# Area 4: 00252000 to 0083FFFF FS
+# bootstrap
+hint.map.0.at="flash/spi0"
+hint.map.0.start=0x00000000
+hint.map.0.end=0x000041ff
+hint.map.0.name="bootstrap"
+hint.map.0.readonly=1
+# uboot environment
+hint.map.1.at="flash/spi0"
+hint.map.1.start=0x00004200
+hint.map.1.end=0x00083ff
+hint.map.1.name="uboot-env"
+#hint.map.1.readonly=1
+# uboot
+hint.map.2.at="flash/spi0"
+hint.map.2.start=0x00008400
+hint.map.2.end=0x00041fff
+hint.map.2.name="uboot"
+hint.map.2.readonly=1
+# kernel
+hint.map.3.at="flash/spi0"
+hint.map.3.start=0x00042000
+hint.map.3.end=0x00251fff
+hint.map.3.name="fs"
+#hint.map.3.readonly=1
+# fs
+hint.map.4.at="flash/spi0"
+hint.map.4.start=0x00252000
+hint.map.4.end=0x0083ffff
+hint.map.4.name="fs"
+#hint.map.4.readonly=1
+
+# EEPROM at24c512 - 512kbit 65,536x8 memory
+hint.icee.0.at="iicbus0"
+hint.icee.0.addr=0xa0
+hint.icee.0.type=16
+hint.icee.0.size=65536
+hint.icee.0.rd_sz=128
+hint.icee.0.wr_sz=128
Property changes on: trunk/sys/arm/conf/HL201.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/IMX53
===================================================================
--- trunk/sys/arm/conf/IMX53 (rev 0)
+++ trunk/sys/arm/conf/IMX53 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,174 @@
+#
+# Kernel configuration for i.MX53 boards
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/IMX53 283368 2015-05-24 14:25:03Z ian $
+
+ident IMX53
+
+include "../freescale/imx/std.imx53"
+
+options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_LABEL # Provides labelization
+#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
+#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
+#options COMPAT_FREEBSD7 # Compatible with FreeBSD7
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options INCLUDE_CONFIG_FILE # Include this file in kernel
+options VFP # Enable floating point hardware support
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options GDB # Support remote GDB
+options DEADLKRES # Enable the deadlock resolver
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+
+# kernel/memory size reduction
+#options MUTEX_NOINLINE
+#options NO_FFS_SNAPSHOT
+#options NO_SWAPPING
+#options NO_SYSCTL_DESCR
+#options RWLOCK_NOINLINE
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device bpf # Berkeley packet filter
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+#device vlan # 802.1Q VLAN support
+#device tun # Packet tunnel.
+device md # Memory "disks"
+#device gif # IPv6 and IPv4 tunneling
+#device faith # IPv6-to-IPv4 relaying (translation)
+#device firmware # firmware assist module
+
+# Ethernet
+device ffec # Freescale Fast Ethernet Controller
+device miibus # Standard mii bus
+
+# Serial (COM) ports
+device uart # Multi-uart driver
+options ALT_BREAK_TO_DEBUGGER
+
+device ata
+device atapci # Only for helper functions
+device imxata
+options ATA_STATIC_ID # Static device numbering
+
+device gpio
+device gpioled
+
+device fsliic
+device iic
+device iicbus
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+options USB_DEBUG # enable debug msgs
+device ehci # OHCI USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+#device ukbd # Allow keyboard like HIDs to control console
+device ums
+
+# USB Ethernet, requires miibus
+#device miibus
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+#device udav # Davicom DM9601E USB
+
+# USB Wireless
+#device rum # Ralink Technology RT2501USB wireless NICs
+
+# Watchdog timer.
+# WARNING: can't be disabled!!!
+device imxwdt # Watchdog
+
+# Wireless NIC cards
+device wlan # 802.11 support
+device wlan_wep # 802.11 WEP support
+device wlan_ccmp # 802.11 CCMP support
+device wlan_tkip # 802.11 TKIP support
+device wlan_amrr # AMRR transmit rate control algorithm
+
+# MMC
+#device sdhci # SD controller
+#device mmc # SD/MMC protocol
+#device mmcsd # SDCard disk device
+
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+
+# NOTE: serial console will be disabled if syscons enabled
+# Uncomment following lines for framebuffer/syscons support
+#device sc
+#device vt
+#device kbdmux
+#options SC_DFLT_FONT # compile font in
+#makeoptions SC_DFLT_FONT=cp437
Property changes on: trunk/sys/arm/conf/IMX53
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/IMX53-QSB
===================================================================
--- trunk/sys/arm/conf/IMX53-QSB (rev 0)
+++ trunk/sys/arm/conf/IMX53-QSB 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,38 @@
+# Kernel configuration for Freescale i.MX53 Quick Start Board
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/IMX53-QSB 283368 2015-05-24 14:25:03Z ian $
+
+#NO_UNIVERSE
+
+include "IMX53"
+ident IMX53-QSB
+
+options HZ=250 # 4ms scheduling quantum
+
+# required for netbooting
+#options BOOTP
+#options BOOTP_COMPAT
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
+
+#options ROOTDEVNAME=\"ufs:ada0s2a\"
+
+# Flattened Device Tree
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=imx53-qsb.dts
Property changes on: trunk/sys/arm/conf/IMX53-QSB
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/IMX6
===================================================================
--- trunk/sys/arm/conf/IMX6 (rev 0)
+++ trunk/sys/arm/conf/IMX6 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,164 @@
+#
+# Kernel configuration for Freescale i.MX6 systems.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/IMX6 287079 2015-08-23 20:16:13Z ian $
+
+ident IMX6
+include "../freescale/imx/std.imx6"
+
+options HZ=500 # Scheduling quantum is 2 milliseconds.
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_LABEL # Provides labelization
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options INCLUDE_CONFIG_FILE # Include this file in kernel
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options GDB # Support remote GDB.
+# Other debugging options...
+options ALT_BREAK_TO_DEBUGGER # Use <CR><tilde><ctrl-b> to enter debugger.
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ffec0
+
+# U-Boot stuff lives on slice 1, FreeBSD on slice 2.
+options ROOTDEVNAME=\"ufs:mmcsd0s2a\"
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device vlan # 802.1Q VLAN support
+device tun # Packet tunnel.
+device md # Memory "disks"
+#device faith # IPv6-to-IPv4 relaying (translation)
+#device gif # IPv6 and IPv4 tunneling
+#device firmware # firmware assist module
+device ether # Ethernet support
+device miibus # Required for ethernet
+device bpf # Berkeley packet filter (required for DHCP)
+
+# General-purpose input/output
+device gpio
+
+# Serial (COM) ports
+device uart # Multi-uart driver
+
+# SDCard
+device sdhci # SD controller
+device mmc # SD/MMC protocol
+device mmcsd # SDCard disk device
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+#options USB_DEBUG # enable debug msgs
+device ehci # OHCI USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+device u3g # USB modems
+#device ukbd # Allow keyboard like HIDs to control console
+#device ums # USB mouse
+
+# USB Ethernet, requires miibus
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+#device udav # Davicom DM9601E USB
+
+# USB Wireless
+#device rum # Ralink Technology RT2501USB wireless NICs
+
+# Wireless NIC cards
+#device wlan # 802.11 support
+#device wlan_wep # 802.11 WEP support
+#device wlan_ccmp # 802.11 CCMP support
+#device wlan_tkip # 802.11 TKIP support
+#device wlan_amrr # AMRR transmit rate control algorithm
+
+# NOTE: serial console will be disabled if syscons enabled
+# Uncomment following lines for framebuffer/syscons support
+# Wandboard has no video console support yet.
+#device sc
+#device kbdmux
+#options SC_DFLT_FONT # compile font in
+#makeoptions SC_DFLT_FONT=cp437
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+makeoptions MODULES_EXTRA=dtb/imx6
+
+# SoC-specific devices
+device ffec # Freescale Fast Ethernet Controller
+device fsliic # Freescale i2c/iic
+device iic # iic protocol
+device iicbus # iic bus
+device imxwdt # Watchdog. WARNING: can't be disabled!!!
+
Property changes on: trunk/sys/arm/conf/IMX6
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/IQ31244
===================================================================
--- trunk/sys/arm/conf/IQ31244 (rev 0)
+++ trunk/sys/arm/conf/IQ31244 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,110 @@
+# IQ31244 -- Custom kernel configuration file for FreeBSD/arm on the IQ31244
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/IQ31244 278677 2015-02-13 15:32:31Z ian $
+
+ident IQ31244
+
+options PHYSADDR=0xa0000000
+options KERNPHYSADDR=0xa0200000
+options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+options FLASHADDR=0xf0000000
+options LOADERRAMADDR=0x00000000
+
+include "../xscale/i80321/std.iq31244"
+makeoptions MODULES_OVERRIDE=""
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions CONF_CFLAGS=-mcpu=xscale
+options HZ=100
+#options DEVICE_POLLING
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options NFSCL # New Network Filesystem Client
+options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=em0
+options BOOTP_COMPAT
+#options PREEMPTION
+device loop
+device ether
+#device saarm
+device miibus
+device rl
+device em
+device uart
+device pci
+
+device ata
+options ATA_STATIC_ID # Static device numbering
+
+device scbus # SCSI bus (required for ATA/SCSI)
+device cd # CD
+device da # Direct Access (disks)
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# SCSI Controllers
+
+device iopwdog # I80321 Watchdog
+device dma # I80321 DMA Controller
+device aau # I80321 Application Accelerator Unit
+device "iq31244_7seg" # IQ31244 7 seg
+#options AHC_REG_PRETTY_PRINT # Print register bitfields in debug
+ # output. Adds ~128k to driver.
+#options AHD_REG_PRETTY_PRINT # Print register bitfields in debug
+ # output. Adds ~215k to driver.
+
+# Debugging for use in -current
+options KDB
+options DDB # Enable the kernel debugger
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+options XSCALE_CACHE_READ_WRITE_ALLOCATE
+device md
+device random # Entropy device
+
+# Floppy drives
+
Property changes on: trunk/sys/arm/conf/IQ31244
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/KB920X
===================================================================
--- trunk/sys/arm/conf/KB920X (rev 0)
+++ trunk/sys/arm/conf/KB920X 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,154 @@
+# KB920X -- Custom kernel configuration for the KB9202 (no letter, A and B)
+# AT91RM9200 evaluation boards from kwikbyte.com.
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/KB920X 278676 2015-02-13 15:27:46Z ian $
+
+#NO_UNIVERSE
+
+ident KB920X
+
+include "../at91/std.kb920x"
+# The AT91 platform doesn't use /boot/loader, so we have to statically wire
+# hints.
+hints "KB920X.hints"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+#options NFS_ROOT # NFS usable as /, requires NFSCL
+#options BOOTP_NFSROOT
+#options BOOTP
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+#options NO_SYSCTL_DESCR
+# Disable the inlining of mutex, rwlock and sx locks. These eat up a lot
+# of space.
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options SX_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+device random
+device loop
+device ether
+device uart
+device ate
+device mii
+device lxtphy
+
+# Debugging for use in -current
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+
+device md
+device at91_twi # TWI: Two Wire Interface
+device at91_spi # SPI:
+device spibus
+# MMC/SD
+device at91_mci
+device mmc
+device mmcsd
+# iic
+device iic
+device iicbus
+device icee
+
+device bpf
+# USB support
+options USB_DEBUG # enable debug msgs
+device ohci # OHCI localbus->USB interface
+device usb # USB Bus (required)
+#device udbp # USB Double Bulk Pipe devices
+device uhid # "Human Interface Devices"
+device ulpt # Printer
+device umass # Disks/Mass storage - Requires scbus and da
+device urio # Diamond Rio 500 MP3 player
+# USB Serial devices
+device uark # Technologies ARK3116 based serial adapters
+device ubsa # Belkin F5U103 and compatible serial adapters
+device uftdi # For FTDI usb serial adapters
+device uipaq # Some WinCE based devices
+device uplcom # Prolific PL-2303 serial adapters
+device uslcom # SI Labs CP2101/CP2102 serial adapters
+device uvisor # Visor and Palm devices
+device uvscom # USB serial support for DDI pocket's PHS
+# USB Ethernet, requires miibus
+device miibus
+device aue # ADMtek USB Ethernet
+device axe # ASIX Electronics USB Ethernet
+device cdce # Generic USB over Ethernet
+device cue # CATC USB Ethernet
+device kue # Kawasaki LSI USB Ethernet
+device rue # RealTek RTL8150 USB Ethernet
+device udav # Davicom DM9601E USB
+# USB Wireless
+device rum # Ralink Technology RT2501USB wireless NICs
+device uath # Atheros AR5523 wireless NICs
+device ural # Ralink Technology RT2500USB wireless NICs
+device zyd # ZyDAS zd1211/zd1211b wireless NICs
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+# Wireless NIC cards
+device wlan # 802.11 support
+device wlan_wep # 802.11 WEP support
+device wlan_ccmp # 802.11 CCMP support
+device wlan_tkip # 802.11 TKIP support
+device wlan_amrr # AMRR transmit rate control algorithm
+
+# USB device (gadget) support
+device at91_dci # Atmel's usb device
+device usfs # emulate a flash
+device cdce # emulate an ethernet
+device usb_template # Control of the gadget
+
+options IEEE80211_SUPPORT_MESH
+
+options AH_SUPPORT_AR5416
Property changes on: trunk/sys/arm/conf/KB920X
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/KB920X.hints
===================================================================
--- trunk/sys/arm/conf/KB920X.hints (rev 0)
+++ trunk/sys/arm/conf/KB920X.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,16 @@
+# $FreeBSD: stable/10/sys/arm/conf/KB920X.hints 167858 2007-03-23 23:47:59Z imp $
+#
+# Kwikbyte KB9202A description (will also work for 9202 and might work with
+# a boot loader tweak on the KB9202B). For the moment, all we list is the
+# eeprom. The temperature sensor isn't listed.
+#
+
+# boot eeprom at 'default' address of 0xa0
+hint.icee.0.at="iicbus0"
+hint.icee.0.addr=0xa0
+hint.icee.0.type=16
+hint.icee.0.size=16384
+hint.icee.0.rd_sz=256
+hint.icee.0.wr_sz=16
+
+# XXX add temperature sensor
Property changes on: trunk/sys/arm/conf/KB920X.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/LN2410SBC
===================================================================
--- trunk/sys/arm/conf/LN2410SBC (rev 0)
+++ trunk/sys/arm/conf/LN2410SBC 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,89 @@
+# LN2410SBC -- Custom kernel configuration for the LN2410SBC
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/LN2410SBC 278726 2015-02-13 22:08:19Z ian $
+
+ident LN2410SBC
+
+include "../samsung/s3c2xx0/std.ln2410sbc"
+#To statically compile in device wiring instead of /boot/device.hints
+#hints "GENERIC.hints" # Default places to look for devices.
+makeoptions MODULES_OVERRIDE=""
+
+device board_ln2410sbc
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options HZ=100
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+options ROOTDEVNAME=\"ufs:da0s1\"
+
+#options BOOTP
+#options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info
+#options NFSCL # New Network Filesystem Client
+#options NFS_ROOT # NFS usable as root device
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options SX_NOINLINE
+
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+device random
+
+device loop
+device ether
+device bpf
+
+device uart
+
+# Debugging for use in -current
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+
+device md
+
+options USB_DEBUG # enable debug msgs
+device usb
+device ohci
+device umass
+device scbus # SCSI bus (required for da)
+device da # Direct Access (disks)
+
Property changes on: trunk/sys/arm/conf/LN2410SBC
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/Makefile
===================================================================
--- trunk/sys/arm/conf/Makefile (rev 0)
+++ trunk/sys/arm/conf/Makefile 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,6 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/arm/conf/Makefile 243581 2012-11-27 01:17:50Z marcel $
+
+TARGET=arm
+
+.include "${.CURDIR}/../../conf/makeLINT.mk"
Property changes on: trunk/sys/arm/conf/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/conf/NOTES
===================================================================
--- trunk/sys/arm/conf/NOTES (rev 0)
+++ trunk/sys/arm/conf/NOTES 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,88 @@
+# $FreeBSD: stable/10/sys/arm/conf/NOTES 309447 2016-12-02 22:53:33Z jhb $
+
+machine arm
+
+cpu CPU_ARM9
+cpu CPU_ARM9E
+cpu CPU_FA526
+cpu CPU_XSCALE_80219
+cpu CPU_XSCALE_80321
+cpu CPU_XSCALE_81342
+cpu CPU_XSCALE_IXP425
+cpu CPU_XSCALE_IXP435
+cpu CPU_XSCALE_PXA2X0
+
+files "../at91/files.at91"
+files "../cavium/cns11xx/files.econa"
+files "../mv/files.mv"
+files "../mv/discovery/files.db78xxx"
+files "../mv/kirkwood/files.kirkwood"
+files "../mv/orion/files.db88f5xxx"
+files "../mv/orion/files.ts7800"
+files "../samsung/s3c2xx0/files.s3c2xx0"
+files "../xscale/i80321/files.ep80219"
+files "../xscale/i80321/files.i80219"
+files "../xscale/i80321/files.i80321"
+files "../xscale/i80321/files.iq31244"
+files "../xscale/i8134x/files.crb"
+files "../xscale/i8134x/files.i81342"
+files "../xscale/ixp425/files.avila"
+files "../xscale/ixp425/files.ixp425"
+files "../xscale/pxa/files.pxa"
+
+options PHYSADDR=0x00000000
+options KERNPHYSADDR=0x00000000
+options KERNVIRTADDR=0xc0000000
+
+makeoptions LDFLAGS="-zmuldefs"
+makeoptions KERNPHYSADDR=0x00000000
+makeoptions KERNVIRTADDR=0xc0000000
+
+options FDT
+
+options SOC_MV_DISCOVERY
+options SOC_MV_KIRKWOOD
+options SOC_MV_ORION
+
+device pci
+
+device at91_board_bwct
+device at91_board_ethernut5
+device at91_board_hl200
+device at91_board_hl201
+device at91_board_kb920x
+device at91_board_qila9g20
+device at91_board_sam9260ek
+device at91_board_sam9g20ek
+device at91_board_sam9x25ek
+device at91_board_tsc4370
+device at91rm9200
+device nand
+device board_ln2410sbc
+
+nooptions SMP
+nooptions MAXCPU
+
+nooptions COMPAT_FREEBSD4
+
+nodevice fdc
+nodevice sym
+nodevice ukbd
+
+nodevice sc
+nodevice blank_saver
+nodevice daemon_saver
+nodevice dragon_saver
+nodevice fade_saver
+nodevice fire_saver
+nodevice green_saver
+nodevice logo_saver
+nodevice rain_saver
+nodevice snake_saver
+nodevice star_saver
+nodevice warp_saver
+
+nodevice cxgbe
+nodevice cxgbev
+nodevice snd_cmi
+nodevice tnt4882
Property changes on: trunk/sys/arm/conf/NOTES
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/NSLU
===================================================================
--- trunk/sys/arm/conf/NSLU (rev 0)
+++ trunk/sys/arm/conf/NSLU 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,119 @@
+# NSLU - kernel configuration file for FreeBSD/arm on Linksys NSLU2
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/NSLU 278676 2015-02-13 15:27:46Z ian $
+
+#NO_UNIVERSE
+
+ident NSLU
+
+# XXX What is defined in std.avila does not exactly match the following:
+#options PHYSADDR=0x10000000
+#options KERNPHYSADDR=0x10200000
+#options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+#options FLASHADDR=0x50000000
+#options LOADERRAMADDR=0x00000000
+
+include "../xscale/ixp425/std.ixp425"
+# NB: memory mapping is defined in std.avila (see also comment above)
+include "../xscale/ixp425/std.avila"
+options XSCALE_CACHE_READ_WRITE_ALLOCATE
+#To statically compile in device wiring instead of /boot/device.hints
+hints "NSLU.hints" # Default places to look for devices.
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions CONF_CFLAGS=-mcpu=xscale
+options HZ=100
+options DEVICE_POLLING
+
+# Debugging for use in -current
+options KDB
+#options GDB
+options DDB # Enable the kernel debugger
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+options SCHED_ULE # ULE scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options NFSCL # New Network Filesystem Client
+options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE # Mutex inlines are space hogs
+options RWLOCK_NOINLINE # rwlock inlines are space hogs
+options SX_NOINLINE # sx inliens are space hogs
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=npe0
+options BOOTP_COMPAT
+
+device pci
+device uart
+
+# I2C Bus
+device iicbus
+device iicbb
+device iic
+
+device ixpiic # I2C bus glue
+device ixpwdog # watchdog timer
+
+device npe # Network Processing Engine
+device npe_fw
+device firmware
+device qmgr # Q Manager (required by npe)
+device mii # Minimal mii routines
+device rlphy # NSLU2 uses Realtek PHY attached to npe
+device ether
+device bpf
+
+device loop
+
+device md
+device random # Entropy device
+
+device usb
+options USB_DEBUG
+device ohci
+device ehci
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
Property changes on: trunk/sys/arm/conf/NSLU
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/NSLU.hints
===================================================================
--- trunk/sys/arm/conf/NSLU.hints (rev 0)
+++ trunk/sys/arm/conf/NSLU.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,38 @@
+# $FreeBSD: stable/10/sys/arm/conf/NSLU.hints 191858 2009-05-06 20:24:17Z cognet $
+
+#
+# Device wiring for the Linksys NSLU2
+#
+
+# DBGU is unit 0
+hint.uart.0.at="ixp0"
+hint.uart.0.addr=0xc8000000
+hint.uart.0.irq=15
+hint.uart.0.flags=0x10
+# USART0 is unit 1
+hint.uart.1.at="ixp0"
+hint.uart.1.addr=0xc8001000
+hint.uart.1.irq=13
+
+# NPE Hardware Queue Manager
+hint.ixpqmgr.0.at="ixp0"
+
+# NPE wired NICs, requires ixpqmgr
+hint.npe.0.at="ixp0"
+hint.npe.0.mac="B"
+hint.npe.0.mii="B"
+hint.npe.0.phy=1
+# The second MAC isn't used on the NSLU, but it needs to be configured or
+# we timeout on dhcp packets
+hint.npe.1.at="ixp0"
+#hint.npe.1.mac="B"
+#hint.npe.1.mii="A"
+#hint.npe.1.phy=0
+
+#not yet
+# RTC
+#hint.xrtc.0.at="iicbus0"
+#hint.xrtc.0.addr=0xde
+# Slug LED
+# Slug button
+# Slug Buzzer
Property changes on: trunk/sys/arm/conf/NSLU.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/PANDABOARD
===================================================================
--- trunk/sys/arm/conf/PANDABOARD (rev 0)
+++ trunk/sys/arm/conf/PANDABOARD 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,154 @@
+#
+# PANDABOARD -- Custom configuration for the PandaBoard ARM development
+# platform, check out www.pandaboard.org
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/PANDABOARD 287082 2015-08-23 20:50:22Z ian $
+
+ident PANDABOARD
+
+# This probably wants to move somewhere else. Maybe we can create a basic
+# OMAP4340 config, then make a PANDABOARD config that includes the basic one,
+# adds the start addresses and custom devices plus pulls in this hints file.
+
+hints "PANDABOARD.hints"
+
+include "../ti/omap4/pandaboard/std.pandaboard"
+
+options HZ=100
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_LABEL # Provides labelization
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
+
+# MMC/SD/SDIO Card slot support
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+device sdhci # mmc/sd host controller
+
+# I2C support
+device iicbus
+device iic
+device ti_i2c
+
+# Console and misc
+device uart
+device uart_ns8250
+device pty
+device snp
+device md
+device random # Entropy device
+device pl310 # PL310 L2 cache controller
+
+# GPIO
+device gpio
+
+# The following enables MFS as root, this seems similar to an initramfs or initrd
+# as used in Linux.
+#options MD_ROOT
+#options MD_ROOT_SIZE=7560
+
+
+
+# USB support
+device usb
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+device ohci
+device ehci
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+
+# Ethernet
+device loop
+device ether
+device mii
+device smc
+device smcphy
+device bpf
+
+# USB Ethernet support, requires miibus
+device miibus
+#device axe # ASIX Electronics USB Ethernet
+device smsc # SMSC LAN95xx USB Ethernet
+
+
+# OMAP-specific devices
+device ti_sdma
+device twl
+device twl_vreg
+device twl_clks
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=pandaboard.dts
Property changes on: trunk/sys/arm/conf/PANDABOARD
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/PANDABOARD.hints
===================================================================
--- trunk/sys/arm/conf/PANDABOARD.hints (rev 0)
+++ trunk/sys/arm/conf/PANDABOARD.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,61 @@
+# $FreeBSD: stable/10/sys/arm/conf/PANDABOARD.hints 239281 2012-08-15 06:31:32Z gonzo $
+
+# USB ECHI
+
+#
+# TI OMAP Power Management and System Companion Device sitting on the I2C bus
+# hint.tps65950.0.at="iicbus0"
+# hint.tps65950.0.addr=0xd0
+
+
+#
+# Defines the GPIO pin used to detect the Write Protect stat of the MMC/SD card.
+#hint.omap_mmc.0.wp_gpio="23"
+
+
+#
+# If 'phy_reset" is set, then the accompaning PHY is reset using one of the
+# GPIO pins. If the reset GPIO pin is not -1 then the pin will be toggled when
+# the USB driver is loaded.
+hint.ehci.0.phy_reset="0"
+
+#
+# Sets the PHY mode for the individual ports, the following values are allowed
+# - EHCI_HCD_OMAP3_MODE_UNKNOWN 0
+# - EHCI_HCD_OMAP3_MODE_PHY 1
+# - EHCI_HCD_OMAP3_MODE_TLL 2
+hint.ehci.0.phy_mode_0="1"
+hint.ehci.0.phy_mode_1="0"
+hint.ehci.0.phy_mode_2="0"
+
+#
+# If specified the value indicates a pin that is toggled as a heart-beat. The
+# heart beat pusle is triggered every 500ms using the system tick timer.
+hint.omap_clk.0.heartbeat_gpio="150"
+
+
+#
+# Padconf (pinmux) settings - typically this would be set by the boot-loader
+# but can be overridden here. These hints are applied to the H/W when the
+# SCM module is initialised.
+#
+# The format is:
+# hint.omap_scm.0.padconf.<padname>=<muxmode:options>
+#
+# Where the options can be one of the following:
+# output, input, input_pullup, input_pulldown
+#
+
+# Setup the pin settings for the HS USB Host (PHY mode)
+hint.omap4.0.padconf.ag19="usbb1_ulpiphy_stp:output"
+hint.omap4.0.padconf.ae18="usbb1_ulpiphy_clk:input_pulldown"
+hint.omap4.0.padconf.af19="usbb1_ulpiphy_dir:input_pulldown"
+hint.omap4.0.padconf.ae19="usbb1_ulpiphy_nxt:input_pulldown"
+hint.omap4.0.padconf.af18="usbb1_ulpiphy_dat0:input_pulldown"
+hint.omap4.0.padconf.ag18="usbb1_ulpiphy_dat1:input_pulldown"
+hint.omap4.0.padconf.ae17="usbb1_ulpiphy_dat2:input_pulldown"
+hint.omap4.0.padconf.af17="usbb1_ulpiphy_dat3:input_pulldown"
+hint.omap4.0.padconf.ah17="usbb1_ulpiphy_dat4:input_pulldown"
+hint.omap4.0.padconf.ae16="usbb1_ulpiphy_dat5:input_pulldown"
+hint.omap4.0.padconf.af16="usbb1_ulpiphy_dat6:input_pulldown"
+hint.omap4.0.padconf.ag16="usbb1_ulpiphy_dat7:input_pulldown"
Property changes on: trunk/sys/arm/conf/PANDABOARD.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/QILA9G20
===================================================================
--- trunk/sys/arm/conf/QILA9G20 (rev 0)
+++ trunk/sys/arm/conf/QILA9G20 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,155 @@
+# Kernel configuration for Calao Syatems QIL-A9G20 development card
+# http://www.calao-systems.com
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/QILA9G20 278676 2015-02-13 15:27:46Z ian $
+
+#NO_UNIVERSE
+
+ident QILA9G20
+
+include "../at91/std.qila9g20"
+
+#To statically compile in device wiring instead of /boot/device.hints
+hints "QILA9G20.hints"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+#options NFS_ROOT # NFS usable as /, requires NFSCL
+#options BOOTP_NFSROOT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ate0
+#options BOOTP_COMPAT
+
+options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
+
+options ALT_BREAK_TO_DEBUGGER
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+#options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging for use in -current
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+device random
+device loop
+device bpf
+device ether
+device md
+
+device uart # Serial Ports
+
+# Ethernet
+device ate # Ethernet Driver
+device mii
+option AT91_ATE_USE_RMII
+
+device at91_twi # TWI: Two Wire Interface (EEPROM)
+device at91_wdt # WDT: Watchdog timer
+
+# NOTE: SPI DataFlash and mci/mmc/mmcsd have hardware
+# confilict on this card. Use one or the other.
+# see board_sam9g20ek.c
+
+# SPI: Data Flash
+#device at91_spi # SPI:
+#device spibus
+#device at45d # at45db642 and maybe others
+
+# MMC/SD
+device at91_mci
+device mmc
+device mmcsd
+option AT91_MCI_HAS_4WIRE
+
+# iic
+device iic
+device iicbus
+device icee
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+device ohci # OHCI localbus->USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+#device ulpt # Printer
+#device udbp # USB Double Bulk Pipe devices
+
+# USB Ethernet, requires miibus
+device miibus
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+device udav # Davicom DM9601E USB
+
+# USB Wireless
+#device rum # Ralink Technology RT2501USB wireless NICs
+#device uath # Atheros AR5523 wireless NICs
+#device ural # Ralink Technology RT2500USB wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
+
+# Wireless NIC cards
+#device wlan # 802.11 support
+#device wlan_wep # 802.11 WEP support
+#device wlan_ccmp # 802.11 CCMP support
+#device wlan_tkip # 802.11 TKIP support
+#device wlan_amrr # AMRR transmit rate control algorithm
+
Property changes on: trunk/sys/arm/conf/QILA9G20
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/QILA9G20.hints
===================================================================
--- trunk/sys/arm/conf/QILA9G20.hints (rev 0)
+++ trunk/sys/arm/conf/QILA9G20.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+# $FreeBSD: stable/10/sys/arm/conf/QILA9G20.hints 236988 2012-06-13 04:40:29Z imp $
+# Kernel configuration hits for Calao Syatems QIL-A9G20 development card
+# http://www.calao-systems.com
+
+# STMicroelctrtronics M41T94 Real-Time Clock
+# on SPI0 NPCS0
+
+# STMicroelctrtronics M95640 8k x 8 EEPROM
+# on SPI0 NPCS1
Property changes on: trunk/sys/arm/conf/QILA9G20.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/QUARTZ
===================================================================
--- trunk/sys/arm/conf/QUARTZ (rev 0)
+++ trunk/sys/arm/conf/QUARTZ 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,28 @@
+# Kernel configuration for Device Solutions Quartz Module.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/QUARTZ 266383 2014-05-18 00:21:14Z ian $
+
+#NO_UNIVERSE
+
+include "VYBRID"
+ident QUARTZ
+
+#FDT
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=vybrid-quartz.dts
Property changes on: trunk/sys/arm/conf/QUARTZ
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/RADXA
===================================================================
--- trunk/sys/arm/conf/RADXA (rev 0)
+++ trunk/sys/arm/conf/RADXA 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,124 @@
+# RADXA -- Custom configuration for the RADXA ARM development
+# platform, check out http://www.radxa.com
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/RADXA 271428 2014-09-11 15:36:36Z ian $
+
+ident RADXA
+
+include "../rockchip/std.rk30xx"
+
+makeoptions MODULES_OVERRIDE=""
+makeoptions WITHOUT_MODULES="ahc"
+
+options HZ=100
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options PREEMPTION
+options FREEBSD_BOOT_LOADER
+options VFP # vfp/neon
+
+# Debugging
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS support
+#options NFSCL
+#options NFSSERVER # Network Filesystem Server
+#options NFSCLIENT # Network Filesystem Client
+
+# MMC/SD/SDIO card slot support
+#device mmc # mmc/sd bus
+#device mmcsd # mmc/sd flash cards
+
+# Boot device is 2nd slice on MMC/SD card
+options ROOTDEVNAME=\"ufs:/dev/da0s2\"
+
+# Console and misc
+device uart
+device uart_ns8250
+device pty
+device snp
+device md
+device random # Entropy device
+
+# I2C support
+#device iicbus
+#device iic
+
+# GPIO
+device gpio
+
+device scbus # SCSI bus (required for SCSI)
+device da # Direct Access (disks)
+device pass
+
+# USB support
+options USB_HOST_ALIGN=32 # Align usb buffers to cache line size.
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+device dwcotg # DWC OTG controller
+
+device umass
+
+# Ethernet
+device loop
+device ether
+device mii
+device smscphy
+device bpf
+
+# USB ethernet support, requires miibus
+device miibus
+device udav
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=rk3188-radxa.dts
+
+options SMP # Enable multiple cores
Property changes on: trunk/sys/arm/conf/RADXA
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/RPI-B
===================================================================
--- trunk/sys/arm/conf/RPI-B (rev 0)
+++ trunk/sys/arm/conf/RPI-B 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,142 @@
+#
+# RPI-B -- Custom configuration for the Raspberry Pi
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/RPI-B 287082 2015-08-23 20:50:22Z ian $
+
+ident RPI-B
+
+include "../broadcom/bcm2835/std.rpi"
+
+options HZ=100
+options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options GEOM_LABEL # Provides labelization
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
+
+#options ROOTDEVNAME=\"ufs:mmcsd0s2\"
+
+device bpf
+device loop
+device ether
+device uart
+device pty
+device snp
+device pl011
+
+# Comment following lines for boot console on serial port
+device vt
+device kbdmux
+device ukbd
+
+device sdhci
+device mmc
+device mmcsd
+
+device gpio
+device gpioled
+
+# I2C
+device iic
+device iicbus
+device bcm2835_bsc
+
+options KDB
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+
+device md
+device random # Entropy device
+
+# USB support
+device usb
+options USB_DEBUG
+device dwcotg # DWC OTG controller
+
+# USB storage support
+device scbus
+device da
+device umass
+
+# USB ethernet support
+device smcphy
+device mii
+device smsc
+
+# SPI
+device spibus
+device bcm2835_spi
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+# Note: DTB is normally loaded and modified by RPi boot loader, then
+# handed to kernel via U-Boot and ubldr.
+#options FDT_DTB_STATIC
+#makeoptions FDT_DTS_FILE=rpi.dts
+makeoptions MODULES_EXTRA=dtb/rpi
Property changes on: trunk/sys/arm/conf/RPI-B
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/SAM9260EK
===================================================================
--- trunk/sys/arm/conf/SAM9260EK (rev 0)
+++ trunk/sys/arm/conf/SAM9260EK 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,185 @@
+# Kernel configuration for Atmel SAM9260-EK eval board
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/SAM9260EK 283368 2015-05-24 14:25:03Z ian $
+
+#NO_UNIVERSE
+
+ident SAM9260EK
+
+include "../at91/std.sam9260ek"
+
+# To statically compile in device wiring instead of /boot/device.hints
+hints "SAM9260EK.hints"
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions MODULES_OVERRIDE=""
+
+options SCHED_4BSD # 4BSD scheduler
+#options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+#options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+#options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+#options MD_ROOT # MD is a potential root device
+options NANDFS # NAND file system
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+#options PSEUDOFS # Pseudo-filesystem framework
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+#options GEOM_PART_GPT # GUID Partition Tables.
+#options GEOM_LABEL # Provides labelization
+#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
+#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
+#options COMPAT_FREEBSD7 # Compatible with FreeBSD7
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+#options STACK # stack(9) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed.
+#options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4)
+#options AUDIT # Security event auditing
+#options CAPABILITY_MODE # Capsicum capability mode
+#options CAPABILITIES # Capsicum capabilities
+#options MAC # TrustedBSD MAC Framework
+#options INCLUDE_CONFIG_FILE # Include this file in kernel
+
+# required for netbooting
+#options BOOTP
+#options BOOTP_COMPAT
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ate0
+
+# alternatively, boot from a MMC/SD memory card
+#options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
+
+# Alternatively, boot from a USB card.
+options ROOTDEVNAME=\"ufs:/dev/da0s1a\"
+
+# kernel/memory size reduction
+options MUTEX_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+options NO_SYSCTL_DESCR
+options RWLOCK_NOINLINE
+
+# Debugging support. Always need this:
+#options KDB # Enable kernel debugger support.
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic.
+# For full debugger support use this instead:
+#options DDB # Support DDB.
+#options GDB # Support remote GDB.
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device bpf # Berkeley packet filter
+
+# Ethernet
+device mii # Minimal MII support
+device ate # Atmel AT91 Ethernet driver
+
+# I2C
+device at91_twi # Atmel AT91 Two-wire Interface
+device iic # I2C generic I/O device driver
+device iicbus # I2C bus system
+device icee # I2C eeprom
+
+# MMC/SD
+# See comment for DataFlash below
+device at91_mci # Atmel AT91 Multimedia Card Interface
+options AT91_MCI_HAS_4WIRE # 4 wires
+options AT91_MCI_SLOT_B # Wired to slot B
+device mmc # MMC/SD bus
+device mmcsd # MMC/SD memory card
+
+# DataFlash
+# The DataFlash and MMC card are wired together, so we must pick one or the
+# other. This is due to pin mux, and also due to the design of the
+# SAM9260EK board. SLOT A wouldn't have this issue.
+#device at91_spi # Atmel AT91 Serial Peripheral Interface
+#device spibus # SPI bus
+#device at45d # Atmel AT45D
+#device geom_map # GEOM partition mapping
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+#device vlan # 802.1Q VLAN support
+#device tun # Packet tunnel.
+#device md # Memory "disks"
+#device gif # IPv6 and IPv4 tunneling
+#device faith # IPv6-to-IPv4 relaying (translation)
+#device firmware # firmware assist module
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+#device ch # SCSI media changers
+device da # Direct Access (disks)
+#device sa # Sequential Access (tape etc)
+device cd # CD/DVD
+device pass # Passthrough device (direct ATA/SCSI access)
+device ses # Enclosure Services (SES and SAF-TE)
+#device ctl # CAM Target Layer
+
+# Serial (COM) ports
+device uart # Multi-uart driver
+options ALT_BREAK_TO_DEBUGGER
+
+# USB support
+#options USB_DEBUG # enable debug msgs
+device ohci # OHCI USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+
+# watchdog
+device at91_wdt # Atmel AT91 Watchdog Timer
+
+# NAND Flash - Reference design has Samsung 256MB but others possible
+device nand # NAND interface on CS3
+
+# Coming soon, but not yet
+#options FDT
+#options FDT_DTB_STATIC
+#makeoptions FDT_DTS_FILE=sam9260ek.dts
+
+options EARLY_PRINTF
+options SOCDEV_PA=0xfc000000
+options SOCDEV_VA=0xdc000000
Property changes on: trunk/sys/arm/conf/SAM9260EK
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/SAM9260EK.hints
===================================================================
--- trunk/sys/arm/conf/SAM9260EK.hints (rev 0)
+++ trunk/sys/arm/conf/SAM9260EK.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,48 @@
+# $FreeBSD: stable/10/sys/arm/conf/SAM9260EK.hints 238811 2012-07-26 16:34:21Z imp $
+
+# Atmel AT45DB21D
+hint.at45d.0.at="spibus0"
+hint.at45d.0.cs=1
+# Area 0: 00000000 to 000041FF (RO) Bootstrap
+# Area 1: 00004200 to 000083FF Environment
+# Area 2: 00008400 to 00041FFF (RO) U-Boot
+# Area 3: 00042000 to 00251FFF Kernel
+# Area 4: 00252000 to 0083FFFF FS
+# bootstrap
+hint.map.0.at="flash/spi0"
+hint.map.0.start=0x00000000
+hint.map.0.end=0x000041ff
+hint.map.0.name="bootstrap"
+hint.map.0.readonly=1
+# uboot environment
+hint.map.1.at="flash/spi0"
+hint.map.1.start=0x00004200
+hint.map.1.end=0x00083ff
+hint.map.1.name="uboot-env"
+#hint.map.1.readonly=1
+# uboot
+hint.map.2.at="flash/spi0"
+hint.map.2.start=0x00008400
+hint.map.2.end=0x00041fff
+hint.map.2.name="uboot"
+hint.map.2.readonly=1
+# kernel
+hint.map.3.at="flash/spi0"
+hint.map.3.start=0x00042000
+hint.map.3.end=0x00251fff
+hint.map.3.name="fs"
+#hint.map.3.readonly=1
+# fs
+hint.map.4.at="flash/spi0"
+hint.map.4.start=0x00252000
+hint.map.4.end=0x0083ffff
+hint.map.4.name="fs"
+#hint.map.4.readonly=1
+
+# EEPROM at24c512 - 512kbit 65,536x8 memory
+hint.icee.0.at="iicbus0"
+hint.icee.0.addr=0xa0
+hint.icee.0.type=16
+hint.icee.0.size=65536
+hint.icee.0.rd_sz=128
+hint.icee.0.wr_sz=128
Property changes on: trunk/sys/arm/conf/SAM9260EK.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/SAM9G20EK
===================================================================
--- trunk/sys/arm/conf/SAM9G20EK (rev 0)
+++ trunk/sys/arm/conf/SAM9G20EK 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,156 @@
+# Kernel configuration for Atmel AT91SAM9G20EK Rev B. development card
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/SAM9G20EK 278676 2015-02-13 15:27:46Z ian $
+
+ident SAM9G20EK
+
+include "../at91/std.sam9g20ek"
+
+#To statically compile in device wiring instead of /boot/device.hints
+hints "SAM9G20EK.hints"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+options NANDFS # NAND file system
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+#options NFS_ROOT # NFS usable as /, requires NFSCL
+#options BOOTP_NFSROOT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ate0
+#options BOOTP_COMPAT
+
+options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
+
+options ALT_BREAK_TO_DEBUGGER
+
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+#options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging for use in -current
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+device random
+device loop
+device bpf
+device ether
+device md
+
+device uart # Serial Ports
+
+# Ethernet
+device ate # Ethernet Driver
+device mii
+option AT91_ATE_USE_RMII
+
+device at91_twi # TWI: Two Wire Interface (EEPROM)
+device at91_wdt # WDT: Watchdog timer
+
+# NAND Flash - Reference design has Samsung 256MB but others possible
+device nand # NAND interface on CS3
+
+# NOTE: SPI DataFlash and mci/mmc/mmcsd have hardware
+# confilict on this card. Use one or the other.
+# see board_sam9g20ek.c
+
+# SPI: Data Flash
+#device at91_spi # SPI:
+#device spibus
+#device at45d # at45db642 and maybe others
+
+# MMC/SD
+device at91_mci
+device mmc
+device mmcsd
+option AT91_MCI_SLOT_B
+option AT91_MCI_HAS_4WIRE
+
+# iic
+device iic
+device iicbus
+device icee
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+device ohci # OHCI localbus->USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+#device ulpt # Printer
+#device udbp # USB Double Bulk Pipe devices
+
+# USB Ethernet, requires miibus
+#device miibus
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+#device udav # Davicom DM9601E USB
+
+# USB Wireless
+#device rum # Ralink Technology RT2501USB wireless NICs
+#device uath # Atheros AR5523 wireless NICs
+#device ural # Ralink Technology RT2500USB wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
+
+# Wireless NIC cards
+#device wlan # 802.11 support
+#device wlan_wep # 802.11 WEP support
+#device wlan_ccmp # 802.11 CCMP support
+#device wlan_tkip # 802.11 TKIP support
+#device wlan_amrr # AMRR transmit rate control algorithm
Property changes on: trunk/sys/arm/conf/SAM9G20EK
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/SAM9G20EK.hints
===================================================================
--- trunk/sys/arm/conf/SAM9G20EK.hints (rev 0)
+++ trunk/sys/arm/conf/SAM9G20EK.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+# $FreeBSD: stable/10/sys/arm/conf/SAM9G20EK.hints 236988 2012-06-13 04:40:29Z imp $
+#
+
+# EEPROM
+hint.icee.0.at="iicbus0"
+hint.icee.0.addr=0xa0
+hint.icee.0.type=16
+hint.icee.0.size=65536
+hint.icee.0.rd_sz=256
+hint.icee.0.wr_sz=256
Property changes on: trunk/sys/arm/conf/SAM9G20EK.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/SAM9X25EK
===================================================================
--- trunk/sys/arm/conf/SAM9X25EK (rev 0)
+++ trunk/sys/arm/conf/SAM9X25EK 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,156 @@
+# Kernel configuration for Atmel AT91SAM9G20EK Rev B. development card
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/SAM9X25EK 278676 2015-02-13 15:27:46Z ian $
+
+#NO_UNIVERSE
+
+ident SAM9X25EK
+
+include "../at91/std.sam9x25ek"
+
+#To statically compile in device wiring instead of /boot/device.hints
+hints "SAM9G20EK.hints"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+#options NFS_ROOT # NFS usable as /, requires NFSCL
+#options BOOTP_NFSROOT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ate0
+#options BOOTP_COMPAT
+
+options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
+
+options ALT_BREAK_TO_DEBUGGER
+
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+#options PSEUDOFS # Pseudo-filesystem framework
+#options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging for use in -current
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+device random
+device pty
+device loop
+device bpf
+device ether
+device md
+
+device uart # Serial Ports
+
+# Ethernet
+device ate # Ethernet Driver
+device mii
+option AT91_ATE_USE_RMII
+
+#device at91_twi # TWI: Two Wire Interface (EEPROM)
+device at91_wdt # WDT: Watchdog timer
+
+# NOTE: SPI DataFlash and mci/mmc/mmcsd have hardware
+# confilict on this card. Use one or the other.
+# see board_sam9g20ek.c
+
+# SPI: Data Flash
+#device at91_spi # SPI:
+#device spibus
+#device at45d # at45db642 and maybe others
+
+# MMC/SD
+device at91_mci
+device mmc
+device mmcsd
+#option AT91_MCI_SLOT_B
+option AT91_MCI_HAS_4WIRE
+
+# iic
+device iic
+device iicbus
+device icee
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+#device ohci # OHCI localbus->USB interface
+#device usb # USB Bus (required)
+#device umass # Disks/Mass storage - Requires scbus and da
+#device uhid # "Human Interface Devices"
+#device ulpt # Printer
+#device udbp # USB Double Bulk Pipe devices
+
+# USB Ethernet, requires miibus
+device miibus
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+#device udav # Davicom DM9601E USB
+
+# USB Wireless
+#device rum # Ralink Technology RT2501USB wireless NICs
+#device uath # Atheros AR5523 wireless NICs
+#device ural # Ralink Technology RT2500USB wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
+
+# Wireless NIC cards
+#device wlan # 802.11 support
+#device wlan_wep # 802.11 WEP support
+#device wlan_ccmp # 802.11 CCMP support
+#device wlan_tkip # 802.11 TKIP support
+#device wlan_amrr # AMRR transmit rate control algorithm
+
Property changes on: trunk/sys/arm/conf/SAM9X25EK
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/SAM9X25EK.hints
===================================================================
--- trunk/sys/arm/conf/SAM9X25EK.hints (rev 0)
+++ trunk/sys/arm/conf/SAM9X25EK.hints 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+# $FreeBSD: stable/10/sys/arm/conf/SAM9X25EK.hints 237742 2012-06-29 04:18:52Z imp $
+#
+
+# EEPROM
+hint.icee.0.at="iicbus0"
+hint.icee.0.addr=0xa0
+hint.icee.0.type=16
+hint.icee.0.size=65536
+hint.icee.0.rd_sz=256
+hint.icee.0.wr_sz=256
Property changes on: trunk/sys/arm/conf/SAM9X25EK.hints
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/SHEEVAPLUG
===================================================================
--- trunk/sys/arm/conf/SHEEVAPLUG (rev 0)
+++ trunk/sys/arm/conf/SHEEVAPLUG 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,85 @@
+#
+# Custom kernel for Marvell SheevaPlug devices.
+#
+# $FreeBSD: stable/10/sys/arm/conf/SHEEVAPLUG 283404 2015-05-24 15:21:47Z ian $
+#
+#NO_UNIVERSE
+
+ident SHEEVAPLUG
+include "../mv/kirkwood/std.db88f6xxx"
+
+options SOC_MV_KIRKWOOD
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions WERROR="-Werror"
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+options FFS # Berkeley Fast Filesystem
+options NANDFS # NAND Filesystem
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=mge0
+
+# Root fs on USB device
+#options ROOTDEVNAME=\"ufs:/dev/da0a\"
+
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+options KDB
+
+# Pseudo devices
+device random
+device loop
+
+# Serial ports
+device uart
+
+# Networking
+device ether
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+device bpf
+options HZ=1000
+options DEVICE_POLLING
+device vlan
+
+device cesa # Marvell security engine
+device crypto
+device cryptodev
+
+# USB
+options USB_DEBUG # enable debug msgs
+device usb
+device ehci
+device umass
+device scbus
+device pass
+device da
+
+# NAND
+device nand
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=sheevaplug.dts
Property changes on: trunk/sys/arm/conf/SHEEVAPLUG
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/SN9G45
===================================================================
--- trunk/sys/arm/conf/SN9G45 (rev 0)
+++ trunk/sys/arm/conf/SN9G45 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,133 @@
+# Kernel configuration for DesignA Electronics Snapper9G45 System on Module
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/SN9G45 278676 2015-02-13 15:27:46Z ian $
+
+#NO_UNIVERSE
+
+ident SN9G45
+
+include "../at91/std.sn9g45"
+
+#To statically compile in device wiring instead of /boot/device.hints
+#hints "SN9G45.hints"
+makeoptions MODULES_OVERRIDE=""
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options DDB
+options KDB
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+#options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+#options SOFTUPDATES # Enable FFS soft updates support
+#options UFS_ACL # Support for access control lists
+#options UFS_DIRHASH # Improve performance on big directories
+#options MD_ROOT # MD is a potential root device
+#options MD_ROOT_SIZE=4096 # 4MB ram disk
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+#options NFSLOCKD # Network Lock Manager
+#options NFS_ROOT # NFS usable as /, requires NFSCL
+#options BOOTP_NFSROOT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ate0
+#options BOOTP_COMPAT
+
+options ROOTDEVNAME=\"ufs:/dev/da0s1\"
+
+options ALT_BREAK_TO_DEBUGGER
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+#options PSEUDOFS # Pseudo-filesystem framework
+options SCSI_DELAY=1000 # Delay (in ms) before probing SCSI
+#options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging for use in -current
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+device random
+device loop
+device bpf
+device ether
+device md
+
+device uart # Serial Ports
+
+# Ethernet
+device ate # Ethernet Driver
+device mii
+option AT91_ATE_USE_RMII
+
+device at91_wdt # WDT: Watchdog timer
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+device ohci # OHCI localbus->USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+#device ulpt # Printer
+#device udbp # USB Double Bulk Pipe devices
+
+# USB Ethernet, requires miibus
+device miibus
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+device udav # Davicom DM9601E USB
+
+# USB Wireless
+#device rum # Ralink Technology RT2501USB wireless NICs
+#device uath # Atheros AR5523 wireless NICs
+#device ural # Ralink Technology RT2500USB wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
+
+# Wireless NIC cards
+#device wlan # 802.11 support
+#device wlan_wep # 802.11 WEP support
+#device wlan_ccmp # 802.11 CCMP support
+#device wlan_tkip # 802.11 TKIP support
+#device wlan_amrr # AMRR transmit rate control algorithm
+
Property changes on: trunk/sys/arm/conf/SN9G45
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/TS7800
===================================================================
--- trunk/sys/arm/conf/TS7800 (rev 0)
+++ trunk/sys/arm/conf/TS7800 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,81 @@
+#
+# Custom kernel for the TS-7800 board.
+#
+# $FreeBSD: stable/10/sys/arm/conf/TS7800 283387 2015-05-24 14:57:17Z ian $
+#
+
+ident TS7800
+include "../mv/orion/std.ts7800"
+
+options SOC_MV_ORION
+
+#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions WERROR="-Werror"
+
+options SCHED_4BSD # 4BSD scheduler
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=mge0
+
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options TMPFS # Efficient memory filesystem
+
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# Debugging
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+options KDB
+options GDB # Support remote GDB.
+
+device mvs
+device pci
+
+# Pseudo devices
+device md
+device loop
+device random
+
+# Serial ports
+device uart
+
+# Networking
+device ether
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+device bpf
+options HZ=1000
+
+# USB
+device usb
+device ehci
+device umass
+device scbus
+device pass
+device da
+
+# SATA
+device ata
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=ts7800.dts
+
Property changes on: trunk/sys/arm/conf/TS7800
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/VERSATILEPB
===================================================================
--- trunk/sys/arm/conf/VERSATILEPB (rev 0)
+++ trunk/sys/arm/conf/VERSATILEPB 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,123 @@
+#
+# VERSATILEPB - Configuration for QEMU version of Versatile Platform Board
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/VERSATILEPB 283368 2015-05-24 14:25:03Z ian $
+
+ident VERSATILEPB
+machine arm armv6
+cpu CPU_ARM1176
+
+files "../versatile/files.versatile"
+makeoptions MODULES_OVERRIDE=""
+
+options KERNVIRTADDR=0xc0100000
+makeoptions KERNVIRTADDR=0xc0100000
+options KERNPHYSADDR=0x00100000
+makeoptions KERNPHYSADDR=0x00100000
+options PHYSADDR=0x00000000
+
+options HZ=100
+options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options LINUX_BOOT_ABI # Process metadata passed from Linux boot loaders
+options VFP # Enable floating point hardware support
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+
+options ROOTDEVNAME=\"ufs:da0s1a\"
+
+device bpf
+device loop
+device mii
+device mii_bitbang
+device smc
+device smcphy
+device ether
+device uart
+device pl011
+device pl190
+
+device pty
+device snp
+
+device pci
+
+# SCSI Controllers
+device sym # NCR/Symbios/LSI Logic 53C8XX/53C1010/53C1510D
+
+# ATA/SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# NOTE: serial console is disabled if syscons enabled
+# Comment following lines for headless setup
+device sc
+device kbdmux
+options SC_DFLT_FONT # compile font in
+makeoptions SC_DFLT_FONT=cp437
+
+options KDB
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+
+device md
+device random # Entropy device
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=versatilepb.dts
Property changes on: trunk/sys/arm/conf/VERSATILEPB
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/VYBRID
===================================================================
--- trunk/sys/arm/conf/VYBRID (rev 0)
+++ trunk/sys/arm/conf/VYBRID 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,154 @@
+#
+# Kernel configuration for Vybrid Family boards.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/VYBRID 287082 2015-08-23 20:50:22Z ian $
+
+ident VYBRID
+include "../freescale/vybrid/std.vybrid"
+
+makeoptions WERROR="-Werror"
+
+options HZ=100
+options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+#options NANDFS # NAND Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+#options SMP # Enable multiple cores
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ffec0
+
+#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/cosmic\"
+#options ROOTDEVNAME=\"nandfs:/dev/gnand0s.root\"
+options ROOTDEVNAME=\"ufs:/dev/da0\"
+
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# MMC/SD/SDIO Card slot support
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+device sdhci # generic sdhci
+
+# Pseudo devices
+
+device loop
+device random
+device pty
+device md
+device gpio
+
+# USB support
+options USB_HOST_ALIGN=32 # Align usb buffers to cache line size.
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+#device musb
+device ehci
+#device ohci
+
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass
+
+# SATA
+#device ata
+#device atadisk
+#device mvs
+
+device nand
+
+# Serial ports
+device uart
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+# Ethernet
+device ether
+device ffec
+
+# USB ethernet support, requires miibus
+device miibus
+device axe # ASIX Electronics USB Ethernet
+device bpf # Berkeley packet filter
+
+device sound
+
+# Framebuffer
+device vt
+device kbdmux
+options SC_DFLT_FONT # compile font in
+makeoptions SC_DFLT_FONT=cp437
+device ukbd
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
Property changes on: trunk/sys/arm/conf/VYBRID
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/ZEDBOARD
===================================================================
--- trunk/sys/arm/conf/ZEDBOARD (rev 0)
+++ trunk/sys/arm/conf/ZEDBOARD 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,114 @@
+#
+# ZEDBOARD -- Custom configuration for the Xilinx Zynq-7000 based
+# ZedBoard (www.zedboard.org)
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/arm/conf/ZEDBOARD 287082 2015-08-23 20:50:22Z ian $
+
+ident ZEDBOARD
+
+include "../xilinx/zedboard/std.zedboard"
+
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+#options NFSSD # Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+
+options ROOTDEVNAME=\"ufs:mmcsd0s2a\"
+
+device loop
+device random
+device ether
+device cgem # Zynq-7000 gig ethernet device
+device mii
+device e1000phy
+device pty
+device uart
+device gpio
+
+device md
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+device sdhci # generic sdhci
+device bpf # Berkeley packet filter
+
+# USB support
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+device ehci
+device umass
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device axe # USB-Ethernet
+
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+#options FDT_DTB_STATIC
+#makeoptions FDT_DTS_FILE=zedboard.dts
+
Property changes on: trunk/sys/arm/conf/ZEDBOARD
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/conf/genboardid.awk
===================================================================
--- trunk/sys/arm/conf/genboardid.awk (rev 0)
+++ trunk/sys/arm/conf/genboardid.awk 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,55 @@
+#!/bin/awk
+# $FreeBSD: stable/10/sys/arm/conf/genboardid.awk 235234 2012-05-10 18:06:00Z imp $
+
+#-
+# Copyright (c) 2012 M. Warner Losh. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+#
+# Generate FreeBSD's board ID's defines from Linux's
+# arm board list.
+#
+# You can grab a new copy any time with:
+# fetch -o sys/arm/conf/mach-types http://www.arm.linux.org.uk/developer/machines/download.php
+#
+BEGIN { nr = 0; boardid[nr] = "ARM_BOARD_ID_NONE"; num[nr++] = 0; }
+/^#/ { next; }
+/^[ ]*$/ { next; }
+
+NF == 4 {
+ boardid[nr] = "ARM_BOARD_ID_"$3;
+ num[nr] = $4;
+ nr++
+}
+
+END {
+ printf("/* Arm board ID file generated automatically from Linux's mach-types file. */\n\n");
+ printf("#ifndef _SYS_ARM_ARM_BOARDID_H\n");
+ printf("#define _SYS_ARM_ARM_BOARDID_H\n\n");
+ for (i = 0; i < nr; i++) {
+ printf("#define %-30s %d\n", boardid[i], num[i]);
+ }
+ printf("\n#endif /* _SYS_ARM_ARM_BOARDID_H */\n");
+}
+
Property changes on: trunk/sys/arm/conf/genboardid.awk
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/conf/mach-types
===================================================================
--- trunk/sys/arm/conf/mach-types (rev 0)
+++ trunk/sys/arm/conf/mach-types 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,4146 @@
+# Database of machine macros and numbers
+#
+# This file is linux/arch/arm/tools/mach-types
+#
+# Up to date versions of this file can be obtained from:
+#
+# http://www.arm.linux.org.uk/developer/machines/download.php
+#
+# Please do not send patches to this file; it is automatically generated!
+# To add an entry into this database, please see Documentation/arm/README,
+# or visit:
+#
+# http://www.arm.linux.org.uk/developer/machines/?action=new
+#
+# Last update: Thu May 10 18:35:23 2012
+#
+# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
+#
+ebsa110 ARCH_EBSA110 EBSA110 0
+riscpc ARCH_RPC RISCPC 1
+nexuspci ARCH_NEXUSPCI NEXUSPCI 3
+ebsa285 ARCH_EBSA285 EBSA285 4
+netwinder ARCH_NETWINDER NETWINDER 5
+cats ARCH_CATS CATS 6
+tbox ARCH_TBOX TBOX 7
+co285 ARCH_CO285 CO285 8
+clps7110 ARCH_CLPS7110 CLPS7110 9
+archimedes ARCH_ARC ARCHIMEDES 10
+a5k ARCH_A5K A5K 11
+etoile ARCH_ETOILE ETOILE 12
+lacie_nas ARCH_LACIE_NAS LACIE_NAS 13
+clps7500 ARCH_CLPS7500 CLPS7500 14
+shark ARCH_SHARK SHARK 15
+brutus SA1100_BRUTUS BRUTUS 16
+personal_server ARCH_PERSONAL_SERVER PERSONAL_SERVER 17
+itsy SA1100_ITSY ITSY 18
+l7200 ARCH_L7200 L7200 19
+pleb SA1100_PLEB PLEB 20
+integrator ARCH_INTEGRATOR INTEGRATOR 21
+h3600 SA1100_H3600 H3600 22
+ixp1200 ARCH_IXP1200 IXP1200 23
+p720t ARCH_P720T P720T 24
+assabet SA1100_ASSABET ASSABET 25
+victor SA1100_VICTOR VICTOR 26
+lart SA1100_LART LART 27
+ranger SA1100_RANGER RANGER 28
+graphicsclient SA1100_GRAPHICSCLIENT GRAPHICSCLIENT 29
+xp860 SA1100_XP860 XP860 30
+cerf SA1100_CERF CERF 31
+nanoengine SA1100_NANOENGINE NANOENGINE 32
+fpic SA1100_FPIC FPIC 33
+extenex1 SA1100_EXTENEX1 EXTENEX1 34
+sherman SA1100_SHERMAN SHERMAN 35
+accelent_sa SA1100_ACCELENT ACCELENT_SA 36
+accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37
+netport SA1100_NETPORT NETPORT 38
+pangolin SA1100_PANGOLIN PANGOLIN 39
+yopy SA1100_YOPY YOPY 40
+coolidge SA1100_COOLIDGE COOLIDGE 41
+huw_webpanel SA1100_HUW_WEBPANEL HUW_WEBPANEL 42
+spotme ARCH_SPOTME SPOTME 43
+freebird ARCH_FREEBIRD FREEBIRD 44
+ti925 ARCH_TI925 TI925 45
+riscstation ARCH_RISCSTATION RISCSTATION 46
+cavy SA1100_CAVY CAVY 47
+jornada720 SA1100_JORNADA720 JORNADA720 48
+omnimeter SA1100_OMNIMETER OMNIMETER 49
+edb7211 ARCH_EDB7211 EDB7211 50
+citygo SA1100_CITYGO CITYGO 51
+pfs168 SA1100_PFS168 PFS168 52
+spot SA1100_SPOT SPOT 53
+flexanet SA1100_FLEXANET FLEXANET 54
+webpal ARCH_WEBPAL WEBPAL 55
+linpda SA1100_LINPDA LINPDA 56
+anakin ARCH_ANAKIN ANAKIN 57
+mvi SA1100_MVI MVI 58
+jupiter SA1100_JUPITER JUPITER 59
+psionw ARCH_PSIONW PSIONW 60
+aln SA1100_ALN ALN 61
+epxa ARCH_CAMELOT CAMELOT 62
+gds2200 SA1100_GDS2200 GDS2200 63
+netbook SA1100_PSION_SERIES7 PSION_SERIES7 64
+xfile SA1100_XFILE XFILE 65
+accelent_ep9312 ARCH_ACCELENT_EP9312 ACCELENT_EP9312 66
+ic200 ARCH_IC200 IC200 67
+creditlart SA1100_CREDITLART CREDITLART 68
+htm SA1100_HTM HTM 69
+iq80310 ARCH_IQ80310 IQ80310 70
+freebot SA1100_FREEBOT FREEBOT 71
+entel ARCH_ENTEL ENTEL 72
+enp3510 ARCH_ENP3510 ENP3510 73
+trizeps SA1100_TRIZEPS TRIZEPS 74
+nesa SA1100_NESA NESA 75
+venus ARCH_VENUS VENUS 76
+tardis ARCH_TARDIS TARDIS 77
+mercury ARCH_MERCURY MERCURY 78
+empeg SA1100_EMPEG EMPEG 79
+adi_evb ARCH_I80200FCC I80200FCC 80
+itt_cpb SA1100_ITT_CPB ITT_CPB 81
+svc SA1100_SVC SVC 82
+alpha2 SA1100_ALPHA2 ALPHA2 84
+alpha1 SA1100_ALPHA1 ALPHA1 85
+netarm ARCH_NETARM NETARM 86
+simpad SA1100_SIMPAD SIMPAD 87
+pda1 ARCH_PDA1 PDA1 88
+lubbock ARCH_LUBBOCK LUBBOCK 89
+aniko ARCH_ANIKO ANIKO 90
+clep7212 ARCH_CLEP7212 CLEP7212 91
+cs89712 ARCH_CS89712 CS89712 92
+weararm SA1100_WEARARM WEARARM 93
+possio_px SA1100_POSSIO_PX POSSIO_PX 94
+sidearm SA1100_SIDEARM SIDEARM 95
+stork SA1100_STORK STORK 96
+shannon SA1100_SHANNON SHANNON 97
+ace ARCH_ACE ACE 98
+ballyarm SA1100_BALLYARM BALLYARM 99
+simputer SA1100_SIMPUTER SIMPUTER 100
+nexterm SA1100_NEXTERM NEXTERM 101
+sa1100_elf SA1100_SA1100_ELF SA1100_ELF 102
+gator SA1100_GATOR GATOR 103
+granite ARCH_GRANITE GRANITE 104
+consus SA1100_CONSUS CONSUS 105
+aaed2000 ARCH_AAED2000 AAED2000 106
+cdb89712 ARCH_CDB89712 CDB89712 107
+graphicsmaster SA1100_GRAPHICSMASTER GRAPHICSMASTER 108
+adsbitsy SA1100_ADSBITSY ADSBITSY 109
+pxa_idp ARCH_PXA_IDP PXA_IDP 110
+plce ARCH_PLCE PLCE 111
+pt_system3 SA1100_PT_SYSTEM3 PT_SYSTEM3 112
+murphy ARCH_MEDALB MEDALB 113
+eagle ARCH_EAGLE EAGLE 114
+dsc21 ARCH_DSC21 DSC21 115
+dsc24 ARCH_DSC24 DSC24 116
+ti5472 ARCH_TI5472 TI5472 117
+autcpu12 ARCH_AUTCPU12 AUTCPU12 118
+uengine ARCH_UENGINE UENGINE 119
+bluestem SA1100_BLUESTEM BLUESTEM 120
+xingu8 ARCH_XINGU8 XINGU8 121
+bushstb ARCH_BUSHSTB BUSHSTB 122
+epsilon1 SA1100_EPSILON1 EPSILON1 123
+balloon SA1100_BALLOON BALLOON 124
+puppy ARCH_PUPPY PUPPY 125
+elroy SA1100_ELROY ELROY 126
+gms720 ARCH_GMS720 GMS720 127
+s24x ARCH_S24X S24X 128
+jtel_clep7312 ARCH_JTEL_CLEP7312 JTEL_CLEP7312 129
+cx821xx ARCH_CX821XX CX821XX 130
+edb7312 ARCH_EDB7312 EDB7312 131
+bsa1110 SA1100_BSA1110 BSA1110 132
+powerpin ARCH_POWERPIN POWERPIN 133
+openarm ARCH_OPENARM OPENARM 134
+whitechapel SA1100_WHITECHAPEL WHITECHAPEL 135
+h3100 SA1100_H3100 H3100 136
+h3800 SA1100_H3800 H3800 137
+blue_v1 ARCH_BLUE_V1 BLUE_V1 138
+pxa_cerf ARCH_PXA_CERF PXA_CERF 139
+arm7tevb ARCH_ARM7TEVB ARM7TEVB 140
+d7400 SA1100_D7400 D7400 141
+piranha ARCH_PIRANHA PIRANHA 142
+sbcamelot SA1100_SBCAMELOT SBCAMELOT 143
+kings SA1100_KINGS KINGS 144
+smdk2400 ARCH_SMDK2400 SMDK2400 145
+collie SA1100_COLLIE COLLIE 146
+idr ARCH_IDR IDR 147
+badge4 SA1100_BADGE4 BADGE4 148
+webnet ARCH_WEBNET WEBNET 149
+d7300 SA1100_D7300 D7300 150
+cep SA1100_CEP CEP 151
+fortunet ARCH_FORTUNET FORTUNET 152
+vc547x ARCH_VC547X VC547X 153
+filewalker SA1100_FILEWALKER FILEWALKER 154
+netgateway SA1100_NETGATEWAY NETGATEWAY 155
+symbol2800 SA1100_SYMBOL2800 SYMBOL2800 156
+suns SA1100_SUNS SUNS 157
+frodo SA1100_FRODO FRODO 158
+ms301 SA1100_MACH_TYTE_MS301 MACH_TYTE_MS301 159
+mx1ads ARCH_MX1ADS MX1ADS 160
+h7201 ARCH_H7201 H7201 161
+h7202 ARCH_H7202 H7202 162
+amico ARCH_AMICO AMICO 163
+iam SA1100_IAM IAM 164
+tt530 SA1100_TT530 TT530 165
+sam2400 ARCH_SAM2400 SAM2400 166
+jornada56x SA1100_JORNADA56X JORNADA56X 167
+active SA1100_ACTIVE ACTIVE 168
+iq80321 ARCH_IQ80321 IQ80321 169
+wid SA1100_WID WID 170
+sabinal ARCH_SABINAL SABINAL 171
+ixp425_matacumbe ARCH_IXP425_MATACUMBE IXP425_MATACUMBE 172
+miniprint SA1100_MINIPRINT MINIPRINT 173
+adm510x ARCH_ADM510X ADM510X 174
+svs200 SA1100_SVS200 SVS200 175
+atg_tcu ARCH_ATG_TCU ATG_TCU 176
+jornada820 SA1100_JORNADA820 JORNADA820 177
+s3c44b0 ARCH_S3C44B0 S3C44B0 178
+margis2 ARCH_MARGIS2 MARGIS2 179
+ks8695 ARCH_KS8695 KS8695 180
+brh ARCH_BRH BRH 181
+s3c2410 ARCH_S3C2410 S3C2410 182
+possio_px30 ARCH_POSSIO_PX30 POSSIO_PX30 183
+s3c2800 ARCH_S3C2800 S3C2800 184
+fleetwood SA1100_FLEETWOOD FLEETWOOD 185
+omaha ARCH_OMAHA OMAHA 186
+ta7 ARCH_TA7 TA7 187
+nova SA1100_NOVA NOVA 188
+hmk ARCH_HMK HMK 189
+karo ARCH_KARO KARO 190
+fester SA1100_FESTER FESTER 191
+gpi ARCH_GPI GPI 192
+smdk2410 ARCH_SMDK2410 SMDK2410 193
+i519 ARCH_I519 I519 194
+nexio SA1100_NEXIO NEXIO 195
+bitbox SA1100_BITBOX BITBOX 196
+g200 SA1100_G200 G200 197
+gill SA1100_GILL GILL 198
+pxa_mercury ARCH_PXA_MERCURY PXA_MERCURY 199
+ceiva ARCH_CEIVA CEIVA 200
+fret SA1100_FRET FRET 201
+emailphone SA1100_EMAILPHONE EMAILPHONE 202
+h3900 ARCH_H3900 H3900 203
+pxa1 ARCH_PXA1 PXA1 204
+koan369 SA1100_KOAN369 KOAN369 205
+cogent ARCH_COGENT COGENT 206
+esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207
+esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208
+esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209
+hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210
+he500 ARCH_HE500 HE500 211
+inhandelf2 SA1100_INHANDELF2 INHANDELF2 212
+inhandftip SA1100_INHANDFTIP INHANDFTIP 213
+dnp1110 SA1100_DNP1110 DNP1110 214
+pnp1110 SA1100_PNP1110 PNP1110 215
+csb226 ARCH_CSB226 CSB226 216
+arnold SA1100_ARNOLD ARNOLD 217
+voiceblue MACH_VOICEBLUE VOICEBLUE 218
+jz8028 ARCH_JZ8028 JZ8028 219
+h5400 ARCH_H5400 H5400 220
+forte SA1100_FORTE FORTE 221
+acam SA1100_ACAM ACAM 222
+abox SA1100_ABOX ABOX 223
+atmel ARCH_ATMEL ATMEL 224
+sitsang ARCH_SITSANG SITSANG 225
+cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226
+mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227
+opus_a1 ARCH_OPUS_A1 OPUS_A1 228
+daytona ARCH_DAYTONA DAYTONA 229
+killbear SA1100_KILLBEAR KILLBEAR 230
+yoho ARCH_YOHO YOHO 231
+jasper ARCH_JASPER JASPER 232
+dsc25 ARCH_DSC25 DSC25 233
+omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234
+mnci ARCH_RAMSES RAMSES 235
+s28x ARCH_S28X S28X 236
+mport3 ARCH_MPORT3 MPORT3 237
+pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238
+pdb ARCH_PDB PDB 239
+blue_2g SA1100_BLUE_2G BLUE_2G 240
+bluearch SA1100_BLUEARCH BLUEARCH 241
+ixdp2400 ARCH_IXDP2400 IXDP2400 242
+ixdp2800 ARCH_IXDP2800 IXDP2800 243
+explorer SA1100_EXPLORER EXPLORER 244
+ixdp425 ARCH_IXDP425 IXDP425 245
+chimp ARCH_CHIMP CHIMP 246
+stork_nest ARCH_STORK_NEST STORK_NEST 247
+stork_egg ARCH_STORK_EGG STORK_EGG 248
+wismo SA1100_WISMO WISMO 249
+ezlinx ARCH_EZLINX EZLINX 250
+at91rm9200 ARCH_AT91RM9200 AT91RM9200 251
+adtech_orion ARCH_ADTECH_ORION ADTECH_ORION 252
+neptune ARCH_NEPTUNE NEPTUNE 253
+hackkit SA1100_HACKKIT HACKKIT 254
+pxa_wins30 ARCH_PXA_WINS30 PXA_WINS30 255
+lavinna SA1100_LAVINNA LAVINNA 256
+pxa_uengine ARCH_PXA_UENGINE PXA_UENGINE 257
+innokom ARCH_INNOKOM INNOKOM 258
+bms ARCH_BMS BMS 259
+ixcdp1100 ARCH_IXCDP1100 IXCDP1100 260
+prpmc1100 ARCH_PRPMC1100 PRPMC1100 261
+at91rm9200dk ARCH_AT91RM9200DK AT91RM9200DK 262
+armstick ARCH_ARMSTICK ARMSTICK 263
+armonie ARCH_ARMONIE ARMONIE 264
+mport1 ARCH_MPORT1 MPORT1 265
+s3c5410 ARCH_S3C5410 S3C5410 266
+zcp320a ARCH_ZCP320A ZCP320A 267
+i_box ARCH_I_BOX I_BOX 268
+stlc1502 ARCH_STLC1502 STLC1502 269
+siren ARCH_SIREN SIREN 270
+greenlake ARCH_GREENLAKE GREENLAKE 271
+argus ARCH_ARGUS ARGUS 272
+combadge SA1100_COMBADGE COMBADGE 273
+rokepxa ARCH_ROKEPXA ROKEPXA 274
+cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275
+guidea07 ARCH_GUIDEA07 GUIDEA07 276
+tat257 ARCH_TAT257 TAT257 277
+igp2425 ARCH_IGP2425 IGP2425 278
+bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279
+ipod ARCH_IPOD IPOD 280
+adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281
+trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282
+viper ARCH_VIPER VIPER 283
+adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284
+adsagc SA1100_ADSAGC ADSAGC 285
+stp7312 ARCH_STP7312 STP7312 286
+nx_phnx MACH_NX_PHNX NX_PHNX 287
+wep_ep250 ARCH_WEP_EP250 WEP_EP250 288
+inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
+adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
+iyonix ARCH_IYONIX IYONIX 291
+damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
+meg03 ARCH_MEG03 MEG03 293
+pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
+nwsc ARCH_NWSC NWSC 295
+nwlarm ARCH_NWLARM NWLARM 296
+ixp425_mguard ARCH_IXP425_MGUARD IXP425_MGUARD 297
+pxa_netdcu4 ARCH_PXA_NETDCU4 PXA_NETDCU4 298
+ixdp2401 ARCH_IXDP2401 IXDP2401 299
+ixdp2801 ARCH_IXDP2801 IXDP2801 300
+zodiac ARCH_ZODIAC ZODIAC 301
+armmodul ARCH_ARMMODUL ARMMODUL 302
+ketop SA1100_KETOP KETOP 303
+av7200 ARCH_AV7200 AV7200 304
+arch_ti925 ARCH_ARCH_TI925 ARCH_TI925 305
+acq200 ARCH_ACQ200 ACQ200 306
+pt_dafit SA1100_PT_DAFIT PT_DAFIT 307
+ihba ARCH_IHBA IHBA 308
+quinque ARCH_QUINQUE QUINQUE 309
+nimbraone ARCH_NIMBRAONE NIMBRAONE 310
+nimbra29x ARCH_NIMBRA29X NIMBRA29X 311
+nimbra210 ARCH_NIMBRA210 NIMBRA210 312
+hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313
+labarm ARCH_LABARM LABARM 314
+m825xx ARCH_M825XX M825XX 315
+m7100 SA1100_M7100 M7100 316
+nipc2 ARCH_NIPC2 NIPC2 317
+fu7202 ARCH_FU7202 FU7202 318
+adsagx ARCH_ADSAGX ADSAGX 319
+pxa_pooh ARCH_PXA_POOH PXA_POOH 320
+bandon ARCH_BANDON BANDON 321
+pcm7210 ARCH_PCM7210 PCM7210 322
+nms9200 ARCH_NMS9200 NMS9200 323
+logodl ARCH_LOGODL LOGODL 324
+m7140 SA1100_M7140 M7140 325
+korebot ARCH_KOREBOT KOREBOT 326
+iq31244 ARCH_IQ31244 IQ31244 327
+koan393 SA1100_KOAN393 KOAN393 328
+inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329
+gonzo ARCH_GONZO GONZO 330
+bast ARCH_BAST BAST 331
+scanpass ARCH_SCANPASS SCANPASS 332
+ep7312_pooh ARCH_EP7312_POOH EP7312_POOH 333
+ta7s ARCH_TA7S TA7S 334
+ta7v ARCH_TA7V TA7V 335
+icarus SA1100_ICARUS ICARUS 336
+h1900 ARCH_H1900 H1900 337
+gemini SA1100_GEMINI GEMINI 338
+axim ARCH_AXIM AXIM 339
+audiotron ARCH_AUDIOTRON AUDIOTRON 340
+h2200 ARCH_H2200 H2200 341
+loox600 ARCH_LOOX600 LOOX600 342
+niop ARCH_NIOP NIOP 343
+dm310 ARCH_DM310 DM310 344
+seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345
+ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346
+h1940 ARCH_H1940 H1940 347
+scorpio ARCH_SCORPIO SCORPIO 348
+viva ARCH_VIVA VIVA 349
+pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350
+csb335 ARCH_CSB335 CSB335 351
+ixrd425 ARCH_IXRD425 IXRD425 352
+iq80315 ARCH_IQ80315 IQ80315 353
+nmp7312 ARCH_NMP7312 NMP7312 354
+cx861xx ARCH_CX861XX CX861XX 355
+enp2611 ARCH_ENP2611 ENP2611 356
+xda SA1100_XDA XDA 357
+csir_ims ARCH_CSIR_IMS CSIR_IMS 358
+ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359
+pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360
+toto ARCH_TOTO TOTO 361
+s3c2440 ARCH_S3C2440 S3C2440 362
+ks8695p ARCH_KS8695P KS8695P 363
+se4000 ARCH_SE4000 SE4000 364
+quadriceps ARCH_QUADRICEPS QUADRICEPS 365
+bronco ARCH_BRONCO BRONCO 366
+esl_wireless_tab ARCH_ESL_WIRELESS_TAB ESL_WIRELESS_TAB 367
+esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
+s5c7375 ARCH_S5C7375 S5C7375 369
+spearhead ARCH_SPEARHEAD SPEARHEAD 370
+pantera ARCH_PANTERA PANTERA 371
+prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
+gumstix ARCH_GUMSTIX GUMSTIX 373
+rcube ARCH_RCUBE RCUBE 374
+rea_olv ARCH_REA_OLV REA_OLV 375
+pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
+s3c3410 ARCH_S3C3410 S3C3410 377
+espd_4510b ARCH_ESPD_4510B ESPD_4510B 378
+mp1x ARCH_MP1X MP1X 379
+at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380
+adsvgx ARCH_ADSVGX ADSVGX 381
+omap_h2 MACH_OMAP_H2 OMAP_H2 382
+pelee ARCH_PELEE PELEE 383
+e740 MACH_E740 E740 384
+iq80331 ARCH_IQ80331 IQ80331 385
+versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387
+kev7a400 MACH_KEV7A400 KEV7A400 388
+lpd7a400 MACH_LPD7A400 LPD7A400 389
+lpd7a404 MACH_LPD7A404 LPD7A404 390
+fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391
+janus2m ARCH_JANUS2M JANUS2M 392
+embtf MACH_EMBTF EMBTF 393
+hpm MACH_HPM HPM 394
+smdk2410tk MACH_SMDK2410TK SMDK2410TK 395
+smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396
+streetracer MACH_STREETRACER STREETRACER 397
+eframe MACH_EFRAME EFRAME 398
+csb337 MACH_CSB337 CSB337 399
+pxa_lark MACH_PXA_LARK PXA_LARK 400
+pxa_pnp2110 MACH_PNP2110 PNP2110 401
+tcc72x MACH_TCC72X TCC72X 402
+altair MACH_ALTAIR ALTAIR 403
+kc3 MACH_KC3 KC3 404
+sinteftd MACH_SINTEFTD SINTEFTD 405
+mainstone MACH_MAINSTONE MAINSTONE 406
+aday4x MACH_ADAY4X ADAY4X 407
+lite300 MACH_LITE300 LITE300 408
+s5c7376 MACH_S5C7376 S5C7376 409
+mt02 MACH_MT02 MT02 410
+mport3s MACH_MPORT3S MPORT3S 411
+ra_alpha MACH_RA_ALPHA RA_ALPHA 412
+xcep MACH_XCEP XCEP 413
+arcom_vulcan MACH_ARCOM_VULCAN ARCOM_VULCAN 414
+stargate MACH_STARGATE STARGATE 415
+armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
+elroy_jack MACH_ELROY_JACK ELROY_JACK 417
+backend MACH_BACKEND BACKEND 418
+s5linbox MACH_S5LINBOX S5LINBOX 419
+nomadik MACH_NOMADIK NOMADIK 420
+ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421
+at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422
+corgi MACH_CORGI CORGI 423
+poodle MACH_POODLE POODLE 424
+ten MACH_TEN TEN 425
+roverp5p MACH_ROVERP5P ROVERP5P 426
+sc2700 MACH_SC2700 SC2700 427
+ex_eagle MACH_EX_EAGLE EX_EAGLE 428
+nx_pxa12 MACH_NX_PXA12 NX_PXA12 429
+nx_pxa5 MACH_NX_PXA5 NX_PXA5 430
+blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431
+i819 MACH_I819 I819 432
+ixmb995e MACH_IXMB995E IXMB995E 433
+skyrider MACH_SKYRIDER SKYRIDER 434
+skyhawk MACH_SKYHAWK SKYHAWK 435
+enterprise MACH_ENTERPRISE ENTERPRISE 436
+dep2410 MACH_DEP2410 DEP2410 437
+armcore MACH_ARMCORE ARMCORE 438
+hobbit MACH_HOBBIT HOBBIT 439
+h7210 MACH_H7210 H7210 440
+pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441
+acc MACH_ACC ACC 442
+esl_sarva MACH_ESL_SARVA ESL_SARVA 443
+xm250 MACH_XM250 XM250 444
+t6tc1xb MACH_T6TC1XB T6TC1XB 445
+ess710 MACH_ESS710 ESS710 446
+mx31ads MACH_MX31ADS MX31ADS 447
+himalaya MACH_HIMALAYA HIMALAYA 448
+bolfenk MACH_BOLFENK BOLFENK 449
+at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
+edb9312 MACH_EDB9312 EDB9312 451
+omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452
+aximx3 MACH_AXIMX3 AXIMX3 453
+eb67xdip MACH_EB67XDIP EB67XDIP 454
+webtxs MACH_WEBTXS WEBTXS 455
+hawk MACH_HAWK HAWK 456
+ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457
+expresso MACH_EXPRESSO EXPRESSO 458
+h4000 MACH_H4000 H4000 459
+dino MACH_DINO DINO 460
+ml675k MACH_ML675K ML675K 461
+edb9301 MACH_EDB9301 EDB9301 462
+edb9315 MACH_EDB9315 EDB9315 463
+reciva_tt MACH_RECIVA_TT RECIVA_TT 464
+cstcb01 MACH_CSTCB01 CSTCB01 465
+cstcb1 MACH_CSTCB1 CSTCB1 466
+shadwell MACH_SHADWELL SHADWELL 467
+goepel263 MACH_GOEPEL263 GOEPEL263 468
+acq100 MACH_ACQ100 ACQ100 469
+mx1fs2 MACH_MX1FS2 MX1FS2 470
+hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471
+sparky MACH_SPARKY SPARKY 472
+ns9750 MACH_NS9750 NS9750 473
+phoenix MACH_PHOENIX PHOENIX 474
+vr1000 MACH_VR1000 VR1000 475
+deisterpxa MACH_DEISTERPXA DEISTERPXA 476
+bcm1160 MACH_BCM1160 BCM1160 477
+pcm022 MACH_PCM022 PCM022 478
+adsgcx MACH_ADSGCX ADSGCX 479
+dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480
+dm320 MACH_DM320 DM320 481
+markov MACH_MARKOV MARKOV 482
+cos7a400 MACH_COS7A400 COS7A400 483
+milano MACH_MILANO MILANO 484
+ue9328 MACH_UE9328 UE9328 485
+uex255 MACH_UEX255 UEX255 486
+ue2410 MACH_UE2410 UE2410 487
+a620 MACH_A620 A620 488
+ocelot MACH_OCELOT OCELOT 489
+cheetah MACH_CHEETAH CHEETAH 490
+omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491
+zvue MACH_ZVUE ZVUE 492
+roverp1 MACH_ROVERP1 ROVERP1 493
+asidial2 MACH_ASIDIAL2 ASIDIAL2 494
+s3c24a0 MACH_S3C24A0 S3C24A0 495
+e800 MACH_E800 E800 496
+e750 MACH_E750 E750 497
+s3c5500 MACH_S3C5500 S3C5500 498
+smdk5500 MACH_SMDK5500 SMDK5500 499
+signalsync MACH_SIGNALSYNC SIGNALSYNC 500
+nbc MACH_NBC NBC 501
+kodiak MACH_KODIAK KODIAK 502
+netbookpro MACH_NETBOOKPRO NETBOOKPRO 503
+hw90200 MACH_HW90200 HW90200 504
+condor MACH_CONDOR CONDOR 505
+cup MACH_CUP CUP 506
+kite MACH_KITE KITE 507
+scb9328 MACH_SCB9328 SCB9328 508
+omap_h3 MACH_OMAP_H3 OMAP_H3 509
+omap_h4 MACH_OMAP_H4 OMAP_H4 510
+n10 MACH_N10 N10 511
+montejade MACH_MONTAJADE MONTAJADE 512
+sg560 MACH_SG560 SG560 513
+dp1000 MACH_DP1000 DP1000 514
+omap_osk MACH_OMAP_OSK OMAP_OSK 515
+rg100v3 MACH_RG100V3 RG100V3 516
+mx2ads MACH_MX2ADS MX2ADS 517
+pxa_kilo MACH_PXA_KILO PXA_KILO 518
+ixp4xx_eagle MACH_IXP4XX_EAGLE IXP4XX_EAGLE 519
+tosa MACH_TOSA TOSA 520
+mb2520f MACH_MB2520F MB2520F 521
+emc1000 MACH_EMC1000 EMC1000 522
+tidsc25 MACH_TIDSC25 TIDSC25 523
+akcpmxl MACH_AKCPMXL AKCPMXL 524
+av3xx MACH_AV3XX AV3XX 525
+avila MACH_AVILA AVILA 526
+pxa_mpm10 MACH_PXA_MPM10 PXA_MPM10 527
+pxa_kyanite MACH_PXA_KYANITE PXA_KYANITE 528
+sgold MACH_SGOLD SGOLD 529
+oscar MACH_OSCAR OSCAR 530
+epxa4usb2 MACH_EPXA4USB2 EPXA4USB2 531
+xsengine MACH_XSENGINE XSENGINE 532
+ip600 MACH_IP600 IP600 533
+mcan2 MACH_MCAN2 MCAN2 534
+ddi_blueridge MACH_DDI_BLUERIDGE DDI_BLUERIDGE 535
+skyminder MACH_SKYMINDER SKYMINDER 536
+lpd79520 MACH_LPD79520 LPD79520 537
+edb9302 MACH_EDB9302 EDB9302 538
+hw90340 MACH_HW90340 HW90340 539
+cip_box MACH_CIP_BOX CIP_BOX 540
+ivpn MACH_IVPN IVPN 541
+rsoc2 MACH_RSOC2 RSOC2 542
+husky MACH_HUSKY HUSKY 543
+boxer MACH_BOXER BOXER 544
+shepherd MACH_SHEPHERD SHEPHERD 545
+aml42800aa MACH_AML42800AA AML42800AA 546
+lpc2294 MACH_LPC2294 LPC2294 548
+switchgrass MACH_SWITCHGRASS SWITCHGRASS 549
+ens_cmu MACH_ENS_CMU ENS_CMU 550
+mm6_sdb MACH_MM6_SDB MM6_SDB 551
+saturn MACH_SATURN SATURN 552
+i30030evb MACH_I30030EVB I30030EVB 553
+mxc27530evb MACH_MXC27530EVB MXC27530EVB 554
+smdk2800 MACH_SMDK2800 SMDK2800 555
+mtwilson MACH_MTWILSON MTWILSON 556
+ziti MACH_ZITI ZITI 557
+grandfather MACH_GRANDFATHER GRANDFATHER 558
+tengine MACH_TENGINE TENGINE 559
+s3c2460 MACH_S3C2460 S3C2460 560
+pdm MACH_PDM PDM 561
+h4700 MACH_H4700 H4700 562
+h6300 MACH_H6300 H6300 563
+rz1700 MACH_RZ1700 RZ1700 564
+a716 MACH_A716 A716 565
+estk2440a MACH_ESTK2440A ESTK2440A 566
+atwixp425 MACH_ATWIXP425 ATWIXP425 567
+csb336 MACH_CSB336 CSB336 568
+rirm2 MACH_RIRM2 RIRM2 569
+cx23518 MACH_CX23518 CX23518 570
+cx2351x MACH_CX2351X CX2351X 571
+computime MACH_COMPUTIME COMPUTIME 572
+izarus MACH_IZARUS IZARUS 573
+pxa_rts MACH_RTS RTS 574
+se5100 MACH_SE5100 SE5100 575
+s3c2510 MACH_S3C2510 S3C2510 576
+csb437tl MACH_CSB437TL CSB437TL 577
+slauson MACH_SLAUSON SLAUSON 578
+pearlriver MACH_PEARLRIVER PEARLRIVER 579
+tdc_p210 MACH_TDC_P210 TDC_P210 580
+sg580 MACH_SG580 SG580 581
+wrsbcarm7 MACH_WRSBCARM7 WRSBCARM7 582
+ipd MACH_IPD IPD 583
+pxa_dnp2110 MACH_PXA_DNP2110 PXA_DNP2110 584
+xaeniax MACH_XAENIAX XAENIAX 585
+somn4250 MACH_SOMN4250 SOMN4250 586
+pleb2 MACH_PLEB2 PLEB2 587
+cornwallis MACH_CORNWALLIS CORNWALLIS 588
+gurney_drv MACH_GURNEY_DRV GURNEY_DRV 589
+chaffee MACH_CHAFFEE CHAFFEE 590
+rms101 MACH_RMS101 RMS101 591
+rx3715 MACH_RX3715 RX3715 592
+swift MACH_SWIFT SWIFT 593
+roverp7 MACH_ROVERP7 ROVERP7 594
+pr818s MACH_PR818S PR818S 595
+trxpro MACH_TRXPRO TRXPRO 596
+nslu2 MACH_NSLU2 NSLU2 597
+e400 MACH_E400 E400 598
+trab MACH_TRAB TRAB 599
+cmc_pu2 MACH_CMC_PU2 CMC_PU2 600
+fulcrum MACH_FULCRUM FULCRUM 601
+netgate42x MACH_NETGATE42X NETGATE42X 602
+str710 MACH_STR710 STR710 603
+ixdpg425 MACH_IXDPG425 IXDPG425 604
+tomtomgo MACH_TOMTOMGO TOMTOMGO 605
+versatile_ab MACH_VERSATILE_AB VERSATILE_AB 606
+edb9307 MACH_EDB9307 EDB9307 607
+sg565 MACH_SG565 SG565 608
+lpd79524 MACH_LPD79524 LPD79524 609
+lpd79525 MACH_LPD79525 LPD79525 610
+rms100 MACH_RMS100 RMS100 611
+kb9200 MACH_KB9200 KB9200 612
+sx1 MACH_SX1 SX1 613
+hms39c7092 MACH_HMS39C7092 HMS39C7092 614
+armadillo MACH_ARMADILLO ARMADILLO 615
+ipcu MACH_IPCU IPCU 616
+loox720 MACH_LOOX720 LOOX720 617
+ixdp465 MACH_IXDP465 IXDP465 618
+ixdp2351 MACH_IXDP2351 IXDP2351 619
+adsvix MACH_ADSVIX ADSVIX 620
+dm270 MACH_DM270 DM270 621
+socltplus MACH_SOCLTPLUS SOCLTPLUS 622
+ecia MACH_ECIA ECIA 623
+cm4008 MACH_CM4008 CM4008 624
+p2001 MACH_P2001 P2001 625
+twister MACH_TWISTER TWISTER 626
+mudshark MACH_MUDSHARK MUDSHARK 627
+hb2 MACH_HB2 HB2 628
+iq80332 MACH_IQ80332 IQ80332 629
+sendt MACH_SENDT SENDT 630
+mx2jazz MACH_MX2JAZZ MX2JAZZ 631
+multiio MACH_MULTIIO MULTIIO 632
+hrdisplay MACH_HRDISPLAY HRDISPLAY 633
+mxc27530ads MACH_MXC27530ADS MXC27530ADS 634
+trizeps3 MACH_TRIZEPS3 TRIZEPS3 635
+zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636
+zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637
+zefeerdzg MACH_ZEFEERDZG ZEFEERDZG 638
+zefeerdzn MACH_ZEFEERDZN ZEFEERDZN 639
+zefeerdzq MACH_ZEFEERDZQ ZEFEERDZQ 640
+gtwx5715 MACH_GTWX5715 GTWX5715 641
+astro_jack MACH_ASTRO_JACK ASTRO_JACK 643
+tip03 MACH_TIP03 TIP03 644
+a9200ec MACH_A9200EC A9200EC 645
+pnx0105 MACH_PNX0105 PNX0105 646
+adcpoecpu MACH_ADCPOECPU ADCPOECPU 647
+csb637 MACH_CSB637 CSB637 648
+mb9200 MACH_MB9200 MB9200 650
+kulun MACH_KULUN KULUN 651
+snapper MACH_SNAPPER SNAPPER 652
+optima MACH_OPTIMA OPTIMA 653
+dlhsbc MACH_DLHSBC DLHSBC 654
+x30 MACH_X30 X30 655
+n30 MACH_N30 N30 656
+manga_ks8695 MACH_MANGA_KS8695 MANGA_KS8695 657
+ajax MACH_AJAX AJAX 658
+nec_mp900 MACH_NEC_MP900 NEC_MP900 659
+vvtk1000 MACH_VVTK1000 VVTK1000 661
+kafa MACH_KAFA KAFA 662
+vvtk3000 MACH_VVTK3000 VVTK3000 663
+pimx1 MACH_PIMX1 PIMX1 664
+ollie MACH_OLLIE OLLIE 665
+skymax MACH_SKYMAX SKYMAX 666
+jazz MACH_JAZZ JAZZ 667
+tel_t3 MACH_TEL_T3 TEL_T3 668
+aisino_fcr255 MACH_AISINO_FCR255 AISINO_FCR255 669
+btweb MACH_BTWEB BTWEB 670
+dbg_lh79520 MACH_DBG_LH79520 DBG_LH79520 671
+cm41xx MACH_CM41XX CM41XX 672
+ts72xx MACH_TS72XX TS72XX 673
+nggpxa MACH_NGGPXA NGGPXA 674
+csb535 MACH_CSB535 CSB535 675
+csb536 MACH_CSB536 CSB536 676
+pxa_trakpod MACH_PXA_TRAKPOD PXA_TRAKPOD 677
+praxis MACH_PRAXIS PRAXIS 678
+lh75411 MACH_LH75411 LH75411 679
+otom MACH_OTOM OTOM 680
+nexcoder_2440 MACH_NEXCODER_2440 NEXCODER_2440 681
+loox410 MACH_LOOX410 LOOX410 682
+westlake MACH_WESTLAKE WESTLAKE 683
+nsb MACH_NSB NSB 684
+esl_sarva_stn MACH_ESL_SARVA_STN ESL_SARVA_STN 685
+esl_sarva_tft MACH_ESL_SARVA_TFT ESL_SARVA_TFT 686
+esl_sarva_iad MACH_ESL_SARVA_IAD ESL_SARVA_IAD 687
+esl_sarva_acc MACH_ESL_SARVA_ACC ESL_SARVA_ACC 688
+typhoon MACH_TYPHOON TYPHOON 689
+cnav MACH_CNAV CNAV 690
+a730 MACH_A730 A730 691
+netstar MACH_NETSTAR NETSTAR 692
+supercon MACH_PHASEFALE_SUPERCON PHASEFALE_SUPERCON 693
+shiva1100 MACH_SHIVA1100 SHIVA1100 694
+etexsc MACH_ETEXSC ETEXSC 695
+ixdpg465 MACH_IXDPG465 IXDPG465 696
+a9m2410 MACH_A9M2410 A9M2410 697
+a9m2440 MACH_A9M2440 A9M2440 698
+a9m9750 MACH_A9M9750 A9M9750 699
+a9m9360 MACH_A9M9360 A9M9360 700
+unc90 MACH_UNC90 UNC90 701
+eco920 MACH_ECO920 ECO920 702
+satview MACH_SATVIEW SATVIEW 703
+roadrunner MACH_ROADRUNNER ROADRUNNER 704
+at91rm9200ek MACH_AT91RM9200EK AT91RM9200EK 705
+gp32 MACH_GP32 GP32 706
+gem MACH_GEM GEM 707
+i858 MACH_I858 I858 708
+hx2750 MACH_HX2750 HX2750 709
+mxc91131evb MACH_MXC91131EVB MXC91131EVB 710
+p700 MACH_P700 P700 711
+cpe MACH_CPE CPE 712
+spitz MACH_SPITZ SPITZ 713
+nimbra340 MACH_NIMBRA340 NIMBRA340 714
+lpc22xx MACH_LPC22XX LPC22XX 715
+omap_comet3 MACH_COMET3 COMET3 716
+omap_comet4 MACH_COMET4 COMET4 717
+csb625 MACH_CSB625 CSB625 718
+fortunet2 MACH_FORTUNET2 FORTUNET2 719
+s5h2200 MACH_S5H2200 S5H2200 720
+optorm920 MACH_OPTORM920 OPTORM920 721
+adsbitsyxb MACH_ADSBITSYXB ADSBITSYXB 722
+adssphere MACH_ADSSPHERE ADSSPHERE 723
+adsportal MACH_ADSPORTAL ADSPORTAL 724
+ln2410sbc MACH_LN2410SBC LN2410SBC 725
+cb3rufc MACH_CB3RUFC CB3RUFC 726
+mp2usb MACH_MP2USB MP2USB 727
+ntnp425c MACH_NTNP425C NTNP425C 728
+colibri MACH_COLIBRI COLIBRI 729
+pcm7220 MACH_PCM7220 PCM7220 730
+gateway7001 MACH_GATEWAY7001 GATEWAY7001 731
+pcm027 MACH_PCM027 PCM027 732
+cmpxa MACH_CMPXA CMPXA 733
+anubis MACH_ANUBIS ANUBIS 734
+ite8152 MACH_ITE8152 ITE8152 735
+lpc3xxx MACH_LPC3XXX LPC3XXX 736
+puppeteer MACH_PUPPETEER PUPPETEER 737
+e570 MACH_E570 E570 739
+x50 MACH_X50 X50 740
+recon MACH_RECON RECON 741
+xboardgp8 MACH_XBOARDGP8 XBOARDGP8 742
+fpic2 MACH_FPIC2 FPIC2 743
+akita MACH_AKITA AKITA 744
+a81 MACH_A81 A81 745
+svm_sc25x MACH_SVM_SC25X SVM_SC25X 746
+vt020 MACH_VADATECH020 VADATECH020 747
+tli MACH_TLI TLI 748
+edb9315lc MACH_EDB9315LC EDB9315LC 749
+passec MACH_PASSEC PASSEC 750
+ds_tiger MACH_DS_TIGER DS_TIGER 751
+e310 MACH_E310 E310 752
+e330 MACH_E330 E330 753
+rt3000 MACH_RT3000 RT3000 754
+nokia770 MACH_NOKIA770 NOKIA770 755
+pnx0106 MACH_PNX0106 PNX0106 756
+hx21xx MACH_HX21XX HX21XX 757
+faraday MACH_FARADAY FARADAY 758
+sbc9312 MACH_SBC9312 SBC9312 759
+batman MACH_BATMAN BATMAN 760
+jpd201 MACH_JPD201 JPD201 761
+mipsa MACH_MIPSA MIPSA 762
+kacom MACH_KACOM KACOM 763
+swarcocpu MACH_SWARCOCPU SWARCOCPU 764
+swarcodsl MACH_SWARCODSL SWARCODSL 765
+blueangel MACH_BLUEANGEL BLUEANGEL 766
+hairygrama MACH_HAIRYGRAMA HAIRYGRAMA 767
+banff MACH_BANFF BANFF 768
+carmeva MACH_CARMEVA CARMEVA 769
+sam255 MACH_SAM255 SAM255 770
+ppm10 MACH_PPM10 PPM10 771
+edb9315a MACH_EDB9315A EDB9315A 772
+sunset MACH_SUNSET SUNSET 773
+stargate2 MACH_STARGATE2 STARGATE2 774
+intelmote2 MACH_INTELMOTE2 INTELMOTE2 775
+trizeps4 MACH_TRIZEPS4 TRIZEPS4 776
+mainstone2 MACH_MAINSTONE2 MAINSTONE2 777
+ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778
+tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779
+universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780
+hicoarm9 MACH_HICOARM9 HICOARM9 781
+pnx4008 MACH_PNX4008 PNX4008 782
+kws6000 MACH_KWS6000 KWS6000 783
+portux920t MACH_PORTUX920T PORTUX920T 784
+ez_x5 MACH_EZ_X5 EZ_X5 785
+omap_rudolph MACH_OMAP_RUDOLPH OMAP_RUDOLPH 786
+cpuat91 MACH_CPUAT91 CPUAT91 787
+rea9200 MACH_REA9200 REA9200 788
+acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789
+ixp425 MACH_IXP425 IXP425 790
+i30030ads MACH_I30030ADS I30030ADS 791
+perch MACH_PERCH PERCH 792
+eis05r1 MACH_EIS05R1 EIS05R1 793
+pepperpad MACH_PEPPERPAD PEPPERPAD 794
+sb3010 MACH_SB3010 SB3010 795
+rm9200 MACH_RM9200 RM9200 796
+dma03 MACH_DMA03 DMA03 797
+road_s101 MACH_ROAD_S101 ROAD_S101 798
+iq81340sc MACH_IQ81340SC IQ81340SC 799
+iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800
+iq81340mc MACH_IQ81340MC IQ81340MC 801
+iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802
+iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803
+mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804
+cybertracker_i MACH_CYBERTRACKER_I CYBERTRACKER_I 805
+gesbc931x MACH_GESBC931X GESBC931X 806
+centipad MACH_CENTIPAD CENTIPAD 807
+armsoc MACH_ARMSOC ARMSOC 808
+se4200 MACH_SE4200 SE4200 809
+ems197a MACH_EMS197A EMS197A 810
+micro9 MACH_MICRO9 MICRO9 811
+micro9l MACH_MICRO9L MICRO9L 812
+uc5471dsp MACH_UC5471DSP UC5471DSP 813
+sj5471eng MACH_SJ5471ENG SJ5471ENG 814
+none MACH_CMPXA26X CMPXA26X 815
+nc1 MACH_NC NC 816
+omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817
+ajax52x MACH_AJAX52X AJAX52X 818
+siriustar MACH_SIRIUSTAR SIRIUSTAR 819
+iodata_hdlg MACH_IODATA_HDLG IODATA_HDLG 820
+at91rm9200utl MACH_AT91RM9200UTL AT91RM9200UTL 821
+biosafe MACH_BIOSAFE BIOSAFE 822
+mp1000 MACH_MP1000 MP1000 823
+parsy MACH_PARSY PARSY 824
+ccxp270 MACH_CCXP CCXP 825
+omap_gsample MACH_OMAP_GSAMPLE OMAP_GSAMPLE 826
+realview_eb MACH_REALVIEW_EB REALVIEW_EB 827
+samoa MACH_SAMOA SAMOA 828
+palmt3 MACH_PALMT3 PALMT3 829
+i878 MACH_I878 I878 830
+borzoi MACH_BORZOI BORZOI 831
+gecko MACH_GECKO GECKO 832
+ds101 MACH_DS101 DS101 833
+omap_palmtt2 MACH_OMAP_PALMTT2 OMAP_PALMTT2 834
+palmld MACH_PALMLD PALMLD 835
+cc9c MACH_CC9C CC9C 836
+sbc1670 MACH_SBC1670 SBC1670 837
+ixdp28x5 MACH_IXDP28X5 IXDP28X5 838
+omap_palmtt MACH_OMAP_PALMTT OMAP_PALMTT 839
+ml696k MACH_ML696K ML696K 840
+arcom_zeus MACH_ARCOM_ZEUS ARCOM_ZEUS 841
+osiris MACH_OSIRIS OSIRIS 842
+maestro MACH_MAESTRO MAESTRO 843
+palmte2 MACH_PALMTE2 PALMTE2 844
+ixbbm MACH_IXBBM IXBBM 845
+mx27ads MACH_MX27ADS MX27ADS 846
+ax8004 MACH_AX8004 AX8004 847
+at91sam9261ek MACH_AT91SAM9261EK AT91SAM9261EK 848
+loft MACH_LOFT LOFT 849
+magpie MACH_MAGPIE MAGPIE 850
+mx21ads MACH_MX21ADS MX21ADS 851
+mb87m3400 MACH_MB87M3400 MB87M3400 852
+mguard_delta MACH_MGUARD_DELTA MGUARD_DELTA 853
+davinci_dvdp MACH_DAVINCI_DVDP DAVINCI_DVDP 854
+htcuniversal MACH_HTCUNIVERSAL HTCUNIVERSAL 855
+tpad MACH_TPAD TPAD 856
+roverp3 MACH_ROVERP3 ROVERP3 857
+jornada928 MACH_JORNADA928 JORNADA928 858
+mv88fxx81 MACH_MV88FXX81 MV88FXX81 859
+stmp36xx MACH_STMP36XX STMP36XX 860
+sxni79524 MACH_SXNI79524 SXNI79524 861
+ams_delta MACH_AMS_DELTA AMS_DELTA 862
+uranium MACH_URANIUM URANIUM 863
+ucon MACH_UCON UCON 864
+nas100d MACH_NAS100D NAS100D 865
+l083 MACH_L083_1000 L083_1000 866
+ezx MACH_EZX EZX 867
+pnx5220 MACH_PNX5220 PNX5220 868
+butte MACH_BUTTE BUTTE 869
+srm2 MACH_SRM2 SRM2 870
+dsbr MACH_DSBR DSBR 871
+crystalball MACH_CRYSTALBALL CRYSTALBALL 872
+tinypxa27x MACH_TINYPXA27X TINYPXA27X 873
+herbie MACH_HERBIE HERBIE 874
+magician MACH_MAGICIAN MAGICIAN 875
+cm4002 MACH_CM4002 CM4002 876
+b4 MACH_B4 B4 877
+maui MACH_MAUI MAUI 878
+cybertracker_g MACH_CYBERTRACKER_G CYBERTRACKER_G 879
+nxdkn MACH_NXDKN NXDKN 880
+mio8390 MACH_MIO8390 MIO8390 881
+omi_board MACH_OMI_BOARD OMI_BOARD 882
+mx21civ MACH_MX21CIV MX21CIV 883
+mahi_cdac MACH_MAHI_CDAC MAHI_CDAC 884
+palmtx MACH_PALMTX PALMTX 885
+s3c2413 MACH_S3C2413 S3C2413 887
+samsys_ep0 MACH_SAMSYS_EP0 SAMSYS_EP0 888
+wg302v1 MACH_WG302V1 WG302V1 889
+wg302v2 MACH_WG302V2 WG302V2 890
+eb42x MACH_EB42X EB42X 891
+iq331es MACH_IQ331ES IQ331ES 892
+cosydsp MACH_COSYDSP COSYDSP 893
+uplat7d_proto MACH_UPLAT7D UPLAT7D 894
+ptdavinci MACH_PTDAVINCI PTDAVINCI 895
+mbus MACH_MBUS MBUS 896
+nadia2vb MACH_NADIA2VB NADIA2VB 897
+r1000 MACH_R1000 R1000 898
+hw90250 MACH_HW90250 HW90250 899
+omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900
+davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901
+omap_tornado MACH_OMAP_TORNADO OMAP_TORNADO 902
+olocreek MACH_OLOCREEK OLOCREEK 903
+palmz72 MACH_PALMZ72 PALMZ72 904
+nxdb500 MACH_NXDB500 NXDB500 905
+apf9328 MACH_APF9328 APF9328 906
+omap_wipoq MACH_OMAP_WIPOQ OMAP_WIPOQ 907
+omap_twip MACH_OMAP_TWIP OMAP_TWIP 908
+treo650 MACH_TREO650 TREO650 909
+acumen MACH_ACUMEN ACUMEN 910
+xp100 MACH_XP100 XP100 911
+fs2410 MACH_FS2410 FS2410 912
+pxa270_cerf MACH_PXA270_CERF PXA270_CERF 913
+sq2ftlpalm MACH_SQ2FTLPALM SQ2FTLPALM 914
+bsemserver MACH_BSEMSERVER BSEMSERVER 915
+netclient MACH_NETCLIENT NETCLIENT 916
+palmt5 MACH_PALMT5 PALMT5 917
+palmtc MACH_PALMTC PALMTC 918
+omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919
+mxc30030evb MACH_MXC30030EVB MXC30030EVB 920
+rea_cpu2 MACH_REA_2D REA_2D 921
+eti3e524 MACH_TI3E524 TI3E524 922
+ateb9200 MACH_ATEB9200 ATEB9200 923
+auckland MACH_AUCKLAND AUCKLAND 924
+ak3220m MACH_AK3320M AK3320M 925
+duramax MACH_DURAMAX DURAMAX 926
+n35 MACH_N35 N35 927
+pronghorn MACH_PRONGHORN PRONGHORN 928
+fundy MACH_FUNDY FUNDY 929
+logicpd_pxa270 MACH_LOGICPD_PXA270 LOGICPD_PXA270 930
+cpu777 MACH_CPU777 CPU777 931
+simicon9201 MACH_SIMICON9201 SIMICON9201 932
+leap2_hpm MACH_LEAP2_HPM LEAP2_HPM 933
+cm922txa10 MACH_CM922TXA10 CM922TXA10 934
+sandgate MACH_PXA PXA 935
+sandgate2 MACH_SANDGATE2 SANDGATE2 936
+sandgate2g MACH_SANDGATE2G SANDGATE2G 937
+sandgate2p MACH_SANDGATE2P SANDGATE2P 938
+fred_jack MACH_FRED_JACK FRED_JACK 939
+ttg_color1 MACH_TTG_COLOR1 TTG_COLOR1 940
+nxeb500hmi MACH_NXEB500HMI NXEB500HMI 941
+netdcu8 MACH_NETDCU8 NETDCU8 942
+ng_fvx538 MACH_NG_FVX538 NG_FVX538 944
+ng_fvs338 MACH_NG_FVS338 NG_FVS338 945
+pnx4103 MACH_PNX4103 PNX4103 946
+hesdb MACH_HESDB HESDB 947
+xsilo MACH_XSILO XSILO 948
+espresso MACH_ESPRESSO ESPRESSO 949
+emlc MACH_EMLC EMLC 950
+sisteron MACH_SISTERON SISTERON 951
+rx1950 MACH_RX1950 RX1950 952
+tsc_venus MACH_TSC_VENUS TSC_VENUS 953
+ds101j MACH_DS101J DS101J 954
+mxc30030ads MACH_MXC30030ADS MXC30030ADS 955
+fujitsu_wimaxsoc MACH_FUJITSU_WIMAXSOC FUJITSU_WIMAXSOC 956
+dualpcmodem MACH_DUALPCMODEM DUALPCMODEM 957
+gesbc9312 MACH_GESBC9312 GESBC9312 958
+htcapache MACH_HTCAPACHE HTCAPACHE 959
+ixdp435 MACH_IXDP435 IXDP435 960
+catprovt100 MACH_CATPROVT100 CATPROVT100 961
+picotux1xx MACH_PICOTUX1XX PICOTUX1XX 962
+picotux2xx MACH_PICOTUX2XX PICOTUX2XX 963
+dsmg600 MACH_DSMG600 DSMG600 964
+empc2 MACH_EMPC2 EMPC2 965
+ventura MACH_VENTURA VENTURA 966
+phidget_sbc MACH_PHIDGET_SBC PHIDGET_SBC 967
+ij3k MACH_IJ3K IJ3K 968
+pisgah MACH_PISGAH PISGAH 969
+omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970
+sg720 MACH_SG720 SG720 971
+redfox MACH_REDFOX REDFOX 972
+mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973
+tpf106 MACH_TPF106 TPF106 974
+at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975
+rcmt2 MACH_SLEDB SLEDB 976
+ontrack MACH_ONTRACK ONTRACK 977
+pm1200 MACH_PM1200 PM1200 978
+ess24562 MACH_ESS24XXX ESS24XXX 979
+coremp7 MACH_COREMP7 COREMP7 980
+nexcoder_6446 MACH_NEXCODER_6446 NEXCODER_6446 981
+stvc8380 MACH_STVC8380 STVC8380 982
+teklynx MACH_TEKLYNX TEKLYNX 983
+carbonado MACH_CARBONADO CARBONADO 984
+sysmos_mp730 MACH_SYSMOS_MP730 SYSMOS_MP730 985
+snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986
+pgigim MACH_PGIGIM PGIGIM 987
+ptx9160p2 MACH_PTX9160P2 PTX9160P2 988
+dcore1 MACH_DCORE1 DCORE1 989
+victorpxa MACH_VICTORPXA VICTORPXA 990
+mx2dtb MACH_MX2DTB MX2DTB 991
+pxa_irex_er0100 MACH_PXA_IREX_ER0100 PXA_IREX_ER0100 992
+omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993
+bartec_deg MACH_BARTEC_DEG BARTEC_DEG 994
+hw50251 MACH_HW50251 HW50251 995
+ibox MACH_IBOX IBOX 996
+atlaslh7a404 MACH_ATLASLH7A404 ATLASLH7A404 997
+pt2026 MACH_PT2026 PT2026 998
+htcalpine MACH_HTCALPINE HTCALPINE 999
+bartec_vtu MACH_BARTEC_VTU BARTEC_VTU 1000
+vcoreii MACH_VCOREII VCOREII 1001
+pdnb3 MACH_PDNB3 PDNB3 1002
+htcbeetles MACH_HTCBEETLES HTCBEETLES 1003
+s3c6400 MACH_S3C6400 S3C6400 1004
+s3c2443 MACH_S3C2443 S3C2443 1005
+omap_ldk MACH_OMAP_LDK OMAP_LDK 1006
+smdk2460 MACH_SMDK2460 SMDK2460 1007
+smdk2440 MACH_SMDK2440 SMDK2440 1008
+smdk2412 MACH_SMDK2412 SMDK2412 1009
+webbox MACH_WEBBOX WEBBOX 1010
+cwwndp MACH_CWWNDP CWWNDP 1011
+i839 MACH_DRAGON DRAGON 1012
+opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013
+ccm2200 MACH_CCM2200 CCM2200 1014
+etwarm MACH_ETWARM ETWARM 1015
+m93030 MACH_M93030 M93030 1016
+cc7u MACH_CC7U CC7U 1017
+mtt_ranger MACH_MTT_RANGER MTT_RANGER 1018
+nexus MACH_NEXUS NEXUS 1019
+desman MACH_DESMAN DESMAN 1020
+bkde303 MACH_BKDE303 BKDE303 1021
+smdk2413 MACH_SMDK2413 SMDK2413 1022
+aml_m7200 MACH_AML_M7200 AML_M7200 1023
+aml_m5900 MACH_AML_M5900 AML_M5900 1024
+sg640 MACH_SG640 SG640 1025
+edg79524 MACH_EDG79524 EDG79524 1026
+ai2410 MACH_AI2410 AI2410 1027
+ixp465 MACH_IXP465 IXP465 1028
+balloon3 MACH_BALLOON3 BALLOON3 1029
+heins MACH_HEINS HEINS 1030
+mpluseva MACH_MPLUSEVA MPLUSEVA 1031
+rt042 MACH_RT042 RT042 1032
+cwiem MACH_CWIEM CWIEM 1033
+cm_x270 MACH_CM_X270 CM_X270 1034
+cm_x255 MACH_CM_X255 CM_X255 1035
+esh_at91 MACH_ESH_AT91 ESH_AT91 1036
+sandgate3 MACH_SANDGATE3 SANDGATE3 1037
+primo MACH_PRIMO PRIMO 1038
+gemstone MACH_GEMSTONE GEMSTONE 1039
+pronghorn_metro MACH_PRONGHORNMETRO PRONGHORNMETRO 1040
+sidewinder MACH_SIDEWINDER SIDEWINDER 1041
+picomod1 MACH_PICOMOD1 PICOMOD1 1042
+sg590 MACH_SG590 SG590 1043
+akai9307 MACH_AKAI9307 AKAI9307 1044
+fontaine MACH_FONTAINE FONTAINE 1045
+wombat MACH_WOMBAT WOMBAT 1046
+acq300 MACH_ACQ300 ACQ300 1047
+mod272 MACH_MOD_270 MOD_270 1048
+vmc_vc0820 MACH_VC0820 VC0820 1049
+ani_aim MACH_ANI_AIM ANI_AIM 1050
+jellyfish MACH_JELLYFISH JELLYFISH 1051
+amanita MACH_AMANITA AMANITA 1052
+vlink MACH_VLINK VLINK 1053
+dexflex MACH_DEXFLEX DEXFLEX 1054
+eigen_ttq MACH_EIGEN_TTQ EIGEN_TTQ 1055
+arcom_titan MACH_ARCOM_TITAN ARCOM_TITAN 1056
+tabla MACH_TABLA TABLA 1057
+mdirac3 MACH_MDIRAC3 MDIRAC3 1058
+mrhfbp2 MACH_MRHFBP2 MRHFBP2 1059
+at91rm9200rb MACH_AT91RM9200RB AT91RM9200RB 1060
+ani_apm MACH_ANI_APM ANI_APM 1061
+ella1 MACH_ELLA1 ELLA1 1062
+inhand_pxa27x MACH_INHAND_PXA27X INHAND_PXA27X 1063
+inhand_pxa25x MACH_INHAND_PXA25X INHAND_PXA25X 1064
+empos_xm MACH_EMPOS_XM EMPOS_XM 1065
+empos MACH_EMPOS EMPOS 1066
+empos_tiny MACH_EMPOS_TINY EMPOS_TINY 1067
+empos_sm MACH_EMPOS_SM EMPOS_SM 1068
+egret MACH_EGRET EGRET 1069
+ostrich MACH_OSTRICH OSTRICH 1070
+n50 MACH_N50 N50 1071
+ecbat91 MACH_ECBAT91 ECBAT91 1072
+stareast MACH_STAREAST STAREAST 1073
+dspg_dw MACH_DSPG_DW DSPG_DW 1074
+onearm MACH_ONEARM ONEARM 1075
+mrg110_6 MACH_MRG110_6 MRG110_6 1076
+wrt300nv2 MACH_WRT300NV2 WRT300NV2 1077
+xm_bulverde MACH_XM_BULVERDE XM_BULVERDE 1078
+msm6100 MACH_MSM6100 MSM6100 1079
+eti_b1 MACH_ETI_B1 ETI_B1 1080
+za9l_series MACH_ZILOG_ZA9L ZILOG_ZA9L 1081
+bit2440 MACH_BIT2440 BIT2440 1082
+nbi MACH_NBI NBI 1083
+smdk2443 MACH_SMDK2443 SMDK2443 1084
+vdavinci MACH_VDAVINCI VDAVINCI 1085
+atc6 MACH_ATC6 ATC6 1086
+multmdw MACH_MULTMDW MULTMDW 1087
+mba2440 MACH_MBA2440 MBA2440 1088
+ecsd MACH_ECSD ECSD 1089
+palmz31 MACH_PALMZ31 PALMZ31 1090
+fsg MACH_FSG FSG 1091
+razor101 MACH_RAZOR101 RAZOR101 1092
+opera_tdm MACH_OPERA_TDM OPERA_TDM 1093
+comcerto MACH_COMCERTO COMCERTO 1094
+tb0319 MACH_TB0319 TB0319 1095
+kws8000 MACH_KWS8000 KWS8000 1096
+b2 MACH_B2 B2 1097
+lcl54 MACH_LCL54 LCL54 1098
+at91sam9260ek MACH_AT91SAM9260EK AT91SAM9260EK 1099
+glantank MACH_GLANTANK GLANTANK 1100
+n2100 MACH_N2100 N2100 1101
+n4100 MACH_N4100 N4100 1102
+rsc4 MACH_VERTICAL_RSC4 VERTICAL_RSC4 1103
+sg8100 MACH_SG8100 SG8100 1104
+im42xx MACH_IM42XX IM42XX 1105
+ftxx MACH_FTXX FTXX 1106
+lwfusion MACH_LWFUSION LWFUSION 1107
+qt2410 MACH_QT2410 QT2410 1108
+kixrp435 MACH_KIXRP435 KIXRP435 1109
+ccw9c MACH_CCW9C CCW9C 1110
+dabhs MACH_DABHS DABHS 1111
+gzmx MACH_GZMX GZMX 1112
+ipnw100ap MACH_IPNW100AP IPNW100AP 1113
+cc9p9360dev MACH_CC9P9360DEV CC9P9360DEV 1114
+cc9p9750dev MACH_CC9P9750DEV CC9P9750DEV 1115
+cc9p9360val MACH_CC9P9360VAL CC9P9360VAL 1116
+cc9p9750val MACH_CC9P9750VAL CC9P9750VAL 1117
+nx70v MACH_NX70V NX70V 1118
+at91rm9200df MACH_AT91RM9200DF AT91RM9200DF 1119
+se_pilot2 MACH_SE_PILOT2 SE_PILOT2 1120
+mtcn_t800 MACH_MTCN_T800 MTCN_T800 1121
+vcmx212 MACH_VCMX212 VCMX212 1122
+lynx MACH_LYNX LYNX 1123
+at91sam9260id MACH_AT91SAM9260ID AT91SAM9260ID 1124
+hw86052 MACH_HW86052 HW86052 1125
+pilz_pmi3 MACH_PILZ_PMI3 PILZ_PMI3 1126
+edb9302a MACH_EDB9302A EDB9302A 1127
+edb9307a MACH_EDB9307A EDB9307A 1128
+ct_dfs MACH_CT_DFS CT_DFS 1129
+pilz_pmi4 MACH_PILZ_PMI4 PILZ_PMI4 1130
+xceednp_ixp MACH_XCEEDNP_IXP XCEEDNP_IXP 1131
+smdk2442b MACH_SMDK2442B SMDK2442B 1132
+xnode MACH_XNODE XNODE 1133
+aidx270 MACH_AIDX270 AIDX270 1134
+rema MACH_REMA REMA 1135
+bps1000 MACH_BPS1000 BPS1000 1136
+hw90350 MACH_HW90350 HW90350 1137
+omap_3430sdp MACH_OMAP_3430SDP OMAP_3430SDP 1138
+bluetouch MACH_BLUETOUCH BLUETOUCH 1139
+vstms MACH_VSTMS VSTMS 1140
+xsbase270 MACH_XSBASE270 XSBASE270 1141
+at91sam9260ek_cn MACH_AT91SAM9260EK_CN AT91SAM9260EK_CN 1142
+adsturboxb MACH_ADSTURBOXB ADSTURBOXB 1143
+oti4110 MACH_OTI4110 OTI4110 1144
+hme_pxa MACH_HME_PXA HME_PXA 1145
+deisterdca MACH_DEISTERDCA DEISTERDCA 1146
+ces_ssem2 MACH_CES_SSEM2 CES_SSEM2 1147
+ces_mtr MACH_CES_MTR CES_MTR 1148
+tds_avng_sbc MACH_TDS_AVNG_SBC TDS_AVNG_SBC 1149
+everest MACH_EVEREST EVEREST 1150
+pnx4010 MACH_PNX4010 PNX4010 1151
+oxnas MACH_OXNAS OXNAS 1152
+fiori MACH_FIORI FIORI 1153
+ml1200 MACH_ML1200 ML1200 1154
+pecos MACH_PECOS PECOS 1155
+nb2xxx MACH_NB2XXX NB2XXX 1156
+hw6900 MACH_HW6900 HW6900 1157
+cdcs_quoll MACH_CDCS_QUOLL CDCS_QUOLL 1158
+quicksilver MACH_QUICKSILVER QUICKSILVER 1159
+uplat926 MACH_UPLAT926 UPLAT926 1160
+dep2410_dep2410 MACH_DEP2410_THOMAS DEP2410_THOMAS 1161
+dtk2410 MACH_DTK2410 DTK2410 1162
+chili MACH_CHILI CHILI 1163
+demeter MACH_DEMETER DEMETER 1164
+dionysus MACH_DIONYSUS DIONYSUS 1165
+as352x MACH_AS352X AS352X 1166
+service MACH_SERVICE SERVICE 1167
+cs_e9301 MACH_CS_E9301 CS_E9301 1168
+micro9m MACH_MICRO9M MICRO9M 1169
+ia_mospck MACH_IA_MOSPCK IA_MOSPCK 1170
+ql201b MACH_QL201B QL201B 1171
+bbm MACH_BBM BBM 1174
+exxx MACH_EXXX EXXX 1175
+wma11b MACH_WMA11B WMA11B 1176
+pelco_atlas MACH_PELCO_ATLAS PELCO_ATLAS 1177
+g500 MACH_G500 G500 1178
+bug MACH_BUG BUG 1179
+mx33ads MACH_MX33ADS MX33ADS 1180
+chub MACH_CHUB CHUB 1181
+neo1973_gta01 MACH_NEO1973_GTA01 NEO1973_GTA01 1182
+w90n740 MACH_W90N740 W90N740 1183
+medallion_sa2410 MACH_MEDALLION_SA2410 MEDALLION_SA2410 1184
+ia_cpu_9200_2 MACH_IA_CPU_9200_2 IA_CPU_9200_2 1185
+dimmrm9200 MACH_DIMMRM9200 DIMMRM9200 1186
+pm9261 MACH_PM9261 PM9261 1187
+ml7304 MACH_ML7304 ML7304 1189
+ucp250 MACH_UCP250 UCP250 1190
+intboard MACH_INTBOARD INTBOARD 1191
+gulfstream MACH_GULFSTREAM GULFSTREAM 1192
+labquest MACH_LABQUEST LABQUEST 1193
+vcmx313 MACH_VCMX313 VCMX313 1194
+urg200 MACH_URG200 URG200 1195
+cpux255lcdnet MACH_CPUX255LCDNET CPUX255LCDNET 1196
+netdcu9 MACH_NETDCU9 NETDCU9 1197
+netdcu10 MACH_NETDCU10 NETDCU10 1198
+dspg_dga MACH_DSPG_DGA DSPG_DGA 1199
+dspg_dvw MACH_DSPG_DVW DSPG_DVW 1200
+solos MACH_SOLOS SOLOS 1201
+at91sam9263ek MACH_AT91SAM9263EK AT91SAM9263EK 1202
+osstbox MACH_OSSTBOX OSSTBOX 1203
+kbat9261 MACH_KBAT9261 KBAT9261 1204
+ct1100 MACH_CT1100 CT1100 1205
+akcppxa MACH_AKCPPXA AKCPPXA 1206
+ochaya1020 MACH_OCHAYA1020 OCHAYA1020 1207
+hitrack MACH_HITRACK HITRACK 1208
+syme1 MACH_SYME1 SYME1 1209
+syhl1 MACH_SYHL1 SYHL1 1210
+empca400 MACH_EMPCA400 EMPCA400 1211
+em7210 MACH_EM7210 EM7210 1212
+htchermes MACH_HTCHERMES HTCHERMES 1213
+eti_c1 MACH_ETI_C1 ETI_C1 1214
+ac100 MACH_AC100 AC100 1216
+sneetch MACH_SNEETCH SNEETCH 1217
+studentmate MACH_STUDENTMATE STUDENTMATE 1218
+zir2410 MACH_ZIR2410 ZIR2410 1219
+zir2413 MACH_ZIR2413 ZIR2413 1220
+dlonip3 MACH_DLONIP3 DLONIP3 1221
+instream MACH_INSTREAM INSTREAM 1222
+ambarella MACH_AMBARELLA AMBARELLA 1223
+nevis MACH_NEVIS NEVIS 1224
+htc_trinity MACH_HTC_TRINITY HTC_TRINITY 1225
+ql202b MACH_QL202B QL202B 1226
+vpac270 MACH_VPAC270 VPAC270 1227
+rd129 MACH_RD129 RD129 1228
+htcwizard MACH_HTCWIZARD HTCWIZARD 1229
+treo680 MACH_TREO680 TREO680 1230
+tecon_tmezon MACH_TECON_TMEZON TECON_TMEZON 1231
+zylonite MACH_ZYLONITE ZYLONITE 1233
+gene1270 MACH_GENE1270 GENE1270 1234
+zir2412 MACH_ZIR2412 ZIR2412 1235
+mx31lite MACH_MX31LITE MX31LITE 1236
+t700wx MACH_T700WX T700WX 1237
+vf100 MACH_VF100 VF100 1238
+nsb2 MACH_NSB2 NSB2 1239
+nxhmi_bb MACH_NXHMI_BB NXHMI_BB 1240
+nxhmi_re MACH_NXHMI_RE NXHMI_RE 1241
+n4100pro MACH_N4100PRO N4100PRO 1242
+sam9260 MACH_SAM9260 SAM9260 1243
+omap_treo600 MACH_OMAP_TREO600 OMAP_TREO600 1244
+indy2410 MACH_INDY2410 INDY2410 1245
+nelt_a MACH_NELT_A NELT_A 1246
+n311 MACH_N311 N311 1248
+at91sam9260vgk MACH_AT91SAM9260VGK AT91SAM9260VGK 1249
+at91leppe MACH_AT91LEPPE AT91LEPPE 1250
+at91lepccn MACH_AT91LEPCCN AT91LEPCCN 1251
+apc7100 MACH_APC7100 APC7100 1252
+stargazer MACH_STARGAZER STARGAZER 1253
+sonata MACH_SONATA SONATA 1254
+schmoogie MACH_SCHMOOGIE SCHMOOGIE 1255
+aztool MACH_AZTOOL AZTOOL 1256
+mioa701 MACH_MIOA701 MIOA701 1257
+sxni9260 MACH_SXNI9260 SXNI9260 1258
+mxc27520evb MACH_MXC27520EVB MXC27520EVB 1259
+armadillo5x0 MACH_ARMADILLO5X0 ARMADILLO5X0 1260
+mb9260 MACH_MB9260 MB9260 1261
+mb9263 MACH_MB9263 MB9263 1262
+ipac9302 MACH_IPAC9302 IPAC9302 1263
+cc9p9360js MACH_CC9P9360JS CC9P9360JS 1264
+gallium MACH_GALLIUM GALLIUM 1265
+msc2410 MACH_MSC2410 MSC2410 1266
+ghi270 MACH_GHI270 GHI270 1267
+davinci_leonardo MACH_DAVINCI_LEONARDO DAVINCI_LEONARDO 1268
+oiab MACH_OIAB OIAB 1269
+smdk6400 MACH_SMDK6400 SMDK6400 1270
+nokia_n800 MACH_NOKIA_N800 NOKIA_N800 1271
+greenphone MACH_GREENPHONE GREENPHONE 1272
+compex42x MACH_COMPEXWP18 COMPEXWP18 1273
+xmate MACH_XMATE XMATE 1274
+energizer MACH_ENERGIZER ENERGIZER 1275
+ime1 MACH_IME1 IME1 1276
+sweda_tms MACH_SWEDATMS SWEDATMS 1277
+ntnp435c MACH_NTNP435C NTNP435C 1278
+spectro2 MACH_SPECTRO2 SPECTRO2 1279
+h6039 MACH_H6039 H6039 1280
+ep80219 MACH_EP80219 EP80219 1281
+samoa_ii MACH_SAMOA_II SAMOA_II 1282
+cwmxl MACH_CWMXL CWMXL 1283
+as9200 MACH_AS9200 AS9200 1284
+sfx1149 MACH_SFX1149 SFX1149 1285
+navi010 MACH_NAVI010 NAVI010 1286
+multmdp MACH_MULTMDP MULTMDP 1287
+scb9520 MACH_SCB9520 SCB9520 1288
+htcathena MACH_HTCATHENA HTCATHENA 1289
+xp179 MACH_XP179 XP179 1290
+h4300 MACH_H4300 H4300 1291
+goramo_mlr MACH_GORAMO_MLR GORAMO_MLR 1292
+mxc30020evb MACH_MXC30020EVB MXC30020EVB 1293
+adsbitsyg5 MACH_ADSBITSYG5 ADSBITSYG5 1294
+adsportalplus MACH_ADSPORTALPLUS ADSPORTALPLUS 1295
+mmsp2plus MACH_MMSP2PLUS MMSP2PLUS 1296
+em_x270 MACH_EM_X270 EM_X270 1297
+tpp302 MACH_TPP302 TPP302 1298
+tpp104 MACH_TPM104 TPM104 1299
+tpm102 MACH_TPM102 TPM102 1300
+tpm109 MACH_TPM109 TPM109 1301
+fbxo1 MACH_FBXO1 FBXO1 1302
+hxd8 MACH_HXD8 HXD8 1303
+neo1973_gta02 MACH_NEO1973_GTA02 NEO1973_GTA02 1304
+emtest MACH_EMTEST EMTEST 1305
+ad6900 MACH_AD6900 AD6900 1306
+europa MACH_EUROPA EUROPA 1307
+metroconnect MACH_METROCONNECT METROCONNECT 1308
+ez_s2410 MACH_EZ_S2410 EZ_S2410 1309
+ez_s2440 MACH_EZ_S2440 EZ_S2440 1310
+ez_ep9312 MACH_EZ_EP9312 EZ_EP9312 1311
+ez_ep9315 MACH_EZ_EP9315 EZ_EP9315 1312
+ez_x7 MACH_EZ_X7 EZ_X7 1313
+godotdb MACH_GODOTDB GODOTDB 1314
+mistral MACH_MISTRAL MISTRAL 1315
+msm MACH_MSM MSM 1316
+ct5910 MACH_CT5910 CT5910 1317
+ct5912 MACH_CT5912 CT5912 1318
+argonst_mp MACH_HYNET_INE HYNET_INE 1319
+hynet_app MACH_HYNET_APP HYNET_APP 1320
+msm7200 MACH_MSM7200 MSM7200 1321
+msm7600 MACH_MSM7600 MSM7600 1322
+ceb255 MACH_CEB255 CEB255 1323
+ciel MACH_CIEL CIEL 1324
+slm5650 MACH_SLM5650 SLM5650 1325
+at91sam9rlek MACH_AT91SAM9RLEK AT91SAM9RLEK 1326
+comtech_router MACH_COMTECH_ROUTER COMTECH_ROUTER 1327
+sbc2410x MACH_SBC2410X SBC2410X 1328
+at4x0bd MACH_AT4X0BD AT4X0BD 1329
+cbifr MACH_CBIFR CBIFR 1330
+arcom_quantum MACH_ARCOM_QUANTUM ARCOM_QUANTUM 1331
+matrix520 MACH_MATRIX520 MATRIX520 1332
+matrix510 MACH_MATRIX510 MATRIX510 1333
+matrix500 MACH_MATRIX500 MATRIX500 1334
+m501 MACH_M501 M501 1335
+aaeon1270 MACH_AAEON1270 AAEON1270 1336
+matrix500ev MACH_MATRIX500EV MATRIX500EV 1337
+pac500 MACH_PAC500 PAC500 1338
+pnx8181 MACH_PNX8181 PNX8181 1339
+colibri320 MACH_COLIBRI320 COLIBRI320 1340
+aztoolbb MACH_AZTOOLBB AZTOOLBB 1341
+aztoolg2 MACH_AZTOOLG2 AZTOOLG2 1342
+dvlhost MACH_DVLHOST DVLHOST 1343
+zir9200 MACH_ZIR9200 ZIR9200 1344
+zir9260 MACH_ZIR9260 ZIR9260 1345
+cocopah MACH_COCOPAH COCOPAH 1346
+nds MACH_NDS NDS 1347
+rosencrantz MACH_ROSENCRANTZ ROSENCRANTZ 1348
+fttx_odsc MACH_FTTX_ODSC FTTX_ODSC 1349
+classe_r6904 MACH_CLASSE_R6904 CLASSE_R6904 1350
+cam60 MACH_CAM60 CAM60 1351
+mxc30031ads MACH_MXC30031ADS MXC30031ADS 1352
+datacall MACH_DATACALL DATACALL 1353
+at91eb01 MACH_AT91EB01 AT91EB01 1354
+rty MACH_RTY RTY 1355
+dwl2100 MACH_DWL2100 DWL2100 1356
+vinsi MACH_VINSI VINSI 1357
+db88f5281 MACH_DB88F5281 DB88F5281 1358
+csb726 MACH_CSB726 CSB726 1359
+tik27 MACH_TIK27 TIK27 1360
+mx_uc7420 MACH_MX_UC7420 MX_UC7420 1361
+rirm3 MACH_RIRM3 RIRM3 1362
+pelco_odyssey MACH_PELCO_ODYSSEY PELCO_ODYSSEY 1363
+adx_abox MACH_ADX_ABOX ADX_ABOX 1365
+adx_tpid MACH_ADX_TPID ADX_TPID 1366
+minicheck MACH_MINICHECK MINICHECK 1367
+idam MACH_IDAM IDAM 1368
+mario_mx MACH_MARIO_MX MARIO_MX 1369
+vi1888 MACH_VI1888 VI1888 1370
+zr4230 MACH_ZR4230 ZR4230 1371
+t1_ix_blue MACH_T1_IX_BLUE T1_IX_BLUE 1372
+syhq2 MACH_SYHQ2 SYHQ2 1373
+computime_r3 MACH_COMPUTIME_R3 COMPUTIME_R3 1374
+oratis MACH_ORATIS ORATIS 1375
+mikko MACH_MIKKO MIKKO 1376
+holon MACH_HOLON HOLON 1377
+olip8 MACH_OLIP8 OLIP8 1378
+ghi270hg MACH_GHI270HG GHI270HG 1379
+davinci_dm6467_evm MACH_DAVINCI_DM6467_EVM DAVINCI_DM6467_EVM 1380
+davinci_dm355_evm MACH_DAVINCI_DM355_EVM DAVINCI_DM355_EVM 1381
+blackriver MACH_BLACKRIVER BLACKRIVER 1383
+sandgate_wp MACH_SANDGATEWP SANDGATEWP 1384
+cdotbwsg MACH_CDOTBWSG CDOTBWSG 1385
+quark963 MACH_QUARK963 QUARK963 1386
+csb735 MACH_CSB735 CSB735 1387
+littleton MACH_LITTLETON LITTLETON 1388
+mio_p550 MACH_MIO_P550 MIO_P550 1389
+motion2440 MACH_MOTION2440 MOTION2440 1390
+imm500 MACH_IMM500 IMM500 1391
+homematic MACH_HOMEMATIC HOMEMATIC 1392
+ermine MACH_ERMINE ERMINE 1393
+kb9202b MACH_KB9202B KB9202B 1394
+hs1xx MACH_HS1XX HS1XX 1395
+studentmate2440 MACH_STUDENTMATE2440 STUDENTMATE2440 1396
+arvoo_l1_z1 MACH_ARVOO_L1_Z1 ARVOO_L1_Z1 1397
+dep2410k MACH_DEP2410K DEP2410K 1398
+xxsvideo MACH_XXSVIDEO XXSVIDEO 1399
+im4004 MACH_IM4004 IM4004 1400
+ochaya1050 MACH_OCHAYA1050 OCHAYA1050 1401
+lep9261 MACH_LEP9261 LEP9261 1402
+svenmeb MACH_SVENMEB SVENMEB 1403
+fortunet2ne MACH_FORTUNET2NE FORTUNET2NE 1404
+nxhx MACH_NXHX NXHX 1406
+realview_pb11mp MACH_REALVIEW_PB11MP REALVIEW_PB11MP 1407
+ids500 MACH_IDS500 IDS500 1408
+ors_n725 MACH_ORS_N725 ORS_N725 1409
+hsdarm MACH_HSDARM HSDARM 1410
+sha_pon003 MACH_SHA_PON003 SHA_PON003 1411
+sha_pon004 MACH_SHA_PON004 SHA_PON004 1412
+sha_pon007 MACH_SHA_PON007 SHA_PON007 1413
+sha_pon011 MACH_SHA_PON011 SHA_PON011 1414
+h6042 MACH_H6042 H6042 1415
+h6043 MACH_H6043 H6043 1416
+looxc550 MACH_LOOXC550 LOOXC550 1417
+cnty_titan MACH_CNTY_TITAN CNTY_TITAN 1418
+app3xx MACH_APP3XX APP3XX 1419
+sideoatsgrama MACH_SIDEOATSGRAMA SIDEOATSGRAMA 1420
+treo700p MACH_TREO700P TREO700P 1421
+treo700w MACH_TREO700W TREO700W 1422
+treo750 MACH_TREO750 TREO750 1423
+treo755p MACH_TREO755P TREO755P 1424
+ezreganut9200 MACH_EZREGANUT9200 EZREGANUT9200 1425
+sarge MACH_SARGE SARGE 1426
+a696 MACH_A696 A696 1427
+turtle1916 MACH_TURTLE TURTLE 1428
+mx27_3ds MACH_MX27_3DS MX27_3DS 1430
+bishop MACH_BISHOP BISHOP 1431
+pxx MACH_PXX PXX 1432
+redwood MACH_REDWOOD REDWOOD 1433
+omap_2430dlp MACH_OMAP_2430DLP OMAP_2430DLP 1436
+omap_2430osk MACH_OMAP_2430OSK OMAP_2430OSK 1437
+sardine MACH_SARDINE SARDINE 1438
+halibut MACH_HALIBUT HALIBUT 1439
+trout MACH_TROUT TROUT 1440
+goldfish MACH_GOLDFISH GOLDFISH 1441
+gesbc2440 MACH_GESBC2440 GESBC2440 1442
+nomad MACH_NOMAD NOMAD 1443
+rosalind MACH_ROSALIND ROSALIND 1444
+cc9p9215 MACH_CC9P9215 CC9P9215 1445
+cc9p9210 MACH_CC9P9210 CC9P9210 1446
+cc9p9215js MACH_CC9P9215JS CC9P9215JS 1447
+cc9p9210js MACH_CC9P9210JS CC9P9210JS 1448
+nasffe MACH_NASFFE NASFFE 1449
+tn2x0bd MACH_TN2X0BD TN2X0BD 1450
+gwmpxa MACH_GWMPXA GWMPXA 1451
+exyplus MACH_EXYPLUS EXYPLUS 1452
+jadoo21 MACH_JADOO21 JADOO21 1453
+looxn560 MACH_LOOXN560 LOOXN560 1454
+bonsai MACH_BONSAI BONSAI 1455
+adsmilgato MACH_ADSMILGATO ADSMILGATO 1456
+gba MACH_GBA GBA 1457
+h6044 MACH_H6044 H6044 1458
+app MACH_APP APP 1459
+tct_hammer MACH_TCT_HAMMER TCT_HAMMER 1460
+herald MACH_HERALD HERALD 1461
+artemis MACH_ARTEMIS ARTEMIS 1462
+htctitan MACH_HTCTITAN HTCTITAN 1463
+qranium MACH_QRANIUM QRANIUM 1464
+adx_wsc2 MACH_ADX_WSC2 ADX_WSC2 1465
+adx_medcom MACH_ADX_MEDCOM ADX_MEDCOM 1466
+bboard MACH_BBOARD BBOARD 1467
+cambria MACH_CAMBRIA CAMBRIA 1468
+mt7xxx MACH_MT7XXX MT7XXX 1469
+matrix512 MACH_MATRIX512 MATRIX512 1470
+matrix522 MACH_MATRIX522 MATRIX522 1471
+ipac5010 MACH_IPAC5010 IPAC5010 1472
+sakura MACH_SAKURA SAKURA 1473
+grocx MACH_GROCX GROCX 1474
+pm9263 MACH_PM9263 PM9263 1475
+sim_one MACH_SIM_ONE SIM_ONE 1476
+acq132 MACH_ACQ132 ACQ132 1477
+datr MACH_DATR DATR 1478
+actux1 MACH_ACTUX1 ACTUX1 1479
+actux2 MACH_ACTUX2 ACTUX2 1480
+actux3 MACH_ACTUX3 ACTUX3 1481
+flexit MACH_FLEXIT FLEXIT 1482
+bh2x0bd MACH_BH2X0BD BH2X0BD 1483
+atb2002 MACH_ATB2002 ATB2002 1484
+xenon MACH_XENON XENON 1485
+fm607 MACH_FM607 FM607 1486
+matrix514 MACH_MATRIX514 MATRIX514 1487
+matrix524 MACH_MATRIX524 MATRIX524 1488
+inpod MACH_INPOD INPOD 1489
+jive MACH_JIVE JIVE 1490
+tll_mx21 MACH_TLL_MX21 TLL_MX21 1491
+sbc2800 MACH_SBC2800 SBC2800 1492
+cc7ucamry MACH_CC7UCAMRY CC7UCAMRY 1493
+ubisys_p9_sc15 MACH_UBISYS_P9_SC15 UBISYS_P9_SC15 1494
+ubisys_p9_ssc2d10 MACH_UBISYS_P9_SSC2D10 UBISYS_P9_SSC2D10 1495
+ubisys_p9_rcu3 MACH_UBISYS_P9_RCU3 UBISYS_P9_RCU3 1496
+aml_m8000 MACH_AML_M8000 AML_M8000 1497
+snapper_270 MACH_SNAPPER_270 SNAPPER_270 1498
+omap_bbx MACH_OMAP_BBX OMAP_BBX 1499
+ucn2410 MACH_UCN2410 UCN2410 1500
+sam9_l9260 MACH_SAM9_L9260 SAM9_L9260 1501
+eti_c2 MACH_ETI_C2 ETI_C2 1502
+avalanche MACH_AVALANCHE AVALANCHE 1503
+realview_pb1176 MACH_REALVIEW_PB1176 REALVIEW_PB1176 1504
+dp1500 MACH_DP1500 DP1500 1505
+apple_iphone MACH_APPLE_IPHONE APPLE_IPHONE 1506
+yl9200 MACH_YL9200 YL9200 1507
+rd88f5182 MACH_RD88F5182 RD88F5182 1508
+kurobox_pro MACH_KUROBOX_PRO KUROBOX_PRO 1509
+se_poet MACH_SE_POET SE_POET 1510
+mx31_3ds MACH_MX31_3DS MX31_3DS 1511
+r270 MACH_R270 R270 1512
+armour21 MACH_ARMOUR21 ARMOUR21 1513
+dt2 MACH_DT2 DT2 1514
+vt4 MACH_VT4 VT4 1515
+tyco320 MACH_TYCO320 TYCO320 1516
+adma MACH_ADMA ADMA 1517
+wp188 MACH_WP188 WP188 1518
+corsica MACH_CORSICA CORSICA 1519
+bigeye MACH_BIGEYE BIGEYE 1520
+tll5000 MACH_TLL5000 TLL5000 1522
+bebot MACH_BEBOT BEBOT 1523
+qong MACH_QONG QONG 1524
+tcompact MACH_TCOMPACT TCOMPACT 1525
+puma5 MACH_PUMA5 PUMA5 1526
+elara MACH_ELARA ELARA 1527
+ellington MACH_ELLINGTON ELLINGTON 1528
+xda_atom MACH_XDA_ATOM XDA_ATOM 1529
+energizer2 MACH_ENERGIZER2 ENERGIZER2 1530
+odin MACH_ODIN ODIN 1531
+actux4 MACH_ACTUX4 ACTUX4 1532
+esl_omap MACH_ESL_OMAP ESL_OMAP 1533
+omap2evm MACH_OMAP2EVM OMAP2EVM 1534
+omap3evm MACH_OMAP3EVM OMAP3EVM 1535
+adx_pcu57 MACH_ADX_PCU57 ADX_PCU57 1536
+monaco MACH_MONACO MONACO 1537
+levante MACH_LEVANTE LEVANTE 1538
+tmxipx425 MACH_TMXIPX425 TMXIPX425 1539
+leep MACH_LEEP LEEP 1540
+raad MACH_RAAD RAAD 1541
+dns323 MACH_DNS323 DNS323 1542
+ap1000 MACH_AP1000 AP1000 1543
+a9sam6432 MACH_A9SAM6432 A9SAM6432 1544
+shiny MACH_SHINY SHINY 1545
+omap3_beagle MACH_OMAP3_BEAGLE OMAP3_BEAGLE 1546
+csr_bdb2 MACH_CSR_BDB2 CSR_BDB2 1547
+nokia_n810 MACH_NOKIA_N810 NOKIA_N810 1548
+c270 MACH_C270 C270 1549
+sentry MACH_SENTRY SENTRY 1550
+pcm038 MACH_PCM038 PCM038 1551
+anc300 MACH_ANC300 ANC300 1552
+htckaiser MACH_HTCKAISER HTCKAISER 1553
+sbat100 MACH_SBAT100 SBAT100 1554
+modunorm MACH_MODUNORM MODUNORM 1555
+pelos_twarm MACH_PELOS_TWARM PELOS_TWARM 1556
+flank MACH_FLANK FLANK 1557
+sirloin MACH_SIRLOIN SIRLOIN 1558
+brisket MACH_BRISKET BRISKET 1559
+chuck MACH_CHUCK CHUCK 1560
+otter MACH_OTTER OTTER 1561
+davinci_ldk MACH_DAVINCI_LDK DAVINCI_LDK 1562
+phreedom MACH_PHREEDOM PHREEDOM 1563
+sg310 MACH_SG310 SG310 1564
+ts209 MACH_TS209 TS209 1565
+at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566
+tion9315 MACH_TION9315 TION9315 1567
+mast MACH_MAST MAST 1568
+pfw MACH_PFW PFW 1569
+yl_p2440 MACH_YL_P2440 YL_P2440 1570
+zsbc32 MACH_ZSBC32 ZSBC32 1571
+omap_pace2 MACH_OMAP_PACE2 OMAP_PACE2 1572
+imx_pace2 MACH_IMX_PACE2 IMX_PACE2 1573
+mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574
+mx37_3ds MACH_MX37_3DS MX37_3DS 1575
+rcc MACH_RCC RCC 1576
+dmp MACH_ARM9 ARM9 1577
+vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578
+scly1000 MACH_SCLY1000 SCLY1000 1579
+fontel_ep MACH_FONTEL_EP FONTEL_EP 1580
+voiceblue3g MACH_VOICEBLUE3G VOICEBLUE3G 1581
+tt9200 MACH_TT9200 TT9200 1582
+digi2410 MACH_DIGI2410 DIGI2410 1583
+terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584
+linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585
+motorola_a780 MACH_MOTOROLA_A780 MOTOROLA_A780 1587
+motorola_e6 MACH_MOTOROLA_E6 MOTOROLA_E6 1588
+motorola_e2 MACH_MOTOROLA_E2 MOTOROLA_E2 1589
+motorola_e680 MACH_MOTOROLA_E680 MOTOROLA_E680 1590
+ur2410 MACH_UR2410 UR2410 1591
+tas9261 MACH_TAS9261 TAS9261 1592
+davinci_hermes_hd MACH_HERMES_HD HERMES_HD 1593
+davinci_perseo_hd MACH_PERSEO_HD PERSEO_HD 1594
+stargazer2 MACH_STARGAZER2 STARGAZER2 1595
+e350 MACH_E350 E350 1596
+wpcm450 MACH_WPCM450 WPCM450 1597
+cartesio MACH_CARTESIO CARTESIO 1598
+toybox MACH_TOYBOX TOYBOX 1599
+tx27 MACH_TX27 TX27 1600
+ts409 MACH_TS409 TS409 1601
+p300 MACH_P300 P300 1602
+xdacomet MACH_XDACOMET XDACOMET 1603
+dexflex2 MACH_DEXFLEX2 DEXFLEX2 1604
+ow MACH_OW OW 1605
+armebs3 MACH_ARMEBS3 ARMEBS3 1606
+u3 MACH_U3 U3 1607
+smdk2450 MACH_SMDK2450 SMDK2450 1608
+rsi_ews MACH_RSI_EWS RSI_EWS 1609
+tnb MACH_TNB TNB 1610
+toepath MACH_TOEPATH TOEPATH 1611
+kb9263 MACH_KB9263 KB9263 1612
+mt7108 MACH_MT7108 MT7108 1613
+smtr2440 MACH_SMTR2440 SMTR2440 1614
+manao MACH_MANAO MANAO 1615
+cm_x300 MACH_CM_X300 CM_X300 1616
+gulfstream_kp MACH_GULFSTREAM_KP GULFSTREAM_KP 1617
+lanreadyfn522 MACH_LANREADYFN522 LANREADYFN522 1618
+arma37 MACH_ARMA37 ARMA37 1619
+mendel MACH_MENDEL MENDEL 1620
+pelco_iliad MACH_PELCO_ILIAD PELCO_ILIAD 1621
+unit2p MACH_UNIT2P UNIT2P 1622
+inc20otter MACH_INC20OTTER INC20OTTER 1623
+at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624
+sc_ge2 MACH_STORCENTER STORCENTER 1625
+smdk6410 MACH_SMDK6410 SMDK6410 1626
+u300 MACH_U300 U300 1627
+u500 MACH_U500 U500 1628
+ds9260 MACH_DS9260 DS9260 1629
+riverrock MACH_RIVERROCK RIVERROCK 1630
+scibath MACH_SCIBATH SCIBATH 1631
+at91sam7se MACH_AT91SAM7SE512EK AT91SAM7SE512EK 1632
+wrt350n_v2 MACH_WRT350N_V2 WRT350N_V2 1633
+multimedia MACH_MULTIMEDIA MULTIMEDIA 1634
+marvin MACH_MARVIN MARVIN 1635
+x500 MACH_X500 X500 1636
+awlug4lcu MACH_AWLUG4LCU AWLUG4LCU 1637
+palermoc MACH_PALERMOC PALERMOC 1638
+omap_ldp MACH_OMAP_LDP OMAP_LDP 1639
+ip500 MACH_IP500 IP500 1640
+ase2 MACH_ASE2 ASE2 1642
+mx35evb MACH_MX35EVB MX35EVB 1643
+aml_m8050 MACH_AML_M8050 AML_M8050 1644
+mx35_3ds MACH_MX35_3DS MX35_3DS 1645
+mars MACH_MARS MARS 1646
+neuros_osd2 MACH_NEUROS_OSD2 NEUROS_OSD2 1647
+badger MACH_BADGER BADGER 1648
+trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649
+trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650
+marlin MACH_MARLIN MARLIN 1651
+ts78xx MACH_TS78XX TS78XX 1652
+hpipaq214 MACH_HPIPAQ214 HPIPAQ214 1653
+at572d940dcm MACH_AT572D940DCM AT572D940DCM 1654
+ne1board MACH_NE1BOARD NE1BOARD 1655
+zante MACH_ZANTE ZANTE 1656
+sffsdr MACH_SFFSDR SFFSDR 1657
+tw2662 MACH_TW2662 TW2662 1658
+vf10xx MACH_VF10XX VF10XX 1659
+zoran43xx MACH_ZORAN43XX ZORAN43XX 1660
+sonix926 MACH_SONIX926 SONIX926 1661
+celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662
+cc9m2443js MACH_CC9M2443JS CC9M2443JS 1663
+tw5334 MACH_TW5334 TW5334 1664
+omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665
+nal_hlite MACH_NAL_HLITE NAL_HLITE 1666
+htcvogue MACH_HTCVOGUE HTCVOGUE 1667
+smartweb MACH_SMARTWEB SMARTWEB 1668
+mv86xx MACH_MV86XX MV86XX 1669
+mv87xx MACH_MV87XX MV87XX 1670
+songyoungho MACH_SONGYOUNGHO SONGYOUNGHO 1671
+younghotema MACH_YOUNGHOTEMA YOUNGHOTEMA 1672
+pcm037 MACH_PCM037 PCM037 1673
+mmvp MACH_MMVP MMVP 1674
+mmap MACH_MMAP MMAP 1675
+ptid2410 MACH_PTID2410 PTID2410 1676
+james_926 MACH_JAMES_926 JAMES_926 1677
+fm6000 MACH_FM6000 FM6000 1678
+db88f6281_bp MACH_DB88F6281_BP DB88F6281_BP 1680
+rd88f6192_nas MACH_RD88F6192_NAS RD88F6192_NAS 1681
+rd88f6281 MACH_RD88F6281 RD88F6281 1682
+db78x00_bp MACH_DB78X00_BP DB78X00_BP 1683
+smdk2416 MACH_SMDK2416 SMDK2416 1685
+oce_spider_si MACH_OCE_SPIDER_SI OCE_SPIDER_SI 1686
+oce_spider_sk MACH_OCE_SPIDER_SK OCE_SPIDER_SK 1687
+rovern6 MACH_ROVERN6 ROVERN6 1688
+pelco_evolution MACH_PELCO_EVOLUTION PELCO_EVOLUTION 1689
+wbd111 MACH_WBD111 WBD111 1690
+elaracpe MACH_ELARACPE ELARACPE 1691
+mabv3 MACH_MABV3 MABV3 1692
+mv2120 MACH_MV2120 MV2120 1693
+csb737 MACH_CSB737 CSB737 1695
+mx51_3ds MACH_MX51_3DS MX51_3DS 1696
+g900 MACH_G900 G900 1697
+apf27 MACH_APF27 APF27 1698
+ggus2000 MACH_GGUS2000 GGUS2000 1699
+omap_2430_mimic MACH_OMAP_2430_MIMIC OMAP_2430_MIMIC 1700
+imx27lite MACH_IMX27LITE IMX27LITE 1701
+almex MACH_ALMEX ALMEX 1702
+control MACH_CONTROL CONTROL 1703
+mba2410 MACH_MBA2410 MBA2410 1704
+volcano MACH_VOLCANO VOLCANO 1705
+zenith MACH_ZENITH ZENITH 1706
+muchip MACH_MUCHIP MUCHIP 1707
+magellan MACH_MAGELLAN MAGELLAN 1708
+usb_a9260 MACH_USB_A9260 USB_A9260 1709
+usb_a9263 MACH_USB_A9263 USB_A9263 1710
+qil_a9260 MACH_QIL_A9260 QIL_A9260 1711
+cme9210 MACH_CME9210 CME9210 1712
+hczh4 MACH_HCZH4 HCZH4 1713
+spearbasic MACH_SPEARBASIC SPEARBASIC 1714
+dep2440 MACH_DEP2440 DEP2440 1715
+hdl_gxr MACH_HDL_GXR HDL_GXR 1716
+hdl_gt MACH_HDL_GT HDL_GT 1717
+hdl_4g MACH_HDL_4G HDL_4G 1718
+s3c6000 MACH_S3C6000 S3C6000 1719
+mmsp2_mdk MACH_MMSP2_MDK MMSP2_MDK 1720
+mpx220 MACH_MPX220 MPX220 1721
+kzm_arm11_01 MACH_KZM_ARM11_01 KZM_ARM11_01 1722
+htc_polaris MACH_HTC_POLARIS HTC_POLARIS 1723
+htc_kaiser MACH_HTC_KAISER HTC_KAISER 1724
+lg_ks20 MACH_LG_KS20 LG_KS20 1725
+hhgps MACH_HHGPS HHGPS 1726
+nokia_n810_wimax MACH_NOKIA_N810_WIMAX NOKIA_N810_WIMAX 1727
+insight MACH_INSIGHT INSIGHT 1728
+sapphire MACH_SAPPHIRE SAPPHIRE 1729
+csb637xo MACH_CSB637XO CSB637XO 1730
+evisiong MACH_EVISIONG EVISIONG 1731
+stmp37xx MACH_STMP37XX STMP37XX 1732
+stmp378x MACH_STMP378X STMP378X 1733
+tnt MACH_TNT TNT 1734
+tbxt MACH_TBXT TBXT 1735
+playmate MACH_PLAYMATE PLAYMATE 1736
+pns10 MACH_PNS10 PNS10 1737
+eznavi MACH_EZNAVI EZNAVI 1738
+ps4000 MACH_PS4000 PS4000 1739
+ezx_a780 MACH_EZX_A780 EZX_A780 1740
+ezx_e680 MACH_EZX_E680 EZX_E680 1741
+ezx_a1200 MACH_EZX_A1200 EZX_A1200 1742
+ezx_e6 MACH_EZX_E6 EZX_E6 1743
+ezx_e2 MACH_EZX_E2 EZX_E2 1744
+ezx_a910 MACH_EZX_A910 EZX_A910 1745
+cwmx31 MACH_CWMX31 CWMX31 1746
+sl2312 MACH_SL2312 SL2312 1747
+blenny MACH_BLENNY BLENNY 1748
+ds107 MACH_DS107 DS107 1749
+dsx07 MACH_DSX07 DSX07 1750
+picocom1 MACH_PICOCOM1 PICOCOM1 1751
+lynx_wolverine MACH_LYNX_WOLVERINE LYNX_WOLVERINE 1752
+ubisys_p9_sc19 MACH_UBISYS_P9_SC19 UBISYS_P9_SC19 1753
+kratos_low MACH_KRATOS_LOW KRATOS_LOW 1754
+m700 MACH_M700 M700 1755
+edmini_v2 MACH_EDMINI_V2 EDMINI_V2 1756
+zipit2 MACH_ZIPIT2 ZIPIT2 1757
+hslfemtocell MACH_HSLFEMTOCELL HSLFEMTOCELL 1758
+daintree_at91 MACH_DAINTREE_AT91 DAINTREE_AT91 1759
+sg560usb MACH_SG560USB SG560USB 1760
+omap3_pandora MACH_OMAP3_PANDORA OMAP3_PANDORA 1761
+usr8200 MACH_USR8200 USR8200 1762
+s1s65k MACH_S1S65K S1S65K 1763
+s2s65a MACH_S2S65A S2S65A 1764
+icore MACH_ICORE ICORE 1765
+mss2 MACH_MSS2 MSS2 1766
+belmont MACH_BELMONT BELMONT 1767
+asusp525 MACH_ASUSP525 ASUSP525 1768
+lb88rc8480 MACH_LB88RC8480 LB88RC8480 1769
+hipxa MACH_HIPXA HIPXA 1770
+mx25_3ds MACH_MX25_3DS MX25_3DS 1771
+m800 MACH_M800 M800 1772
+omap3530_lv_som MACH_OMAP3530_LV_SOM OMAP3530_LV_SOM 1773
+prima_evb MACH_PRIMA_EVB PRIMA_EVB 1774
+mx31bt1 MACH_MX31BT1 MX31BT1 1775
+atlas4_evb MACH_ATLAS4_EVB ATLAS4_EVB 1776
+mx31cicada MACH_MX31CICADA MX31CICADA 1777
+mi424wr MACH_MI424WR MI424WR 1778
+axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779
+at572d940deb MACH_AT572D940DEB AT572D940DEB 1780
+davinci_da830_evm MACH_DAVINCI_DA830_EVM DAVINCI_DA830_EVM 1781
+ep9302 MACH_EP9302 EP9302 1782
+at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783
+cybook3 MACH_CYBOOK3 CYBOOK3 1784
+wdg002 MACH_WDG002 WDG002 1785
+sg560adsl MACH_SG560ADSL SG560ADSL 1786
+nextio_n2800_ica MACH_NEXTIO_N2800_ICA NEXTIO_N2800_ICA 1787
+dove_db MACH_DOVE_DB DOVE_DB 1788
+vandihud MACH_VANDIHUD VANDIHUD 1790
+magx_e8 MACH_MAGX_E8 MAGX_E8 1791
+magx_z6 MACH_MAGX_Z6 MAGX_Z6 1792
+magx_v8 MACH_MAGX_V8 MAGX_V8 1793
+magx_u9 MACH_MAGX_U9 MAGX_U9 1794
+toughcf08 MACH_TOUGHCF08 TOUGHCF08 1795
+zw4400 MACH_ZW4400 ZW4400 1796
+marat91 MACH_MARAT91 MARAT91 1797
+overo MACH_OVERO OVERO 1798
+at2440evb MACH_AT2440EVB AT2440EVB 1799
+neocore926 MACH_NEOCORE926 NEOCORE926 1800
+wnr854t MACH_WNR854T WNR854T 1801
+imx27 MACH_IMX27 IMX27 1802
+moose_db MACH_MOOSE_DB MOOSE_DB 1803
+fab4 MACH_FAB4 FAB4 1804
+htcdiamond MACH_HTCDIAMOND HTCDIAMOND 1805
+fiona MACH_FIONA FIONA 1806
+mxc30030_x MACH_MXC30030_X MXC30030_X 1807
+bmp1000 MACH_BMP1000 BMP1000 1808
+logi9200 MACH_LOGI9200 LOGI9200 1809
+tqma31 MACH_TQMA31 TQMA31 1810
+ccw9p9215js MACH_CCW9P9215JS CCW9P9215JS 1811
+rd88f5181l_ge MACH_RD88F5181L_GE RD88F5181L_GE 1812
+sifmain MACH_SIFMAIN SIFMAIN 1813
+sam9_l9261 MACH_SAM9_L9261 SAM9_L9261 1814
+cc9m2443 MACH_CC9M2443 CC9M2443 1815
+xaria300 MACH_XARIA300 XARIA300 1816
+it9200 MACH_IT9200 IT9200 1817
+rd88f5181l_fxo MACH_RD88F5181L_FXO RD88F5181L_FXO 1818
+kriss_sensor MACH_KRISS_SENSOR KRISS_SENSOR 1819
+pilz_pmi5 MACH_PILZ_PMI5 PILZ_PMI5 1820
+jade MACH_JADE JADE 1821
+ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822
+gprisc3 MACH_GPRISC3 GPRISC3 1823
+stamp9g20 MACH_STAMP9G20 STAMP9G20 1824
+smdk6430 MACH_SMDK6430 SMDK6430 1825
+smdkc100 MACH_SMDKC100 SMDKC100 1826
+tavorevb MACH_TAVOREVB TAVOREVB 1827
+saar MACH_SAAR SAAR 1828
+deister_eyecam MACH_DEISTER_EYECAM DEISTER_EYECAM 1829
+at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830
+linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831
+hit_b0 MACH_HIT_B0 HIT_B0 1832
+adx_rmu MACH_ADX_RMU ADX_RMU 1833
+xg_cpe_main MACH_XG_CPE_MAIN XG_CPE_MAIN 1834
+edb9407a MACH_EDB9407A EDB9407A 1835
+dtb9608 MACH_DTB9608 DTB9608 1836
+em104v1 MACH_EM104V1 EM104V1 1837
+demo MACH_DEMO DEMO 1838
+logi9260 MACH_LOGI9260 LOGI9260 1839
+mx31_exm32 MACH_MX31_EXM32 MX31_EXM32 1840
+usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841
+picproje2008 MACH_PICPROJE2008 PICPROJE2008 1842
+cs_e9315 MACH_CS_E9315 CS_E9315 1843
+qil_a9g20 MACH_QIL_A9G20 QIL_A9G20 1844
+sha_pon020 MACH_SHA_PON020 SHA_PON020 1845
+nad MACH_NAD NAD 1846
+sbc35_a9260 MACH_SBC35_A9260 SBC35_A9260 1847
+sbc35_a9g20 MACH_SBC35_A9G20 SBC35_A9G20 1848
+davinci_beginning MACH_DAVINCI_BEGINNING DAVINCI_BEGINNING 1849
+uwc MACH_UWC UWC 1850
+mxlads MACH_MXLADS MXLADS 1851
+htcnike MACH_HTCNIKE HTCNIKE 1852
+deister_pxa270 MACH_DEISTER_PXA270 DEISTER_PXA270 1853
+cme9210js MACH_CME9210JS CME9210JS 1854
+cc9p9360 MACH_CC9P9360 CC9P9360 1855
+mocha MACH_MOCHA MOCHA 1856
+wapd170ag MACH_WAPD170AG WAPD170AG 1857
+linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858
+afeb9260 MACH_AFEB9260 AFEB9260 1859
+w90x900 MACH_W90X900 W90X900 1860
+w90x700 MACH_W90X700 W90X700 1861
+kt300ip MACH_KT300IP KT300IP 1862
+kt300ip_g20 MACH_KT300IP_G20 KT300IP_G20 1863
+srcm MACH_SRCM SRCM 1864
+wlnx_9260 MACH_WLNX_9260 WLNX_9260 1865
+openmoko_gta03 MACH_OPENMOKO_GTA03 OPENMOKO_GTA03 1866
+osprey2 MACH_OSPREY2 OSPREY2 1867
+kbio9260 MACH_KBIO9260 KBIO9260 1868
+ginza MACH_GINZA GINZA 1869
+a636n MACH_A636N A636N 1870
+imx27ipcam MACH_IMX27IPCAM IMX27IPCAM 1871
+nemoc MACH_NEMOC NEMOC 1872
+geneva MACH_GENEVA GENEVA 1873
+htcpharos MACH_HTCPHAROS HTCPHAROS 1874
+neonc MACH_NEONC NEONC 1875
+nas7100 MACH_NAS7100 NAS7100 1876
+teuphone MACH_TEUPHONE TEUPHONE 1877
+annax_eth2 MACH_ANNAX_ETH2 ANNAX_ETH2 1878
+csb733 MACH_CSB733 CSB733 1879
+bk3 MACH_BK3 BK3 1880
+omap_em32 MACH_OMAP_EM32 OMAP_EM32 1881
+et9261cp MACH_ET9261CP ET9261CP 1882
+jasperc MACH_JASPERC JASPERC 1883
+issi_arm9 MACH_ISSI_ARM9 ISSI_ARM9 1884
+ued MACH_UED UED 1885
+esiblade MACH_ESIBLADE ESIBLADE 1886
+eye02 MACH_EYE02 EYE02 1887
+imx27kbd MACH_IMX27KBD IMX27KBD 1888
+kixvp435 MACH_KIXVP435 KIXVP435 1890
+kixnp435 MACH_KIXNP435 KIXNP435 1891
+africa MACH_AFRICA AFRICA 1892
+nh233 MACH_NH233 NH233 1893
+rd88f6183ap_ge MACH_RD88F6183AP_GE RD88F6183AP_GE 1894
+bcm4760 MACH_BCM4760 BCM4760 1895
+eddy_v2 MACH_EDDY_V2 EDDY_V2 1896
+realview_pba8 MACH_REALVIEW_PBA8 REALVIEW_PBA8 1897
+hid_a7 MACH_HID_A7 HID_A7 1898
+hero MACH_HERO HERO 1899
+omap_poseidon MACH_OMAP_POSEIDON OMAP_POSEIDON 1900
+realview_pbx MACH_REALVIEW_PBX REALVIEW_PBX 1901
+micro9s MACH_MICRO9S MICRO9S 1902
+mako MACH_MAKO MAKO 1903
+xdaflame MACH_XDAFLAME XDAFLAME 1904
+phidget_sbc2 MACH_PHIDGET_SBC2 PHIDGET_SBC2 1905
+limestone MACH_LIMESTONE LIMESTONE 1906
+iprobe_c32 MACH_IPROBE_C32 IPROBE_C32 1907
+rut100 MACH_RUT100 RUT100 1908
+asusp535 MACH_ASUSP535 ASUSP535 1909
+htcraphael MACH_HTCRAPHAEL HTCRAPHAEL 1910
+sygdg1 MACH_SYGDG1 SYGDG1 1911
+sygdg2 MACH_SYGDG2 SYGDG2 1912
+seoul MACH_SEOUL SEOUL 1913
+salerno MACH_SALERNO SALERNO 1914
+ucn_s3c64xx MACH_UCN_S3C64XX UCN_S3C64XX 1915
+msm7201a MACH_MSM7201A MSM7201A 1916
+lpr1 MACH_LPR1 LPR1 1917
+armadillo500fx MACH_ARMADILLO500FX ARMADILLO500FX 1918
+g3evm MACH_G3EVM G3EVM 1919
+z3_dm355 MACH_Z3_DM355 Z3_DM355 1920
+w90p910evb MACH_W90P910EVB W90P910EVB 1921
+w90p920evb MACH_W90P920EVB W90P920EVB 1922
+w90p950evb MACH_W90P950EVB W90P950EVB 1923
+w90n960evb MACH_W90N960EVB W90N960EVB 1924
+camhd MACH_CAMHD CAMHD 1925
+mvc100 MACH_MVC100 MVC100 1926
+electrum_200 MACH_ELECTRUM_200 ELECTRUM_200 1927
+htcjade MACH_HTCJADE HTCJADE 1928
+memphis MACH_MEMPHIS MEMPHIS 1929
+imx27sbc MACH_IMX27SBC IMX27SBC 1930
+lextar MACH_LEXTAR LEXTAR 1931
+mv88f6281gtw_ge MACH_MV88F6281GTW_GE MV88F6281GTW_GE 1932
+ncp MACH_NCP NCP 1933
+z32an_series MACH_Z32AN Z32AN 1934
+tmq_capd MACH_TMQ_CAPD TMQ_CAPD 1935
+omap3_wl MACH_OMAP3_WL OMAP3_WL 1936
+chumby MACH_CHUMBY CHUMBY 1937
+atsarm9 MACH_ATSARM9 ATSARM9 1938
+davinci_dm365_evm MACH_DAVINCI_DM365_EVM DAVINCI_DM365_EVM 1939
+bahamas MACH_BAHAMAS BAHAMAS 1940
+das MACH_DAS DAS 1941
+minidas MACH_MINIDAS MINIDAS 1942
+vk1000 MACH_VK1000 VK1000 1943
+centro MACH_CENTRO CENTRO 1944
+ctera_2bay MACH_CTERA_2BAY CTERA_2BAY 1945
+edgeconnect MACH_EDGECONNECT EDGECONNECT 1946
+nd27000 MACH_ND27000 ND27000 1947
+cobra MACH_GEMALTO_COBRA GEMALTO_COBRA 1948
+ingelabs_comet MACH_INGELABS_COMET INGELABS_COMET 1949
+pollux_wiz MACH_POLLUX_WIZ POLLUX_WIZ 1950
+blackstone MACH_BLACKSTONE BLACKSTONE 1951
+topaz MACH_TOPAZ TOPAZ 1952
+aixle MACH_AIXLE AIXLE 1953
+mw998 MACH_MW998 MW998 1954
+nokia_rx51 MACH_NOKIA_RX51 NOKIA_RX51 1955
+vsc5605ev MACH_VSC5605EV VSC5605EV 1956
+nt98700dk MACH_NT98700DK NT98700DK 1957
+icontact MACH_ICONTACT ICONTACT 1958
+swarco_frcpu MACH_SWARCO_FRCPU SWARCO_FRCPU 1959
+swarco_scpu MACH_SWARCO_SCPU SWARCO_SCPU 1960
+bbox_p16 MACH_BBOX_P16 BBOX_P16 1961
+bstd MACH_BSTD BSTD 1962
+sbc2440ii MACH_SBC2440II SBC2440II 1963
+pcm034 MACH_PCM034 PCM034 1964
+neso MACH_NESO NESO 1965
+wlnx_9g20 MACH_WLNX_9G20 WLNX_9G20 1966
+omap_zoom2 MACH_OMAP_ZOOM2 OMAP_ZOOM2 1967
+totemnova MACH_TOTEMNOVA TOTEMNOVA 1968
+c5000 MACH_C5000 C5000 1969
+unipo_at91sam9263 MACH_UNIPO_AT91SAM9263 UNIPO_AT91SAM9263 1970
+ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971
+arm11 MACH_ARM11 ARM11 1972
+cpuat9260 MACH_CPUAT9260 CPUAT9260 1973
+cpupxa255 MACH_CPUPXA255 CPUPXA255 1974
+eukrea_cpuimx27 MACH_EUKREA_CPUIMX27 EUKREA_CPUIMX27 1975
+cheflux MACH_CHEFLUX CHEFLUX 1976
+eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977
+opcotec MACH_OPCOTEC OPCOTEC 1978
+yt MACH_YT YT 1979
+motoq MACH_MOTOQ MOTOQ 1980
+bsb1 MACH_BSB1 BSB1 1981
+acs5k MACH_ACS5K ACS5K 1982
+milan MACH_MILAN MILAN 1983
+quartzv2 MACH_QUARTZV2 QUARTZV2 1984
+rsvp MACH_RSVP RSVP 1985
+rmp200 MACH_RMP200 RMP200 1986
+snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987
+dsm320 MACH_DSM320 DSM320 1988
+adsgcm MACH_ADSGCM ADSGCM 1989
+ase2_400 MACH_ASE2_400 ASE2_400 1990
+pizza MACH_PIZZA PIZZA 1991
+spot_ngpl MACH_SPOT_NGPL SPOT_NGPL 1992
+armata MACH_ARMATA ARMATA 1993
+exeda MACH_EXEDA EXEDA 1994
+mx31sf005 MACH_MX31SF005 MX31SF005 1995
+f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996
+q2440 MACH_Q2440 Q2440 1997
+qq2440 MACH_QQ2440 QQ2440 1998
+mini2440 MACH_MINI2440 MINI2440 1999
+colibri300 MACH_COLIBRI300 COLIBRI300 2000
+jades MACH_JADES JADES 2001
+spark MACH_SPARK SPARK 2002
+benzina MACH_BENZINA BENZINA 2003
+blaze MACH_BLAZE BLAZE 2004
+linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005
+htckovsky MACH_HTCKOVSKY HTCKOVSKY 2006
+sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007
+hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008
+sapphira MACH_SAPPHIRA SAPPHIRA 2009
+dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010
+armbox MACH_ARMBOX ARMBOX 2011
+harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012
+ribaldo MACH_RIBALDO RIBALDO 2013
+agora MACH_AGORA AGORA 2014
+omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015
+a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016
+usg2410 MACH_USG2410 USG2410 2017
+pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018
+mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019
+topas910 MACH_TOPAS910 TOPAS910 2020
+hyena MACH_HYENA HYENA 2021
+pospax MACH_POSPAX POSPAX 2022
+hdl_gx MACH_HDL_GX HDL_GX 2023
+ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024
+ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025
+crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026
+egauge2 MACH_EGAUGE2 EGAUGE2 2027
+didj MACH_DIDJ DIDJ 2028
+m_s3c2443 MACH_MEISTER MEISTER 2029
+htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030
+cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031
+smdk6440 MACH_SMDK6440 SMDK6440 2032
+omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033
+ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034
+pvg610_100 MACH_PVG610 PVG610 2035
+hprw6815 MACH_HPRW6815 HPRW6815 2036
+omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037
+nas4220b MACH_NAS4220B NAS4220B 2038
+htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039
+htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040
+scaler MACH_SCALER SCALER 2041
+zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042
+aspenite MACH_ASPENITE ASPENITE 2043
+teton MACH_TETON TETON 2044
+ttc_dkb MACH_TTC_DKB TTC_DKB 2045
+bishop2 MACH_BISHOP2 BISHOP2 2046
+ippv5 MACH_IPPV5 IPPV5 2047
+farm926 MACH_FARM926 FARM926 2048
+mmccpu MACH_MMCCPU MMCCPU 2049
+sgmsfl MACH_SGMSFL SGMSFL 2050
+tt8000 MACH_TT8000 TT8000 2051
+zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052
+mptc MACH_MPTC MPTC 2053
+h6051 MACH_H6051 H6051 2054
+pvg610_101 MACH_PVG610_101 PVG610_101 2055
+stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056
+pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057
+tny_a9260 MACH_TNY_A9260 TNY_A9260 2058
+tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059
+aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060
+dx900 MACH_DX900 DX900 2061
+cpodc2 MACH_CPODC2 CPODC2 2062
+tilt_8925 MACH_TILT_8925 TILT_8925 2063
+davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064
+swordfish MACH_SWORDFISH SWORDFISH 2065
+corvus MACH_CORVUS CORVUS 2066
+taurus MACH_TAURUS TAURUS 2067
+axm MACH_AXM AXM 2068
+axc MACH_AXC AXC 2069
+baby MACH_BABY BABY 2070
+mp200 MACH_MP200 MP200 2071
+pcm043 MACH_PCM043 PCM043 2072
+hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073
+kbk9g20 MACH_KBK9G20 KBK9G20 2074
+adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075
+avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076
+suc82x MACH_SUC SUC 2077
+at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078
+mendoza MACH_MENDOZA MENDOZA 2079
+kira MACH_KIRA KIRA 2080
+mx1hbm MACH_MX1HBM MX1HBM 2081
+quatro43xx MACH_QUATRO43XX QUATRO43XX 2082
+quatro4230 MACH_QUATRO4230 QUATRO4230 2083
+nsb400 MACH_NSB400 NSB400 2084
+drp255 MACH_DRP255 DRP255 2085
+thoth MACH_THOTH THOTH 2086
+firestone MACH_FIRESTONE FIRESTONE 2087
+asusp750 MACH_ASUSP750 ASUSP750 2088
+ctera_dl MACH_CTERA_DL CTERA_DL 2089
+socr MACH_SOCR SOCR 2090
+htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091
+heroc MACH_HEROC HEROC 2092
+zeno6800 MACH_ZENO6800 ZENO6800 2093
+sc2mcs MACH_SC2MCS SC2MCS 2094
+gene100 MACH_GENE100 GENE100 2095
+as353x MACH_AS353X AS353X 2096
+sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097
+at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098
+mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099
+cc9200 MACH_CC9200 CC9200 2100
+sm9200 MACH_SM9200 SM9200 2101
+tp9200 MACH_TP9200 TP9200 2102
+snapperdv MACH_SNAPPERDV SNAPPERDV 2103
+avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104
+avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105
+omap3axon MACH_OMAP3AXON OMAP3AXON 2106
+ma8xx MACH_MA8XX MA8XX 2107
+mp201ek MACH_MP201EK MP201EK 2108
+davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109
+mpa1600 MACH_MPA1600 MPA1600 2110
+pelco_troy MACH_PELCO_TROY PELCO_TROY 2111
+nsb667 MACH_NSB667 NSB667 2112
+rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113
+twocom MACH_TWOCOM TWOCOM 2114
+ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115
+hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116
+afeusb MACH_AFEUSB AFEUSB 2117
+t830 MACH_T830 T830 2118
+spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119
+om_3d7k MACH_OM_3D7K OM_3D7K 2120
+picocom2 MACH_PICOCOM2 PICOCOM2 2121
+uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122
+uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123
+cherry MACH_CHERRY CHERRY 2124
+mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125
+s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126
+tx37 MACH_TX37 TX37 2127
+sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128
+benzglb MACH_BENZGLB BENZGLB 2129
+benztd MACH_BENZTD BENZTD 2130
+cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131
+solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132
+mx27wallace MACH_MX27WALLACE MX27WALLACE 2133
+fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134
+rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135
+smallogger MACH_SMALLOGGER SMALLOGGER 2136
+ccw9p9215 MACH_CCW9P9215 CCW9P9215 2137
+dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138
+ts219 MACH_TS219 TS219 2139
+tny_a9263 MACH_TNY_A9263 TNY_A9263 2140
+apollo MACH_APOLLO APOLLO 2141
+at91cap9stk MACH_AT91CAP9STK AT91CAP9STK 2142
+spc300 MACH_SPC300 SPC300 2143
+eko MACH_EKO EKO 2144
+ccw9m2443 MACH_CCW9M2443 CCW9M2443 2145
+ccw9m2443js MACH_CCW9M2443JS CCW9M2443JS 2146
+m2m_router_device MACH_M2M_ROUTER_DEVICE M2M_ROUTER_DEVICE 2147
+str9104nas MACH_STAR9104NAS STAR9104NAS 2148
+pca100 MACH_PCA100 PCA100 2149
+z3_dm365_mod_01 MACH_Z3_DM365_MOD_01 Z3_DM365_MOD_01 2150
+hipox MACH_HIPOX HIPOX 2151
+omap3_piteds MACH_OMAP3_PITEDS OMAP3_PITEDS 2152
+bm150r MACH_BM150R BM150R 2153
+tbone MACH_TBONE TBONE 2154
+merlin MACH_MERLIN MERLIN 2155
+falcon MACH_FALCON FALCON 2156
+davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157
+s5p6440 MACH_S5P6440 S5P6440 2158
+at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159
+omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160
+lpc313x MACH_LPC313X LPC313X 2161
+magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162
+magx_em30 MACH_MAGX_EM30 MAGX_EM30 2163
+magx_ve66 MACH_MAGX_VE66 MAGX_VE66 2164
+meesc MACH_MEESC MEESC 2165
+otc570 MACH_OTC570 OTC570 2166
+bcu2412 MACH_BCU2412 BCU2412 2167
+beacon MACH_BEACON BEACON 2168
+actia_tgw MACH_ACTIA_TGW ACTIA_TGW 2169
+e4430 MACH_E4430 E4430 2170
+ql300 MACH_QL300 QL300 2171
+btmavb101 MACH_BTMAVB101 BTMAVB101 2172
+btmawb101 MACH_BTMAWB101 BTMAWB101 2173
+sq201 MACH_SQ201 SQ201 2174
+quatro45xx MACH_QUATRO45XX QUATRO45XX 2175
+openpad MACH_OPENPAD OPENPAD 2176
+tx25 MACH_TX25 TX25 2177
+omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178
+htcraphael_k MACH_HTCRAPHAEL_K HTCRAPHAEL_K 2179
+lal43 MACH_LAL43 LAL43 2181
+htcraphael_cdma500 MACH_HTCRAPHAEL_CDMA500 HTCRAPHAEL_CDMA500 2182
+anw6410 MACH_ANW6410 ANW6410 2183
+htcprophet MACH_HTCPROPHET HTCPROPHET 2185
+cfa_10022 MACH_CFA_10022 CFA_10022 2186
+imx27_visstrim_m10 MACH_IMX27_VISSTRIM_M10 IMX27_VISSTRIM_M10 2187
+px2imx27 MACH_PX2IMX27 PX2IMX27 2188
+stm3210e_eval MACH_STM3210E_EVAL STM3210E_EVAL 2189
+dvs10 MACH_DVS10 DVS10 2190
+portuxg20 MACH_PORTUXG20 PORTUXG20 2191
+arm_spv MACH_ARM_SPV ARM_SPV 2192
+smdkc110 MACH_SMDKC110 SMDKC110 2193
+cabespresso MACH_CABESPRESSO CABESPRESSO 2194
+hmc800 MACH_HMC800 HMC800 2195
+sholes MACH_SHOLES SHOLES 2196
+btmxc31 MACH_BTMXC31 BTMXC31 2197
+dt501 MACH_DT501 DT501 2198
+ktx MACH_KTX KTX 2199
+omap3517evm MACH_OMAP3517EVM OMAP3517EVM 2200
+netspace_v2 MACH_NETSPACE_V2 NETSPACE_V2 2201
+netspace_max_v2 MACH_NETSPACE_MAX_V2 NETSPACE_MAX_V2 2202
+d2net_v2 MACH_D2NET_V2 D2NET_V2 2203
+net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204
+net4big_v2 MACH_NET4BIG_V2 NET4BIG_V2 2205
+net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206
+endb2443 MACH_ENDB2443 ENDB2443 2207
+inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208
+tros MACH_TROS TROS 2209
+pelco_homer MACH_PELCO_HOMER PELCO_HOMER 2210
+ofsp8 MACH_OFSP8 OFSP8 2211
+at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212
+guf_cupid MACH_GUF_CUPID GUF_CUPID 2213
+eab1r MACH_EAB1R EAB1R 2214
+desirec MACH_DESIREC DESIREC 2215
+cordoba MACH_CORDOBA CORDOBA 2216
+irvine MACH_IRVINE IRVINE 2217
+sff772 MACH_SFF772 SFF772 2218
+pelco_milano MACH_PELCO_MILANO PELCO_MILANO 2219
+pc7302 MACH_PC7302 PC7302 2220
+bip6000 MACH_BIP6000 BIP6000 2221
+silvermoon MACH_SILVERMOON SILVERMOON 2222
+vc0830 MACH_VC0830 VC0830 2223
+dt430 MACH_DT430 DT430 2224
+ji42pf MACH_JI42PF JI42PF 2225
+gnet_ksm MACH_GNET_KSM GNET_KSM 2226
+gnet_sgm MACH_GNET_SGM GNET_SGM 2227
+gnet_sgr MACH_GNET_SGR GNET_SGR 2228
+omap3_icetekevm MACH_OMAP3_ICETEKEVM OMAP3_ICETEKEVM 2229
+pnp MACH_PNP PNP 2230
+ctera_2bay_k MACH_CTERA_2BAY_K CTERA_2BAY_K 2231
+ctera_2bay_u MACH_CTERA_2BAY_U CTERA_2BAY_U 2232
+sas_c MACH_SAS_C SAS_C 2233
+vma2315 MACH_VMA2315 VMA2315 2234
+vcs MACH_VCS VCS 2235
+spear600 MACH_SPEAR600 SPEAR600 2236
+spear300 MACH_SPEAR300 SPEAR300 2237
+spear1300 MACH_SPEAR1300 SPEAR1300 2238
+lilly1131 MACH_LILLY1131 LILLY1131 2239
+arvoo_ax301 MACH_ARVOO_AX301 ARVOO_AX301 2240
+mapphone MACH_MAPPHONE MAPPHONE 2241
+legend MACH_LEGEND LEGEND 2242
+salsa MACH_SALSA SALSA 2243
+lounge MACH_LOUNGE LOUNGE 2244
+vision MACH_VISION VISION 2245
+vmb20 MACH_VMB20 VMB20 2246
+hy2410 MACH_HY2410 HY2410 2247
+hy9315 MACH_HY9315 HY9315 2248
+bullwinkle MACH_BULLWINKLE BULLWINKLE 2249
+arm_ultimator2 MACH_ARM_ULTIMATOR2 ARM_ULTIMATOR2 2250
+vs_v210 MACH_VS_V210 VS_V210 2252
+vs_v212 MACH_VS_V212 VS_V212 2253
+hmt MACH_HMT HMT 2254
+km_kirkwood MACH_KM_KIRKWOOD KM_KIRKWOOD 2255
+vesper MACH_VESPER VESPER 2256
+str9 MACH_STR9 STR9 2257
+omap3_wl_ff MACH_OMAP3_WL_FF OMAP3_WL_FF 2258
+simcom MACH_SIMCOM SIMCOM 2259
+mcwebio MACH_MCWEBIO MCWEBIO 2260
+omap3_phrazer MACH_OMAP3_PHRAZER OMAP3_PHRAZER 2261
+darwin MACH_DARWIN DARWIN 2262
+oratiscomu MACH_ORATISCOMU ORATISCOMU 2263
+rtsbc20 MACH_RTSBC20 RTSBC20 2264
+sgh_i780 MACH_I780 I780 2265
+gemini324 MACH_GEMINI324 GEMINI324 2266
+oratislan MACH_ORATISLAN ORATISLAN 2267
+oratisalog MACH_ORATISALOG ORATISALOG 2268
+oratismadi MACH_ORATISMADI ORATISMADI 2269
+oratisot16 MACH_ORATISOT16 ORATISOT16 2270
+oratisdesk MACH_ORATISDESK ORATISDESK 2271
+vexpress MACH_VEXPRESS VEXPRESS 2272
+sintexo MACH_SINTEXO SINTEXO 2273
+cm3389 MACH_CM3389 CM3389 2274
+omap3_cio MACH_OMAP3_CIO OMAP3_CIO 2275
+sgh_i900 MACH_SGH_I900 SGH_I900 2276
+bst100 MACH_BST100 BST100 2277
+passion MACH_PASSION PASSION 2278
+indesign_at91sam MACH_INDESIGN_AT91SAM INDESIGN_AT91SAM 2279
+c4_badger MACH_C4_BADGER C4_BADGER 2280
+c4_viper MACH_C4_VIPER C4_VIPER 2281
+d2net MACH_D2NET D2NET 2282
+bigdisk MACH_BIGDISK BIGDISK 2283
+notalvision MACH_NOTALVISION NOTALVISION 2284
+omap3_kboc MACH_OMAP3_KBOC OMAP3_KBOC 2285
+cyclone MACH_CYCLONE CYCLONE 2286
+ninja MACH_NINJA NINJA 2287
+at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288
+bcmring MACH_BCMRING BCMRING 2289
+resol_dl2 MACH_RESOL_DL2 RESOL_DL2 2290
+ifosw MACH_IFOSW IFOSW 2291
+htcrhodium MACH_HTCRHODIUM HTCRHODIUM 2292
+htctopaz MACH_HTCTOPAZ HTCTOPAZ 2293
+matrix504 MACH_MATRIX504 MATRIX504 2294
+mrfsa MACH_MRFSA MRFSA 2295
+sc_p270 MACH_SC_P270 SC_P270 2296
+atlas5_evb MACH_ATLAS5_EVB ATLAS5_EVB 2297
+pelco_lobox MACH_PELCO_LOBOX PELCO_LOBOX 2298
+dilax_pcu200 MACH_DILAX_PCU200 DILAX_PCU200 2299
+leonardo MACH_LEONARDO LEONARDO 2300
+zoran_approach7 MACH_ZORAN_APPROACH7 ZORAN_APPROACH7 2301
+dp6xx MACH_DP6XX DP6XX 2302
+bcm2153_vesper MACH_BCM2153_VESPER BCM2153_VESPER 2303
+mahimahi MACH_MAHIMAHI MAHIMAHI 2304
+clickc MACH_CLICKC CLICKC 2305
+zb_gateway MACH_ZB_GATEWAY ZB_GATEWAY 2306
+tazcard MACH_TAZCARD TAZCARD 2307
+tazdev MACH_TAZDEV TAZDEV 2308
+annax_cb_arm MACH_ANNAX_CB_ARM ANNAX_CB_ARM 2309
+annax_dm3 MACH_ANNAX_DM3 ANNAX_DM3 2310
+cerebric MACH_CEREBRIC CEREBRIC 2311
+orca MACH_ORCA ORCA 2312
+pc9260 MACH_PC9260 PC9260 2313
+ems285a MACH_EMS285A EMS285A 2314
+gec2410 MACH_GEC2410 GEC2410 2315
+gec2440 MACH_GEC2440 GEC2440 2316
+mw903 MACH_ARCH_MW903 ARCH_MW903 2317
+mw2440 MACH_MW2440 MW2440 2318
+ecac2378 MACH_ECAC2378 ECAC2378 2319
+tazkiosk MACH_TAZKIOSK TAZKIOSK 2320
+whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321
+sbox9263 MACH_SBOX9263 SBOX9263 2322
+smdk6442 MACH_SMDK6442 SMDK6442 2324
+openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325
+incredible MACH_INCREDIBLE INCREDIBLE 2326
+incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327
+heroct MACH_HEROCT HEROCT 2328
+mmnet1000 MACH_MMNET1000 MMNET1000 2329
+devkit8000 MACH_DEVKIT8000 DEVKIT8000 2330
+devkit9000 MACH_DEVKIT9000 DEVKIT9000 2331
+mx31txtr MACH_MX31TXTR MX31TXTR 2332
+u380 MACH_U380 U380 2333
+oamp3_hualu MACH_HUALU_BOARD HUALU_BOARD 2334
+npcmx50 MACH_NPCMX50 NPCMX50 2335
+mx51_efikamx MACH_MX51_EFIKAMX MX51_EFIKAMX 2336
+mx51_lange52 MACH_MX51_LANGE52 MX51_LANGE52 2337
+riom MACH_RIOM RIOM 2338
+comcas MACH_COMCAS COMCAS 2339
+wsi_mx27 MACH_WSI_MX27 WSI_MX27 2340
+cm_t35 MACH_CM_T35 CM_T35 2341
+net2big MACH_NET2BIG NET2BIG 2342
+motorola_a1600 MACH_MOTOROLA_A1600 MOTOROLA_A1600 2343
+igep0020 MACH_IGEP0020 IGEP0020 2344
+igep0010 MACH_IGEP0010 IGEP0010 2345
+mv6281gtwge2 MACH_MV6281GTWGE2 MV6281GTWGE2 2346
+scat100 MACH_SCAT100 SCAT100 2347
+sanmina MACH_SANMINA SANMINA 2348
+momento MACH_MOMENTO MOMENTO 2349
+nuc9xx MACH_NUC9XX NUC9XX 2350
+nuc910evb MACH_NUC910EVB NUC910EVB 2351
+nuc920evb MACH_NUC920EVB NUC920EVB 2352
+nuc950evb MACH_NUC950EVB NUC950EVB 2353
+nuc945evb MACH_NUC945EVB NUC945EVB 2354
+nuc960evb MACH_NUC960EVB NUC960EVB 2355
+nuc932evb MACH_NUC932EVB NUC932EVB 2356
+nuc900 MACH_NUC900 NUC900 2357
+sd1soc MACH_SD1SOC SD1SOC 2358
+ln2440bc MACH_LN2440BC LN2440BC 2359
+rsbc MACH_RSBC RSBC 2360
+openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361
+hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362
+wayland MACH_WAYLAND WAYLAND 2363
+acnbsx102 MACH_ACNBSX102 ACNBSX102 2364
+hwat91 MACH_HWAT91 HWAT91 2365
+at91sam9263cs MACH_AT91SAM9263CS AT91SAM9263CS 2366
+csb732 MACH_CSB732 CSB732 2367
+u8500 MACH_U8500 U8500 2368
+huqiu MACH_HUQIU HUQIU 2369
+mx51_efikasb MACH_MX51_EFIKASB MX51_EFIKASB 2370
+pmt1g MACH_PMT1G PMT1G 2371
+htcelf MACH_HTCELF HTCELF 2372
+armadillo420 MACH_ARMADILLO420 ARMADILLO420 2373
+armadillo440 MACH_ARMADILLO440 ARMADILLO440 2374
+u_chip_dual_arm MACH_U_CHIP_DUAL_ARM U_CHIP_DUAL_ARM 2375
+csr_bdb3 MACH_CSR_BDB3 CSR_BDB3 2376
+dolby_cat1018 MACH_DOLBY_CAT1018 DOLBY_CAT1018 2377
+hy9307 MACH_HY9307 HY9307 2378
+aspire_easystore MACH_A_ES A_ES 2379
+davinci_irif MACH_DAVINCI_IRIF DAVINCI_IRIF 2380
+agama9263 MACH_AGAMA9263 AGAMA9263 2381
+marvell_jasper MACH_MARVELL_JASPER MARVELL_JASPER 2382
+flint MACH_FLINT FLINT 2383
+tavorevb3 MACH_TAVOREVB3 TAVOREVB3 2384
+sch_m490 MACH_SCH_M490 SCH_M490 2386
+rbl01 MACH_RBL01 RBL01 2387
+omnifi MACH_OMNIFI OMNIFI 2388
+otavalo MACH_OTAVALO OTAVALO 2389
+htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391
+htc_opal MACH_HTC_OPAL HTC_OPAL 2392
+touchbook MACH_TOUCHBOOK TOUCHBOOK 2393
+latte MACH_LATTE LATTE 2394
+xa200 MACH_XA200 XA200 2395
+nimrod MACH_NIMROD NIMROD 2396
+cc9p9215_3g MACH_CC9P9215_3G CC9P9215_3G 2397
+cc9p9215_3gjs MACH_CC9P9215_3GJS CC9P9215_3GJS 2398
+tk71 MACH_TK71 TK71 2399
+comham3525 MACH_COMHAM3525 COMHAM3525 2400
+mx31erebus MACH_MX31EREBUS MX31EREBUS 2401
+mcardmx27 MACH_MCARDMX27 MCARDMX27 2402
+paradise MACH_PARADISE PARADISE 2403
+tide MACH_TIDE TIDE 2404
+wzl2440 MACH_WZL2440 WZL2440 2405
+sdrdemo MACH_SDRDEMO SDRDEMO 2406
+ethercan2 MACH_ETHERCAN2 ETHERCAN2 2407
+ecmimg20 MACH_ECMIMG20 ECMIMG20 2408
+omap_dragon MACH_OMAP_DRAGON OMAP_DRAGON 2409
+halo MACH_HALO HALO 2410
+huangshan MACH_HUANGSHAN HUANGSHAN 2411
+vl_ma2sc MACH_VL_MA2SC VL_MA2SC 2412
+raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413
+raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414
+raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415
+multibus_master MACH_MULTIBUS_MASTER MULTIBUS_MASTER 2416
+multibus_pbk MACH_MULTIBUS_PBK MULTIBUS_PBK 2417
+tnetv107x MACH_TNETV107X TNETV107X 2418
+snake MACH_SNAKE SNAKE 2419
+cwmx27 MACH_CWMX27 CWMX27 2420
+sch_m480 MACH_SCH_M480 SCH_M480 2421
+platypus MACH_PLATYPUS PLATYPUS 2422
+pss2 MACH_PSS2 PSS2 2423
+davinci_apm150 MACH_DAVINCI_APM150 DAVINCI_APM150 2424
+str9100 MACH_STR9100 STR9100 2425
+net5big MACH_NET5BIG NET5BIG 2426
+seabed9263 MACH_SEABED9263 SEABED9263 2427
+mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428
+octvocplus_eb MACH_OCTVOCPLUS_EB OCTVOCPLUS_EB 2429
+klk_firefox MACH_KLK_FIREFOX KLK_FIREFOX 2430
+klk_wirma_module MACH_KLK_WIRMA_MODULE KLK_WIRMA_MODULE 2431
+klk_wirma_mmi MACH_KLK_WIRMA_MMI KLK_WIRMA_MMI 2432
+supersonic MACH_SUPERSONIC SUPERSONIC 2433
+liberty MACH_LIBERTY LIBERTY 2434
+mh355 MACH_MH355 MH355 2435
+pc7802 MACH_PC7802 PC7802 2436
+gnet_sgc MACH_GNET_SGC GNET_SGC 2437
+einstein15 MACH_EINSTEIN15 EINSTEIN15 2438
+cmpd MACH_CMPD CMPD 2439
+davinci_hase1 MACH_DAVINCI_HASE1 DAVINCI_HASE1 2440
+lgeincitephone MACH_LGEINCITEPHONE LGEINCITEPHONE 2441
+ea313x MACH_EA313X EA313X 2442
+fwbd_39064 MACH_FWBD_39064 FWBD_39064 2443
+fwbd_390128 MACH_FWBD_390128 FWBD_390128 2444
+pelco_moe MACH_PELCO_MOE PELCO_MOE 2445
+minimix27 MACH_MINIMIX27 MINIMIX27 2446
+omap3_thunder MACH_OMAP3_THUNDER OMAP3_THUNDER 2447
+passionc MACH_PASSIONC PASSIONC 2448
+mx27amata MACH_MX27AMATA MX27AMATA 2449
+bgat1 MACH_BGAT1 BGAT1 2450
+buzz MACH_BUZZ BUZZ 2451
+mb9g20 MACH_MB9G20 MB9G20 2452
+yushan MACH_YUSHAN YUSHAN 2453
+lizard MACH_LIZARD LIZARD 2454
+omap3polycom MACH_OMAP3POLYCOM OMAP3POLYCOM 2455
+smdkv210 MACH_SMDKV210 SMDKV210 2456
+bravo MACH_BRAVO BRAVO 2457
+siogentoo1 MACH_SIOGENTOO1 SIOGENTOO1 2458
+siogentoo2 MACH_SIOGENTOO2 SIOGENTOO2 2459
+sm3k MACH_SM3K SM3K 2460
+acer_tempo_f900 MACH_ACER_TEMPO_F900 ACER_TEMPO_F900 2461
+glittertind MACH_GLITTERTIND GLITTERTIND 2463
+omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464
+omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465
+cybook2440 MACH_CYBOOK2440 CYBOOK2440 2466
+torino_s MACH_TORINO_S TORINO_S 2467
+havana MACH_HAVANA HAVANA 2468
+beaumont_11 MACH_BEAUMONT_11 BEAUMONT_11 2469
+vanguard MACH_VANGUARD VANGUARD 2470
+s5pc110_draco MACH_S5PC110_DRACO S5PC110_DRACO 2471
+cartesio_two MACH_CARTESIO_TWO CARTESIO_TWO 2472
+aster MACH_ASTER ASTER 2473
+voguesv210 MACH_VOGUESV210 VOGUESV210 2474
+acm500x MACH_ACM500X ACM500X 2475
+km9260 MACH_KM9260 KM9260 2476
+nideflexg1 MACH_NIDEFLEXG1 NIDEFLEXG1 2477
+ctera_plug_io MACH_CTERA_PLUG_IO CTERA_PLUG_IO 2478
+smartq7 MACH_SMARTQ7 SMARTQ7 2479
+at91sam9g10ek2 MACH_AT91SAM9G10EK2 AT91SAM9G10EK2 2480
+asusp527 MACH_ASUSP527 ASUSP527 2481
+at91sam9g20mpm2 MACH_AT91SAM9G20MPM2 AT91SAM9G20MPM2 2482
+topasa900 MACH_TOPASA900 TOPASA900 2483
+electrum_100 MACH_ELECTRUM_100 ELECTRUM_100 2484
+mx51grb MACH_MX51GRB MX51GRB 2485
+xea300 MACH_XEA300 XEA300 2486
+htcstartrek MACH_HTCSTARTREK HTCSTARTREK 2487
+lima MACH_LIMA LIMA 2488
+csb740 MACH_CSB740 CSB740 2489
+usb_s8815 MACH_USB_S8815 USB_S8815 2490
+watson_efm_plugin MACH_WATSON_EFM_PLUGIN WATSON_EFM_PLUGIN 2491
+milkyway MACH_MILKYWAY MILKYWAY 2492
+g4evm MACH_G4EVM G4EVM 2493
+picomod6 MACH_PICOMOD6 PICOMOD6 2494
+omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495
+ip6000 MACH_IP6000 IP6000 2496
+ip6010 MACH_IP6010 IP6010 2497
+utm400 MACH_UTM400 UTM400 2498
+omap3_zybex MACH_OMAP3_ZYBEX OMAP3_ZYBEX 2499
+wireless_space MACH_WIRELESS_SPACE WIRELESS_SPACE 2500
+sx560 MACH_SX560 SX560 2501
+ts41x MACH_TS41X TS41X 2502
+elphel10373 MACH_ELPHEL10373 ELPHEL10373 2503
+rhobot MACH_RHOBOT RHOBOT 2504
+mx51_refresh MACH_MX51_REFRESH MX51_REFRESH 2505
+ls9260 MACH_LS9260 LS9260 2506
+shank MACH_SHANK SHANK 2507
+qsd8x50_st1 MACH_QSD8X50_ST1 QSD8X50_ST1 2508
+at91sam9m10ekes MACH_AT91SAM9M10EKES AT91SAM9M10EKES 2509
+hiram MACH_HIRAM HIRAM 2510
+phy3250 MACH_PHY3250 PHY3250 2511
+ea3250 MACH_EA3250 EA3250 2512
+fdi3250 MACH_FDI3250 FDI3250 2513
+at91sam9263nit MACH_AT91SAM9263NIT AT91SAM9263NIT 2515
+ccmx51 MACH_CCMX51 CCMX51 2516
+ccmx51js MACH_CCMX51JS CCMX51JS 2517
+ccwmx51 MACH_CCWMX51 CCWMX51 2518
+ccwmx51js MACH_CCWMX51JS CCWMX51JS 2519
+mini6410 MACH_MINI6410 MINI6410 2520
+tiny6410 MACH_TINY6410 TINY6410 2521
+nano6410 MACH_NANO6410 NANO6410 2522
+at572d940hfnldb MACH_AT572D940HFNLDB AT572D940HFNLDB 2523
+htcleo MACH_HTCLEO HTCLEO 2524
+avp13 MACH_AVP13 AVP13 2525
+xxsvideod MACH_XXSVIDEOD XXSVIDEOD 2526
+vpnext MACH_VPNEXT VPNEXT 2527
+swarco_itc3 MACH_SWARCO_ITC3 SWARCO_ITC3 2528
+tx51 MACH_TX51 TX51 2529
+dolby_cat1021 MACH_DOLBY_CAT1021 DOLBY_CAT1021 2530
+mx28evk MACH_MX28EVK MX28EVK 2531
+phoenix260 MACH_PHOENIX260 PHOENIX260 2532
+uvaca_stork MACH_UVACA_STORK UVACA_STORK 2533
+smartq5 MACH_SMARTQ5 SMARTQ5 2534
+all3078 MACH_ALL3078 ALL3078 2535
+ctera_2bay_ds MACH_CTERA_2BAY_DS CTERA_2BAY_DS 2536
+siogentoo3 MACH_SIOGENTOO3 SIOGENTOO3 2537
+epb5000 MACH_EPB5000 EPB5000 2538
+hy9263 MACH_HY9263 HY9263 2539
+acer_tempo_m900 MACH_ACER_TEMPO_M900 ACER_TEMPO_M900 2540
+acer_tempo_dx650 MACH_ACER_TEMPO_DX900 ACER_TEMPO_DX900 2541
+acer_tempo_x960 MACH_ACER_TEMPO_X960 ACER_TEMPO_X960 2542
+acer_eten_v900 MACH_ACER_ETEN_V900 ACER_ETEN_V900 2543
+acer_eten_x900 MACH_ACER_ETEN_X900 ACER_ETEN_X900 2544
+bonnell MACH_BONNELL BONNELL 2545
+oht_mx27 MACH_OHT_MX27 OHT_MX27 2546
+htcquartz MACH_HTCQUARTZ HTCQUARTZ 2547
+davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548
+c3ax03 MACH_C3AX03 C3AX03 2549
+mxt_td60 MACH_MXT_TD60 MXT_TD60 2550
+esyx MACH_ESYX ESYX 2551
+dove_db2 MACH_DOVE_DB2 DOVE_DB2 2552
+bulldog MACH_BULLDOG BULLDOG 2553
+derell_me2000 MACH_DERELL_ME2000 DERELL_ME2000 2554
+bcmring_base MACH_BCMRING_BASE BCMRING_BASE 2555
+bcmring_evm MACH_BCMRING_EVM BCMRING_EVM 2556
+bcmring_evm_jazz MACH_BCMRING_EVM_JAZZ BCMRING_EVM_JAZZ 2557
+bcmring_sp MACH_BCMRING_SP BCMRING_SP 2558
+bcmring_sv MACH_BCMRING_SV BCMRING_SV 2559
+bcmring_sv_jazz MACH_BCMRING_SV_JAZZ BCMRING_SV_JAZZ 2560
+bcmring_tablet MACH_BCMRING_TABLET BCMRING_TABLET 2561
+bcmring_vp MACH_BCMRING_VP BCMRING_VP 2562
+bcmring_evm_seikor MACH_BCMRING_EVM_SEIKOR BCMRING_EVM_SEIKOR 2563
+bcmring_sp_wqvga MACH_BCMRING_SP_WQVGA BCMRING_SP_WQVGA 2564
+bcmring_custom MACH_BCMRING_CUSTOM BCMRING_CUSTOM 2565
+acer_s200 MACH_ACER_S200 ACER_S200 2566
+bt270 MACH_BT270 BT270 2567
+iseo MACH_ISEO ISEO 2568
+cezanne MACH_CEZANNE CEZANNE 2569
+lucca MACH_LUCCA LUCCA 2570
+supersmart MACH_SUPERSMART SUPERSMART 2571
+arm11_board MACH_CS_MISANO CS_MISANO 2572
+magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573
+emxx MACH_EMXX EMXX 2574
+outlaw MACH_OUTLAW OUTLAW 2575
+riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576
+riot_gx2 MACH_RIOT_VOX RIOT_VOX 2577
+riot_x37 MACH_RIOT_X37 RIOT_X37 2578
+mega25mx MACH_MEGA25MX MEGA25MX 2579
+benzina2 MACH_BENZINA2 BENZINA2 2580
+ignite MACH_IGNITE IGNITE 2581
+foggia MACH_FOGGIA FOGGIA 2582
+arezzo MACH_AREZZO AREZZO 2583
+leica_skywalker MACH_LEICA_SKYWALKER LEICA_SKYWALKER 2584
+jacinto2_jamr MACH_JACINTO2_JAMR JACINTO2_JAMR 2585
+gts_nova MACH_GTS_NOVA GTS_NOVA 2586
+p3600 MACH_P3600 P3600 2587
+dlt2 MACH_DLT2 DLT2 2588
+df3120 MACH_DF3120 DF3120 2589
+ecucore_9g20 MACH_ECUCORE_9G20 ECUCORE_9G20 2590
+nautel_am35xx MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591
+glacier MACH_GLACIER GLACIER 2592
+phrazer_bulldog MACH_PHRAZER_BULLDOG PHRAZER_BULLDOG 2593
+omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594
+pca101 MACH_PCA101 PCA101 2595
+buzzc MACH_BUZZC BUZZC 2596
+sasie2 MACH_SASIE2 SASIE2 2597
+smartmeter_dl MACH_SMARTMETER_DL SMARTMETER_DL 2599
+wzl6410 MACH_WZL6410 WZL6410 2600
+wzl6410m MACH_WZL6410M WZL6410M 2601
+wzl6410f MACH_WZL6410F WZL6410F 2602
+wzl6410i MACH_WZL6410I WZL6410I 2603
+spacecom1 MACH_SPACECOM1 SPACECOM1 2604
+pingu920 MACH_PINGU920 PINGU920 2605
+bravoc MACH_BRAVOC BRAVOC 2606
+vdssw MACH_VDSSW VDSSW 2608
+romulus MACH_ROMULUS ROMULUS 2609
+omap_magic MACH_OMAP_MAGIC OMAP_MAGIC 2610
+eltd100 MACH_ELTD100 ELTD100 2611
+capc7117 MACH_CAPC7117 CAPC7117 2612
+swan MACH_SWAN SWAN 2613
+veu MACH_VEU VEU 2614
+rm2 MACH_RM2 RM2 2615
+tt2100 MACH_TT2100 TT2100 2616
+venice MACH_VENICE VENICE 2617
+pc7323 MACH_PC7323 PC7323 2618
+masp MACH_MASP MASP 2619
+fujitsu_tvstbsoc0 MACH_FUJITSU_TVSTBSOC FUJITSU_TVSTBSOC 2620
+fujitsu_tvstbsoc1 MACH_FUJITSU_TVSTBSOC1 FUJITSU_TVSTBSOC1 2621
+lexikon MACH_LEXIKON LEXIKON 2622
+mini2440v2 MACH_MINI2440V2 MINI2440V2 2623
+icontrol MACH_ICONTROL ICONTROL 2624
+gplugd MACH_GPLUGD GPLUGD 2625
+qsd8x50a_st1_1 MACH_QSD8X50A_ST1_1 QSD8X50A_ST1_1 2626
+qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627
+bee MACH_BEE BEE 2628
+mx23evk MACH_MX23EVK MX23EVK 2629
+ap4evb MACH_AP4EVB AP4EVB 2630
+stockholm MACH_STOCKHOLM STOCKHOLM 2631
+lpc_h3131 MACH_LPC_H3131 LPC_H3131 2632
+stingray MACH_STINGRAY STINGRAY 2633
+kraken MACH_KRAKEN KRAKEN 2634
+gw2388 MACH_GW2388 GW2388 2635
+jadecpu MACH_JADECPU JADECPU 2636
+carlisle MACH_CARLISLE CARLISLE 2637
+lux_sf9 MACH_LUX_SF9 LUX_SF9 2638
+nemid_tb MACH_NEMID_TB NEMID_TB 2639
+terrier MACH_TERRIER TERRIER 2640
+turbot MACH_TURBOT TURBOT 2641
+sanddab MACH_SANDDAB SANDDAB 2642
+mx35_cicada MACH_MX35_CICADA MX35_CICADA 2643
+ghi2703d MACH_GHI2703D GHI2703D 2644
+lux_sfx9 MACH_LUX_SFX9 LUX_SFX9 2645
+lux_sf9g MACH_LUX_SF9G LUX_SF9G 2646
+lux_edk9 MACH_LUX_EDK9 LUX_EDK9 2647
+hw90240 MACH_HW90240 HW90240 2648
+dm365_leopard MACH_DM365_LEOPARD DM365_LEOPARD 2649
+mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650
+scat110 MACH_SCAT110 SCAT110 2651
+acer_a1 MACH_ACER_A1 ACER_A1 2652
+cmcontrol MACH_CMCONTROL CMCONTROL 2653
+pelco_lamar MACH_PELCO_LAMAR PELCO_LAMAR 2654
+rfp43 MACH_RFP43 RFP43 2655
+sk86r0301 MACH_SK86R0301 SK86R0301 2656
+ctpxa MACH_CTPXA CTPXA 2657
+epb_arm9_a MACH_EPB_ARM9_A EPB_ARM9_A 2658
+guruplug MACH_GURUPLUG GURUPLUG 2659
+spear310 MACH_SPEAR310 SPEAR310 2660
+spear320 MACH_SPEAR320 SPEAR320 2661
+robotx MACH_ROBOTX ROBOTX 2662
+lsxhl MACH_LSXHL LSXHL 2663
+smartlite MACH_SMARTLITE SMARTLITE 2664
+cws2 MACH_CWS2 CWS2 2665
+m619 MACH_M619 M619 2666
+smartview MACH_SMARTVIEW SMARTVIEW 2667
+lsa_salsa MACH_LSA_SALSA LSA_SALSA 2668
+kizbox MACH_KIZBOX KIZBOX 2669
+htccharmer MACH_HTCCHARMER HTCCHARMER 2670
+guf_neso_lt MACH_GUF_NESO_LT GUF_NESO_LT 2671
+pm9g45 MACH_PM9G45 PM9G45 2672
+htcpanther MACH_HTCPANTHER HTCPANTHER 2673
+htcpanther_cdma MACH_HTCPANTHER_CDMA HTCPANTHER_CDMA 2674
+reb01 MACH_REB01 REB01 2675
+aquila MACH_AQUILA AQUILA 2676
+spark_sls_hw2 MACH_SPARK_SLS_HW2 SPARK_SLS_HW2 2677
+esata_sheevaplug MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678
+msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679
+micro2440 MACH_MICRO2440 MICRO2440 2680
+am2440 MACH_AM2440 AM2440 2681
+tq2440 MACH_TQ2440 TQ2440 2682
+ea2478devkit MACH_EA2478DEVKIT EA2478DEVKIT 2683
+ak880x MACH_AK880X AK880X 2684
+cobra3530 MACH_COBRA3530 COBRA3530 2685
+pmppb MACH_PMPPB PMPPB 2686
+u6715 MACH_U6715 U6715 2687
+axar1500_sender MACH_AXAR1500_SENDER AXAR1500_SENDER 2688
+g30_dvb MACH_G30_DVB G30_DVB 2689
+vc088x MACH_VC088X VC088X 2690
+mioa702 MACH_MIOA702 MIOA702 2691
+hpmin MACH_HPMIN HPMIN 2692
+ak880xak MACH_AK880XAK AK880XAK 2693
+arm926tomap850 MACH_ARM926TOMAP850 ARM926TOMAP850 2694
+lkevm MACH_LKEVM LKEVM 2695
+mw6410 MACH_MW6410 MW6410 2696
+terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697
+cpu8000e MACH_CPU8000E CPU8000E 2698
+tokyo MACH_TOKYO TOKYO 2700
+msm7201a_surf MACH_MSM7201A_SURF MSM7201A_SURF 2701
+msm7201a_ffa MACH_MSM7201A_FFA MSM7201A_FFA 2702
+msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703
+msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704
+msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705
+msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706
+msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707
+qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708
+qsd8x50_comet MACH_QSD8X50_COMET QSD8X50_COMET 2709
+qsd8x50_ffa MACH_QSD8X50_FFA QSD8X50_FFA 2710
+qsd8x50a_surf MACH_QSD8X50A_SURF QSD8X50A_SURF 2711
+qsd8x50a_ffa MACH_QSD8X50A_FFA QSD8X50A_FFA 2712
+adx_xgcp10 MACH_ADX_XGCP10 ADX_XGCP10 2713
+mcgwumts2a MACH_MCGWUMTS2A MCGWUMTS2A 2714
+mobikt MACH_MOBIKT MOBIKT 2715
+mx53_evk MACH_MX53_EVK MX53_EVK 2716
+igep0030 MACH_IGEP0030 IGEP0030 2717
+axell_h40_h50_ctrl MACH_AXELL_H40_H50_CTRL AXELL_H40_H50_CTRL 2718
+dtcommod MACH_DTCOMMOD DTCOMMOD 2719
+gould MACH_GOULD GOULD 2720
+siberia MACH_SIBERIA SIBERIA 2721
+sbc3530 MACH_SBC3530 SBC3530 2722
+qarm MACH_QARM QARM 2723
+mips MACH_MIPS MIPS 2724
+mx27grb MACH_MX27GRB MX27GRB 2725
+sbc8100 MACH_SBC8100 SBC8100 2726
+saarb MACH_SAARB SAARB 2727
+omap3mini MACH_OMAP3MINI OMAP3MINI 2728
+cnmbook7se MACH_CNMBOOK7SE CNMBOOK7SE 2729
+catan MACH_CATAN CATAN 2730
+harmony MACH_HARMONY HARMONY 2731
+tonga MACH_TONGA TONGA 2732
+cybook_orizon MACH_CYBOOK_ORIZON CYBOOK_ORIZON 2733
+htcrhodiumcdma MACH_HTCRHODIUMCDMA HTCRHODIUMCDMA 2734
+epc_g45 MACH_EPC_G45 EPC_G45 2735
+epc_lpc3250 MACH_EPC_LPC3250 EPC_LPC3250 2736
+mxc91341evb MACH_MXC91341EVB MXC91341EVB 2737
+rtw1000 MACH_RTW1000 RTW1000 2738
+bobcat MACH_BOBCAT BOBCAT 2739
+trizeps6 MACH_TRIZEPS6 TRIZEPS6 2740
+msm7x30_fluid MACH_MSM7X30_FLUID MSM7X30_FLUID 2741
+nedap9263 MACH_NEDAP9263 NEDAP9263 2742
+netgear_ms2110 MACH_NETGEAR_MS2110 NETGEAR_MS2110 2743
+bmx MACH_BMX BMX 2744
+netstream MACH_NETSTREAM NETSTREAM 2745
+vpnext_rcu MACH_VPNEXT_RCU VPNEXT_RCU 2746
+vpnext_mpu MACH_VPNEXT_MPU VPNEXT_MPU 2747
+bcmring_tablet_v1 MACH_BCMRING_TABLET_V1 BCMRING_TABLET_V1 2748
+sgarm10 MACH_SGARM10 SGARM10 2749
+cm_t3517 MACH_CM_T3517 CM_T3517 2750
+dig297 MACH_OMAP3_CPS OMAP3_CPS 2751
+axar1500_receiver MACH_AXAR1500_RECEIVER AXAR1500_RECEIVER 2752
+wbd222 MACH_WBD222 WBD222 2753
+mt65xx MACH_MT65XX MT65XX 2754
+msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755
+msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756
+tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758
+nanos MACH_NANOS NANOS 2759
+stamp9g10 MACH_STAMP9G10 STAMP9G10 2760
+stamp9g45 MACH_STAMP9G45 STAMP9G45 2761
+h6053 MACH_H6053 H6053 2762
+smint01 MACH_SMINT01 SMINT01 2763
+prtlvt2 MACH_PRTLVT2 PRTLVT2 2764
+ap420 MACH_AP420 AP420 2765
+davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767
+msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768
+msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769
+esl_vamana MACH_ESL_VAMANA ESL_VAMANA 2770
+sbc35 MACH_SBC35 SBC35 2771
+mpx6446 MACH_MPX6446 MPX6446 2772
+oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773
+kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774
+ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775
+cns3420vb MACH_CNS3420VB CNS3420VB 2776
+lpc_evo MACH_LPC2 LPC2 2777
+olympus MACH_OLYMPUS OLYMPUS 2778
+vortex MACH_VORTEX VORTEX 2779
+s5pc200 MACH_S5PC200 S5PC200 2780
+ecucore_9263 MACH_ECUCORE_9263 ECUCORE_9263 2781
+smdkc200 MACH_SMDKC200 SMDKC200 2782
+emsiso_sx27 MACH_EMSISO_SX27 EMSISO_SX27 2783
+apx_som9g45_ek MACH_APX_SOM9G45_EK APX_SOM9G45_EK 2784
+songshan MACH_SONGSHAN SONGSHAN 2785
+tianshan MACH_TIANSHAN TIANSHAN 2786
+vpx500 MACH_VPX500 VPX500 2787
+am3517sam MACH_AM3517SAM AM3517SAM 2788
+skat91_sim508 MACH_SKAT91_SIM508 SKAT91_SIM508 2789
+skat91_s3e MACH_SKAT91_S3E SKAT91_S3E 2790
+omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791
+df7220 MACH_DF7220 DF7220 2792
+nemini MACH_NEMINI NEMINI 2793
+t8200 MACH_T8200 T8200 2794
+apf51 MACH_APF51 APF51 2795
+dr_rc_unit MACH_DR_RC_UNIT DR_RC_UNIT 2796
+bordeaux MACH_BORDEAUX BORDEAUX 2797
+catania_b MACH_CATANIA_B CATANIA_B 2798
+mx51_ocean MACH_MX51_OCEAN MX51_OCEAN 2799
+ti8168evm MACH_TI8168EVM TI8168EVM 2800
+neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801
+withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802
+dbps MACH_DBPS DBPS 2803
+pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805
+speedy MACH_SPEEDY SPEEDY 2806
+chrysaor MACH_CHRYSAOR CHRYSAOR 2807
+tango MACH_TANGO TANGO 2808
+synology_dsx11 MACH_SYNOLOGY_DSX11 SYNOLOGY_DSX11 2809
+hanlin_v3ext MACH_HANLIN_V3EXT HANLIN_V3EXT 2810
+hanlin_v5 MACH_HANLIN_V5 HANLIN_V5 2811
+hanlin_v3plus MACH_HANLIN_V3PLUS HANLIN_V3PLUS 2812
+iriver_story MACH_IRIVER_STORY IRIVER_STORY 2813
+irex_iliad MACH_IREX_ILIAD IREX_ILIAD 2814
+irex_dr1000 MACH_IREX_DR1000 IREX_DR1000 2815
+teton_bga MACH_TETON_BGA TETON_BGA 2816
+snapper9g45 MACH_SNAPPER9G45 SNAPPER9G45 2817
+tam3517 MACH_TAM3517 TAM3517 2818
+pdc100 MACH_PDC100 PDC100 2819
+eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25SD EUKREA_CPUIMX25SD 2820
+eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35SD EUKREA_CPUIMX35SD 2821
+eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822
+eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823
+p565 MACH_P565 P565 2824
+acer_a4 MACH_ACER_A4 ACER_A4 2825
+davinci_dm368_bip MACH_DAVINCI_DM368_BIP DAVINCI_DM368_BIP 2826
+eshare MACH_ESHARE ESHARE 2827
+wlbargn MACH_WLBARGN WLBARGN 2829
+bm170 MACH_BM170 BM170 2830
+netspace_mini_v2 MACH_NETSPACE_MINI_V2 NETSPACE_MINI_V2 2831
+netspace_plug_v2 MACH_NETSPACE_PLUG_V2 NETSPACE_PLUG_V2 2832
+siemens_l1 MACH_SIEMENS_L1 SIEMENS_L1 2833
+elv_lcu1 MACH_ELV_LCU1 ELV_LCU1 2834
+mcu1 MACH_MCU1 MCU1 2835
+omap3_tao3530 MACH_OMAP3_TAO3530 OMAP3_TAO3530 2836
+omap3_pcutouch MACH_OMAP3_PCUTOUCH OMAP3_PCUTOUCH 2837
+smdkc210 MACH_SMDKC210 SMDKC210 2838
+omap3_braillo MACH_OMAP3_BRAILLO OMAP3_BRAILLO 2839
+spyplug MACH_SPYPLUG SPYPLUG 2840
+ginger MACH_GINGER GINGER 2841
+tny_t3530 MACH_TNY_T3530 TNY_T3530 2842
+pcaal1 MACH_PCAAL1 PCAAL1 2843
+spade MACH_SPADE SPADE 2844
+mxc25_topaz MACH_MXC25_TOPAZ MXC25_TOPAZ 2845
+t5325 MACH_T5325 T5325 2846
+gw2361 MACH_GW2361 GW2361 2847
+elog MACH_ELOG ELOG 2848
+income MACH_INCOME INCOME 2849
+bcm589x MACH_BCM589X BCM589X 2850
+etna MACH_ETNA ETNA 2851
+hawks MACH_HAWKS HAWKS 2852
+meson MACH_MESON MESON 2853
+xsbase255 MACH_XSBASE255 XSBASE255 2854
+pvm2030 MACH_PVM2030 PVM2030 2855
+mioa502 MACH_MIOA502 MIOA502 2856
+vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857
+vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858
+vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859
+htc_spv_m700 MACH_HTC_SPV_M700 HTC_SPV_M700 2860
+mx257sx MACH_MX257SX MX257SX 2861
+goni MACH_GONI GONI 2862
+msm8x55_svlte_ffa MACH_MSM8X55_SVLTE_FFA MSM8X55_SVLTE_FFA 2863
+msm8x55_svlte_surf MACH_MSM8X55_SVLTE_SURF MSM8X55_SVLTE_SURF 2864
+quickstep MACH_QUICKSTEP QUICKSTEP 2865
+dmw96 MACH_DMW96 DMW96 2866
+hammerhead MACH_HAMMERHEAD HAMMERHEAD 2867
+trident MACH_TRIDENT TRIDENT 2868
+lightning MACH_LIGHTNING LIGHTNING 2869
+iconnect MACH_ICONNECT ICONNECT 2870
+autobot MACH_AUTOBOT AUTOBOT 2871
+coconut MACH_COCONUT COCONUT 2872
+durian MACH_DURIAN DURIAN 2873
+cayenne MACH_CAYENNE CAYENNE 2874
+fuji MACH_FUJI FUJI 2875
+synology_6282 MACH_SYNOLOGY_6282 SYNOLOGY_6282 2876
+em1sy MACH_EM1SY EM1SY 2877
+m502 MACH_M502 M502 2878
+matrix518 MACH_MATRIX518 MATRIX518 2879
+tiny_gurnard MACH_TINY_GURNARD TINY_GURNARD 2880
+spear1310 MACH_SPEAR1310 SPEAR1310 2881
+bv07 MACH_BV07 BV07 2882
+mxt_td61 MACH_MXT_TD61 MXT_TD61 2883
+openrd_ultimate MACH_OPENRD_ULTIMATE OPENRD_ULTIMATE 2884
+devixp MACH_DEVIXP DEVIXP 2885
+miccpt MACH_MICCPT MICCPT 2886
+mic256 MACH_MIC256 MIC256 2887
+as1167 MACH_AS1167 AS1167 2888
+omap3_ibiza MACH_OMAP3_IBIZA OMAP3_IBIZA 2889
+u5500 MACH_U5500 U5500 2890
+davinci_picto MACH_DAVINCI_PICTO DAVINCI_PICTO 2891
+mecha MACH_MECHA MECHA 2892
+bubba3 MACH_BUBBA3 BUBBA3 2893
+pupitre MACH_PUPITRE PUPITRE 2894
+tegra_vogue MACH_TEGRA_VOGUE TEGRA_VOGUE 2896
+tegra_e1165 MACH_TEGRA_E1165 TEGRA_E1165 2897
+simplenet MACH_SIMPLENET SIMPLENET 2898
+ec4350tbm MACH_EC4350TBM EC4350TBM 2899
+pec_tc MACH_PEC_TC PEC_TC 2900
+pec_hc2 MACH_PEC_HC2 PEC_HC2 2901
+esl_mobilis_a MACH_ESL_MOBILIS_A ESL_MOBILIS_A 2902
+esl_mobilis_b MACH_ESL_MOBILIS_B ESL_MOBILIS_B 2903
+esl_wave_a MACH_ESL_WAVE_A ESL_WAVE_A 2904
+esl_wave_b MACH_ESL_WAVE_B ESL_WAVE_B 2905
+unisense_mmm MACH_UNISENSE_MMM UNISENSE_MMM 2906
+blueshark MACH_BLUESHARK BLUESHARK 2907
+e10 MACH_E10 E10 2908
+app3k_robin MACH_APP3K_ROBIN APP3K_ROBIN 2909
+pov15hd MACH_POV15HD POV15HD 2910
+stella MACH_STELLA STELLA 2911
+linkstation_lschl MACH_LINKSTATION_LSCHL LINKSTATION_LSCHL 2913
+netwalker MACH_NETWALKER NETWALKER 2914
+acsx106 MACH_ACSX106 ACSX106 2915
+atlas5_c1 MACH_ATLAS5_C1 ATLAS5_C1 2916
+nsb3ast MACH_NSB3AST NSB3AST 2917
+gnet_slc MACH_GNET_SLC GNET_SLC 2918
+af4000 MACH_AF4000 AF4000 2919
+ark9431 MACH_ARK9431 ARK9431 2920
+fs_s5pc100 MACH_FS_S5PC100 FS_S5PC100 2921
+omap3505nova8 MACH_OMAP3505NOVA8 OMAP3505NOVA8 2922
+omap3621_edp1 MACH_OMAP3621_EDP1 OMAP3621_EDP1 2923
+oratisaes MACH_ORATISAES ORATISAES 2924
+smdkv310 MACH_SMDKV310 SMDKV310 2925
+siemens_l0 MACH_SIEMENS_L0 SIEMENS_L0 2926
+ventana MACH_VENTANA VENTANA 2927
+wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928
+ec4350sdb MACH_EC4350SDB EC4350SDB 2929
+mimas MACH_MIMAS MIMAS 2930
+titan MACH_TITAN TITAN 2931
+craneboard MACH_CRANEBOARD CRANEBOARD 2932
+es2440 MACH_ES2440 ES2440 2933
+najay_a9263 MACH_NAJAY_A9263 NAJAY_A9263 2934
+htctornado MACH_HTCTORNADO HTCTORNADO 2935
+dimm_mx257 MACH_DIMM_MX257 DIMM_MX257 2936
+jigen301 MACH_JIGEN JIGEN 2937
+smdk6450 MACH_SMDK6450 SMDK6450 2938
+meno_qng MACH_MENO_QNG MENO_QNG 2939
+ns2416 MACH_NS2416 NS2416 2940
+rpc353 MACH_RPC353 RPC353 2941
+tq6410 MACH_TQ6410 TQ6410 2942
+sky6410 MACH_SKY6410 SKY6410 2943
+dynasty MACH_DYNASTY DYNASTY 2944
+vivo MACH_VIVO VIVO 2945
+bury_bl7582 MACH_BURY_BL7582 BURY_BL7582 2946
+bury_bps5270 MACH_BURY_BPS5270 BURY_BPS5270 2947
+basi MACH_BASI BASI 2948
+tn200 MACH_TN200 TN200 2949
+c2mmi MACH_C2MMI C2MMI 2950
+meson_6236m MACH_MESON_6236M MESON_6236M 2951
+meson_8626m MACH_MESON_8626M MESON_8626M 2952
+tube MACH_TUBE TUBE 2953
+messina MACH_MESSINA MESSINA 2954
+mx50_arm2 MACH_MX50_ARM2 MX50_ARM2 2955
+cetus9263 MACH_CETUS9263 CETUS9263 2956
+brownstone MACH_BROWNSTONE BROWNSTONE 2957
+vmx25 MACH_VMX25 VMX25 2958
+vmx51 MACH_VMX51 VMX51 2959
+abacus MACH_ABACUS ABACUS 2960
+cm4745 MACH_CM4745 CM4745 2961
+oratislink MACH_ORATISLINK ORATISLINK 2962
+davinci_dm365_dvr MACH_DAVINCI_DM365_DVR DAVINCI_DM365_DVR 2963
+netviz MACH_NETVIZ NETVIZ 2964
+flexibity MACH_FLEXIBITY FLEXIBITY 2965
+wlan_computer MACH_WLAN_COMPUTER WLAN_COMPUTER 2966
+lpc24xx MACH_LPC24XX LPC24XX 2967
+spica MACH_SPICA SPICA 2968
+gpsdisplay MACH_GPSDISPLAY GPSDISPLAY 2969
+bipnet MACH_BIPNET BIPNET 2970
+overo_ctu_inertial MACH_OVERO_CTU_INERTIAL OVERO_CTU_INERTIAL 2971
+davinci_dm355_mmm MACH_DAVINCI_DM355_MMM DAVINCI_DM355_MMM 2972
+pc9260_v2 MACH_PC9260_V2 PC9260_V2 2973
+ptx7545 MACH_PTX7545 PTX7545 2974
+tm_efdc MACH_TM_EFDC TM_EFDC 2975
+omap3_waldo1 MACH_OMAP3_WALDO1 OMAP3_WALDO1 2977
+flyer MACH_FLYER FLYER 2978
+tornado3240 MACH_TORNADO3240 TORNADO3240 2979
+soli_01 MACH_SOLI_01 SOLI_01 2980
+omapl138_europalc MACH_OMAPL138_EUROPALC OMAPL138_EUROPALC 2981
+helios_v1 MACH_HELIOS_V1 HELIOS_V1 2982
+netspace_lite_v2 MACH_NETSPACE_LITE_V2 NETSPACE_LITE_V2 2983
+ssc MACH_SSC SSC 2984
+premierwave_en MACH_PREMIERWAVE_EN PREMIERWAVE_EN 2985
+wasabi MACH_WASABI WASABI 2986
+mx50_rdp MACH_MX50_RDP MX50_RDP 2988
+universal_c210 MACH_UNIVERSAL_C210 UNIVERSAL_C210 2989
+real6410 MACH_REAL6410 REAL6410 2990
+spx_sakura MACH_SPX_SAKURA SPX_SAKURA 2991
+ij3k_2440 MACH_IJ3K_2440 IJ3K_2440 2992
+omap3_bc10 MACH_OMAP3_BC10 OMAP3_BC10 2993
+thebe MACH_THEBE THEBE 2994
+rv082 MACH_RV082 RV082 2995
+armlguest MACH_ARMLGUEST ARMLGUEST 2996
+tjinc1000 MACH_TJINC1000 TJINC1000 2997
+dockstar MACH_DOCKSTAR DOCKSTAR 2998
+ax8008 MACH_AX8008 AX8008 2999
+gnet_sgce MACH_GNET_SGCE GNET_SGCE 3000
+pxwnas_500_1000 MACH_PXWNAS_500_1000 PXWNAS_500_1000 3001
+ea20 MACH_EA20 EA20 3002
+awm2 MACH_AWM2 AWM2 3003
+ti8148evm MACH_TI8148EVM TI8148EVM 3004
+seaboard MACH_SEABOARD SEABOARD 3005
+linkstation_chlv2 MACH_LINKSTATION_CHLV2 LINKSTATION_CHLV2 3006
+tera_pro2_rack MACH_TERA_PRO2_RACK TERA_PRO2_RACK 3007
+rubys MACH_RUBYS RUBYS 3008
+aquarius MACH_AQUARIUS AQUARIUS 3009
+mx53_ard MACH_MX53_ARD MX53_ARD 3010
+mx53_smd MACH_MX53_SMD MX53_SMD 3011
+lswxl MACH_LSWXL LSWXL 3012
+dove_avng_v3 MACH_DOVE_AVNG_V3 DOVE_AVNG_V3 3013
+sdi_ess_9263 MACH_SDI_ESS_9263 SDI_ESS_9263 3014
+jocpu550 MACH_JOCPU550 JOCPU550 3015
+msm8x60_rumi3 MACH_MSM8X60_RUMI3 MSM8X60_RUMI3 3016
+msm8x60_ffa MACH_MSM8X60_FFA MSM8X60_FFA 3017
+yanomami MACH_YANOMAMI YANOMAMI 3018
+gta04 MACH_GTA04 GTA04 3019
+cm_a510 MACH_CM_A510 CM_A510 3020
+omap3_rfs200 MACH_OMAP3_RFS200 OMAP3_RFS200 3021
+kx33xx MACH_KX33XX KX33XX 3022
+ptx7510 MACH_PTX7510 PTX7510 3023
+top9000 MACH_TOP9000 TOP9000 3024
+teenote MACH_TEENOTE TEENOTE 3025
+ts3 MACH_TS3 TS3 3026
+a0 MACH_A0 A0 3027
+fsm9xxx_surf MACH_FSM9XXX_SURF FSM9XXX_SURF 3028
+fsm9xxx_ffa MACH_FSM9XXX_FFA FSM9XXX_FFA 3029
+frrhwcdma60w MACH_FRRHWCDMA60W FRRHWCDMA60W 3030
+remus MACH_REMUS REMUS 3031
+at91cap7xdk MACH_AT91CAP7XDK AT91CAP7XDK 3032
+at91cap7stk MACH_AT91CAP7STK AT91CAP7STK 3033
+kt_sbc_sam9_1 MACH_KT_SBC_SAM9_1 KT_SBC_SAM9_1 3034
+armada_xp_db MACH_ARMADA_XP_DB ARMADA_XP_DB 3036
+spdm MACH_SPDM SPDM 3037
+gtib MACH_GTIB GTIB 3038
+dgm3240 MACH_DGM3240 DGM3240 3039
+htcmega MACH_HTCMEGA HTCMEGA 3041
+tricorder MACH_TRICORDER TRICORDER 3042
+tx28 MACH_TX28 TX28 3043
+bstbrd MACH_BSTBRD BSTBRD 3044
+pwb3090 MACH_PWB3090 PWB3090 3045
+idea6410 MACH_IDEA6410 IDEA6410 3046
+qbc9263 MACH_QBC9263 QBC9263 3047
+borabora MACH_BORABORA BORABORA 3048
+valdez MACH_VALDEZ VALDEZ 3049
+ls9g20 MACH_LS9G20 LS9G20 3050
+mios_v1 MACH_MIOS_V1 MIOS_V1 3051
+s5pc110_crespo MACH_S5PC110_CRESPO S5PC110_CRESPO 3052
+controltek9g20 MACH_CONTROLTEK9G20 CONTROLTEK9G20 3053
+tin307 MACH_TIN307 TIN307 3054
+tin510 MACH_TIN510 TIN510 3055
+ep3505 MACH_EP3517 EP3517 3056
+bluecheese MACH_BLUECHEESE BLUECHEESE 3057
+tem3x30 MACH_TEM3X30 TEM3X30 3058
+harvest_desoto MACH_HARVEST_DESOTO HARVEST_DESOTO 3059
+msm8x60_qrdc MACH_MSM8X60_QRDC MSM8X60_QRDC 3060
+spear900 MACH_SPEAR900 SPEAR900 3061
+pcontrol_g20 MACH_PCONTROL_G20 PCONTROL_G20 3062
+rdstor MACH_RDSTOR RDSTOR 3063
+usdloader MACH_USDLOADER USDLOADER 3064
+tsoploader MACH_TSOPLOADER TSOPLOADER 3065
+kronos MACH_KRONOS KRONOS 3066
+ffcore MACH_FFCORE FFCORE 3067
+mone MACH_MONE MONE 3068
+unit2s MACH_UNIT2S UNIT2S 3069
+acer_a5 MACH_ACER_A5 ACER_A5 3070
+etherpro_isp MACH_ETHERPRO_ISP ETHERPRO_ISP 3071
+stretchs7000 MACH_STRETCHS7000 STRETCHS7000 3072
+p87_smartsim MACH_P87_SMARTSIM P87_SMARTSIM 3073
+tulip MACH_TULIP TULIP 3074
+sunflower MACH_SUNFLOWER SUNFLOWER 3075
+rib MACH_RIB RIB 3076
+clod MACH_CLOD CLOD 3077
+rump MACH_RUMP RUMP 3078
+tenderloin MACH_TENDERLOIN TENDERLOIN 3079
+shortloin MACH_SHORTLOIN SHORTLOIN 3080
+antares MACH_ANTARES ANTARES 3082
+wb40n MACH_WB40N WB40N 3083
+herring MACH_HERRING HERRING 3084
+naxy400 MACH_NAXY400 NAXY400 3085
+naxy1200 MACH_NAXY1200 NAXY1200 3086
+vpr200 MACH_VPR200 VPR200 3087
+bug20 MACH_BUG20 BUG20 3088
+goflexnet MACH_GOFLEXNET GOFLEXNET 3089
+torbreck MACH_TORBRECK TORBRECK 3090
+saarb_mg1 MACH_SAARB_MG1 SAARB_MG1 3091
+callisto MACH_CALLISTO CALLISTO 3092
+multhsu MACH_MULTHSU MULTHSU 3093
+saluda MACH_SALUDA SALUDA 3094
+pemp_omap3_apollo MACH_PEMP_OMAP3_APOLLO PEMP_OMAP3_APOLLO 3095
+vc0718 MACH_VC0718 VC0718 3096
+mvblx MACH_MVBLX MVBLX 3097
+inhand_apeiron MACH_INHAND_APEIRON INHAND_APEIRON 3098
+inhand_fury MACH_INHAND_FURY INHAND_FURY 3099
+inhand_siren MACH_INHAND_SIREN INHAND_SIREN 3100
+hdnvp MACH_HDNVP HDNVP 3101
+softwinner MACH_SOFTWINNER SOFTWINNER 3102
+prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103
+nas6210 MACH_NAS6210 NAS6210 3104
+unisdev MACH_UNISDEV UNISDEV 3105
+sbca11 MACH_SBCA11 SBCA11 3106
+saga MACH_SAGA SAGA 3107
+ns_k330 MACH_NS_K330 NS_K330 3108
+tanna MACH_TANNA TANNA 3109
+imate8502 MACH_IMATE8502 IMATE8502 3110
+aspen MACH_ASPEN ASPEN 3111
+daintree_cwac MACH_DAINTREE_CWAC DAINTREE_CWAC 3112
+zmx25 MACH_ZMX25 ZMX25 3113
+maple1 MACH_MAPLE1 MAPLE1 3114
+qsd8x72_surf MACH_QSD8X72_SURF QSD8X72_SURF 3115
+qsd8x72_ffa MACH_QSD8X72_FFA QSD8X72_FFA 3116
+abilene MACH_ABILENE ABILENE 3117
+eigen_ttr MACH_EIGEN_TTR EIGEN_TTR 3118
+iomega_ix2_200 MACH_IOMEGA_IX2_200 IOMEGA_IX2_200 3119
+coretec_vcx7400 MACH_CORETEC_VCX7400 CORETEC_VCX7400 3120
+santiago MACH_SANTIAGO SANTIAGO 3121
+mx257sol MACH_MX257SOL MX257SOL 3122
+strasbourg MACH_STRASBOURG STRASBOURG 3123
+msm8x60_fluid MACH_MSM8X60_FLUID MSM8X60_FLUID 3124
+smartqv5 MACH_SMARTQV5 SMARTQV5 3125
+smartqv3 MACH_SMARTQV3 SMARTQV3 3126
+smartqv7 MACH_SMARTQV7 SMARTQV7 3127
+paz00 MACH_PAZ00 PAZ00 3128
+acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129
+fwbd_0404 MACH_FWBD_0404 FWBD_0404 3131
+hdgu MACH_HDGU HDGU 3132
+pyramid MACH_PYRAMID PYRAMID 3133
+epiphan MACH_EPIPHAN EPIPHAN 3134
+omap_bender MACH_OMAP_BENDER OMAP_BENDER 3135
+gurnard MACH_GURNARD GURNARD 3136
+gtl_it5100 MACH_GTL_IT5100 GTL_IT5100 3137
+bcm2708 MACH_BCM2708 BCM2708 3138
+mx51_ggc MACH_MX51_GGC MX51_GGC 3139
+sharespace MACH_SHARESPACE SHARESPACE 3140
+haba_knx_explorer MACH_HABA_KNX_EXPLORER HABA_KNX_EXPLORER 3141
+simtec_kirkmod MACH_SIMTEC_KIRKMOD SIMTEC_KIRKMOD 3142
+crux MACH_CRUX CRUX 3143
+mx51_bravo MACH_MX51_BRAVO MX51_BRAVO 3144
+charon MACH_CHARON CHARON 3145
+picocom3 MACH_PICOCOM3 PICOCOM3 3146
+picocom4 MACH_PICOCOM4 PICOCOM4 3147
+serrano MACH_SERRANO SERRANO 3148
+doubleshot MACH_DOUBLESHOT DOUBLESHOT 3149
+evsy MACH_EVSY EVSY 3150
+huashan MACH_HUASHAN HUASHAN 3151
+lausanne MACH_LAUSANNE LAUSANNE 3152
+emerald MACH_EMERALD EMERALD 3153
+tqma35 MACH_TQMA35 TQMA35 3154
+marvel MACH_MARVEL MARVEL 3155
+manuae MACH_MANUAE MANUAE 3156
+chacha MACH_CHACHA CHACHA 3157
+lemon MACH_LEMON LEMON 3158
+csc MACH_CSC CSC 3159
+gira_knxip_router MACH_GIRA_KNXIP_ROUTER GIRA_KNXIP_ROUTER 3160
+t20 MACH_T20 T20 3161
+hdmini MACH_HDMINI HDMINI 3162
+sciphone_g2 MACH_SCIPHONE_G2 SCIPHONE_G2 3163
+express MACH_EXPRESS EXPRESS 3164
+express_kt MACH_EXPRESS_KT EXPRESS_KT 3165
+maximasp MACH_MAXIMASP MAXIMASP 3166
+nitrogen_imx51 MACH_NITROGEN_IMX51 NITROGEN_IMX51 3167
+nitrogen_imx53 MACH_NITROGEN_IMX53 NITROGEN_IMX53 3168
+sunfire MACH_SUNFIRE SUNFIRE 3169
+arowana MACH_AROWANA AROWANA 3170
+tegra_daytona MACH_TEGRA_DAYTONA TEGRA_DAYTONA 3171
+tegra_swordfish MACH_TEGRA_SWORDFISH TEGRA_SWORDFISH 3172
+edison MACH_EDISON EDISON 3173
+svp8500v1 MACH_SVP8500V1 SVP8500V1 3174
+svp8500v2 MACH_SVP8500V2 SVP8500V2 3175
+svp5500 MACH_SVP5500 SVP5500 3176
+b5500 MACH_B5500 B5500 3177
+s5500 MACH_S5500 S5500 3178
+icon MACH_ICON ICON 3179
+elephant MACH_ELEPHANT ELEPHANT 3180
+shooter MACH_SHOOTER SHOOTER 3182
+spade_lte MACH_SPADE_LTE SPADE_LTE 3183
+philhwani MACH_PHILHWANI PHILHWANI 3184
+gsncomm MACH_GSNCOMM GSNCOMM 3185
+strasbourg_a2 MACH_STRASBOURG_A2 STRASBOURG_A2 3186
+mmm MACH_MMM MMM 3187
+davinci_dm365_bv MACH_DAVINCI_DM365_BV DAVINCI_DM365_BV 3188
+ag5evm MACH_AG5EVM AG5EVM 3189
+sc575plc MACH_SC575PLC SC575PLC 3190
+sc575hmi MACH_SC575IPC SC575IPC 3191
+omap3_tdm3730 MACH_OMAP3_TDM3730 OMAP3_TDM3730 3192
+top9000_eval MACH_TOP9000_EVAL TOP9000_EVAL 3194
+top9000_su MACH_TOP9000_SU TOP9000_SU 3195
+utm300 MACH_UTM300 UTM300 3196
+tsunagi MACH_TSUNAGI TSUNAGI 3197
+ts75xx MACH_TS75XX TS75XX 3198
+ts47xx MACH_TS47XX TS47XX 3200
+da850_k5 MACH_DA850_K5 DA850_K5 3201
+ax502 MACH_AX502 AX502 3202
+igep0032 MACH_IGEP0032 IGEP0032 3203
+antero MACH_ANTERO ANTERO 3204
+synergy MACH_SYNERGY SYNERGY 3205
+ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206
+wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207
+punica MACH_PUNICA PUNICA 3208
+trimslice MACH_TRIMSLICE TRIMSLICE 3209
+mx27_wmultra MACH_MX27_WMULTRA MX27_WMULTRA 3210
+mackerel MACH_MACKEREL MACKEREL 3211
+fa9x27 MACH_FA9X27 FA9X27 3213
+ns2816tb MACH_NS2816TB NS2816TB 3214
+ns2816_ntpad MACH_NS2816_NTPAD NS2816_NTPAD 3215
+ns2816_ntnb MACH_NS2816_NTNB NS2816_NTNB 3216
+kaen MACH_KAEN KAEN 3217
+nv1000 MACH_NV1000 NV1000 3218
+nuc950ts MACH_NUC950TS NUC950TS 3219
+nokia_rm680 MACH_NOKIA_RM680 NOKIA_RM680 3220
+ast2200 MACH_AST2200 AST2200 3221
+lead MACH_LEAD LEAD 3222
+unino1 MACH_UNINO1 UNINO1 3223
+greeco MACH_GREECO GREECO 3224
+verdi MACH_VERDI VERDI 3225
+dm6446_adbox MACH_DM6446_ADBOX DM6446_ADBOX 3226
+quad_salsa MACH_QUAD_SALSA QUAD_SALSA 3227
+abb_gma_1_1 MACH_ABB_GMA_1_1 ABB_GMA_1_1 3228
+svcid MACH_SVCID SVCID 3229
+msm8960_sim MACH_MSM8960_SIM MSM8960_SIM 3230
+msm8960_rumi3 MACH_MSM8960_RUMI3 MSM8960_RUMI3 3231
+icon_g MACH_ICON_G ICON_G 3232
+mb3 MACH_MB3 MB3 3233
+gsia18s MACH_GSIA18S GSIA18S 3234
+pivicc MACH_PIVICC PIVICC 3235
+pcm048 MACH_PCM048 PCM048 3236
+dds MACH_DDS DDS 3237
+chalten_xa1 MACH_CHALTEN_XA1 CHALTEN_XA1 3238
+ts48xx MACH_TS48XX TS48XX 3239
+tonga2_tfttimer MACH_TONGA2_TFTTIMER TONGA2_TFTTIMER 3240
+whistler MACH_WHISTLER WHISTLER 3241
+asl_phoenix MACH_ASL_PHOENIX ASL_PHOENIX 3242
+at91sam9263otlite MACH_AT91SAM9263OTLITE AT91SAM9263OTLITE 3243
+ddplug MACH_DDPLUG DDPLUG 3244
+d2plug MACH_D2PLUG D2PLUG 3245
+kzm9d MACH_KZM9D KZM9D 3246
+verdi_lte MACH_VERDI_LTE VERDI_LTE 3247
+nanozoom MACH_NANOZOOM NANOZOOM 3248
+dm3730_som_lv MACH_DM3730_SOM_LV DM3730_SOM_LV 3249
+dm3730_torpedo MACH_DM3730_TORPEDO DM3730_TORPEDO 3250
+anchovy MACH_ANCHOVY ANCHOVY 3251
+re2rev20 MACH_RE2REV20 RE2REV20 3253
+re2rev21 MACH_RE2REV21 RE2REV21 3254
+cns21xx MACH_CNS21XX CNS21XX 3255
+rider MACH_RIDER RIDER 3257
+nsk330 MACH_NSK330 NSK330 3258
+cns2133evb MACH_CNS2133EVB CNS2133EVB 3259
+z3_816x_mod MACH_Z3_816X_MOD Z3_816X_MOD 3260
+z3_814x_mod MACH_Z3_814X_MOD Z3_814X_MOD 3261
+beect MACH_BEECT BEECT 3262
+dma_thunderbug MACH_DMA_THUNDERBUG DMA_THUNDERBUG 3263
+omn_at91sam9g20 MACH_OMN_AT91SAM9G20 OMN_AT91SAM9G20 3264
+mx25_e2s_uc MACH_MX25_E2S_UC MX25_E2S_UC 3265
+mione MACH_MIONE MIONE 3266
+top9000_tcu MACH_TOP9000_TCU TOP9000_TCU 3267
+top9000_bsl MACH_TOP9000_BSL TOP9000_BSL 3268
+kingdom MACH_KINGDOM KINGDOM 3269
+armadillo460 MACH_ARMADILLO460 ARMADILLO460 3270
+lq2 MACH_LQ2 LQ2 3271
+sweda_tms2 MACH_SWEDA_TMS2 SWEDA_TMS2 3272
+mx53_loco MACH_MX53_LOCO MX53_LOCO 3273
+acer_a8 MACH_ACER_A8 ACER_A8 3275
+acer_gauguin MACH_ACER_GAUGUIN ACER_GAUGUIN 3276
+guppy MACH_GUPPY GUPPY 3277
+mx61_ard MACH_MX61_ARD MX61_ARD 3278
+tx53 MACH_TX53 TX53 3279
+omapl138_case_a3 MACH_OMAPL138_CASE_A3 OMAPL138_CASE_A3 3280
+uemd MACH_UEMD UEMD 3281
+ccwmx51mut MACH_CCWMX51MUT CCWMX51MUT 3282
+rockhopper MACH_ROCKHOPPER ROCKHOPPER 3283
+encore MACH_ENCORE ENCORE 3284
+hkdkc100 MACH_HKDKC100 HKDKC100 3285
+ts42xx MACH_TS42XX TS42XX 3286
+aebl MACH_AEBL AEBL 3287
+wario MACH_WARIO WARIO 3288
+gfs_spm MACH_GFS_SPM GFS_SPM 3289
+cm_t3730 MACH_CM_T3730 CM_T3730 3290
+isc3 MACH_ISC3 ISC3 3291
+rascal MACH_RASCAL RASCAL 3292
+hrefv60 MACH_HREFV60 HREFV60 3293
+tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294
+pydtd MACH_PYRAMID_TD PYRAMID_TD 3295
+splendor MACH_SPLENDOR SPLENDOR 3296
+guf_vincell MACH_GUF_PLANET GUF_PLANET 3297
+msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298
+htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299
+athene MACH_ATHENE ATHENE 3300
+deep_r_ek_1 MACH_DEEP_R_EK_1 DEEP_R_EK_1 3301
+vivow_ct MACH_VIVOW_CT VIVOW_CT 3302
+nery_1000 MACH_NERY_1000 NERY_1000 3303
+rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304
+nmh MACH_NMH NMH 3305
+wn802t MACH_WN802T WN802T 3306
+dragonet MACH_DRAGONET DRAGONET 3307
+geneva_b4 MACH_GENEVA_B GENEVA_B 3308
+at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309
+bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310
+bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311
+koi MACH_KOI KOI 3312
+ts4800 MACH_TS4800 TS4800 3313
+tqma9263 MACH_TQMA9263 TQMA9263 3314
+holiday MACH_HOLIDAY HOLIDAY 3315
+dma_6410 MACH_DMA6410 DMA6410 3316
+pcats_overlay MACH_PCATS_OVERLAY PCATS_OVERLAY 3317
+hwgw6410 MACH_HWGW6410 HWGW6410 3318
+shenzhou MACH_SHENZHOU SHENZHOU 3319
+cwme9210 MACH_CWME9210 CWME9210 3320
+cwme9210js MACH_CWME9210JS CWME9210JS 3321
+pgs_v1 MACH_PGS_SITARA PGS_SITARA 3322
+colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323
+w21 MACH_W21 W21 3324
+polysat1 MACH_POLYSAT1 POLYSAT1 3325
+dataway MACH_DATAWAY DATAWAY 3326
+cobral138 MACH_COBRAL138 COBRAL138 3327
+roverpcs8 MACH_ROVERPCS8 ROVERPCS8 3328
+marvelc MACH_MARVELC MARVELC 3329
+navefihid MACH_NAVEFIHID NAVEFIHID 3330
+dm365_cv100 MACH_DM365_CV100 DM365_CV100 3331
+able MACH_ABLE ABLE 3332
+legacy MACH_LEGACY LEGACY 3333
+icong MACH_ICONG ICONG 3334
+rover_g8 MACH_ROVER_G8 ROVER_G8 3335
+t5388p MACH_T5388P T5388P 3336
+dingo MACH_DINGO DINGO 3337
+goflexhome MACH_GOFLEXHOME GOFLEXHOME 3338
+lanreadyfn511 MACH_LANREADYFN511 LANREADYFN511 3340
+omap3_baia MACH_OMAP3_BAIA OMAP3_BAIA 3341
+omap3smartdisplay MACH_OMAP3SMARTDISPLAY OMAP3SMARTDISPLAY 3342
+xilinx MACH_XILINX XILINX 3343
+a2f MACH_A2F A2F 3344
+sky25 MACH_SKY25 SKY25 3345
+ccmx53 MACH_CCMX53 CCMX53 3346
+ccmx53js MACH_CCMX53JS CCMX53JS 3347
+ccwmx53 MACH_CCWMX53 CCWMX53 3348
+ccwmx53js MACH_CCWMX53JS CCWMX53JS 3349
+frisms MACH_FRISMS FRISMS 3350
+msm7x27a_ffa MACH_MSM7X27A_FFA MSM7X27A_FFA 3351
+msm7x27a_surf MACH_MSM7X27A_SURF MSM7X27A_SURF 3352
+msm7x27a_rumi3 MACH_MSM7X27A_RUMI3 MSM7X27A_RUMI3 3353
+dimmsam9g20 MACH_DIMMSAM9G20 DIMMSAM9G20 3354
+dimm_imx28 MACH_DIMM_IMX28 DIMM_IMX28 3355
+amk_a4 MACH_AMK_A4 AMK_A4 3356
+gnet_sgme MACH_GNET_SGME GNET_SGME 3357
+shooter_u MACH_SHOOTER_U SHOOTER_U 3358
+vmx53 MACH_VMX53 VMX53 3359
+rhino MACH_RHINO RHINO 3360
+armlex4210 MACH_ARMLEX4210 ARMLEX4210 3361
+swarcoextmodem MACH_SWARCOEXTMODEM SWARCOEXTMODEM 3362
+snowball MACH_SNOWBALL SNOWBALL 3363
+pcm049 MACH_PCM049 PCM049 3364
+vigor MACH_VIGOR VIGOR 3365
+oslo_amundsen MACH_OSLO_AMUNDSEN OSLO_AMUNDSEN 3366
+gsl_diamond MACH_GSL_DIAMOND GSL_DIAMOND 3367
+cv2201 MACH_CV2201 CV2201 3368
+cv2202 MACH_CV2202 CV2202 3369
+cv2203 MACH_CV2203 CV2203 3370
+vit_ibox MACH_VIT_IBOX VIT_IBOX 3371
+dm6441_esp MACH_DM6441_ESP DM6441_ESP 3372
+at91sam9x5ek MACH_AT91SAM9X5EK AT91SAM9X5EK 3373
+libra MACH_LIBRA LIBRA 3374
+easycrrh MACH_EASYCRRH EASYCRRH 3375
+tripel MACH_TRIPEL TRIPEL 3376
+endian_mini MACH_ENDIAN_MINI ENDIAN_MINI 3377
+xilinx_ep107 MACH_XILINX_EP107 XILINX_EP107 3378
+nuri MACH_NURI NURI 3379
+janus MACH_JANUS JANUS 3380
+ddnas MACH_DDNAS DDNAS 3381
+tag MACH_TAG TAG 3382
+tagw MACH_TAGW TAGW 3383
+nitrogen_vm_imx51 MACH_NITROGEN_VM_IMX51 NITROGEN_VM_IMX51 3384
+viprinet MACH_VIPRINET VIPRINET 3385
+bockw MACH_BOCKW BOCKW 3386
+eva2000 MACH_EVA2000 EVA2000 3387
+steelyard MACH_STEELYARD STEELYARD 3388
+ea2468devkit MACH_LPC2468OEM LPC2468OEM 3389
+sdh001 MACH_MACH_SDH001 MACH_SDH001 3390
+fe2478mblox MACH_LPC2478MICROBLOX LPC2478MICROBLOX 3391
+nsslsboard MACH_NSSLSBOARD NSSLSBOARD 3392
+geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393
+spear1340 MACH_SPEAR1340 SPEAR1340 3394
+rexmas MACH_REXMAS REXMAS 3395
+msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396
+msm8960_mtp MACH_MSM8960_MDP MSM8960_MDP 3397
+msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398
+msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399
+helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400
+mif10p MACH_MIF10P MIF10P 3401
+iam28 MACH_IAM28 IAM28 3402
+picasso MACH_PICASSO PICASSO 3403
+mr301a MACH_MR301A MR301A 3404
+notle MACH_NOTLE NOTLE 3405
+eelx2 MACH_EELX2 EELX2 3406
+moon MACH_MOON MOON 3407
+ruby MACH_RUBY RUBY 3408
+goldengate MACH_GOLDENGATE GOLDENGATE 3409
+ctbu_gen2 MACH_CTBU_GEN2 CTBU_GEN2 3410
+kmp_am17_01 MACH_KMP_AM17_01 KMP_AM17_01 3411
+wtplug MACH_WTPLUG WTPLUG 3412
+mx27su2 MACH_MX27SU2 MX27SU2 3413
+nb31 MACH_NB31 NB31 3414
+hjsdu MACH_HJSDU HJSDU 3415
+td3_rev1 MACH_TD3_REV1 TD3_REV1 3416
+eag_ci4000 MACH_EAG_CI4000 EAG_CI4000 3417
+net5big_nand_v2 MACH_NET5BIG_NAND_V2 NET5BIG_NAND_V2 3418
+cpx2 MACH_CPX2 CPX2 3419
+net2big_nand_v2 MACH_NET2BIG_NAND_V2 NET2BIG_NAND_V2 3420
+ecuv5 MACH_ECUV5 ECUV5 3421
+hsgx6d MACH_HSGX6D HSGX6D 3422
+dawad7 MACH_DAWAD7 DAWAD7 3423
+sam9repeater MACH_SAM9REPEATER SAM9REPEATER 3424
+gt_i5700 MACH_GT_I5700 GT_I5700 3425
+ctera_plug_c2 MACH_CTERA_PLUG_C2 CTERA_PLUG_C2 3426
+marvelct MACH_MARVELCT MARVELCT 3427
+ag11005 MACH_AG11005 AG11005 3428
+omap_tabletblaze MACH_OMAP_BLAZE OMAP_BLAZE 3429
+vangogh MACH_VANGOGH VANGOGH 3430
+matrix505 MACH_MATRIX505 MATRIX505 3431
+oce_nigma MACH_OCE_NIGMA OCE_NIGMA 3432
+t55 MACH_T55 T55 3433
+bio3k MACH_BIO3K BIO3K 3434
+expressct MACH_EXPRESSCT EXPRESSCT 3435
+cardhu MACH_CARDHU CARDHU 3436
+aruba MACH_ARUBA ARUBA 3437
+bonaire MACH_BONAIRE BONAIRE 3438
+nuc700evb MACH_NUC700EVB NUC700EVB 3439
+nuc710evb MACH_NUC710EVB NUC710EVB 3440
+nuc740evb MACH_NUC740EVB NUC740EVB 3441
+nuc745evb MACH_NUC745EVB NUC745EVB 3442
+transcede MACH_TRANSCEDE TRANSCEDE 3443
+mora MACH_MORA MORA 3444
+nda_evm MACH_NDA_EVM NDA_EVM 3445
+timu MACH_TIMU TIMU 3446
+expressh MACH_EXPRESSH EXPRESSH 3447
+veridis_a300 MACH_VERIDIS_A300 VERIDIS_A300 3448
+dm368_leopard MACH_DM368_LEOPARD DM368_LEOPARD 3449
+omap_mcop MACH_OMAP_MCOP OMAP_MCOP 3450
+tritip MACH_TRITIP TRITIP 3451
+sm1k MACH_SM1K SM1K 3452
+monch MACH_MONCH MONCH 3453
+curacao MACH_CURACAO CURACAO 3454
+origen MACH_ORIGEN ORIGEN 3455
+epc10 MACH_EPC10 EPC10 3456
+sgh_i740 MACH_SGH_I740 SGH_I740 3457
+tuna MACH_TUNA TUNA 3458
+mx51_tulip MACH_MX51_TULIP MX51_TULIP 3459
+mx51_aster7 MACH_MX51_ASTER7 MX51_ASTER7 3460
+acro37xbrd MACH_ACRO37XBRD ACRO37XBRD 3461
+elke MACH_ELKE ELKE 3462
+sbc6000x MACH_SBC6000X SBC6000X 3463
+r1801e MACH_R1801E R1801E 3464
+h1600 MACH_H1600 H1600 3465
+mini210 MACH_MINI210 MINI210 3466
+mini8168 MACH_MINI8168 MINI8168 3467
+pc7308 MACH_PC7308 PC7308 3468
+ge863_pro3_evk MACH_GE863 GE863 3469
+kmm2m01 MACH_KMM2M01 KMM2M01 3470
+mx51erebus MACH_MX51EREBUS MX51EREBUS 3471
+wm8650refboard MACH_WM8650REFBOARD WM8650REFBOARD 3472
+tuxrail MACH_TUXRAIL TUXRAIL 3473
+arthur MACH_ARTHUR ARTHUR 3474
+doorboy MACH_DOORBOY DOORBOY 3475
+xarina MACH_XARINA XARINA 3476
+roverx7 MACH_ROVERX7 ROVERX7 3477
+sdvr MACH_SDVR SDVR 3478
+acer_maya MACH_ACER_MAYA ACER_MAYA 3479
+pico MACH_PICO PICO 3480
+cwmx233 MACH_CWMX233 CWMX233 3481
+cwam1808 MACH_CWAM1808 CWAM1808 3482
+cwdm365 MACH_CWDM365 CWDM365 3483
+mx51_moray MACH_MX51_MORAY MX51_MORAY 3484
+thales_cbc MACH_THALES_CBC THALES_CBC 3485
+bluepoint MACH_BLUEPOINT BLUEPOINT 3486
+dir665 MACH_DIR665 DIR665 3487
+acmerover1 MACH_ACMEROVER1 ACMEROVER1 3488
+shooter_ct MACH_SHOOTER_CT SHOOTER_CT 3489
+bliss MACH_BLISS BLISS 3490
+blissc MACH_BLISSC BLISSC 3491
+thales_adc MACH_THALES_ADC THALES_ADC 3492
+ubisys_p9d_evp MACH_UBISYS_P9D_EVP UBISYS_P9D_EVP 3493
+atdgp318 MACH_ATDGP318 ATDGP318 3494
+dma210u MACH_DMA210U DMA210U 3495
+em_t3 MACH_EM_T3 EM_T3 3496
+htx3250 MACH_HTX3250 HTX3250 3497
+g50 MACH_G50 G50 3498
+eco5 MACH_ECO5 ECO5 3499
+wintergrasp MACH_WINTERGRASP WINTERGRASP 3500
+puro MACH_PURO PURO 3501
+shooter_k MACH_SHOOTER_K SHOOTER_K 3502
+nspire MACH_NSPIRE NSPIRE 3503
+mickxx MACH_MICKXX MICKXX 3504
+lxmb MACH_LXMB LXMB 3505
+tmdxscbp6618x MACH_TMDXSCBP6616X TMDXSCBP6616X 3506
+adam MACH_ADAM ADAM 3507
+b1004 MACH_B1004 B1004 3508
+oboea MACH_OBOEA OBOEA 3509
+a1015 MACH_A1015 A1015 3510
+robin_vbdt30 MACH_ROBIN_VBDT30 ROBIN_VBDT30 3511
+tegra_enterprise MACH_TEGRA_ENTERPRISE TEGRA_ENTERPRISE 3512
+rfl108200_mk10 MACH_RFL108200_MK10 RFL108200_MK10 3513
+rfl108300_mk16 MACH_RFL108300_MK16 RFL108300_MK16 3514
+rover_v7 MACH_ROVER_V7 ROVER_V7 3515
+miphone MACH_MIPHONE MIPHONE 3516
+femtobts MACH_FEMTOBTS FEMTOBTS 3517
+monopoli MACH_MONOPOLI MONOPOLI 3518
+boss MACH_BOSS BOSS 3519
+davinci_dm368_vtam MACH_DAVINCI_DM368_VTAM DAVINCI_DM368_VTAM 3520
+clcon MACH_CLCON CLCON 3521
+nokia_rm696 MACH_NOKIA_RM696 NOKIA_RM696 3522
+tahiti MACH_TAHITI TAHITI 3523
+fighter MACH_FIGHTER FIGHTER 3524
+sgh_i710 MACH_SGH_I710 SGH_I710 3525
+integreproscb MACH_INTEGREPROSCB INTEGREPROSCB 3526
+monza MACH_MONZA MONZA 3527
+calimain MACH_CALIMAIN CALIMAIN 3528
+mx6q_sabreauto MACH_MX6Q_SABREAUTO MX6Q_SABREAUTO 3529
+gma01x MACH_GMA01X GMA01X 3530
+sbc51 MACH_SBC51 SBC51 3531
+fit MACH_FIT FIT 3532
+steelhead MACH_STEELHEAD STEELHEAD 3533
+panther MACH_PANTHER PANTHER 3534
+msm8960_liquid MACH_MSM8960_LIQUID MSM8960_LIQUID 3535
+lexikonct MACH_LEXIKONCT LEXIKONCT 3536
+ns2816_stb MACH_NS2816_STB NS2816_STB 3537
+sei_mm2_lpc3250 MACH_SEI_MM2_LPC3250 SEI_MM2_LPC3250 3538
+cmimx53 MACH_CMIMX53 CMIMX53 3539
+sandwich MACH_SANDWICH SANDWICH 3540
+chief MACH_CHIEF CHIEF 3541
+pogo_e02 MACH_POGO_E02 POGO_E02 3542
+mikrap_x168 MACH_MIKRAP_X168 MIKRAP_X168 3543
+htcmozart MACH_HTCMOZART HTCMOZART 3544
+htcgold MACH_HTCGOLD HTCGOLD 3545
+mt72xx MACH_MT72XX MT72XX 3546
+mx51_ivy MACH_MX51_IVY MX51_IVY 3547
+mx51_lvd MACH_MX51_LVD MX51_LVD 3548
+omap3_wiser2 MACH_OMAP3_WISER2 OMAP3_WISER2 3549
+dreamplug MACH_DREAMPLUG DREAMPLUG 3550
+cobas_c_111 MACH_COBAS_C_111 COBAS_C_111 3551
+cobas_u_411 MACH_COBAS_U_411 COBAS_U_411 3552
+hssd MACH_HSSD HSSD 3553
+iom35x MACH_IOM35X IOM35X 3554
+psom_omap MACH_PSOM_OMAP PSOM_OMAP 3555
+iphone_2g MACH_IPHONE_2G IPHONE_2G 3556
+iphone_3g MACH_IPHONE_3G IPHONE_3G 3557
+ipod_touch_1g MACH_IPOD_TOUCH_1G IPOD_TOUCH_1G 3558
+pharos_tpc MACH_PHAROS_TPC PHAROS_TPC 3559
+mx53_hydra MACH_MX53_HYDRA MX53_HYDRA 3560
+ns2816_dev_board MACH_NS2816_DEV_BOARD NS2816_DEV_BOARD 3561
+iphone_3gs MACH_IPHONE_3GS IPHONE_3GS 3562
+iphone_4 MACH_IPHONE_4 IPHONE_4 3563
+ipod_touch_4g MACH_IPOD_TOUCH_4G IPOD_TOUCH_4G 3564
+dragon_e1100 MACH_DRAGON_E1100 DRAGON_E1100 3565
+topside MACH_TOPSIDE TOPSIDE 3566
+irisiii MACH_IRISIII IRISIII 3567
+deto_macarm9 MACH_DETO_MACARM9 DETO_MACARM9 3568
+eti_d1 MACH_ETI_D1 ETI_D1 3569
+som3530sdk MACH_SOM3530SDK SOM3530SDK 3570
+oc_engine MACH_OC_ENGINE OC_ENGINE 3571
+apq8064_sim MACH_APQ8064_SIM APQ8064_SIM 3572
+alps MACH_ALPS ALPS 3575
+tny_t3730 MACH_TNY_T3730 TNY_T3730 3576
+geryon_nfe MACH_GERYON_NFE GERYON_NFE 3577
+ns2816_ref_board MACH_NS2816_REF_BOARD NS2816_REF_BOARD 3578
+silverstone MACH_SILVERSTONE SILVERSTONE 3579
+mtt2440 MACH_MTT2440 MTT2440 3580
+ynicdb MACH_YNICDB YNICDB 3581
+bct MACH_BCT BCT 3582
+tuscan MACH_TUSCAN TUSCAN 3583
+xbt_sam9g45 MACH_XBT_SAM9G45 XBT_SAM9G45 3584
+enbw_cmc MACH_ENBW_CMC ENBW_CMC 3585
+msm8x60_dragon MACH_APQ8060_DRAGON APQ8060_DRAGON 3586
+ch104mx257 MACH_CH104MX257 CH104MX257 3587
+openpri MACH_OPENPRI OPENPRI 3588
+am335xevm MACH_AM335XEVM AM335XEVM 3589
+picodmb MACH_PICODMB PICODMB 3590
+waluigi MACH_WALUIGI WALUIGI 3591
+punicag7 MACH_PUNICAG7 PUNICAG7 3592
+ipad_1g MACH_IPAD_1G IPAD_1G 3593
+appletv_2g MACH_APPLETV_2G APPLETV_2G 3594
+mach_ecog45 MACH_MACH_ECOG45 MACH_ECOG45 3595
+ait_cam_enc_4xx MACH_AIT_CAM_ENC_4XX AIT_CAM_ENC_4XX 3596
+runnymede MACH_RUNNYMEDE RUNNYMEDE 3597
+play MACH_PLAY PLAY 3598
+hw90260 MACH_HW90260 HW90260 3599
+tagh MACH_TAGH TAGH 3600
+filbert MACH_FILBERT FILBERT 3601
+getinge_netcomv3 MACH_GETINGE_NETCOMV3 GETINGE_NETCOMV3 3602
+cw20 MACH_CW20 CW20 3603
+cinema MACH_CINEMA CINEMA 3604
+cinema_tea MACH_CINEMA_TEA CINEMA_TEA 3605
+cinema_coffee MACH_CINEMA_COFFEE CINEMA_COFFEE 3606
+cinema_juice MACH_CINEMA_JUICE CINEMA_JUICE 3607
+linux_pad MACH_THEPAD THEPAD 3608
+mx53_mirage2 MACH_MX53_MIRAGE2 MX53_MIRAGE2 3609
+mx53_efikasb MACH_MX53_EFIKASB MX53_EFIKASB 3610
+stm_b2000 MACH_STM_B2000 STM_B2000 3612
+m28evk MACH_M28EVK M28EVK 3613
+pda MACH_PDA PDA 3614
+meraki_mr58 MACH_MERAKI_MR58 MERAKI_MR58 3615
+kota2 MACH_KOTA2 KOTA2 3616
+letcool MACH_LETCOOL LETCOOL 3617
+mx27iat MACH_MX27IAT MX27IAT 3618
+apollo_td MACH_APOLLO_TD APOLLO_TD 3619
+arena MACH_ARENA ARENA 3620
+gsngateway MACH_GSNGATEWAY GSNGATEWAY 3621
+lf2000 MACH_LF2000 LF2000 3622
+bonito MACH_BONITO BONITO 3623
+asymptote MACH_ASYMPTOTE ASYMPTOTE 3624
+bst2brd MACH_BST2BRD BST2BRD 3625
+tx335s MACH_TX335S TX335S 3626
+pelco_tesla MACH_PELCO_TESLA PELCO_TESLA 3627
+rrhtestplat MACH_RRHTESTPLAT RRHTESTPLAT 3628
+vidtonic_pro MACH_VIDTONIC_PRO VIDTONIC_PRO 3629
+pl_apollo MACH_PL_APOLLO PL_APOLLO 3630
+pl_phoenix MACH_PL_PHOENIX PL_PHOENIX 3631
+m28cu3 MACH_M28CU3 M28CU3 3632
+vvbox_hd MACH_VVBOX_HD VVBOX_HD 3633
+coreware_sam9260_ MACH_COREWARE_SAM9260_ COREWARE_SAM9260_ 3634
+marmaduke MACH_MARMADUKE MARMADUKE 3635
+amg_xlcore_camera MACH_AMG_XLCORE_CAMERA AMG_XLCORE_CAMERA 3636
+omap3_egf MACH_OMAP3_EGF OMAP3_EGF 3637
+smdk4212 MACH_SMDK4212 SMDK4212 3638
+dnp9200 MACH_DNP9200 DNP9200 3639
+tf101 MACH_TF101 TF101 3640
+omap3silvio MACH_OMAP3SILVIO OMAP3SILVIO 3641
+picasso2 MACH_PICASSO2 PICASSO2 3642
+vangogh2 MACH_VANGOGH2 VANGOGH2 3643
+olpc_xo_1_75 MACH_OLPC_XO_1_75 OLPC_XO_1_75 3644
+gx400 MACH_GX400 GX400 3645
+gs300 MACH_GS300 GS300 3646
+acer_a9 MACH_ACER_A9 ACER_A9 3647
+vivow_evm MACH_VIVOW_EVM VIVOW_EVM 3648
+veloce_cxq MACH_VELOCE_CXQ VELOCE_CXQ 3649
+veloce_cxm MACH_VELOCE_CXM VELOCE_CXM 3650
+p1852 MACH_P1852 P1852 3651
+naxy100 MACH_NAXY100 NAXY100 3652
+taishan MACH_TAISHAN TAISHAN 3653
+touchlink MACH_TOUCHLINK TOUCHLINK 3654
+stm32f103ze MACH_STM32F103ZE STM32F103ZE 3655
+mcx MACH_MCX MCX 3656
+stm_nmhdk_fli7610 MACH_STM_NMHDK_FLI7610 STM_NMHDK_FLI7610 3657
+top28x MACH_TOP28X TOP28X 3658
+okl4vp_microvisor MACH_OKL4VP_MICROVISOR OKL4VP_MICROVISOR 3659
+pop MACH_POP POP 3660
+layer MACH_LAYER LAYER 3661
+trondheim MACH_TRONDHEIM TRONDHEIM 3662
+eva MACH_EVA EVA 3663
+trust_taurus MACH_TRUST_TAURUS TRUST_TAURUS 3664
+ns2816_huashan MACH_NS2816_HUASHAN NS2816_HUASHAN 3665
+ns2816_yangcheng MACH_NS2816_YANGCHENG NS2816_YANGCHENG 3666
+p852 MACH_P852 P852 3667
+flea3 MACH_FLEA3 FLEA3 3668
+bowfin MACH_BOWFIN BOWFIN 3669
+mv88de3100 MACH_MV88DE3100 MV88DE3100 3670
+pia_am35x MACH_PIA_AM35X PIA_AM35X 3671
+cedar MACH_CEDAR CEDAR 3672
+picasso_e MACH_PICASSO_E PICASSO_E 3673
+samsung_e60 MACH_SAMSUNG_E60 SAMSUNG_E60 3674
+msm9615_cdp MACH_MDM9615 MDM9615 3675
+sdvr_mini MACH_SDVR_MINI SDVR_MINI 3676
+omap3_ij3k MACH_OMAP3_IJ3K OMAP3_IJ3K 3677
+modasmc1 MACH_MODASMC1 MODASMC1 3678
+apq8064_rumi3 MACH_APQ8064_RUMI3 APQ8064_RUMI3 3679
+matrix506 MACH_MATRIX506 MATRIX506 3680
+msm9615_mtp MACH_MSM9615_MTP MSM9615_MTP 3681
+dm36x_spawndc MACH_DM36X_SPAWNDC DM36X_SPAWNDC 3682
+sff792 MACH_SFF792 SFF792 3683
+am335xiaevm MACH_AM335XIAEVM AM335XIAEVM 3684
+g3c2440 MACH_G3C2440 G3C2440 3685
+tion270 MACH_TION270 TION270 3686
+w22q7arm02 MACH_W22Q7ARM02 W22Q7ARM02 3687
+omap_cat MACH_OMAP_CAT OMAP_CAT 3688
+at91sam9n12ek MACH_AT91SAM9N12EK AT91SAM9N12EK 3689
+morrison MACH_MORRISON MORRISON 3690
+svdu MACH_SVDU SVDU 3691
+lpp01 MACH_LPP01 LPP01 3692
+ubc283 MACH_UBC283 UBC283 3693
+zeppelin MACH_ZEPPELIN ZEPPELIN 3694
+motus MACH_MOTUS MOTUS 3695
+neomainboard MACH_NEOMAINBOARD NEOMAINBOARD 3696
+devkit3250 MACH_DEVKIT3250 DEVKIT3250 3697
+devkit7000 MACH_DEVKIT7000 DEVKIT7000 3698
+fmc_uic MACH_FMC_UIC FMC_UIC 3699
+fmc_dcm MACH_FMC_DCM FMC_DCM 3700
+batwm MACH_BATWM BATWM 3701
+atlas6cb MACH_ATLAS6CB ATLAS6CB 3702
+quattro_f MACH_QUATTROF QUATTROF 3703
+quattro_u MACH_QUATTROU QUATTROU 3704
+blue MACH_BLUE BLUE 3705
+colorado MACH_COLORADO COLORADO 3706
+popc MACH_POPC POPC 3707
+promwad_jade MACH_PROMWAD_JADE PROMWAD_JADE 3708
+amp MACH_AMP AMP 3709
+gnet_amp MACH_GNET_AMP GNET_AMP 3710
+toques MACH_TOQUES TOQUES 3711
+apx4devkit MACH_APX4DEVKIT APX4DEVKIT 3712
+dct_storm MACH_DCT_STORM DCT_STORM 3713
+dm8168z3 MACH_Z3 Z3 3714
+owl MACH_OWL OWL 3715
+cogent_csb1741 MACH_COGENT_CSB1741 COGENT_CSB1741 3716
+omap3_kiko MACH_OMAP3 OMAP3 3717
+adillustra610 MACH_ADILLUSTRA610 ADILLUSTRA610 3718
+ecafe_na04 MACH_ECAFE_NA04 ECAFE_NA04 3719
+popct MACH_POPCT POPCT 3720
+omap3_helena MACH_OMAP3_HELENA OMAP3_HELENA 3721
+ach MACH_ACH ACH 3722
+module_dtb MACH_MODULE_DTB MODULE_DTB 3723
+ratebox MACH_RACKBOX RACKBOX 3724
+oslo_elisabeth MACH_OSLO_ELISABETH OSLO_ELISABETH 3725
+tt01 MACH_TT01 TT01 3726
+msm8930_cdp MACH_MSM8930_CDP MSM8930_CDP 3727
+msm8930_mtp MACH_MSM8930_MTP MSM8930_MTP 3728
+msm8930_fluid MACH_MSM8930_FLUID MSM8930_FLUID 3729
+ltu11 MACH_LTU11 LTU11 3730
+am1808_spawnco MACH_AM1808_SPAWNCO AM1808_SPAWNCO 3731
+flx6410 MACH_FLX6410 FLX6410 3732
+mx6q_qsb MACH_MX6Q_QSB MX6Q_QSB 3733
+mx53_plt424 MACH_MX53_PLT424 MX53_PLT424 3734
+jasmine MACH_JASMINE JASMINE 3735
+l138_owlboard_plus MACH_L138_OWLBOARD_PLUS L138_OWLBOARD_PLUS 3736
+wr21 MACH_WR21 WR21 3737
+peaboy MACH_PEABOY PEABOY 3739
+mx28_plato MACH_MX28_PLATO MX28_PLATO 3740
+kacom2 MACH_KACOM2 KACOM2 3741
+slco MACH_SLCO SLCO 3742
+imx51pico MACH_IMX51PICO IMX51PICO 3743
+glink1 MACH_GLINK1 GLINK1 3744
+diamond MACH_DIAMOND DIAMOND 3745
+d9000 MACH_D9000 D9000 3746
+w5300e01 MACH_W5300E01 W5300E01 3747
+im6000 MACH_IM6000 IM6000 3748
+mx51_fred51 MACH_MX51_FRED51 MX51_FRED51 3749
+stm32f2 MACH_STM32F2 STM32F2 3750
+ville MACH_VILLE VILLE 3751
+ptip_murnau MACH_PTIP_MURNAU PTIP_MURNAU 3752
+ptip_classic MACH_PTIP_CLASSIC PTIP_CLASSIC 3753
+mx53grb MACH_MX53GRB MX53GRB 3754
+gagarin MACH_GAGARIN GAGARIN 3755
+msm7627a_qrd1 MACH_MSM7X27A_QRD1 MSM7X27A_QRD1 3756
+nas2big MACH_NAS2BIG NAS2BIG 3757
+superfemto MACH_SUPERFEMTO SUPERFEMTO 3758
+teufel MACH_TEUFEL TEUFEL 3759
+dinara MACH_DINARA DINARA 3760
+vanquish MACH_VANQUISH VANQUISH 3761
+zipabox1 MACH_ZIPABOX1 ZIPABOX1 3762
+u9540 MACH_U9540 U9540 3763
+jet MACH_JET JET 3764
+smdk4412 MACH_SMDK4412 SMDK4412 3765
+elite MACH_ELITE ELITE 3766
+spear320_hmi MACH_SPEAR320_HMI SPEAR320_HMI 3767
+ontario MACH_ONTARIO ONTARIO 3768
+mx6q_sabrelite MACH_MX6Q_SABRELITE MX6Q_SABRELITE 3769
+vc200 MACH_VC200 VC200 3770
+msm7625a_ffa MACH_MSM7625A_FFA MSM7625A_FFA 3771
+msm7625a_surf MACH_MSM7625A_SURF MSM7625A_SURF 3772
+benthossbp MACH_BENTHOSSBP BENTHOSSBP 3773
+smdk5210 MACH_SMDK5210 SMDK5210 3774
+empq2300 MACH_EMPQ2300 EMPQ2300 3775
+minipos MACH_MINIPOS MINIPOS 3776
+omap5_sevm MACH_OMAP5_SEVM OMAP5_SEVM 3777
+shelter MACH_SHELTER SHELTER 3778
+omap3_devkit8500 MACH_OMAP3_DEVKIT8500 OMAP3_DEVKIT8500 3779
+edgetd MACH_EDGETD EDGETD 3780
+copperyard MACH_COPPERYARD COPPERYARD 3781
+edge_test MACH_EDGE EDGE 3782
+edge_u MACH_EDGE_U EDGE_U 3783
+edge_td MACH_EDGE_TD EDGE_TD 3784
+wdss MACH_WDSS WDSS 3785
+dl_pb25 MACH_DL_PB25 DL_PB25 3786
+dss11 MACH_DSS11 DSS11 3787
+cpa MACH_CPA CPA 3788
+aptp2000 MACH_APTP2000 APTP2000 3789
+marzen MACH_MARZEN MARZEN 3790
+st_turbine MACH_ST_TURBINE ST_TURBINE 3791
+gtl_it3300 MACH_GTL_IT3300 GTL_IT3300 3792
+mx6_mule MACH_MX6_MULE MX6_MULE 3793
+v7pxa_dt MACH_V7PXA_DT V7PXA_DT 3794
+v7mmp_dt MACH_V7MMP_DT V7MMP_DT 3795
+dragon7 MACH_DRAGON7 DRAGON7 3796
+krome MACH_KROME KROME 3797
+oratisdante MACH_ORATISDANTE ORATISDANTE 3798
+fathom MACH_FATHOM FATHOM 3799
+dns325 MACH_DNS325 DNS325 3800
+sarnen MACH_SARNEN SARNEN 3801
+ubisys_g1 MACH_UBISYS_G1 UBISYS_G1 3802
+mx53_pf1 MACH_MX53_PF1 MX53_PF1 3803
+asanti MACH_ASANTI ASANTI 3804
+volta MACH_VOLTA VOLTA 3805
+potenza MACH_S5P6450 S5P6450 3806
+knight MACH_KNIGHT KNIGHT 3807
+beaglebone MACH_BEAGLEBONE BEAGLEBONE 3808
+becker MACH_BECKER BECKER 3809
+fc360 MACH_FC360 FC360 3810
+pmi2_xls MACH_PMI2_XLS PMI2_XLS 3811
+taranto MACH_TARANTO TARANTO 3812
+plutux MACH_PLUTUX PLUTUX 3813
+ipmp_medcom MACH_IPMP_MEDCOM IPMP_MEDCOM 3814
+absolut MACH_ABSOLUT ABSOLUT 3815
+awpb3 MACH_AWPB3 AWPB3 3816
+nfp32xx_dt MACH_NFP32XX_DT NFP32XX_DT 3817
+dl_pb53 MACH_DL_PB53 DL_PB53 3818
+acu_ii MACH_ACU_II ACU_II 3819
+avalon MACH_AVALON AVALON 3820
+sphinx MACH_SPHINX SPHINX 3821
+titan_t MACH_TITAN_T TITAN_T 3822
+harvest_boris MACH_HARVEST_BORIS HARVEST_BORIS 3823
+mach_msm7x30_m3s MACH_MACH_MSM7X30_M3S MACH_MSM7X30_M3S 3824
+smdk5250 MACH_SMDK5250 SMDK5250 3825
+imxt_lite MACH_IMXT_LITE IMXT_LITE 3826
+imxt_std MACH_IMXT_STD IMXT_STD 3827
+imxt_log MACH_IMXT_LOG IMXT_LOG 3828
+imxt_nav MACH_IMXT_NAV IMXT_NAV 3829
+imxt_full MACH_IMXT_FULL IMXT_FULL 3830
+ag09015 MACH_AG09015 AG09015 3831
+am3517_mt_ventoux MACH_AM3517_MT_VENTOUX AM3517_MT_VENTOUX 3832
+dp1arm9 MACH_DP1ARM9 DP1ARM9 3833
+picasso_m MACH_PICASSO_M PICASSO_M 3834
+video_gadget MACH_VIDEO_GADGET VIDEO_GADGET 3835
+mtt_om3x MACH_MTT_OM3X MTT_OM3X 3836
+mx6q_arm2 MACH_MX6Q_ARM2 MX6Q_ARM2 3837
+picosam9g45 MACH_PICOSAM9G45 PICOSAM9G45 3838
+vpm_dm365 MACH_VPM_DM365 VPM_DM365 3839
+bonfire MACH_BONFIRE BONFIRE 3840
+mt2p2d MACH_MT2P2D MT2P2D 3841
+sigpda01 MACH_SIGPDA01 SIGPDA01 3842
+cn27 MACH_CN27 CN27 3843
+mx25_cwtap MACH_MX25_CWTAP MX25_CWTAP 3844
+apf28 MACH_APF28 APF28 3845
+pelco_maxwell MACH_PELCO_MAXWELL PELCO_MAXWELL 3846
+ge_phoenix MACH_GE_PHOENIX GE_PHOENIX 3847
+empc_a500 MACH_EMPC_A500 EMPC_A500 3848
+ims_arm9 MACH_IMS_ARM9 IMS_ARM9 3849
+mini2416 MACH_MINI2416 MINI2416 3850
+mini2450 MACH_MINI2450 MINI2450 3851
+mini310 MACH_MINI310 MINI310 3852
+spear_hurricane MACH_SPEAR_HURRICANE SPEAR_HURRICANE 3853
+mt7208 MACH_MT7208 MT7208 3854
+lpc178x MACH_LPC178X LPC178X 3855
+farleys MACH_FARLEYS FARLEYS 3856
+efm32gg_dk3750 MACH_EFM32GG_DK3750 EFM32GG_DK3750 3857
+zeus_board MACH_ZEUS_BOARD ZEUS_BOARD 3858
+cc51 MACH_CC51 CC51 3859
+fxi_c210 MACH_FXI_C210 FXI_C210 3860
+msm8627_cdp MACH_MSM8627_CDP MSM8627_CDP 3861
+msm8627_mtp MACH_MSM8627_MTP MSM8627_MTP 3862
+armadillo800eva MACH_ARMADILLO800EVA ARMADILLO800EVA 3863
+primou MACH_PRIMOU PRIMOU 3864
+primoc MACH_PRIMOC PRIMOC 3865
+primoct MACH_PRIMOCT PRIMOCT 3866
+a9500 MACH_A9500 A9500 3867
+pue_td MACH_PULSE_TD PULSE_TD 3868
+pluto MACH_PLUTO PLUTO 3869
+acfx100 MACH_ACFX100 ACFX100 3870
+msm8625_rumi3 MACH_MSM8625_RUMI3 MSM8625_RUMI3 3871
+valente MACH_VALENTE VALENTE 3872
+crfs_rfeye MACH_CRFS_RFEYE CRFS_RFEYE 3873
+rfeye MACH_RFEYE RFEYE 3874
+phidget_sbc3 MACH_PHIDGET_SBC3 PHIDGET_SBC3 3875
+tcw_mika MACH_TCW_MIKA TCW_MIKA 3876
+imx28_egf MACH_IMX28_EGF IMX28_EGF 3877
+valente_wx MACH_VALENTE_WX VALENTE_WX 3878
+huangshans MACH_HUANGSHANS HUANGSHANS 3879
+bosphorus1 MACH_BOSPHORUS1 BOSPHORUS1 3880
+prima MACH_PRIMA PRIMA 3881
+meson3_skt MACH_M3_SKT M3_SKT 3882
+meson3_ref MACH_M3_REF M3_REF 3883
+evita_ulk MACH_EVITA_ULK EVITA_ULK 3884
+merisc600 MACH_MERISC600 MERISC600 3885
+dolak MACH_DOLAK DOLAK 3886
+sbc53 MACH_SBC53 SBC53 3887
+elite_ulk MACH_ELITE_ULK ELITE_ULK 3888
+pov2 MACH_POV2 POV2 3889
+ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890
+da850_pqab MACH_DA850_PQAB DA850_PQAB 3891
+fermi MACH_FERMI FERMI 3892
+ccardwmx28 MACH_CCARDWMX28 CCARDWMX28 3893
+ccardmx28 MACH_CCARDMX28 CCARDMX28 3894
+fs20_fcm2050 MACH_FS20_FCM2050 FS20_FCM2050 3895
+kinetis MACH_KINETIS KINETIS 3896
+kai MACH_KAI KAI 3897
+bcthb2 MACH_BCTHB2 BCTHB2 3898
+inels3_cu MACH_INELS3_CU INELS3_CU 3899
+da850_juniper MACH_JUNIPER JUNIPER 3900
+da850_apollo MACH_DA850_APOLLO DA850_APOLLO 3901
+tracnas MACH_TRACNAS TRACNAS 3902
+mityarm335x MACH_MITYARM335X MITYARM335X 3903
+xcgz7x MACH_XCGZ7X XCGZ7X 3904
+cubox MACH_CUBOX CUBOX 3905
+terminator MACH_TERMINATOR TERMINATOR 3906
+eye03 MACH_EYE03 EYE03 3907
+kota3 MACH_KOTA3 KOTA3 3908
+mx53_nitrogen_k MACH_MX5 MX5 3909
+pscpe MACH_PSCPE PSCPE 3910
+akt1100 MACH_AKT1100 AKT1100 3911
+pcaaxl2 MACH_PCAAXL2 PCAAXL2 3912
+primodd_ct MACH_PRIMODD_CT PRIMODD_CT 3913
+nsbc MACH_NSBC NSBC 3914
+meson2_skt MACH_MESON2_SKT MESON2_SKT 3915
+meson2_ref MACH_MESON2_REF MESON2_REF 3916
+ccardwmx28js MACH_CCARDWMX28JS CCARDWMX28JS 3917
+ccardmx28js MACH_CCARDMX28JS CCARDMX28JS 3918
+indico MACH_INDICO INDICO 3919
+msm8960dt MACH_MSM8960DT MSM8960DT 3920
+primods MACH_PRIMODS PRIMODS 3921
+beluga_m1388 MACH_BELUGA_M1388 BELUGA_M1388 3922
+primotd MACH_PRIMOTD PRIMOTD 3923
+varan_master MACH_VARAN_MASTER VARAN_MASTER 3924
+primodd MACH_PRIMODD PRIMODD 3925
+jetduo MACH_JETDUO JETDUO 3926
+mx53_umobo MACH_MX53_UMOBO MX53_UMOBO 3927
+trats MACH_TRATS TRATS 3928
+starcraft MACH_STARCRAFT STARCRAFT 3929
+qseven_tegra2 MACH_QSEVEN_TEGRA2 QSEVEN_TEGRA2 3930
+lichee_sun4i_devbd MACH_LICHEE_SUN4I_DEVBD LICHEE_SUN4I_DEVBD 3931
+movenow MACH_MOVENOW MOVENOW 3932
+golf_u MACH_GOLF_U GOLF_U 3933
+msm7627a_evb MACH_MSM7627A_EVB MSM7627A_EVB 3934
+rambo MACH_RAMBO RAMBO 3935
+golfu MACH_GOLFU GOLFU 3936
+mango310 MACH_MANGO310 MANGO310 3937
+dns343 MACH_DNS343 DNS343 3938
+var_som_om44 MACH_VAR_SOM_OM44 VAR_SOM_OM44 3939
+naon MACH_NAON NAON 3940
+vp4000 MACH_VP4000 VP4000 3941
+impcard MACH_IMPCARD IMPCARD 3942
+smoovcam MACH_SMOOVCAM SMOOVCAM 3943
+cobham3725 MACH_COBHAM3725 COBHAM3725 3944
+cobham3730 MACH_COBHAM3730 COBHAM3730 3945
+cobham3703 MACH_COBHAM3703 COBHAM3703 3946
+quetzal MACH_QUETZAL QUETZAL 3947
+apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
+apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
+apq8064_fluid MACH_APQ8064_FLUID APQ8064_FLUID 3950
+apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
+mango210 MACH_MANGO210 MANGO210 3952
+mango100 MACH_MANGO100 MANGO100 3953
+mango24 MACH_MANGO24 MANGO24 3954
+mango64 MACH_MANGO64 MANGO64 3955
+nsa320 MACH_NSA320 NSA320 3956
+elv_ccu2 MACH_ELV_CCU2 ELV_CCU2 3957
+triton_x00 MACH_TRITON_X00 TRITON_X00 3958
+triton_1500_2000 MACH_TRITON_1500_2000 TRITON_1500_2000 3959
+pogoplugv4 MACH_POGOPLUGV4 POGOPLUGV4 3960
+venus_cl MACH_VENUS_CL VENUS_CL 3961
+vulcano_g20 MACH_VULCANO_G20 VULCANO_G20 3962
+sgs_i9100 MACH_SGS_I9100 SGS_I9100 3963
+stsv2 MACH_STSV2 STSV2 3964
+csb1724 MACH_CSB1724 CSB1724 3965
+omapl138_lcdk MACH_OMAPL138_LCDK OMAPL138_LCDK 3966
+jel_dd MACH_JEWEL_DD JEWEL_DD 3967
+pvd_mx25 MACH_PVD_MX25 PVD_MX25 3968
+meson6_skt MACH_MESON6_SKT MESON6_SKT 3969
+meson6_ref MACH_MESON6_REF MESON6_REF 3970
+pxm MACH_PXM PXM 3971
+stuttgart MACH_S3 S3 3972
+pogoplugv3 MACH_POGOPLUGV3 POGOPLUGV3 3973
+mlp89626 MACH_MLP89626 MLP89626 3974
+iomegahmndce MACH_IOMEGAHMNDCE IOMEGAHMNDCE 3975
+pogoplugv3pci MACH_POGOPLUGV3PCI POGOPLUGV3PCI 3976
+bntv250 MACH_BNTV250 BNTV250 3977
+mx53_qseven MACH_MX53_QSEVEN MX53_QSEVEN 3978
+gtl_it1100 MACH_GTL_IT1100 GTL_IT1100 3979
+mx6q_sabresd MACH_MX6Q_SABRESD MX6Q_SABRESD 3980
+mt4 MACH_MT4 MT4 3981
+jumbo_d MACH_JUMBO_D JUMBO_D 3982
+jumbo_i MACH_JUMBO_I JUMBO_I 3983
+fs20_dmp MACH_FS20_DMP FS20_DMP 3984
+dns320 MACH_DNS320 DNS320 3985
+mx28bacos MACH_MX28BACOS MX28BACOS 3986
+tl80 MACH_TL80 TL80 3987
+polatis_nic_1001 MACH_POLATIS_NIC_1001 POLATIS_NIC_1001 3988
+tely MACH_TELY TELY 3989
+u8520 MACH_U8520 U8520 3990
+manta MACH_MANTA MANTA 3991
+spear1340_lcad MACH_SPEAR_EM_S900 SPEAR_EM_S900 3992
+mpq8064_cdp MACH_MPQ8064_CDP MPQ8064_CDP 3993
+mpq8064_hrd MACH_MPQ8064_STB MPQ8064_STB 3994
+mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995
+dm368som MACH_DM368SOM DM368SOM 3996
+gprisb2 MACH_GPRISB2 GPRISB2 3997
+chammid MACH_CHAMMID CHAMMID 3998
+seoul2 MACH_SEOUL2 SEOUL2 3999
+omap4_nooktablet MACH_OMAP4_NOOKTABLET OMAP4_NOOKTABLET 4000
+aalto MACH_AALTO AALTO 4001
+metro MACH_METRO METRO 4002
+cydm3730 MACH_CYDM3730 CYDM3730 4003
+tqma53 MACH_TQMA53 TQMA53 4004
+msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
+mx28_canby MACH_MX28_CANBY MX28_CANBY 4006
+tiger MACH_TIGER TIGER 4007
+pcats_9307_type_a MACH_PCATS_9307_TYPE_A PCATS_9307_TYPE_A 4008
+pcats_9307_type_o MACH_PCATS_9307_TYPE_O PCATS_9307_TYPE_O 4009
+pcats_9307_type_r MACH_PCATS_9307_TYPE_R PCATS_9307_TYPE_R 4010
+streamplug MACH_STREAMPLUG STREAMPLUG 4011
+icechicken_dev MACH_ICECHICKEN_DEV ICECHICKEN_DEV 4012
+hedgehog MACH_HEDGEHOG HEDGEHOG 4013
+yusend_obc MACH_YUSEND_OBC YUSEND_OBC 4014
+imxninja MACH_IMXNINJA IMXNINJA 4015
+omap4_jarod MACH_OMAP4_JAROD OMAP4_JAROD 4016
+eco5_pk MACH_ECO5_PK ECO5_PK 4017
+qj2440 MACH_QJ2440 QJ2440 4018
+mx6q_mercury MACH_MX6Q_MERCURY MX6Q_MERCURY 4019
+cm6810 MACH_CM6810 CM6810 4020
+omap4_torpedo MACH_OMAP4_TORPEDO OMAP4_TORPEDO 4021
+nsa310 MACH_NSA310 NSA310 4022
+tmx536 MACH_TMX536 TMX536 4023
+ktt20 MACH_KTT20 KTT20 4024
+dragonix MACH_DRAGONIX DRAGONIX 4025
+lungching MACH_LUNGCHING LUNGCHING 4026
+bulogics MACH_BULOGICS BULOGICS 4027
+mx535_sx MACH_MX535_SX MX535_SX 4028
+ngui3250 MACH_NGUI3250 NGUI3250 4029
+salutec_dac MACH_SALUTEC_DAC SALUTEC_DAC 4030
+loco MACH_LOCO LOCO 4031
+ctera_plug_usi MACH_CTERA_PLUG_USI CTERA_PLUG_USI 4032
+scepter MACH_SCEPTER SCEPTER 4033
+sga MACH_SGA SGA 4034
+p_81_j5 MACH_P_81_J5 P_81_J5 4035
+p_81_o4 MACH_P_81_O4 P_81_O4 4036
+msm8625_surf MACH_MSM8625_SURF MSM8625_SURF 4037
+carallon_shark MACH_CARALLON_SHARK CARALLON_SHARK 4038
+lsgc_icam MACH_LSGCICAM LSGCICAM 4039
+ordog MACH_ORDOG ORDOG 4040
+puente_io MACH_PUENTE_IO PUENTE_IO 4041
+msm8625_evb MACH_MSM8625_EVB MSM8625_EVB 4042
+ev_am1707 MACH_EV_AM1707 EV_AM1707 4043
+ev_am1707e2 MACH_EV_AM1707E2 EV_AM1707E2 4044
+ev_am3517e2 MACH_EV_AM3517E2 EV_AM3517E2 4045
+calabria MACH_CALABRIA CALABRIA 4046
+ev_imx287 MACH_EV_IMX287 EV_IMX287 4047
+erau MACH_ERAU ERAU 4048
+sichuan MACH_SICHUAN SICHUAN 4049
+sopdm MACH_WIRMA3 WIRMA3 4050
+davinci_da850 MACH_DAVINCI_DA850 DAVINCI_DA850 4051
+omap138_trunarc MACH_OMAP138_TRUNARC OMAP138_TRUNARC 4052
+bcm4761 MACH_BCM4761 BCM4761 4053
+picasso_e2 MACH_PICASSO_E2 PICASSO_E2 4054
+picasso_mf MACH_PICASSO_MF PICASSO_MF 4055
+miro MACH_MIRO MIRO 4056
+at91sam9g20ewon3 MACH_AT91SAM9G20EWON3 AT91SAM9G20EWON3 4057
+yoyo MACH_YOYO YOYO 4058
+windjkl MACH_WINDJKL WINDJKL 4059
+monarudo MACH_MONARUDO MONARUDO 4060
+batan MACH_BATAN BATAN 4061
+tadao MACH_TADAO TADAO 4062
+baso MACH_BASO BASO 4063
+mahon MACH_MAHON MAHON 4064
+villec2 MACH_VILLEC2 VILLEC2 4065
+asi1230 MACH_ASI1230 ASI1230 4066
+alaska MACH_ALASKA ALASKA 4067
+swarco_shdsl2 MACH_SWARCO_SHDSL2 SWARCO_SHDSL2 4068
+oxrtu MACH_OXRTU OXRTU 4069
+omap5_panda MACH_OMAP5_PANDA OMAP5_PANDA 4070
+imx286 MACH_MX28XDI MX28XDI 4071
+c8000 MACH_C8000 C8000 4072
+bje_display3_5 MACH_BJE_DISPLAY3_5 BJE_DISPLAY3_5 4073
+picomod7 MACH_PICOMOD7 PICOMOD7 4074
+picocom5 MACH_PICOCOM5 PICOCOM5 4075
+qblissa8 MACH_QBLISSA8 QBLISSA8 4076
+armstonea8 MACH_ARMSTONEA8 ARMSTONEA8 4077
+netdcu14 MACH_NETDCU14 NETDCU14 4078
+at91sam9x5_epiphan MACH_AT91SAM9X5_EPIPHAN AT91SAM9X5_EPIPHAN 4079
+p2u MACH_P2U P2U 4080
+doris MACH_DORIS DORIS 4081
+j49 MACH_J49 J49 4082
+vdss2e MACH_VDSS2E VDSS2E 4083
+vc300 MACH_VC300 VC300 4084
+ns115_pad_test MACH_NS115_PAD_TEST NS115_PAD_TEST 4085
+ns115_pad_ref MACH_NS115_PAD_REF NS115_PAD_REF 4086
+ns115_phone_test MACH_NS115_PHONE_TEST NS115_PHONE_TEST 4087
+ns115_phone_ref MACH_NS115_PHONE_REF NS115_PHONE_REF 4088
+golfc MACH_GOLFC GOLFC 4089
+xerox_olympus MACH_XEROX_OLYMPUS XEROX_OLYMPUS 4090
+mx6sl_arm2 MACH_MX6SL_ARM2 MX6SL_ARM2 4091
+csb1701_csb1726 MACH_CSB1701_CSB1726 CSB1701_CSB1726 4092
+at91sam9xeek MACH_AT91SAM9XEEK AT91SAM9XEEK 4093
+ebv210 MACH_EBV210 EBV210 4094
+msm7627a_qrd7 MACH_MSM7627A_QRD7 MSM7627A_QRD7 4095
+svthin MACH_SVTHIN SVTHIN 4096
+duovero MACH_DUOVERO DUOVERO 4097
+chupacabra MACH_CHUPACABRA CHUPACABRA 4098
+scorpion MACH_SCORPION SCORPION 4099
+davinci_he_hmi10 MACH_DAVINCI_HE_HMI10 DAVINCI_HE_HMI10 4100
+topkick MACH_TOPKICK TOPKICK 4101
+m3_auguestrush MACH_M3_AUGUESTRUSH M3_AUGUESTRUSH 4102
+ipc335x MACH_IPC335X IPC335X 4103
+sun4i MACH_SUN4I SUN4I 4104
+imx233_olinuxino MACH_IMX233_OLINUXINO IMX233_OLINUXINO 4105
+k2_wl MACH_K2_WL K2_WL 4106
+k2_ul MACH_K2_UL K2_UL 4107
+k2_cl MACH_K2_CL K2_CL 4108
+minbari_w MACH_MINBARI_W MINBARI_W 4109
+minbari_m MACH_MINBARI_M MINBARI_M 4110
+k035 MACH_K035 K035 4111
+ariel MACH_ARIEL ARIEL 4112
+arielsaarc MACH_ARIELSAARC ARIELSAARC 4113
+arieldkb MACH_ARIELDKB ARIELDKB 4114
+armadillo810 MACH_ARMADILLO810 ARMADILLO810 4115
+tam335x MACH_TAM335X TAM335X 4116
+grouper MACH_GROUPER GROUPER 4117
+mpcsa21_9g20 MACH_MPCSA21_9G20 MPCSA21_9G20 4118
+m6u_cpu MACH_M6U_CPU M6U_CPU 4119
+davinci_dp10 MACH_DAVINCI_DP10 DAVINCI_DP10 4120
+ginkgo MACH_GINKGO GINKGO 4121
+cgt_qmx6 MACH_CGT_QMX6 CGT_QMX6 4122
+profpga MACH_PROFPGA PROFPGA 4123
+acfx100oc MACH_ACFX100OC ACFX100OC 4124
+acfx100nb MACH_ACFX100NB ACFX100NB 4125
+capricorn MACH_CAPRICORN CAPRICORN 4126
+pisces MACH_PISCES PISCES 4127
+aries MACH_ARIES ARIES 4128
+cancer MACH_CANCER CANCER 4129
+leo MACH_LEO LEO 4130
+virgo MACH_VIRGO VIRGO 4131
+sagittarius MACH_SAGITTARIUS SAGITTARIUS 4132
+devil MACH_DEVIL DEVIL 4133
+ballantines MACH_BALLANTINES BALLANTINES 4134
+omap3_procerusvpu MACH_OMAP3_PROCERUSVPU OMAP3_PROCERUSVPU 4135
+my27 MACH_MY27 MY27 4136
+sun6i MACH_SUN6I SUN6I 4137
+sun5i MACH_SUN5I SUN5I 4138
+mx512_mx MACH_MX512_MX MX512_MX 4139
+kzm9g MACH_KZM9G KZM9G 4140
+vdstbn MACH_VDSTBN VDSTBN 4141
+cfa10036 MACH_CFA10036 CFA10036 4142
+cfa10049 MACH_CFA10049 CFA10049 4143
+pcm051 MACH_PCM051 PCM051 4144
+vybrid_vf7xx MACH_VYBRID_VF7XX VYBRID_VF7XX 4145
+vybrid_vf6xx MACH_VYBRID_VF6XX VYBRID_VF6XX 4146
+vybrid_vf5xx MACH_VYBRID_VF5XX VYBRID_VF5XX 4147
+vybrid_vf4xx MACH_VYBRID_VF4XX VYBRID_VF4XX 4148
+aria_g25 MACH_ARIA_G25 ARIA_G25 4149
+bcm21553 MACH_BCM21553 BCM21553 4150
+smdk5410 MACH_SMDK5410 SMDK5410 4151
+lpc18xx MACH_LPC18XX LPC18XX 4152
+oratisparty MACH_ORATISPARTY ORATISPARTY 4153
+qseven MACH_QSEVEN QSEVEN 4154
+gmv_generic MACH_GMV_GENERIC GMV_GENERIC 4155
+th_link_eth MACH_TH_LINK_ETH TH_LINK_ETH 4156
+tn_muninn MACH_TN_MUNINN TN_MUNINN 4157
+rampage MACH_RAMPAGE RAMPAGE 4158
+visstrim_mv10 MACH_VISSTRIM_MV10 VISSTRIM_MV10 4159
+monacotdu MACH_MONACO_TDU MONACO_TDU 4160
+monacoul MACH_MONACO_UL MONACO_UL 4161
+enrc2u MACH_ENRC2_U ENRC2_U 4162
+evitareul MACH_EVITA_UL EVITA_UL 4163
+mx28_wilma MACH_MX28_WILMA MX28_WILMA 4164
+monacou MACH_MONACO_U MONACO_U 4165
+msm8625_ffa MACH_MSM8625_FFA MSM8625_FFA 4166
+vpu101 MACH_VPU101 VPU101 4167
+operaul MACH_OPERA_UL OPERA_UL 4168
+baileys MACH_BAILEYS BAILEYS 4169
+familybox MACH_FAMILYBOX FAMILYBOX 4170
+ensemble_mx35 MACH_ENSEMBLE_MX35 ENSEMBLE_MX35 4171
+sc_sps_1 MACH_SC_SPS_1 SC_SPS_1 4172
+ucsimply_sam9260 MACH_UCSIMPLY_SAM9260 UCSIMPLY_SAM9260 4173
+unicorn MACH_UNICORN UNICORN 4174
+m9g45a MACH_M9G45A M9G45A 4175
+mtwebif MACH_MTWEBIF MTWEBIF 4176
+playstone MACH_PLAYSTONE PLAYSTONE 4177
+chelsea MACH_CHELSEA CHELSEA 4178
+bayern MACH_BAYERN BAYERN 4179
+mitwo MACH_MITWO MITWO 4180
+mx25_noah MACH_MX25_NOAH MX25_NOAH 4181
+stm_b2020 MACH_STM_B2020 STM_B2020 4182
+annax_src MACH_ANNAX_SRC ANNAX_SRC 4183
+ionics_stratus MACH_IONICS_STRATUS IONICS_STRATUS 4184
+hugo MACH_HUGO HUGO 4185
+em300 MACH_EM300 EM300 4186
+mmp3_qseven MACH_MMP3_QSEVEN MMP3_QSEVEN 4187
+bosphorus2 MACH_BOSPHORUS2 BOSPHORUS2 4188
+tt2200 MACH_TT2200 TT2200 4189
+ocelot3 MACH_OCELOT3 OCELOT3 4190
+tek_cobra MACH_TEK_COBRA TEK_COBRA 4191
+protou MACH_PROTOU PROTOU 4192
Property changes on: trunk/sys/arm/conf/mach-types
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/fsl_ocotp.c
===================================================================
--- trunk/sys/arm/freescale/fsl_ocotp.c (rev 0)
+++ trunk/sys/arm/freescale/fsl_ocotp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,206 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Steven Lawrance <stl at koffein.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/fsl_ocotp.c 273656 2014-10-26 02:09:58Z ian $");
+
+/*
+ * Access to the Freescale i.MX6 On-Chip One-Time-Programmable Memory
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include <arm/freescale/fsl_ocotpreg.h>
+#include <arm/freescale/fsl_ocotpvar.h>
+
+/*
+ * Find the physical address and size of the ocotp registers and devmap them,
+ * returning a pointer to the virtual address of the base.
+ *
+ * XXX This is temporary until we've worked out all the details of controlling
+ * the load order of devices. In an ideal world this device would be up and
+ * running before anything that needs it. When we're at a point to make that
+ * happen, this little block of code, and the few lines in fsl_ocotp_read_4()
+ * that refer to it can be deleted.
+ */
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <dev/fdt/fdt_common.h>
+#include <machine/devmap.h>
+
+static uint32_t *ocotp_regs;
+static vm_size_t ocotp_size;
+
+static void
+fsl_ocotp_devmap(void)
+{
+ phandle_t child, root;
+ u_long base, size;
+
+ if ((root = OF_finddevice("/")) == 0)
+ goto fatal;
+ if ((child = fdt_depth_search_compatible(root, "fsl,imx6q-ocotp", 0)) == 0)
+ goto fatal;
+ if (fdt_regsize(child, &base, &size) != 0)
+ goto fatal;
+
+ ocotp_size = (vm_size_t)size;
+
+ if ((ocotp_regs = pmap_mapdev((vm_offset_t)base, ocotp_size)) == NULL)
+ goto fatal;
+
+ return;
+fatal:
+ panic("cannot find/map the ocotp registers");
+}
+/* XXX end of temporary code */
+
+struct ocotp_softc {
+ device_t dev;
+ struct resource *mem_res;
+};
+
+static struct ocotp_softc *ocotp_sc;
+
+static inline uint32_t
+RD4(struct ocotp_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static int
+ocotp_detach(device_t dev)
+{
+
+ /* The ocotp registers are always accessible. */
+ return (EBUSY);
+}
+
+static int
+ocotp_attach(device_t dev)
+{
+ struct ocotp_softc *sc;
+ int err, rid;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ /* Allocate bus_space resources. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ ocotp_sc = sc;
+
+ /* We're done with the temporary mapping now. */
+ if (ocotp_regs != NULL)
+ pmap_unmapdev((vm_offset_t)ocotp_regs, ocotp_size);
+
+ err = 0;
+
+out:
+ if (err != 0)
+ ocotp_detach(dev);
+
+ return (err);
+}
+
+static int
+ocotp_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "fsl,imx6q-ocotp") == 0)
+ return (ENXIO);
+
+ device_set_desc(dev,
+ "Freescale On-Chip One-Time-Programmable Memory");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+uint32_t
+fsl_ocotp_read_4(bus_size_t off)
+{
+
+ if (off > FSL_OCOTP_LAST_REG)
+ panic("fsl_ocotp_read_4: offset out of range");
+
+ /* If we have a softcontext use the regular bus_space read. */
+ if (ocotp_sc != NULL)
+ return (RD4(ocotp_sc, off));
+
+ /*
+ * Otherwise establish a tempory device mapping if necessary, and read
+ * the device without any help from bus_space.
+ *
+ * XXX Eventually the code from there down can be deleted.
+ */
+ if (ocotp_regs == NULL)
+ fsl_ocotp_devmap();
+
+ return (ocotp_regs[off / 4]);
+}
+
+static device_method_t ocotp_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ocotp_probe),
+ DEVMETHOD(device_attach, ocotp_attach),
+ DEVMETHOD(device_detach, ocotp_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t ocotp_driver = {
+ "ocotp",
+ ocotp_methods,
+ sizeof(struct ocotp_softc)
+};
+
+static devclass_t ocotp_devclass;
+
+EARLY_DRIVER_MODULE(ocotp, simplebus, ocotp_driver, ocotp_devclass, 0, 0,
+ BUS_PASS_CPU + BUS_PASS_ORDER_FIRST);
+
Property changes on: trunk/sys/arm/freescale/fsl_ocotp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/fsl_ocotpreg.h
===================================================================
--- trunk/sys/arm/freescale/fsl_ocotpreg.h (rev 0)
+++ trunk/sys/arm/freescale/fsl_ocotpreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,89 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Steven Lawrance <stl at koffein.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/fsl_ocotpreg.h 266200 2014-05-15 22:35:04Z ian $
+ */
+
+#ifndef FSL_OCOTPREG_H
+#define FSL_OCOTPREG_H
+
+#define FSL_OCOTP_CTRL 0x000
+#define FSL_OCOTP_CTRL_SET 0x004
+#define FSL_OCOTP_CTRL_CLR 0x008
+#define FSL_OCOTP_CTRL_TOG 0x00C
+#define FSL_OCOTP_TIMING 0x010
+#define FSL_OCOTP_DATA 0x020
+#define FSL_OCOTP_READ_CTRL 0x030
+#define FSL_OCOTP_READ_FUSE_DATA 0x040
+#define FSL_OCOTP_SW_STICKY 0x050
+#define FSL_OCOTP_SCS 0x060
+#define FSL_OCOTP_SCS_SET 0x064
+#define FSL_OCOTP_SCS_CLR 0x068
+#define FSL_OCOTP_SCS_TOG 0x06C
+#define FSL_OCOTP_VERSION 0x090
+#define FSL_OCOTP_LOCK 0x400
+#define FSL_OCOTP_CFG0 0x410
+#define FSL_OCOTP_CFG1 0x420
+#define FSL_OCOTP_CFG2 0x430
+#define FSL_OCOTP_CFG3 0x440
+#define FSL_OCOTP_CFG3_SPEED_SHIFT 16
+#define FSL_OCOTP_CFG3_SPEED_MASK \
+ (0x03 << FSL_OCOTP_CFG3_SPEED_SHIFT)
+#define FSL_OCOTP_CFG3_SPEED_792MHZ 0
+#define FSL_OCOTP_CFG3_SPEED_852MHZ 1
+#define FSL_OCOTP_CFG3_SPEED_996MHZ 2
+#define FSL_OCOTP_CFG3_SPEED_1200MHZ 3
+#define FSL_OCOTP_CFG4 0x450
+#define FSL_OCOTP_CFG5 0x460
+#define FSL_OCOTP_CFG6 0x470
+#define FSL_OCOTP_MEM0 0x480
+#define FSL_OCOTP_MEM1 0x490
+#define FSL_OCOTP_MEM2 0x4A0
+#define FSL_OCOTP_MEM3 0x4B0
+#define FSL_OCOTP_ANA0 0x4D0
+#define FSL_OCOTP_ANA1 0x4E0
+#define FSL_OCOTP_ANA2 0x4F0
+#define FSL_OCOTP_SRK0 0x580
+#define FSL_OCOTP_SRK1 0x590
+#define FSL_OCOTP_SRK2 0x5A0
+#define FSL_OCOTP_SRK3 0x5B0
+#define FSL_OCOTP_SRK4 0x5C0
+#define FSL_OCOTP_SRK5 0x5D0
+#define FSL_OCOTP_SRK6 0x5E0
+#define FSL_OCOTP_SRK7 0x5F0
+#define FSL_OCOTP_HSJC_RESP0 0x600
+#define FSL_OCOTP_HSJC_RESP1 0x610
+#define FSL_OCOTP_MAC0 0x620
+#define FSL_OCOTP_MAC1 0x630
+#define FSL_OCOTP_GP1 0x660
+#define FSL_OCOTP_GP2 0x670
+#define FSL_OCOTP_MISC_CONF 0x6D0
+#define FSL_OCOTP_FIELD_RETURN 0x6E0
+#define FSL_OCOTP_SRK_REVOKE 0x6F0
+
+#define FSL_OCOTP_LAST_REG FSL_OCOTP_SRK_REVOKE
+
+#endif
Property changes on: trunk/sys/arm/freescale/fsl_ocotpreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/fsl_ocotpvar.h
===================================================================
--- trunk/sys/arm/freescale/fsl_ocotpvar.h (rev 0)
+++ trunk/sys/arm/freescale/fsl_ocotpvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,35 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Steven Lawrance <stl at koffein.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/fsl_ocotpvar.h 266200 2014-05-15 22:35:04Z ian $
+ */
+
+#ifndef FSL_OCOTPVAR_H
+#define FSL_OCOTPVAR_H
+
+uint32_t fsl_ocotp_read_4(bus_size_t _offset);
+
+#endif
Property changes on: trunk/sys/arm/freescale/fsl_ocotpvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/console.c
===================================================================
--- trunk/sys/arm/freescale/imx/console.c (rev 0)
+++ trunk/sys/arm/freescale/imx/console.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,178 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Simple UART console driver for Freescale i.MX515 */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/console.c 253914 2013-08-03 13:31:10Z ian $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cons.h>
+#include <sys/consio.h>
+#include <sys/kernel.h>
+
+/* Allow it to be predefined, to be able to use another UART for console */
+#ifndef IMX_UART_BASE
+#define IMX_UART_BASE 0xe3fbc000 /* imx51 UART1 */
+#endif
+
+#define IMX_RXD 0x00
+#define IMX_TXD 0x40
+
+#define IMX_UFCR 0x90
+#define IMX_USR1 0x94
+#define IMX_USR1_TRDY (1 << 13)
+
+#define IMX_USR2 0x98
+#define IMX_USR2_RDR (1 << 0)
+#define IMX_USR2_TXFE (1 << 14)
+#define IMX_USR2_TXDC (1 << 3)
+
+#define IMX_UTS 0xb4
+#define IMX_UTS_TXFULL (1 << 4)
+
+/*
+ * The base address of the uart registers.
+ *
+ * This is global so that it can be changed on the fly from the outside. For
+ * example, set imx_uart_base=physaddr and then call cninit() as the first two
+ * lines of initarm() and enjoy printf() availability through the tricky bits of
+ * startup. After initarm() switches from physical to virtual addressing, just
+ * set imx_uart_base=virtaddr and printf keeps working.
+ */
+uint32_t imx_uart_base = IMX_UART_BASE;
+
+/*
+ * uart related funcs
+ */
+static uint32_t
+ub_getreg(uint32_t off)
+{
+
+ return *((volatile uint32_t *)(imx_uart_base + off));
+}
+
+static void
+ub_setreg(uint32_t off, uint32_t val)
+{
+
+ *((volatile uint32_t *)(imx_uart_base + off)) = val;
+}
+
+static int
+ub_tstc(void)
+{
+
+ return ((ub_getreg(IMX_USR2) & IMX_USR2_RDR) ? 1 : 0);
+}
+
+static int
+ub_getc(void)
+{
+
+ while (!ub_tstc());
+ __asm __volatile("nop");
+
+ return (ub_getreg(IMX_RXD) & 0xff);
+}
+
+static void
+ub_putc(unsigned char c)
+{
+
+ if (c == '\n')
+ ub_putc('\r');
+
+ while (ub_getreg(IMX_UTS) & IMX_UTS_TXFULL)
+ __asm __volatile("nop");
+
+ ub_setreg(IMX_TXD, c);
+}
+
+static cn_probe_t uart_cnprobe;
+static cn_init_t uart_cninit;
+static cn_term_t uart_cnterm;
+static cn_getc_t uart_cngetc;
+static cn_putc_t uart_cnputc;
+static cn_grab_t uart_cngrab;
+static cn_ungrab_t uart_cnungrab;
+
+static void
+uart_cngrab(struct consdev *cp)
+{
+
+}
+
+static void
+uart_cnungrab(struct consdev *cp)
+{
+
+}
+
+
+static void
+uart_cnprobe(struct consdev *cp)
+{
+
+ sprintf(cp->cn_name, "uart");
+ cp->cn_pri = CN_NORMAL;
+}
+
+static void
+uart_cninit(struct consdev *cp)
+{
+
+ /* Init fifo trigger levels to 32 bytes, refclock div to 2. */
+ ub_setreg(IMX_UFCR, 0x00004210);
+}
+
+static void
+uart_cnputc(struct consdev *cp, int c)
+{
+
+ ub_putc(c);
+}
+
+static int
+uart_cngetc(struct consdev * cp)
+{
+
+ return ub_getc();
+}
+
+static void
+uart_cnterm(struct consdev * cp)
+{
+
+}
+
+CONSOLE_DRIVER(uart);
Property changes on: trunk/sys/arm/freescale/imx/console.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/files.imx51
===================================================================
--- trunk/sys/arm/freescale/imx/files.imx51 (rev 0)
+++ trunk/sys/arm/freescale/imx/files.imx51 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,52 @@
+# $FreeBSD: stable/10/sys/arm/freescale/imx/files.imx51 278727 2015-02-13 22:32:02Z ian $
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+kern/kern_clocksource.c standard
+
+# Init
+arm/freescale/imx/imx_common.c standard
+arm/freescale/imx/imx_machdep.c standard
+arm/freescale/imx/imx51_machdep.c standard
+arm/arm/bus_space_base.c standard
+
+# Dummy serial console
+#arm/freescale/imx/console.c standard
+
+# TrustZone Interrupt Controller
+arm/freescale/imx/tzic.c standard
+
+# IOMUX - external pins multiplexor
+arm/freescale/imx/imx_iomux.c standard
+
+# GPIO
+arm/freescale/imx/imx_gpio.c optional gpio
+
+# Generic Periodic Timer
+arm/freescale/imx/imx_gpt.c standard
+
+# Clock Configuration Manager
+arm/freescale/imx/imx51_ccm.c standard
+
+# i.MX5xx PATA controller
+dev/ata/chipsets/ata-fsl.c optional imxata
+
+# UART driver
+dev/uart/uart_dev_imx.c optional uart
+
+# USB OH3 controller (1 OTG, 3 EHCI)
+arm/freescale/imx/imx_nop_usbphy.c optional echi
+dev/usb/controller/ehci_imx.c optional ehci
+
+# Watchdog
+arm/freescale/imx/imx_wdog.c optional imxwdt
+
+# i2c
+arm/freescale/imx/imx_i2c.c optional fsliic
+
+# IPU - Image Processing Unit (frame buffer also)
+arm/freescale/imx/imx51_ipuv3.c optional sc
+arm/freescale/imx/imx51_ipuv3_fbd.c optional vt
+dev/vt/hw/fb/vt_early_fb.c optional vt
Property changes on: trunk/sys/arm/freescale/imx/files.imx51
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/files.imx53
===================================================================
--- trunk/sys/arm/freescale/imx/files.imx53 (rev 0)
+++ trunk/sys/arm/freescale/imx/files.imx53 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,59 @@
+# $FreeBSD: stable/10/sys/arm/freescale/imx/files.imx53 278727 2015-02-13 22:32:02Z ian $
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+kern/kern_clocksource.c standard
+
+# Init
+arm/freescale/imx/imx_common.c standard
+arm/freescale/imx/imx_machdep.c standard
+arm/freescale/imx/imx53_machdep.c standard
+arm/arm/bus_space_base.c standard
+
+# Special serial console for debuging early boot code
+#arm/freescale/imx/console.c standard
+
+# UART driver (includes serial console support)
+dev/uart/uart_dev_imx.c optional uart
+
+# TrustZone Interrupt Controller
+arm/freescale/imx/tzic.c standard
+
+# IOMUX - external pins multiplexor
+arm/freescale/imx/imx_iomux.c standard
+
+# GPIO
+arm/freescale/imx/imx_gpio.c optional gpio
+
+# Generic Periodic Timer
+arm/freescale/imx/imx_gpt.c standard
+
+# Clock Configuration Manager
+arm/freescale/imx/imx51_ccm.c standard
+
+# i.MX5xx PATA controller
+dev/ata/chipsets/ata-fsl.c optional imxata
+
+# SDHCI/MMC
+arm/freescale/imx/imx_sdhci.c optional sdhci
+
+# USB OH3 controller (1 OTG, 3 EHCI)
+arm/freescale/imx/imx_nop_usbphy.c optional ehci
+dev/usb/controller/ehci_imx.c optional ehci
+
+# Watchdog
+arm/freescale/imx/imx_wdog.c optional imxwdt
+
+# i2c
+arm/freescale/imx/imx_i2c.c optional fsliic
+
+# IPU - Image Processing Unit (frame buffer also)
+arm/freescale/imx/imx51_ipuv3.c optional sc
+arm/freescale/imx/imx51_ipuv3_fbd.c optional vt
+dev/vt/hw/fb/vt_early_fb.c optional vt
+
+# Fast Ethernet Controller
+dev/ffec/if_ffec.c optional ffec
+
Property changes on: trunk/sys/arm/freescale/imx/files.imx53
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/files.imx6
===================================================================
--- trunk/sys/arm/freescale/imx/files.imx6 (rev 0)
+++ trunk/sys/arm/freescale/imx/files.imx6 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,73 @@
+# $FreeBSD: stable/10/sys/arm/freescale/imx/files.imx6 283500 2015-05-24 18:59:45Z ian $
+
+#
+# Standard ARM support.
+#
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+kern/kern_clocksource.c standard
+
+#
+# Standard imx6 devices and support.
+#
+arm/arm/gic.c standard
+arm/arm/pl310.c standard
+arm/arm/bus_space_base.c standard
+arm/arm/mpcore_timer.c standard
+arm/freescale/fsl_ocotp.c standard
+arm/freescale/imx/imx6_anatop.c standard
+arm/freescale/imx/imx6_ccm.c standard
+arm/freescale/imx/imx6_machdep.c standard
+arm/freescale/imx/imx6_mp.c optional smp
+arm/freescale/imx/imx6_pl310.c standard
+arm/freescale/imx/imx_iomux.c standard
+arm/freescale/imx/imx_machdep.c standard
+arm/freescale/imx/imx_gpt.c standard
+arm/freescale/imx/imx_gpio.c optional gpio
+arm/freescale/imx/imx_i2c.c optional fsliic
+arm/freescale/imx/imx6_sdma.c optional sdma
+arm/freescale/imx/imx6_audmux.c optional sound
+arm/freescale/imx/imx6_ssi.c optional sound
+
+#
+# Optional devices.
+#
+arm/freescale/imx/imx_sdhci.c optional sdhci
+
+arm/freescale/imx/imx_wdog.c optional imxwdt
+
+dev/ffec/if_ffec.c optional ffec
+
+dev/uart/uart_dev_imx.c optional uart
+
+dev/usb/controller/ehci_imx.c optional ehci
+arm/freescale/imx/imx6_usbphy.c optional ehci
+
+#
+# Low-level serial console for debugging early kernel startup.
+#
+#arm/freescale/imx/console.c standard
+
+#
+# Not ready yet...
+#
+#arm/freescale/imx/imx51_ipuv3.c optional sc
+
+# SDMA firmware
+sdma_fw.c optional sdma_fw \
+ compile-with "${AWK} -f $S/tools/fw_stub.awk sdma-imx6q-to1.bin:sdma_fw -msdma -c${.TARGET}" \
+ no-implicit-rule before-depend local \
+ clean "sdma_fw.c"
+sdma-imx6q-to1.fwo optional sdma_fw \
+ dependency "sdma-imx6q-to1.bin" \
+ compile-with "${LD} -b binary -d -warn-common -r -d -o ${.TARGET} sdma-imx6q-to1.bin" \
+ no-implicit-rule \
+ clean "sdma-imx6q-to1.fwo"
+sdma-imx6q-to1.bin optional sdma_fw \
+ dependency "$S/contrib/dev/imx/sdma-imx6q-to1.bin.uu" \
+ compile-with "uudecode < $S/contrib/dev/imx/sdma-imx6q-to1.bin.uu" \
+ no-obj no-implicit-rule \
+ clean "sdma-imx6q-to1.bin"
Property changes on: trunk/sys/arm/freescale/imx/files.imx6
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_ccm.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_ccm.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_ccm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,590 @@
+/* $MidnightBSD$ */
+/* $NetBSD: imx51_ccm.c,v 1.1 2012/04/17 09:33:31 bsh Exp $ */
+/*
+ * Copyright (c) 2010, 2011, 2012 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Clock Controller Module (CCM)
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx51_ccm.c 273659 2014-10-26 02:25:34Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/freescale/imx/imx51_ccmvar.h>
+#include <arm/freescale/imx/imx51_ccmreg.h>
+#include <arm/freescale/imx/imx51_dpllreg.h>
+#include <arm/freescale/imx/imx_ccmvar.h>
+#include <arm/freescale/imx/imx_machdep.h>
+
+#define IMXCCMDEBUG
+#undef IMXCCMDEBUG
+
+#ifndef IMX51_OSC_FREQ
+#define IMX51_OSC_FREQ (24 * 1000 * 1000) /* 24MHz */
+#endif
+
+#ifndef IMX51_CKIL_FREQ
+#define IMX51_CKIL_FREQ 32768
+#endif
+
+struct imxccm_softc {
+ device_t sc_dev;
+ struct resource *res[7];
+ u_int64_t pll_freq[IMX51_N_DPLLS];
+};
+
+struct imxccm_softc *ccm_softc = NULL;
+
+static uint64_t imx51_get_pll_freq(u_int);
+
+static int imxccm_match(device_t);
+static int imxccm_attach(device_t);
+
+static device_method_t imxccm_methods[] = {
+ DEVMETHOD(device_probe, imxccm_match),
+ DEVMETHOD(device_attach, imxccm_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t imxccm_driver = {
+ "imxccm",
+ imxccm_methods,
+ sizeof(struct imxccm_softc),
+};
+
+static devclass_t imxccm_devclass;
+
+EARLY_DRIVER_MODULE(imxccm, simplebus, imxccm_driver, imxccm_devclass, 0, 0,
+ BUS_PASS_CPU);
+
+static struct resource_spec imxccm_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Global registers */
+ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* DPLLIP1 */
+ { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* DPLLIP2 */
+ { SYS_RES_MEMORY, 3, RF_ACTIVE }, /* DPLLIP3 */
+ { SYS_RES_IRQ, 0, RF_ACTIVE }, /* 71 */
+ { SYS_RES_IRQ, 1, RF_ACTIVE }, /* 72 */
+ { -1, 0 }
+};
+
+static int
+imxccm_match(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm") &&
+ !ofw_bus_is_compatible(dev, "fsl,imx53-ccm"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale Clock Control Module");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+imxccm_attach(device_t dev)
+{
+ struct imxccm_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ if (bus_alloc_resources(dev, imxccm_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ ccm_softc = sc;
+
+ imx51_get_pll_freq(1);
+ imx51_get_pll_freq(2);
+ imx51_get_pll_freq(3);
+
+ device_printf(dev, "PLL1=%lluMHz, PLL2=%lluMHz, PLL3=%lluMHz\n",
+ sc->pll_freq[0] / 1000000,
+ sc->pll_freq[1] / 1000000,
+ sc->pll_freq[2] / 1000000);
+ device_printf(dev, "CPU clock=%d, UART clock=%d\n",
+ imx51_get_clock(IMX51CLK_ARM_ROOT),
+ imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
+ device_printf(dev,
+ "mainbus clock=%d, ahb clock=%d ipg clock=%d perclk=%d\n",
+ imx51_get_clock(IMX51CLK_MAIN_BUS_CLK),
+ imx51_get_clock(IMX51CLK_AHB_CLK_ROOT),
+ imx51_get_clock(IMX51CLK_IPG_CLK_ROOT),
+ imx51_get_clock(IMX51CLK_PERCLK_ROOT));
+
+
+ return (0);
+}
+
+u_int
+imx51_get_clock(enum imx51_clock clk)
+{
+ u_int freq;
+ u_int sel;
+ uint32_t cacrr; /* ARM clock root register */
+ uint32_t ccsr;
+ uint32_t cscdr1;
+ uint32_t cscmr1;
+ uint32_t cbcdr;
+ uint32_t cbcmr;
+ uint32_t cdcr;
+
+ if (ccm_softc == NULL)
+ return (0);
+
+ switch (clk) {
+ case IMX51CLK_PLL1:
+ case IMX51CLK_PLL2:
+ case IMX51CLK_PLL3:
+ return ccm_softc->pll_freq[clk-IMX51CLK_PLL1];
+ case IMX51CLK_PLL1SW:
+ ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
+ if ((ccsr & CCSR_PLL1_SW_CLK_SEL) == 0)
+ return ccm_softc->pll_freq[1-1];
+ /* step clock */
+ /* FALLTHROUGH */
+ case IMX51CLK_PLL1STEP:
+ ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
+ switch ((ccsr & CCSR_STEP_SEL_MASK) >> CCSR_STEP_SEL_SHIFT) {
+ case 0:
+ return imx51_get_clock(IMX51CLK_LP_APM);
+ case 1:
+ return 0; /* XXX PLL bypass clock */
+ case 2:
+ return ccm_softc->pll_freq[2-1] /
+ (1 + ((ccsr & CCSR_PLL2_DIV_PODF_MASK) >>
+ CCSR_PLL2_DIV_PODF_SHIFT));
+ case 3:
+ return ccm_softc->pll_freq[3-1] /
+ (1 + ((ccsr & CCSR_PLL3_DIV_PODF_MASK) >>
+ CCSR_PLL3_DIV_PODF_SHIFT));
+ }
+ /*NOTREACHED*/
+ case IMX51CLK_PLL2SW:
+ ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
+ if ((ccsr & CCSR_PLL2_SW_CLK_SEL) == 0)
+ return imx51_get_clock(IMX51CLK_PLL2);
+ return 0; /* XXX PLL2 bypass clk */
+ case IMX51CLK_PLL3SW:
+ ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
+ if ((ccsr & CCSR_PLL3_SW_CLK_SEL) == 0)
+ return imx51_get_clock(IMX51CLK_PLL3);
+ return 0; /* XXX PLL3 bypass clk */
+
+ case IMX51CLK_LP_APM:
+ ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
+ return (ccsr & CCSR_LP_APM) ?
+ imx51_get_clock(IMX51CLK_FPM) : IMX51_OSC_FREQ;
+
+ case IMX51CLK_ARM_ROOT:
+ freq = imx51_get_clock(IMX51CLK_PLL1SW);
+ cacrr = bus_read_4(ccm_softc->res[0], CCMC_CACRR);
+ return freq / (cacrr + 1);
+
+ /* ... */
+ case IMX51CLK_MAIN_BUS_CLK_SRC:
+ cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
+ if ((cbcdr & CBCDR_PERIPH_CLK_SEL) == 0)
+ freq = imx51_get_clock(IMX51CLK_PLL2SW);
+ else {
+ freq = 0;
+ cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR);
+ switch ((cbcmr & CBCMR_PERIPH_APM_SEL_MASK) >>
+ CBCMR_PERIPH_APM_SEL_SHIFT) {
+ case 0:
+ freq = imx51_get_clock(IMX51CLK_PLL1SW);
+ break;
+ case 1:
+ freq = imx51_get_clock(IMX51CLK_PLL3SW);
+ break;
+ case 2:
+ freq = imx51_get_clock(IMX51CLK_LP_APM);
+ break;
+ case 3:
+ /* XXX: error */
+ break;
+ }
+ }
+ return freq;
+ case IMX51CLK_MAIN_BUS_CLK:
+ freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
+ cdcr = bus_read_4(ccm_softc->res[0], CCMC_CDCR);
+ return freq / (1 + ((cdcr & CDCR_PERIPH_CLK_DVFS_PODF_MASK) >>
+ CDCR_PERIPH_CLK_DVFS_PODF_SHIFT));
+ case IMX51CLK_AHB_CLK_ROOT:
+ freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK);
+ cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
+ return freq / (1 + ((cbcdr & CBCDR_AHB_PODF_MASK) >>
+ CBCDR_AHB_PODF_SHIFT));
+ case IMX51CLK_IPG_CLK_ROOT:
+ freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
+ cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
+ return freq / (1 + ((cbcdr & CBCDR_IPG_PODF_MASK) >>
+ CBCDR_IPG_PODF_SHIFT));
+
+ case IMX51CLK_PERCLK_ROOT:
+ cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR);
+ if (cbcmr & CBCMR_PERCLK_IPG_SEL)
+ return imx51_get_clock(IMX51CLK_IPG_CLK_ROOT);
+ if (cbcmr & CBCMR_PERCLK_LP_APM_SEL)
+ freq = imx51_get_clock(IMX51CLK_LP_APM);
+ else
+ freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
+ cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
+
+#ifdef IMXCCMDEBUG
+ printf("cbcmr=%x cbcdr=%x\n", cbcmr, cbcdr);
+#endif
+
+ freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED1_MASK) >>
+ CBCDR_PERCLK_PRED1_SHIFT);
+ freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED2_MASK) >>
+ CBCDR_PERCLK_PRED2_SHIFT);
+ freq /= 1 + ((cbcdr & CBCDR_PERCLK_PODF_MASK) >>
+ CBCDR_PERCLK_PODF_SHIFT);
+ return freq;
+ case IMX51CLK_UART_CLK_ROOT:
+ cscdr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1);
+ cscmr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
+
+#ifdef IMXCCMDEBUG
+ printf("cscdr1=%x cscmr1=%x\n", cscdr1, cscmr1);
+#endif
+
+ sel = (cscmr1 & CSCMR1_UART_CLK_SEL_MASK) >>
+ CSCMR1_UART_CLK_SEL_SHIFT;
+
+ freq = 0; /* shut up GCC */
+ switch (sel) {
+ case 0:
+ case 1:
+ case 2:
+ freq = imx51_get_clock(IMX51CLK_PLL1SW + sel);
+ break;
+ case 3:
+ freq = imx51_get_clock(IMX51CLK_LP_APM);
+ break;
+ }
+
+ return freq / (1 + ((cscdr1 & CSCDR1_UART_CLK_PRED_MASK) >>
+ CSCDR1_UART_CLK_PRED_SHIFT)) /
+ (1 + ((cscdr1 & CSCDR1_UART_CLK_PODF_MASK) >>
+ CSCDR1_UART_CLK_PODF_SHIFT));
+ case IMX51CLK_IPU_HSP_CLK_ROOT:
+ freq = 0;
+ cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR);
+ switch ((cbcmr & CBCMR_IPU_HSP_CLK_SEL_MASK) >>
+ CBCMR_IPU_HSP_CLK_SEL_SHIFT) {
+ case 0:
+ freq = imx51_get_clock(IMX51CLK_ARM_AXI_A_CLK);
+ break;
+ case 1:
+ freq = imx51_get_clock(IMX51CLK_ARM_AXI_B_CLK);
+ break;
+ case 2:
+ freq = imx51_get_clock(
+ IMX51CLK_EMI_SLOW_CLK_ROOT);
+ break;
+ case 3:
+ freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
+ break;
+ }
+ return freq;
+ default:
+ device_printf(ccm_softc->sc_dev,
+ "clock %d: not supported yet\n", clk);
+ return 0;
+ }
+}
+
+
+static uint64_t
+imx51_get_pll_freq(u_int pll_no)
+{
+ uint32_t dp_ctrl;
+ uint32_t dp_op;
+ uint32_t dp_mfd;
+ uint32_t dp_mfn;
+ uint32_t mfi;
+ int32_t mfn;
+ uint32_t mfd;
+ uint32_t pdf;
+ uint32_t ccr;
+ uint64_t freq = 0;
+ u_int ref = 0;
+
+ KASSERT(1 <= pll_no && pll_no <= IMX51_N_DPLLS, ("Wrong PLL id"));
+
+ dp_ctrl = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_CTL);
+
+ if (dp_ctrl & DP_CTL_HFSM) {
+ dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_OP);
+ dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFD);
+ dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFN);
+ } else {
+ dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_OP);
+ dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFD);
+ dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFN);
+ }
+
+ pdf = dp_op & DP_OP_PDF_MASK;
+ mfi = max(5, (dp_op & DP_OP_MFI_MASK) >> DP_OP_MFI_SHIFT);
+ mfd = dp_mfd;
+ if (dp_mfn & 0x04000000)
+ /* 27bit signed value */
+ mfn = (uint32_t)(0xf8000000 | dp_mfn);
+ else
+ mfn = dp_mfn;
+
+ switch (dp_ctrl & DP_CTL_REF_CLK_SEL_MASK) {
+ case DP_CTL_REF_CLK_SEL_COSC:
+ /* Internal Oscillator */
+ /* TODO: get from FDT "fsl,imx-osc" */
+ ref = 24000000; /* IMX51_OSC_FREQ */
+ break;
+ case DP_CTL_REF_CLK_SEL_FPM:
+ ccr = bus_read_4(ccm_softc->res[0], CCMC_CCR);
+ if (ccr & CCR_FPM_MULT)
+ /* TODO: get from FDT "fsl,imx-ckil" */
+ ref = 32768 * 1024;
+ else
+ /* TODO: get from FDT "fsl,imx-ckil" */
+ ref = 32768 * 512;
+ break;
+ default:
+ ref = 0;
+ }
+
+ if (dp_ctrl & DP_CTL_REF_CLK_DIV)
+ ref /= 2;
+
+ ref *= 4;
+ freq = (int64_t)ref * mfi + (int64_t)ref * mfn / (mfd + 1);
+ freq /= pdf + 1;
+
+ if (!(dp_ctrl & DP_CTL_DPDCK0_2_EN))
+ freq /= 2;
+
+#ifdef IMXCCMDEBUG
+ printf("ref: %dKHz ", ref);
+ printf("dp_ctl: %08x ", dp_ctrl);
+ printf("pdf: %3d ", pdf);
+ printf("mfi: %3d ", mfi);
+ printf("mfd: %3d ", mfd);
+ printf("mfn: %3d ", mfn);
+ printf("pll: %d\n", (uint32_t)freq);
+#endif
+
+ ccm_softc->pll_freq[pll_no-1] = freq;
+
+ return (freq);
+}
+
+void
+imx51_clk_gating(int clk_src, int mode)
+{
+ int field, group;
+ uint32_t reg;
+
+ group = CCMR_CCGR_MODULE(clk_src);
+ field = clk_src % CCMR_CCGR_NSOURCE;
+ reg = bus_read_4(ccm_softc->res[0], CCMC_CCGR(group));
+ reg &= ~(0x03 << field * 2);
+ reg |= (mode << field * 2);
+ bus_write_4(ccm_softc->res[0], CCMC_CCGR(group), reg);
+}
+
+int
+imx51_get_clk_gating(int clk_src)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(ccm_softc->res[0],
+ CCMC_CCGR(CCMR_CCGR_MODULE(clk_src)));
+ return ((reg >> (clk_src % CCMR_CCGR_NSOURCE) * 2) & 0x03);
+}
+
+/*
+ * Code from here down is temporary, in lieu of a SoC-independent clock API.
+ */
+
+void
+imx_ccm_usb_enable(device_t dev)
+{
+ uint32_t regval;
+
+ /*
+ * Select PLL2 as the source for the USB clock.
+ * The default is PLL3, but U-boot changes it to PLL2.
+ */
+ regval = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
+ regval &= ~CSCMR1_USBOH3_CLK_SEL_MASK;
+ regval |= 1 << CSCMR1_USBOH3_CLK_SEL_SHIFT;
+ bus_write_4(ccm_softc->res[0], CCMC_CSCMR1, regval);
+
+ /*
+ * Set the USB clock pre-divider to div-by-5, post-divider to div-by-2.
+ */
+ regval = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1);
+ regval &= ~CSCDR1_USBOH3_CLK_PODF_MASK;
+ regval &= ~CSCDR1_USBOH3_CLK_PRED_MASK;
+ regval |= 4 << CSCDR1_USBOH3_CLK_PRED_SHIFT;
+ regval |= 1 << CSCDR1_USBOH3_CLK_PODF_SHIFT;
+ bus_write_4(ccm_softc->res[0], CCMC_CSCDR1, regval);
+
+ /*
+ * The same two clocks gates are used on imx51 and imx53.
+ */
+ imx51_clk_gating(CCGR_USBOH3_IPG_AHB_CLK, CCGR_CLK_MODE_ALWAYS);
+ imx51_clk_gating(CCGR_USBOH3_60M_CLK, CCGR_CLK_MODE_ALWAYS);
+}
+
+void
+imx_ccm_usbphy_enable(device_t dev)
+{
+ uint32_t regval;
+
+ /*
+ * Select PLL3 as the source for the USBPHY clock. U-boot does this
+ * only for imx53, but the bit exists on imx51. That seems a bit
+ * strange, but we'll go with it until more is known.
+ */
+ if (imx_soc_type() == IMXSOC_53) {
+ regval = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
+ regval |= 1 << CSCMR1_USBPHY_CLK_SEL_SHIFT;
+ bus_write_4(ccm_softc->res[0], CCMC_CSCMR1, regval);
+ }
+
+ /*
+ * For the imx51 there's just one phy gate control, enable it.
+ */
+ if (imx_soc_type() == IMXSOC_51) {
+ imx51_clk_gating(CCGR_USB_PHY_CLK, CCGR_CLK_MODE_ALWAYS);
+ return;
+ }
+
+ /*
+ * For imx53 we don't have a full set of clock defines yet, but the
+ * datasheet says:
+ * gate reg 4, bits 13-12 usb ph2 clock (usb_phy2_clk_enable)
+ * gate reg 4, bits 11-10 usb ph1 clock (usb_phy1_clk_enable)
+ *
+ * We should use the fdt data for the device to figure out which of
+ * the two we're working on, but for now just turn them both on.
+ */
+ if (imx_soc_type() == IMXSOC_53) {
+ imx51_clk_gating(__CCGR_NUM(4, 5), CCGR_CLK_MODE_ALWAYS);
+ imx51_clk_gating(__CCGR_NUM(4, 6), CCGR_CLK_MODE_ALWAYS);
+ return;
+ }
+}
+
+uint32_t
+imx_ccm_ipg_hz(void)
+{
+
+ return (imx51_get_clock(IMX51CLK_IPG_CLK_ROOT));
+}
+
+uint32_t
+imx_ccm_sdhci_hz(void)
+{
+
+ return (imx51_get_clock(IMX51CLK_ESDHC1_CLK_ROOT));
+}
+
+uint32_t
+imx_ccm_perclk_hz(void)
+{
+
+ return (imx51_get_clock(IMX51CLK_PERCLK_ROOT));
+}
+
+uint32_t
+imx_ccm_uart_hz(void)
+{
+
+ return (imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
+}
+
+uint32_t
+imx_ccm_ahb_hz(void)
+{
+
+ return (imx51_get_clock(IMX51CLK_AHB_CLK_ROOT));
+}
Property changes on: trunk/sys/arm/freescale/imx/imx51_ccm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_ccmreg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_ccmreg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_ccmreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,259 @@
+/* $MidnightBSD$ */
+/* $NetBSD: imx51_ccmreg.h,v 1.1 2012/04/17 09:33:31 bsh Exp $ */
+/*
+ * Copyright (c) 2011, 2012 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx51_ccmreg.h 259343 2013-12-13 22:12:37Z ian $
+ */
+
+#ifndef _IMX51_CCMREG_H
+#define _IMX51_CCMREG_H
+
+#include <sys/cdefs.h>
+
+/* register offset address */
+
+#define CCMC_BASE 0x73fd4000
+#define CCMC_CCR 0x0000
+#define CCR_FPM_MULT 0x00001000
+#define CCMC_CCDR 0x0004
+#define CCMC_CSR 0x0008
+#define CCMC_CCSR 0x000c
+#define CCSR_LP_APM 0x00000200
+#define CCSR_STEP_SEL_SHIFT 7
+#define CCSR_STEP_SEL_MASK 0x00000180
+#define CCSR_PLL2_DIV_PODF_SHIFT 5
+#define CCSR_PLL2_DIV_PODF_MASK 0x00000060
+#define CCSR_PLL3_DIV_PODF_SHIFT 3
+#define CCSR_PLL3_DIV_PODF_MASK 0x00000030
+#define CCSR_PLL1_SW_CLK_SEL 0x00000004
+#define CCSR_PLL2_SW_CLK_SEL 0x00000002
+#define CCSR_PLL3_SW_CLK_SEL 0x00000001
+#define CCMC_CACRR 0x0010
+#define CCMC_CBCDR 0x0014
+#define CBCDR_DDR_HIGH_FREQ_CLK_SEL 0x40000000
+#define CBCDR_DDR_CLK_PODF_SHIFT 27
+#define CBCDR_DDR_CLK_PODF_MASK 0x38000000
+#define CBCDR_EMI_CLK_SEL 0x04000000
+#define CBCDR_PERIPH_CLK_SEL 0x02000000
+#define CBCDR_EMI_SLOW_PODF_SHIFT 22
+#define CBCDR_EMI_SLOW_PODF_MASK 0x01c00000
+#define CBCDR_AXI_B_PODF_SHIFT 19
+#define CBCDR_AXI_B_PODF_MASK 0x00380000
+#define CBCDR_AXI_A_PODF_SHIFT 16
+#define CBCDR_AXI_A_PODF_MASK 0x1fff0000
+#define CBCDR_NFC_PODF_SHIFT 13
+#define CBCDR_NFC_PODF_MASK 0x00018000
+#define CBCDR_AHB_PODF_SHIFT 10
+#define CBCDR_AHB_PODF_MASK 0x00001c00
+#define CBCDR_IPG_PODF_SHIFT 8
+#define CBCDR_IPG_PODF_MASK 0x00000300
+#define CBCDR_PERCLK_PRED1_SHIFT 6
+#define CBCDR_PERCLK_PRED1_MASK 0x000000c0
+#define CBCDR_PERCLK_PRED2_SHIFT 3
+#define CBCDR_PERCLK_PRED2_MASK 0x00000038
+#define CBCDR_PERCLK_PODF_SHIFT 0
+#define CBCDR_PERCLK_PODF_MASK 0x00000007
+#define CCMC_CBCMR 0x0018
+#define CBCMR_PERIPH_APM_SEL_SHIFT 12
+#define CBCMR_PERIPH_APM_SEL_MASK 0x00003000
+#define CBCMR_IPU_HSP_CLK_SEL_SHIFT 6
+#define CBCMR_IPU_HSP_CLK_SEL_MASK 0x000000c0
+#define CBCMR_PERCLK_LP_APM_SEL 0x00000002
+#define CBCMR_PERCLK_IPG_SEL 0x00000001
+#define CCMC_CSCMR1 0x001c
+#define CSCMR1_UART_CLK_SEL_SHIFT 24
+#define CSCMR1_UART_CLK_SEL_MASK 0x03000000
+#define CSCMR1_USBPHY_CLK_SEL_SHIFT 26
+#define CSCMR1_USBPHY_CLK_SEL_MASK 0x04000000
+#define CSCMR1_USBOH3_CLK_SEL_SHIFT 22
+#define CSCMR1_USBOH3_CLK_SEL_MASK 0x00c00000
+#define CCMC_CSCMR2 0x0020
+#define CCMC_CSCDR1 0x0024
+#define CSCDR1_UART_CLK_PRED_SHIFT 3
+#define CSCDR1_UART_CLK_PRED_MASK 0x00000038
+#define CSCDR1_UART_CLK_PODF_SHIFT 0
+#define CSCDR1_UART_CLK_PODF_MASK 0x00000007
+#define CSCDR1_USBOH3_CLK_PRED_SHIFT 8
+#define CSCDR1_USBOH3_CLK_PRED_MASK 0x00000700
+#define CSCDR1_USBOH3_CLK_PODF_SHIFT 6
+#define CSCDR1_USBOH3_CLK_PODF_MASK 0x000000c0
+#define CCMC_CS1CDR 0x0028
+#define CCMC_CS2CDR 0x002c
+#define CCMC_CDCDR 0x0030
+#define CCMC_CSCDR2 0x0038
+#define CCMC_CSCDR3 0x003c
+#define CCMC_CSCDR4 0x0040
+#define CCMC_CWDR 0x0044
+#define CCMC_CDHIPR 0x0048
+#define CCMC_CDCR 0x004c
+#define CDCR_PERIPH_CLK_DVFS_PODF_SHIFT 0
+#define CDCR_PERIPH_CLK_DVFS_PODF_MASK 0x00000003
+#define CCMC_CTOR 0x0050
+#define CCMC_CLPCR 0x0054
+#define CCMC_CISR 0x0058
+#define CCMC_CIMR 0x005c
+#define CCMC_CCOSR 0x0060
+#define CCMC_CGPR 0x0064
+#define CCMC_CCGR(n) (0x0068 + (n) * 4)
+#define CCMC_CMEOR 0x0084
+
+#define CCMC_SIZE 0x88
+
+/* CCGR Clock Gate Register */
+
+#define CCMR_CCGR_NSOURCE 16
+#define CCMR_CCGR_NGROUPS 7
+#define CCMR_CCGR_MODULE(clk) ((clk) / CCMR_CCGR_NSOURCE)
+#define __CCGR_NUM(a, b) ((a) * 16 + (b))
+
+#define CCGR_ARM_BUS_CLK __CCGR_NUM(0, 0)
+#define CCGR_ARM_AXI_CLK __CCGR_NUM(0, 1)
+#define CCGR_ARM_DEBUG_CLK __CCGR_NUM(0, 2)
+#define CCGR_TZIC_CLK __CCGR_NUM(0, 3)
+#define CCGR_DAP_CLK __CCGR_NUM(0, 4)
+#define CCGR_TPIU_CLK __CCGR_NUM(0, 5)
+#define CCGR_CTI2_CLK __CCGR_NUM(0, 6)
+#define CCGR_CTI3_CLK __CCGR_NUM(0, 7)
+#define CCGR_AHBMUX1_CLK __CCGR_NUM(0, 8)
+#define CCGR_AHBMUX2_CLK __CCGR_NUM(0, 9)
+#define CCGR_ROMCP_CLK __CCGR_NUM(0, 10)
+#define CCGR_ROM_CLK __CCGR_NUM(0, 11)
+#define CCGR_AIPS_TZ1_CLK __CCGR_NUM(0, 12)
+#define CCGR_AIPS_TZ2_CLK __CCGR_NUM(0, 13)
+#define CCGR_AHB_MAX_CLK __CCGR_NUM(0, 14)
+#define CCGR_IIM_CLK __CCGR_NUM(0, 15)
+#define CCGR_TMAX1_CLK __CCGR_NUM(1, 0)
+#define CCGR_TMAX2_CLK __CCGR_NUM(1, 1)
+#define CCGR_TMAX3_CLK __CCGR_NUM(1, 2)
+#define CCGR_UART1_CLK __CCGR_NUM(1, 3)
+#define CCGR_UART1_SERIAL_CLK __CCGR_NUM(1, 4)
+#define CCGR_UART2_CLK __CCGR_NUM(1, 5)
+#define CCGR_UART2_SERIAL_CLK __CCGR_NUM(1, 6)
+#define CCGR_UART3_CLK __CCGR_NUM(1, 7)
+#define CCGR_UART3_SERIAL_CLK __CCGR_NUM(1, 8)
+#define CCGR_I2C1_SERIAL_CLK __CCGR_NUM(1, 9)
+#define CCGR_I2C2_SERIAL_CLK __CCGR_NUM(1, 10)
+#define CCGR_HSI2C_CLK __CCGR_NUM(1, 11)
+#define CCGR_HSI2C_SERIAL_CLK __CCGR_NUM(1, 12)
+#define CCGR_FIRI_CLK __CCGR_NUM(1, 13)
+#define CCGR_FIRI_SERIAL_CLK __CCGR_NUM(1, 14)
+#define CCGR_SCC_CLK __CCGR_NUM(1, 15)
+
+#define CCGR_USB_PHY_CLK __CCGR_NUM(2, 0)
+#define CCGR_EPIT1_CLK __CCGR_NUM(2, 1)
+#define CCGR_EPIT1_SERIAL_CLK __CCGR_NUM(2, 2)
+#define CCGR_EPIT2_CLK __CCGR_NUM(2, 3)
+#define CCGR_EPIT2_SERIAL_CLK __CCGR_NUM(2, 4)
+#define CCGR_PWM1_CLK __CCGR_NUM(2, 5)
+#define CCGR_PWM1_SERIAL_CLK __CCGR_NUM(2, 6)
+#define CCGR_PWM2_CLK __CCGR_NUM(2, 7)
+#define CCGR_PWM2_SERIAL_CLK __CCGR_NUM(2, 8)
+#define CCGR_GPT_CLK __CCGR_NUM(2, 9)
+#define CCGR_GPT_SERIAL_CLK __CCGR_NUM(2, 10)
+#define CCGR_OWIRE_CLK __CCGR_NUM(2, 11)
+#define CCGR_FEC_CLK __CCGR_NUM(2, 12)
+#define CCGR_USBOH3_IPG_AHB_CLK __CCGR_NUM(2, 13)
+#define CCGR_USBOH3_60M_CLK __CCGR_NUM(2, 14)
+#define CCGR_TVE_CLK __CCGR_NUM(2, 15)
+
+#define CCGR_ESDHC1_CLK __CCGR_NUM(3, 0)
+#define CCGR_ESDHC1_SERIAL_CLK __CCGR_NUM(3, 1)
+#define CCGR_ESDHC2_CLK __CCGR_NUM(3, 2)
+#define CCGR_ESDHC2_SERIAL_CLK __CCGR_NUM(3, 3)
+#define CCGR_ESDHC3_CLK __CCGR_NUM(3, 4)
+#define CCGR_ESDHC3_SERIAL_CLK __CCGR_NUM(3, 5)
+#define CCGR_ESDHC4_CLK __CCGR_NUM(3, 6)
+#define CCGR_ESDHC4_SERIAL_CLK __CCGR_NUM(3, 7)
+#define CCGR_SSI1_CLK __CCGR_NUM(3, 8)
+#define CCGR_SSI1_SERIAL_CLK __CCGR_NUM(3, 9)
+#define CCGR_SSI2_CLK __CCGR_NUM(3, 10)
+#define CCGR_SSI2_SERIAL_CLK __CCGR_NUM(3, 11)
+#define CCGR_SSI3_CLK __CCGR_NUM(3, 12)
+#define CCGR_SSI3_SERIAL_CLK __CCGR_NUM(3, 13)
+#define CCGR_SSI_EXT1_CLK __CCGR_NUM(3, 14)
+#define CCGR_SSI_EXT2_CLK __CCGR_NUM(3, 15)
+
+#define CCGR_PATA_CLK __CCGR_NUM(4, 0)
+#define CCGR_SIM_CLK __CCGR_NUM(4, 1)
+#define CCGR_SIM_SERIAL_CLK __CCGR_NUM(4, 2)
+#define CCGR_SAHARA_CLK __CCGR_NUM(4, 3)
+#define CCGR_RTIC_CLK __CCGR_NUM(4, 4)
+#define CCGR_ECSPI1_CLK __CCGR_NUM(4, 5)
+#define CCGR_ECSPI1_SERIAL_CLK __CCGR_NUM(4, 6)
+#define CCGR_ECSPI2_CLK __CCGR_NUM(4, 7)
+#define CCGR_ECSPI2_SERIAL_CLK __CCGR_NUM(4, 8)
+#define CCGR_CSPI_CLK __CCGR_NUM(4, 9)
+#define CCGR_SRTC_CLK __CCGR_NUM(4, 10)
+#define CCGR_SDMA_CLK __CCGR_NUM(4, 11)
+
+#define CCGR_SPBA_CLK __CCGR_NUM(5, 0)
+#define CCGR_GPU_CLK __CCGR_NUM(5, 1)
+#define CCGR_GARB_CLK __CCGR_NUM(5, 2)
+#define CCGR_VPU_CLK __CCGR_NUM(5, 3)
+#define CCGR_VPU_SERIAL_CLK __CCGR_NUM(5, 4)
+#define CCGR_IPU_CLK __CCGR_NUM(5, 5)
+#define CCGR_EMI_GARB_CLK __CCGR_NUM(6, 0)
+#define CCGR_IPU_DI0_CLK __CCGR_NUM(6, 1)
+#define CCGR_IPU_DI1_CLK __CCGR_NUM(6, 2)
+#define CCGR_GPU2D_CLK __CCGR_NUM(6, 3)
+#define CCGR_SLIMBUS_CLK __CCGR_NUM(6, 4)
+#define CCGR_SLIMBUS_SERIAL_CLK __CCGR_NUM(6, 5)
+
+#define CCGR_CLK_MODE_OFF 0
+#define CCGR_CLK_MODE_RUNMODE 1
+#define CCGR_CLK_MODE_ALWAYS 3
+
+#endif /* _IMX51_CCMREG_H */
+
Property changes on: trunk/sys/arm/freescale/imx/imx51_ccmreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_ccmvar.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_ccmvar.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_ccmvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,111 @@
+/* $MidnightBSD$ */
+/* $NetBSD: imx51_ccmvar.h,v 1.1 2012/04/17 09:33:31 bsh Exp $ */
+/*
+ * Copyright (c) 2012 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx51_ccmvar.h 250357 2013-05-08 09:42:50Z ray $
+ */
+
+#ifndef _ARM_IMX_IMX51_CCMVAR_H_
+#define _ARM_IMX_IMX51_CCMVAR_H_
+
+enum imx51_clock {
+ IMX51CLK_FPM,
+ IMX51CLK_PLL1,
+ IMX51CLK_PLL2,
+ IMX51CLK_PLL3,
+ IMX51CLK_PLL1SW,
+ IMX51CLK_PLL2SW,
+ IMX51CLK_PLL3SW,
+ IMX51CLK_PLL1STEP,
+ IMX51CLK_LP_APM,
+ IMX51CLK_ARM_ROOT,
+ IMX51CLK_MAIN_BUS_CLK_SRC, /* XXX */
+ IMX51CLK_MAIN_BUS_CLK,
+ IMX51CLK_EMI_SLOW_CLK_ROOT,
+ IMX51CLK_ENFC_CLK_ROOT,
+ IMX51CLK_AHB_CLK_ROOT,
+ IMX51CLK_IPG_CLK_ROOT,
+ IMX51CLK_PERCLK_ROOT,
+ IMX51CLK_DDR_CLK_ROOT,
+ IMX51CLK_ARM_AXI_CLK_ROOT,
+ IMX51CLK_ARM_AXI_A_CLK,
+ IMX51CLK_ARM_AXI_B_CLK,
+ IMX51CLK_IPU_HSP_CLK_ROOT,
+ IMX51CLK_CKIL_SYNC_CLK_ROOT,
+ IMX51CLK_USBOH3_CLK_ROOT,
+ IMX51CLK_ESDHC1_CLK_ROOT,
+ IMX51CLK_ESDHC2_CLK_ROOT,
+ IMX51CLK_ESDHC3_CLK_ROOT,
+ IMX51CLK_UART_CLK_ROOT,
+ IMX51CLK_SSI1_CLK_ROOT,
+ IMX51CLK_SSI2_CLK_ROOT,
+ IMX51CLK_SSI_EXT1_CLK_ROOT,
+ IMX51CLK_SSI_EXT2_CLK_ROOT,
+ IMX51CLK_USB_PHY_CLK_ROOT,
+ IMX51CLK_TVE_216_54_CLK_ROOT,
+ IMX51CLK_DI_CLK_ROOT,
+ IMX51CLK_SPDIF0_CLK_ROOT,
+ IMX51CLK_SPDIF1_CLK_ROOT,
+ IMX51CLK_CSPI_CLK_ROOT,
+ IMX51CLK_WRCK_CLK_ROOT,
+ IMX51CLK_LPSR_CLK_ROOT,
+ IMX51CLK_PGC_CLK_ROOT
+};
+
+u_int imx51_get_clock(enum imx51_clock);
+void imx51_clk_gating(int, int);
+int imx51_get_clk_gating(int);
+
+#endif /* _ARM_IMX_IMX51_CCMVAR_H_ */
Property changes on: trunk/sys/arm/freescale/imx/imx51_ccmvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_dpllreg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_dpllreg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_dpllreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,106 @@
+/* $MidnightBSD$ */
+/* $NetBSD: imx51_dpllreg.h,v 1.1 2012/04/17 09:33:31 bsh Exp $ */
+/*
+ * Copyright (c) 2012 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx51_dpllreg.h 250357 2013-05-08 09:42:50Z ray $
+ */
+
+#ifndef _IMX51_DPLLREG_H
+#define _IMX51_DPLLREG_H
+
+#include <sys/cdefs.h>
+
+/* register offset address */
+
+#define IMX51_N_DPLLS 3 /* 1..3 */
+
+#define DPLL_BASE(n) (0x83F80000 + (0x4000 * ((n)-1)))
+#define DPLL_SIZE 0x100
+
+#define DPLL_DP_CTL 0x0000 /* 0x1223 */
+#define DP_CTL_LRF 0x00000001
+#define DP_CTL_BRM 0x00000002
+#define DP_CTL_PLM 0x00000004
+#define DP_CTL_RCP 0x00000008
+#define DP_CTL_RST 0x00000010
+#define DP_CTL_UPEN 0x00000020
+#define DP_CTL_PRE 0x00000040
+#define DP_CTL_HFSM 0x00000080
+#define DP_CTL_REF_CLK_SEL_MASK 0x00000300
+#define DP_CTL_REF_CLK_SEL_COSC 0x00000200
+#define DP_CTL_REF_CLK_SEL_FPM 0x00000300
+#define DP_CTL_REF_CLK_DIV 0x00000400
+#define DP_CTL_DPDCK0_2_EN 0x00001000
+#define DP_CTL_HIGHCLK_EN DP_CTL_DPDCK0_2_EN
+#define DP_CTL_MULCTRL 0x00002000
+#define DPLL_DP_CONFIG 0x0004 /* 2 */
+#define DPLL_DP_CONFIG_APEN 0x00000002
+#define DPLL_DP_CONFIG_LDREQ 0x00000001
+#define DPLL_DP_OP 0x0008 /* 0x80 */
+#define DP_OP_PDF_SHIFT 0
+#define DP_OP_PDF_MASK (0xf << DP_OP_PDF_SHIFT)
+#define DP_OP_MFI_SHIFT 4
+#define DP_OP_MFI_MASK (0xf << DP_OP_MFI_SHIFT)
+#define DPLL_DP_MFD 0x000C /* 2 */
+#define DPLL_DP_MFN 0x0010 /* 1 */
+#define DPLL_DP_MFNMINUS 0x0014 /* 0 */
+#define DPLL_DP_MFNPLUS 0x0018 /* 0 */
+#define DPLL_DP_HFS_OP 0x001C /* 0x80 */
+#define DPLL_DP_HFS_MFD 0x0020 /* 2 */
+#define DPLL_DP_HFS_MFN 0x0024 /* 1 */
+#define DPLL_DP_TOGC 0x0028 /* 0x20000 */
+#define DPLL_DP_DESTAT 0x002C /* 1 */
+
+#endif /* _IMX51_DPLLREG_H */
Property changes on: trunk/sys/arm/freescale/imx/imx51_dpllreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_ipuv3.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_ipuv3.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_ipuv3.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,898 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx51_ipuv3.c 266365 2014-05-17 22:00:10Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/fdt.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#include <arm/freescale/imx/imx51_ccmvar.h>
+
+#include <arm/freescale/imx/imx51_ipuv3reg.h>
+
+#define IMX51_IPU_HSP_CLOCK 665000000
+#define IPU3FB_FONT_HEIGHT 16
+
+struct ipu3sc_softc {
+ device_t dev;
+ bus_addr_t pbase;
+ bus_addr_t vbase;
+
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ bus_space_handle_t cm_ioh;
+ bus_space_handle_t dp_ioh;
+ bus_space_handle_t di0_ioh;
+ bus_space_handle_t di1_ioh;
+ bus_space_handle_t dctmpl_ioh;
+ bus_space_handle_t dc_ioh;
+ bus_space_handle_t dmfc_ioh;
+ bus_space_handle_t idmac_ioh;
+ bus_space_handle_t cpmem_ioh;
+};
+
+struct video_adapter_softc {
+ /* Videoadpater part */
+ video_adapter_t va;
+
+ intptr_t fb_addr;
+ intptr_t fb_paddr;
+ unsigned int fb_size;
+
+ int bpp;
+ int depth;
+ unsigned int height;
+ unsigned int width;
+ unsigned int stride;
+
+ unsigned int xmargin;
+ unsigned int ymargin;
+
+ unsigned char *font;
+ int initialized;
+};
+
+static struct ipu3sc_softc *ipu3sc_softc;
+static struct video_adapter_softc va_softc;
+
+/* FIXME: not only 2 bytes color supported */
+static uint16_t colors[16] = {
+ 0x0000, /* black */
+ 0x001f, /* blue */
+ 0x07e0, /* green */
+ 0x07ff, /* cyan */
+ 0xf800, /* red */
+ 0xf81f, /* magenta */
+ 0x3800, /* brown */
+ 0xc618, /* light grey */
+ 0xc618, /* XXX: dark grey */
+ 0x001f, /* XXX: light blue */
+ 0x07e0, /* XXX: light green */
+ 0x07ff, /* XXX: light cyan */
+ 0xf800, /* XXX: light red */
+ 0xf81f, /* XXX: light magenta */
+ 0xffe0, /* yellow */
+ 0xffff, /* white */
+};
+static uint32_t colors_24[16] = {
+ 0x000000,/* Black */
+ 0x000080,/* Blue */
+ 0x008000,/* Green */
+ 0x008080,/* Cyan */
+ 0x800000,/* Red */
+ 0x800080,/* Magenta */
+ 0xcc6600,/* brown */
+ 0xC0C0C0,/* Silver */
+ 0x808080,/* Gray */
+ 0x0000FF,/* Light Blue */
+ 0x00FF00,/* Light Green */
+ 0x00FFFF,/* Light Cyan */
+ 0xFF0000,/* Light Red */
+ 0xFF00FF,/* Light Magenta */
+ 0xFFFF00,/* Yellow */
+ 0xFFFFFF,/* White */
+
+
+};
+
+#define IPUV3_READ(ipuv3, module, reg) \
+ bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg))
+#define IPUV3_WRITE(ipuv3, module, reg, val) \
+ bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val))
+
+#define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40)
+#define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20)
+#define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000)
+#define IMX_IPU_DP0 0
+#define IMX_IPU_DP1 1
+#define CPMEM_CHANNEL(_dp, _ch, _w) \
+ (CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \
+ CPMEM_WORD_OFFSET(_w))
+#define CPMEM_OFFSET(_dp, _ch, _w, _o) \
+ (CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o))
+
+#define IPUV3_DEBUG 100
+
+#ifdef IPUV3_DEBUG
+#define SUBMOD_DUMP_REG(_sc, _m, _l) \
+ { \
+ int i; \
+ printf("*** " #_m " ***\n"); \
+ for (i = 0; i <= (_l); i += 4) { \
+ if ((i % 32) == 0) \
+ printf("%04x: ", i & 0xffff); \
+ printf("0x%08x%c", IPUV3_READ((_sc), _m, i), \
+ ((i + 4) % 32)?' ':'\n'); \
+ } \
+ printf("\n"); \
+ }
+#endif
+
+#ifdef IPUV3_DEBUG
+int ipuv3_debug = IPUV3_DEBUG;
+#define DPRINTFN(n,x) if (ipuv3_debug>(n)) printf x; else
+#else
+#define DPRINTFN(n,x)
+#endif
+
+static int ipu3_fb_probe(device_t);
+static int ipu3_fb_attach(device_t);
+
+static int
+ipu3_fb_malloc(struct ipu3sc_softc *sc, size_t size)
+{
+
+ sc->vbase = (uint32_t)contigmalloc(size, M_DEVBUF, M_ZERO, 0, ~0,
+ PAGE_SIZE, 0);
+ sc->pbase = vtophys(sc->vbase);
+
+ return (0);
+}
+
+static void
+ipu3_fb_init(void *arg)
+{
+ struct ipu3sc_softc *sc = arg;
+ struct video_adapter_softc *va_sc = &va_softc;
+ uint64_t w0sh96;
+ uint32_t w1sh96;
+
+ /* FW W0[137:125] - 96 = [41:29] */
+ /* FH W0[149:138] - 96 = [53:42] */
+ w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16));
+ w0sh96 <<= 32;
+ w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12));
+
+ va_sc->width = ((w0sh96 >> 29) & 0x1fff) + 1;
+ va_sc->height = ((w0sh96 >> 42) & 0x0fff) + 1;
+
+ /* SLY W1[115:102] - 96 = [19:6] */
+ w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12));
+ va_sc->stride = ((w1sh96 >> 6) & 0x3fff) + 1;
+
+ printf("%dx%d [%d]\n", va_sc->width, va_sc->height, va_sc->stride);
+ va_sc->fb_size = va_sc->height * va_sc->stride;
+
+ ipu3_fb_malloc(sc, va_sc->fb_size);
+
+ /* DP1 + config_ch_23 + word_2 */
+ IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0),
+ ((sc->pbase >> 3) | ((sc->pbase >> 3) << 29)) & 0xffffffff);
+
+ IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4),
+ ((sc->pbase >> 3) >> 3) & 0xffffffff);
+
+ va_sc->fb_addr = (intptr_t)sc->vbase;
+ va_sc->fb_paddr = (intptr_t)sc->pbase;
+ va_sc->bpp = va_sc->stride / va_sc->width;
+ va_sc->depth = va_sc->bpp * 8;
+}
+
+static int
+ipu3_fb_probe(device_t dev)
+{
+ int error;
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,ipu3"))
+ return (ENXIO);
+
+ device_set_desc(dev, "i.MX5x Image Processing Unit v3 (FB)");
+
+ error = sc_probe_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD);
+
+ if (error != 0)
+ return (error);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ipu3_fb_attach(device_t dev)
+{
+ struct ipu3sc_softc *sc = device_get_softc(dev);
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ phandle_t node;
+ pcell_t reg;
+ int err;
+ uintptr_t base;
+
+ if (ipu3sc_softc)
+ return (ENXIO);
+
+ ipu3sc_softc = sc;
+
+ if (bootverbose)
+ device_printf(dev, "clock gate status is %d\n",
+ imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT));
+
+ sc->dev = dev;
+
+ err = (sc_attach_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD));
+
+ if (err) {
+ device_printf(dev, "failed to attach syscons\n");
+ goto fail;
+ }
+
+ sc = device_get_softc(dev);
+ sc->iot = iot = fdtbus_bs_tag;
+
+ /*
+ * Retrieve the device address based on the start address in the
+ * DTS. The DTS for i.MX51 specifies 0x5e000000 as the first register
+ * address, so we just subtract IPU_CM_BASE to get the offset at which
+ * the IPU device was memory mapped.
+ * On i.MX53, the offset is 0.
+ */
+ node = ofw_bus_get_node(dev);
+ if ((OF_getprop(node, "reg", ®, sizeof(reg))) <= 0)
+ base = 0;
+ else
+ base = fdt32_to_cpu(reg) - IPU_CM_BASE(0);
+ /* map controller registers */
+ err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_cm;
+ sc->cm_ioh = ioh;
+
+ /* map Display Multi FIFO Controller registers */
+ err = bus_space_map(iot, IPU_DMFC_BASE(base), IPU_DMFC_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dmfc;
+ sc->dmfc_ioh = ioh;
+
+ /* map Display Interface 0 registers */
+ err = bus_space_map(iot, IPU_DI0_BASE(base), IPU_DI0_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_di0;
+ sc->di0_ioh = ioh;
+
+ /* map Display Interface 1 registers */
+ err = bus_space_map(iot, IPU_DI1_BASE(base), IPU_DI0_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_di1;
+ sc->di1_ioh = ioh;
+
+ /* map Display Processor registers */
+ err = bus_space_map(iot, IPU_DP_BASE(base), IPU_DP_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dp;
+ sc->dp_ioh = ioh;
+
+ /* map Display Controller registers */
+ err = bus_space_map(iot, IPU_DC_BASE(base), IPU_DC_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dc;
+ sc->dc_ioh = ioh;
+
+ /* map Image DMA Controller registers */
+ err = bus_space_map(iot, IPU_IDMAC_BASE(base), IPU_IDMAC_SIZE, 0,
+ &ioh);
+ if (err)
+ goto fail_retarn_idmac;
+ sc->idmac_ioh = ioh;
+
+ /* map CPMEM registers */
+ err = bus_space_map(iot, IPU_CPMEM_BASE(base), IPU_CPMEM_SIZE, 0,
+ &ioh);
+ if (err)
+ goto fail_retarn_cpmem;
+ sc->cpmem_ioh = ioh;
+
+ /* map DCTEMPL registers */
+ err = bus_space_map(iot, IPU_DCTMPL_BASE(base), IPU_DCTMPL_SIZE, 0,
+ &ioh);
+ if (err)
+ goto fail_retarn_dctmpl;
+ sc->dctmpl_ioh = ioh;
+
+#ifdef notyet
+ sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO,
+ ipuv3intr, sc);
+ if (sc->ih == NULL) {
+ device_printf(sc->dev,
+ "unable to establish interrupt at irq %d\n",
+ IMX51_INT_IPUV3);
+ return (ENXIO);
+ }
+#endif
+
+ /*
+ * We have to wait until interrupts are enabled.
+ * Mailbox relies on it to get data from VideoCore
+ */
+ ipu3_fb_init(sc);
+
+ return (0);
+
+fail:
+ return (ENXIO);
+fail_retarn_dctmpl:
+ bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE);
+fail_retarn_cpmem:
+ bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE);
+fail_retarn_idmac:
+ bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE);
+fail_retarn_dp:
+ bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE);
+fail_retarn_dc:
+ bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE);
+fail_retarn_di1:
+ bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE);
+fail_retarn_di0:
+ bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE);
+fail_retarn_dmfc:
+ bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE);
+fail_retarn_cm:
+ device_printf(sc->dev,
+ "failed to map registers (errno=%d)\n", err);
+ return (err);
+}
+
+static device_method_t ipu3_fb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ipu3_fb_probe),
+ DEVMETHOD(device_attach, ipu3_fb_attach),
+
+ { 0, 0 }
+};
+
+static devclass_t ipu3_fb_devclass;
+
+static driver_t ipu3_fb_driver = {
+ "fb",
+ ipu3_fb_methods,
+ sizeof(struct ipu3sc_softc),
+};
+
+DRIVER_MODULE(ipu3fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0);
+
+/*
+ * Video driver routines and glue.
+ */
+static int ipu3fb_configure(int);
+static vi_probe_t ipu3fb_probe;
+static vi_init_t ipu3fb_init;
+static vi_get_info_t ipu3fb_get_info;
+static vi_query_mode_t ipu3fb_query_mode;
+static vi_set_mode_t ipu3fb_set_mode;
+static vi_save_font_t ipu3fb_save_font;
+static vi_load_font_t ipu3fb_load_font;
+static vi_show_font_t ipu3fb_show_font;
+static vi_save_palette_t ipu3fb_save_palette;
+static vi_load_palette_t ipu3fb_load_palette;
+static vi_set_border_t ipu3fb_set_border;
+static vi_save_state_t ipu3fb_save_state;
+static vi_load_state_t ipu3fb_load_state;
+static vi_set_win_org_t ipu3fb_set_win_org;
+static vi_read_hw_cursor_t ipu3fb_read_hw_cursor;
+static vi_set_hw_cursor_t ipu3fb_set_hw_cursor;
+static vi_set_hw_cursor_shape_t ipu3fb_set_hw_cursor_shape;
+static vi_blank_display_t ipu3fb_blank_display;
+static vi_mmap_t ipu3fb_mmap;
+static vi_ioctl_t ipu3fb_ioctl;
+static vi_clear_t ipu3fb_clear;
+static vi_fill_rect_t ipu3fb_fill_rect;
+static vi_bitblt_t ipu3fb_bitblt;
+static vi_diag_t ipu3fb_diag;
+static vi_save_cursor_palette_t ipu3fb_save_cursor_palette;
+static vi_load_cursor_palette_t ipu3fb_load_cursor_palette;
+static vi_copy_t ipu3fb_copy;
+static vi_putp_t ipu3fb_putp;
+static vi_putc_t ipu3fb_putc;
+static vi_puts_t ipu3fb_puts;
+static vi_putm_t ipu3fb_putm;
+
+static video_switch_t ipu3fbvidsw = {
+ .probe = ipu3fb_probe,
+ .init = ipu3fb_init,
+ .get_info = ipu3fb_get_info,
+ .query_mode = ipu3fb_query_mode,
+ .set_mode = ipu3fb_set_mode,
+ .save_font = ipu3fb_save_font,
+ .load_font = ipu3fb_load_font,
+ .show_font = ipu3fb_show_font,
+ .save_palette = ipu3fb_save_palette,
+ .load_palette = ipu3fb_load_palette,
+ .set_border = ipu3fb_set_border,
+ .save_state = ipu3fb_save_state,
+ .load_state = ipu3fb_load_state,
+ .set_win_org = ipu3fb_set_win_org,
+ .read_hw_cursor = ipu3fb_read_hw_cursor,
+ .set_hw_cursor = ipu3fb_set_hw_cursor,
+ .set_hw_cursor_shape = ipu3fb_set_hw_cursor_shape,
+ .blank_display = ipu3fb_blank_display,
+ .mmap = ipu3fb_mmap,
+ .ioctl = ipu3fb_ioctl,
+ .clear = ipu3fb_clear,
+ .fill_rect = ipu3fb_fill_rect,
+ .bitblt = ipu3fb_bitblt,
+ .diag = ipu3fb_diag,
+ .save_cursor_palette = ipu3fb_save_cursor_palette,
+ .load_cursor_palette = ipu3fb_load_cursor_palette,
+ .copy = ipu3fb_copy,
+ .putp = ipu3fb_putp,
+ .putc = ipu3fb_putc,
+ .puts = ipu3fb_puts,
+ .putm = ipu3fb_putm,
+};
+
+VIDEO_DRIVER(ipu3fb, ipu3fbvidsw, ipu3fb_configure);
+
+extern sc_rndr_sw_t txtrndrsw;
+RENDERER(ipu3fb, 0, txtrndrsw, gfb_set);
+RENDERER_MODULE(ipu3fb, gfb_set);
+
+static uint16_t ipu3fb_static_window[ROW*COL];
+extern u_char dflt_font_16[];
+
+static int
+ipu3fb_configure(int flags)
+{
+ struct video_adapter_softc *sc;
+
+ sc = &va_softc;
+
+ if (sc->initialized)
+ return 0;
+
+ sc->width = 640;
+ sc->height = 480;
+ sc->bpp = 2;
+ sc->stride = sc->width * sc->bpp;
+
+ ipu3fb_init(0, &sc->va, 0);
+
+ sc->initialized = 1;
+
+ return (0);
+}
+
+static int
+ipu3fb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_init(int unit, video_adapter_t *adp, int flags)
+{
+ struct video_adapter_softc *sc;
+ video_info_t *vi;
+
+ sc = (struct video_adapter_softc *)adp;
+ vi = &adp->va_info;
+
+ vid_init_struct(adp, "ipu3fb", -1, unit);
+
+ sc->font = dflt_font_16;
+ vi->vi_cheight = IPU3FB_FONT_HEIGHT;
+ vi->vi_cwidth = 8;
+ vi->vi_width = sc->width/8;
+ vi->vi_height = sc->height/vi->vi_cheight;
+
+ /*
+ * Clamp width/height to syscons maximums
+ */
+ if (vi->vi_width > COL)
+ vi->vi_width = COL;
+ if (vi->vi_height > ROW)
+ vi->vi_height = ROW;
+
+ sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
+
+ adp->va_window = (vm_offset_t) ipu3fb_static_window;
+ adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
+ adp->va_line_width = sc->stride;
+ adp->va_buffer_size = sc->fb_size;
+
+ vid_register(&sc->va);
+
+ return (0);
+}
+
+static int
+ipu3fb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
+{
+
+ bcopy(&adp->va_info, info, sizeof(*info));
+ return (0);
+}
+
+static int
+ipu3fb_query_mode(video_adapter_t *adp, video_info_t *info)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_set_mode(video_adapter_t *adp, int mode)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_save_font(video_adapter_t *adp, int page, int size, int width,
+ u_char *data, int c, int count)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_load_font(video_adapter_t *adp, int page, int size, int width,
+ u_char *data, int c, int count)
+{
+ struct video_adapter_softc *sc;
+
+ sc = (struct video_adapter_softc *)adp;
+ sc->font = data;
+
+ return (0);
+}
+
+static int
+ipu3fb_show_font(video_adapter_t *adp, int page)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_save_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_load_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_set_border(video_adapter_t *adp, int border)
+{
+
+ return (ipu3fb_blank_display(adp, border));
+}
+
+static int
+ipu3fb_save_state(video_adapter_t *adp, void *p, size_t size)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_load_state(video_adapter_t *adp, void *p)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_set_win_org(video_adapter_t *adp, off_t offset)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
+{
+
+ *col = *row = 0;
+ return (0);
+}
+
+static int
+ipu3fb_set_hw_cursor(video_adapter_t *adp, int col, int row)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
+ int celsize, int blink)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_blank_display(video_adapter_t *adp, int mode)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int prot, vm_memattr_t *memattr)
+{
+ struct video_adapter_softc *sc;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ /*
+ * This might be a legacy VGA mem request: if so, just point it at the
+ * framebuffer, since it shouldn't be touched
+ */
+ if (offset < sc->stride * sc->height) {
+ *paddr = sc->fb_paddr + offset;
+ return (0);
+ }
+
+ return (EINVAL);
+}
+
+static int
+ipu3fb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
+{
+ struct video_adapter_softc *sc;
+ struct fbtype *fb;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ switch (cmd) {
+ case FBIOGTYPE:
+ fb = (struct fbtype *)data;
+ fb->fb_type = FBTYPE_PCIMISC;
+ fb->fb_height = sc->height;
+ fb->fb_width = sc->width;
+ fb->fb_depth = sc->depth;
+ if (sc->depth <= 1 || sc->depth > 8)
+ fb->fb_cmsize = 0;
+ else
+ fb->fb_cmsize = 1 << sc->depth;
+ fb->fb_size = sc->fb_size;
+ break;
+ case FBIOSCURSOR:
+ return (ENODEV);
+ default:
+ return (fb_commonioctl(adp, cmd, data));
+ }
+
+ return (0);
+}
+
+static int
+ipu3fb_clear(video_adapter_t *adp)
+{
+
+ return (ipu3fb_blank_display(adp, 0));
+}
+
+static int
+ipu3fb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_bitblt(video_adapter_t *adp, ...)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_diag(video_adapter_t *adp, int level)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
+ int size, int bpp, int bit_ltor, int byte_ltor)
+{
+
+ return (0);
+}
+
+static int
+ipu3fb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+{
+ struct video_adapter_softc *sc;
+ int col, row, bpp;
+ int b, i, j, k;
+ uint8_t *addr;
+ u_char *p;
+ uint32_t fg, bg, color;
+
+ sc = (struct video_adapter_softc *)adp;
+ bpp = sc->bpp;
+
+ if (sc->fb_addr == 0)
+ return (0);
+ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+ col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+ p = sc->font + c * IPU3FB_FONT_HEIGHT;
+ addr = (uint8_t *)sc->fb_addr
+ + (row + sc->ymargin) * (sc->stride)
+ + bpp * (col + sc->xmargin);
+
+ if (bpp == 2) {
+ bg = colors[(a >> 4) & 0x0f];
+ fg = colors[a & 0x0f];
+ } else if (bpp == 3) {
+ bg = colors_24[(a >> 4) & 0x0f];
+ fg = colors_24[a & 0x0f];
+ } else {
+ return (ENXIO);
+ }
+
+ for (i = 0; i < IPU3FB_FONT_HEIGHT; i++) {
+ for (j = 0, k = 7; j < 8; j++, k--) {
+ if ((p[i] & (1 << k)) == 0)
+ color = bg;
+ else
+ color = fg;
+ /* FIXME: BPP maybe different */
+ for (b = 0; b < bpp; b ++)
+ addr[bpp * j + b] =
+ (color >> (b << 3)) & 0xff;
+ }
+
+ addr += (sc->stride);
+ }
+
+ return (0);
+}
+
+static int
+ipu3fb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ ipu3fb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
+
+ return (0);
+}
+
+static int
+ipu3fb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+ uint32_t pixel_mask, int size, int width)
+{
+
+ return (0);
+}
+
+/*
+ * Define a stub keyboard driver in case one hasn't been
+ * compiled into the kernel
+ */
+#include <sys/kbio.h>
+#include <dev/kbd/kbdreg.h>
+
+static int dummy_kbd_configure(int flags);
+
+keyboard_switch_t ipu3dummysw;
+
+static int
+dummy_kbd_configure(int flags)
+{
+
+ return (0);
+}
+KEYBOARD_DRIVER(ipu3dummy, ipu3dummysw, dummy_kbd_configure);
Property changes on: trunk/sys/arm/freescale/imx/imx51_ipuv3.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_ipuv3_fbd.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_ipuv3_fbd.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_ipuv3_fbd.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,367 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx51_ipuv3_fbd.c 270262 2014-08-21 10:18:42Z dumbbell $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+#include <sys/eventhandler.h>
+
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/fdt.h>
+#include <machine/resource.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/vt/vt.h>
+#include <dev/vt/colors/vt_termcolors.h>
+
+#include <arm/freescale/imx/imx51_ccmvar.h>
+
+#include <arm/freescale/imx/imx51_ipuv3reg.h>
+
+#include "fb_if.h"
+
+#define IMX51_IPU_HSP_CLOCK 665000000
+
+struct ipu3sc_softc {
+ device_t dev;
+ device_t sc_fbd; /* fbd child */
+ struct fb_info sc_info;
+
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ bus_space_handle_t cm_ioh;
+ bus_space_handle_t dp_ioh;
+ bus_space_handle_t di0_ioh;
+ bus_space_handle_t di1_ioh;
+ bus_space_handle_t dctmpl_ioh;
+ bus_space_handle_t dc_ioh;
+ bus_space_handle_t dmfc_ioh;
+ bus_space_handle_t idmac_ioh;
+ bus_space_handle_t cpmem_ioh;
+};
+
+static struct ipu3sc_softc *ipu3sc_softc;
+
+#define IPUV3_READ(ipuv3, module, reg) \
+ bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg))
+#define IPUV3_WRITE(ipuv3, module, reg, val) \
+ bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val))
+
+#define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40)
+#define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20)
+#define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000)
+#define IMX_IPU_DP0 0
+#define IMX_IPU_DP1 1
+#define CPMEM_CHANNEL(_dp, _ch, _w) \
+ (CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \
+ CPMEM_WORD_OFFSET(_w))
+#define CPMEM_OFFSET(_dp, _ch, _w, _o) \
+ (CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o))
+
+static int ipu3_fb_probe(device_t);
+static int ipu3_fb_attach(device_t);
+
+static void
+ipu3_fb_init(struct ipu3sc_softc *sc)
+{
+ uint64_t w0sh96;
+ uint32_t w1sh96;
+
+ /* FW W0[137:125] - 96 = [41:29] */
+ /* FH W0[149:138] - 96 = [53:42] */
+ w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16));
+ w0sh96 <<= 32;
+ w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12));
+
+ sc->sc_info.fb_width = ((w0sh96 >> 29) & 0x1fff) + 1;
+ sc->sc_info.fb_height = ((w0sh96 >> 42) & 0x0fff) + 1;
+
+ /* SLY W1[115:102] - 96 = [19:6] */
+ w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12));
+ sc->sc_info.fb_stride = ((w1sh96 >> 6) & 0x3fff) + 1;
+
+ printf("%dx%d [%d]\n", sc->sc_info.fb_width, sc->sc_info.fb_height,
+ sc->sc_info.fb_stride);
+ sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride;
+
+ sc->sc_info.fb_vbase = (intptr_t)contigmalloc(sc->sc_info.fb_size,
+ M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0);
+ sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase);
+
+ /* DP1 + config_ch_23 + word_2 */
+ IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0),
+ (((uint32_t)sc->sc_info.fb_pbase >> 3) |
+ (((uint32_t)sc->sc_info.fb_pbase >> 3) << 29)) & 0xffffffff);
+
+ IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4),
+ (((uint32_t)sc->sc_info.fb_pbase >> 3) >> 3) & 0xffffffff);
+
+ /* XXX: fetch or set it from/to IPU. */
+ sc->sc_info.fb_bpp = sc->sc_info.fb_depth = sc->sc_info.fb_stride /
+ sc->sc_info.fb_width * 8;
+}
+
+/* Use own color map, because of different RGB offset. */
+static int
+ipu3_fb_init_cmap(uint32_t *cmap, int bytespp)
+{
+
+ switch (bytespp) {
+ case 8:
+ return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
+ 0x7, 5, 0x7, 2, 0x3, 0));
+ case 15:
+ return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
+ 0x1f, 10, 0x1f, 5, 0x1f, 0));
+ case 16:
+ return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
+ 0x1f, 11, 0x3f, 5, 0x1f, 0));
+ case 24:
+ case 32: /* Ignore alpha. */
+ return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
+ 0xff, 0, 0xff, 8, 0xff, 16));
+ default:
+ return (1);
+ }
+}
+
+static int
+ipu3_fb_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,ipu3"))
+ return (ENXIO);
+
+ device_set_desc(dev, "i.MX5x Image Processing Unit v3 (FB)");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ipu3_fb_attach(device_t dev)
+{
+ struct ipu3sc_softc *sc = device_get_softc(dev);
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ phandle_t node;
+ pcell_t reg;
+ int err;
+ uintptr_t base;
+
+ ipu3sc_softc = sc;
+
+ if (bootverbose)
+ device_printf(dev, "clock gate status is %d\n",
+ imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT));
+
+ sc->dev = dev;
+
+ sc = device_get_softc(dev);
+ sc->iot = iot = fdtbus_bs_tag;
+
+ /*
+ * Retrieve the device address based on the start address in the
+ * DTS. The DTS for i.MX51 specifies 0x5e000000 as the first register
+ * address, so we just subtract IPU_CM_BASE to get the offset at which
+ * the IPU device was memory mapped.
+ * On i.MX53, the offset is 0.
+ */
+ node = ofw_bus_get_node(dev);
+ if ((OF_getprop(node, "reg", ®, sizeof(reg))) <= 0)
+ base = 0;
+ else
+ base = fdt32_to_cpu(reg) - IPU_CM_BASE(0);
+ /* map controller registers */
+ err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_cm;
+ sc->cm_ioh = ioh;
+
+ /* map Display Multi FIFO Controller registers */
+ err = bus_space_map(iot, IPU_DMFC_BASE(base), IPU_DMFC_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dmfc;
+ sc->dmfc_ioh = ioh;
+
+ /* map Display Interface 0 registers */
+ err = bus_space_map(iot, IPU_DI0_BASE(base), IPU_DI0_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_di0;
+ sc->di0_ioh = ioh;
+
+ /* map Display Interface 1 registers */
+ err = bus_space_map(iot, IPU_DI1_BASE(base), IPU_DI0_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_di1;
+ sc->di1_ioh = ioh;
+
+ /* map Display Processor registers */
+ err = bus_space_map(iot, IPU_DP_BASE(base), IPU_DP_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dp;
+ sc->dp_ioh = ioh;
+
+ /* map Display Controller registers */
+ err = bus_space_map(iot, IPU_DC_BASE(base), IPU_DC_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dc;
+ sc->dc_ioh = ioh;
+
+ /* map Image DMA Controller registers */
+ err = bus_space_map(iot, IPU_IDMAC_BASE(base), IPU_IDMAC_SIZE, 0,
+ &ioh);
+ if (err)
+ goto fail_retarn_idmac;
+ sc->idmac_ioh = ioh;
+
+ /* map CPMEM registers */
+ err = bus_space_map(iot, IPU_CPMEM_BASE(base), IPU_CPMEM_SIZE, 0,
+ &ioh);
+ if (err)
+ goto fail_retarn_cpmem;
+ sc->cpmem_ioh = ioh;
+
+ /* map DCTEMPL registers */
+ err = bus_space_map(iot, IPU_DCTMPL_BASE(base), IPU_DCTMPL_SIZE, 0,
+ &ioh);
+ if (err)
+ goto fail_retarn_dctmpl;
+ sc->dctmpl_ioh = ioh;
+
+#ifdef notyet
+ sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO,
+ ipuv3intr, sc);
+ if (sc->ih == NULL) {
+ device_printf(sc->dev,
+ "unable to establish interrupt at irq %d\n",
+ IMX51_INT_IPUV3);
+ return (ENXIO);
+ }
+#endif
+
+ /*
+ * We have to wait until interrupts are enabled.
+ * Mailbox relies on it to get data from VideoCore
+ */
+ ipu3_fb_init(sc);
+
+ sc->sc_info.fb_name = device_get_nameunit(dev);
+
+ ipu3_fb_init_cmap(sc->sc_info.fb_cmap, sc->sc_info.fb_depth);
+ sc->sc_info.fb_cmsize = 16;
+
+ /* Ask newbus to attach framebuffer device to me. */
+ sc->sc_fbd = device_add_child(dev, "fbd", device_get_unit(dev));
+ if (sc->sc_fbd == NULL)
+ device_printf(dev, "Can't attach fbd device\n");
+
+ return (bus_generic_attach(dev));
+
+fail_retarn_dctmpl:
+ bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE);
+fail_retarn_cpmem:
+ bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE);
+fail_retarn_idmac:
+ bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE);
+fail_retarn_dp:
+ bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE);
+fail_retarn_dc:
+ bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE);
+fail_retarn_di1:
+ bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE);
+fail_retarn_di0:
+ bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE);
+fail_retarn_dmfc:
+ bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE);
+fail_retarn_cm:
+ device_printf(sc->dev,
+ "failed to map registers (errno=%d)\n", err);
+ return (err);
+}
+
+static struct fb_info *
+ipu3_fb_getinfo(device_t dev)
+{
+ struct ipu3sc_softc *sc = device_get_softc(dev);
+
+ return (&sc->sc_info);
+}
+
+static device_method_t ipu3_fb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ipu3_fb_probe),
+ DEVMETHOD(device_attach, ipu3_fb_attach),
+
+ /* Framebuffer service methods */
+ DEVMETHOD(fb_getinfo, ipu3_fb_getinfo),
+ { 0, 0 }
+};
+
+static devclass_t ipu3_fb_devclass;
+
+static driver_t ipu3_fb_driver = {
+ "fb",
+ ipu3_fb_methods,
+ sizeof(struct ipu3sc_softc),
+};
+
+DRIVER_MODULE(fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/imx/imx51_ipuv3_fbd.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_ipuv3reg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_ipuv3reg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_ipuv3reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,923 @@
+/* $MidnightBSD$ */
+/* $NetBSD: imx51_ipuv3reg.h,v 1.1 2012/04/17 10:19:57 bsh Exp $ */
+/*
+ * Copyright (c) 2011, 2012 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx51_ipuv3reg.h 266365 2014-05-17 22:00:10Z ian $
+ */
+
+#ifndef _ARM_IMX_IMX51_IPUV3REG_H
+#define _ARM_IMX_IMX51_IPUV3REG_H
+
+/* register offset address */
+
+/*
+ * CM
+ * Control Module
+ */
+#define IPU_CM_CONF 0x00000000
+#define CM_CONF_CSI_SEL 0x80000000
+#define CM_CONF_IC_INPUT 0x40000000
+#define CM_CONF_CSI1_DATA_SOURCE 0x20000000
+#define CM_CONF_CSI0_DATA_SOURCE 0x10000000
+#define CM_CONF_VDI_DMFC_SYNC 0x08000000
+#define CM_CONF_IC_DMFC_SYNC 0x04000000
+#define CM_CONF_IC_DMFC_SEL 0x02000000
+#define CM_CONF_ISP_DOUBLE_FLOW 0x01000000
+#define CM_CONF_IDMAC_DISABLE 0x00400000
+#define CM_CONF_IPU_DIAGBUS_ON 0x00200000
+#define CM_CONF_IPU_DIAGBUS_MODE 0x001f0000
+#define CM_CONF_VDI_EN 0x00001000
+#define CM_CONF_SISG_EN 0x00000800
+#define CM_CONF_DMFC_EN 0x00000400
+#define CM_CONF_DC_EN 0x00000200
+#define CM_CONF_SMFC_EN 0x00000100
+#define CM_CONF_DI1_EN 0x00000080
+#define CM_CONF_DI0_EN 0x00000040
+#define CM_CONF_DP_EN 0x00000020
+#define CM_CONF_ISP_EN 0x00000010
+#define CM_CONF_IRT_EN 0x00000008
+#define CM_CONF_IC_EN 0x00000004
+#define CM_CONF_CSI1_EN 0x00000002
+#define CM_CONF_CSI0_EN 0x00000001
+#define IPU_SISG_CTRL0 0x00000004
+#define IPU_SISG_CTRL1 0x00000008
+#define IPU_CM_INT_CTRL_1 0x0000003c
+#define IPU_CM_INT_CTRL_2 0x00000040
+#define IPU_CM_INT_CTRL_3 0x00000044
+#define IPU_CM_INT_CTRL_4 0x00000048
+#define IPU_CM_INT_CTRL_5 0x0000004c
+#define IPU_CM_INT_CTRL_6 0x00000050
+#define IPU_CM_INT_CTRL_7 0x00000054
+#define IPU_CM_INT_CTRL_8 0x00000058
+#define IPU_CM_INT_CTRL_9 0x0000005c
+#define IPU_CM_INT_CTRL_10 0x00000060
+#define IPU_CM_INT_CTRL_11 0x00000064
+#define IPU_CM_INT_CTRL_12 0x00000068
+#define IPU_CM_INT_CTRL_13 0x0000006c
+#define IPU_CM_INT_CTRL_14 0x00000070
+#define IPU_CM_INT_CTRL_15 0x00000074
+#define IPU_CM_SDMA_EVENT_1 0x00000078
+#define IPU_CM_SDMA_EVENT_2 0x0000007c
+#define IPU_CM_SDMA_EVENT_3 0x00000080
+#define IPU_CM_SDMA_EVENT_4 0x00000084
+#define IPU_CM_SDMA_EVENT_7 0x00000088
+#define IPU_CM_SDMA_EVENT_8 0x0000008c
+#define IPU_CM_SDMA_EVENT_11 0x00000090
+#define IPU_CM_SDMA_EVENT_12 0x00000094
+#define IPU_CM_SDMA_EVENT_13 0x00000098
+#define IPU_CM_SDMA_EVENT_14 0x0000009c
+#define IPU_CM_SRM_PRI1 0x000000a0
+#define IPU_CM_SRM_PRI2 0x000000a4
+#define IPU_CM_FS_PROC_FLOW1 0x000000a8
+#define IPU_CM_FS_PROC_FLOW2 0x000000ac
+#define IPU_CM_FS_PROC_FLOW3 0x000000b0
+#define IPU_CM_FS_DISP_FLOW1 0x000000b4
+#define IPU_CM_FS_DISP_FLOW2 0x000000b8
+#define IPU_CM_SKIP 0x000000bc
+#define IPU_CM_DISP_ALT_CONF 0x000000c0
+#define IPU_CM_DISP_GEN 0x000000c4
+#define CM_DISP_GEN_DI0_COUNTER_RELEASE 0x01000000
+#define CM_DISP_GEN_DI1_COUNTER_RELEASE 0x00800000
+#define CM_DISP_GEN_MCU_MAX_BURST_STOP 0x00400000
+#define CM_DISP_GEN_MCU_T_SHIFT 18
+#define CM_DISP_GEN_MCU_T(n) ((n) << CM_DISP_GEN_MCU_T_SHIFT)
+#define IPU_CM_DISP_ALT1 0x000000c8
+#define IPU_CM_DISP_ALT2 0x000000cc
+#define IPU_CM_DISP_ALT3 0x000000d0
+#define IPU_CM_DISP_ALT4 0x000000d4
+#define IPU_CM_SNOOP 0x000000d8
+#define IPU_CM_MEM_RST 0x000000dc
+#define CM_MEM_START 0x80000000
+#define CM_MEM_EN 0x007fffff
+#define IPU_CM_PM 0x000000e0
+#define IPU_CM_GPR 0x000000e4
+#define CM_GPR_IPU_CH_BUF1_RDY1_CLR 0x80000000
+#define CM_GPR_IPU_CH_BUF1_RDY0_CLR 0x40000000
+#define CM_GPR_IPU_CH_BUF0_RDY1_CLR 0x20000000
+#define CM_GPR_IPU_CH_BUF0_RDY0_CLR 0x10000000
+#define CM_GPR_IPU_ALT_CH_BUF1_RDY1_CLR 0x08000000
+#define CM_GPR_IPU_ALT_CH_BUF1_RDY0_CLR 0x04000000
+#define CM_GPR_IPU_ALT_CH_BUF0_RDY1_CLR 0x02000000
+#define CM_GPR_IPU_ALT_CH_BUF0_RDY0_CLR 0x01000000
+#define CM_GPR_IPU_DI1_CLK_CHANGE_ACK_DIS 0x00800000
+#define CM_GPR_IPU_DI0_CLK_CHANGE_ACK_DIS 0x00400000
+#define CM_GPR_IPU_CH_BUF2_RDY1_CLR 0x00200000
+#define CM_GPR_IPU_CH_BUF2_RDY0_CLR 0x00100000
+#define CM_GPR_IPU_GP(n) __BIT((n))
+#define IPU_CM_CH_DB_MODE_SEL_0 0x00000150
+#define IPU_CM_CH_DB_MODE_SEL_1 0x00000154
+#define IPU_CM_ALT_CH_DB_MODE_SEL_0 0x00000168
+#define IPU_CM_ALT_CH_DB_MODE_SEL_1 0x0000016c
+#define IPU_CM_CH_TRB_MODE_SEL_0 0x00000178
+#define IPU_CM_CH_TRB_MODE_SEL_1 0x0000017c
+#define IPU_CM_INT_STAT_1 0x00000200
+#define IPU_CM_INT_STAT_2 0x00000204
+#define IPU_CM_INT_STAT_3 0x00000208
+#define IPU_CM_INT_STAT_4 0x0000020c
+#define IPU_CM_INT_STAT_5 0x00000210
+#define IPU_CM_INT_STAT_6 0x00000214
+#define IPU_CM_INT_STAT_7 0x00000218
+#define IPU_CM_INT_STAT_8 0x0000021c
+#define IPU_CM_INT_STAT_9 0x00000220
+#define IPU_CM_INT_STAT_10 0x00000224
+#define IPU_CM_INT_STAT_11 0x00000228
+#define IPU_CM_INT_STAT_12 0x0000022c
+#define IPU_CM_INT_STAT_13 0x00000230
+#define IPU_CM_INT_STAT_14 0x00000234
+#define IPU_CM_INT_STAT_15 0x00000238
+#define IPU_CM_CUR_BUF_0 0x0000023c
+#define IPU_CM_CUR_BUF_1 0x00000240
+#define IPU_CM_ALT_CUR_BUF_0 0x00000244
+#define IPU_CM_ALT_CUR_BUF_1 0x00000248
+#define IPU_CM_SRM_STAT 0x0000024c
+#define IPU_CM_PROC_TASKS_STAT 0x00000250
+#define IPU_CM_DISP_TASKS_STAT 0x00000254
+#define IPU_CM_TRIPLE_CUR_BUF_0 0x00000258
+#define IPU_CM_TRIPLE_CUR_BUF_1 0x0000025c
+#define IPU_CM_TRIPLE_CUR_BUF_2 0x00000260
+#define IPU_CM_TRIPLE_CUR_BUF_3 0x00000264
+#define IPU_CM_CH_BUF0_RDY0 0x00000268
+#define IPU_CM_CH_BUF0_RDY1 0x0000026c
+#define IPU_CM_CH_BUF1_RDY0 0x00000270
+#define IPU_CM_CH_BUF1_RDY1 0x00000274
+#define IPU_CM_ALT_CH_BUF0_RDY0 0x00000278
+#define IPU_CM_ALT_CH_BUF0_RDY1 0x0000027c
+#define IPU_CM_ALT_CH_BUF1_RDY0 0x00000280
+#define IPU_CM_ALT_CH_BUF1_RDY1 0x00000284
+#define IPU_CM_CH_BUF2_RDY0 0x00000288
+#define IPU_CM_CH_BUF2_RDY1 0x0000028c
+
+/*
+ * IDMAC
+ * Image DMA Controller
+ */
+#define IPU_IDMAC_CONF 0x00000000
+#define IPU_IDMAC_CH_EN_1 0x00000004
+#define IPU_IDMAC_CH_EN_2 0x00000008
+#define IPU_IDMAC_SEP_ALPHA 0x0000000c
+#define IPU_IDMAC_ALT_SEP_ALPHA 0x00000010
+#define IPU_IDMAC_CH_PRI_1 0x00000014
+#define IPU_IDMAC_CH_PRI_2 0x00000018
+#define IPU_IDMAC_WM_EN_1 0x0000001c
+#define IPU_IDMAC_WM_EN_2 0x00000020
+#define IPU_IDMAC_LOCK_EN_1 0x00000024
+#define IPU_IDMAC_LOCK_EN_2 0x00000028
+#define IPU_IDMAC_SUB_ADDR_0 0x0000002c
+#define IPU_IDMAC_SUB_ADDR_1 0x00000030
+#define IPU_IDMAC_SUB_ADDR_2 0x00000034
+#define IPU_IDMAC_SUB_ADDR_3 0x00000038
+#define IPU_IDMAC_SUB_ADDR_4 0x0000003c
+#define IPU_IDMAC_BNDM_EN_1 0x00000040
+#define IPU_IDMAC_BNDM_EN_2 0x00000044
+#define IPU_IDMAC_SC_CORD 0x00000048
+#define IPU_IDMAC_SC_CORD1 0x0000004c
+#define IPU_IDMAC_CH_BUSY_1 0x00000100
+#define IPU_IDMAC_CH_BUSY_2 0x00000104
+
+#define CH_PANNEL_BG 23
+#define CH_PANNEL_FG 27
+
+/*
+ * DP
+ * Display Port
+ */
+#define IPU_DP_DEBUG_CNT 0x000000bc
+#define IPU_DP_DEBUG_STAT 0x000000c0
+
+/*
+ * IC
+ * Image Converter
+ */
+#define IPU_IC_CONF 0x00000000
+#define IPU_IC_PRP_ENC_RSC 0x00000004
+#define IPU_IC_PRP_VF_RSC 0x00000008
+#define IPU_IC_PP_RSC 0x0000000c
+#define IPU_IC_CMBP_1 0x00000010
+#define IPU_IC_CMBP_2 0x00000014
+#define IPU_IC_IDMAC_1 0x00000018
+#define IPU_IC_IDMAC_2 0x0000001c
+#define IPU_IC_IDMAC_3 0x00000020
+#define IPU_IC_IDMAC_4 0x00000024
+
+/*
+ * CSI
+ * Camera Sensor Interface
+ */
+#define IPU_CSI0_SENS_CONF 0x00000000
+#define IPU_CSI0_SENS_FRM_SIZE 0x00000004
+#define IPU_CSI0_ACT_FRM_SIZE 0x00000008
+#define IPU_CSI0_OUT_FRM_CTRL 0x0000000c
+#define IPU_CSI0_TST_CTRL 0x00000010
+#define IPU_CSI0_CCIR_CODE_1 0x00000014
+#define IPU_CSI0_CCIR_CODE_2 0x00000018
+#define IPU_CSI0_CCIR_CODE_3 0x0000001c
+#define IPU_CSI0_DI 0x00000020
+#define IPU_CSI0_SKIP 0x00000024
+#define IPU_CSI0_CPD_CTRL 0x00000028
+#define IPU_CSI0_CPD_OFFSET1 0x000000ec
+#define IPU_CSI0_CPD_OFFSET2 0x000000f0
+
+#define IPU_CSI1_SENS_CONF 0x00000000
+#define IPU_CSI1_SENS_FRM_SIZE 0x00000004
+#define IPU_CSI1_ACT_FRM_SIZE 0x00000008
+#define IPU_CSI1_OUT_FRM_CTRL 0x0000000c
+#define IPU_CSI1_TST_CTRL 0x00000010
+#define IPU_CSI1_CCIR_CODE_1 0x00000014
+#define IPU_CSI1_CCIR_CODE_2 0x00000018
+#define IPU_CSI1_CCIR_CODE_3 0x0000001c
+#define IPU_CSI1_DI 0x00000020
+#define IPU_CSI1_SKIP 0x00000024
+#define IPU_CSI1_CPD_CTRL 0x00000028
+#define IPU_CSI1_CPD_OFFSET1 0x000000ec
+#define IPU_CSI1_CPD_OFFSET2 0x000000f0
+
+/*
+ * DI
+ * Display Interface
+ */
+#define IPU_DI_GENERAL 0x00000000
+#define DI_GENERAL_DISP_Y_SEL 0x70000000
+#define DI_GENERAL_CLOCK_STOP_MODE 0x0f000000
+#define DI_GENERAL_DISP_CLOCK_INIT 0x00800000
+#define DI_GENERAL_MASK_SEL 0x00400000
+#define DI_GENERAL_VSYNC_EXT 0x00200000
+#define DI_GENERAL_CLK_EXT 0x00100000
+#define DI_GENERAL_WATCHDOG_MODE 0x000c0000
+#define DI_GENERAL_POLARITY_DISP_CLK 0x00020000
+#define DI_GENERAL_SYNC_COUNT_SEL 0x0000f000
+#define DI_GENERAL_ERR_TREATMENT 0x00000800
+#define DI_GENERAL_ERM_VSYNC_SEL 0x00000400
+#define DI_GENERAL_POLARITY_CS(n) (1 << ((n) + 8))
+#define DI_GENERAL_POLARITY(n) (1 << ((n) - 1))
+
+#define IPU_DI_BS_CLKGEN0 0x00000004
+#define DI_BS_CLKGEN0_OFFSET_SHIFT 16
+#define IPU_DI_BS_CLKGEN1 0x00000008
+#define DI_BS_CLKGEN1_DOWN_SHIFT 16
+#define DI_BS_CLKGEN1_UP_SHIFT 0
+#define IPU_DI_SW_GEN0(n) (0x0000000c + ((n) - 1) * 4)
+#define DI_SW_GEN0_RUN_VAL 0x7ff80000
+#define DI_SW_GEN0_RUN_RESOL 0x00070000
+#define DI_SW_GEN0_OFFSET_VAL 0x00007ff8
+#define DI_SW_GEN0_OFFSET_RESOL 0x00000007
+#define __DI_SW_GEN0(run_val, run_resol, offset_val, offset_resol) \
+ (((run_val) << 19) | ((run_resol) << 16) | \
+ ((offset_val) << 3) | (offset_resol))
+#define IPU_DI_SW_GEN1(n) (0x00000030 + ((n) - 1) * 4)
+#define DI_SW_GEN1_CNT_POL_GEN_EN 0x60000000
+#define DI_SW_GEN1_CNT_AUTO_RELOAD 0x10000000
+#define DI_SW_GEN1_CNT_CLR_SEL 0x0e000000
+#define DI_SW_GEN1_CNT_DOWN 0x01ff0000
+#define DI_SW_GEN1_CNT_POL_TRIG_SEL 0x00007000
+#define DI_SW_GEN1_CNT_POL_CLR_SEL 0x00000e00
+#define DI_SW_GEN1_CNT_UP 0x000001ff
+#define __DI_SW_GEN1(pol_gen_en, auto_reload, clr_sel, down, pol_trig_sel, pol_clr_sel, up) \
+ (((pol_gen_en) << 29) | ((auto_reload) << 28) | \
+ ((clr_sel) << 25) | \
+ ((down) << 16) | ((pol_trig_sel) << 12) | \
+ ((pol_clr_sel) << 9) | (up))
+#define IPU_DI_SYNC_AS_GEN 0x00000054
+#define DI_SYNC_AS_GEN_SYNC_START_EN 0x10000000
+#define DI_SYNC_AS_GEN_VSYNC_SEL 0x0000e000
+#define DI_SYNC_AS_GEN_VSYNC_SEL_SHIFT 13
+#define DI_SYNC_AS_GEN_SYNC_STAR 0x00000fff
+#define IPU_DI_DW_GEN(n) (0x00000058 + (n) * 4)
+#define DI_DW_GEN_ACCESS_SIZE_SHIFT 24
+#define DI_DW_GEN_COMPONNENT_SIZE_SHIFT 16
+#define DI_DW_GEN_PIN_SHIFT(n) (((n) - 11) * 2)
+#define DI_DW_GEN_PIN(n) __BITS(DI_DW_GEN_PIN_SHIFT(n) + 1, \
+ DI_DW_GEN_PIN_SHIFT(n))
+#define IPU_DI_DW_SET(n, m) (0x00000088 + (n) * 4 + (m) * 0x30)
+#define DI_DW_SET_DOWN_SHIFT 16
+#define DI_DW_SET_UP_SHIFT 0
+#define IPU_DI_STP_REP(n) (0x00000148 + ((n - 1) / 2) * 4)
+#define DI_STP_REP_SHIFT(n) (((n - 1) % 2) * 16)
+#define DI_STP_REP_MASK(n) (0x00000fff << DI_STP_REP_SHIFT((n)))
+#define IPU_DI_SER_CONF 0x0000015c
+#define IPU_DI_SSC 0x00000160
+#define IPU_DI_POL 0x00000164
+#define DI_POL_DRDY_POLARITY_17 0x00000040
+#define DI_POL_DRDY_POLARITY_16 0x00000020
+#define DI_POL_DRDY_POLARITY_15 0x00000010
+#define DI_POL_DRDY_POLARITY_14 0x00000008
+#define DI_POL_DRDY_POLARITY_13 0x00000004
+#define DI_POL_DRDY_POLARITY_12 0x00000002
+#define DI_POL_DRDY_POLARITY_11 0x00000001
+#define IPU_DI_AW0 0x00000168
+#define IPU_DI_AW1 0x0000016c
+#define IPU_DI_SCR_CONF 0x00000170
+#define IPU_DI_STAT 0x00000174
+
+/*
+ * SMFC
+ * Sensor Multi FIFO Controller
+ */
+#define IPU_SMFC_MAP 0x00000000
+#define IPU_SMFC_WMC 0x00000004
+#define IPU_SMFC_BS 0x00000008
+
+/*
+ * DC
+ * Display Controller
+ */
+#define IPU_DC_READ_CH_CONF 0x00000000
+#define IPU_DC_READ_CH_ADDR 0x00000004
+
+#define IPU_DC_RL0_CH_0 0x00000008
+#define IPU_DC_RL1_CH_0 0x0000000c
+#define IPU_DC_RL2_CH_0 0x00000010
+#define IPU_DC_RL3_CH_0 0x00000014
+#define IPU_DC_RL4_CH_0 0x00000018
+#define IPU_DC_WR_CH_CONF_1 0x0000001c
+#define IPU_DC_WR_CH_ADDR_1 0x00000020
+#define IPU_DC_RL0_CH_1 0x00000024
+#define IPU_DC_RL1_CH_1 0x00000028
+#define IPU_DC_RL2_CH_1 0x0000002c
+#define IPU_DC_RL3_CH_1 0x00000030
+#define IPU_DC_RL4_CH_1 0x00000034
+#define IPU_DC_WR_CH_CONF_2 0x00000038
+#define IPU_DC_WR_CH_ADDR_2 0x0000003c
+#define IPU_DC_RL0_CH_2 0x00000040
+#define IPU_DC_RL1_CH_2 0x00000044
+#define IPU_DC_RL2_CH_2 0x00000048
+#define IPU_DC_RL3_CH_2 0x0000004c
+#define IPU_DC_RL4_CH_2 0x00000050
+#define IPU_DC_CMD_CH_CONF_3 0x00000054
+#define IPU_DC_CMD_CH_CONF_4 0x00000058
+#define IPU_DC_WR_CH_CONF_5 0x0000005c
+#define IPU_DC_WR_CH_ADDR_5 0x00000060
+#define IPU_DC_RL0_CH_5 0x00000064
+#define IPU_DC_RL1_CH_5 0x00000068
+#define IPU_DC_RL2_CH_5 0x0000006c
+#define IPU_DC_RL3_CH_5 0x00000070
+#define IPU_DC_RL4_CH_5 0x00000074
+#define IPU_DC_WR_CH_CONF_6 0x00000078
+#define IPU_DC_WR_CH_ADDR_6 0x0000007c
+#define IPU_DC_RL0_CH_6 0x00000080
+#define IPU_DC_RL1_CH_6 0x00000084
+#define IPU_DC_RL2_CH_6 0x00000088
+#define IPU_DC_RL3_CH_6 0x0000008c
+#define IPU_DC_RL4_CH_6 0x00000090
+#define IPU_DC_WR_CH_CONF1_8 0x00000094
+#define IPU_DC_WR_CH_CONF2_8 0x00000098
+#define IPU_DC_RL1_CH_8 0x0000009c
+#define IPU_DC_RL2_CH_8 0x000000a0
+#define IPU_DC_RL3_CH_8 0x000000a4
+#define IPU_DC_RL4_CH_8 0x000000a8
+#define IPU_DC_RL5_CH_8 0x000000ac
+#define IPU_DC_RL6_CH_8 0x000000b0
+#define IPU_DC_WR_CH_CONF1_9 0x000000b4
+#define IPU_DC_WR_CH_CONF2_9 0x000000b8
+#define IPU_DC_RL1_CH_9 0x000000bc
+#define IPU_DC_RL2_CH_9 0x000000c0
+#define IPU_DC_RL3_CH_9 0x000000c4
+#define IPU_DC_RL4_CH_9 0x000000c8
+#define IPU_DC_RL5_CH_9 0x000000cc
+#define IPU_DC_RL6_CH_9 0x000000d0
+
+#define IPU_DC_RL(chan_base, evt) ((chan_base) + (evt / 2) *0x4)
+#define DC_RL_CH_0 IPU_DC_RL0_CH_0
+#define DC_RL_CH_1 IPU_DC_RL0_CH_1
+#define DC_RL_CH_2 IPU_DC_RL0_CH_2
+#define DC_RL_CH_5 IPU_DC_RL0_CH_5
+#define DC_RL_CH_6 IPU_DC_RL0_CH_6
+#define DC_RL_CH_8 IPU_DC_RL0_CH_8
+
+#define DC_RL_EVT_NF 0
+#define DC_RL_EVT_NL 1
+#define DC_RL_EVT_EOF 2
+#define DC_RL_EVT_NFIELD 3
+#define DC_RL_EVT_EOL 4
+#define DC_RL_EVT_EOFIELD 5
+#define DC_RL_EVT_NEW_ADDR 6
+#define DC_RL_EVT_NEW_CHAN 7
+#define DC_RL_EVT_NEW_DATA 8
+
+#define IPU_DC_GEN 0x000000d4
+#define IPU_DC_DISP_CONF1_0 0x000000d8
+#define IPU_DC_DISP_CONF1_1 0x000000dc
+#define IPU_DC_DISP_CONF1_2 0x000000e0
+#define IPU_DC_DISP_CONF1_3 0x000000e4
+#define IPU_DC_DISP_CONF2_0 0x000000e8
+#define IPU_DC_DISP_CONF2_1 0x000000ec
+#define IPU_DC_DISP_CONF2_2 0x000000f0
+#define IPU_DC_DISP_CONF2_3 0x000000f4
+#define IPU_DC_DI0_CONF_1 0x000000f8
+#define IPU_DC_DI0_CONF_2 0x000000fc
+#define IPU_DC_DI1_CONF_1 0x00000100
+#define IPU_DC_DI1_CONF_2 0x00000104
+
+#define IPU_DC_MAP_CONF_PNTR(n) (0x00000108 + (n) * 4)
+#define IPU_DC_MAP_CONF_0 0x00000108
+#define IPU_DC_MAP_CONF_1 0x0000010c
+#define IPU_DC_MAP_CONF_2 0x00000110
+#define IPU_DC_MAP_CONF_3 0x00000114
+#define IPU_DC_MAP_CONF_4 0x00000118
+#define IPU_DC_MAP_CONF_5 0x0000011c
+#define IPU_DC_MAP_CONF_6 0x00000120
+#define IPU_DC_MAP_CONF_7 0x00000124
+#define IPU_DC_MAP_CONF_8 0x00000128
+#define IPU_DC_MAP_CONF_9 0x0000012c
+#define IPU_DC_MAP_CONF_10 0x00000130
+#define IPU_DC_MAP_CONF_11 0x00000134
+#define IPU_DC_MAP_CONF_12 0x00000138
+#define IPU_DC_MAP_CONF_13 0x0000013c
+#define IPU_DC_MAP_CONF_14 0x00000140
+
+#define IPU_DC_MAP_CONF_MASK(n) (0x00000144 + (n) * 4)
+#define IPU_DC_MAP_CONF_15 0x00000144
+#define IPU_DC_MAP_CONF_16 0x00000148
+#define IPU_DC_MAP_CONF_17 0x0000014c
+#define IPU_DC_MAP_CONF_18 0x00000150
+#define IPU_DC_MAP_CONF_19 0x00000154
+#define IPU_DC_MAP_CONF_20 0x00000158
+#define IPU_DC_MAP_CONF_21 0x0000015c
+#define IPU_DC_MAP_CONF_22 0x00000160
+#define IPU_DC_MAP_CONF_23 0x00000164
+#define IPU_DC_MAP_CONF_24 0x00000168
+#define IPU_DC_MAP_CONF_25 0x0000016c
+#define IPU_DC_MAP_CONF_26 0x00000170
+
+#define IPU_DC_UGDE(m, n) (0x00000174 + (m) * 0x10 + (n) +4)
+#define IPU_DC_UGDE0_0 0x00000174
+#define IPU_DC_UGDE0_1 0x00000178
+#define IPU_DC_UGDE0_2 0x0000017c
+#define IPU_DC_UGDE0_3 0x00000180
+#define IPU_DC_UGDE1_0 0x00000184
+#define IPU_DC_UGDE1_1 0x00000188
+#define IPU_DC_UGDE1_2 0x0000018c
+#define IPU_DC_UGDE1_3 0x00000190
+#define IPU_DC_UGDE2_0 0x00000194
+#define IPU_DC_UGDE2_1 0x00000198
+#define IPU_DC_UGDE2_2 0x0000019c
+#define IPU_DC_UGDE2_3 0x000001a0
+#define IPU_DC_UGDE3_0 0x000001a4
+#define IPU_DC_UGDE3_1 0x000001a8
+#define IPU_DC_UGDE3_2 0x000001ac
+#define IPU_DC_UGDE3_3 0x000001b0
+#define IPU_DC_LLA0 0x000001b4
+#define IPU_DC_LLA1 0x000001b8
+#define IPU_DC_R_LLA0 0x000001bc
+#define IPU_DC_R_LLA1 0x000001c0
+#define IPU_DC_WR_CH_ADDR_5_ALT 0x000001c4
+#define IPU_DC_STAT 0x000001c8
+
+/*
+ * DMFC
+ * Display Multi FIFO Controller
+ */
+#define IPU_DMFC_RD_CHAN 0x00000000
+#define DMFC_RD_CHAN_PPW_C 0x03000000
+#define DMFC_RD_CHAN_WM_DR_0 0x00e00000
+#define DMFC_RD_CHAN_WM_SET_0 0x001c0000
+#define DMFC_RD_CHAN_WM_EN_0 0x00020000
+#define DMFC_RD_CHAN_BURST_SIZE_0 0x000000c0
+#define IPU_DMFC_WR_CHAN 0x00000004
+#define DMFC_WR_CHAN_BUSRT_SIZE_2C 0xc0000000
+#define DMFC_WR_CHAN_FIFO_SIZE_2C 0x38000000
+#define DMFC_WR_CHAN_ST_ADDR_2C 0x07000000
+#define DMFC_WR_CHAN_BURST_SIZE_1C 0x00c00000
+#define DMFC_WR_CHAN_FIFO_SIZE_1C 0x00380000
+#define DMFC_WR_CHAN_ST_ADDR_1C 0x00070000
+#define DMFC_WR_CHAN_BURST_SIZE_2 0x0000c000
+#define DMFC_WR_CHAN_FIFO_SIZE_2 0x00003800
+#define DMFC_WR_CHAN_ST_ADDR_2 0x00000700
+#define DMFC_WR_CHAN_BURST_SIZE_1 0x000000c0
+#define DMFC_WR_CHAN_FIFO_SIZE_1 0x00000038
+#define DMFC_WR_CHAN_ST_ADDR_1 0x00000007
+#define IPU_DMFC_WR_CHAN_DEF 0x00000008
+#define DMFC_WR_CHAN_DEF_WM_CLR_2C 0xe0000000
+#define DMFC_WR_CHAN_DEF_WM_SET_2C 0x1c000000
+#define DMFC_WR_CHAN_DEF_WM_EN_2C 0x02000000
+#define DMFC_WR_CHAN_DEF_WM_CLR_1C 0x00e00000
+#define DMFC_WR_CHAN_DEF_WM_SET_1C 0x001c0000
+#define DMFC_WR_CHAN_DEF_WM_EN_1C 0x00020000
+#define DMFC_WR_CHAN_DEF_WM_CLR_2 0x0000e000
+#define DMFC_WR_CHAN_DEF_WM_SET_2 0x00001c00
+#define DMFC_WR_CHAN_DEF_WM_EN_2 0x00000200
+#define DMFC_WR_CHAN_DEF_WM_CLR_1 0x000000e0
+#define DMFC_WR_CHAN_DEF_WM_SET_1 0x0000000c
+#define DMFC_WR_CHAN_DEF_WM_EN_1 0x00000002
+#define IPU_DMFC_DP_CHAN 0x0000000c
+#define DMFC_DP_CHAN_BUSRT_SIZE_6F 0xc0000000
+#define DMFC_DP_CHAN_FIFO_SIZE_6F 0x38000000
+#define DMFC_DP_CHAN_ST_ADDR_6F 0x07000000
+#define DMFC_DP_CHAN_BURST_SIZE_6B 0x00c00000
+#define DMFC_DP_CHAN_FIFO_SIZE_6B 0x00380000
+#define DMFC_DP_CHAN_ST_ADDR_6B 0x00070000
+#define DMFC_DP_CHAN_BURST_SIZE_5F 0x0000c000
+#define DMFC_DP_CHAN_FIFO_SIZE_5F 0x00003800
+#define DMFC_DP_CHAN_ST_ADDR_5F 0x00000700
+#define DMFC_DP_CHAN_BURST_SIZE_5B 0x000000c0
+#define DMFC_DP_CHAN_FIFO_SIZE_5B 0x00000038
+#define DMFC_DP_CHAN_ST_ADDR_5B 0x00000007
+#define IPU_DMFC_DP_CHAN_DEF 0x00000010
+#define DMFC_DP_CHAN_DEF_WM_CLR_6F 0xe0000000
+#define DMFC_DP_CHAN_DEF_WM_SET_6F 0x1c000000
+#define DMFC_DP_CHAN_DEF_WM_EN_6F 0x02000000
+#define DMFC_DP_CHAN_DEF_WM_CLR_6B 0x00e00000
+#define DMFC_DP_CHAN_DEF_WM_SET_6B 0x001c0000
+#define DMFC_DP_CHAN_DEF_WM_EN_6B 0x00020000
+#define DMFC_DP_CHAN_DEF_WM_CLR_5F 0x0000e000
+#define DMFC_DP_CHAN_DEF_WM_SET_5F 0x00001c00
+#define DMFC_DP_CHAN_DEF_WM_EN_5F 0x00000200
+#define DMFC_DP_CHAN_DEF_WM_CLR_5B 0x000000e0
+#define DMFC_DP_CHAN_DEF_WM_SET_5B 0x0000001c
+#define DMFC_DP_CHAN_DEF_WM_EN_5B 0x00000002
+#define IPU_DMFC_GENERAL1 0x00000014
+#define DMFC_GENERAL1_WAIT4EOT_9 0x01000000
+#define DMFC_GENERAL1_WAIT4EOT_6F 0x00800000
+#define DMFC_GENERAL1_WAIT4EOT_6B 0x00400000
+#define DMFC_GENERAL1_WAIT4EOT_5F 0x00200000
+#define DMFC_GENERAL1_WAIT4EOT_5B 0x00100000
+#define DMFC_GENERAL1_WAIT4EOT_4 0x00080000
+#define DMFC_GENERAL1_WAIT4EOT_3 0x00040000
+#define DMFC_GENERAL1_WAIT4EOT_2 0x00020000
+#define DMFC_GENERAL1_WAIT4EOT_1 0x00010000
+#define DMFC_GENERAL1_WM_CLR_9 0x0000e000
+#define DMFC_GENERAL1_WM_SET_9 0x00001c00
+#define DMFC_GENERAL1_BURST_SIZE_9 0x00000060
+#define DMFC_GENERAL1_DCDP_SYNC_PR 0x00000003
+#define DCDP_SYNC_PR_FORBIDDEN 0
+#define DCDP_SYNC_PR_DC_DP 1
+#define DCDP_SYNC_PR_DP_DC 2
+#define DCDP_SYNC_PR_ROUNDROBIN 3
+#define IPU_DMFC_GENERAL2 0x00000018
+#define DMFC_GENERAL2_FRAME_HEIGHT_RD 0x1fff0000
+#define DMFC_GENERAL2_FRAME_WIDTH_RD 0x00001fff
+#define IPU_DMFC_IC_CTRL 0x0000001c
+#define DMFC_IC_CTRL_IC_FRAME_HEIGHT_RD 0xfff80000
+#define DMFC_IC_CTRL_IC_FRAME_WIDTH_RD 0x0007ffc0
+#define DMFC_IC_CTRL_IC_PPW_C 0x00000030
+#define DMFC_IC_CTRL_IC_IN_PORT 0x00000007
+#define IC_IN_PORT_CH28 0
+#define IC_IN_PORT_CH41 1
+#define IC_IN_PORT_DISABLE 2
+#define IC_IN_PORT_CH23 4
+#define IC_IN_PORT_CH27 5
+#define IC_IN_PORT_CH24 6
+#define IC_IN_PORT_CH29 7
+#define IPU_DMFC_WR_CHAN_ALT 0x00000020
+#define IPU_DMFC_WR_CHAN_DEF_ALT 0x00000024
+#define IPU_DMFC_DP_CHAN_ALT 0x00000028
+#define IPU_DMFC_DP_CHAN_DEF_ALT 0x0000002c
+#define DMFC_DP_CHAN_DEF_ALT_WM_CLR_6F_ALT 0xe0000000
+#define DMFC_DP_CHAN_DEF_ALT_WM_SET_6F_ALT 0x1c000000
+#define DMFC_DP_CHAN_DEF_ALT_WM_EN_6F_ALT 0x02000000
+#define DMFC_DP_CHAN_DEF_ALT_WM_CLR_6B_ALT 0x00e00000
+#define DMFC_DP_CHAN_DEF_ALT_WM_SET_6B_ALT 0x001c0000
+#define DMFC_DP_CHAN_DEF_ALT_WM_EN_6B_ALT 0x00020000
+#define DMFC_DP_CHAN_DEF_ALT_WM_CLR_5B_ALT 0x000000e0
+#define DMFC_DP_CHAN_DEF_ALT_WM_SET_5B_ALT 0x0000001c
+#define DMFC_DP_CHAN_DEF_ALT_WM_EN_5B_ALT 0x00000002
+#define IPU_DMFC_GENERAL1_ALT 0x00000030
+#define DMFC_GENERAL1_ALT_WAIT4EOT_6F_ALT 0x00800000
+#define DMFC_GENERAL1_ALT_WAIT4EOT_6B_ALT 0x00400000
+#define DMFC_GENERAL1_ALT_WAIT4EOT_5B_ALT 0x00100000
+#define DMFC_GENERAL1_ALT_WAIT4EOT_2_ALT 0x00020000
+#define IPU_DMFC_STAT 0x00000034
+#define DMFC_STAT_IC_BUFFER_EMPTY 0x02000000
+#define DMFC_STAT_IC_BUFFER_FULL 0x01000000
+#define DMFC_STAT_FIFO_EMPTY(n) __BIT(12 + (n))
+#define DMFC_STAT_FIFO_FULL(n) __BIT((n))
+
+/*
+ * VCI
+ * Video De Interkacing Module
+ */
+#define IPU_VDI_FSIZE 0x00000000
+#define IPU_VDI_C 0x00000004
+
+/*
+ * DP
+ * Display Processor
+ */
+#define IPU_DP_COM_CONF_SYNC 0x00000000
+#define DP_FG_EN_SYNC 0x00000001
+#define DP_DP_GWAM_SYNC 0x00000004
+#define IPU_DP_GRAPH_WIND_CTRL_SYNC 0x00000004
+#define IPU_DP_FG_POS_SYNC 0x00000008
+#define IPU_DP_CUR_POS_SYNC 0x0000000c
+#define IPU_DP_CUR_MAP_SYNC 0x00000010
+#define IPU_DP_CSC_SYNC_0 0x00000054
+#define IPU_DP_CSC_SYNC_1 0x00000058
+#define IPU_DP_CUR_POS_ALT 0x0000005c
+#define IPU_DP_COM_CONF_ASYNC0 0x00000060
+#define IPU_DP_GRAPH_WIND_CTRL_ASYNC0 0x00000064
+#define IPU_DP_FG_POS_ASYNC0 0x00000068
+#define IPU_DP_CUR_POS_ASYNC0 0x0000006c
+#define IPU_DP_CUR_MAP_ASYNC0 0x00000070
+#define IPU_DP_CSC_ASYNC0_0 0x000000b4
+#define IPU_DP_CSC_ASYNC0_1 0x000000b8
+#define IPU_DP_COM_CONF_ASYNC1 0x000000bc
+#define IPU_DP_GRAPH_WIND_CTRL_ASYNC1 0x000000c0
+#define IPU_DP_FG_POS_ASYNC1 0x000000c4
+#define IPU_DP_CUR_POS_ASYNC1 0x000000c8
+#define IPU_DP_CUR_MAP_ASYNC1 0x000000cc
+#define IPU_DP_CSC_ASYNC1_0 0x00000110
+#define IPU_DP_CSC_ASYNC1_1 0x00000114
+
+/* IDMA parameter */
+ /*
+ * non-Interleaved parameter
+ *
+ * param 0: XV W0[ 9: 0]
+ * YV W0[18:10]
+ * XB W0[31:19]
+ * param 1: YB W0[43:32]
+ * NSB W0[44]
+ * CF W0[45]
+ * UBO W0[61:46]
+ * param 2: UBO W0[67:62]
+ * VBO W0[89:68]
+ * IOX W0[93:90]
+ * RDRW W0[94]
+ * Reserved W0[95]
+ * param 3: Reserved W0[112:96]
+ * S0 W0[113]
+ * BNDM W0[116:114]
+ * BM W0[118:117]
+ * ROT W0[119]
+ * HF W0[120]
+ * VF W0[121]
+ * THF W0[122]
+ * CAP W0[123]
+ * CAE W0[124]
+ * FW W0[127:125]
+ * param 4: FW W0[137:128]
+ * FH W0[149:138]
+ * param 5: EBA0 W1[28:0]
+ * EBA1 W1[31:29]
+ * param 6: EBA1 W1[57:32]
+ * ILO W1[63:58]
+ * param 7: ILO W1[77:64]
+ * NPB W1[84:78]
+ * PFS W1[88:85]
+ * ALU W1[89]
+ * ALBM W1[92:90]
+ * ID W1[94:93]
+ * TH W1[95]
+ * param 8: TH W1[101:96]
+ * SLY W1[115:102]
+ * WID3 W1[127:125]
+ * param 9: SLUV W1[141:128]
+ * CRE W1[149]
+ *
+ * Interleaved parameter
+ *
+ * param 0: XV W0[ 9: 0]
+ * YV W0[18:10]
+ * XB W0[31:19]
+ * param 1: YB W0[43:32]
+ * NSB W0[44]
+ * CF W0[45]
+ * SX W0[57:46]
+ * SY W0[61:58]
+ * param 2: SY W0[68:62]
+ * NS W0[78:69]
+ * SDX W0[85:79]
+ * SM W0[95:86]
+ * param 3: SCC W0[96]
+ * SCE W0[97]
+ * SDY W0[104:98]
+ * SDRX W0[105]
+ * SDRY W0[106]
+ * BPP W0[109:107]
+ * DEC_SEL W0[111:110]
+ * DIM W0[112]
+ * SO W0[113]
+ * BNDM W0[116:114]
+ * BM W0[118:117]
+ * ROT W0[119]
+ * HF W0[120]
+ * VF W0[121]
+ * THF W0[122]
+ * CAP W0[123]
+ * CAE W0[124]
+ * FW W0[127:125]
+ * param 4: FW W0[137:128]
+ * FH W0[149:138]
+ * param 5: EBA0 W1[28:0]
+ * EBA1 W1[31:29]
+ * param 6: EBA1 W1[57:32]
+ * ILO W1[63:58]
+ * param 7: ILO W1[77:64]
+ * NPB W1[84:78]
+ * PFS W1[88:85]
+ * ALU W1[89]
+ * ALBM W1[92:90]
+ * ID W1[94:93]
+ * TH W1[95]
+ * param 8: TH W1[101:96]
+ * SL W1[115:102]
+ * WID0 W1[118:116]
+ * WID1 W1[121:119]
+ * WID2 W1[124:122]
+ * WID3 W1[127:125]
+ * param 9: OFS0 W1[132:128]
+ * OFS1 W1[137:133]
+ * OFS2 W1[142:138]
+ * OFS3 W1[147:143]
+ * SXYS W1[148]
+ * CRE W1[149]
+ * DEC_SEL2 W1[150]
+ */
+
+#define __IDMA_PARAM(word, shift, size) \
+ ((((word) & 0xff) << 16) | (((shift) & 0xff) << 8) | ((size) & 0xff))
+
+/* non-Interleaved parameter */
+/* W0 */
+#define IDMAC_Ch_PARAM_XV __IDMA_PARAM(0, 0, 10)
+#define IDMAC_Ch_PARAM_YV __IDMA_PARAM(0, 10, 9)
+#define IDMAC_Ch_PARAM_XB __IDMA_PARAM(0, 19, 13)
+#define IDMAC_Ch_PARAM_YB __IDMA_PARAM(0, 32, 12)
+#define IDMAC_Ch_PARAM_NSB __IDMA_PARAM(0, 44, 1)
+#define IDMAC_Ch_PARAM_CF __IDMA_PARAM(0, 45, 1)
+#define IDMAC_Ch_PARAM_UBO __IDMA_PARAM(0, 46, 22)
+#define IDMAC_Ch_PARAM_VBO __IDMA_PARAM(0, 68, 22)
+#define IDMAC_Ch_PARAM_IOX __IDMA_PARAM(0, 90, 4)
+#define IDMAC_Ch_PARAM_RDRW __IDMA_PARAM(0, 94, 1)
+#define IDMAC_Ch_PARAM_S0 __IDMA_PARAM(0,113, 1)
+#define IDMAC_Ch_PARAM_BNDM __IDMA_PARAM(0,114, 3)
+#define IDMAC_Ch_PARAM_BM __IDMA_PARAM(0,117, 2)
+#define IDMAC_Ch_PARAM_ROT __IDMA_PARAM(0,119, 1)
+#define IDMAC_Ch_PARAM_HF __IDMA_PARAM(0,120, 1)
+#define IDMAC_Ch_PARAM_VF __IDMA_PARAM(0,121, 1)
+#define IDMAC_Ch_PARAM_THF __IDMA_PARAM(0,122, 1)
+#define IDMAC_Ch_PARAM_CAP __IDMA_PARAM(0,123, 1)
+#define IDMAC_Ch_PARAM_CAE __IDMA_PARAM(0,124, 1)
+#define IDMAC_Ch_PARAM_FW __IDMA_PARAM(0,125, 13)
+#define IDMAC_Ch_PARAM_FH __IDMA_PARAM(0,138, 12)
+/* W1 */
+#define IDMAC_Ch_PARAM_EBA0 __IDMA_PARAM(1, 0, 29)
+#define IDMAC_Ch_PARAM_EBA1 __IDMA_PARAM(1, 29, 29)
+#define IDMAC_Ch_PARAM_ILO __IDMA_PARAM(1, 58, 20)
+#define IDMAC_Ch_PARAM_NPB __IDMA_PARAM(1, 78, 7)
+#define IDMAC_Ch_PARAM_PFS __IDMA_PARAM(1, 85, 4)
+#define IDMAC_Ch_PARAM_ALU __IDMA_PARAM(1, 89, 1)
+#define IDMAC_Ch_PARAM_ALBM __IDMA_PARAM(1, 90, 3)
+#define IDMAC_Ch_PARAM_ID __IDMA_PARAM(1, 93, 2)
+#define IDMAC_Ch_PARAM_TH __IDMA_PARAM(1, 95, 7)
+#define IDMAC_Ch_PARAM_SL __IDMA_PARAM(1,102, 14)
+#define IDMAC_Ch_PARAM_WID3 __IDMA_PARAM(1,125, 3)
+#define IDMAC_Ch_PARAM_SLUV __IDMA_PARAM(1,128, 14)
+#define IDMAC_Ch_PARAM_CRE __IDMA_PARAM(1,149, 1)
+
+/* Interleaved parameter */
+/* W0 */
+#define IDMAC_Ch_PARAM_XV __IDMA_PARAM(0, 0, 10)
+#define IDMAC_Ch_PARAM_YV __IDMA_PARAM(0, 10, 9)
+#define IDMAC_Ch_PARAM_XB __IDMA_PARAM(0, 19, 13)
+#define IDMAC_Ch_PARAM_YB __IDMA_PARAM(0, 32, 12)
+#define IDMAC_Ch_PARAM_NSB __IDMA_PARAM(0, 44, 1)
+#define IDMAC_Ch_PARAM_CF __IDMA_PARAM(0, 45, 1)
+#define IDMAC_Ch_PARAM_SX __IDMA_PARAM(0, 46, 12)
+#define IDMAC_Ch_PARAM_SY __IDMA_PARAM(0, 58, 11)
+#define IDMAC_Ch_PARAM_NS __IDMA_PARAM(0, 69, 10)
+#define IDMAC_Ch_PARAM_SDX __IDMA_PARAM(0, 79, 7)
+#define IDMAC_Ch_PARAM_SM __IDMA_PARAM(0, 86, 10)
+#define IDMAC_Ch_PARAM_SCC __IDMA_PARAM(0, 96, 1)
+#define IDMAC_Ch_PARAM_SCE __IDMA_PARAM(0, 97, 1)
+#define IDMAC_Ch_PARAM_SDY __IDMA_PARAM(0, 98, 7)
+#define IDMAC_Ch_PARAM_SDRX __IDMA_PARAM(0,105, 1)
+#define IDMAC_Ch_PARAM_SDRY __IDMA_PARAM(0,106, 1)
+#define IDMAC_Ch_PARAM_BPP __IDMA_PARAM(0,107, 3)
+#define IDMAC_Ch_PARAM_DEC_SEL __IDMA_PARAM(0,110, 2)
+#define IDMAC_Ch_PARAM_DIM __IDMA_PARAM(0,112, 1)
+#define IDMAC_Ch_PARAM_SO __IDMA_PARAM(0,113, 1)
+#define IDMAC_Ch_PARAM_BNDM __IDMA_PARAM(0,114, 3)
+#define IDMAC_Ch_PARAM_BM __IDMA_PARAM(0,117, 2)
+#define IDMAC_Ch_PARAM_ROT __IDMA_PARAM(0,119, 1)
+#define IDMAC_Ch_PARAM_HF __IDMA_PARAM(0,120, 1)
+#define IDMAC_Ch_PARAM_VF __IDMA_PARAM(0,121, 1)
+#define IDMAC_Ch_PARAM_THF __IDMA_PARAM(0,122, 1)
+#define IDMAC_Ch_PARAM_CAP __IDMA_PARAM(0,123, 1)
+#define IDMAC_Ch_PARAM_CAE __IDMA_PARAM(0,124, 1)
+#define IDMAC_Ch_PARAM_FW __IDMA_PARAM(0,125, 13)
+#define IDMAC_Ch_PARAM_FH __IDMA_PARAM(0,138, 12)
+/* W1 */
+#define IDMAC_Ch_PARAM_EBA0 __IDMA_PARAM(1, 0, 29)
+#define IDMAC_Ch_PARAM_EBA1 __IDMA_PARAM(1, 29, 29)
+#define IDMAC_Ch_PARAM_ILO __IDMA_PARAM(1, 58, 20)
+#define IDMAC_Ch_PARAM_NPB __IDMA_PARAM(1, 78, 7)
+#define IDMAC_Ch_PARAM_PFS __IDMA_PARAM(1, 85, 4)
+#define IDMAC_Ch_PARAM_ALU __IDMA_PARAM(1, 89, 1)
+#define IDMAC_Ch_PARAM_ALBM __IDMA_PARAM(1, 90, 3)
+#define IDMAC_Ch_PARAM_ID __IDMA_PARAM(1, 93, 2)
+#define IDMAC_Ch_PARAM_TH __IDMA_PARAM(1, 95, 7)
+#define IDMAC_Ch_PARAM_SL __IDMA_PARAM(1,102, 14)
+#define IDMAC_Ch_PARAM_WID0 __IDMA_PARAM(1,116, 3)
+#define IDMAC_Ch_PARAM_WID1 __IDMA_PARAM(1,119, 3)
+#define IDMAC_Ch_PARAM_WID2 __IDMA_PARAM(1,122, 3)
+#define IDMAC_Ch_PARAM_WID3 __IDMA_PARAM(1,125, 3)
+#define IDMAC_Ch_PARAM_OFS0 __IDMA_PARAM(1,128, 5)
+#define IDMAC_Ch_PARAM_OFS1 __IDMA_PARAM(1,133, 5)
+#define IDMAC_Ch_PARAM_OFS2 __IDMA_PARAM(1,138, 5)
+#define IDMAC_Ch_PARAM_OFS3 __IDMA_PARAM(1,143, 5)
+#define IDMAC_Ch_PARAM_SXYS __IDMA_PARAM(1,148, 1)
+#define IDMAC_Ch_PARAM_CRE __IDMA_PARAM(1,149, 1)
+#define IDMAC_Ch_PARAM_DEC_SEL2 __IDMA_PARAM(1,150, 1)
+
+/* XXX Temp */
+#define GPUMEM_BASE 0x20000000
+#define GPUMEM_SIZE 0x20000
+
+#define GPU_BASE 0x30000000
+#define GPU_SIZE 0x10000000
+
+/*
+ * Image Processing Unit
+ *
+ * All addresses are relative to the base SoC address.
+ */
+#define IPU_CM_BASE(_base) ((_base) + 0x1e000000)
+#define IPU_CM_SIZE 0x8000
+#define IPU_IDMAC_BASE(_base) ((_base) + 0x1e008000)
+#define IPU_IDMAC_SIZE 0x8000
+#define IPU_DP_BASE(_base) ((_base) + 0x1e018000)
+#define IPU_DP_SIZE 0x8000
+#define IPU_IC_BASE(_base) ((_base) + 0x1e020000)
+#define IPU_IC_SIZE 0x8000
+#define IPU_IRT_BASE(_base) ((_base) + 0x1e028000)
+#define IPU_IRT_SIZE 0x8000
+#define IPU_CSI0_BASE(_base) ((_base) + 0x1e030000)
+#define IPU_CSI0_SIZE 0x8000
+#define IPU_CSI1_BASE(_base) ((_base) + 0x1e038000)
+#define IPU_CSI1_SIZE 0x8000
+#define IPU_DI0_BASE(_base) ((_base) + 0x1e040000)
+#define IPU_DI0_SIZE 0x8000
+#define IPU_DI1_BASE(_base) ((_base) + 0x1e048000)
+#define IPU_DI1_SIZE 0x8000
+#define IPU_SMFC_BASE(_base) ((_base) + 0x1e050000)
+#define IPU_SMFC_SIZE 0x8000
+#define IPU_DC_BASE(_base) ((_base) + 0x1e058000)
+#define IPU_DC_SIZE 0x8000
+#define IPU_DMFC_BASE(_base) ((_base) + 0x1e060000)
+#define IPU_DMFC_SIZE 0x8000
+#define IPU_VDI_BASE(_base) ((_base) + 0x1e068000)
+#define IPU_VDI_SIZE 0x8000
+#define IPU_CPMEM_BASE(_base) ((_base) + 0x1f000000)
+#define IPU_CPMEM_SIZE 0x20000
+#define IPU_LUT_BASE(_base) ((_base) + 0x1f020000)
+#define IPU_LUT_SIZE 0x20000
+#define IPU_SRM_BASE(_base) ((_base) + 0x1f040000)
+#define IPU_SRM_SIZE 0x20000
+#define IPU_TPM_BASE(_base) ((_base) + 0x1f060000)
+#define IPU_TPM_SIZE 0x20000
+#define IPU_DCTMPL_BASE(_base) ((_base) + 0x1f080000)
+#define IPU_DCTMPL_SIZE 0x20000
+
+#endif /* _ARM_IMX_IMX51_IPUV3REG_H */
Property changes on: trunk/sys/arm/freescale/imx/imx51_ipuv3reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_machdep.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_machdep.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,103 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx51_machdep.c 259365 2013-12-14 00:16:08Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/reboot.h>
+
+#include <vm/vm.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <arm/freescale/imx/imx_machdep.h>
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+
+ /* XXX - Get rid of this stuff soon. */
+ boothowto |= RB_VERBOSE|RB_MULTIPLE;
+ bootverbose = 1;
+}
+
+void
+initarm_gpio_init(void)
+{
+
+}
+
+void
+initarm_late_init(void)
+{
+
+}
+
+/*
+ * Set up static device mappings. This is hand-optimized platform-specific
+ * config data which covers most of the common on-chip devices with a few 1MB
+ * section mappings.
+ *
+ * Notably missing are entries for GPU, IPU, in general anything video related.
+ */
+int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(0x70000000, 0x00100000);
+ arm_devmap_add_entry(0x73f00000, 0x00100000);
+ arm_devmap_add_entry(0x83f00000, 0x00100000);
+
+ return (0);
+}
+
+void
+cpu_reset(void)
+{
+
+ imx_wdog_cpu_reset(0x73F98000);
+}
+
+u_int imx_soc_type()
+{
+ return (IMXSOC_51);
+}
+
Property changes on: trunk/sys/arm/freescale/imx/imx51_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_sdmareg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_sdmareg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_sdmareg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,143 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx51_sdmareg.h 250357 2013-05-08 09:42:50Z ray $
+ */
+
+/* Internal Registers definition for Freescale i.MX515 SDMA Core */
+
+/* SDMA Core Instruction Memory Space */
+#define SDMA_IBUS_ROM_ADDR_BASE 0x0000
+#define SDMA_IBUS_ROM_ADDR_SIZE 0x07ff
+#define SDMA_IBUS_RAM_ADDR_BASE 0x1000
+#define SDMA_IBUS_RAM_ADDR_SIZE 0x1fff
+
+/* SDMA Core Internal Registers */
+#define SDMA_MC0PTR 0x7000 /* AP (MCU) Channel 0 Pointer R */
+
+#define SDMA_CCPTR 0x7002 /* Current Channel Pointer R */
+#define SDMA_ECTL_CCPTR_MASK 0x0000ffff
+#define SDMA_ECTL_CCPTR_SHIFT 0
+
+#define SDMA_CCR 0x7003 /* Current Channel Register R */
+#define SDMA_ECTL_CCR_MASK 0x0000001f
+#define SDMA_ECTL_CCR_SHIFT 0
+
+#define SDMA_NCR 0x7004 /* Highest Pending Channel Register R */
+#define SDMA_ECTL_NCR_MASK 0x0000001f
+#define SDMA_ECTL_NCR_SHIFT 0
+
+#define SDMA_EVENTS 0x7005 /* External DMA Requests Mirror R */
+
+#define SDMA_CCPRI 0x7006 /* Current Channel Priority R */
+#define SDMA_ECTL_CCPRI_MASK 0x00000007
+#define SDMA_ECTL_CCPRI_SHIFT 0
+
+#define SDMA_NCPRI 0x7007 /* Next Channel Priority R */
+#define SDMA_ECTL_NCPRI_MASK 0x00000007
+#define SDMA_ECTL_NCPRI_SHIFT 0
+
+#define SDMA_ECOUNT 0x7009 /* OnCE Event Cell Counter R/W */
+#define SDMA_ECTL_ECOUNT_MASK 0x0000ffff
+#define SDMA_ECTL_ECOUNT_SHIFT 0
+
+#define SDMA_ECTL 0x700A /* OnCE Event Cell Control Register R/W */
+#define SDMA_ECTL_EN (1 << 13)
+#define SDMA_ECTL_CNT (1 << 12)
+#define SDMA_ECTL_ECTC_MASK 0x00000c00
+#define SDMA_ECTL_ECTC_SHIFT 10
+#define SDMA_ECTL_DTC_MASK 0x00000300
+#define SDMA_ECTL_DTC_SHIFT 8
+#define SDMA_ECTL_ATC_MASK 0x000000c0
+#define SDMA_ECTL_ATC_SHIFT 6
+#define SDMA_ECTL_ABTC_MASK 0x00000030
+#define SDMA_ECTL_ABTC_SHIFT 4
+#define SDMA_ECTL_AATC_MASK 0x0000000c
+#define SDMA_ECTL_AATC_SHIFT 2
+#define SDMA_ECTL_ATS_MASK 0x00000003
+#define SDMA_ECTL_ATS_SHIFT 0
+
+#define SDMA_EAA 0x700B /* OnCE Event Address Register A R/W */
+#define SDMA_ECTL_EAA_MASK 0x0000ffff
+#define SDMA_ECTL_EAA_SHIFT 0
+
+#define SDMA_EAB 0x700C /* OnCE Event Cell Address Register B R/W */
+#define SDMA_ECTL_EAB_MASK 0x0000ffff
+#define SDMA_ECTL_EAB_SHIFT 0
+
+#define SDMA_EAM 0x700D /* OnCE Event Cell Address Mask R/W */
+#define SDMA_ECTL_EAM_MASK 0x0000ffff
+#define SDMA_ECTL_EAM_SHIFT 0
+
+#define SDMA_ED 0x700E /* OnCE Event Cell Data Register R/W */
+#define SDMA_EDM 0x700F /* OnCE Event Cell Data Mask R/W */
+#define SDMA_RTB 0x7018 /* OnCE Real-Time Buffer R/W */
+
+#define SDMA_TB 0x7019 /* OnCE Trace Buffer R */
+#define SDMA_TB_TBF (1 << 28)
+#define SDMA_TB_TADDR_MASK 0x0fffc000
+#define SDMA_TB_TADDR_SHIFT 14
+#define SDMA_TB_CHFADDR_MASK 0x00003fff
+#define SDMA_TB_CHFADDR_SHIFT 0
+
+#define SDMA_OSTAT 0x701A /* OnCE Status R */
+#define SDMA_OSTAT_PST_MASK 0x0000f000
+#define SDMA_OSTAT_PST_SHIFT 12
+#define SDMA_OSTAT_RCV (1 << 11)
+#define SDMA_OSTAT_EDR (1 << 10)
+#define SDMA_OSTAT_ODR (1 << 9)
+#define SDMA_OSTAT_SWB (1 << 8)
+#define SDMA_OSTAT_MST (1 << 7)
+#define SDMA_OSTAT_ECDR_MASK 0x00000007
+#define SDMA_OSTAT_ECDR_SHIFT 0
+
+#define SDMA_MCHN0ADDR 0x701C /* Channel 0 Boot Address R */
+#define SDMA_MCHN0ADDR_SMS_Z (1 << 14)
+#define SDMA_MCHN0ADDR_CHN0ADDR_MASK 0x00003fff
+#define SDMA_MCHN0ADDR_CHN0ADDR_SHIFT 0
+
+#define SDMA_MODE 0x701D /* Mode Status Register R */
+#define SDMA_MODE_DSPCtrl (1 << 3)
+#define SDMA_MODE_AP_END (1 << 0)
+
+#define SDMA_LOCK 0x701E /* Lock Status Register R */
+#define SDMA_LOCK_LOCK (1 << 0)
+
+#define SDMA_EVENTS2 0x701F /* External DMA Requests Mirror #2 R */
+
+#define SDMA_HE 0x7020 /* AP Enable Register R */
+#define SDMA_PRIV 0x7022 /* Current Channel BP Privilege Register R */
+#define SDMA_PRIV_BPPRIV (1 << 0)
+#define SDMA_PRF_CNT 0x7023 /* Profile Free Running Register R/W */
+#define SDMA_PRF_CNT_SEL_MASK 0xc0000000
+#define SDMA_PRF_CNT_SEL_SHIFT 30
+#define SDMA_PRF_CNT_EN (1 << 29)
+#define SDMA_PRF_CNT_OFL (1 << 22)
+#define SDMA_PRF_CNT_COUNTER_MASK 0x003fffff
+#define SDMA_PRF_CNT_COUNTER_SHIFT 0
Property changes on: trunk/sys/arm/freescale/imx/imx51_sdmareg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_ssireg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_ssireg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_ssireg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,181 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx51_ssireg.h 250357 2013-05-08 09:42:50Z ray $
+ */
+
+/* Registers definition for Freescale i.MX515 Synchronous Serial Interface */
+
+#define IMX51_SSI_STX0_REG 0x0000 /* SSI TX Data Register 0 */
+#define IMX51_SSI_STX1_REG 0x0004 /* SSI TX Data Register 1 */
+#define IMX51_SSI_SRX0_REG 0x0008 /* SSI RX Data Register 0 */
+#define IMX51_SSI_SRX1_REG 0x000C /* SSI RX Data Register 1 */
+#define IMX51_SSI_SCR_REG 0x0010 /* SSI Control Register */
+#define SSI_SCR_RFR_CLK_DIS (1 << 11) /* RX FC Disable */
+#define SSI_SCR_TFR_CLK_DIS (1 << 10) /* TX FC Disable */
+#define SSI_SCR_CLK_IST (1 << 9) /* Clock Idle */
+#define SSI_SCR_TCH_EN (1 << 8) /* 2Chan Enable */
+#define SSI_SCR_SYS_CLK_EN (1 << 7) /* System Clock En */
+#define SSI_SCR_MODE_NORMAL (0 << 5)
+#define SSI_SCR_MODE_I2S_MASTER (1 << 5)
+#define SSI_SCR_MODE_I2S_SLAVE (2 << 5)
+#define SSI_SCR_MODE_MASK (3 << 5)
+#define SSI_SCR_SYN (1 << 4) /* Sync Mode */
+#define SSI_SCR_NET (1 << 3) /* Network Mode */
+#define SSI_SCR_RE (1 << 2) /* RX Enable */
+#define SSI_SCR_TE (1 << 1) /* TX Enable */
+#define SSI_SCR_SSIEN (1 << 0) /* SSI Enable */
+
+#define IMX51_SSI_SISR_REG 0x0014 /* SSI Interrupt Status Register */
+#define SSI_SISR_RFRC (1 << 24) /* RX Frame Complete */
+#define SSI_SIR_TFRC (1 << 23) /* TX Frame Complete */
+#define SSI_SIR_CMDAU (1 << 18) /* Command Address Updated */
+#define SSI_SIR_CMDDU (1 << 17) /* Command Data Updated */
+#define SSI_SIR_RXT (1 << 16) /* RX Tag Updated */
+#define SSI_SIR_RDR1 (1 << 15) /* RX Data Ready 1 */
+#define SSI_SIR_RDR0 (1 << 14) /* RX Data Ready 0 */
+#define SSI_SIR_TDE1 (1 << 13) /* TX Data Reg Empty 1 */
+#define SSI_SIR_TDE0 (1 << 12) /* TX Data Reg Empty 0 */
+#define SSI_SIR_ROE1 (1 << 11) /* RXer Overrun Error 1 */
+#define SSI_SIR_ROE0 (1 << 10) /* RXer Overrun Error 0 */
+#define SSI_SIR_TUE1 (1 << 9) /* TXer Underrun Error 1 */
+#define SSI_SIR_TUE0 (1 << 8) /* TXer Underrun Error 0 */
+#define SSI_SIR_TFS (1 << 7) /* TX Frame Sync */
+#define SSI_SIR_RFS (1 << 6) /* RX Frame Sync */
+#define SSI_SIR_TLS (1 << 5) /* TX Last Time Slot */
+#define SSI_SIR_RLS (1 << 4) /* RX Last Time Slot */
+#define SSI_SIR_RFF1 (1 << 3) /* RX FIFO Full 1 */
+#define SSI_SIR_RFF0 (1 << 2) /* RX FIFO Full 0 */
+#define SSI_SIR_TFE1 (1 << 1) /* TX FIFO Empty 1 */
+#define SSI_SIR_TFE0 (1 << 0) /* TX FIFO Empty 0 */
+
+#define IMX51_SSI_SIER_REG 0x0018 /* SSI Interrupt Enable Register */
+/* 24-23 Enable Bit (See SISR) */
+#define SSI_SIER_RDMAE (1 << 22) /* RX DMA Enable */
+#define SSI_SIER_RIE (1 << 21) /* RX Interrupt Enable */
+#define SSI_SIER_TDMAE (1 << 20) /* TX DMA Enable */
+#define SSI_SIER_TIE (1 << 19) /* TX Interrupt Enable */
+/* 18-0 Enable Bits (See SISR) */
+
+#define IMX51_SSI_STCR_REG 0x001C /* SSI TX Configuration Register */
+#define SSI_STCR_TXBIT0 (1 << 9) /* TX Bit 0 */
+#define SSI_STCR_TFEN1 (1 << 8) /* TX FIFO Enable 1 */
+#define SSI_STCR_TFEN0 (1 << 7) /* TX FIFO Enable 0 */
+#define SSI_STCR_TFDIR (1 << 6) /* TX Frame Direction */
+#define SSI_STCR_TXDIR (1 << 5) /* TX Clock Direction */
+#define SSI_STCR_TSHFD (1 << 4) /* TX Shift Direction */
+#define SSI_STCR_TSCKP (1 << 3) /* TX Clock Polarity */
+#define SSI_STCR_TFSI (1 << 2) /* TX Frame Sync Invert */
+#define SSI_STCR_TFSL (1 << 1) /* TX Frame Sync Length */
+#define SSI_STCR_TEFS (1 << 0) /* TX Early Frame Sync */
+
+#define IMX51_SSI_SRCR_REG 0x0020 /* SSI RX Configuration Register */
+#define SSI_SRCR_RXEXT (1 << 10) /* RX Data Extension */
+#define SSI_SRCR_RXBIT0 (1 << 9) /* RX Bit 0 */
+#define SSI_SRCR_RFEN1 (1 << 8) /* RX FIFO Enable 1 */
+#define SSI_SRCR_RFEN0 (1 << 7) /* RX FIFO Enable 0 */
+#define SSI_SRCR_RFDIR (1 << 6) /* RX Frame Direction */
+#define SSI_SRCR_RXDIR (1 << 5) /* RX Clock Direction */
+#define SSI_SRCR_RSHFD (1 << 4) /* RX Shift Direction */
+#define SSI_SRCR_RSCKP (1 << 3) /* RX Clock Polarity */
+#define SSI_SRCR_RFSI (1 << 2) /* RX Frame Sync Invert */
+#define SSI_SRCR_RFSL (1 << 1) /* RX Frame Sync Length */
+#define SSI_SRCR_REFS (1 << 0) /* RX Early Frame Sync */
+
+#define IMX51_SSI_STCCR_REG 0x0024 /* TX Clock Control */
+#define IMX51_SSI_SRCCR_REG 0x0028 /* RX Clock Control */
+#define SSI_SXCCR_DIV2 (1 << 18) /* Divide By 2 */
+#define SSI_SXCCR_PSR (1 << 17) /* Prescaler Range */
+#define SSI_SXCCR_WL_MASK 0x0001e000
+#define SSI_SXCCR_WL_SHIFT 13 /* Word Length Control */
+#define SSI_SXCCR_DC_MASK 0x00001f00
+#define SSI_SXCCR_DC_SHIFT 8 /* Frame Rate Divider */
+#define SSI_SXCCR_PM_MASK 0x000000ff
+#define SSI_SXCCR_PM_SHIFT 0 /* Prescaler Modulus */
+
+#define IMX51_SSI_SFCSR_REG 0x002C /* SSI FIFO Control/Status Register */
+#define SSI_SFCSR_RFCNT1_MASK 0xf0000000
+#define SSI_SFCSR_RFCNT1_SHIFT 28 /* RX FIFO Counter 1 */
+#define SSI_SFCSR_TFCNT1_MASK 0x0f000000
+#define SSI_SFCSR_TFCNT1_SHIFT 24 /* TX FIFO Counter 1 */
+#define SSI_SFCSR_RFWM1_MASK 0x00f00000
+#define SSI_SFCSR_RFWM1_SHIFT 20 /* RX FIFO Full WaterMark 1 */
+#define SSI_SFCSR_TFWM1_MASK 0x000f0000
+#define SSI_SFCSR_TFWM1_SHIFT 16 /* TX FIFO Empty WaterMark 1 */
+#define SSI_SFCSR_RFCNT0_MASK 0x0000f000
+#define SSI_SFCSR_RFCNT0_SHIFT 12 /* RX FIFO Counter 0 */
+#define SSI_SFCSR_TFCNT0_MASK 0x00000f00
+#define SSI_SFCSR_TFCNT0_SHIFT 8 /* TX FIFO Counter 0 */
+#define SSI_SFCSR_RFWM0_MASK 0x000000f0
+#define SSI_SFCSR_RFWM0_SHIFT 4 /* RX FIFO Full WaterMark 0 */
+#define SSI_SFCSR_TFWM0_MASK 0x0000000f
+#define SSI_SFCSR_TFWM0_SHIFT 0 /* TX FIFO Empty WaterMark 0 */
+
+#define IMX51_SSI_STR_REG 0x0030 /* SSI Test Register1 */
+#define SSI_STR_TEST (1 << 15) /* Test Mode */
+#define SSI_STR_RCK2TCK (1 << 14) /* RX<->TX Clock Loop Back */
+#define SSI_STR_RFS2TFS (1 << 13) /* RX<->TX Frame Loop Back */
+#define SSI_STR_RXSTATE_MASK 0x00001f00
+#define SSI_STR_RXSTATE_SHIFT 8 /* RXer State Machine Status */
+#define SSI_STR_TXD2RXD (1 << 7) /* TX<->RX Data Loop Back */
+#define SSI_STR_TCK2RCK (1 << 6) /* TX<->RX Clock Loop Back */
+#define SSI_STR_TFS2RFS (1 << 5) /* TX<->RX Frame Loop Back */
+#define SSI_STR_TXSTATE_MASK 0x0000001f
+#define SSI_STR_TXSTATE_SHIFT 0 /* TXer State Machine Status */
+
+#define IMX51_SSI_SOR_REG 0x0034 /* SSI Option Register2 */
+#define SSI_SOR_CLKOFF (1 << 6) /* Clock Off */
+#define SSI_SOR_RX_CLR (1 << 5) /* RXer Clear */
+#define SSI_SOR_TX_CLR (1 << 4) /* TXer Clear */
+#define SSI_SOR_INIT (1 << 3) /* Initialize */
+#define SSI_SOR_WAIT_MASK 0x00000006
+#define SSI_SOR_INIT_SHIFT 1 /* Wait */
+#define SSI_SOR_SYNRST (1 << 0) /* Frame Sync Reset */
+
+#define IMX51_SSI_SACNT_REG 0x0038 /* SSI AC97 Control Register */
+#define SSI_SACNT_FRDIV_MASK 0x000007e0
+#define SSI_SACNT_FRDIV_SHIFT 5 /* Frame Rate Divider */
+#define SSI_SACNT_WR (1 << 4) /* Write Command */
+#define SSI_SACNT_RD (1 << 3) /* Read Command */
+#define SSI_SACNT_TIF (1 << 2) /* Tag in FIFO */
+#define SSI_SACNT_FV (1 << 1) /* Fixed/Variable Operation */
+#define SSI_SACNT_AC97EN (1 << 0) /* AC97 Mode Enable */
+
+#define IMX51_SSI_SACADD_REG 0x003C /* SSI AC97 Command Address Register */
+#define SSI_SACADD_MASK 0x0007ffff
+#define IMX51_SSI_SACDAT_REG 0x0040 /* SSI AC97 Command Data Register */
+#define SSI_SACDAT_MASK 0x000fffff
+#define IMX51_SSI_SATAG_REG 0x0044 /* SSI AC97 Tag Register */
+#define SSI_SATAG_MASK 0x0000ffff
+#define IMX51_SSI_STMSK_REG 0x0048 /* SSI TX Time Slot Mask Register */
+#define IMX51_SSI_SRMSK_REG 0x004C /* SSI RX Time Slot Mask Register */
+#define IMX51_SSI_SACCST_REG 0x0050 /* SSI AC97 Channel Status Register */
+#define IMX51_SSI_SACCEN_REG 0x0054 /* SSI AC97 Channel Enable Register */
+#define IMX51_SSI_SACCDIS_REG 0x0058 /* SSI AC97 Channel Disable Register */
+#define SSI_SAC_MASK 0x000003ff /* SACCST,SACCEN,SACCDIS */
Property changes on: trunk/sys/arm/freescale/imx/imx51_ssireg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx51_tzicreg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx51_tzicreg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx51_tzicreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,86 @@
+/* $MidnightBSD$ */
+/* $NetBSD: imx51_tzicreg.h,v 1.1 2010/11/13 07:11:03 bsh Exp $ */
+/*
+ * Copyright (c) 2010 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx51_tzicreg.h 263455 2014-03-20 23:48:18Z dim $
+ */
+
+#ifndef _IMX51_TZICREG_H_
+#define _IMX51_TZICREG_H_
+
+#include <sys/cdefs.h>
+
+#define TZIC_SIZE 0x4000
+#define TZIC_INTCNTL 0x0000
+#define INTCNTL_NSEN_MASK 0x80000000
+#define INTCNTL_NSEN 0x00010000
+#define INTCNTL_EN 0x00000001
+#define TZIC_INTTYPE 0x0004
+#define TZIC_PRIOMASK 0x000c
+#define TZIC_SYNCCTRL 0x0010
+#define TZIC_DSMINT 0x0014
+#define TZIC_INTSEC(n) (0x0080 + 0x04 * (n))
+#define TZIC_ENSET(n) (0x0100 + 0x04 * (n))
+#define TZIC_ENCLEAR(n) (0x0180 + 0x04 * (n))
+#define TZIC_SRCSET(n) (0x0200 + 0x04 * (n))
+#define TZIC_SRCCLAR(n) (0x0280 + 0x04 * (n))
+#define TZIC_PRIORITY(n) (0x0400 + 0x04 * (n))
+#define TZIC_PND(n) (0x0d00 + 0x04 * (n))
+#define TZIC_HIPND(n) (0x0d80 + 0x04 * (n))
+#define TZIC_WAKEUP(n) (0x0e00 + 0x04 * (n))
+#define TZIC_SWINT 0x0f00
+
+#define TZIC_INTNUM 128
+#endif /* _IMX51_TZICRREG_H_ */
Property changes on: trunk/sys/arm/freescale/imx/imx51_tzicreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx53_machdep.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx53_machdep.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx53_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,103 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx53_machdep.c 259365 2013-12-14 00:16:08Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/reboot.h>
+
+#include <vm/vm.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+#include <arm/freescale/imx/imx_machdep.h>
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+
+ /* XXX - Get rid of this stuff soon. */
+ boothowto |= RB_VERBOSE|RB_MULTIPLE;
+ bootverbose = 1;
+}
+
+void
+initarm_gpio_init(void)
+{
+
+}
+
+void
+initarm_late_init(void)
+{
+
+}
+
+/*
+ * Set up static device mappings. This is hand-optimized platform-specific
+ * config data which covers most of the common on-chip devices with a few 1MB
+ * section mappings.
+ *
+ * Notably missing are entries for GPU, IPU, in general anything video related.
+ */
+int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(0x50000000, 0x00100000);
+ arm_devmap_add_entry(0x53f00000, 0x00100000);
+ arm_devmap_add_entry(0x63f00000, 0x00100000);
+
+ return (0);
+}
+
+void
+cpu_reset(void)
+{
+
+ imx_wdog_cpu_reset(0x53F98000);
+}
+
+u_int imx_soc_type()
+{
+ return (IMXSOC_53);
+}
+
+
Property changes on: trunk/sys/arm/freescale/imx/imx53_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_anatop.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_anatop.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_anatop.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,810 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * Copyright (c) 2014 Steven Lawrance <stl at koffein.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_anatop.c 294678 2016-01-24 19:34:05Z ian $");
+
+/*
+ * Analog PLL and power regulator driver for Freescale i.MX6 family of SoCs.
+ * Also, temperature montoring and cpu frequency control. It was Freescale who
+ * kitchen-sinked this device, not us. :)
+ *
+ * We don't really do anything with analog PLLs, but the registers for
+ * controlling them belong to the same block as the power regulator registers.
+ * Since the newbus hierarchy makes it hard for anyone other than us to get at
+ * them, we just export a couple public functions to allow the imx6 CCM clock
+ * driver to read and write those registers.
+ *
+ * We also don't do anything about power regulation yet, but when the need
+ * arises, this would be the place for that code to live.
+ *
+ * I have no idea where the "anatop" name comes from. It's in the standard DTS
+ * source describing i.MX6 SoCs, and in the linux and u-boot code which comes
+ * from Freescale, but it's not in the SoC manual.
+ *
+ * Note that temperature values throughout this code are handled in two types of
+ * units. Items with '_cnt' in the name use the hardware temperature count
+ * units (higher counts are lower temperatures). Items with '_val' in the name
+ * are deci-Celcius, which are converted to/from deci-Kelvins in the sysctl
+ * handlers (dK is the standard unit for temperature in sysctl).
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/sysctl.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/arm/mpcore_timervar.h>
+#include <arm/freescale/fsl_ocotpreg.h>
+#include <arm/freescale/fsl_ocotpvar.h>
+#include <arm/freescale/imx/imx_ccmvar.h>
+#include <arm/freescale/imx/imx_machdep.h>
+#include <arm/freescale/imx/imx6_anatopreg.h>
+#include <arm/freescale/imx/imx6_anatopvar.h>
+
+static struct resource_spec imx6_anatop_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+#define MEMRES 0
+#define IRQRES 1
+
+struct imx6_anatop_softc {
+ device_t dev;
+ struct resource *res[2];
+ struct intr_config_hook
+ intr_setup_hook;
+ uint32_t cpu_curmhz;
+ uint32_t cpu_curmv;
+ uint32_t cpu_minmhz;
+ uint32_t cpu_minmv;
+ uint32_t cpu_maxmhz;
+ uint32_t cpu_maxmv;
+ uint32_t cpu_maxmhz_hw;
+ boolean_t cpu_overclock_enable;
+ boolean_t cpu_init_done;
+ uint32_t refosc_mhz;
+ void *temp_intrhand;
+ uint32_t temp_high_val;
+ uint32_t temp_high_cnt;
+ uint32_t temp_last_cnt;
+ uint32_t temp_room_cnt;
+ struct callout temp_throttle_callout;
+ sbintime_t temp_throttle_delay;
+ uint32_t temp_throttle_reset_cnt;
+ uint32_t temp_throttle_trigger_cnt;
+ uint32_t temp_throttle_val;
+};
+
+static struct imx6_anatop_softc *imx6_anatop_sc;
+
+/*
+ * Table of "operating points".
+ * These are combinations of frequency and voltage blessed by Freescale.
+ * While the datasheet says the ARM voltage can be as low as 925mV at
+ * 396MHz, it also says that the ARM and SOC voltages can't differ by
+ * more than 200mV, and the minimum SOC voltage is 1150mV, so that
+ * dictates the 950mV entry in this table.
+ */
+static struct oppt {
+ uint32_t mhz;
+ uint32_t mv;
+} imx6_oppt_table[] = {
+ { 396, 950},
+ { 792, 1150},
+ { 852, 1225},
+ { 996, 1225},
+ {1200, 1275},
+};
+
+/*
+ * Table of CPU max frequencies. This is used to translate the max frequency
+ * value (0-3) from the ocotp CFG3 register into a mhz value that can be looked
+ * up in the operating points table.
+ */
+static uint32_t imx6_ocotp_mhz_tab[] = {792, 852, 996, 1200};
+
+#define TZ_ZEROC 2732 /* deci-Kelvin <-> deci-Celcius offset. */
+
+uint32_t
+imx6_anatop_read_4(bus_size_t offset)
+{
+
+ KASSERT(imx6_anatop_sc != NULL, ("imx6_anatop_read_4 sc NULL"));
+
+ return (bus_read_4(imx6_anatop_sc->res[MEMRES], offset));
+}
+
+void
+imx6_anatop_write_4(bus_size_t offset, uint32_t value)
+{
+
+ KASSERT(imx6_anatop_sc != NULL, ("imx6_anatop_write_4 sc NULL"));
+
+ bus_write_4(imx6_anatop_sc->res[MEMRES], offset, value);
+}
+
+static void
+vdd_set(struct imx6_anatop_softc *sc, int mv)
+{
+ int newtarg, newtargSoc, oldtarg;
+ uint32_t delay, pmureg;
+ static boolean_t init_done = false;
+
+ /*
+ * The datasheet says VDD_PU and VDD_SOC must be equal, and VDD_ARM
+ * can't be more than 50mV above or 200mV below them. We keep them the
+ * same except in the case of the lowest operating point, which is
+ * handled as a special case below.
+ */
+
+ pmureg = imx6_anatop_read_4(IMX6_ANALOG_PMU_REG_CORE);
+ oldtarg = pmureg & IMX6_ANALOG_PMU_REG0_TARG_MASK;
+
+ /* Convert mV to target value. Clamp target to valid range. */
+ if (mv < 725)
+ newtarg = 0x00;
+ else if (mv > 1450)
+ newtarg = 0x1F;
+ else
+ newtarg = (mv - 700) / 25;
+
+ /*
+ * The SOC voltage can't go below 1150mV, and thus because of the 200mV
+ * rule, the ARM voltage can't go below 950mV. The 950 is encoded in
+ * our oppt table, here we handle the SOC 1150 rule as a special case.
+ * (1150-700/25=18).
+ */
+ newtargSoc = (newtarg < 18) ? 18 : newtarg;
+
+ /*
+ * The first time through the 3 voltages might not be equal so use a
+ * long conservative delay. After that we need to delay 3uS for every
+ * 25mV step upward; we actually delay 6uS because empirically, it works
+ * and the 3uS per step recommended by the docs doesn't (3uS fails when
+ * going from 400->1200, but works for smaller changes).
+ */
+ if (init_done) {
+ if (newtarg == oldtarg)
+ return;
+ else if (newtarg > oldtarg)
+ delay = (newtarg - oldtarg) * 6;
+ else
+ delay = 0;
+ } else {
+ delay = (700 / 25) * 6;
+ init_done = true;
+ }
+
+ /*
+ * Make the change and wait for it to take effect.
+ */
+ pmureg &= ~(IMX6_ANALOG_PMU_REG0_TARG_MASK |
+ IMX6_ANALOG_PMU_REG1_TARG_MASK |
+ IMX6_ANALOG_PMU_REG2_TARG_MASK);
+
+ pmureg |= newtarg << IMX6_ANALOG_PMU_REG0_TARG_SHIFT;
+ pmureg |= newtarg << IMX6_ANALOG_PMU_REG1_TARG_SHIFT;
+ pmureg |= newtargSoc << IMX6_ANALOG_PMU_REG2_TARG_SHIFT;
+
+ imx6_anatop_write_4(IMX6_ANALOG_PMU_REG_CORE, pmureg);
+ DELAY(delay);
+ sc->cpu_curmv = newtarg * 25 + 700;
+}
+
+static inline uint32_t
+cpufreq_mhz_from_div(struct imx6_anatop_softc *sc, uint32_t corediv,
+ uint32_t plldiv)
+{
+
+ return ((sc->refosc_mhz * (plldiv / 2)) / (corediv + 1));
+}
+
+static inline void
+cpufreq_mhz_to_div(struct imx6_anatop_softc *sc, uint32_t cpu_mhz,
+ uint32_t *corediv, uint32_t *plldiv)
+{
+
+ *corediv = (cpu_mhz < 650) ? 1 : 0;
+ *plldiv = ((*corediv + 1) * cpu_mhz) / (sc->refosc_mhz / 2);
+}
+
+static inline uint32_t
+cpufreq_actual_mhz(struct imx6_anatop_softc *sc, uint32_t cpu_mhz)
+{
+ uint32_t corediv, plldiv;
+
+ cpufreq_mhz_to_div(sc, cpu_mhz, &corediv, &plldiv);
+ return (cpufreq_mhz_from_div(sc, corediv, plldiv));
+}
+
+static struct oppt *
+cpufreq_nearest_oppt(struct imx6_anatop_softc *sc, uint32_t cpu_newmhz)
+{
+ int d, diff, i, nearest;
+
+ if (cpu_newmhz > sc->cpu_maxmhz_hw && !sc->cpu_overclock_enable)
+ cpu_newmhz = sc->cpu_maxmhz_hw;
+
+ diff = INT_MAX;
+ nearest = 0;
+ for (i = 0; i < nitems(imx6_oppt_table); ++i) {
+ d = abs((int)cpu_newmhz - (int)imx6_oppt_table[i].mhz);
+ if (diff > d) {
+ diff = d;
+ nearest = i;
+ }
+ }
+ return (&imx6_oppt_table[nearest]);
+}
+
+static void
+cpufreq_set_clock(struct imx6_anatop_softc * sc, struct oppt *op)
+{
+ uint32_t corediv, plldiv, timeout, wrk32;
+
+ /* If increasing the frequency, we must first increase the voltage. */
+ if (op->mhz > sc->cpu_curmhz) {
+ vdd_set(sc, op->mv);
+ }
+
+ /*
+ * I can't find a documented procedure for changing the ARM PLL divisor,
+ * but some trial and error came up with this:
+ * - Set the bypass clock source to REF_CLK_24M (source #0).
+ * - Set the PLL into bypass mode; cpu should now be running at 24mhz.
+ * - Change the divisor.
+ * - Wait for the LOCK bit to come on; it takes ~50 loop iterations.
+ * - Turn off bypass mode; cpu should now be running at the new speed.
+ */
+ cpufreq_mhz_to_div(sc, op->mhz, &corediv, &plldiv);
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_CLR,
+ IMX6_ANALOG_CCM_PLL_ARM_CLK_SRC_MASK);
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_SET,
+ IMX6_ANALOG_CCM_PLL_ARM_BYPASS);
+
+ wrk32 = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM);
+ wrk32 &= ~IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK;
+ wrk32 |= plldiv;
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM, wrk32);
+
+ timeout = 10000;
+ while ((imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM) &
+ IMX6_ANALOG_CCM_PLL_ARM_LOCK) == 0)
+ if (--timeout == 0)
+ panic("imx6_set_cpu_clock(): PLL never locked");
+
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_CLR,
+ IMX6_ANALOG_CCM_PLL_ARM_BYPASS);
+ imx_ccm_set_cacrr(corediv);
+
+ /* If lowering the frequency, it is now safe to lower the voltage. */
+ if (op->mhz < sc->cpu_curmhz)
+ vdd_set(sc, op->mv);
+ sc->cpu_curmhz = op->mhz;
+
+ /* Tell the mpcore timer that its frequency has changed. */
+ arm_tmr_change_frequency(
+ cpufreq_actual_mhz(sc, sc->cpu_curmhz) * 1000000 / 2);
+}
+
+static int
+cpufreq_sysctl_minmhz(SYSCTL_HANDLER_ARGS)
+{
+ struct imx6_anatop_softc *sc;
+ struct oppt * op;
+ uint32_t temp;
+ int err;
+
+ sc = arg1;
+
+ temp = sc->cpu_minmhz;
+ err = sysctl_handle_int(oidp, &temp, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+
+ op = cpufreq_nearest_oppt(sc, temp);
+ if (op->mhz > sc->cpu_maxmhz)
+ return (ERANGE);
+ else if (op->mhz == sc->cpu_minmhz)
+ return (0);
+
+ /*
+ * Value changed, update softc. If the new min is higher than the
+ * current speed, raise the current speed to match.
+ */
+ sc->cpu_minmhz = op->mhz;
+ if (sc->cpu_minmhz > sc->cpu_curmhz) {
+ cpufreq_set_clock(sc, op);
+ }
+ return (err);
+}
+
+static int
+cpufreq_sysctl_maxmhz(SYSCTL_HANDLER_ARGS)
+{
+ struct imx6_anatop_softc *sc;
+ struct oppt * op;
+ uint32_t temp;
+ int err;
+
+ sc = arg1;
+
+ temp = sc->cpu_maxmhz;
+ err = sysctl_handle_int(oidp, &temp, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+
+ op = cpufreq_nearest_oppt(sc, temp);
+ if (op->mhz < sc->cpu_minmhz)
+ return (ERANGE);
+ else if (op->mhz == sc->cpu_maxmhz)
+ return (0);
+
+ /*
+ * Value changed, update softc and hardware. The hardware update is
+ * unconditional. We always try to run at max speed, so any change of
+ * the max means we need to change the current speed too, regardless of
+ * whether it is higher or lower than the old max.
+ */
+ sc->cpu_maxmhz = op->mhz;
+ cpufreq_set_clock(sc, op);
+
+ return (err);
+}
+
+static void
+cpufreq_initialize(struct imx6_anatop_softc *sc)
+{
+ uint32_t cfg3speed;
+ struct oppt * op;
+
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
+ OID_AUTO, "cpu_mhz", CTLFLAG_RD, &sc->cpu_curmhz, 0,
+ "CPU frequency");
+
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
+ OID_AUTO, "cpu_minmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
+ cpufreq_sysctl_minmhz, "IU", "Minimum CPU frequency");
+
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
+ OID_AUTO, "cpu_maxmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
+ cpufreq_sysctl_maxmhz, "IU", "Maximum CPU frequency");
+
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
+ OID_AUTO, "cpu_maxmhz_hw", CTLFLAG_RD, &sc->cpu_maxmhz_hw, 0,
+ "Maximum CPU frequency allowed by hardware");
+
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
+ OID_AUTO, "cpu_overclock_enable", CTLFLAG_RWTUN,
+ &sc->cpu_overclock_enable, 0,
+ "Allow setting CPU frequency higher than cpu_maxmhz_hw");
+
+ /*
+ * XXX 24mhz shouldn't be hard-coded, should get this from imx6_ccm
+ * (even though in the real world it will always be 24mhz). Oh wait a
+ * sec, I never wrote imx6_ccm.
+ */
+ sc->refosc_mhz = 24;
+
+ /*
+ * Get the maximum speed this cpu can be set to. The values in the
+ * OCOTP CFG3 register are not documented in the reference manual.
+ * The following info was in an archived email found via web search:
+ * - 2b'11: 1200000000Hz;
+ * - 2b'10: 996000000Hz;
+ * - 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
+ * - 2b'00: 792000000Hz;
+ * The default hardware max speed can be overridden by a tunable.
+ */
+ cfg3speed = (fsl_ocotp_read_4(FSL_OCOTP_CFG3) &
+ FSL_OCOTP_CFG3_SPEED_MASK) >> FSL_OCOTP_CFG3_SPEED_SHIFT;
+ sc->cpu_maxmhz_hw = imx6_ocotp_mhz_tab[cfg3speed];
+ sc->cpu_maxmhz = sc->cpu_maxmhz_hw;
+
+ TUNABLE_INT_FETCH("hw.imx6.cpu_overclock_enable",
+ &sc->cpu_overclock_enable);
+
+ TUNABLE_INT_FETCH("hw.imx6.cpu_minmhz", &sc->cpu_minmhz);
+ op = cpufreq_nearest_oppt(sc, sc->cpu_minmhz);
+ sc->cpu_minmhz = op->mhz;
+ sc->cpu_minmv = op->mv;
+
+ TUNABLE_INT_FETCH("hw.imx6.cpu_maxmhz", &sc->cpu_maxmhz);
+ op = cpufreq_nearest_oppt(sc, sc->cpu_maxmhz);
+ sc->cpu_maxmhz = op->mhz;
+ sc->cpu_maxmv = op->mv;
+
+ /*
+ * Set the CPU to maximum speed.
+ *
+ * We won't have thermal throttling until interrupts are enabled, but we
+ * want to run at full speed through all the device init stuff. This
+ * basically assumes that a single core can't overheat before interrupts
+ * are enabled; empirical testing shows that to be a safe assumption.
+ */
+ cpufreq_set_clock(sc, op);
+}
+
+static inline uint32_t
+temp_from_count(struct imx6_anatop_softc *sc, uint32_t count)
+{
+
+ return (((sc->temp_high_val - (count - sc->temp_high_cnt) *
+ (sc->temp_high_val - 250) /
+ (sc->temp_room_cnt - sc->temp_high_cnt))));
+}
+
+static inline uint32_t
+temp_to_count(struct imx6_anatop_softc *sc, uint32_t temp)
+{
+
+ return ((sc->temp_room_cnt - sc->temp_high_cnt) *
+ (sc->temp_high_val - temp) / (sc->temp_high_val - 250) +
+ sc->temp_high_cnt);
+}
+
+static void
+temp_update_count(struct imx6_anatop_softc *sc)
+{
+ uint32_t val;
+
+ val = imx6_anatop_read_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0);
+ if (!(val & IMX6_ANALOG_TEMPMON_TEMPSENSE0_VALID))
+ return;
+ sc->temp_last_cnt =
+ (val & IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_MASK) >>
+ IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT;
+}
+
+static int
+temp_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ struct imx6_anatop_softc *sc = arg1;
+ uint32_t t;
+
+ temp_update_count(sc);
+
+ t = temp_from_count(sc, sc->temp_last_cnt) + TZ_ZEROC;
+
+ return (sysctl_handle_int(oidp, &t, 0, req));
+}
+
+static int
+temp_throttle_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ struct imx6_anatop_softc *sc = arg1;
+ int err;
+ uint32_t temp;
+
+ temp = sc->temp_throttle_val + TZ_ZEROC;
+ err = sysctl_handle_int(oidp, &temp, 0, req);
+ if (temp < TZ_ZEROC)
+ return (ERANGE);
+ temp -= TZ_ZEROC;
+ if (err != 0 || req->newptr == NULL || temp == sc->temp_throttle_val)
+ return (err);
+
+ /* Value changed, update counts in softc and hardware. */
+ sc->temp_throttle_val = temp;
+ sc->temp_throttle_trigger_cnt = temp_to_count(sc, sc->temp_throttle_val);
+ sc->temp_throttle_reset_cnt = temp_to_count(sc, sc->temp_throttle_val - 100);
+ imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0_CLR,
+ IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_MASK);
+ imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0_SET,
+ (sc->temp_throttle_trigger_cnt <<
+ IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT));
+ return (err);
+}
+
+static void
+tempmon_gofast(struct imx6_anatop_softc *sc)
+{
+
+ if (sc->cpu_curmhz < sc->cpu_maxmhz) {
+ cpufreq_set_clock(sc, cpufreq_nearest_oppt(sc, sc->cpu_maxmhz));
+ }
+}
+
+static void
+tempmon_goslow(struct imx6_anatop_softc *sc)
+{
+
+ if (sc->cpu_curmhz > sc->cpu_minmhz) {
+ cpufreq_set_clock(sc, cpufreq_nearest_oppt(sc, sc->cpu_minmhz));
+ }
+}
+
+static int
+tempmon_intr(void *arg)
+{
+ struct imx6_anatop_softc *sc = arg;
+
+ /*
+ * XXX Note that this code doesn't currently run (for some mysterious
+ * reason we just never get an interrupt), so the real monitoring is
+ * done by tempmon_throttle_check().
+ */
+ tempmon_goslow(sc);
+ /* XXX Schedule callout to speed back up eventually. */
+ return (FILTER_HANDLED);
+}
+
+static void
+tempmon_throttle_check(void *arg)
+{
+ struct imx6_anatop_softc *sc = arg;
+
+ /* Lower counts are higher temperatures. */
+ if (sc->temp_last_cnt < sc->temp_throttle_trigger_cnt)
+ tempmon_goslow(sc);
+ else if (sc->temp_last_cnt > (sc->temp_throttle_reset_cnt))
+ tempmon_gofast(sc);
+
+ callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay,
+ 0, tempmon_throttle_check, sc, 0);
+
+}
+
+static void
+initialize_tempmon(struct imx6_anatop_softc *sc)
+{
+ uint32_t cal;
+
+ /*
+ * Fetch calibration data: a sensor count at room temperature (25C),
+ * a sensor count at a high temperature, and that temperature
+ */
+ cal = fsl_ocotp_read_4(FSL_OCOTP_ANA1);
+ sc->temp_room_cnt = (cal & 0xFFF00000) >> 20;
+ sc->temp_high_cnt = (cal & 0x000FFF00) >> 8;
+ sc->temp_high_val = (cal & 0x000000FF) * 10;
+
+ /*
+ * Throttle to a lower cpu freq at 10C below the "hot" temperature, and
+ * reset back to max cpu freq at 5C below the trigger.
+ */
+ sc->temp_throttle_val = sc->temp_high_val - 100;
+ sc->temp_throttle_trigger_cnt =
+ temp_to_count(sc, sc->temp_throttle_val);
+ sc->temp_throttle_reset_cnt =
+ temp_to_count(sc, sc->temp_throttle_val - 50);
+
+ /*
+ * Set the sensor to sample automatically at 16Hz (32.768KHz/0x800), set
+ * the throttle count, and begin making measurements.
+ */
+ imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE1, 0x0800);
+ imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0,
+ (sc->temp_throttle_trigger_cnt <<
+ IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT) |
+ IMX6_ANALOG_TEMPMON_TEMPSENSE0_MEASURE);
+
+ /*
+ * XXX Note that the alarm-interrupt feature isn't working yet, so
+ * we'll use a callout handler to check at 10Hz. Make sure we have an
+ * initial temperature reading before starting up the callouts so we
+ * don't get a bogus reading of zero.
+ */
+ while (sc->temp_last_cnt == 0)
+ temp_update_count(sc);
+ sc->temp_throttle_delay = 100 * SBT_1MS;
+ callout_init(&sc->temp_throttle_callout, 0);
+ callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay,
+ 0, tempmon_throttle_check, sc, 0);
+
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
+ OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
+ temp_sysctl_handler, "IK", "Current die temperature");
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
+ OID_AUTO, "throttle_temperature", CTLTYPE_INT | CTLFLAG_RW, sc,
+ 0, temp_throttle_sysctl_handler, "IK",
+ "Throttle CPU when exceeding this temperature");
+}
+
+static void
+intr_setup(void *arg)
+{
+ struct imx6_anatop_softc *sc;
+
+ sc = arg;
+ bus_setup_intr(sc->dev, sc->res[IRQRES], INTR_TYPE_MISC | INTR_MPSAFE,
+ tempmon_intr, NULL, sc, &sc->temp_intrhand);
+ config_intrhook_disestablish(&sc->intr_setup_hook);
+}
+
+static void
+imx6_anatop_new_pass(device_t dev)
+{
+ struct imx6_anatop_softc *sc;
+ const int cpu_init_pass = BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE;
+
+ /*
+ * We attach during BUS_PASS_BUS (because some day we will be a
+ * simplebus that has regulator devices as children), but some of our
+ * init work cannot be done until BUS_PASS_CPU (we rely on other devices
+ * that attach on the CPU pass).
+ */
+ sc = device_get_softc(dev);
+ if (!sc->cpu_init_done && bus_current_pass >= cpu_init_pass) {
+ sc->cpu_init_done = true;
+ cpufreq_initialize(sc);
+ initialize_tempmon(sc);
+ if (bootverbose) {
+ device_printf(sc->dev, "CPU %uMHz @ %umV\n",
+ sc->cpu_curmhz, sc->cpu_curmv);
+ }
+ }
+ bus_generic_new_pass(dev);
+}
+
+static int
+imx6_anatop_detach(device_t dev)
+{
+
+ /* This device can never detach. */
+ return (EBUSY);
+}
+
+static int
+imx6_anatop_attach(device_t dev)
+{
+ struct imx6_anatop_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ /* Allocate bus_space resources. */
+ if (bus_alloc_resources(dev, imx6_anatop_spec, sc->res)) {
+ device_printf(dev, "Cannot allocate resources\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ sc->intr_setup_hook.ich_func = intr_setup;
+ sc->intr_setup_hook.ich_arg = sc;
+ config_intrhook_establish(&sc->intr_setup_hook);
+
+ SYSCTL_ADD_UINT(device_get_sysctl_ctx(sc->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
+ OID_AUTO, "cpu_voltage", CTLFLAG_RD,
+ &sc->cpu_curmv, 0, "Current CPU voltage in millivolts");
+
+ imx6_anatop_sc = sc;
+
+ /*
+ * Other code seen on the net sets this SELFBIASOFF flag around the same
+ * time the temperature sensor is set up, although it's unclear how the
+ * two are related (if at all).
+ */
+ imx6_anatop_write_4(IMX6_ANALOG_PMU_MISC0_SET,
+ IMX6_ANALOG_PMU_MISC0_SELFBIASOFF);
+
+ /*
+ * Some day, when we're ready to deal with the actual anatop regulators
+ * that are described in fdt data as children of this "bus", this would
+ * be the place to invoke a simplebus helper routine to instantiate the
+ * children from the fdt data.
+ */
+
+ err = 0;
+
+out:
+
+ if (err != 0) {
+ bus_release_resources(dev, imx6_anatop_spec, sc->res);
+ }
+
+ return (err);
+}
+
+uint32_t
+pll4_configure_output(uint32_t mfi, uint32_t mfn, uint32_t mfd)
+{
+ int reg;
+
+ /*
+ * Audio PLL (PLL4).
+ * PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM)
+ */
+
+ reg = (IMX6_ANALOG_CCM_PLL_AUDIO_ENABLE);
+ reg &= ~(IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_MASK << \
+ IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_SHIFT);
+ reg |= (mfi << IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_SHIFT);
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_AUDIO, reg);
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_AUDIO_NUM, mfn);
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_AUDIO_DENOM, mfd);
+
+ return (0);
+}
+
+static int
+imx6_anatop_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "fsl,imx6q-anatop") == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale i.MX6 Analog PLLs and Power");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+uint32_t
+imx6_get_cpu_clock()
+{
+ uint32_t corediv, plldiv;
+
+ corediv = imx_ccm_get_cacrr();
+ plldiv = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM) &
+ IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK;
+ return (cpufreq_mhz_from_div(imx6_anatop_sc, corediv, plldiv));
+}
+
+static device_method_t imx6_anatop_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, imx6_anatop_probe),
+ DEVMETHOD(device_attach, imx6_anatop_attach),
+ DEVMETHOD(device_detach, imx6_anatop_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_new_pass, imx6_anatop_new_pass),
+
+ DEVMETHOD_END
+};
+
+static driver_t imx6_anatop_driver = {
+ "imx6_anatop",
+ imx6_anatop_methods,
+ sizeof(struct imx6_anatop_softc)
+};
+
+static devclass_t imx6_anatop_devclass;
+
+EARLY_DRIVER_MODULE(imx6_anatop, simplebus, imx6_anatop_driver,
+ imx6_anatop_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(imx6_anatop, ofwbus, imx6_anatop_driver,
+ imx6_anatop_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+
Property changes on: trunk/sys/arm/freescale/imx/imx6_anatop.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_anatopreg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_anatopreg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_anatopreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,192 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx6_anatopreg.h 283500 2015-05-24 18:59:45Z ian $
+ */
+
+#ifndef IMX6_ANATOPREG_H
+#define IMX6_ANATOPREG_H
+
+#define IMX6_ANALOG_CCM_PLL_ARM 0x000
+#define IMX6_ANALOG_CCM_PLL_ARM_SET 0x004
+#define IMX6_ANALOG_CCM_PLL_ARM_CLR 0x008
+#define IMX6_ANALOG_CCM_PLL_ARM_TOG 0x00C
+#define IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK 0x7F
+#define IMX6_ANALOG_CCM_PLL_ARM_LOCK (1U << 31)
+#define IMX6_ANALOG_CCM_PLL_ARM_BYPASS (1 << 16)
+#define IMX6_ANALOG_CCM_PLL_ARM_CLK_SRC_MASK (0x03 << 16)
+#define IMX6_ANALOG_CCM_PLL_USB1 0x010
+#define IMX6_ANALOG_CCM_PLL_USB1_SET 0x014
+#define IMX6_ANALOG_CCM_PLL_USB1_CLR 0x018
+#define IMX6_ANALOG_CCM_PLL_USB1_TOG 0x01C
+#define IMX6_ANALOG_CCM_PLL_USB_LOCK (1U << 31)
+#define IMX6_ANALOG_CCM_PLL_USB_BYPASS (1 << 16)
+#define IMX6_ANALOG_CCM_PLL_USB_ENABLE (1 << 13)
+#define IMX6_ANALOG_CCM_PLL_USB_POWER (1 << 12)
+#define IMX6_ANALOG_CCM_PLL_USB_EN_USB_CLKS (1 << 6)
+#define IMX6_ANALOG_CCM_PLL_USB2 0x020
+#define IMX6_ANALOG_CCM_PLL_USB2_SET 0x024
+#define IMX6_ANALOG_CCM_PLL_USB2_CLR 0x028
+#define IMX6_ANALOG_CCM_PLL_USB2_TOG 0x02C
+#define IMX6_ANALOG_CCM_PLL_SYS 0x030
+#define IMX6_ANALOG_CCM_PLL_SYS_SET 0x034
+#define IMX6_ANALOG_CCM_PLL_SYS_CLR 0x038
+#define IMX6_ANALOG_CCM_PLL_SYS_TOG 0x03C
+#define IMX6_ANALOG_CCM_PLL_SYS_SS 0x040
+#define IMX6_ANALOG_CCM_PLL_SYS_NUM 0x050
+#define IMX6_ANALOG_CCM_PLL_SYS_DENOM 0x060
+#define IMX6_ANALOG_CCM_PLL_AUDIO 0x070
+#define IMX6_ANALOG_CCM_PLL_AUDIO_ENABLE (1 << 13)
+#define IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_SHIFT 0
+#define IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_MASK 0x7f
+#define IMX6_ANALOG_CCM_PLL_AUDIO_SET 0x074
+#define IMX6_ANALOG_CCM_PLL_AUDIO_CLR 0x078
+#define IMX6_ANALOG_CCM_PLL_AUDIO_TOG 0x07C
+#define IMX6_ANALOG_CCM_PLL_AUDIO_NUM 0x080
+#define IMX6_ANALOG_CCM_PLL_AUDIO_DENOM 0x090
+#define IMX6_ANALOG_CCM_PLL_VIDEO 0x0A0
+#define IMX6_ANALOG_CCM_PLL_VIDEO_SET 0x0A4
+#define IMX6_ANALOG_CCM_PLL_VIDEO_CLR 0x0A8
+#define IMX6_ANALOG_CCM_PLL_VIDEO_TOG 0x0AC
+#define IMX6_ANALOG_CCM_PLL_VIDEO_NUM 0x0B0
+#define IMX6_ANALOG_CCM_PLL_VIDEO_DENOM 0x0C0
+#define IMX6_ANALOG_CCM_PLL_MLB 0x0D0
+#define IMX6_ANALOG_CCM_PLL_MLB_SET 0x0D4
+#define IMX6_ANALOG_CCM_PLL_MLB_CLR 0x0D8
+#define IMX6_ANALOG_CCM_PLL_MLB_TOG 0x0DC
+#define IMX6_ANALOG_CCM_PLL_ENET 0x0E0
+#define IMX6_ANALOG_CCM_PLL_ENET_SET 0x0E4
+#define IMX6_ANALOG_CCM_PLL_ENET_CLR 0x0E8
+#define IMX6_ANALOG_CCM_PLL_ENET_TOG 0x0EC
+#define IMX6_ANALOG_CCM_PFD_480 0x0F0
+#define IMX6_ANALOG_CCM_PFD_480_SET 0x0F4
+#define IMX6_ANALOG_CCM_PFD_480_CLR 0x0F8
+#define IMX6_ANALOG_CCM_PFD_480_TOG 0x0FC
+#define IMX6_ANALOG_CCM_PFD_528 0x100
+#define IMX6_ANALOG_CCM_PFD_528_SET 0x104
+#define IMX6_ANALOG_CCM_PFD_528_CLR 0x108
+#define IMX6_ANALOG_CCM_PFD_528_TOG 0x10C
+
+#define IMX6_ANALOG_PMU_REG_CORE 0x140
+#define IMX6_ANALOG_PMU_REG2_TARG_SHIFT 18
+#define IMX6_ANALOG_PMU_REG2_TARG_MASK \
+ (0x1f << IMX6_ANALOG_PMU_REG2_TARG_SHIFT)
+#define IMX6_ANALOG_PMU_REG1_TARG_SHIFT 9
+#define IMX6_ANALOG_PMU_REG1_TARG_MASK \
+ (0x1f << IMX6_ANALOG_PMU_REG1_TARG_SHIFT)
+#define IMX6_ANALOG_PMU_REG0_TARG_SHIFT 0
+#define IMX6_ANALOG_PMU_REG0_TARG_MASK \
+ (0x1f << IMX6_ANALOG_PMU_REG0_TARG_SHIFT)
+
+#define IMX6_ANALOG_PMU_MISC0 0x150
+#define IMX6_ANALOG_PMU_MISC0_SET 0x154
+#define IMX6_ANALOG_PMU_MISC0_CLR 0x158
+#define IMX6_ANALOG_PMU_MISC0_TOG 0x15C
+#define IMX6_ANALOG_PMU_MISC0_SELFBIASOFF (1 << 3)
+
+#define IMX6_ANALOG_PMU_MISC1 0x160
+#define IMX6_ANALOG_PMU_MISC1_SET 0x164
+#define IMX6_ANALOG_PMU_MISC1_CLR 0x168
+#define IMX6_ANALOG_PMU_MISC1_TOG 0x16C
+#define IMX6_ANALOG_PMU_MISC1_IRQ_TEMPSENSE (1 << 29)
+
+#define IMX6_ANALOG_PMU_MISC2 0x170
+#define IMX6_ANALOG_PMU_MISC2_SET 0x174
+#define IMX6_ANALOG_PMU_MISC2_CLR 0x178
+#define IMX6_ANALOG_PMU_MISC2_TOG 0x17C
+
+/*
+ * Note that the ANALOG_CCM_MISCn registers are the same as the PMU_MISCn
+ * registers; some bits conceptually belong to the PMU and some to the CCM.
+ */
+#define IMX6_ANALOG_CCM_MISC0 IMX6_ANALOG_PMU_MISC0
+#define IMX6_ANALOG_CCM_MISC0_SET IMX6_ANALOG_PMU_MISC0_SET
+#define IMX6_ANALOG_CCM_MISC0_CLR IMX6_ANALOG_PMU_MISC0_CLR
+#define IMX6_ANALOG_CCM_MISC0_TOG IMX6_ANALOG_PMU_MISC0_TOG
+
+#define IMX6_ANALOG_CCM_MISC2 IMX6_ANALOG_PMU_MISC2
+#define IMX6_ANALOG_CCM_MISC2_SET IMX6_ANALOG_PMU_MISC2_SET
+#define IMX6_ANALOG_CCM_MISC2_CLR IMX6_ANALOG_PMU_MISC2_CLR
+#define IMX6_ANALOG_CCM_MISC2_TOG IMX6_ANALOG_PMU_MISC2_TOG
+
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0 0x180
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_SET 0x184
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_CLR 0x188
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_TOG 0x18C
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_TOG 0x18C
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT 20
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_MASK \
+ (0xfff << IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT)
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT 8
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_MASK \
+ (0xfff << IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT)
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_VALID 0x4
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_MEASURE 0x2
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_POWER_DOWN 0x1
+
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE1 0x190
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE1_SET 0x194
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE1_CLR 0x198
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE1_TOG 0x19C
+
+#define IMX6_ANALOG_USB1_VBUS_DETECT 0x1A0
+#define IMX6_ANALOG_USB1_VBUS_DETECT_SET 0x1A4
+#define IMX6_ANALOG_USB1_VBUS_DETECT_CLR 0x1A8
+#define IMX6_ANALOG_USB1_VBUS_DETECT_TOG 0x1AC
+#define IMX6_ANALOG_USB1_CHRG_DETECT 0x1B0
+#define IMX6_ANALOG_USB1_CHRG_DETECT_SET 0x1B4
+#define IMX6_ANALOG_USB1_CHRG_DETECT_CLR 0x1B8
+#define IMX6_ANALOG_USB1_CHRG_DETECT_TOG 0x1BC
+#define IMX6_ANALOG_USB_CHRG_DETECT_N_ENABLE (1 << 20) /* EN_B */
+#define IMX6_ANALOG_USB_CHRG_DETECT_N_CHK_CHRG (1 << 19) /* CHK_CHRG_B */
+#define IMX6_ANALOG_USB_CHRG_DETECT_CHK_CONTACT (1 << 18)
+#define IMX6_ANALOG_USB1_VBUS_DETECT_STAT 0x1C0
+#define IMX6_ANALOG_USB1_CHRG_DETECT_STAT 0x1D0
+#define IMX6_ANALOG_USB1_MISC 0x1F0
+#define IMX6_ANALOG_USB1_MISC_SET 0x1F4
+#define IMX6_ANALOG_USB1_MISC_CLR 0x1F8
+#define IMX6_ANALOG_USB1_MISC_TOG 0x1FC
+#define IMX6_ANALOG_USB2_VBUS_DETECT 0x200
+#define IMX6_ANALOG_USB2_VBUS_DETECT_SET 0x204
+#define IMX6_ANALOG_USB2_VBUS_DETECT_CLR 0x208
+#define IMX6_ANALOG_USB2_VBUS_DETECT_TOG 0x20C
+#define IMX6_ANALOG_USB2_CHRG_DETECT 0x210
+#define IMX6_ANALOG_USB2_CHRG_DETECT_SET 0x214
+#define IMX6_ANALOG_USB2_CHRG_DETECT_CLR 0x218
+#define IMX6_ANALOG_USB2_CHRG_DETECT_TOG 0x21C
+#define IMX6_ANALOG_USB2_VBUS_DETECT_STAT 0x220
+#define IMX6_ANALOG_USB2_CHRG_DETECT_STAT 0x230
+#define IMX6_ANALOG_USB2_MISC 0x250
+#define IMX6_ANALOG_USB2_MISC_SET 0x254
+#define IMX6_ANALOG_USB2_MISC_CLR 0x258
+#define IMX6_ANALOG_USB2_MISC_TOG 0x25C
+#define IMX6_ANALOG_DIGPROG 0x260
+#define IMX6_ANALOG_DIGPROG_SL 0x280
+#define IMX6_ANALOG_DIGPROG_SOCTYPE_SHIFT 16
+#define IMX6_ANALOG_DIGPROG_SOCTYPE_MASK \
+ (0xff << IMX6_ANALOG_DIGPROG_SOCTYPE_SHIFT)
+
+#endif
Property changes on: trunk/sys/arm/freescale/imx/imx6_anatopreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_anatopvar.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_anatopvar.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_anatopvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,48 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx6_anatopvar.h 283500 2015-05-24 18:59:45Z ian $
+ */
+
+#ifndef IMX6_ANATOPVAR_H
+#define IMX6_ANATOPVAR_H
+
+/*
+ * All registers controlling various analog aspects of the SoC (such as PLLs or
+ * voltage regulators or USB VBUS detection) are gathered together under the
+ * anatop device (because of newbus hierarchical resource management), but other
+ * drivers such as CMM or USBPHY need access to these registers. These
+ * functions let them have at the hardware directly. No effort is made by these
+ * functions to mediate concurrent access.
+ */
+uint32_t imx6_anatop_read_4(bus_size_t _offset);
+void imx6_anatop_write_4(bus_size_t _offset, uint32_t _value);
+
+uint32_t imx6_get_cpu_clock(void);
+
+uint32_t pll4_configure_output(uint32_t mfi, uint32_t mfn, uint32_t mfd);
+
+#endif
Property changes on: trunk/sys/arm/freescale/imx/imx6_anatopvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_audmux.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_audmux.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_audmux.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,160 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * i.MX6 Digital Audio Multiplexer (AUDMUX)
+ * Chapter 16, i.MX 6Dual/6Quad Applications Processor Reference Manual,
+ * Rev. 1, 04/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_audmux.c 283500 2015-05-24 18:59:45Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/endian.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#define READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst, _sc->bsh, _reg)
+#define WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
+
+#define AUDMUX_PTCR(n) (0x8 * (n - 1)) /* Port Timing Control Register */
+#define PTCR_TFS_DIR (1 << 31) /* Transmit Frame Sync Direction Control */
+#define PTCR_TFSEL_S 27 /* Transmit Frame Sync Select */
+#define PTCR_TFSEL_M 0xf
+#define PTCR_TCLKDIR (1 << 26) /* Transmit Clock Direction Control */
+#define PTCR_TCSEL_S 22 /* Transmit Clock Select. */
+#define PTCR_TCSEL_M 0xf
+#define PTCR_RFS_DIR (1 << 21) /* Receive Frame Sync Direction Control */
+#define PTCR_SYN (1 << 11)
+#define AUDMUX_PDCR(n) (0x8 * (n - 1) + 0x4) /* Port Data Control Reg */
+#define PDCR_RXDSEL_S 13 /* Receive Data Select */
+#define PDCR_RXDSEL_M 0x3
+#define PDCR_RXDSEL_PORT(n) (n - 1)
+
+struct audmux_softc {
+ struct resource *res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ void *ih;
+};
+
+static struct resource_spec audmux_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+audmux_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,imx6q-audmux"))
+ return (ENXIO);
+
+ device_set_desc(dev, "i.MX6 Digital Audio Multiplexer");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+audmux_configure(struct audmux_softc *sc,
+ int ssi_port, int audmux_port)
+{
+ uint32_t reg;
+
+ /* Direction: output */
+ reg = (PTCR_TFS_DIR | PTCR_TCLKDIR | PTCR_SYN);
+ WRITE4(sc, AUDMUX_PTCR(audmux_port), reg);
+
+ /* Select source */
+ reg = (PDCR_RXDSEL_PORT(ssi_port) << PDCR_RXDSEL_S);
+ WRITE4(sc, AUDMUX_PDCR(audmux_port), reg);
+
+ return (0);
+}
+
+static int
+audmux_attach(device_t dev)
+{
+ struct audmux_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, audmux_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /*
+ * Direct SSI1 output to AUDMUX5 pins.
+ * TODO: dehardcore this.
+ */
+ audmux_configure(sc, 1, 5);
+
+ return (0);
+};
+
+static device_method_t audmux_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, audmux_probe),
+ DEVMETHOD(device_attach, audmux_attach),
+ { 0, 0 }
+};
+
+static driver_t audmux_driver = {
+ "audmux",
+ audmux_methods,
+ sizeof(struct audmux_softc),
+};
+
+static devclass_t audmux_devclass;
+
+DRIVER_MODULE(audmux, simplebus, audmux_driver, audmux_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/imx/imx6_audmux.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_ccm.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_ccm.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_ccm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,357 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_ccm.c 283501 2015-05-24 19:00:46Z ian $");
+
+/*
+ * Clocks and power control driver for Freescale i.MX6 family of SoCs.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include <arm/freescale/imx/imx6_anatopreg.h>
+#include <arm/freescale/imx/imx6_anatopvar.h>
+#include <arm/freescale/imx/imx6_ccmreg.h>
+#include <arm/freescale/imx/imx_machdep.h>
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+#ifndef CCGR_CLK_MODE_ALWAYS
+#define CCGR_CLK_MODE_OFF 0
+#define CCGR_CLK_MODE_RUNMODE 1
+#define CCGR_CLK_MODE_ALWAYS 3
+#endif
+
+struct ccm_softc {
+ device_t dev;
+ struct resource *mem_res;
+};
+
+static struct ccm_softc *ccm_sc;
+
+static inline uint32_t
+RD4(struct ccm_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct ccm_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+/*
+ * Until we have a fully functional ccm driver which implements the fdt_clock
+ * interface, use the age-old workaround of unconditionally enabling the clocks
+ * for devices we might need to use. The SoC defaults to most clocks enabled,
+ * but the rom boot code and u-boot disable a few of them. We turn on only
+ * what's needed to run the chip plus devices we have drivers for, and turn off
+ * devices we don't yet have drivers for. (Note that USB is not turned on here
+ * because that is one we do when the driver asks for it.)
+ */
+static void
+ccm_init_gates(struct ccm_softc *sc)
+{
+ /* Turns on... */
+ WR4(sc, CCM_CCGR0, 0x0000003f); /* ahpbdma, aipstz 1 & 2 busses */
+ WR4(sc, CCM_CCGR1, 0x00300c00); /* gpt, enet */
+ WR4(sc, CCM_CCGR2, 0x0fffffc0); /* ipmux & ipsync (bridges), iomux, i2c */
+ WR4(sc, CCM_CCGR3, 0x3ff00000); /* DDR memory controller */
+ WR4(sc, CCM_CCGR4, 0x0000f300); /* pl301 bus crossbar */
+ WR4(sc, CCM_CCGR5, 0x0ffc00c0); /* uarts, ssi, sdma */
+ WR4(sc, CCM_CCGR6, 0x000000ff); /* usdhc 1-4 */
+}
+
+static int
+ccm_detach(device_t dev)
+{
+ struct ccm_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (0);
+}
+
+static int
+ccm_attach(device_t dev)
+{
+ struct ccm_softc *sc;
+ int err, rid;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+ err = 0;
+
+ /* Allocate bus_space resources. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ ccm_sc = sc;
+
+ /*
+ * Configure the Low Power Mode setting to leave the ARM core power on
+ * when a WFI instruction is executed. This lets the MPCore timers and
+ * GIC continue to run, which is helpful when the only thing that can
+ * wake you up is an MPCore Private Timer interrupt delivered via GIC.
+ *
+ * XXX Based on the docs, setting CCM_CGPR_INT_MEM_CLK_LPM shouldn't be
+ * required when the LPM bits are set to LPM_RUN. But experimentally
+ * I've experienced a fairly rare lockup when not setting it. I was
+ * unable to prove conclusively that the lockup was related to power
+ * management or that this definitively fixes it. Revisit this.
+ */
+ reg = RD4(sc, CCM_CGPR);
+ reg |= CCM_CGPR_INT_MEM_CLK_LPM;
+ WR4(sc, CCM_CGPR, reg);
+ reg = RD4(sc, CCM_CLPCR);
+ reg = (reg & ~CCM_CLPCR_LPM_MASK) | CCM_CLPCR_LPM_RUN;
+ WR4(sc, CCM_CLPCR, reg);
+
+ ccm_init_gates(sc);
+
+ err = 0;
+
+out:
+
+ if (err != 0)
+ ccm_detach(dev);
+
+ return (err);
+}
+
+static int
+ccm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "fsl,imx6q-ccm") == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale i.MX6 Clock Control Module");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+void
+imx_ccm_ssi_configure(device_t _ssidev)
+{
+ struct ccm_softc *sc;
+ uint32_t reg;
+
+ sc = ccm_sc;
+
+ /*
+ * Select PLL4 (Audio PLL) clock multiplexer as source.
+ * PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM).
+ */
+
+ reg = RD4(sc, CCM_CSCMR1);
+ reg &= ~(SSI_CLK_SEL_M << SSI1_CLK_SEL_S);
+ reg |= (SSI_CLK_SEL_PLL4 << SSI1_CLK_SEL_S);
+ reg &= ~(SSI_CLK_SEL_M << SSI2_CLK_SEL_S);
+ reg |= (SSI_CLK_SEL_PLL4 << SSI2_CLK_SEL_S);
+ reg &= ~(SSI_CLK_SEL_M << SSI3_CLK_SEL_S);
+ reg |= (SSI_CLK_SEL_PLL4 << SSI3_CLK_SEL_S);
+ WR4(sc, CCM_CSCMR1, reg);
+
+ /*
+ * Ensure we have set hardware-default values
+ * for pre and post dividers.
+ */
+
+ /* SSI1 and SSI3 */
+ reg = RD4(sc, CCM_CS1CDR);
+ /* Divide by 2 */
+ reg &= ~(SSI_CLK_PODF_MASK << SSI1_CLK_PODF_SHIFT);
+ reg &= ~(SSI_CLK_PODF_MASK << SSI3_CLK_PODF_SHIFT);
+ reg |= (0x1 << SSI1_CLK_PODF_SHIFT);
+ reg |= (0x1 << SSI3_CLK_PODF_SHIFT);
+ /* Divide by 4 */
+ reg &= ~(SSI_CLK_PRED_MASK << SSI1_CLK_PRED_SHIFT);
+ reg &= ~(SSI_CLK_PRED_MASK << SSI3_CLK_PRED_SHIFT);
+ reg |= (0x3 << SSI1_CLK_PRED_SHIFT);
+ reg |= (0x3 << SSI3_CLK_PRED_SHIFT);
+ WR4(sc, CCM_CS1CDR, reg);
+
+ /* SSI2 */
+ reg = RD4(sc, CCM_CS2CDR);
+ /* Divide by 2 */
+ reg &= ~(SSI_CLK_PODF_MASK << SSI2_CLK_PODF_SHIFT);
+ reg |= (0x1 << SSI2_CLK_PODF_SHIFT);
+ /* Divide by 4 */
+ reg &= ~(SSI_CLK_PRED_MASK << SSI2_CLK_PRED_SHIFT);
+ reg |= (0x3 << SSI2_CLK_PRED_SHIFT);
+ WR4(sc, CCM_CS2CDR, reg);
+}
+
+void
+imx_ccm_usb_enable(device_t _usbdev)
+{
+
+ /*
+ * For imx6, the USBOH3 clock gate is bits 0-1 of CCGR6, so no need for
+ * shifting and masking here, just set the low-order two bits to ALWAYS.
+ */
+ WR4(ccm_sc, CCM_CCGR6, RD4(ccm_sc, CCM_CCGR6) | CCGR_CLK_MODE_ALWAYS);
+}
+
+void
+imx_ccm_usbphy_enable(device_t _phydev)
+{
+ /*
+ * XXX Which unit?
+ * Right now it's not clear how to figure from fdt data which phy unit
+ * we're supposed to operate on. Until this is worked out, just enable
+ * both PHYs.
+ */
+#if 0
+ int phy_num, regoff;
+
+ phy_num = 0; /* XXX */
+
+ switch (phy_num) {
+ case 0:
+ regoff = 0;
+ break;
+ case 1:
+ regoff = 0x10;
+ break;
+ default:
+ device_printf(ccm_sc->dev, "Bad PHY number %u,\n",
+ phy_num);
+ return;
+ }
+
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_USB1 + regoff,
+ IMX6_ANALOG_CCM_PLL_USB_ENABLE |
+ IMX6_ANALOG_CCM_PLL_USB_POWER |
+ IMX6_ANALOG_CCM_PLL_USB_EN_USB_CLKS);
+#else
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_USB1 + 0,
+ IMX6_ANALOG_CCM_PLL_USB_ENABLE |
+ IMX6_ANALOG_CCM_PLL_USB_POWER |
+ IMX6_ANALOG_CCM_PLL_USB_EN_USB_CLKS);
+
+ imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_USB1 + 0x10,
+ IMX6_ANALOG_CCM_PLL_USB_ENABLE |
+ IMX6_ANALOG_CCM_PLL_USB_POWER |
+ IMX6_ANALOG_CCM_PLL_USB_EN_USB_CLKS);
+#endif
+}
+
+uint32_t
+imx_ccm_ipg_hz(void)
+{
+
+ return (66000000);
+}
+
+uint32_t
+imx_ccm_perclk_hz(void)
+{
+
+ return (66000000);
+}
+
+uint32_t
+imx_ccm_sdhci_hz(void)
+{
+
+ return (200000000);
+}
+
+uint32_t
+imx_ccm_uart_hz(void)
+{
+
+ return (80000000);
+}
+
+uint32_t
+imx_ccm_ahb_hz(void)
+{
+ return (132000000);
+}
+
+uint32_t
+imx_ccm_get_cacrr(void)
+{
+
+ return (RD4(ccm_sc, CCM_CACCR));
+}
+
+void
+imx_ccm_set_cacrr(uint32_t divisor)
+{
+
+ WR4(ccm_sc, CCM_CACCR, divisor);
+}
+
+static device_method_t ccm_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ccm_probe),
+ DEVMETHOD(device_attach, ccm_attach),
+ DEVMETHOD(device_detach, ccm_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t ccm_driver = {
+ "ccm",
+ ccm_methods,
+ sizeof(struct ccm_softc)
+};
+
+static devclass_t ccm_devclass;
+
+EARLY_DRIVER_MODULE(ccm, simplebus, ccm_driver, ccm_devclass, 0, 0,
+ BUS_PASS_CPU + BUS_PASS_ORDER_EARLY);
+
Property changes on: trunk/sys/arm/freescale/imx/imx6_ccm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_ccmreg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_ccmreg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_ccmreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx6_ccmreg.h 283501 2015-05-24 19:00:46Z ian $
+ */
+
+#ifndef IMX6_CCMREG_H
+#define IMX6_CCMREG_H
+
+#define CCM_CACCR 0x010
+#define CCM_CSCMR1 0x01C
+#define SSI1_CLK_SEL_S 10
+#define SSI2_CLK_SEL_S 12
+#define SSI3_CLK_SEL_S 14
+#define SSI_CLK_SEL_M 0x3
+#define SSI_CLK_SEL_508_PFD 0
+#define SSI_CLK_SEL_454_PFD 1
+#define SSI_CLK_SEL_PLL4 2
+#define CCM_CSCMR2 0x020
+#define CCM_CS1CDR 0x028
+#define SSI1_CLK_PODF_SHIFT 0
+#define SSI1_CLK_PRED_SHIFT 6
+#define SSI3_CLK_PODF_SHIFT 16
+#define SSI3_CLK_PRED_SHIFT 22
+#define SSI_CLK_PODF_MASK 0x3f
+#define SSI_CLK_PRED_MASK 0x7
+#define CCM_CS2CDR 0x02C
+#define SSI2_CLK_PODF_SHIFT 0
+#define SSI2_CLK_PRED_SHIFT 6
+#define CCM_CSCDR2 0x038
+#define CCM_CLPCR 0x054
+#define CCM_CLPCR_LPM_MASK 0x03
+#define CCM_CLPCR_LPM_RUN 0x00
+#define CCM_CLPCR_LPM_WAIT 0x01
+#define CCM_CLPCR_LPM_STOP 0x02
+#define CCM_CGPR 0x064
+#define CCM_CGPR_INT_MEM_CLK_LPM (1 << 17)
+#define CCM_CCGR0 0x068
+#define CCM_CCGR1 0x06C
+#define CCM_CCGR2 0x070
+#define CCM_CCGR3 0x074
+#define CCM_CCGR4 0x078
+#define CCM_CCGR5 0x07C
+#define CCM_CCGR6 0x080
+#define CCM_CMEOR 0x088
+
+#endif
Property changes on: trunk/sys/arm/freescale/imx/imx6_ccmreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_machdep.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_machdep.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,275 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_machdep.c 294678 2016-01-24 19:34:05Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/reboot.h>
+
+#include <vm/vm.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/intr.h>
+#include <machine/machdep.h>
+
+#include <arm/arm/mpcore_timervar.h>
+#include <arm/freescale/imx/imx6_anatopreg.h>
+#include <arm/freescale/imx/imx6_anatopvar.h>
+#include <arm/freescale/imx/imx_machdep.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static uint32_t gpio1_node;
+
+/*
+ * Work around the linux workaround for imx6 erratum 006687, in which some
+ * ethernet interrupts don't go to the GPC and thus won't wake the system from
+ * Wait mode. We don't use Wait mode (which halts the GIC, leaving only GPC
+ * interrupts able to wake the system), so we don't experience the bug at all.
+ * The linux workaround is to reconfigure GPIO1_6 as the ENET interrupt by
+ * writing magic values to an undocumented IOMUX register, then letting the gpio
+ * interrupt driver notify the ethernet driver. We'll be able to do all that
+ * (even though we don't need to) once the INTRNG project is committed and the
+ * imx_gpio driver becomes an interrupt driver. Until then, this crazy little
+ * workaround watches for requests to map an interrupt 6 with the interrupt
+ * controller node referring to gpio1, and it substitutes the proper ffec
+ * interrupt number.
+ */
+static int
+imx6_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
+ int *trig, int *pol)
+{
+
+ if (fdt32_to_cpu(intr[0]) == 6 &&
+ OF_node_from_xref(iparent) == gpio1_node) {
+ *interrupt = 150;
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+ }
+ return (gic_decode_fdt(iparent, intr, interrupt, trig, pol));
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &imx6_decode_fdt,
+ NULL
+};
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+ /* Inform the MPCore timer driver that its clock is variable. */
+ arm_tmr_change_frequency(ARM_TMR_FREQUENCY_VARIES);
+}
+
+void
+initarm_gpio_init(void)
+{
+
+}
+
+void
+initarm_late_init(void)
+{
+ const uint32_t IMX6_WDOG_SR_PHYS = 0x020bc004;
+
+ imx_wdog_init_last_reset(IMX6_WDOG_SR_PHYS);
+
+ /* Cache the gpio1 node handle for imx6_decode_fdt() workaround code. */
+ gpio1_node = OF_node_from_xref(
+ OF_finddevice("/soc/aips-bus at 02000000/gpio at 0209c000"));
+}
+
+/*
+ * Set up static device mappings.
+ *
+ * This attempts to cover the most-used devices with 1MB section mappings, which
+ * is good for performance (uses fewer TLB entries for device access).
+ *
+ * ARMMP covers the interrupt controller, MPCore timers, global timer, and the
+ * L2 cache controller. Most of the 1MB range is unused reserved space.
+ *
+ * AIPS1/AIPS2 cover most of the on-chip devices such as uart, spi, i2c, etc.
+ *
+ * Notably not mapped right now are HDMI, GPU, and other devices below ARMMP in
+ * the memory map. When we get support for graphics it might make sense to
+ * static map some of that area. Be careful with other things in that area such
+ * as OCRAM that probably shouldn't be mapped as PTE_DEVICE memory.
+ */
+int
+initarm_devmap_init(void)
+{
+ const uint32_t IMX6_ARMMP_PHYS = 0x00a00000;
+ const uint32_t IMX6_ARMMP_SIZE = 0x00100000;
+ const uint32_t IMX6_AIPS1_PHYS = 0x02000000;
+ const uint32_t IMX6_AIPS1_SIZE = 0x00100000;
+ const uint32_t IMX6_AIPS2_PHYS = 0x02100000;
+ const uint32_t IMX6_AIPS2_SIZE = 0x00100000;
+
+ arm_devmap_add_entry(IMX6_ARMMP_PHYS, IMX6_ARMMP_SIZE);
+ arm_devmap_add_entry(IMX6_AIPS1_PHYS, IMX6_AIPS1_SIZE);
+ arm_devmap_add_entry(IMX6_AIPS2_PHYS, IMX6_AIPS2_SIZE);
+
+ return (0);
+}
+
+void
+cpu_reset(void)
+{
+ const uint32_t IMX6_WDOG_CR_PHYS = 0x020bc000;
+
+ imx_wdog_cpu_reset(IMX6_WDOG_CR_PHYS);
+}
+
+/*
+ * Determine what flavor of imx6 we're running on.
+ *
+ * This code is based on the way u-boot does it. Information found on the web
+ * indicates that Freescale themselves were the original source of this logic,
+ * including the strange check for number of CPUs in the SCU configuration
+ * register, which is apparently needed on some revisions of the SOLO.
+ *
+ * According to the documentation, there is such a thing as an i.MX6 Dual
+ * (non-lite flavor). However, Freescale doesn't seem to have assigned it a
+ * number or provided any logic to handle it in their detection code.
+ *
+ * Note that the ANALOG_DIGPROG and SCU configuration registers are not
+ * documented in the chip reference manual. (SCU configuration is mentioned,
+ * but not mapped out in detail.) I think the bottom two bits of the scu config
+ * register may be ncpu-1.
+ *
+ * This hasn't been tested yet on a dual[-lite].
+ *
+ * On a solo:
+ * digprog = 0x00610001
+ * hwsoc = 0x00000062
+ * scu config = 0x00000500
+ * On a quad:
+ * digprog = 0x00630002
+ * hwsoc = 0x00000063
+ * scu config = 0x00005503
+ */
+u_int imx_soc_type()
+{
+ uint32_t digprog, hwsoc;
+ uint32_t *pcr;
+ static u_int soctype;
+ const vm_offset_t SCU_CONFIG_PHYSADDR = 0x00a00004;
+#define HWSOC_MX6SL 0x60
+#define HWSOC_MX6DL 0x61
+#define HWSOC_MX6SOLO 0x62
+#define HWSOC_MX6Q 0x63
+
+ if (soctype != 0)
+ return (soctype);
+
+ digprog = imx6_anatop_read_4(IMX6_ANALOG_DIGPROG_SL);
+ hwsoc = (digprog >> IMX6_ANALOG_DIGPROG_SOCTYPE_SHIFT) &
+ IMX6_ANALOG_DIGPROG_SOCTYPE_MASK;
+
+ if (hwsoc != HWSOC_MX6SL) {
+ digprog = imx6_anatop_read_4(IMX6_ANALOG_DIGPROG);
+ hwsoc = (digprog & IMX6_ANALOG_DIGPROG_SOCTYPE_MASK) >>
+ IMX6_ANALOG_DIGPROG_SOCTYPE_SHIFT;
+ /*printf("digprog = 0x%08x\n", digprog);*/
+ if (hwsoc == HWSOC_MX6DL) {
+ pcr = arm_devmap_ptov(SCU_CONFIG_PHYSADDR, 4);
+ if (pcr != NULL) {
+ /*printf("scu config = 0x%08x\n", *pcr);*/
+ if ((*pcr & 0x03) == 0) {
+ hwsoc = HWSOC_MX6SOLO;
+ }
+ }
+ }
+ }
+ /* printf("hwsoc 0x%08x\n", hwsoc); */
+
+ switch (hwsoc) {
+ case HWSOC_MX6SL:
+ soctype = IMXSOC_6SL;
+ break;
+ case HWSOC_MX6SOLO:
+ soctype = IMXSOC_6S;
+ break;
+ case HWSOC_MX6DL:
+ soctype = IMXSOC_6DL;
+ break;
+ case HWSOC_MX6Q :
+ soctype = IMXSOC_6Q;
+ break;
+ default:
+ printf("imx_soc_type: Don't understand hwsoc 0x%02x, "
+ "digprog 0x%08x; assuming IMXSOC_6Q\n", hwsoc, digprog);
+ soctype = IMXSOC_6Q;
+ break;
+ }
+
+ return (soctype);
+}
+
+/*
+ * Early putc routine for EARLY_PRINTF support. To use, add to kernel config:
+ * option SOCDEV_PA=0x02000000
+ * option SOCDEV_VA=0x02000000
+ * option EARLY_PRINTF
+ * Resist the temptation to change the #if 0 to #ifdef EARLY_PRINTF here. It
+ * makes sense now, but if multiple SOCs do that it will make early_putc another
+ * duplicate symbol to be eliminated on the path to a generic kernel.
+ */
+#if 0
+static void
+imx6_early_putc(int c)
+{
+ volatile uint32_t * UART_STAT_REG = (uint32_t *)0x02020098;
+ volatile uint32_t * UART_TX_REG = (uint32_t *)0x02020040;
+ const uint32_t UART_TXRDY = (1 << 3);
+
+ while ((*UART_STAT_REG & UART_TXRDY) == 0)
+ continue;
+ *UART_TX_REG = c;
+}
+early_putc_t *early_putc = imx6_early_putc;
+#endif
+
Property changes on: trunk/sys/arm/freescale/imx/imx6_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_mp.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_mp.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_mp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,179 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Juergen Weiss <weiss at uni-mainz.de>
+ * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_mp.c 269104 2014-07-25 23:36:39Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#define SCU_PHYSBASE 0x00a00000
+#define SCU_SIZE 0x00001000
+
+#define SCU_CONTROL_REG 0x00
+#define SCU_CONTROL_ENABLE (1 << 0)
+#define SCU_CONFIG_REG 0x04
+#define SCU_CONFIG_REG_NCPU_MASK 0x03
+#define SCU_CPUPOWER_REG 0x08
+#define SCU_INV_TAGS_REG 0x0c
+#define SCU_DIAG_CONTROL 0x30
+#define SCU_DIAG_DISABLE_MIGBIT (1 << 0)
+#define SCU_FILTER_START_REG 0x40
+#define SCU_FILTER_END_REG 0x44
+#define SCU_SECURE_ACCESS_REG 0x50
+#define SCU_NONSECURE_ACCESS_REG 0x54
+
+#define SRC_PHYSBASE 0x020d8000
+#define SRC_SIZE 0x4000
+#define SRC_CONTROL_REG 0x00
+#define SRC_CONTROL_C1ENA_SHIFT 22 /* Bit for Core 1 enable */
+#define SRC_CONTROL_C1RST_SHIFT 14 /* Bit for Core 1 reset */
+#define SRC_GPR0_C1FUNC 0x20 /* Register for Core 1 entry func */
+#define SRC_GPR1_C1ARG 0x24 /* Register for Core 1 entry arg */
+
+void
+platform_mp_init_secondary(void)
+{
+
+ gic_init_secondary();
+}
+
+void
+platform_mp_setmaxid(void)
+{
+ bus_space_handle_t scu;
+ int hwcpu, ncpu;
+ uint32_t val;
+
+ /* If we've already set the global vars don't bother to do it again. */
+ if (mp_ncpus != 0)
+ return;
+
+ if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
+ panic("Couldn't map the SCU\n");
+ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONFIG_REG);
+ hwcpu = (val & SCU_CONFIG_REG_NCPU_MASK) + 1;
+ bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
+
+ ncpu = hwcpu;
+ TUNABLE_INT_FETCH("hw.ncpu", &ncpu);
+ if (ncpu < 1 || ncpu > hwcpu)
+ ncpu = hwcpu;
+
+ mp_ncpus = ncpu;
+ mp_maxid = ncpu - 1;
+}
+
+int
+platform_mp_probe(void)
+{
+
+ /* I think platform_mp_setmaxid must get called first, but be safe. */
+ if (mp_ncpus == 0)
+ platform_mp_setmaxid();
+
+ return (mp_ncpus > 1);
+}
+
+void
+platform_mp_start_ap(void)
+{
+ bus_space_handle_t scu;
+ bus_space_handle_t src;
+
+ uint32_t val;
+ int i;
+
+ if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
+ panic("Couldn't map the SCU\n");
+ if (bus_space_map(fdtbus_bs_tag, SRC_PHYSBASE, SRC_SIZE, 0, &src) != 0)
+ panic("Couldn't map the system reset controller (SRC)\n");
+
+ /*
+ * Invalidate SCU cache tags. The 0x0000ffff constant invalidates all
+ * ways on all cores 0-3. Per the ARM docs, it's harmless to write to
+ * the bits for cores that are not present.
+ */
+ bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff);
+
+ /*
+ * Erratum ARM/MP: 764369 (problems with cache maintenance).
+ * Setting the "disable-migratory bit" in the undocumented SCU
+ * Diagnostic Control Register helps work around the problem.
+ */
+ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL);
+ bus_space_write_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL,
+ val | SCU_DIAG_DISABLE_MIGBIT);
+
+ /*
+ * Enable the SCU, then clean the cache on this core. After these two
+ * operations the cache tag ram in the SCU is coherent with the contents
+ * of the cache on this core. The other cores aren't running yet so
+ * their caches can't contain valid data yet, but we've initialized
+ * their SCU tag ram above, so they will be coherent from startup.
+ */
+ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG);
+ bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG,
+ val | SCU_CONTROL_ENABLE);
+ cpu_idcache_wbinv_all();
+
+ /*
+ * For each AP core, set the entry point address and argument registers,
+ * and set the core-enable and core-reset bits in the control register.
+ */
+ val = bus_space_read_4(fdtbus_bs_tag, src, SRC_CONTROL_REG);
+ for (i=1; i < mp_ncpus; i++) {
+ bus_space_write_4(fdtbus_bs_tag, src, SRC_GPR0_C1FUNC + 8*i,
+ pmap_kextract((vm_offset_t)mpentry));
+ bus_space_write_4(fdtbus_bs_tag, src, SRC_GPR1_C1ARG + 8*i, 0);
+
+ val |= ((1 << (SRC_CONTROL_C1ENA_SHIFT - 1 + i )) |
+ ( 1 << (SRC_CONTROL_C1RST_SHIFT - 1 + i)));
+
+ }
+ bus_space_write_4(fdtbus_bs_tag, src, SRC_CONTROL_REG, val);
+
+ armv7_sev();
+
+ bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
+ bus_space_unmap(fdtbus_bs_tag, src, SRC_SIZE);
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+
+ pic_ipi_send(cpus, ipi);
+}
Property changes on: trunk/sys/arm/freescale/imx/imx6_mp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_pl310.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_pl310.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_pl310.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,76 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_pl310.c 266384 2014-05-18 00:26:42Z ian $");
+
+/*
+ * The machine-dependent part of the arm/pl310 driver for imx6 SoCs.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/pl310.h>
+
+void
+platform_pl310_init(struct pl310_softc *sc)
+{
+ uint32_t reg;
+
+ /*
+ * Enable power saving modes:
+ * - Dynamic Gating stops the clock when the controller is idle.
+ * - Standby stops the clock when the cores are in WFI mode.
+ */
+ reg = pl310_read4(sc, PL310_POWER_CTRL);
+ reg |= POWER_CTRL_ENABLE_GATING | POWER_CTRL_ENABLE_STANDBY;
+ pl310_write4(sc, PL310_POWER_CTRL, reg);
+
+ pl310_set_ram_latency(sc, PL310_TAG_RAM_CTRL, 4, 2, 3);
+ pl310_set_ram_latency(sc, PL310_DATA_RAM_CTRL, 4, 2, 3);
+}
+
+void
+platform_pl310_write_ctrl(struct pl310_softc *sc, uint32_t val)
+{
+
+ pl310_write4(sc, PL310_CTRL, val);
+}
+
+void
+platform_pl310_write_debug(struct pl310_softc *sc, uint32_t val)
+{
+
+ pl310_write4(sc, PL310_DEBUG_CTRL, val);
+}
+
Property changes on: trunk/sys/arm/freescale/imx/imx6_pl310.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_sdma.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_sdma.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_sdma.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,519 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * i.MX6 Smart Direct Memory Access Controller (sDMA)
+ * Chapter 41, i.MX 6Dual/6Quad Applications Processor Reference Manual,
+ * Rev. 1, 04/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_sdma.c 283500 2015-05-24 18:59:45Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/endian.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/firmware.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/imx/imx6_sdma.h>
+
+#define MAX_BD (PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
+
+#define READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst, _sc->bsh, _reg)
+#define WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
+
+struct sdma_softc *sdma_sc;
+
+static struct resource_spec sdma_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static void
+sdma_intr(void *arg)
+{
+ struct sdma_buffer_descriptor *bd;
+ struct sdma_channel *channel;
+ struct sdma_conf *conf;
+ struct sdma_softc *sc;
+ int pending;
+ int i;
+ int j;
+
+ sc = arg;
+
+ pending = READ4(sc, SDMAARM_INTR);
+
+ /* Ack intr */
+ WRITE4(sc, SDMAARM_INTR, pending);
+
+ for (i = 0; i < SDMA_N_CHANNELS; i++) {
+ if ((pending & (1 << i)) == 0)
+ continue;
+ channel = &sc->channel[i];
+ conf = channel->conf;
+ if (!conf)
+ continue;
+ for (j = 0; j < conf->num_bd; j++) {
+ bd = &channel->bd[j];
+ bd->mode.status |= BD_DONE;
+ if (bd->mode.status & BD_RROR)
+ printf("sDMA error\n");
+ }
+
+ conf->ih(conf->ih_user, 1);
+
+ WRITE4(sc, SDMAARM_HSTART, (1 << i));
+ }
+}
+
+static int
+sdma_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,imx6q-sdma"))
+ return (ENXIO);
+
+ device_set_desc(dev, "i.MX6 Smart Direct Memory Access Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+int
+sdma_start(int chn)
+{
+ struct sdma_softc *sc;
+
+ sc = sdma_sc;
+
+ WRITE4(sc, SDMAARM_HSTART, (1 << chn));
+
+ return (0);
+}
+
+int
+sdma_stop(int chn)
+{
+ struct sdma_softc *sc;
+
+ sc = sdma_sc;
+
+ WRITE4(sc, SDMAARM_STOP_STAT, (1 << chn));
+
+ return (0);
+}
+
+int
+sdma_alloc(void)
+{
+ struct sdma_channel *channel;
+ struct sdma_softc *sc;
+ int found;
+ int chn;
+ int i;
+
+ sc = sdma_sc;
+ found = 0;
+
+ /* Channel 0 can't be used */
+ for (i = 1; i < SDMA_N_CHANNELS; i++) {
+ channel = &sc->channel[i];
+ if (channel->in_use == 0) {
+ channel->in_use = 1;
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return (-1);
+
+ chn = i;
+
+ /* Allocate area for buffer descriptors */
+ channel->bd = (void *)kmem_alloc_contig(kernel_arena,
+ PAGE_SIZE, M_ZERO, 0, ~0, PAGE_SIZE, 0,
+ VM_MEMATTR_UNCACHEABLE);
+
+ return (chn);
+}
+
+int
+sdma_free(int chn)
+{
+ struct sdma_channel *channel;
+ struct sdma_softc *sc;
+
+ sc = sdma_sc;
+
+ channel = &sc->channel[chn];
+ channel->in_use = 0;
+
+ kmem_free(kernel_arena, (vm_offset_t)channel->bd,
+ PAGE_SIZE);
+
+ return (0);
+}
+
+static int
+sdma_overrides(struct sdma_softc *sc, int chn,
+ int evt, int host, int dsp)
+{
+ int reg;
+
+ /* Ignore sDMA requests */
+ reg = READ4(sc, SDMAARM_EVTOVR);
+ if (evt)
+ reg |= (1 << chn);
+ else
+ reg &= ~(1 << chn);
+ WRITE4(sc, SDMAARM_EVTOVR, reg);
+
+ /* Ignore enable bit (HE) */
+ reg = READ4(sc, SDMAARM_HOSTOVR);
+ if (host)
+ reg |= (1 << chn);
+ else
+ reg &= ~(1 << chn);
+ WRITE4(sc, SDMAARM_HOSTOVR, reg);
+
+ /* Prevent sDMA channel from starting */
+ reg = READ4(sc, SDMAARM_DSPOVR);
+ if (!dsp)
+ reg |= (1 << chn);
+ else
+ reg &= ~(1 << chn);
+ WRITE4(sc, SDMAARM_DSPOVR, reg);
+
+ return (0);
+}
+
+int
+sdma_configure(int chn, struct sdma_conf *conf)
+{
+ struct sdma_buffer_descriptor *bd0;
+ struct sdma_buffer_descriptor *bd;
+ struct sdma_context_data *context;
+ struct sdma_channel *channel;
+ struct sdma_softc *sc;
+#if 0
+ int timeout;
+ int ret;
+#endif
+ int i;
+
+ sc = sdma_sc;
+
+ channel = &sc->channel[chn];
+ channel->conf = conf;
+
+ /* Ensure operation has stopped */
+ sdma_stop(chn);
+
+ /* Set priority and enable the channel */
+ WRITE4(sc, SDMAARM_SDMA_CHNPRI(chn), 1);
+ WRITE4(sc, SDMAARM_CHNENBL(conf->event), (1 << chn));
+
+ sdma_overrides(sc, chn, 0, 0, 0);
+
+ if (conf->num_bd > MAX_BD) {
+ device_printf(sc->dev, "Error: too much buffer"
+ " descriptors requested\n");
+ return (-1);
+ }
+
+ for (i = 0; i < conf->num_bd; i++) {
+ bd = &channel->bd[i];
+ bd->mode.command = conf->command;
+ bd->mode.status = BD_DONE | BD_EXTD | BD_CONT | BD_INTR;
+ if (i == (conf->num_bd - 1))
+ bd->mode.status |= BD_WRAP;
+ bd->mode.count = conf->period;
+ bd->buffer_addr = conf->saddr + (conf->period * i);
+ bd->ext_buffer_addr = 0;
+ }
+
+ sc->ccb[chn].base_bd_ptr = vtophys(channel->bd);
+ sc->ccb[chn].current_bd_ptr = vtophys(channel->bd);
+
+ /*
+ * Load context.
+ *
+ * i.MX6 Reference Manual: Appendix A SDMA Scripts
+ * A.3.1.7.1 (mcu_2_app)
+ */
+
+ /*
+ * TODO: allow using other scripts
+ */
+ context = sc->context;
+ memset(context, 0, sizeof(*context));
+ context->channel_state.pc = sc->fw_scripts->mcu_2_app_addr;
+
+ /*
+ * Tx FIFO 0 address (r6)
+ * Event_mask (r1)
+ * Event2_mask (r0)
+ * Watermark level (r7)
+ */
+
+ if (conf->event > 32) {
+ context->gReg[0] = (1 << (conf->event % 32));
+ context->gReg[1] = 0;
+ } else {
+ context->gReg[0] = 0;
+ context->gReg[1] = (1 << conf->event);
+ }
+
+ context->gReg[6] = conf->daddr;
+ context->gReg[7] = conf->word_length;
+
+ bd0 = sc->bd0;
+ bd0->mode.command = C0_SETDM;
+ bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
+ bd0->mode.count = sizeof(*context) / 4;
+ bd0->buffer_addr = sc->context_phys;
+ bd0->ext_buffer_addr = 2048 + (sizeof(*context) / 4) * chn;
+
+ WRITE4(sc, SDMAARM_HSTART, 1);
+
+#if 0
+ /* Debug purposes */
+
+ timeout = 1000;
+ while (!(ret = READ4(sc, SDMAARM_INTR) & 1)) {
+ if (timeout-- <= 0)
+ break;
+ DELAY(10);
+ };
+
+ if (!ret) {
+ device_printf(sc->dev, "Failed to load context.\n");
+ return (-1);
+ }
+
+ WRITE4(sc, SDMAARM_INTR, ret);
+
+ device_printf(sc->dev, "Context loaded successfully.\n");
+#endif
+
+ return (0);
+}
+
+static int
+load_firmware(struct sdma_softc *sc)
+{
+ struct sdma_firmware_header *header;
+ const struct firmware *fp;
+
+ fp = firmware_get("sdma_fw");
+ if (fp == NULL) {
+ device_printf(sc->dev, "Can't get firmware.\n");
+ return (-1);
+ }
+
+ header = (struct sdma_firmware_header *)fp->data;
+ if (header->magic != FW_HEADER_MAGIC) {
+ device_printf(sc->dev, "Can't use firmware.\n");
+ return (-1);
+ }
+
+ sc->fw_header = header;
+ sc->fw_scripts = (void *)((char *)header +
+ header->script_addrs_start);
+
+ return (0);
+}
+
+static int
+boot_firmware(struct sdma_softc *sc)
+{
+ struct sdma_buffer_descriptor *bd0;
+ uint32_t *ram_code;
+ int timeout;
+ int ret;
+ int chn;
+ int sz;
+ int i;
+
+ ram_code = (void *)((char *)sc->fw_header +
+ sc->fw_header->ram_code_start);
+
+ /* Make sure SDMA has not started yet */
+ WRITE4(sc, SDMAARM_MC0PTR, 0);
+
+ sz = SDMA_N_CHANNELS * sizeof(struct sdma_channel_control) + \
+ sizeof(struct sdma_context_data);
+ sc->ccb = (void *)kmem_alloc_contig(kernel_arena,
+ sz, M_ZERO, 0, ~0, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE);
+ sc->ccb_phys = vtophys(sc->ccb);
+
+ sc->context = (void *)((char *)sc->ccb + \
+ SDMA_N_CHANNELS * sizeof(struct sdma_channel_control));
+ sc->context_phys = vtophys(sc->context);
+
+ /* Disable all the channels */
+ for (i = 0; i < SDMA_N_EVENTS; i++)
+ WRITE4(sc, SDMAARM_CHNENBL(i), 0);
+
+ /* All channels have priority 0 */
+ for (i = 0; i < SDMA_N_CHANNELS; i++)
+ WRITE4(sc, SDMAARM_SDMA_CHNPRI(i), 0);
+
+ /* Channel 0 is used for booting firmware */
+ chn = 0;
+
+ sc->bd0 = (void *)kmem_alloc_contig(kernel_arena,
+ PAGE_SIZE, M_ZERO, 0, ~0, PAGE_SIZE, 0,
+ VM_MEMATTR_UNCACHEABLE);
+ bd0 = sc->bd0;
+ sc->ccb[chn].base_bd_ptr = vtophys(bd0);
+ sc->ccb[chn].current_bd_ptr = vtophys(bd0);
+
+ WRITE4(sc, SDMAARM_SDMA_CHNPRI(chn), 1);
+
+ sdma_overrides(sc, chn, 1, 0, 0);
+
+ /* XXX: not sure what is that */
+ WRITE4(sc, SDMAARM_CHN0ADDR, 0x4050);
+
+ WRITE4(sc, SDMAARM_CONFIG, 0);
+ WRITE4(sc, SDMAARM_MC0PTR, sc->ccb_phys);
+ WRITE4(sc, SDMAARM_CONFIG, CONFIG_CSM);
+ WRITE4(sc, SDMAARM_SDMA_CHNPRI(chn), 1);
+
+ bd0->mode.command = C0_SETPM;
+ bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
+ bd0->mode.count = sc->fw_header->ram_code_size / 2;
+ bd0->buffer_addr = vtophys(ram_code);
+ bd0->ext_buffer_addr = sc->fw_scripts->ram_code_start_addr;
+
+ WRITE4(sc, SDMAARM_HSTART, 1);
+
+ timeout = 100;
+ while (!(ret = READ4(sc, SDMAARM_INTR) & 1)) {
+ if (timeout-- <= 0)
+ break;
+ DELAY(10);
+ };
+
+ if (ret == 0) {
+ device_printf(sc->dev, "SDMA failed to boot\n");
+ return (-1);
+ }
+
+ WRITE4(sc, SDMAARM_INTR, ret);
+
+#if 0
+ device_printf(sc->dev, "SDMA booted successfully.\n");
+#endif
+
+ /* Debug is disabled */
+ WRITE4(sc, SDMAARM_ONCE_ENB, 0);
+
+ return (0);
+}
+
+static int
+sdma_attach(device_t dev)
+{
+ struct sdma_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, sdma_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ sdma_sc = sc;
+
+ /* Setup interrupt handler */
+ err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, sdma_intr, sc, &sc->ih);
+ if (err) {
+ device_printf(dev, "Unable to alloc interrupt resource.\n");
+ return (ENXIO);
+ }
+
+ if (load_firmware(sc) == -1)
+ return (ENXIO);
+
+ if (boot_firmware(sc) == -1)
+ return (ENXIO);
+
+ return (0);
+};
+
+static device_method_t sdma_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, sdma_probe),
+ DEVMETHOD(device_attach, sdma_attach),
+ { 0, 0 }
+};
+
+static driver_t sdma_driver = {
+ "sdma",
+ sdma_methods,
+ sizeof(struct sdma_softc),
+};
+
+static devclass_t sdma_devclass;
+
+DRIVER_MODULE(sdma, simplebus, sdma_driver, sdma_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/imx/imx6_sdma.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_sdma.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_sdma.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_sdma.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,246 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx6_sdma.h 283500 2015-05-24 18:59:45Z ian $
+ */
+
+#define SDMAARM_MC0PTR 0x00 /* ARM platform Channel 0 Pointer */
+#define SDMAARM_INTR 0x04 /* Channel Interrupts */
+#define SDMAARM_STOP_STAT 0x08 /* Channel Stop/Channel Status */
+#define SDMAARM_HSTART 0x0C /* Channel Start */
+#define SDMAARM_EVTOVR 0x10 /* Channel Event Override */
+#define SDMAARM_DSPOVR 0x14 /* Channel BP Override */
+#define SDMAARM_HOSTOVR 0x18 /* Channel ARM platform Override */
+#define SDMAARM_EVTPEND 0x1C /* Channel Event Pending */
+#define SDMAARM_RESET 0x24 /* Reset Register */
+#define SDMAARM_EVTERR 0x28 /* DMA Request Error Register */
+#define SDMAARM_INTRMASK 0x2C /* Channel ARM platform Interrupt Mask */
+#define SDMAARM_PSW 0x30 /* Schedule Status */
+#define SDMAARM_EVTERRDBG 0x34 /* DMA Request Error Register */
+#define SDMAARM_CONFIG 0x38 /* Configuration Register */
+#define CONFIG_CSM 0x3
+#define SDMAARM_SDMA_LOCK 0x3C /* SDMA LOCK */
+#define SDMAARM_ONCE_ENB 0x40 /* OnCE Enable */
+#define SDMAARM_ONCE_DATA 0x44 /* OnCE Data Register */
+#define SDMAARM_ONCE_INSTR 0x48 /* OnCE Instruction Register */
+#define SDMAARM_ONCE_STAT 0x4C /* OnCE Status Register */
+#define SDMAARM_ONCE_CMD 0x50 /* OnCE Command Register */
+#define SDMAARM_ILLINSTADDR 0x58 /* Illegal Instruction Trap Address */
+#define SDMAARM_CHN0ADDR 0x5C /* Channel 0 Boot Address */
+#define SDMAARM_EVT_MIRROR 0x60 /* DMA Requests */
+#define SDMAARM_EVT_MIRROR2 0x64 /* DMA Requests 2 */
+#define SDMAARM_XTRIG_CONF1 0x70 /* Cross-Trigger Events Configuration Register 1 */
+#define SDMAARM_XTRIG_CONF2 0x74 /* Cross-Trigger Events Configuration Register 2 */
+#define SDMAARM_SDMA_CHNPRI(n) (0x100 + 0x4 * n) /* Channel Priority Registers */
+#define SDMAARM_CHNENBL(n) (0x200 + 0x4 * n) /* Channel Enable RAM */
+
+/* SDMA Event Mappings */
+#define SSI1_RX_1 35
+#define SSI1_TX_1 36
+#define SSI1_RX_0 37
+#define SSI1_TX_0 38
+#define SSI2_RX_1 39
+#define SSI2_TX_1 40
+#define SSI2_RX_0 41
+#define SSI2_TX_0 42
+#define SSI3_RX_1 43
+#define SSI3_TX_1 44
+#define SSI3_RX_0 45
+#define SSI3_TX_0 46
+
+#define C0_ADDR 0x01
+#define C0_LOAD 0x02
+#define C0_DUMP 0x03
+#define C0_SETCTX 0x07
+#define C0_GETCTX 0x03
+#define C0_SETDM 0x01
+#define C0_SETPM 0x04
+#define C0_GETDM 0x02
+#define C0_GETPM 0x08
+
+#define BD_DONE 0x01
+#define BD_WRAP 0x02
+#define BD_CONT 0x04
+#define BD_INTR 0x08
+#define BD_RROR 0x10
+#define BD_LAST 0x20
+#define BD_EXTD 0x80
+
+/* sDMA data transfer length */
+#define CMD_4BYTES 0
+#define CMD_3BYTES 3
+#define CMD_2BYTES 2
+#define CMD_1BYTES 1
+
+struct sdma_firmware_header {
+ uint32_t magic;
+ uint32_t version_major;
+ uint32_t version_minor;
+ uint32_t script_addrs_start;
+ uint32_t num_script_addrs;
+ uint32_t ram_code_start;
+ uint32_t ram_code_size;
+};
+
+struct sdma_mode_count {
+ uint16_t count;
+ uint8_t status;
+ uint8_t command;
+};
+
+struct sdma_buffer_descriptor {
+ struct sdma_mode_count mode;
+ uint32_t buffer_addr;
+ uint32_t ext_buffer_addr;
+} __packed;
+
+struct sdma_channel_control {
+ uint32_t current_bd_ptr;
+ uint32_t base_bd_ptr;
+ uint32_t unused[2];
+} __packed;
+
+struct sdma_state_registers {
+ uint32_t pc :14;
+ uint32_t unused1: 1;
+ uint32_t t : 1;
+ uint32_t rpc :14;
+ uint32_t unused0: 1;
+ uint32_t sf : 1;
+ uint32_t spc :14;
+ uint32_t unused2: 1;
+ uint32_t df : 1;
+ uint32_t epc :14;
+ uint32_t lm : 2;
+} __packed;
+
+struct sdma_context_data {
+ struct sdma_state_registers channel_state;
+ uint32_t gReg[8];
+ uint32_t mda;
+ uint32_t msa;
+ uint32_t ms;
+ uint32_t md;
+ uint32_t pda;
+ uint32_t psa;
+ uint32_t ps;
+ uint32_t pd;
+ uint32_t ca;
+ uint32_t cs;
+ uint32_t dda;
+ uint32_t dsa;
+ uint32_t ds;
+ uint32_t dd;
+ uint32_t unused[8];
+} __packed;
+
+/* SDMA firmware script pointers */
+struct sdma_script_start_addrs {
+ int32_t ap_2_ap_addr;
+ int32_t ap_2_bp_addr;
+ int32_t ap_2_ap_fixed_addr;
+ int32_t bp_2_ap_addr;
+ int32_t loopback_on_dsp_side_addr;
+ int32_t mcu_interrupt_only_addr;
+ int32_t firi_2_per_addr;
+ int32_t firi_2_mcu_addr;
+ int32_t per_2_firi_addr;
+ int32_t mcu_2_firi_addr;
+ int32_t uart_2_per_addr;
+ int32_t uart_2_mcu_addr;
+ int32_t per_2_app_addr;
+ int32_t mcu_2_app_addr;
+ int32_t per_2_per_addr;
+ int32_t uartsh_2_per_addr;
+ int32_t uartsh_2_mcu_addr;
+ int32_t per_2_shp_addr;
+ int32_t mcu_2_shp_addr;
+ int32_t ata_2_mcu_addr;
+ int32_t mcu_2_ata_addr;
+ int32_t app_2_per_addr;
+ int32_t app_2_mcu_addr;
+ int32_t shp_2_per_addr;
+ int32_t shp_2_mcu_addr;
+ int32_t mshc_2_mcu_addr;
+ int32_t mcu_2_mshc_addr;
+ int32_t spdif_2_mcu_addr;
+ int32_t mcu_2_spdif_addr;
+ int32_t asrc_2_mcu_addr;
+ int32_t ext_mem_2_ipu_addr;
+ int32_t descrambler_addr;
+ int32_t dptc_dvfs_addr;
+ int32_t utra_addr;
+ int32_t ram_code_start_addr;
+ int32_t mcu_2_ssish_addr;
+ int32_t ssish_2_mcu_addr;
+ int32_t hdmi_dma_addr;
+};
+
+#define SDMA_N_CHANNELS 32
+#define SDMA_N_EVENTS 48
+#define FW_HEADER_MAGIC 0x414d4453
+
+struct sdma_channel {
+ struct sdma_conf *conf;
+ struct sdma_buffer_descriptor *bd;
+ uint8_t in_use;
+};
+
+struct sdma_softc {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ void *ih;
+ struct sdma_channel_control *ccb;
+ struct sdma_buffer_descriptor *bd0;
+ struct sdma_context_data *context;
+ struct sdma_channel channel[SDMA_N_CHANNELS];
+ uint32_t num_bd;
+ uint32_t ccb_phys;
+ uint32_t context_phys;
+ struct sdma_firmware_header *fw_header;
+ struct sdma_script_start_addrs *fw_scripts;
+};
+
+struct sdma_conf {
+ bus_addr_t saddr;
+ bus_addr_t daddr;
+ uint32_t word_length;
+ uint32_t nbits;
+ uint32_t command;
+ uint32_t num_bd;
+ uint32_t event;
+ uint32_t period;
+ uint32_t (*ih)(void *, int);
+ void *ih_user;
+};
+
+int sdma_configure(int, struct sdma_conf *);
+int sdma_start(int);
+int sdma_stop(int);
+int sdma_alloc(void);
+int sdma_free(int);
Property changes on: trunk/sys/arm/freescale/imx/imx6_sdma.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_ssi.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_ssi.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_ssi.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,856 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * i.MX6 Synchronous Serial Interface (SSI)
+ *
+ * Chapter 61, i.MX 6Dual/6Quad Applications Processor Reference Manual,
+ * Rev. 1, 04/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_ssi.c 283500 2015-05-24 18:59:45Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/chip.h>
+#include <mixer_if.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/imx/imx6_sdma.h>
+#include <arm/freescale/imx/imx6_anatopvar.h>
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+#define READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst, _sc->bsh, _reg)
+#define WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
+
+#define SSI_NCHANNELS 1
+
+/* i.MX6 SSI registers */
+
+#define SSI_STX0 0x00 /* Transmit Data Register n */
+#define SSI_STX1 0x04 /* Transmit Data Register n */
+#define SSI_SRX0 0x08 /* Receive Data Register n */
+#define SSI_SRX1 0x0C /* Receive Data Register n */
+#define SSI_SCR 0x10 /* Control Register */
+#define SCR_I2S_MODE_S 5 /* I2S Mode Select. */
+#define SCR_I2S_MODE_M 0x3
+#define SCR_SYN (1 << 4)
+#define SCR_NET (1 << 3) /* Network mode */
+#define SCR_RE (1 << 2) /* Receive Enable. */
+#define SCR_TE (1 << 1) /* Transmit Enable. */
+#define SCR_SSIEN (1 << 0) /* SSI Enable */
+#define SSI_SISR 0x14 /* Interrupt Status Register */
+#define SSI_SIER 0x18 /* Interrupt Enable Register */
+#define SIER_RDMAE (1 << 22) /* Receive DMA Enable. */
+#define SIER_RIE (1 << 21) /* Receive Interrupt Enable. */
+#define SIER_TDMAE (1 << 20) /* Transmit DMA Enable. */
+#define SIER_TIE (1 << 19) /* Transmit Interrupt Enable. */
+#define SIER_TDE0IE (1 << 12) /* Transmit Data Register Empty 0. */
+#define SIER_TUE0IE (1 << 8) /* Transmitter Underrun Error 0. */
+#define SIER_TFE0IE (1 << 0) /* Transmit FIFO Empty 0 IE. */
+#define SSI_STCR 0x1C /* Transmit Configuration Register */
+#define STCR_TXBIT0 (1 << 9) /* Transmit Bit 0 shift MSB/LSB */
+#define STCR_TFEN1 (1 << 8) /* Transmit FIFO Enable 1. */
+#define STCR_TFEN0 (1 << 7) /* Transmit FIFO Enable 0. */
+#define STCR_TFDIR (1 << 6) /* Transmit Frame Direction. */
+#define STCR_TXDIR (1 << 5) /* Transmit Clock Direction. */
+#define STCR_TSHFD (1 << 4) /* Transmit Shift Direction. */
+#define STCR_TSCKP (1 << 3) /* Transmit Clock Polarity. */
+#define STCR_TFSI (1 << 2) /* Transmit Frame Sync Invert. */
+#define STCR_TFSL (1 << 1) /* Transmit Frame Sync Length. */
+#define STCR_TEFS (1 << 0) /* Transmit Early Frame Sync. */
+#define SSI_SRCR 0x20 /* Receive Configuration Register */
+#define SSI_STCCR 0x24 /* Transmit Clock Control Register */
+#define STCCR_DIV2 (1 << 18) /* Divide By 2. */
+#define STCCR_PSR (1 << 17) /* Divide clock by 8. */
+#define WL3_WL0_S 13
+#define WL3_WL0_M 0xf
+#define DC4_DC0_S 8
+#define DC4_DC0_M 0x1f
+#define PM7_PM0_S 0
+#define PM7_PM0_M 0xff
+#define SSI_SRCCR 0x28 /* Receive Clock Control Register */
+#define SSI_SFCSR 0x2C /* FIFO Control/Status Register */
+#define SFCSR_RFWM1_S 20 /* Receive FIFO Empty WaterMark 1 */
+#define SFCSR_RFWM1_M 0xf
+#define SFCSR_TFWM1_S 16 /* Transmit FIFO Empty WaterMark 1 */
+#define SFCSR_TFWM1_M 0xf
+#define SFCSR_RFWM0_S 4 /* Receive FIFO Empty WaterMark 0 */
+#define SFCSR_RFWM0_M 0xf
+#define SFCSR_TFWM0_S 0 /* Transmit FIFO Empty WaterMark 0 */
+#define SFCSR_TFWM0_M 0xf
+#define SSI_SACNT 0x38 /* AC97 Control Register */
+#define SSI_SACADD 0x3C /* AC97 Command Address Register */
+#define SSI_SACDAT 0x40 /* AC97 Command Data Register */
+#define SSI_SATAG 0x44 /* AC97 Tag Register */
+#define SSI_STMSK 0x48 /* Transmit Time Slot Mask Register */
+#define SSI_SRMSK 0x4C /* Receive Time Slot Mask Register */
+#define SSI_SACCST 0x50 /* AC97 Channel Status Register */
+#define SSI_SACCEN 0x54 /* AC97 Channel Enable Register */
+#define SSI_SACCDIS 0x58 /* AC97 Channel Disable Register */
+
+static MALLOC_DEFINE(M_SSI, "ssi", "ssi audio");
+
+uint32_t ssi_dma_intr(void *arg, int chn);
+
+struct ssi_rate {
+ uint32_t speed;
+ uint32_t mfi; /* PLL4 Multiplication Factor Integer */
+ uint32_t mfn; /* PLL4 Multiplication Factor Numerator */
+ uint32_t mfd; /* PLL4 Multiplication Factor Denominator */
+ /* More dividers to configure can be added here */
+};
+
+static struct ssi_rate rate_map[] = {
+ { 192000, 49, 152, 1000 }, /* PLL4 49.152 Mhz */
+ /* TODO: add more frequences */
+ { 0, 0 },
+};
+
+/*
+ * i.MX6 example bit clock formula
+ *
+ * BCLK = 2 channels * 192000 hz * 24 bit = 9216000 hz =
+ * (24000000 * (49 + 152/1000.0) / 4 / 4 / 2 / 2 / 2 / 1 / 1)
+ * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
+ * | | | | | | | | | | |
+ * Fref ------/ | | | | | | | | | |
+ * PLL4 div select -/ | | | | | | | | |
+ * PLL4 num --------------/ | | | | | | | |
+ * PLL4 denom -------------------/ | | | | | | |
+ * PLL4 post div ---------------------/ | | | | | |
+ * CCM ssi pre div (CCM_CS1CDR) ----------/ | | | | |
+ * CCM ssi post div (CCM_CS1CDR) -------------/ | | | |
+ * SSI PM7_PM0_S ---------------------------------/ | | |
+ * SSI Fixed divider ---------------------------------/ | |
+ * SSI DIV2 ----------------------------------------------/ |
+ * SSI PSR (prescaler /1 or /8) ------------------------------/
+ *
+ * MCLK (Master clock) depends on DAC, usually BCLK * 4
+ */
+
+struct sc_info {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ struct mtx *lock;
+ void *ih;
+ int pos;
+ int dma_size;
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+ bus_addr_t buf_base_phys;
+ uint32_t *buf_base;
+ struct sdma_conf *conf;
+ struct ssi_rate *sr;
+ struct sdma_softc *sdma_sc;
+ int sdma_ev_rx;
+ int sdma_ev_tx;
+ int sdma_channel;
+};
+
+/* Channel registers */
+struct sc_chinfo {
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_pcminfo *parent;
+
+ /* Channel information */
+ uint32_t dir;
+ uint32_t format;
+
+ /* Flags */
+ uint32_t run;
+};
+
+/* PCM device private data */
+struct sc_pcminfo {
+ device_t dev;
+ uint32_t (*ih)(struct sc_pcminfo *scp);
+ uint32_t chnum;
+ struct sc_chinfo chan[SSI_NCHANNELS];
+ struct sc_info *sc;
+};
+
+static struct resource_spec ssi_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int setup_dma(struct sc_pcminfo *scp);
+static void setup_ssi(struct sc_info *);
+static void ssi_configure_clock(struct sc_info *);
+
+/*
+ * Mixer interface.
+ */
+
+static int
+ssimixer_init(struct snd_mixer *m)
+{
+ struct sc_pcminfo *scp;
+ struct sc_info *sc;
+ int mask;
+
+ scp = mix_getdevinfo(m);
+ sc = scp->sc;
+
+ if (sc == NULL)
+ return -1;
+
+ mask = SOUND_MASK_PCM;
+ mask |= SOUND_MASK_VOLUME;
+
+ snd_mtxlock(sc->lock);
+ pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL);
+ mix_setdevs(m, mask);
+ snd_mtxunlock(sc->lock);
+
+ return (0);
+}
+
+static int
+ssimixer_set(struct snd_mixer *m, unsigned dev,
+ unsigned left, unsigned right)
+{
+ struct sc_pcminfo *scp;
+
+ scp = mix_getdevinfo(m);
+
+ /* Here we can configure hardware volume on our DAC */
+
+#if 1
+ device_printf(scp->dev, "ssimixer_set() %d %d\n",
+ left, right);
+#endif
+
+ return (0);
+}
+
+static kobj_method_t ssimixer_methods[] = {
+ KOBJMETHOD(mixer_init, ssimixer_init),
+ KOBJMETHOD(mixer_set, ssimixer_set),
+ KOBJMETHOD_END
+};
+MIXER_DECLARE(ssimixer);
+
+
+/*
+ * Channel interface.
+ */
+
+static void *
+ssichan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
+ struct pcm_channel *c, int dir)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+
+ scp = (struct sc_pcminfo *)devinfo;
+ sc = scp->sc;
+
+ snd_mtxlock(sc->lock);
+ ch = &scp->chan[0];
+ ch->dir = dir;
+ ch->run = 0;
+ ch->buffer = b;
+ ch->channel = c;
+ ch->parent = scp;
+ snd_mtxunlock(sc->lock);
+
+ if (sndbuf_setup(ch->buffer, sc->buf_base, sc->dma_size) != 0) {
+ device_printf(scp->dev, "Can't setup sndbuf.\n");
+ return NULL;
+ }
+
+ return ch;
+}
+
+static int
+ssichan_free(kobj_t obj, void *data)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_pcminfo *scp = ch->parent;
+ struct sc_info *sc = scp->sc;
+
+#if 0
+ device_printf(scp->dev, "ssichan_free()\n");
+#endif
+
+ snd_mtxlock(sc->lock);
+ /* TODO: free channel buffer */
+ snd_mtxunlock(sc->lock);
+
+ return (0);
+}
+
+static int
+ssichan_setformat(kobj_t obj, void *data, uint32_t format)
+{
+ struct sc_chinfo *ch = data;
+
+ ch->format = format;
+
+ return (0);
+}
+
+static uint32_t
+ssichan_setspeed(kobj_t obj, void *data, uint32_t speed)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct ssi_rate *sr;
+ struct sc_info *sc;
+ int threshold;
+ int i;
+
+ ch = data;
+ scp = ch->parent;
+ sc = scp->sc;
+
+ sr = NULL;
+
+ /* First look for equal frequency. */
+ for (i = 0; rate_map[i].speed != 0; i++) {
+ if (rate_map[i].speed == speed)
+ sr = &rate_map[i];
+ }
+
+ /* If no match, just find nearest. */
+ if (sr == NULL) {
+ for (i = 0; rate_map[i].speed != 0; i++) {
+ sr = &rate_map[i];
+ threshold = sr->speed + ((rate_map[i + 1].speed != 0) ?
+ ((rate_map[i + 1].speed - sr->speed) >> 1) : 0);
+ if (speed < threshold)
+ break;
+ }
+ }
+
+ sc->sr = sr;
+
+ ssi_configure_clock(sc);
+
+ return (sr->speed);
+}
+
+static void
+ssi_configure_clock(struct sc_info *sc)
+{
+ struct ssi_rate *sr;
+
+ sr = sc->sr;
+
+ pll4_configure_output(sr->mfi, sr->mfn, sr->mfd);
+
+ /* Configure other dividers here, if any */
+}
+
+static uint32_t
+ssichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_pcminfo *scp = ch->parent;
+ struct sc_info *sc = scp->sc;
+
+ sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize);
+
+ setup_dma(scp);
+
+ return (sndbuf_getblksz(ch->buffer));
+}
+
+uint32_t
+ssi_dma_intr(void *arg, int chn)
+{
+ struct sc_pcminfo *scp;
+ struct sdma_conf *conf;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+ int bufsize;
+
+ scp = arg;
+ ch = &scp->chan[0];
+ sc = scp->sc;
+ conf = sc->conf;
+
+ bufsize = sndbuf_getsize(ch->buffer);
+
+ sc->pos += conf->period;
+ if (sc->pos >= bufsize)
+ sc->pos -= bufsize;
+
+ if (ch->run)
+ chn_intr(ch->channel);
+
+ return (0);
+}
+
+static int
+find_sdma_controller(struct sc_info *sc)
+{
+ struct sdma_softc *sdma_sc;
+ phandle_t node, sdma_node;
+ device_t sdma_dev;
+ int dts_value[8];
+ int len;
+
+ if ((node = ofw_bus_get_node(sc->dev)) == -1)
+ return (ENXIO);
+
+ if ((len = OF_getproplen(node, "dmas")) <= 0)
+ return (ENXIO);
+
+ OF_getprop(node, "dmas", &dts_value, len);
+
+ sc->sdma_ev_rx = fdt32_to_cpu(dts_value[1]);
+ sc->sdma_ev_tx = fdt32_to_cpu(dts_value[5]);
+
+ sdma_node = OF_node_from_xref(fdt32_to_cpu(dts_value[0]));
+
+ sdma_sc = NULL;
+
+ sdma_dev = devclass_get_device(devclass_find("sdma"), 0);
+ if (sdma_dev)
+ sdma_sc = device_get_softc(sdma_dev);
+
+ if (sdma_sc == NULL) {
+ device_printf(sc->dev, "No sDMA found. Can't operate\n");
+ return (ENXIO);
+ };
+
+ sc->sdma_sc = sdma_sc;
+
+ return (0);
+};
+
+static int
+setup_dma(struct sc_pcminfo *scp)
+{
+ struct sdma_conf *conf;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+ int fmt;
+
+ ch = &scp->chan[0];
+ sc = scp->sc;
+ conf = sc->conf;
+
+ conf->ih = ssi_dma_intr;
+ conf->ih_user = scp;
+ conf->saddr = sc->buf_base_phys;
+ conf->daddr = rman_get_start(sc->res[0]) + SSI_STX0;
+ conf->event = sc->sdma_ev_tx; /* SDMA TX event */
+ conf->period = sndbuf_getblksz(ch->buffer);
+ conf->num_bd = sndbuf_getblkcnt(ch->buffer);
+
+ /*
+ * Word Length
+ * Can be 32, 24, 16 or 8 for sDMA.
+ *
+ * SSI supports 24 at max.
+ */
+
+ fmt = sndbuf_getfmt(ch->buffer);
+
+ if (fmt & AFMT_16BIT) {
+ conf->word_length = 16;
+ conf->command = CMD_2BYTES;
+ } else if (fmt & AFMT_24BIT) {
+ conf->word_length = 24;
+ conf->command = CMD_3BYTES;
+ } else {
+ device_printf(sc->dev, "Unknown format\n");
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+ssi_start(struct sc_pcminfo *scp)
+{
+ struct sc_info *sc;
+ int reg;
+
+ sc = scp->sc;
+
+ if (sdma_configure(sc->sdma_channel, sc->conf) != 0) {
+ device_printf(sc->dev, "Can't configure sDMA\n");
+ return (-1);
+ }
+
+ /* Enable DMA interrupt */
+ reg = (SIER_TDMAE);
+ WRITE4(sc, SSI_SIER, reg);
+
+ sdma_start(sc->sdma_channel);
+
+ return (0);
+}
+
+static int
+ssi_stop(struct sc_pcminfo *scp)
+{
+ struct sc_info *sc;
+ int reg;
+
+ sc = scp->sc;
+
+ reg = READ4(sc, SSI_SIER);
+ reg &= ~(SIER_TDMAE);
+ WRITE4(sc, SSI_SIER, reg);
+
+ sdma_stop(sc->sdma_channel);
+
+ bzero(sc->buf_base, sc->dma_size);
+
+ return (0);
+}
+
+static int
+ssichan_trigger(kobj_t obj, void *data, int go)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+
+ ch = data;
+ scp = ch->parent;
+ sc = scp->sc;
+
+ snd_mtxlock(sc->lock);
+
+ switch (go) {
+ case PCMTRIG_START:
+#if 0
+ device_printf(scp->dev, "trigger start\n");
+#endif
+ ch->run = 1;
+
+ ssi_start(scp);
+
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+#if 0
+ device_printf(scp->dev, "trigger stop or abort\n");
+#endif
+ ch->run = 0;
+
+ ssi_stop(scp);
+
+ break;
+ }
+
+ snd_mtxunlock(sc->lock);
+
+ return (0);
+}
+
+static uint32_t
+ssichan_getptr(kobj_t obj, void *data)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+
+ ch = data;
+ scp = ch->parent;
+ sc = scp->sc;
+
+ return (sc->pos);
+}
+
+static uint32_t ssi_pfmt[] = {
+ SND_FORMAT(AFMT_S24_LE, 2, 0),
+ 0
+};
+
+static struct pcmchan_caps ssi_pcaps = {44100, 192000, ssi_pfmt, 0};
+
+static struct pcmchan_caps *
+ssichan_getcaps(kobj_t obj, void *data)
+{
+
+ return (&ssi_pcaps);
+}
+
+static kobj_method_t ssichan_methods[] = {
+ KOBJMETHOD(channel_init, ssichan_init),
+ KOBJMETHOD(channel_free, ssichan_free),
+ KOBJMETHOD(channel_setformat, ssichan_setformat),
+ KOBJMETHOD(channel_setspeed, ssichan_setspeed),
+ KOBJMETHOD(channel_setblocksize, ssichan_setblocksize),
+ KOBJMETHOD(channel_trigger, ssichan_trigger),
+ KOBJMETHOD(channel_getptr, ssichan_getptr),
+ KOBJMETHOD(channel_getcaps, ssichan_getcaps),
+ KOBJMETHOD_END
+};
+CHANNEL_DECLARE(ssichan);
+
+static int
+ssi_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,imx6q-ssi"))
+ return (ENXIO);
+
+ device_set_desc(dev, "i.MX6 Synchronous Serial Interface (SSI)");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static void
+ssi_intr(void *arg)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+
+ scp = arg;
+ sc = scp->sc;
+ ch = &scp->chan[0];
+
+ /* We don't use SSI interrupt */
+#if 0
+ device_printf(sc->dev, "SSI Intr 0x%08x\n",
+ READ4(sc, SSI_SISR));
+#endif
+}
+
+static void
+setup_ssi(struct sc_info *sc)
+{
+ int reg;
+
+ reg = READ4(sc, SSI_STCCR);
+ reg &= ~(WL3_WL0_M << WL3_WL0_S);
+ reg |= (0xb << WL3_WL0_S); /* 24 bit */
+ reg &= ~(DC4_DC0_M << DC4_DC0_S);
+ reg |= (1 << DC4_DC0_S); /* 2 words per frame */
+ reg &= ~(STCCR_DIV2); /* Divide by 1 */
+ reg &= ~(STCCR_PSR); /* Divide by 1 */
+ reg &= ~(PM7_PM0_M << PM7_PM0_S);
+ reg |= (1 << PM7_PM0_S); /* Divide by 2 */
+ WRITE4(sc, SSI_STCCR, reg);
+
+ reg = READ4(sc, SSI_SFCSR);
+ reg &= ~(SFCSR_TFWM0_M << SFCSR_TFWM0_S);
+ reg |= (8 << SFCSR_TFWM0_S); /* empty slots */
+ WRITE4(sc, SSI_SFCSR, reg);
+
+ reg = READ4(sc, SSI_STCR);
+ reg |= (STCR_TFEN0);
+ reg &= ~(STCR_TFEN1);
+ reg &= ~(STCR_TSHFD); /* MSB */
+ reg |= (STCR_TXBIT0);
+ reg |= (STCR_TXDIR | STCR_TFDIR);
+ reg |= (STCR_TSCKP); /* falling edge */
+ reg |= (STCR_TFSI);
+ reg &= ~(STCR_TFSI); /* active high frame sync */
+ reg &= ~(STCR_TFSL);
+ reg |= STCR_TEFS;
+ WRITE4(sc, SSI_STCR, reg);
+
+ reg = READ4(sc, SSI_SCR);
+ reg &= ~(SCR_I2S_MODE_M << SCR_I2S_MODE_S); /* Not master */
+ reg |= (SCR_SSIEN | SCR_TE);
+ reg |= (SCR_NET);
+ reg |= (SCR_SYN);
+ WRITE4(sc, SSI_SCR, reg);
+}
+
+static void
+ssi_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+
+ addr = (bus_addr_t*)arg;
+ *addr = segs[0].ds_addr;
+}
+
+static int
+ssi_attach(device_t dev)
+{
+ char status[SND_STATUSLEN];
+ struct sc_pcminfo *scp;
+ struct sc_info *sc;
+ int err;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->dev = dev;
+ sc->sr = &rate_map[0];
+ sc->pos = 0;
+ sc->conf = malloc(sizeof(struct sdma_conf), M_DEVBUF, M_WAITOK | M_ZERO);
+
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "ssi softc");
+ if (sc->lock == NULL) {
+ device_printf(dev, "Cant create mtx\n");
+ return (ENXIO);
+ }
+
+ if (bus_alloc_resources(dev, ssi_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /* SDMA */
+ if (find_sdma_controller(sc)) {
+ device_printf(dev, "could not find active SDMA\n");
+ return (ENXIO);
+ }
+
+ /* Setup PCM */
+ scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ scp->sc = sc;
+ scp->dev = dev;
+
+ /*
+ * Maximum possible DMA buffer.
+ * Will be used partialy to match 24 bit word.
+ */
+ sc->dma_size = 131072;
+
+ /*
+ * Must use dma_size boundary as modulo feature required.
+ * Modulo feature allows setup circular buffer.
+ */
+
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev),
+ 4, sc->dma_size, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ sc->dma_size, 1, /* maxsize, nsegments */
+ sc->dma_size, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->dma_tag);
+
+ err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->buf_base,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->dma_map);
+ if (err) {
+ device_printf(dev, "cannot allocate framebuffer\n");
+ return (ENXIO);
+ }
+
+ err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->buf_base,
+ sc->dma_size, ssi_dmamap_cb, &sc->buf_base_phys, BUS_DMA_NOWAIT);
+ if (err) {
+ device_printf(dev, "cannot load DMA map\n");
+ return (ENXIO);
+ }
+
+ bzero(sc->buf_base, sc->dma_size);
+
+ /* Setup interrupt handler */
+ err = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_AV,
+ NULL, ssi_intr, scp, &sc->ih);
+ if (err) {
+ device_printf(dev, "Unable to alloc interrupt resource.\n");
+ return (ENXIO);
+ }
+
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
+
+ err = pcm_register(dev, scp, 1, 0);
+ if (err) {
+ device_printf(dev, "Can't register pcm.\n");
+ return (ENXIO);
+ }
+
+ scp->chnum = 0;
+ pcm_addchan(dev, PCMDIR_PLAY, &ssichan_class, scp);
+ scp->chnum++;
+
+ snprintf(status, SND_STATUSLEN, "at simplebus");
+ pcm_setstatus(dev, status);
+
+ mixer_init(dev, &ssimixer_class, scp);
+ setup_ssi(sc);
+
+ imx_ccm_ssi_configure(dev);
+
+ sc->sdma_channel = sdma_alloc();
+ if (sc->sdma_channel < 0) {
+ device_printf(sc->dev, "Can't get sDMA channel\n");
+ return (1);
+ }
+
+ return (0);
+}
+
+static device_method_t ssi_pcm_methods[] = {
+ DEVMETHOD(device_probe, ssi_probe),
+ DEVMETHOD(device_attach, ssi_attach),
+ { 0, 0 }
+};
+
+static driver_t ssi_pcm_driver = {
+ "pcm",
+ ssi_pcm_methods,
+ PCM_SOFTC_SIZE,
+};
+
+DRIVER_MODULE(ssi, simplebus, ssi_pcm_driver, pcm_devclass, 0, 0);
+MODULE_DEPEND(ssi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
+MODULE_VERSION(ssi, 1);
Property changes on: trunk/sys/arm/freescale/imx/imx6_ssi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx6_usbphy.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx6_usbphy.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx6_usbphy.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,193 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx6_usbphy.c 266371 2014-05-17 22:29:24Z ian $");
+
+/*
+ * USBPHY driver for Freescale i.MX6 family of SoCs.
+ */
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include <arm/freescale/imx/imx_ccmvar.h>
+#include <arm/freescale/imx/imx6_anatopreg.h>
+#include <arm/freescale/imx/imx6_anatopvar.h>
+
+/*
+ * Hardware register defines.
+ */
+#define PWD_REG 0x0000
+#define CTRL_STATUS_REG 0x0030
+#define CTRL_SET_REG 0x0034
+#define CTRL_CLR_REG 0x0038
+#define CTRL_TOGGLE_REG 0x003c
+#define CTRL_SFTRST (1U << 31)
+#define CTRL_CLKGATE (1 << 30)
+#define CTRL_ENUTMILEVEL3 (1 << 15)
+#define CTRL_ENUTMILEVEL2 (1 << 14)
+
+struct usbphy_softc {
+ device_t dev;
+ struct resource *mem_res;
+ u_int phy_num;
+};
+
+static int
+usbphy_detach(device_t dev)
+{
+ struct usbphy_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (0);
+}
+
+static int
+usbphy_attach(device_t dev)
+{
+ struct usbphy_softc *sc;
+ int err, regoff, rid;
+
+ sc = device_get_softc(dev);
+ err = 0;
+
+ /* Allocate bus_space resources. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ /*
+ * XXX Totally lame way to get the unit number (but not quite as lame as
+ * adding an ad-hoc property to the fdt data). This works as long as
+ * this driver is used for imx6 only.
+ */
+ const uint32_t PWD_PHY1_REG_PHYSADDR = 0x020c9000;
+ if (BUS_SPACE_PHYSADDR(sc->mem_res, 0) == PWD_PHY1_REG_PHYSADDR) {
+ sc->phy_num = 0;
+ regoff = 0;
+ } else {
+ sc->phy_num = 1;
+ regoff = 0x60;
+ }
+
+ /*
+ * Based on a note in the u-boot source code, disable charger detection
+ * to avoid degrading the differential signaling on the DP line. Note
+ * that this disables (by design) both charger detection and contact
+ * detection, because of the screwball mix of active-high and active-low
+ * bits in this register.
+ */
+ imx6_anatop_write_4(IMX6_ANALOG_USB1_CHRG_DETECT + regoff,
+ IMX6_ANALOG_USB_CHRG_DETECT_N_ENABLE |
+ IMX6_ANALOG_USB_CHRG_DETECT_N_CHK_CHRG);
+
+ imx6_anatop_write_4(IMX6_ANALOG_USB1_CHRG_DETECT + regoff,
+ IMX6_ANALOG_USB_CHRG_DETECT_N_ENABLE |
+ IMX6_ANALOG_USB_CHRG_DETECT_N_CHK_CHRG);
+
+ /* XXX Configure the overcurrent detection here. */
+
+ /*
+ * Turn on the phy clocks.
+ */
+ imx_ccm_usbphy_enable(dev);
+
+ /*
+ * Set the software reset bit, then clear both it and the clock gate bit
+ * to bring the device out of reset with the clock running.
+ */
+ bus_write_4(sc->mem_res, CTRL_SET_REG, CTRL_SFTRST);
+ bus_write_4(sc->mem_res, CTRL_CLR_REG, CTRL_SFTRST | CTRL_CLKGATE);
+
+ /* Power up: clear all bits in the powerdown register. */
+ bus_write_4(sc->mem_res, PWD_REG, 0);
+
+ err = 0;
+
+out:
+
+ if (err != 0)
+ usbphy_detach(dev);
+
+ return (err);
+}
+
+static int
+usbphy_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "fsl,imx6q-usbphy") == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale i.MX6 USB PHY");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static device_method_t usbphy_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, usbphy_probe),
+ DEVMETHOD(device_attach, usbphy_attach),
+ DEVMETHOD(device_detach, usbphy_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t usbphy_driver = {
+ "usbphy",
+ usbphy_methods,
+ sizeof(struct usbphy_softc)
+};
+
+static devclass_t usbphy_devclass;
+
+DRIVER_MODULE(usbphy, simplebus, usbphy_driver, usbphy_devclass, 0, 0);
+
Property changes on: trunk/sys/arm/freescale/imx/imx6_usbphy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_ccmvar.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx_ccmvar.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_ccmvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,61 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx_ccmvar.h 283501 2015-05-24 19:00:46Z ian $
+ */
+
+#ifndef IMX_CCMVAR_H
+#define IMX_CCMVAR_H
+
+/*
+ * We need a clock management system that works across unrelated SoCs and
+ * devices. For now, to keep imx development moving, define some barebones
+ * functionality that can be shared within the imx family by having each SoC
+ * implement functions with a common name.
+ *
+ * The usb enable functions are best-effort. They turn on the usb otg, host,
+ * and phy clocks in a SoC-specific manner, but it may take a lot more than that
+ * to make usb work on a given board. In particular, it can require specific
+ * pinmux setup of gpio pins connected to external phy parts, voltage regulators
+ * and overcurrent detectors, and so on. On such boards, u-boot or other early
+ * board setup code has to handle those things.
+ */
+
+uint32_t imx_ccm_ipg_hz(void);
+uint32_t imx_ccm_perclk_hz(void);
+uint32_t imx_ccm_sdhci_hz(void);
+uint32_t imx_ccm_uart_hz(void);
+uint32_t imx_ccm_ahb_hz(void);
+
+void imx_ccm_usb_enable(device_t _usbdev);
+void imx_ccm_usbphy_enable(device_t _phydev);
+void imx_ccm_ssi_configure(device_t _ssidev);
+
+/* Routines to get and set the arm clock root divisor register. */
+uint32_t imx_ccm_get_cacrr(void);
+void imx_ccm_set_cacrr(uint32_t _divisor);
+
+#endif
Property changes on: trunk/sys/arm/freescale/imx/imx_ccmvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_common.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_common.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,76 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD.
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_global.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx_common.c 266277 2014-05-17 00:53:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kdb.h>
+#include <sys/reboot.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_intc_decode_ic,
+ NULL
+};
Property changes on: trunk/sys/arm/freescale/imx/imx_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_gpio.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_gpio.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,482 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Freescale i.MX515 GPIO driver.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx_gpio.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "gpio_if.h"
+
+#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define GPIO_LOCK_INIT(_sc) mtx_init(&_sc->sc_mtx, \
+ device_get_nameunit(_sc->sc_dev), "imx_gpio", MTX_DEF)
+#define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+#define WRITE4(_sc, _r, _v) \
+ bus_space_write_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r), (_v))
+#define READ4(_sc, _r) \
+ bus_space_read_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r))
+#define SET4(_sc, _r, _m) \
+ WRITE4((_sc), (_r), READ4((_sc), (_r)) | (_m))
+#define CLEAR4(_sc, _r, _m) \
+ WRITE4((_sc), (_r), READ4((_sc), (_r)) & ~(_m))
+
+/* Registers definition for Freescale i.MX515 GPIO controller */
+
+#define IMX_GPIO_DR_REG 0x000 /* Pin Data */
+#define IMX_GPIO_OE_REG 0x004 /* Set Pin Output */
+#define IMX_GPIO_PSR_REG 0x008 /* Pad Status */
+#define IMX_GPIO_ICR1_REG 0x00C /* Interrupt Configuration */
+#define IMX_GPIO_ICR2_REG 0x010 /* Interrupt Configuration */
+#define GPIO_ICR_COND_LOW 0
+#define GPIO_ICR_COND_HIGH 1
+#define GPIO_ICR_COND_RISE 2
+#define GPIO_ICR_COND_FALL 3
+#define IMX_GPIO_IMR_REG 0x014 /* Interrupt Mask Register */
+#define IMX_GPIO_ISR_REG 0x018 /* Interrupt Status Register */
+#define IMX_GPIO_EDGE_REG 0x01C /* Edge Detect Register */
+
+#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
+#define NGPIO 32
+
+struct imx51_gpio_softc {
+ device_t dev;
+ struct mtx sc_mtx;
+ struct resource *sc_res[11]; /* 1 x mem, 2 x IRQ, 8 x IRQ */
+ void *gpio_ih[11]; /* 1 ptr is not a big waste */
+ int sc_l_irq; /* Last irq resource */
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ int gpio_npins;
+ struct gpio_pin gpio_pins[NGPIO];
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6q-gpio", 1},
+ {"fsl,imx53-gpio", 1},
+ {"fsl,imx51-gpio", 1},
+ {NULL, 0}
+};
+
+static struct resource_spec imx_gpio_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct resource_spec imx_gpio0irq_spec[] = {
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { SYS_RES_IRQ, 4, RF_ACTIVE },
+ { SYS_RES_IRQ, 5, RF_ACTIVE },
+ { SYS_RES_IRQ, 6, RF_ACTIVE },
+ { SYS_RES_IRQ, 7, RF_ACTIVE },
+ { SYS_RES_IRQ, 8, RF_ACTIVE },
+ { SYS_RES_IRQ, 9, RF_ACTIVE },
+ { -1, 0 }
+};
+
+/*
+ * Helpers
+ */
+static void imx51_gpio_pin_configure(struct imx51_gpio_softc *,
+ struct gpio_pin *, uint32_t);
+
+/*
+ * Driver stuff
+ */
+static int imx51_gpio_probe(device_t);
+static int imx51_gpio_attach(device_t);
+static int imx51_gpio_detach(device_t);
+static int imx51_gpio_intr(void *);
+
+/*
+ * GPIO interface
+ */
+static int imx51_gpio_pin_max(device_t, int *);
+static int imx51_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
+static int imx51_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
+static int imx51_gpio_pin_getname(device_t, uint32_t, char *);
+static int imx51_gpio_pin_setflags(device_t, uint32_t, uint32_t);
+static int imx51_gpio_pin_set(device_t, uint32_t, unsigned int);
+static int imx51_gpio_pin_get(device_t, uint32_t, unsigned int *);
+static int imx51_gpio_pin_toggle(device_t, uint32_t pin);
+
+static void
+imx51_gpio_pin_configure(struct imx51_gpio_softc *sc, struct gpio_pin *pin,
+ unsigned int flags)
+{
+
+ GPIO_LOCK(sc);
+
+ /*
+ * Manage input/output
+ */
+ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
+ pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
+ if (flags & GPIO_PIN_OUTPUT) {
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+ SET4(sc, IMX_GPIO_OE_REG, (1 << pin->gp_pin));
+ }
+ else {
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ CLEAR4(sc, IMX_GPIO_OE_REG, (1 << pin->gp_pin));
+ }
+ }
+
+ GPIO_UNLOCK(sc);
+}
+
+static int
+imx51_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = NGPIO - 1;
+ return (0);
+}
+
+static int
+imx51_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct imx51_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *caps = sc->gpio_pins[i].gp_caps;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+imx51_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct imx51_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *flags = sc->gpio_pins[i].gp_flags;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+imx51_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct imx51_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+imx51_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct imx51_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ imx51_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
+
+ return (0);
+}
+
+static int
+imx51_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct imx51_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ if (value)
+ SET4(sc, IMX_GPIO_DR_REG, (1 << i));
+ else
+ CLEAR4(sc, IMX_GPIO_DR_REG, (1 << i));
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+imx51_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct imx51_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *val = (READ4(sc, IMX_GPIO_DR_REG) >> i) & 1;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+imx51_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct imx51_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ WRITE4(sc, IMX_GPIO_DR_REG,
+ (READ4(sc, IMX_GPIO_DR_REG) ^ (1 << i)));
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+imx51_gpio_intr(void *arg)
+{
+ struct imx51_gpio_softc *sc;
+ uint32_t input, value;
+
+ sc = arg;
+ input = READ4(sc, IMX_GPIO_ISR_REG);
+ value = input & READ4(sc, IMX_GPIO_IMR_REG);
+ WRITE4(sc, IMX_GPIO_ISR_REG, input);
+
+ if (!value)
+ goto intr_done;
+
+ /* TODO: interrupt handling */
+
+intr_done:
+ return (FILTER_HANDLED);
+}
+
+static int
+imx51_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Freescale i.MX GPIO Controller");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+imx51_gpio_attach(device_t dev)
+{
+ struct imx51_gpio_softc *sc;
+ int i, irq;
+
+ sc = device_get_softc(dev);
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ if (bus_alloc_resources(dev, imx_gpio_spec, sc->sc_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->dev = dev;
+ sc->gpio_npins = NGPIO;
+ sc->sc_l_irq = 2;
+ sc->sc_iot = rman_get_bustag(sc->sc_res[0]);
+ sc->sc_ioh = rman_get_bushandle(sc->sc_res[0]);
+
+ if (bus_alloc_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]) == 0) {
+ /*
+ * First GPIO unit able to serve +8 interrupts for 8 first
+ * pins.
+ */
+ sc->sc_l_irq = 10;
+ }
+
+ for (irq = 1; irq <= sc->sc_l_irq; irq ++) {
+ if ((bus_setup_intr(dev, sc->sc_res[irq], INTR_TYPE_MISC,
+ imx51_gpio_intr, NULL, sc, &sc->gpio_ih[irq]))) {
+ device_printf(dev,
+ "WARNING: unable to register interrupt handler\n");
+ return (ENXIO);
+ }
+ }
+
+ for (i = 0; i < sc->gpio_npins; i++) {
+ sc->gpio_pins[i].gp_pin = i;
+ sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
+ sc->gpio_pins[i].gp_flags =
+ (READ4(sc, IMX_GPIO_OE_REG) & (1 << i)) ? GPIO_PIN_OUTPUT:
+ GPIO_PIN_INPUT;
+ snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
+ "imx_gpio%d.%d", device_get_unit(dev), i);
+ }
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+imx51_gpio_detach(device_t dev)
+{
+ struct imx51_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
+
+ bus_generic_detach(dev);
+
+ if (sc->sc_res[3])
+ bus_release_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]);
+
+ if (sc->sc_res[0])
+ bus_release_resources(dev, imx_gpio_spec, sc->sc_res);
+
+ mtx_destroy(&sc->sc_mtx);
+
+ return(0);
+}
+
+static device_method_t imx51_gpio_methods[] = {
+ DEVMETHOD(device_probe, imx51_gpio_probe),
+ DEVMETHOD(device_attach, imx51_gpio_attach),
+ DEVMETHOD(device_detach, imx51_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, imx51_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, imx51_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, imx51_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, imx51_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, imx51_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, imx51_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, imx51_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, imx51_gpio_pin_toggle),
+ {0, 0},
+};
+
+static driver_t imx51_gpio_driver = {
+ "gpio",
+ imx51_gpio_methods,
+ sizeof(struct imx51_gpio_softc),
+};
+static devclass_t imx51_gpio_devclass;
+
+DRIVER_MODULE(imx51_gpio, simplebus, imx51_gpio_driver, imx51_gpio_devclass,
+ 0, 0);
Property changes on: trunk/sys/arm/freescale/imx/imx_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_gpt.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_gpt.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_gpt.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,417 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx_gpt.c 273681 2014-10-26 04:15:27Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <machine/fdt.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/freescale/imx/imx_gptvar.h>
+#include <arm/freescale/imx/imx_gptreg.h>
+
+#include <sys/kdb.h>
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+#define WRITE4(_sc, _r, _v) \
+ bus_space_write_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r), (_v))
+#define READ4(_sc, _r) \
+ bus_space_read_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r))
+#define SET4(_sc, _r, _m) \
+ WRITE4((_sc), (_r), READ4((_sc), (_r)) | (_m))
+#define CLEAR4(_sc, _r, _m) \
+ WRITE4((_sc), (_r), READ4((_sc), (_r)) & ~(_m))
+
+static u_int imx_gpt_get_timecount(struct timecounter *);
+static int imx_gpt_timer_start(struct eventtimer *, sbintime_t,
+ sbintime_t);
+static int imx_gpt_timer_stop(struct eventtimer *);
+
+static int imx_gpt_intr(void *);
+static int imx_gpt_probe(device_t);
+static int imx_gpt_attach(device_t);
+
+static struct timecounter imx_gpt_timecounter = {
+ .tc_name = "iMXGPT",
+ .tc_get_timecount = imx_gpt_get_timecount,
+ .tc_counter_mask = ~0u,
+ .tc_frequency = 0,
+ .tc_quality = 1000,
+};
+
+/* Global softc pointer for use in DELAY(). */
+struct imx_gpt_softc *imx_gpt_sc = NULL;
+
+/*
+ * Hand-calibrated delay-loop counter. This was calibrated on an i.MX6 running
+ * at 792mhz. It will delay a bit too long on slower processors -- that's
+ * better than not delaying long enough. In practice this is unlikely to get
+ * used much since the clock driver is one of the first to start up, and once
+ * we're attached the delay loop switches to using the timer hardware.
+ */
+static const int imx_gpt_delay_count = 78;
+
+/* Try to divide down an available fast clock to this frequency. */
+#define TARGET_FREQUENCY 1000000000
+
+/* Don't try to set an event timer period smaller than this. */
+#define MIN_ET_PERIOD 10LLU
+
+
+static struct resource_spec imx_gpt_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6q-gpt", 1},
+ {"fsl,imx53-gpt", 1},
+ {"fsl,imx51-gpt", 1},
+ {"fsl,imx31-gpt", 1},
+ {"fsl,imx27-gpt", 1},
+ {"fsl,imx25-gpt", 1},
+ {NULL, 0}
+};
+
+static int
+imx_gpt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Freescale i.MX GPT timer");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+imx_gpt_attach(device_t dev)
+{
+ struct imx_gpt_softc *sc;
+ int ctlreg, err;
+ uint32_t basefreq, prescale;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, imx_gpt_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->sc_dev = dev;
+ sc->sc_iot = rman_get_bustag(sc->res[0]);
+ sc->sc_ioh = rman_get_bushandle(sc->res[0]);
+
+ /*
+ * For now, just automatically choose a good clock for the hardware
+ * we're running on. Eventually we could allow selection from the fdt;
+ * the code in this driver will cope with any clock frequency.
+ */
+ sc->sc_clksrc = GPT_CR_CLKSRC_IPG;
+
+ ctlreg = 0;
+
+ switch (sc->sc_clksrc) {
+ case GPT_CR_CLKSRC_32K:
+ basefreq = 32768;
+ break;
+ case GPT_CR_CLKSRC_IPG:
+ basefreq = imx_ccm_ipg_hz();
+ break;
+ case GPT_CR_CLKSRC_IPG_HIGH:
+ basefreq = imx_ccm_ipg_hz() * 2;
+ break;
+ case GPT_CR_CLKSRC_24M:
+ ctlreg |= GPT_CR_24MEN;
+ basefreq = 24000000;
+ break;
+ case GPT_CR_CLKSRC_NONE:/* Can't run without a clock. */
+ case GPT_CR_CLKSRC_EXT: /* No way to get the freq of an ext clock. */
+ default:
+ device_printf(dev, "Unsupported clock source '%d'\n",
+ sc->sc_clksrc);
+ return (EINVAL);
+ }
+
+ /*
+ * The following setup sequence is from the I.MX6 reference manual,
+ * "Selecting the clock source". First, disable the clock and
+ * interrupts. This also clears input and output mode bits and in
+ * general completes several of the early steps in the procedure.
+ */
+ WRITE4(sc, IMX_GPT_CR, 0);
+ WRITE4(sc, IMX_GPT_IR, 0);
+
+ /* Choose the clock and the power-saving behaviors. */
+ ctlreg |=
+ sc->sc_clksrc | /* Use selected clock */
+ GPT_CR_FRR | /* Just count (FreeRunner mode) */
+ GPT_CR_STOPEN | /* Run in STOP mode */
+ GPT_CR_DOZEEN | /* Run in DOZE mode */
+ GPT_CR_WAITEN | /* Run in WAIT mode */
+ GPT_CR_DBGEN; /* Run in DEBUG mode */
+ WRITE4(sc, IMX_GPT_CR, ctlreg);
+
+ /*
+ * The datasheet says to do the software reset after choosing the clock
+ * source. It says nothing about needing to wait for the reset to
+ * complete, but the register description does document the fact that
+ * the reset isn't complete until the SWR bit reads 0, so let's be safe.
+ * The reset also clears all registers except for a few of the bits in
+ * CR, but we'll rewrite all the CR bits when we start the counter.
+ */
+ WRITE4(sc, IMX_GPT_CR, ctlreg | GPT_CR_SWR);
+ while (READ4(sc, IMX_GPT_CR) & GPT_CR_SWR)
+ continue;
+
+ /* Set a prescaler value that gets us near the target frequency. */
+ if (basefreq < TARGET_FREQUENCY) {
+ prescale = 0;
+ sc->clkfreq = basefreq;
+ } else {
+ prescale = basefreq / TARGET_FREQUENCY;
+ sc->clkfreq = basefreq / prescale;
+ prescale -= 1; /* 1..n range is 0..n-1 in hardware. */
+ }
+ WRITE4(sc, IMX_GPT_PR, prescale);
+
+ /* Clear the status register. */
+ WRITE4(sc, IMX_GPT_SR, GPT_IR_ALL);
+
+ /* Start the counter. */
+ WRITE4(sc, IMX_GPT_CR, ctlreg | GPT_CR_EN);
+
+ if (bootverbose)
+ device_printf(dev, "Running on %dKHz clock, base freq %uHz CR=0x%08x, PR=0x%08x\n",
+ sc->clkfreq / 1000, basefreq, READ4(sc, IMX_GPT_CR), READ4(sc, IMX_GPT_PR));
+
+ /* Setup the timer interrupt. */
+ err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, imx_gpt_intr,
+ NULL, sc, &sc->sc_ih);
+ if (err != 0) {
+ bus_release_resources(dev, imx_gpt_spec, sc->res);
+ device_printf(dev, "Unable to setup the clock irq handler, "
+ "err = %d\n", err);
+ return (ENXIO);
+ }
+
+ /* Register as an eventtimer. */
+ sc->et.et_name = "iMXGPT";
+ sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
+ sc->et.et_quality = 800;
+ sc->et.et_frequency = sc->clkfreq;
+ sc->et.et_min_period = (MIN_ET_PERIOD << 32) / sc->et.et_frequency;
+ sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
+ sc->et.et_start = imx_gpt_timer_start;
+ sc->et.et_stop = imx_gpt_timer_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ /* Register as a timecounter. */
+ imx_gpt_timecounter.tc_frequency = sc->clkfreq;
+ tc_init(&imx_gpt_timecounter);
+
+ /* If this is the first unit, store the softc for use in DELAY. */
+ if (device_get_unit(dev) == 0)
+ imx_gpt_sc = sc;
+
+ return (0);
+}
+
+static int
+imx_gpt_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct imx_gpt_softc *sc;
+ uint32_t ticks;
+
+ sc = (struct imx_gpt_softc *)et->et_priv;
+
+ if (period != 0) {
+ sc->sc_period = ((uint32_t)et->et_frequency * period) >> 32;
+ /* Set expected value */
+ WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) + sc->sc_period);
+ /* Enable compare register 2 Interrupt */
+ SET4(sc, IMX_GPT_IR, GPT_IR_OF2);
+ return (0);
+ } else if (first != 0) {
+ ticks = ((uint32_t)et->et_frequency * first) >> 32;
+ /* Do not disturb, otherwise event will be lost */
+ spinlock_enter();
+ /* Set expected value */
+ WRITE4(sc, IMX_GPT_OCR3, READ4(sc, IMX_GPT_CNT) + ticks);
+ /* Enable compare register 1 Interrupt */
+ SET4(sc, IMX_GPT_IR, GPT_IR_OF3);
+ /* Now everybody can relax */
+ spinlock_exit();
+ return (0);
+ }
+
+ return (EINVAL);
+}
+
+static int
+imx_gpt_timer_stop(struct eventtimer *et)
+{
+ struct imx_gpt_softc *sc;
+
+ sc = (struct imx_gpt_softc *)et->et_priv;
+
+ /* Disable OF2 Interrupt */
+ CLEAR4(sc, IMX_GPT_IR, GPT_IR_OF2);
+ WRITE4(sc, IMX_GPT_SR, GPT_IR_OF2);
+ sc->sc_period = 0;
+
+ return (0);
+}
+
+int
+imx_gpt_get_timerfreq(struct imx_gpt_softc *sc)
+{
+
+ return (sc->clkfreq);
+}
+
+static int
+imx_gpt_intr(void *arg)
+{
+ struct imx_gpt_softc *sc;
+ uint32_t status;
+
+ sc = (struct imx_gpt_softc *)arg;
+
+ status = READ4(sc, IMX_GPT_SR);
+
+ /*
+ * Clear interrupt status before invoking event callbacks. The callback
+ * often sets up a new one-shot timer event and if the interval is short
+ * enough it can fire before we get out of this function. If we cleared
+ * at the bottom we'd miss the interrupt and hang until the clock wraps.
+ */
+ WRITE4(sc, IMX_GPT_SR, status);
+
+ /* Handle one-shot timer events. */
+ if (status & GPT_IR_OF3) {
+ if (sc->et.et_active) {
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+ }
+ }
+
+ /* Handle periodic timer events. */
+ if (status & GPT_IR_OF2) {
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+ if (sc->sc_period != 0)
+ WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) +
+ sc->sc_period);
+ }
+
+ return (FILTER_HANDLED);
+}
+
+u_int
+imx_gpt_get_timecount(struct timecounter *tc)
+{
+
+ if (imx_gpt_sc == NULL)
+ return (0);
+
+ return (READ4(imx_gpt_sc, IMX_GPT_CNT));
+}
+
+static device_method_t imx_gpt_methods[] = {
+ DEVMETHOD(device_probe, imx_gpt_probe),
+ DEVMETHOD(device_attach, imx_gpt_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t imx_gpt_driver = {
+ "imx_gpt",
+ imx_gpt_methods,
+ sizeof(struct imx_gpt_softc),
+};
+
+static devclass_t imx_gpt_devclass;
+
+EARLY_DRIVER_MODULE(imx_gpt, simplebus, imx_gpt_driver, imx_gpt_devclass, 0,
+ 0, BUS_PASS_TIMER);
+
+void
+DELAY(int usec)
+{
+ uint64_t curcnt, endcnt, startcnt, ticks;
+
+ /* If the timer hardware is not accessible, just use a loop. */
+ if (imx_gpt_sc == NULL) {
+ while (usec-- > 0)
+ for (ticks = 0; ticks < imx_gpt_delay_count; ++ticks)
+ cpufunc_nullop();
+ return;
+ }
+
+ /*
+ * Calculate the tick count with 64-bit values so that it works for any
+ * clock frequency. Loop until the hardware count reaches start+ticks.
+ * If the 32-bit hardware count rolls over while we're looping, just
+ * manually do a carry into the high bits after each read; don't worry
+ * that doing this on each loop iteration is inefficient -- we're trying
+ * to waste time here.
+ */
+ ticks = 1 + ((uint64_t)usec * imx_gpt_sc->clkfreq) / 1000000;
+ curcnt = startcnt = READ4(imx_gpt_sc, IMX_GPT_CNT);
+ endcnt = startcnt + ticks;
+ while (curcnt < endcnt) {
+ curcnt = READ4(imx_gpt_sc, IMX_GPT_CNT);
+ if (curcnt < startcnt)
+ curcnt += 1ULL << 32;
+ }
+}
Property changes on: trunk/sys/arm/freescale/imx/imx_gpt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_gptreg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx_gptreg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_gptreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,102 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx_gptreg.h 261455 2014-02-04 03:36:42Z eadler $
+ */
+
+/* Registers definition for Freescale i.MX515 Generic Periodic Timer */
+
+#define IMX_GPT_CR 0x0000 /* Control Register R/W */
+#define GPT_CR_FO3 (1U << 31)
+#define GPT_CR_FO2 (1 << 30)
+#define GPT_CR_FO1 (1 << 29)
+#define GPT_CR_OM3_SHIFT 26
+#define GPT_CR_OM3_MASK 0x1c000000
+#define GPT_CR_OM2_SHIFT 23
+#define GPT_CR_OM2_MASK 0x03800000
+#define GPT_CR_OM1_SHIFT 20
+#define GPT_CR_OM1_MASK 0x00700000
+#define GPT_CR_OMX_NONE 0
+#define GPT_CR_OMX_TOGGLE 1
+#define GPT_CR_OMX_CLEAR 2
+#define GPT_CR_OMX_SET 3
+#define GPT_CR_OMX_PULSE 4 /* Run CLKSRC on output pin */
+#define GPT_CR_IM2_SHIFT 18
+#define GPT_CR_IM2_MASK 0x000c0000
+#define GPT_CR_IM1_SHIFT 16
+#define GPT_CR_IM1_MASK 0x00030000
+#define GPT_CR_IMX_NONE 0
+#define GPT_CR_IMX_REDGE 1
+#define GPT_CR_IMX_FEDGE 2
+#define GPT_CR_IMX_BOTH 3
+#define GPT_CR_SWR (1 << 15)
+#define GPT_CR_24MEN (1 << 10)
+#define GPT_CR_FRR (1 << 9)
+#define GPT_CR_CLKSRC_NONE (0 << 6)
+#define GPT_CR_CLKSRC_IPG (1 << 6)
+#define GPT_CR_CLKSRC_IPG_HIGH (2 << 6)
+#define GPT_CR_CLKSRC_EXT (3 << 6)
+#define GPT_CR_CLKSRC_32K (4 << 6)
+#define GPT_CR_CLKSRC_24M (5 << 6)
+#define GPT_CR_STOPEN (1 << 5)
+#define GPT_CR_DOZEEN (1 << 4)
+#define GPT_CR_WAITEN (1 << 3)
+#define GPT_CR_DBGEN (1 << 2)
+#define GPT_CR_ENMOD (1 << 1)
+#define GPT_CR_EN (1 << 0)
+
+#define IMX_GPT_PR 0x0004 /* Prescaler Register R/W */
+#define GPT_PR_VALUE_SHIFT 0
+#define GPT_PR_VALUE_MASK 0x00000fff
+#define GPT_PR_VALUE_SHIFT_24M 12
+#define GPT_PR_VALUE_MASK_24M 0x0000f000
+
+/* Same map for SR and IR */
+#define IMX_GPT_SR 0x0008 /* Status Register R/W */
+#define IMX_GPT_IR 0x000c /* Interrupt Register R/W */
+#define GPT_IR_ROV (1 << 5)
+#define GPT_IR_IF2 (1 << 4)
+#define GPT_IR_IF1 (1 << 3)
+#define GPT_IR_OF3 (1 << 2)
+#define GPT_IR_OF2 (1 << 1)
+#define GPT_IR_OF1 (1 << 0)
+#define GPT_IR_ALL \
+ (GPT_IR_ROV | \
+ GPT_IR_IF2 | \
+ GPT_IR_IF1 | \
+ GPT_IR_OF3 | \
+ GPT_IR_OF2 | \
+ GPT_IR_OF1)
+
+#define IMX_GPT_OCR1 0x0010 /* Output Compare Register 1 R/W */
+#define IMX_GPT_OCR2 0x0014 /* Output Compare Register 2 R/W */
+#define IMX_GPT_OCR3 0x0018 /* Output Compare Register 3 R/W */
+#define IMX_GPT_ICR1 0x001c /* Input capture Register 1 RO */
+#define IMX_GPT_ICR2 0x0020 /* Input capture Register 2 RO */
+#define IMX_GPT_CNT 0x0024 /* Counter Register RO */
Property changes on: trunk/sys/arm/freescale/imx/imx_gptreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_gptvar.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx_gptvar.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_gptvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,51 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx_gptvar.h 250357 2013-05-08 09:42:50Z ray $
+ */
+
+#ifndef _IMXGPTVAR_H
+#define _IMXGPTVAR_H
+
+struct imx_gpt_softc {
+ device_t sc_dev;
+ struct resource *res[2];
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ void *sc_ih; /* interrupt handler */
+ uint32_t sc_period;
+ uint32_t sc_clksrc;
+ uint32_t clkfreq;
+ struct eventtimer et;
+};
+
+extern struct imx_gpt_softc *imx_gpt_sc;
+
+int imx_gpt_get_timerfreq(struct imx_gpt_softc *);
+#endif /* _IMXGPTVAR_H */
Property changes on: trunk/sys/arm/freescale/imx/imx_gptvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_i2c.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_i2c.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_i2c.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,483 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008-2009 Semihalf, Michal Hajduk
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * Copyright (c) 2015 Ian Lepore <ian at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * I2C driver for Freescale i.MX hardware.
+ *
+ * Note that the hardware is capable of running as both a master and a slave.
+ * This driver currently implements only master-mode operations.
+ *
+ * This driver supports multi-master i2c busses, by detecting bus arbitration
+ * loss and returning IIC_EBUSBSY status. Notably, it does not do any kind of
+ * retries if some other master jumps onto the bus and interrupts one of our
+ * transfer cycles resulting in arbitration loss in mid-transfer. The caller
+ * must handle retries in a way that makes sense for the slave being addressed.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx_i2c.c 289666 2015-10-20 21:20:34Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include "iicbus_if.h"
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#define I2C_ADDR_REG 0x00 /* I2C slave address register */
+#define I2C_FDR_REG 0x04 /* I2C frequency divider register */
+#define I2C_CONTROL_REG 0x08 /* I2C control register */
+#define I2C_STATUS_REG 0x0C /* I2C status register */
+#define I2C_DATA_REG 0x10 /* I2C data register */
+#define I2C_DFSRR_REG 0x14 /* I2C Digital Filter Sampling rate */
+
+#define I2CCR_MEN (1 << 7) /* Module enable */
+#define I2CCR_MSTA (1 << 5) /* Master/slave mode */
+#define I2CCR_MTX (1 << 4) /* Transmit/receive mode */
+#define I2CCR_TXAK (1 << 3) /* Transfer acknowledge */
+#define I2CCR_RSTA (1 << 2) /* Repeated START */
+
+#define I2CSR_MCF (1 << 7) /* Data transfer */
+#define I2CSR_MASS (1 << 6) /* Addressed as a slave */
+#define I2CSR_MBB (1 << 5) /* Bus busy */
+#define I2CSR_MAL (1 << 4) /* Arbitration lost */
+#define I2CSR_SRW (1 << 2) /* Slave read/write */
+#define I2CSR_MIF (1 << 1) /* Module interrupt */
+#define I2CSR_RXAK (1 << 0) /* Received acknowledge */
+
+#define I2C_BAUD_RATE_FAST 0x31
+#define I2C_BAUD_RATE_DEF 0x3F
+#define I2C_DFSSR_DIV 0x10
+
+/*
+ * A table of available divisors and the associated coded values to put in the
+ * FDR register to achieve that divisor.. There is no algorithmic relationship I
+ * can see between divisors and the codes that go into the register. The table
+ * begins and ends with entries that handle insane configuration values.
+ */
+struct clkdiv {
+ u_int divisor;
+ u_int regcode;
+};
+static struct clkdiv clkdiv_table[] = {
+ { 0, 0x20 }, { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 },
+ { 28, 0x23 }, { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 },
+ { 40, 0x26 }, { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 },
+ { 52, 0x05 }, { 56, 0x29 }, { 60, 0x06 }, { 64, 0x2a },
+ { 72, 0x2b }, { 80, 0x2c }, { 88, 0x09 }, { 96, 0x2d },
+ { 104, 0x0a }, { 112, 0x2e }, { 128, 0x2f }, { 144, 0x0c },
+ { 160, 0x30 }, { 192, 0x31 }, { 224, 0x32 }, { 240, 0x0f },
+ { 256, 0x33 }, { 288, 0x10 }, { 320, 0x34 }, { 384, 0x35 },
+ { 448, 0x36 }, { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 },
+ { 640, 0x38 }, { 768, 0x39 }, { 896, 0x3a }, { 960, 0x17 },
+ { 1024, 0x3b }, { 1152, 0x18 }, { 1280, 0x3c }, { 1536, 0x3d },
+ { 1792, 0x3e }, { 1920, 0x1b }, { 2048, 0x3f }, { 2304, 0x1c },
+ { 2560, 0x1d }, { 3072, 0x1e }, { 3840, 0x1f }, {UINT_MAX, 0x1f}
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6q-i2c", 1},
+ {"fsl,imx-i2c", 1},
+ {NULL, 0}
+};
+
+struct i2c_softc {
+ device_t dev;
+ device_t iicbus;
+ struct resource *res;
+ int rid;
+ sbintime_t byte_time_sbt;
+};
+
+static phandle_t i2c_get_node(device_t, device_t);
+static int i2c_probe(device_t);
+static int i2c_attach(device_t);
+
+static int i2c_repeated_start(device_t, u_char, int);
+static int i2c_start(device_t, u_char, int);
+static int i2c_stop(device_t);
+static int i2c_reset(device_t, u_char, u_char, u_char *);
+static int i2c_read(device_t, char *, int, int *, int, int);
+static int i2c_write(device_t, const char *, int, int *, int);
+
+static device_method_t i2c_methods[] = {
+ DEVMETHOD(device_probe, i2c_probe),
+ DEVMETHOD(device_attach, i2c_attach),
+
+ /* OFW methods */
+ DEVMETHOD(ofw_bus_get_node, i2c_get_node),
+
+ DEVMETHOD(iicbus_callback, iicbus_null_callback),
+ DEVMETHOD(iicbus_repeated_start, i2c_repeated_start),
+ DEVMETHOD(iicbus_start, i2c_start),
+ DEVMETHOD(iicbus_stop, i2c_stop),
+ DEVMETHOD(iicbus_reset, i2c_reset),
+ DEVMETHOD(iicbus_read, i2c_read),
+ DEVMETHOD(iicbus_write, i2c_write),
+ DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
+
+ DEVMETHOD_END
+};
+
+static driver_t i2c_driver = {
+ "iichb",
+ i2c_methods,
+ sizeof(struct i2c_softc),
+};
+static devclass_t i2c_devclass;
+
+DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0);
+DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);
+
+static phandle_t
+i2c_get_node(device_t bus, device_t dev)
+{
+ /*
+ * Share controller node with iicbus device
+ */
+ return ofw_bus_get_node(bus);
+}
+
+static __inline void
+i2c_write_reg(struct i2c_softc *sc, bus_size_t off, uint8_t val)
+{
+
+ bus_write_1(sc->res, off, val);
+}
+
+static __inline uint8_t
+i2c_read_reg(struct i2c_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_1(sc->res, off));
+}
+
+static __inline void
+i2c_flag_set(struct i2c_softc *sc, bus_size_t off, uint8_t mask)
+{
+ uint8_t status;
+
+ status = i2c_read_reg(sc, off);
+ status |= mask;
+ i2c_write_reg(sc, off, status);
+}
+
+/* Wait for bus to become busy or not-busy. */
+static int
+wait_for_busbusy(struct i2c_softc *sc, int wantbusy)
+{
+ int retry, srb;
+
+ retry = 1000;
+ while (retry --) {
+ srb = i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MBB;
+ if ((srb && wantbusy) || (!srb && !wantbusy))
+ return (IIC_NOERR);
+ DELAY(1);
+ }
+ return (IIC_ETIMEOUT);
+}
+
+/* Wait for transfer to complete, optionally check RXAK. */
+static int
+wait_for_xfer(struct i2c_softc *sc, int checkack)
+{
+ int retry, sr;
+
+ /*
+ * Sleep for about the time it takes to transfer a byte (with precision
+ * set to tolerate 5% oversleep). We calculate the approximate byte
+ * transfer time when we set the bus speed divisor. Slaves are allowed
+ * to do clock-stretching so the actual transfer time can be larger, but
+ * this gets the bulk of the waiting out of the way without tying up the
+ * processor the whole time.
+ */
+ pause_sbt("imxi2c", sc->byte_time_sbt, sc->byte_time_sbt / 20, 0);
+
+ retry = 10000;
+ while (retry --) {
+ sr = i2c_read_reg(sc, I2C_STATUS_REG);
+ if (sr & I2CSR_MIF) {
+ if (sr & I2CSR_MAL)
+ return (IIC_EBUSERR);
+ else if (checkack && (sr & I2CSR_RXAK))
+ return (IIC_ENOACK);
+ else
+ return (IIC_NOERR);
+ }
+ DELAY(1);
+ }
+ return (IIC_ETIMEOUT);
+}
+
+/*
+ * Implement the error handling shown in the state diagram of the imx6 reference
+ * manual. If there was an error, then:
+ * - Clear master mode (MSTA and MTX).
+ * - Wait for the bus to become free or for a timeout to happen.
+ * - Disable the controller.
+ */
+static int
+i2c_error_handler(struct i2c_softc *sc, int error)
+{
+
+ if (error != 0) {
+ i2c_write_reg(sc, I2C_STATUS_REG, 0);
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN);
+ wait_for_busbusy(sc, false);
+ i2c_write_reg(sc, I2C_CONTROL_REG, 0);
+ }
+ return (error);
+}
+
+static int
+i2c_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale i.MX I2C");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+i2c_attach(device_t dev)
+{
+ struct i2c_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->rid = 0;
+
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
+ RF_ACTIVE);
+ if (sc->res == NULL) {
+ device_printf(dev, "could not allocate resources");
+ return (ENXIO);
+ }
+
+ sc->iicbus = device_add_child(dev, "iicbus", -1);
+ if (sc->iicbus == NULL) {
+ device_printf(dev, "could not add iicbus child");
+ return (ENXIO);
+ }
+
+ bus_generic_attach(dev);
+ return (0);
+}
+
+static int
+i2c_repeated_start(device_t dev, u_char slave, int timeout)
+{
+ struct i2c_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ if ((i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MBB) == 0) {
+ return (IIC_EBUSERR);
+ }
+
+ /*
+ * Set repeated start condition, delay (per reference manual, min 156nS)
+ * before writing slave address, wait for ack after write.
+ */
+ i2c_flag_set(sc, I2C_CONTROL_REG, I2CCR_RSTA);
+ DELAY(1);
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+ i2c_write_reg(sc, I2C_DATA_REG, slave);
+ error = wait_for_xfer(sc, true);
+ return (i2c_error_handler(sc, error));
+}
+
+static int
+i2c_start(device_t dev, u_char slave, int timeout)
+{
+ struct i2c_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN);
+ DELAY(10); /* Delay for controller to sample bus state. */
+ if (i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MBB) {
+ return (i2c_error_handler(sc, IIC_EBUSERR));
+ }
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_MSTA | I2CCR_MTX);
+ if ((error = wait_for_busbusy(sc, true)) != IIC_NOERR)
+ return (i2c_error_handler(sc, error));
+ i2c_write_reg(sc, I2C_STATUS_REG, 0);
+ i2c_write_reg(sc, I2C_DATA_REG, slave);
+ error = wait_for_xfer(sc, true);
+ return (i2c_error_handler(sc, error));
+}
+
+static int
+i2c_stop(device_t dev)
+{
+ struct i2c_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN);
+ wait_for_busbusy(sc, false);
+ i2c_write_reg(sc, I2C_CONTROL_REG, 0);
+ return (IIC_NOERR);
+}
+
+static int
+i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
+{
+ struct i2c_softc *sc;
+ u_int busfreq, div, i, ipgfreq;
+
+ sc = device_get_softc(dev);
+
+ /*
+ * Look up the divisor that gives the nearest speed that doesn't exceed
+ * the configured value for the bus.
+ */
+ ipgfreq = imx_ccm_ipg_hz();
+ busfreq = IICBUS_GET_FREQUENCY(sc->iicbus, speed);
+ div = (ipgfreq + busfreq - 1) / busfreq;
+ for (i = 0; i < nitems(clkdiv_table); i++) {
+ if (clkdiv_table[i].divisor >= div)
+ break;
+ }
+
+ /*
+ * Calculate roughly how long it will take to transfer a byte (which
+ * requires 9 clock cycles) at the new bus speed. This value is used to
+ * pause() while waiting for transfer-complete. With a 66MHz IPG clock
+ * and the actual i2c bus speeds that leads to, for nominal 100KHz and
+ * 400KHz bus speeds the transfer times are roughly 104uS and 22uS.
+ */
+ busfreq = ipgfreq / clkdiv_table[i].divisor;
+ sc->byte_time_sbt = SBT_1US * (9000000 / busfreq);
+
+ /*
+ * Disable the controller (do the reset), and set the new clock divisor.
+ */
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+ i2c_write_reg(sc, I2C_CONTROL_REG, 0x0);
+ i2c_write_reg(sc, I2C_FDR_REG, (uint8_t)clkdiv_table[i].regcode);
+ return (IIC_NOERR);
+}
+
+static int
+i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay)
+{
+ struct i2c_softc *sc;
+ int error, reg;
+
+ sc = device_get_softc(dev);
+ *read = 0;
+
+ if (len) {
+ if (len == 1)
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
+ I2CCR_MSTA | I2CCR_TXAK);
+ else
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
+ I2CCR_MSTA);
+ /* Dummy read to prime the receiver. */
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+ i2c_read_reg(sc, I2C_DATA_REG);
+ }
+
+ error = 0;
+ *read = 0;
+ while (*read < len) {
+ if ((error = wait_for_xfer(sc, false)) != IIC_NOERR)
+ break;
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+ if (last) {
+ if (*read == len - 2) {
+ /* NO ACK on last byte */
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
+ I2CCR_MSTA | I2CCR_TXAK);
+ } else if (*read == len - 1) {
+ /* Transfer done, signal stop. */
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
+ I2CCR_TXAK);
+ wait_for_busbusy(sc, false);
+ }
+ }
+ reg = i2c_read_reg(sc, I2C_DATA_REG);
+ *buf++ = reg;
+ (*read)++;
+ }
+
+ return (i2c_error_handler(sc, error));
+}
+
+static int
+i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout)
+{
+ struct i2c_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = 0;
+ *sent = 0;
+ while (*sent < len) {
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+ i2c_write_reg(sc, I2C_DATA_REG, *buf++);
+ if ((error = wait_for_xfer(sc, true)) != IIC_NOERR)
+ break;
+ (*sent)++;
+ }
+
+ return (i2c_error_handler(sc, error));
+}
Property changes on: trunk/sys/arm/freescale/imx/imx_i2c.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_iomux.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_iomux.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_iomux.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,326 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ian Lepore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx_iomux.c 278732 2015-02-13 23:34:40Z ian $
+ */
+
+/*
+ * Pin mux and pad control driver for imx5 and imx6.
+ *
+ * This driver implements the fdt_pinctrl interface for configuring the gpio and
+ * peripheral pins based on fdt configuration data.
+ *
+ * When the driver attaches, it walks the entire fdt tree and automatically
+ * configures the pins for each device which has a pinctrl-0 property and whose
+ * status is "okay". In addition it implements the fdt_pinctrl_configure()
+ * method which any other driver can call at any time to reconfigure its pins.
+ *
+ * The nature of the fsl,pins property in fdt data makes this driver's job very
+ * easy. Instead of representing each pin and pad configuration using symbolic
+ * properties such as pullup-enable="true" and so on, the data simply contains
+ * the addresses of the registers that control the pins, and the raw values to
+ * store in those registers.
+ *
+ * The imx5 and imx6 SoCs also have a small number of "general purpose
+ * registers" in the iomuxc device which are used to control an assortment
+ * of completely unrelated aspects of SoC behavior. This driver provides other
+ * drivers with direct access to those registers via simple accessor functions.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/fdt/fdt_pinctrl.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/freescale/imx/imx_iomuxvar.h>
+#include <arm/freescale/imx/imx_machdep.h>
+
+struct iomux_softc {
+ device_t dev;
+ struct resource *mem_res;
+ u_int last_gpreg;
+};
+
+static struct iomux_softc *iomux_sc;
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6dl-iomuxc", true},
+ {"fsl,imx6q-iomuxc", true},
+ {"fsl,imx6sl-iomuxc", true},
+ {"fsl,imx6sx-iomuxc", true},
+ {"fsl,imx53-iomuxc", true},
+ {"fsl,imx51-iomuxc", true},
+ {NULL, false},
+};
+
+/*
+ * Each tuple in an fsl,pins property contains these fields.
+ */
+struct pincfg {
+ uint32_t mux_reg;
+ uint32_t padconf_reg;
+ uint32_t input_reg;
+ uint32_t mux_val;
+ uint32_t input_val;
+ uint32_t padconf_val;
+};
+
+#define PADCONF_NONE (1U << 31) /* Do not configure pad. */
+#define PADCONF_SION (1U << 30) /* Force SION bit in mux register. */
+#define PADMUX_SION (1U << 4) /* The SION bit in the mux register. */
+
+static inline uint32_t
+RD4(struct iomux_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct iomux_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+static void
+iomux_configure_input(struct iomux_softc *sc, uint32_t reg, uint32_t val)
+{
+ u_int select, mask, shift, width;
+
+ /* If register and value are zero, there is nothing to configure. */
+ if (reg == 0 && val == 0)
+ return;
+
+ /*
+ * If the config value has 0xff in the high byte it is encoded:
+ * 31 23 15 7 0
+ * | 0xff | shift | width | select |
+ * We need to mask out the old select value and OR in the new, using a
+ * mask of the given width and shifting the values up by shift.
+ */
+ if ((val & 0xff000000) == 0xff000000) {
+ select = val & 0x000000ff;
+ width = (val & 0x0000ff00) >> 8;
+ shift = (val & 0x00ff0000) >> 16;
+ mask = ((1u << width) - 1) << shift;
+ val = (RD4(sc, reg) & ~mask) | (select << shift);
+ }
+ WR4(sc, reg, val);
+}
+
+static int
+iomux_configure_pins(device_t dev, phandle_t cfgxref)
+{
+ struct iomux_softc *sc;
+ struct pincfg *cfgtuples, *cfg;
+ phandle_t cfgnode;
+ int i, ntuples;
+ uint32_t sion;
+
+ sc = device_get_softc(dev);
+ cfgnode = OF_node_from_xref(cfgxref);
+ ntuples = OF_getencprop_alloc(cfgnode, "fsl,pins", sizeof(*cfgtuples),
+ (void **)&cfgtuples);
+ if (ntuples < 0)
+ return (ENOENT);
+ if (ntuples == 0)
+ return (0); /* Empty property is not an error. */
+ for (i = 0, cfg = cfgtuples; i < ntuples; i++, cfg++) {
+ sion = (cfg->padconf_val & PADCONF_SION) ? PADMUX_SION : 0;
+ WR4(sc, cfg->mux_reg, cfg->mux_val | sion);
+ iomux_configure_input(sc, cfg->input_reg, cfg->input_val);
+ if ((cfg->padconf_val & PADCONF_NONE) == 0)
+ WR4(sc, cfg->padconf_reg, cfg->padconf_val);
+ if (bootverbose) {
+ char name[32];
+ OF_getprop(cfgnode, "name", &name, sizeof(name));
+ printf("%16s: muxreg 0x%04x muxval 0x%02x "
+ "inpreg 0x%04x inpval 0x%02x "
+ "padreg 0x%04x padval 0x%08x\n",
+ name, cfg->mux_reg, cfg->mux_val | sion,
+ cfg->input_reg, cfg->input_val,
+ cfg->padconf_reg, cfg->padconf_val);
+ }
+ }
+ free(cfgtuples, M_OFWPROP);
+ return (0);
+}
+
+static int
+iomux_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale i.MX pin configuration");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+iomux_detach(device_t dev)
+{
+
+ /* This device is always present. */
+ return (EBUSY);
+}
+
+static int
+iomux_attach(device_t dev)
+{
+ struct iomux_softc * sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ switch (imx_soc_type()) {
+ case IMXSOC_51:
+ sc->last_gpreg = 1;
+ break;
+ case IMXSOC_53:
+ sc->last_gpreg = 2;
+ break;
+ case IMXSOC_6DL:
+ case IMXSOC_6S:
+ case IMXSOC_6SL:
+ case IMXSOC_6Q:
+ sc->last_gpreg = 13;
+ break;
+ default:
+ device_printf(dev, "Unknown SoC type\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ iomux_sc = sc;
+
+ /*
+ * Register as a pinctrl device, and call the convenience function that
+ * walks the entire device tree invoking FDT_PINCTRL_CONFIGURE() on any
+ * pinctrl-0 property cells whose xref phandle refers to a configuration
+ * that is a child node of our node in the tree.
+ *
+ * The pinctrl bindings documentation specifically mentions that the
+ * pinctrl device itself may have a pinctrl-0 property which contains
+ * static configuration to be applied at device init time. The tree
+ * walk will automatically handle this for us when it passes through our
+ * node in the tree.
+ */
+ fdt_pinctrl_register(dev, "fsl,pins");
+ fdt_pinctrl_configure_tree(dev);
+
+ return (0);
+}
+
+uint32_t
+imx_iomux_gpr_get(u_int regnum)
+{
+ struct iomux_softc * sc;
+
+ sc = iomux_sc;
+ KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__));
+ KASSERT(regnum >= 0 && regnum <= sc->last_gpreg,
+ ("%s bad regnum %u, max %u", __FUNCTION__, regnum, sc->last_gpreg));
+
+ return (RD4(iomux_sc, regnum * 4));
+}
+
+void
+imx_iomux_gpr_set(u_int regnum, uint32_t val)
+{
+ struct iomux_softc * sc;
+
+ sc = iomux_sc;
+ KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__));
+ KASSERT(regnum >= 0 && regnum <= sc->last_gpreg,
+ ("%s bad regnum %u, max %u", __FUNCTION__, regnum, sc->last_gpreg));
+
+ WR4(iomux_sc, regnum * 4, val);
+}
+
+void
+imx_iomux_gpr_set_masked(u_int regnum, uint32_t clrbits, uint32_t setbits)
+{
+ struct iomux_softc * sc;
+ uint32_t val;
+
+ sc = iomux_sc;
+ KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__));
+ KASSERT(regnum >= 0 && regnum <= sc->last_gpreg,
+ ("%s bad regnum %u, max %u", __FUNCTION__, regnum, sc->last_gpreg));
+
+ val = RD4(iomux_sc, regnum * 4);
+ val = (val & ~clrbits) | setbits;
+ WR4(iomux_sc, regnum * 4, val);
+}
+
+static device_method_t imx_iomux_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, iomux_probe),
+ DEVMETHOD(device_attach, iomux_attach),
+ DEVMETHOD(device_detach, iomux_detach),
+
+ /* fdt_pinctrl interface */
+ DEVMETHOD(fdt_pinctrl_configure,iomux_configure_pins),
+
+ DEVMETHOD_END
+};
+
+static driver_t imx_iomux_driver = {
+ "imx_iomux",
+ imx_iomux_methods,
+ sizeof(struct iomux_softc),
+};
+
+static devclass_t imx_iomux_devclass;
+
+EARLY_DRIVER_MODULE(imx_iomux, simplebus, imx_iomux_driver,
+ imx_iomux_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_LATE);
+
Property changes on: trunk/sys/arm/freescale/imx/imx_iomux.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_iomuxvar.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx_iomuxvar.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_iomuxvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,50 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx_iomuxvar.h 273663 2014-10-26 02:44:41Z ian $
+ */
+
+#ifndef IMX_IOMUXVAR_H
+#define IMX_IOMUXVAR_H
+
+/*
+ * IOMUX interface functions
+ */
+void iomux_set_function(u_int pin, u_int fn);
+void iomux_set_pad(u_int pin, u_int cfg);
+u_int iomux_get_pad_config(u_int pin);
+
+/*
+ * The IOMUX Controller device has a small set of "general purpose registers"
+ * which control various aspects of SoC operation that really have nothing to do
+ * with IO pin assignments or pad control. These functions let other soc level
+ * code manipulate these values.
+ */
+uint32_t imx_iomux_gpr_get(u_int regnum);
+void imx_iomux_gpr_set(u_int regnum, uint32_t val);
+void imx_iomux_gpr_set_masked(u_int regnum, uint32_t clrbits, uint32_t setbits);
+
+#endif
Property changes on: trunk/sys/arm/freescale/imx/imx_iomuxvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_machdep.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_machdep.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,121 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx_machdep.c 294678 2016-01-24 19:34:05Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <arm/freescale/imx/imx_machdep.h>
+#include <arm/freescale/imx/imx_wdogreg.h>
+
+SYSCTL_NODE(_hw, OID_AUTO, imx, CTLFLAG_RW, NULL, "i.MX container");
+
+static int last_reset_status;
+SYSCTL_UINT(_hw_imx, OID_AUTO, last_reset_status, CTLFLAG_RD,
+ &last_reset_status, 0, "Last reset status register");
+
+SYSCTL_STRING(_hw_imx, OID_AUTO, last_reset_reason, CTLFLAG_RD,
+ "unknown", 0, "Last reset reason");
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+/*
+ * This code which manipulates the watchdog hardware is here to implement
+ * cpu_reset() because the watchdog is the only way for software to reset the
+ * chip. Why here and not in imx_wdog.c? Because there's no requirement that
+ * the watchdog driver be compiled in, but it's nice to be able to reboot even
+ * if it's not.
+ */
+void
+imx_wdog_cpu_reset(vm_offset_t wdcr_physaddr)
+{
+ volatile uint16_t * pcr;
+
+ /*
+ * Trigger an immediate reset by clearing the SRS bit in the watchdog
+ * control register. The reset happens on the next cycle of the wdog
+ * 32KHz clock, so hang out in a spin loop until the reset takes effect.
+ */
+ if ((pcr = arm_devmap_ptov(wdcr_physaddr, sizeof(*pcr))) == NULL) {
+ printf("cpu_reset() can't find its control register... locking up now.");
+ } else {
+ *pcr &= ~WDOG_CR_SRS;
+ }
+ for (;;)
+ continue;
+}
+
+void
+imx_wdog_init_last_reset(vm_offset_t wdsr_phys)
+{
+ volatile uint16_t * psr;
+
+ if ((psr = arm_devmap_ptov(wdsr_phys, sizeof(*psr))) == NULL)
+ return;
+ last_reset_status = *psr;
+ if (last_reset_status & WDOG_RSR_SFTW) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "SoftwareReset";
+ } else if (last_reset_status & WDOG_RSR_TOUT) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "WatchdogTimeout";
+ } else if (last_reset_status & WDOG_RSR_POR) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "PowerOnReset";
+ }
+}
+
+u_int
+imx_soc_family(void)
+{
+ return (imx_soc_type() >> IMXSOC_FAMSHIFT);
+}
+
+
Property changes on: trunk/sys/arm/freescale/imx/imx_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_machdep.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx_machdep.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_machdep.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,65 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx_machdep.h 294678 2016-01-24 19:34:05Z ian $
+ */
+
+#ifndef IMX_MACHDEP_H
+#define IMX_MACHDEP_H
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+SYSCTL_DECL(_hw_imx);
+
+/* Common functions, implemented in imx_machdep.c. */
+
+void imx_wdog_cpu_reset(vm_offset_t _wdcr_phys) __attribute__((__noreturn__));
+void imx_wdog_init_last_reset(vm_offset_t _wdsr_phys);
+
+/* From here down, routines are implemented in imxNN_machdep.c. */
+
+/*
+ * SoC identity.
+ * According to the documentation, there is such a thing as an i.MX6 Dual
+ * (non-lite flavor). However, Freescale doesn't seem to have assigned it a
+ * number in their code for determining the SoC type in u-boot.
+ *
+ * To-do: put silicon revision numbers into the low-order bits somewhere.
+ */
+#define IMXSOC_51 0x51000000
+#define IMXSOC_53 0x53000000
+#define IMXSOC_6SL 0x60000000
+#define IMXSOC_6DL 0x61000000
+#define IMXSOC_6S 0x62000000
+#define IMXSOC_6Q 0x63000000
+#define IMXSOC_FAMSHIFT 28
+
+u_int imx_soc_type(void);
+u_int imx_soc_family(void);
+
+#endif
+
Property changes on: trunk/sys/arm/freescale/imx/imx_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_nop_usbphy.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_nop_usbphy.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_nop_usbphy.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,122 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx_nop_usbphy.c 266371 2014-05-17 22:29:24Z ian $");
+
+/*
+ * USBPHY "no-op" driver for Freescale family of SoCs. This driver is used on
+ * SoCs which have usbphy hardware whose clocks need to be enabled, but no other
+ * action has to be taken to make the hardware work.
+ */
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+/*
+ * Table of supported FDT compat strings.
+ */
+static struct ofw_compat_data compat_data[] = {
+ {"nop-usbphy", true},
+ {"usb-nop-xceiv", true},
+ {NULL, false},
+};
+
+struct usbphy_softc {
+ device_t dev;
+ u_int phy_num;
+};
+
+static int
+usbphy_detach(device_t dev)
+{
+
+ return (0);
+}
+
+static int
+usbphy_attach(device_t dev)
+{
+ struct usbphy_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /*
+ * Turn on the phy clocks.
+ */
+ imx_ccm_usbphy_enable(dev);
+
+ return (0);
+}
+
+static int
+usbphy_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Freescale USB PHY");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static device_method_t usbphy_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, usbphy_probe),
+ DEVMETHOD(device_attach, usbphy_attach),
+ DEVMETHOD(device_detach, usbphy_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t usbphy_driver = {
+ "usbphy",
+ usbphy_methods,
+ sizeof(struct usbphy_softc)
+};
+
+static devclass_t usbphy_devclass;
+
+DRIVER_MODULE(usbphy, simplebus, usbphy_driver, usbphy_devclass, 0, 0);
+
Property changes on: trunk/sys/arm/freescale/imx/imx_nop_usbphy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_sdhci.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_sdhci.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_sdhci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,839 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx_sdhci.c 321946 2017-08-02 20:27:30Z marius $");
+
+/*
+ * SDHCI driver glue for Freescale i.MX SoC family.
+ *
+ * This supports both eSDHC (earlier SoCs) and uSDHC (more recent SoCs).
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+#include <sys/time.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/mmc/bridge.h>
+
+#include <dev/sdhci/sdhci.h>
+
+#include "mmcbr_if.h"
+#include "sdhci_if.h"
+
+struct imx_sdhci_softc {
+ device_t dev;
+ struct resource * mem_res;
+ struct resource * irq_res;
+ void * intr_cookie;
+ struct sdhci_slot slot;
+ struct callout r1bfix_callout;
+ sbintime_t r1bfix_timeout_at;
+ uint32_t baseclk_hz;
+ uint32_t sdclockreg_freq_bits;
+ uint32_t cmd_and_mode;
+ uint32_t r1bfix_intmask;
+ uint8_t r1bfix_type;
+ uint8_t hwtype;
+ boolean_t force_card_present;
+};
+
+#define R1BFIX_NONE 0 /* No fix needed at next interrupt. */
+#define R1BFIX_NODATA 1 /* Synthesize DATA_END for R1B w/o data. */
+#define R1BFIX_AC12 2 /* Wait for busy after auto command 12. */
+
+#define HWTYPE_NONE 0 /* Hardware not recognized/supported. */
+#define HWTYPE_ESDHC 1 /* imx5x and earlier. */
+#define HWTYPE_USDHC 2 /* imx6. */
+
+#define SDHC_WTMK_LVL 0x44 /* Watermark Level register. */
+#define USDHC_MIX_CONTROL 0x48 /* Mix(ed) Control register. */
+#define SDHC_VEND_SPEC 0xC0 /* Vendor-specific register. */
+#define SDHC_VEND_FRC_SDCLK_ON (1 << 8)
+#define SDHC_VEND_IPGEN (1 << 11)
+#define SDHC_VEND_HCKEN (1 << 12)
+#define SDHC_VEND_PEREN (1 << 13)
+
+#define SDHC_PRES_STATE 0x24
+#define SDHC_PRES_CIHB (1 << 0)
+#define SDHC_PRES_CDIHB (1 << 1)
+#define SDHC_PRES_DLA (1 << 2)
+#define SDHC_PRES_SDSTB (1 << 3)
+#define SDHC_PRES_IPGOFF (1 << 4)
+#define SDHC_PRES_HCKOFF (1 << 5)
+#define SDHC_PRES_PEROFF (1 << 6)
+#define SDHC_PRES_SDOFF (1 << 7)
+#define SDHC_PRES_WTA (1 << 8)
+#define SDHC_PRES_RTA (1 << 9)
+#define SDHC_PRES_BWEN (1 << 10)
+#define SDHC_PRES_BREN (1 << 11)
+#define SDHC_PRES_RTR (1 << 12)
+#define SDHC_PRES_CINST (1 << 16)
+#define SDHC_PRES_CDPL (1 << 18)
+#define SDHC_PRES_WPSPL (1 << 19)
+#define SDHC_PRES_CLSL (1 << 23)
+#define SDHC_PRES_DLSL_SHIFT 24
+#define SDHC_PRES_DLSL_MASK (0xffU << SDHC_PRES_DLSL_SHIFT)
+
+#define SDHC_PROT_CTRL 0x28
+#define SDHC_PROT_LED (1 << 0)
+#define SDHC_PROT_WIDTH_1BIT (0 << 1)
+#define SDHC_PROT_WIDTH_4BIT (1 << 1)
+#define SDHC_PROT_WIDTH_8BIT (2 << 1)
+#define SDHC_PROT_WIDTH_MASK (3 << 1)
+#define SDHC_PROT_D3CD (1 << 3)
+#define SDHC_PROT_EMODE_BIG (0 << 4)
+#define SDHC_PROT_EMODE_HALF (1 << 4)
+#define SDHC_PROT_EMODE_LITTLE (2 << 4)
+#define SDHC_PROT_EMODE_MASK (3 << 4)
+#define SDHC_PROT_SDMA (0 << 8)
+#define SDHC_PROT_ADMA1 (1 << 8)
+#define SDHC_PROT_ADMA2 (2 << 8)
+#define SDHC_PROT_ADMA264 (3 << 8)
+#define SDHC_PROT_DMA_MASK (3 << 8)
+#define SDHC_PROT_CDTL (1 << 6)
+#define SDHC_PROT_CDSS (1 << 7)
+
+#define SDHC_INT_STATUS 0x30
+
+#define SDHC_CLK_IPGEN (1 << 0)
+#define SDHC_CLK_HCKEN (1 << 1)
+#define SDHC_CLK_PEREN (1 << 2)
+#define SDHC_CLK_DIVISOR_MASK 0x000000f0
+#define SDHC_CLK_DIVISOR_SHIFT 4
+#define SDHC_CLK_PRESCALE_MASK 0x0000ff00
+#define SDHC_CLK_PRESCALE_SHIFT 8
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6q-usdhc", HWTYPE_USDHC},
+ {"fsl,imx6sl-usdhc", HWTYPE_USDHC},
+ {"fsl,imx53-esdhc", HWTYPE_ESDHC},
+ {"fsl,imx51-esdhc", HWTYPE_ESDHC},
+ {NULL, HWTYPE_NONE},
+};;
+
+static void imx_sdhc_set_clock(struct imx_sdhci_softc *sc, int enable);
+static void imx_sdhci_r1bfix_func(void *arg);
+
+static inline uint32_t
+RD4(struct imx_sdhci_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+WR4(struct imx_sdhci_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+static uint8_t
+imx_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32, wrk32;
+
+ /*
+ * Most of the things in the standard host control register are in the
+ * hardware's wider protocol control register, but some of the bits are
+ * moved around.
+ */
+ if (off == SDHCI_HOST_CONTROL) {
+ wrk32 = RD4(sc, SDHC_PROT_CTRL);
+ val32 = wrk32 & (SDHCI_CTRL_LED | SDHCI_CTRL_CARD_DET |
+ SDHCI_CTRL_FORCE_CARD);
+ switch (wrk32 & SDHC_PROT_WIDTH_MASK) {
+ case SDHC_PROT_WIDTH_1BIT:
+ /* Value is already 0. */
+ break;
+ case SDHC_PROT_WIDTH_4BIT:
+ val32 |= SDHCI_CTRL_4BITBUS;
+ break;
+ case SDHC_PROT_WIDTH_8BIT:
+ val32 |= SDHCI_CTRL_8BITBUS;
+ break;
+ }
+ switch (wrk32 & SDHC_PROT_DMA_MASK) {
+ case SDHC_PROT_SDMA:
+ /* Value is already 0. */
+ break;
+ case SDHC_PROT_ADMA1:
+ /* This value is deprecated, should never appear. */
+ break;
+ case SDHC_PROT_ADMA2:
+ val32 |= SDHCI_CTRL_ADMA2;
+ break;
+ case SDHC_PROT_ADMA264:
+ val32 |= SDHCI_CTRL_ADMA264;
+ break;
+ }
+ return val32;
+ }
+
+ /*
+ * XXX can't find the bus power on/off knob. For now we have to say the
+ * power is always on and always set to the same voltage.
+ */
+ if (off == SDHCI_POWER_CONTROL) {
+ return (SDHCI_POWER_ON | SDHCI_POWER_300);
+ }
+
+
+ return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xff);
+}
+
+static uint16_t
+imx_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32, wrk32;
+
+ if (sc->hwtype == HWTYPE_USDHC) {
+ /*
+ * The USDHC hardware has nothing in the version register, but
+ * it's v3 compatible with all our translation code.
+ */
+ if (off == SDHCI_HOST_VERSION) {
+ return (SDHCI_SPEC_300 << SDHCI_SPEC_VER_SHIFT);
+ }
+ /*
+ * The USDHC hardware moved the transfer mode bits to the mixed
+ * control register, fetch them from there.
+ */
+ if (off == SDHCI_TRANSFER_MODE)
+ return (RD4(sc, USDHC_MIX_CONTROL) & 0x37);
+
+ } else if (sc->hwtype == HWTYPE_ESDHC) {
+
+ /*
+ * The ESDHC hardware has the typical 32-bit combined "command
+ * and mode" register that we have to cache so that command
+ * isn't written until after mode. On a read, just retrieve the
+ * cached values last written.
+ */
+ if (off == SDHCI_TRANSFER_MODE) {
+ return (sc->cmd_and_mode >> 16);
+ } else if (off == SDHCI_COMMAND_FLAGS) {
+ return (sc->cmd_and_mode & 0x0000ffff);
+ }
+ }
+
+ /*
+ * This hardware only manages one slot. Synthesize a slot interrupt
+ * status register... if there are any enabled interrupts active they
+ * must be coming from our one and only slot.
+ */
+ if (off == SDHCI_SLOT_INT_STATUS) {
+ val32 = RD4(sc, SDHCI_INT_STATUS);
+ val32 &= RD4(sc, SDHCI_SIGNAL_ENABLE);
+ return (val32 ? 1 : 0);
+ }
+
+ /*
+ * The clock enable bit is in the vendor register and the clock-stable
+ * bit is in the present state register. Transcribe them as if they
+ * were in the clock control register where they should be.
+ * XXX Is it important that we distinguish between "internal" and "card"
+ * clocks? Probably not; transcribe the card clock status to both bits.
+ */
+ if (off == SDHCI_CLOCK_CONTROL) {
+ val32 = 0;
+ wrk32 = RD4(sc, SDHC_VEND_SPEC);
+ if (wrk32 & SDHC_VEND_FRC_SDCLK_ON)
+ val32 |= SDHCI_CLOCK_INT_EN | SDHCI_CLOCK_CARD_EN;
+ wrk32 = RD4(sc, SDHC_PRES_STATE);
+ if (wrk32 & SDHC_PRES_SDSTB)
+ val32 |= SDHCI_CLOCK_INT_STABLE;
+ val32 |= sc->sdclockreg_freq_bits;
+ return (val32);
+ }
+
+ return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xffff);
+}
+
+static uint32_t
+imx_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32, wrk32;
+
+ val32 = RD4(sc, off);
+
+ /*
+ * The hardware leaves the base clock frequency out of the capabilities
+ * register; fill it in. The timeout clock is the same as the active
+ * output sdclock; we indicate that with a quirk setting so don't
+ * populate the timeout frequency bits.
+ *
+ * XXX Turn off (for now) features the hardware can do but this driver
+ * doesn't yet handle (1.8v, suspend/resume, etc).
+ */
+ if (off == SDHCI_CAPABILITIES) {
+ val32 &= ~SDHCI_CAN_VDD_180;
+ val32 &= ~SDHCI_CAN_DO_SUSPEND;
+ val32 |= SDHCI_CAN_DO_8BITBUS;
+ val32 |= (sc->baseclk_hz / 1000000) << SDHCI_CLOCK_BASE_SHIFT;
+ return (val32);
+ }
+
+ /*
+ * The hardware moves bits around in the present state register to make
+ * room for all 8 data line state bits. To translate, mask out all the
+ * bits which are not in the same position in both registers (this also
+ * masks out some freescale-specific bits in locations defined as
+ * reserved by sdhci), then shift the data line and retune request bits
+ * down to their standard locations.
+ */
+ if (off == SDHCI_PRESENT_STATE) {
+ wrk32 = val32;
+ val32 &= 0x000F0F07;
+ val32 |= (wrk32 >> 4) & SDHCI_STATE_DAT_MASK;
+ val32 |= (wrk32 >> 9) & SDHCI_RETUNE_REQUEST;
+ if (sc->force_card_present)
+ val32 |= SDHCI_CARD_PRESENT;
+ return (val32);
+ }
+
+ /*
+ * imx_sdhci_intr() can synthesize a DATA_END interrupt following a
+ * command with an R1B response, mix it into the hardware status.
+ */
+ if (off == SDHCI_INT_STATUS) {
+ return (val32 | sc->r1bfix_intmask);
+ }
+
+ return val32;
+}
+
+static void
+imx_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t *data, bus_size_t count)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+
+ bus_read_multi_4(sc->mem_res, off, data, count);
+}
+
+static void
+imx_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint8_t val)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32;
+
+ /*
+ * Most of the things in the standard host control register are in the
+ * hardware's wider protocol control register, but some of the bits are
+ * moved around.
+ */
+ if (off == SDHCI_HOST_CONTROL) {
+ val32 = RD4(sc, SDHC_PROT_CTRL);
+ val32 &= ~(SDHC_PROT_LED | SDHC_PROT_DMA_MASK |
+ SDHC_PROT_WIDTH_MASK | SDHC_PROT_CDTL | SDHC_PROT_CDSS);
+ val32 |= (val & SDHCI_CTRL_LED);
+ if (val & SDHCI_CTRL_8BITBUS)
+ val32 |= SDHC_PROT_WIDTH_8BIT;
+ else
+ val32 |= (val & SDHCI_CTRL_4BITBUS);
+ val32 |= (val & (SDHCI_CTRL_SDMA | SDHCI_CTRL_ADMA2)) << 4;
+ val32 |= (val & (SDHCI_CTRL_CARD_DET | SDHCI_CTRL_FORCE_CARD));
+ WR4(sc, SDHC_PROT_CTRL, val32);
+ return;
+ }
+
+ /* XXX I can't find the bus power on/off knob; do nothing. */
+ if (off == SDHCI_POWER_CONTROL) {
+ return;
+ }
+
+ val32 = RD4(sc, off & ~3);
+ val32 &= ~(0xff << (off & 3) * 8);
+ val32 |= (val << (off & 3) * 8);
+
+ WR4(sc, off & ~3, val32);
+}
+
+static void
+imx_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32;
+
+ /* The USDHC hardware moved the transfer mode bits to mixed control. */
+ if (sc->hwtype == HWTYPE_USDHC) {
+ if (off == SDHCI_TRANSFER_MODE) {
+ val32 = RD4(sc, USDHC_MIX_CONTROL);
+ val32 &= ~0x3f;
+ val32 |= val & 0x37;
+ // XXX acmd23 not supported here (or by sdhci driver)
+ WR4(sc, USDHC_MIX_CONTROL, val32);
+ return;
+ }
+ }
+
+ /*
+ * The clock control stuff is complex enough to have its own routine
+ * that can both change speeds and en/disable the clock output. Also,
+ * save the register bits in SDHCI format so that we can play them back
+ * in the read2 routine without complex decoding.
+ */
+ if (off == SDHCI_CLOCK_CONTROL) {
+ sc->sdclockreg_freq_bits = val & 0xffc0;
+ if (val & SDHCI_CLOCK_CARD_EN) {
+ imx_sdhc_set_clock(sc, true);
+ } else {
+ imx_sdhc_set_clock(sc, false);
+ }
+ return;
+ }
+
+ /*
+ * Figure out whether we need to check the DAT0 line for busy status at
+ * interrupt time. The controller should be doing this, but for some
+ * reason it doesn't. There are two cases:
+ * - R1B response with no data transfer should generate a DATA_END (aka
+ * TRANSFER_COMPLETE) interrupt after waiting for busy, but if
+ * there's no data transfer there's no DATA_END interrupt. This is
+ * documented; they seem to think it's a feature.
+ * - R1B response after Auto-CMD12 appears to not work, even though
+ * there's a control bit for it (bit 3) in the vendor register.
+ * When we're starting a command that needs a manual DAT0 line check at
+ * interrupt time, we leave ourselves a note in r1bfix_type so that we
+ * can do the extra work in imx_sdhci_intr().
+ */
+ if (off == SDHCI_COMMAND_FLAGS) {
+ if (val & SDHCI_CMD_DATA) {
+ const uint32_t MBAUTOCMD = SDHCI_TRNS_ACMD12 | SDHCI_TRNS_MULTI;
+ val32 = RD4(sc, USDHC_MIX_CONTROL);
+ if ((val32 & MBAUTOCMD) == MBAUTOCMD)
+ sc->r1bfix_type = R1BFIX_AC12;
+ } else {
+ if ((val & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_SHORT_BUSY) {
+ WR4(sc, SDHCI_INT_ENABLE, slot->intmask | SDHCI_INT_RESPONSE);
+ WR4(sc, SDHCI_SIGNAL_ENABLE, slot->intmask | SDHCI_INT_RESPONSE);
+ sc->r1bfix_type = R1BFIX_NODATA;
+ }
+ }
+ }
+
+ val32 = RD4(sc, off & ~3);
+ val32 &= ~(0xffff << (off & 3) * 8);
+ val32 |= ((val & 0xffff) << (off & 3) * 8);
+ WR4(sc, off & ~3, val32);
+}
+
+static void
+imx_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+
+ /* Clear synthesized interrupts, then pass the value to the hardware. */
+ if (off == SDHCI_INT_STATUS) {
+ sc->r1bfix_intmask &= ~val;
+ }
+
+ WR4(sc, off, val);
+}
+
+static void
+imx_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t *data, bus_size_t count)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+
+ bus_write_multi_4(sc->mem_res, off, data, count);
+}
+
+static void
+imx_sdhc_set_clock(struct imx_sdhci_softc *sc, int enable)
+{
+ uint32_t divisor, enable_bits, enable_reg, freq, prescale, val32;
+
+ if (sc->hwtype == HWTYPE_ESDHC) {
+ divisor = (sc->sdclockreg_freq_bits >> SDHCI_DIVIDER_SHIFT) &
+ SDHCI_DIVIDER_MASK;
+ enable_reg = SDHCI_CLOCK_CONTROL;
+ enable_bits = SDHC_CLK_IPGEN | SDHC_CLK_HCKEN |
+ SDHC_CLK_PEREN;
+ } else {
+ divisor = (sc->sdclockreg_freq_bits >> SDHCI_DIVIDER_SHIFT) &
+ SDHCI_DIVIDER_MASK;
+ divisor |= ((sc->sdclockreg_freq_bits >>
+ SDHCI_DIVIDER_HI_SHIFT) &
+ SDHCI_DIVIDER_HI_MASK) << SDHCI_DIVIDER_MASK_LEN;
+ enable_reg = SDHCI_CLOCK_CONTROL;
+ enable_bits = SDHC_VEND_IPGEN | SDHC_VEND_HCKEN |
+ SDHC_VEND_PEREN;
+ }
+
+ WR4(sc, SDHC_VEND_SPEC,
+ RD4(sc, SDHC_VEND_SPEC) & ~SDHC_VEND_FRC_SDCLK_ON);
+ WR4(sc, enable_reg, RD4(sc, enable_reg) & ~enable_bits);
+
+ if (!enable)
+ return;
+
+ if (divisor == 0)
+ freq = sc->baseclk_hz;
+ else
+ freq = sc->baseclk_hz / (2 * divisor);
+
+ for (prescale = 2; freq < sc->baseclk_hz / (prescale * 16);)
+ prescale <<= 1;
+
+ for (divisor = 1; freq < sc->baseclk_hz / (prescale * divisor);)
+ ++divisor;
+
+#ifdef DEBUG
+ device_printf(sc->dev,
+ "desired SD freq: %d, actual: %d; base %d prescale %d divisor %d\n",
+ freq, sc->baseclk_hz / (prescale * divisor), sc->baseclk_hz,
+ prescale, divisor);
+#endif
+
+ prescale >>= 1;
+ divisor -= 1;
+
+ val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
+ val32 &= ~SDHC_CLK_DIVISOR_MASK;
+ val32 |= divisor << SDHC_CLK_DIVISOR_SHIFT;
+ val32 &= ~SDHC_CLK_PRESCALE_MASK;
+ val32 |= prescale << SDHC_CLK_PRESCALE_SHIFT;
+ WR4(sc, SDHCI_CLOCK_CONTROL, val32);
+
+ WR4(sc, enable_reg, RD4(sc, enable_reg) | enable_bits);
+ WR4(sc, SDHC_VEND_SPEC,
+ RD4(sc, SDHC_VEND_SPEC) | SDHC_VEND_FRC_SDCLK_ON);
+}
+
+static boolean_t
+imx_sdhci_r1bfix_is_wait_done(struct imx_sdhci_softc *sc)
+{
+ uint32_t inhibit;
+
+ mtx_assert(&sc->slot.mtx, MA_OWNED);
+
+ /*
+ * Check the DAT0 line status using both the DLA (data line active) and
+ * CDIHB (data inhibit) bits in the present state register. In theory
+ * just DLA should do the trick, but in practice it takes both. If the
+ * DAT0 line is still being held and we're not yet beyond the timeout
+ * point, just schedule another callout to check again later.
+ */
+ inhibit = RD4(sc, SDHC_PRES_STATE) & (SDHC_PRES_DLA | SDHC_PRES_CDIHB);
+
+ if (inhibit && getsbinuptime() < sc->r1bfix_timeout_at) {
+ callout_reset_sbt(&sc->r1bfix_callout, SBT_1MS, 0,
+ imx_sdhci_r1bfix_func, sc, 0);
+ return (false);
+ }
+
+ /*
+ * If we reach this point with the inhibit bits still set, we've got a
+ * timeout, synthesize a DATA_TIMEOUT interrupt. Otherwise the DAT0
+ * line has been released, and we synthesize a DATA_END, and if the type
+ * of fix needed was on a command-without-data we also now add in the
+ * original INT_RESPONSE that we suppressed earlier.
+ */
+ if (inhibit)
+ sc->r1bfix_intmask |= SDHCI_INT_DATA_TIMEOUT;
+ else {
+ sc->r1bfix_intmask |= SDHCI_INT_DATA_END;
+ if (sc->r1bfix_type == R1BFIX_NODATA)
+ sc->r1bfix_intmask |= SDHCI_INT_RESPONSE;
+ }
+
+ sc->r1bfix_type = R1BFIX_NONE;
+ return (true);
+}
+
+static void
+imx_sdhci_r1bfix_func(void * arg)
+{
+ struct imx_sdhci_softc *sc = arg;
+ boolean_t r1bwait_done;
+
+ mtx_lock(&sc->slot.mtx);
+ r1bwait_done = imx_sdhci_r1bfix_is_wait_done(sc);
+ mtx_unlock(&sc->slot.mtx);
+ if (r1bwait_done)
+ sdhci_generic_intr(&sc->slot);
+}
+
+static void
+imx_sdhci_intr(void *arg)
+{
+ struct imx_sdhci_softc *sc = arg;
+ uint32_t intmask;
+
+ mtx_lock(&sc->slot.mtx);
+
+ /*
+ * Manually check the DAT0 line for R1B response types that the
+ * controller fails to handle properly. The controller asserts the done
+ * interrupt while the card is still asserting busy with the DAT0 line.
+ *
+ * We check DAT0 immediately because most of the time, especially on a
+ * read, the card will actually be done by time we get here. If it's
+ * not, then the wait_done routine will schedule a callout to re-check
+ * periodically until it is done. In that case we clear the interrupt
+ * out of the hardware now so that we can present it later when the DAT0
+ * line is released.
+ *
+ * If we need to wait for the the DAT0 line to be released, we set up a
+ * timeout point 250ms in the future. This number comes from the SD
+ * spec, which allows a command to take that long. In the real world,
+ * cards tend to take 10-20ms for a long-running command such as a write
+ * or erase that spans two pages.
+ */
+ switch (sc->r1bfix_type) {
+ case R1BFIX_NODATA:
+ intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_RESPONSE;
+ break;
+ case R1BFIX_AC12:
+ intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_DATA_END;
+ break;
+ default:
+ intmask = 0;
+ break;
+ }
+ if (intmask) {
+ sc->r1bfix_timeout_at = getsbinuptime() + 250 * SBT_1MS;
+ if (!imx_sdhci_r1bfix_is_wait_done(sc)) {
+ WR4(sc, SDHC_INT_STATUS, intmask);
+ bus_barrier(sc->mem_res, SDHC_INT_STATUS, 4,
+ BUS_SPACE_BARRIER_WRITE);
+ }
+ }
+
+ mtx_unlock(&sc->slot.mtx);
+ sdhci_generic_intr(&sc->slot);
+}
+
+static int
+imx_sdhci_get_ro(device_t bus, device_t child)
+{
+
+ return (false);
+}
+
+static int
+imx_sdhci_detach(device_t dev)
+{
+
+ return (EBUSY);
+}
+
+static int
+imx_sdhci_attach(device_t dev)
+{
+ struct imx_sdhci_softc *sc = device_get_softc(dev);
+ int rid, err;
+ phandle_t node;
+
+ sc->dev = dev;
+
+ sc->hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ if (sc->hwtype == HWTYPE_NONE)
+ panic("Impossible: not compatible in imx_sdhci_attach()");
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, imx_sdhci_intr, sc, &sc->intr_cookie)) {
+ device_printf(dev, "cannot setup interrupt handler\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ sc->slot.quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
+
+ /*
+ * DMA is not really broken, I just haven't implemented it yet.
+ */
+ sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA;
+
+ /*
+ * Set the buffer watermark level to 128 words (512 bytes) for both read
+ * and write. The hardware has a restriction that when the read or
+ * write ready status is asserted, that means you can read exactly the
+ * number of words set in the watermark register before you have to
+ * re-check the status and potentially wait for more data. The main
+ * sdhci driver provides no hook for doing status checking on less than
+ * a full block boundary, so we set the watermark level to be a full
+ * block. Reads and writes where the block size is less than the
+ * watermark size will work correctly too, no need to change the
+ * watermark for different size blocks. However, 128 is the maximum
+ * allowed for the watermark, so PIO is limitted to 512 byte blocks
+ * (which works fine for SD cards, may be a problem for SDIO some day).
+ *
+ * XXX need named constants for this stuff.
+ */
+ WR4(sc, SDHC_WTMK_LVL, 0x08800880);
+
+ sc->baseclk_hz = imx_ccm_sdhci_hz();
+
+ /*
+ * If the slot is flagged with the non-removable property, set our flag
+ * to always force the SDHCI_CARD_PRESENT bit on.
+ *
+ * XXX Workaround for gpio-based card detect...
+ *
+ * We don't have gpio support yet. If there's a cd-gpios property just
+ * force the SDHCI_CARD_PRESENT bit on for now. If there isn't really a
+ * card there it will fail to probe at the mmc layer and nothing bad
+ * happens except instantiating an mmcN device for an empty slot.
+ */
+ node = ofw_bus_get_node(dev);
+ if (OF_hasprop(node, "non-removable"))
+ sc->force_card_present = true;
+ else if (OF_hasprop(node, "cd-gpios")) {
+ /* XXX put real gpio hookup here. */
+ sc->force_card_present = true;
+ }
+
+ callout_init(&sc->r1bfix_callout, true);
+ sdhci_init_slot(dev, &sc->slot, 0);
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ sdhci_start_slot(&sc->slot);
+
+ return (0);
+
+fail:
+ if (sc->intr_cookie)
+ bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie);
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (err);
+}
+
+static int
+imx_sdhci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
+ case HWTYPE_ESDHC:
+ device_set_desc(dev, "Freescale eSDHC controller");
+ return (BUS_PROBE_DEFAULT);
+ case HWTYPE_USDHC:
+ device_set_desc(dev, "Freescale uSDHC controller");
+ return (BUS_PROBE_DEFAULT);
+ default:
+ break;
+ }
+ return (ENXIO);
+}
+
+static device_method_t imx_sdhci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, imx_sdhci_probe),
+ DEVMETHOD(device_attach, imx_sdhci_attach),
+ DEVMETHOD(device_detach, imx_sdhci_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
+ DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
+
+ /* MMC bridge interface */
+ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios),
+ DEVMETHOD(mmcbr_request, sdhci_generic_request),
+ DEVMETHOD(mmcbr_get_ro, imx_sdhci_get_ro),
+ DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host),
+ DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
+
+ /* SDHCI registers accessors */
+ DEVMETHOD(sdhci_read_1, imx_sdhci_read_1),
+ DEVMETHOD(sdhci_read_2, imx_sdhci_read_2),
+ DEVMETHOD(sdhci_read_4, imx_sdhci_read_4),
+ DEVMETHOD(sdhci_read_multi_4, imx_sdhci_read_multi_4),
+ DEVMETHOD(sdhci_write_1, imx_sdhci_write_1),
+ DEVMETHOD(sdhci_write_2, imx_sdhci_write_2),
+ DEVMETHOD(sdhci_write_4, imx_sdhci_write_4),
+ DEVMETHOD(sdhci_write_multi_4, imx_sdhci_write_multi_4),
+
+ DEVMETHOD_END
+};
+
+static devclass_t imx_sdhci_devclass;
+
+static driver_t imx_sdhci_driver = {
+ "sdhci_imx",
+ imx_sdhci_methods,
+ sizeof(struct imx_sdhci_softc),
+};
+
+DRIVER_MODULE(sdhci_imx, simplebus, imx_sdhci_driver, imx_sdhci_devclass,
+ NULL, NULL);
+MODULE_DEPEND(sdhci_imx, sdhci, 1, 1, 1);
+MMC_DECLARE_BRIDGE(sdhci_imx);
Property changes on: trunk/sys/arm/freescale/imx/imx_sdhci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_wdog.c
===================================================================
--- trunk/sys/arm/freescale/imx/imx_wdog.c (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_wdog.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,177 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/imx_wdog.c 287079 2015-08-23 20:16:13Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/watchdog.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <machine/fdt.h>
+
+#include <arm/freescale/imx/imx_wdogreg.h>
+
+struct imx_wdog_softc {
+ struct mtx sc_mtx;
+ device_t sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ struct resource *sc_res[2];
+ uint32_t sc_timeout;
+};
+
+static struct resource_spec imx_wdog_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6sx-wdt", 1},
+ {"fsl,imx6sl-wdt", 1},
+ {"fsl,imx6q-wdt", 1},
+ {"fsl,imx53-wdt", 1},
+ {"fsl,imx51-wdt", 1},
+ {"fsl,imx50-wdt", 1},
+ {"fsl,imx35-wdt", 1},
+ {"fsl,imx27-wdt", 1},
+ {"fsl,imx25-wdt", 1},
+ {"fsl,imx21-wdt", 1},
+ {NULL, 0}
+};
+
+static void imx_watchdog(void *, u_int, int *);
+static int imx_wdog_probe(device_t);
+static int imx_wdog_attach(device_t);
+
+static device_method_t imx_wdog_methods[] = {
+ DEVMETHOD(device_probe, imx_wdog_probe),
+ DEVMETHOD(device_attach, imx_wdog_attach),
+ DEVMETHOD_END
+};
+
+static driver_t imx_wdog_driver = {
+ "imx_wdog",
+ imx_wdog_methods,
+ sizeof(struct imx_wdog_softc),
+};
+static devclass_t imx_wdog_devclass;
+DRIVER_MODULE(imx_wdog, simplebus, imx_wdog_driver, imx_wdog_devclass, 0, 0);
+
+#define RD2(_sc, _r) \
+ bus_space_read_2((_sc)->sc_bst, (_sc)->sc_bsh, (_r))
+#define WR2(_sc, _r, _v) \
+ bus_space_write_2((_sc)->sc_bst, (_sc)->sc_bsh, (_r), (_v))
+
+static void
+imx_watchdog(void *arg, u_int cmd, int *error)
+{
+ struct imx_wdog_softc *sc;
+ uint16_t reg;
+ u_int timeout;
+
+ sc = arg;
+ mtx_lock(&sc->sc_mtx);
+ if (cmd == 0) {
+ if (bootverbose)
+ device_printf(sc->sc_dev, "Can not be disabled.\n");
+ *error = EOPNOTSUPP;
+ } else {
+ timeout = (u_int)((1ULL << (cmd & WD_INTERVAL)) / 1000000000U);
+ if (timeout > 1 && timeout < 128) {
+ if (timeout != sc->sc_timeout) {
+ sc->sc_timeout = timeout;
+ reg = RD2(sc, WDOG_CR_REG);
+ reg &= ~WDOG_CR_WT_MASK;
+ reg |= (timeout << (WDOG_CR_WT_SHIFT + 1)) &
+ WDOG_CR_WT_MASK;
+ WR2(sc, WDOG_CR_REG, reg | WDOG_CR_WDE);
+ }
+ /* Refresh counter */
+ WR2(sc, WDOG_SR_REG, WDOG_SR_STEP1);
+ WR2(sc, WDOG_SR_REG, WDOG_SR_STEP2);
+ *error = 0;
+ }
+ }
+ mtx_unlock(&sc->sc_mtx);
+}
+
+static int
+imx_wdog_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale i.MX Watchdog");
+ return (0);
+}
+
+static int
+imx_wdog_attach(device_t dev)
+{
+ struct imx_wdog_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ if (bus_alloc_resources(dev, imx_wdog_spec, sc->sc_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "imx_wdt", MTX_DEF);
+
+ sc->sc_dev = dev;
+ sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
+
+ /* TODO: handle interrupt */
+
+ EVENTHANDLER_REGISTER(watchdog_list, imx_watchdog, sc, 0);
+ return (0);
+}
Property changes on: trunk/sys/arm/freescale/imx/imx_wdog.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/imx_wdogreg.h
===================================================================
--- trunk/sys/arm/freescale/imx/imx_wdogreg.h (rev 0)
+++ trunk/sys/arm/freescale/imx/imx_wdogreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,63 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/imx/imx_wdogreg.h 294678 2016-01-24 19:34:05Z ian $
+ */
+
+#define WDOG_CLK_FREQ 32768
+
+#define WDOG_CR_REG 0x00 /* Control Register */
+#define WDOG_CR_WT_MASK 0xff00 /* Count of 0.5 sec */
+#define WDOG_CR_WT_SHIFT 8
+#define WDOG_CR_WDW (1 << 7) /* Suspend WDog */
+#define WDOG_CR_WDA (1 << 5) /* Don't touch ipp_wdog */
+#define WDOG_CR_SRS (1 << 4) /* Don't touch sys_reset */
+#define WDOG_CR_WDT (1 << 3) /* Assert ipp_wdog on tout */
+#define WDOG_CR_WDE (1 << 2) /* WDog Enable */
+#define WDOG_CR_WDBG (1 << 1) /* Suspend when DBG mode */
+#define WDOG_CR_WDZST (1 << 0) /* Suspend when LP mode */
+
+#define WDOG_SR_REG 0x02 /* Service Register */
+#define WDOG_SR_STEP1 0x5555
+#define WDOG_SR_STEP2 0xaaaa
+
+#define WDOG_RSR_REG 0x04 /* Reset Status Register */
+#define WDOG_RSR_POR (1 << 4) /* Due to Power-On Reset */
+#define WDOG_RSR_TOUT (1 << 1) /* Due WDog timeout reset */
+#define WDOG_RSR_SFTW (1 << 0) /* Due Soft reset */
+
+#define WDOG_ICR_REG 0x06 /* Interrupt Control Register */
+#define WDOG_ICR_WIE (1 << 15) /* Enable Interrupt */
+#define WDOG_ICR_WTIS (1 << 14) /* Interrupt has occurred */
+#define WDOG_ICR_WTCT_MASK 0x00ff
+#define WDOG_ICR_WTCT_SHIFT 0 /* Interrupt hold time */
+
+#define WDOG_MCR_REG 0x08 /* Miscellaneous Control Register */
+#define WDOG_MCR_PDE (1 << 0)
+
Property changes on: trunk/sys/arm/freescale/imx/imx_wdogreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/std.imx51
===================================================================
--- trunk/sys/arm/freescale/imx/std.imx51 (rev 0)
+++ trunk/sys/arm/freescale/imx/std.imx51 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,17 @@
+# $FreeBSD: stable/10/sys/arm/freescale/imx/std.imx51 278601 2015-02-11 22:47:48Z ian $
+machine arm armv6
+cpu CPU_CORTEXA
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+makeoptions ARM_LITTLE_ENDIAN
+options ARM_L2_PIPT
+
+options KERNVIRTADDR=0xc0100000
+makeoptions KERNVIRTADDR=0xc0100000
+options KERNPHYSADDR=0x90100000
+makeoptions KERNPHYSADDR=0x90100000
+options PHYSADDR=0x90000000
+
+device fdt_pinctrl
+
+files "../freescale/imx/files.imx51"
+
Property changes on: trunk/sys/arm/freescale/imx/std.imx51
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/std.imx53
===================================================================
--- trunk/sys/arm/freescale/imx/std.imx53 (rev 0)
+++ trunk/sys/arm/freescale/imx/std.imx53 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,17 @@
+# $FreeBSD: stable/10/sys/arm/freescale/imx/std.imx53 278601 2015-02-11 22:47:48Z ian $
+machine arm armv6
+cpu CPU_CORTEXA
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+makeoptions ARM_LITTLE_ENDIAN
+options ARM_L2_PIPT
+
+options KERNVIRTADDR=0xc0100000
+makeoptions KERNVIRTADDR=0xc0100000
+options KERNPHYSADDR=0x70100000
+makeoptions KERNPHYSADDR=0x70100000
+options PHYSADDR=0x70000000
+
+device fdt_pinctrl
+
+files "../freescale/imx/files.imx53"
+
Property changes on: trunk/sys/arm/freescale/imx/std.imx53
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/std.imx6
===================================================================
--- trunk/sys/arm/freescale/imx/std.imx6 (rev 0)
+++ trunk/sys/arm/freescale/imx/std.imx6 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,20 @@
+# $FreeBSD: stable/10/sys/arm/freescale/imx/std.imx6 278601 2015-02-11 22:47:48Z ian $
+machine arm armv6
+cpu CPU_CORTEXA
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+makeoptions ARM_LITTLE_ENDIAN
+options ARM_L2_PIPT
+
+options KERNVIRTADDR = 0xc2000000
+makeoptions KERNVIRTADDR = 0xc2000000
+options KERNPHYSADDR = 0x12000000
+makeoptions KERNPHYSADDR = 0x12000000
+options PHYSADDR = 0x10000000
+
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
+
+device fdt_pinctrl
+
+files "../freescale/imx/files.imx6"
+
Property changes on: trunk/sys/arm/freescale/imx/std.imx6
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/imx/tzic.c
===================================================================
--- trunk/sys/arm/freescale/imx/tzic.c (rev 0)
+++ trunk/sys/arm/freescale/imx/tzic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,192 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/imx/tzic.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/cpuset.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/freescale/imx/imx51_tzicreg.h>
+
+struct tzic_softc {
+ struct resource * tzic_res[3];
+ bus_space_tag_t tzic_bst;
+ bus_space_handle_t tzic_bsh;
+ uint8_t ver;
+};
+
+static struct resource_spec tzic_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct tzic_softc *tzic_sc = NULL;
+
+#define tzic_read_4(reg) \
+ bus_space_read_4(tzic_sc->tzic_bst, tzic_sc->tzic_bsh, reg)
+#define tzic_write_4(reg, val) \
+ bus_space_write_4(tzic_sc->tzic_bst, tzic_sc->tzic_bsh, reg, val)
+
+static void tzic_post_filter(void *);
+
+static int
+tzic_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "fsl,tzic")) {
+ device_set_desc(dev, "TrustZone Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+tzic_attach(device_t dev)
+{
+ struct tzic_softc *sc = device_get_softc(dev);
+ int i;
+ uint32_t reg;
+
+ if (tzic_sc)
+ return (ENXIO);
+
+ if (bus_alloc_resources(dev, tzic_spec, sc->tzic_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ arm_post_filter = tzic_post_filter;
+
+ /* Distributor Interface */
+ sc->tzic_bst = rman_get_bustag(sc->tzic_res[0]);
+ sc->tzic_bsh = rman_get_bushandle(sc->tzic_res[0]);
+
+ tzic_sc = sc;
+
+ reg = tzic_read_4(TZIC_INTCNTL);
+ tzic_write_4(TZIC_INTCNTL, INTCNTL_NSEN_MASK|INTCNTL_NSEN|INTCNTL_EN);
+ reg = tzic_read_4(TZIC_INTCNTL);
+ tzic_write_4(TZIC_PRIOMASK, 0x1f);
+ reg = tzic_read_4(TZIC_PRIOMASK);
+
+ tzic_write_4(TZIC_SYNCCTRL, 0x02);
+ reg = tzic_read_4(TZIC_SYNCCTRL);
+
+ /* route all interrupts to IRQ. secure interrupts are for FIQ */
+ for (i = 0; i < 4; i++)
+ tzic_write_4(TZIC_INTSEC(i), 0xffffffff);
+
+ /* disable all interrupts */
+ for (i = 0; i < 4; i++)
+ tzic_write_4(TZIC_ENCLEAR(i), 0xffffffff);
+
+ return (0);
+}
+
+static device_method_t tzic_methods[] = {
+ DEVMETHOD(device_probe, tzic_probe),
+ DEVMETHOD(device_attach, tzic_attach),
+ { 0, 0 }
+};
+
+static driver_t tzic_driver = {
+ "tzic",
+ tzic_methods,
+ sizeof(struct tzic_softc),
+};
+
+static devclass_t tzic_devclass;
+
+/*
+ * Memory space of controller located outside of device range, so let him to
+ * attach not only to simplebus, but ofwbus also.
+ */
+EARLY_DRIVER_MODULE(tzic, ofwbus, tzic_driver, tzic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT);
+EARLY_DRIVER_MODULE(tzic, simplebus, tzic_driver, tzic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT);
+
+static void
+tzic_post_filter(void *arg)
+{
+
+}
+
+int
+arm_get_next_irq(int last_irq)
+{
+ uint32_t pending;
+ int i, b;
+
+ for (i = 0; i < 4; i++) {
+ pending = tzic_read_4(TZIC_PND(i));
+ for (b = 0; pending != 0 && b < 32; b++)
+ if (pending & (1 << b)) {
+ return (i * 32 + b);
+ }
+ }
+
+ return (-1);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+
+ tzic_write_4(TZIC_ENCLEAR(nb / 32), (1UL <<(nb % 32)));
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+
+ tzic_write_4(TZIC_ENSET(nb / 32), (1UL <<(nb % 32)));
+}
Property changes on: trunk/sys/arm/freescale/imx/tzic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/files.vybrid
===================================================================
--- trunk/sys/arm/freescale/vybrid/files.vybrid (rev 0)
+++ trunk/sys/arm/freescale/vybrid/files.vybrid 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,34 @@
+# $FreeBSD: stable/10/sys/arm/freescale/vybrid/files.vybrid 278727 2015-02-13 22:32:02Z ian $
+
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_generic.c standard
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+
+arm/arm/bus_space_base.c standard
+arm/arm/gic.c standard
+arm/arm/mpcore_timer.c standard
+
+arm/freescale/vybrid/vf_machdep.c standard
+arm/freescale/vybrid/vf_common.c standard
+arm/freescale/vybrid/vf_ccm.c standard
+arm/freescale/vybrid/vf_anadig.c standard
+arm/freescale/vybrid/vf_iomuxc.c standard
+arm/freescale/vybrid/vf_mscm.c standard
+arm/freescale/vybrid/vf_src.c standard
+arm/freescale/vybrid/vf_edma.c standard
+arm/freescale/vybrid/vf_dmamux.c standard
+arm/freescale/vybrid/vf_port.c standard
+arm/freescale/vybrid/vf_i2c.c optional iicbus
+arm/freescale/vybrid/vf_tcon.c optional vt
+arm/freescale/vybrid/vf_dcu4.c optional vt
+arm/freescale/vybrid/vf_nfc.c optional nand
+arm/freescale/vybrid/vf_ehci.c optional ehci
+arm/freescale/vybrid/vf_gpio.c optional gpio
+arm/freescale/vybrid/vf_uart.c optional uart
+arm/freescale/vybrid/vf_sai.c optional sound
+dev/ffec/if_ffec.c optional ffec
Property changes on: trunk/sys/arm/freescale/vybrid/files.vybrid
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/std.vybrid
===================================================================
--- trunk/sys/arm/freescale/vybrid/std.vybrid (rev 0)
+++ trunk/sys/arm/freescale/vybrid/std.vybrid 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,19 @@
+# $FreeBSD: stable/10/sys/arm/freescale/vybrid/std.vybrid 278601 2015-02-11 22:47:48Z ian $
+
+makeoption ARM_LITTLE_ENDIAN
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+
+options PHYSADDR=0x80000000
+
+makeoptions KERNPHYSADDR=0x80100000
+options KERNPHYSADDR=0x80100000
+
+makeoptions KERNVIRTADDR=0xc0100000
+options KERNVIRTADDR=0xc0100000
+
+options ARM_L2_PIPT
+
+files "../freescale/vybrid/files.vybrid"
Property changes on: trunk/sys/arm/freescale/vybrid/std.vybrid
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_anadig.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_anadig.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_anadig.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,247 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Analog components control digital interface (ANADIG)
+ * Chapter 11, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_anadig.c 266198 2014-05-15 22:03:24Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_common.h>
+
+#define ANADIG_PLL3_CTRL 0x010 /* PLL3 Control */
+#define ANADIG_PLL7_CTRL 0x020 /* PLL7 Control */
+#define ANADIG_PLL2_CTRL 0x030 /* PLL2 Control */
+#define ANADIG_PLL2_SS 0x040 /* PLL2 Spread Spectrum */
+#define ANADIG_PLL2_NUM 0x050 /* PLL2 Numerator */
+#define ANADIG_PLL2_DENOM 0x060 /* PLL2 Denominator */
+#define ANADIG_PLL4_CTRL 0x070 /* PLL4 Control */
+#define ANADIG_PLL4_NUM 0x080 /* PLL4 Numerator */
+#define ANADIG_PLL4_DENOM 0x090 /* PLL4 Denominator */
+#define ANADIG_PLL6_CTRL 0x0A0 /* PLL6 Control */
+#define ANADIG_PLL6_NUM 0x0B0 /* PLL6 Numerator */
+#define ANADIG_PLL6_DENOM 0x0C0 /* PLL6 Denominator */
+#define ANADIG_PLL5_CTRL 0x0E0 /* PLL5 Control */
+#define ANADIG_PLL3_PFD 0x0F0 /* PLL3 PFD */
+#define ANADIG_PLL2_PFD 0x100 /* PLL2 PFD */
+#define ANADIG_REG_1P1 0x110 /* Regulator 1P1 */
+#define ANADIG_REG_3P0 0x120 /* Regulator 3P0 */
+#define ANADIG_REG_2P5 0x130 /* Regulator 2P5 */
+#define ANADIG_ANA_MISC0 0x150 /* Analog Miscellaneous */
+#define ANADIG_ANA_MISC1 0x160 /* Analog Miscellaneous */
+#define ANADIG_ANADIG_DIGPROG 0x260 /* Digital Program */
+#define ANADIG_PLL1_CTRL 0x270 /* PLL1 Control */
+#define ANADIG_PLL1_SS 0x280 /* PLL1 Spread Spectrum */
+#define ANADIG_PLL1_NUM 0x290 /* PLL1 Numerator */
+#define ANADIG_PLL1_DENOM 0x2A0 /* PLL1 Denominator */
+#define ANADIG_PLL1_PFD 0x2B0 /* PLL1_PFD */
+#define ANADIG_PLL_LOCK 0x2C0 /* PLL Lock */
+
+#define USB_VBUS_DETECT(n) (0x1A0 + 0x60 * n)
+#define USB_CHRG_DETECT(n) (0x1B0 + 0x60 * n)
+#define USB_VBUS_DETECT_STATUS(n) (0x1C0 + 0x60 * n)
+#define USB_CHRG_DETECT_STATUS(n) (0x1D0 + 0x60 * n)
+#define USB_LOOPBACK(n) (0x1E0 + 0x60 * n)
+#define USB_MISC(n) (0x1F0 + 0x60 * n)
+
+#define ANADIG_PLL_LOCKED (1 << 31)
+#define ENABLE_LINREG (1 << 0)
+#define EN_CLK_TO_UTMI (1 << 30)
+
+#define CTRL_BYPASS (1 << 16)
+#define CTRL_PWR (1 << 12)
+#define CTRL_PLL_EN (1 << 13)
+#define EN_USB_CLKS (1 << 6)
+
+#define PLL4_CTRL_DIV_SEL_S 0
+#define PLL4_CTRL_DIV_SEL_M 0x7f
+
+struct anadig_softc {
+ struct resource *res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+struct anadig_softc *anadig_sc;
+
+static struct resource_spec anadig_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+anadig_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-anadig"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family ANADIG Unit");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+enable_pll(struct anadig_softc *sc, int pll_ctrl)
+{
+ int reg;
+
+ reg = READ4(sc, pll_ctrl);
+ reg &= ~(CTRL_BYPASS | CTRL_PWR);
+ if (pll_ctrl == ANADIG_PLL3_CTRL || pll_ctrl == ANADIG_PLL7_CTRL) {
+ /* It is USB PLL. Power bit logic is reversed */
+ reg |= (CTRL_PWR | EN_USB_CLKS);
+ }
+ WRITE4(sc, pll_ctrl, reg);
+
+ /* Wait for PLL lock */
+ while (!(READ4(sc, pll_ctrl) & ANADIG_PLL_LOCKED))
+ ;
+
+ reg = READ4(sc, pll_ctrl);
+ reg |= (CTRL_PLL_EN);
+ WRITE4(sc, pll_ctrl, reg);
+
+ return (0);
+}
+
+uint32_t
+pll4_configure_output(uint32_t mfi, uint32_t mfn, uint32_t mfd)
+{
+ struct anadig_softc *sc;
+ int reg;
+
+ sc = anadig_sc;
+
+ /*
+ * PLLout = Fsys * (MFI+(MFN/MFD))
+ */
+
+ reg = READ4(sc, ANADIG_PLL4_CTRL);
+ reg &= ~(PLL4_CTRL_DIV_SEL_M << PLL4_CTRL_DIV_SEL_S);
+ reg |= (mfi << PLL4_CTRL_DIV_SEL_S);
+ WRITE4(sc, ANADIG_PLL4_CTRL, reg);
+ WRITE4(sc, ANADIG_PLL4_NUM, mfn);
+ WRITE4(sc, ANADIG_PLL4_DENOM, mfd);
+
+ return (0);
+}
+
+static int
+anadig_attach(device_t dev)
+{
+ struct anadig_softc *sc;
+ int reg;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, anadig_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ anadig_sc = sc;
+
+ /* Enable USB PLLs */
+ enable_pll(sc, ANADIG_PLL3_CTRL);
+ enable_pll(sc, ANADIG_PLL7_CTRL);
+
+ /* Enable other PLLs */
+ enable_pll(sc, ANADIG_PLL1_CTRL);
+ enable_pll(sc, ANADIG_PLL2_CTRL);
+ enable_pll(sc, ANADIG_PLL4_CTRL);
+ enable_pll(sc, ANADIG_PLL5_CTRL);
+ enable_pll(sc, ANADIG_PLL6_CTRL);
+
+ /* Enable USB voltage regulator */
+ reg = READ4(sc, ANADIG_REG_3P0);
+ reg |= (ENABLE_LINREG);
+ WRITE4(sc, ANADIG_REG_3P0, reg);
+
+ /* Give clocks to USB */
+ reg = READ4(sc, USB_MISC(0));
+ reg |= (EN_CLK_TO_UTMI);
+ WRITE4(sc, USB_MISC(0), reg);
+
+ reg = READ4(sc, USB_MISC(1));
+ reg |= (EN_CLK_TO_UTMI);
+ WRITE4(sc, USB_MISC(1), reg);
+
+#if 0
+ printf("USB_ANALOG_USB_MISC(0) == 0x%08x\n",
+ READ4(sc, USB_ANALOG_USB_MISC(0)));
+ printf("USB_ANALOG_USB_MISC(1) == 0x%08x\n",
+ READ4(sc, USB_ANALOG_USB_MISC(1)));
+#endif
+
+ return (0);
+}
+
+static device_method_t anadig_methods[] = {
+ DEVMETHOD(device_probe, anadig_probe),
+ DEVMETHOD(device_attach, anadig_attach),
+ { 0, 0 }
+};
+
+static driver_t anadig_driver = {
+ "anadig",
+ anadig_methods,
+ sizeof(struct anadig_softc),
+};
+
+static devclass_t anadig_devclass;
+
+DRIVER_MODULE(anadig, simplebus, anadig_driver, anadig_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_anadig.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_ccm.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_ccm.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_ccm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,502 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Clock Controller Module (CCM)
+ * Chapter 10, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_ccm.c 266203 2014-05-16 00:14:50Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_common.h>
+
+#define CCM_CCR 0x00 /* Control Register */
+#define CCM_CSR 0x04 /* Status Register */
+#define CCM_CCSR 0x08 /* Clock Switcher Register */
+#define CCM_CACRR 0x0C /* ARM Clock Root Register */
+#define CCM_CSCMR1 0x10 /* Serial Clock Multiplexer Register 1 */
+#define CCM_CSCDR1 0x14 /* Serial Clock Divider Register 1 */
+#define CCM_CSCDR2 0x18 /* Serial Clock Divider Register 2 */
+#define CCM_CSCDR3 0x1C /* Serial Clock Divider Register 3 */
+#define CCM_CSCMR2 0x20 /* Serial Clock Multiplexer Register 2 */
+#define CCM_CTOR 0x28 /* Testing Observability Register */
+#define CCM_CLPCR 0x2C /* Low Power Control Register */
+#define CCM_CISR 0x30 /* Interrupt Status Register */
+#define CCM_CIMR 0x34 /* Interrupt Mask Register */
+#define CCM_CCOSR 0x38 /* Clock Output Source Register */
+#define CCM_CGPR 0x3C /* General Purpose Register */
+
+#define CCM_CCGRN 12
+#define CCM_CCGR(n) (0x40 + (n * 0x04)) /* Clock Gating Register */
+#define CCM_CMEOR(n) (0x70 + (n * 0x70)) /* Module Enable Override */
+#define CCM_CCPGR(n) (0x90 + (n * 0x04)) /* Platform Clock Gating */
+
+#define CCM_CPPDSR 0x88 /* PLL PFD Disable Status Register */
+#define CCM_CCOWR 0x8C /* CORE Wakeup Register */
+
+#define PLL3_PFD4_EN (1 << 31)
+#define PLL3_PFD3_EN (1 << 30)
+#define PLL3_PFD2_EN (1 << 29)
+#define PLL3_PFD1_EN (1 << 28)
+#define PLL2_PFD4_EN (1 << 15)
+#define PLL2_PFD3_EN (1 << 14)
+#define PLL2_PFD2_EN (1 << 13)
+#define PLL2_PFD1_EN (1 << 12)
+#define PLL1_PFD4_EN (1 << 11)
+#define PLL1_PFD3_EN (1 << 10)
+#define PLL1_PFD2_EN (1 << 9)
+#define PLL1_PFD1_EN (1 << 8)
+
+/* CCM_CCR */
+#define FIRC_EN (1 << 16)
+#define FXOSC_EN (1 << 12)
+#define FXOSC_RDY (1 << 5)
+
+/* CCM_CSCDR1 */
+#define ENET_TS_EN (1 << 23)
+#define RMII_CLK_EN (1 << 24)
+#define SAI3_EN (1 << 19)
+
+/* CCM_CSCDR2 */
+#define ESAI_EN (1 << 30)
+#define ESDHC1_EN (1 << 29)
+#define ESDHC0_EN (1 << 28)
+#define NFC_EN (1 << 9)
+#define ESDHC1_DIV_S 20
+#define ESDHC1_DIV_M 0xf
+#define ESDHC0_DIV_S 16
+#define ESDHC0_DIV_M 0xf
+
+/* CCM_CSCDR3 */
+#define DCU0_EN (1 << 19)
+
+#define QSPI1_EN (1 << 12)
+#define QSPI1_DIV (1 << 11)
+#define QSPI1_X2_DIV (1 << 10)
+#define QSPI1_X4_DIV_M 0x3
+#define QSPI1_X4_DIV_S 8
+
+#define QSPI0_EN (1 << 4)
+#define QSPI0_DIV (1 << 3)
+#define QSPI0_X2_DIV (1 << 2)
+#define QSPI0_X4_DIV_M 0x3
+#define QSPI0_X4_DIV_S 0
+
+#define SAI3_DIV_SHIFT 12
+#define SAI3_DIV_MASK 0xf
+#define ESAI_DIV_SHIFT 24
+#define ESAI_DIV_MASK 0xf
+
+#define PLL4_CLK_DIV_SHIFT 6
+#define PLL4_CLK_DIV_MASK 0x7
+
+#define IPG_CLK_DIV_SHIFT 11
+#define IPG_CLK_DIV_MASK 0x3
+
+#define ESAI_CLK_SEL_SHIFT 20
+#define ESAI_CLK_SEL_MASK 0x3
+
+#define SAI3_CLK_SEL_SHIFT 6
+#define SAI3_CLK_SEL_MASK 0x3
+
+#define CKO1_EN (1 << 10)
+#define CKO1_DIV_MASK 0xf
+#define CKO1_DIV_SHIFT 6
+#define CKO1_SEL_MASK 0x3f
+#define CKO1_SEL_SHIFT 0
+#define CKO1_PLL4_MAIN 0x6
+#define CKO1_PLL4_DIVD 0x7
+
+struct clk {
+ uint32_t reg;
+ uint32_t enable_reg;
+ uint32_t div_mask;
+ uint32_t div_shift;
+ uint32_t div_val;
+ uint32_t sel_reg;
+ uint32_t sel_mask;
+ uint32_t sel_shift;
+ uint32_t sel_val;
+};
+
+static struct clk ipg_clk = {
+ .reg = CCM_CACRR,
+ .enable_reg = 0,
+ .div_mask = IPG_CLK_DIV_MASK,
+ .div_shift = IPG_CLK_DIV_SHIFT,
+ .div_val = 1, /* Divide by 2 */
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
+/*
+ PLL4 clock divider (before switching the clocks should be gated)
+ 000 Divide by 1 (only if PLL frequency less than or equal to 650 MHz)
+ 001 Divide by 4
+ 010 Divide by 6
+ 011 Divide by 8
+ 100 Divide by 10
+ 101 Divide by 12
+ 110 Divide by 14
+ 111 Divide by 16
+*/
+
+static struct clk pll4_clk = {
+ .reg = CCM_CACRR,
+ .enable_reg = 0,
+ .div_mask = PLL4_CLK_DIV_MASK,
+ .div_shift = PLL4_CLK_DIV_SHIFT,
+ .div_val = 5, /* Divide by 12 */
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
+static struct clk sai3_clk = {
+ .reg = CCM_CSCDR1,
+ .enable_reg = SAI3_EN,
+ .div_mask = SAI3_DIV_MASK,
+ .div_shift = SAI3_DIV_SHIFT,
+ .div_val = 1,
+ .sel_reg = CCM_CSCMR1,
+ .sel_mask = SAI3_CLK_SEL_MASK,
+ .sel_shift = SAI3_CLK_SEL_SHIFT,
+ .sel_val = 0x3, /* Divided PLL4 main clock */
+};
+
+static struct clk cko1_clk = {
+ .reg = CCM_CCOSR,
+ .enable_reg = CKO1_EN,
+ .div_mask = CKO1_DIV_MASK,
+ .div_shift = CKO1_DIV_SHIFT,
+ .div_val = 1,
+ .sel_reg = CCM_CCOSR,
+ .sel_mask = CKO1_SEL_MASK,
+ .sel_shift = CKO1_SEL_SHIFT,
+ .sel_val = CKO1_PLL4_DIVD,
+};
+
+static struct clk esdhc0_clk = {
+ .reg = CCM_CSCDR2,
+ .enable_reg = ESDHC0_EN,
+ .div_mask = ESDHC0_DIV_M,
+ .div_shift = ESDHC0_DIV_S,
+ .div_val = 0x9,
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
+static struct clk esdhc1_clk = {
+ .reg = CCM_CSCDR2,
+ .enable_reg = ESDHC1_EN,
+ .div_mask = ESDHC1_DIV_M,
+ .div_shift = ESDHC1_DIV_S,
+ .div_val = 0x9,
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
+static struct clk qspi0_clk = {
+ .reg = CCM_CSCDR3,
+ .enable_reg = QSPI0_EN,
+ .div_mask = 0,
+ .div_shift = 0,
+ .div_val = 0,
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
+static struct clk dcu0_clk = {
+ .reg = CCM_CSCDR3,
+ .enable_reg = DCU0_EN,
+ .div_mask = 0x7,
+ .div_shift = 16, /* DCU0_DIV */
+ .div_val = 0, /* divide by 1 */
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
+static struct clk enet_clk = {
+ .reg = CCM_CSCDR1,
+ .enable_reg = (ENET_TS_EN | RMII_CLK_EN),
+ .div_mask = 0,
+ .div_shift = 0,
+ .div_val = 0,
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
+static struct clk nand_clk = {
+ .reg = CCM_CSCDR2,
+ .enable_reg = NFC_EN,
+ .div_mask = 0,
+ .div_shift = 0,
+ .div_val = 0,
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
+/*
+ Divider to generate ESAI clock
+ 0000 Divide by 1
+ 0001 Divide by 2
+ ... ...
+ 1111 Divide by 16
+*/
+
+static struct clk esai_clk = {
+ .reg = CCM_CSCDR2,
+ .enable_reg = ESAI_EN,
+ .div_mask = ESAI_DIV_MASK,
+ .div_shift = ESAI_DIV_SHIFT,
+ .div_val = 3, /* Divide by 4 */
+ .sel_reg = CCM_CSCMR1,
+ .sel_mask = ESAI_CLK_SEL_MASK,
+ .sel_shift = ESAI_CLK_SEL_SHIFT,
+ .sel_val = 0x3, /* Divided PLL4 main clock */
+};
+
+struct clock_entry {
+ char *name;
+ struct clk *clk;
+};
+
+static struct clock_entry clock_map[] = {
+ {"ipg", &ipg_clk},
+ {"pll4", &pll4_clk},
+ {"sai3", &sai3_clk},
+ {"cko1", &cko1_clk},
+ {"esdhc0", &esdhc0_clk},
+ {"esdhc1", &esdhc1_clk},
+ {"qspi0", &qspi0_clk},
+ {"dcu0", &dcu0_clk},
+ {"enet", &enet_clk},
+ {"nand", &nand_clk},
+ {"esai", &esai_clk},
+ {NULL, NULL}
+};
+
+struct ccm_softc {
+ struct resource *res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+};
+
+static struct resource_spec ccm_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+ccm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-ccm"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family CCM Unit");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+set_clock(struct ccm_softc *sc, char *name)
+{
+ struct clk *clk;
+ int reg;
+ int i;
+
+ for (i = 0; clock_map[i].name != NULL; i++) {
+ if (strcmp(clock_map[i].name, name) == 0) {
+#if 0
+ device_printf(sc->dev, "Configuring %s clk\n", name);
+#endif
+ clk = clock_map[i].clk;
+ if (clk->sel_reg != 0) {
+ reg = READ4(sc, clk->sel_reg);
+ reg &= ~(clk->sel_mask << clk->sel_shift);
+ reg |= (clk->sel_val << clk->sel_shift);
+ WRITE4(sc, clk->sel_reg, reg);
+ };
+
+ reg = READ4(sc, clk->reg);
+ reg |= clk->enable_reg;
+ reg &= ~(clk->div_mask << clk->div_shift);
+ reg |= (clk->div_val << clk->div_shift);
+ WRITE4(sc, clk->reg, reg);
+ };
+ };
+
+ return (0);
+}
+
+static int
+ccm_fdt_set(struct ccm_softc *sc)
+{
+ phandle_t child, parent, root;
+ int len;
+ char *fdt_config, *name;
+
+ root = OF_finddevice("/");
+ len = 0;
+ parent = root;
+
+ /* Find 'clock_names' prop in the tree */
+ for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
+
+ /* Find a 'leaf'. Start the search from this node. */
+ while (OF_child(child)) {
+ parent = child;
+ child = OF_child(child);
+ }
+
+ if (!fdt_is_enabled(child))
+ continue;
+
+ if ((len = OF_getproplen(child, "clock_names")) > 0) {
+ len = OF_getproplen(child, "clock_names");
+ OF_getprop_alloc(child, "clock_names", 1,
+ (void **)&fdt_config);
+
+ while (len > 0) {
+ name = fdt_config;
+ fdt_config += strlen(name) + 1;
+ len -= strlen(name) + 1;
+ set_clock(sc, name);
+ };
+ };
+
+ if (OF_peer(child) == 0) {
+ /* No more siblings. */
+ child = parent;
+ parent = OF_parent(child);
+ }
+ }
+
+ return (0);
+}
+
+static int
+ccm_attach(device_t dev)
+{
+ struct ccm_softc *sc;
+ int reg;
+ int i;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, ccm_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Enable oscillator */
+ reg = READ4(sc, CCM_CCR);
+ reg |= (FIRC_EN | FXOSC_EN);
+ WRITE4(sc, CCM_CCR, reg);
+
+ /* Wait 10 times */
+ for (i = 0; i < 10; i++) {
+ if (READ4(sc, CCM_CSR) & FXOSC_RDY) {
+ device_printf(sc->dev, "On board oscillator is ready.\n");
+ break;
+ }
+
+ cpufunc_nullop();
+ }
+
+ /* Clock is on during all modes, except stop mode. */
+ for (i = 0; i < CCM_CCGRN; i++) {
+ WRITE4(sc, CCM_CCGR(i), 0xffffffff);
+ }
+
+ /* Take and apply FDT clocks */
+ ccm_fdt_set(sc);
+
+ return (0);
+}
+
+static device_method_t ccm_methods[] = {
+ DEVMETHOD(device_probe, ccm_probe),
+ DEVMETHOD(device_attach, ccm_attach),
+ { 0, 0 }
+};
+
+static driver_t ccm_driver = {
+ "ccm",
+ ccm_methods,
+ sizeof(struct ccm_softc),
+};
+
+static devclass_t ccm_devclass;
+
+DRIVER_MODULE(ccm, simplebus, ccm_driver, ccm_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_ccm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_common.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_common.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,87 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_common.c 258057 2013-11-12 18:02:56Z br $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/freescale/vybrid/vf_src.h>
+
+void
+cpu_reset(void)
+{
+ phandle_t src;
+ uint32_t addr, paddr;
+ bus_addr_t vaddr;
+
+ if (src_swreset() == 0)
+ goto end;
+
+ src = OF_finddevice("src");
+ if ((src != 0) && (OF_getprop(src, "reg", &paddr, sizeof(paddr))) > 0) {
+ addr = fdt32_to_cpu(paddr);
+ if (bus_space_map(fdtbus_bs_tag, addr, 0x10, 0, &vaddr) == 0) {
+ bus_space_write_4(fdtbus_bs_tag, vaddr, 0x00, SW_RST);
+ }
+ }
+
+end:
+ while (1);
+}
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (!fdt_is_compatible(node, "arm,gic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_pic_decode_ic,
+ NULL
+};
Property changes on: trunk/sys/arm/freescale/vybrid/vf_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_common.h
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_common.h (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_common.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,44 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_common.h 266198 2014-05-15 22:03:24Z ian $
+ */
+
+#define READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst, _sc->bsh, _reg)
+#define WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
+#define READ2(_sc, _reg) \
+ bus_space_read_2(_sc->bst, _sc->bsh, _reg)
+#define WRITE2(_sc, _reg, _val) \
+ bus_space_write_2(_sc->bst, _sc->bsh, _reg, _val)
+#define READ1(_sc, _reg) \
+ bus_space_read_1(_sc->bst, _sc->bsh, _reg)
+#define WRITE1(_sc, _reg, _val) \
+ bus_space_write_1(_sc->bst, _sc->bsh, _reg, _val)
+
+uint32_t pll4_configure_output(uint32_t mfi, uint32_t mfn, uint32_t mfd);
+uint32_t tcon_bypass(void);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_common.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_dcu4.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_dcu4.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_dcu4.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,468 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Display Control Unit (DCU4)
+ * Chapter 55, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_dcu4.c 266274 2014-05-16 23:27:18Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+#include <sys/eventhandler.h>
+#include <sys/gpio.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/vt/vt.h>
+#include <dev/vt/colors/vt_termcolors.h>
+
+#include "gpio_if.h"
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include "fb_if.h"
+
+#include <arm/freescale/vybrid/vf_common.h>
+
+#define DCU_CTRLDESCCURSOR1 0x000 /* Control Descriptor Cursor 1 */
+#define DCU_CTRLDESCCURSOR2 0x004 /* Control Descriptor Cursor 2 */
+#define DCU_CTRLDESCCURSOR3 0x008 /* Control Descriptor Cursor 3 */
+#define DCU_CTRLDESCCURSOR4 0x00C /* Control Descriptor Cursor 4 */
+#define DCU_DCU_MODE 0x010 /* DCU4 Mode */
+#define DCU_MODE_M 0x3
+#define DCU_MODE_S 0
+#define DCU_MODE_NORMAL 0x1
+#define DCU_MODE_TEST 0x2
+#define DCU_MODE_COLBAR 0x3
+#define RASTER_EN (1 << 14) /* Raster scan of pixel data */
+#define PDI_EN (1 << 13)
+#define PDI_DE_MODE (1 << 11)
+#define PDI_MODE_M 2
+#define DCU_BGND 0x014 /* Background */
+#define DCU_DISP_SIZE 0x018 /* Display Size */
+#define DELTA_M 0x7ff
+#define DELTA_Y_S 16
+#define DELTA_X_S 0
+#define DCU_HSYN_PARA 0x01C /* Horizontal Sync Parameter */
+#define BP_H_SHIFT 22
+#define PW_H_SHIFT 11
+#define FP_H_SHIFT 0
+#define DCU_VSYN_PARA 0x020 /* Vertical Sync Parameter */
+#define BP_V_SHIFT 22
+#define PW_V_SHIFT 11
+#define FP_V_SHIFT 0
+#define DCU_SYNPOL 0x024 /* Synchronize Polarity */
+#define INV_HS (1 << 0)
+#define INV_VS (1 << 1)
+#define INV_PDI_VS (1 << 8) /* Polarity of PDI input VSYNC. */
+#define INV_PDI_HS (1 << 9) /* Polarity of PDI input HSYNC. */
+#define INV_PDI_DE (1 << 10) /* Polarity of PDI input DE. */
+#define DCU_THRESHOLD 0x028 /* Threshold */
+#define LS_BF_VS_SHIFT 16
+#define OUT_BUF_HIGH_SHIFT 8
+#define OUT_BUF_LOW_SHIFT 0
+#define DCU_INT_STATUS 0x02C /* Interrupt Status */
+#define DCU_INT_MASK 0x030 /* Interrupt Mask */
+#define DCU_COLBAR_1 0x034 /* COLBAR_1 */
+#define DCU_COLBAR_2 0x038 /* COLBAR_2 */
+#define DCU_COLBAR_3 0x03C /* COLBAR_3 */
+#define DCU_COLBAR_4 0x040 /* COLBAR_4 */
+#define DCU_COLBAR_5 0x044 /* COLBAR_5 */
+#define DCU_COLBAR_6 0x048 /* COLBAR_6 */
+#define DCU_COLBAR_7 0x04C /* COLBAR_7 */
+#define DCU_COLBAR_8 0x050 /* COLBAR_8 */
+#define DCU_DIV_RATIO 0x054 /* Divide Ratio */
+#define DCU_SIGN_CALC_1 0x058 /* Sign Calculation 1 */
+#define DCU_SIGN_CALC_2 0x05C /* Sign Calculation 2 */
+#define DCU_CRC_VAL 0x060 /* CRC Value */
+#define DCU_PDI_STATUS 0x064 /* PDI Status */
+#define DCU_PDI_STA_MSK 0x068 /* PDI Status Mask */
+#define DCU_PARR_ERR_STATUS1 0x06C /* Parameter Error Status 1 */
+#define DCU_PARR_ERR_STATUS2 0x070 /* Parameter Error Status 2 */
+#define DCU_PARR_ERR_STATUS3 0x07C /* Parameter Error Status 3 */
+#define DCU_MASK_PARR_ERR_ST1 0x080 /* Mask Parameter Error Status 1 */
+#define DCU_MASK_PARR_ERR_ST2 0x084 /* Mask Parameter Error Status 2 */
+#define DCU_MASK_PARR_ERR_ST3 0x090 /* Mask Parameter Error Status 3 */
+#define DCU_THRESHOLD_INP_BUF_1 0x094 /* Threshold Input 1 */
+#define DCU_THRESHOLD_INP_BUF_2 0x098 /* Threshold Input 2 */
+#define DCU_THRESHOLD_INP_BUF_3 0x09C /* Threshold Input 3 */
+#define DCU_LUMA_COMP 0x0A0 /* LUMA Component */
+#define DCU_CHROMA_RED 0x0A4 /* Red Chroma Components */
+#define DCU_CHROMA_GREEN 0x0A8 /* Green Chroma Components */
+#define DCU_CHROMA_BLUE 0x0AC /* Blue Chroma Components */
+#define DCU_CRC_POS 0x0B0 /* CRC Position */
+#define DCU_LYR_INTPOL_EN 0x0B4 /* Layer Interpolation Enable */
+#define DCU_LYR_LUMA_COMP 0x0B8 /* Layer Luminance Component */
+#define DCU_LYR_CHRM_RED 0x0BC /* Layer Chroma Red */
+#define DCU_LYR_CHRM_GRN 0x0C0 /* Layer Chroma Green */
+#define DCU_LYR_CHRM_BLUE 0x0C4 /* Layer Chroma Blue */
+#define DCU_COMP_IMSIZE 0x0C8 /* Compression Image Size */
+#define DCU_UPDATE_MODE 0x0CC /* Update Mode */
+#define READREG (1 << 30)
+#define MODE (1 << 31)
+#define DCU_UNDERRUN 0x0D0 /* Underrun */
+#define DCU_GLBL_PROTECT 0x100 /* Global Protection */
+#define DCU_SFT_LCK_BIT_L0 0x104 /* Soft Lock Bit Layer 0 */
+#define DCU_SFT_LCK_BIT_L1 0x108 /* Soft Lock Bit Layer 1 */
+#define DCU_SFT_LCK_DISP_SIZE 0x10C /* Soft Lock Display Size */
+#define DCU_SFT_LCK_HS_VS_PARA 0x110 /* Soft Lock Hsync/Vsync Parameter */
+#define DCU_SFT_LCK_POL 0x114 /* Soft Lock POL */
+#define DCU_SFT_LCK_L0_TRANSP 0x118 /* Soft Lock L0 Transparency */
+#define DCU_SFT_LCK_L1_TRANSP 0x11C /* Soft Lock L1 Transparency */
+
+/* Control Descriptor */
+#define DCU_CTRLDESCL(n, m) 0x200 + (0x40 * n) + 0x4 * (m - 1)
+#define DCU_CTRLDESCLn_1(n) DCU_CTRLDESCL(n, 1)
+#define DCU_CTRLDESCLn_2(n) DCU_CTRLDESCL(n, 2)
+#define DCU_CTRLDESCLn_3(n) DCU_CTRLDESCL(n, 3)
+#define TRANS_SHIFT 20
+#define DCU_CTRLDESCLn_4(n) DCU_CTRLDESCL(n, 4)
+#define BPP_MASK 0xf /* Bit per pixel Mask */
+#define BPP_SHIFT 16 /* Bit per pixel Shift */
+#define BPP24 0x5
+#define EN_LAYER (1 << 31) /* Enable the layer */
+#define DCU_CTRLDESCLn_5(n) DCU_CTRLDESCL(n, 5)
+#define DCU_CTRLDESCLn_6(n) DCU_CTRLDESCL(n, 6)
+#define DCU_CTRLDESCLn_7(n) DCU_CTRLDESCL(n, 7)
+#define DCU_CTRLDESCLn_8(n) DCU_CTRLDESCL(n, 8)
+#define DCU_CTRLDESCLn_9(n) DCU_CTRLDESCL(n, 9)
+
+#define NUM_LAYERS 64
+
+struct panel_info {
+ uint32_t width;
+ uint32_t height;
+ uint32_t h_back_porch;
+ uint32_t h_pulse_width;
+ uint32_t h_front_porch;
+ uint32_t v_back_porch;
+ uint32_t v_pulse_width;
+ uint32_t v_front_porch;
+ uint32_t clk_div;
+ uint32_t backlight_pin;
+};
+
+struct dcu_softc {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ void *ih;
+ device_t dev;
+ device_t sc_fbd; /* fbd child */
+ struct fb_info sc_info;
+ struct panel_info *panel;
+};
+
+static struct resource_spec dcu_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+dcu_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-dcu4"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family Display Control Unit (DCU4)");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static void
+dcu_intr(void *arg)
+{
+ struct dcu_softc *sc;
+ int reg;
+
+ sc = arg;
+
+ /* Ack interrupts */
+ reg = READ4(sc, DCU_INT_STATUS);
+ WRITE4(sc, DCU_INT_STATUS, reg);
+
+ /* TODO interrupt handler */
+}
+
+static int
+get_panel_info(struct dcu_softc *sc, struct panel_info *panel)
+{
+ phandle_t node;
+ pcell_t dts_value[3];
+ int len;
+
+ if ((node = ofw_bus_get_node(sc->dev)) == -1)
+ return (ENXIO);
+
+ /* panel size */
+ if ((len = OF_getproplen(node, "panel-size")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-size", &dts_value, len);
+ panel->width = fdt32_to_cpu(dts_value[0]);
+ panel->height = fdt32_to_cpu(dts_value[1]);
+
+ /* hsync */
+ if ((len = OF_getproplen(node, "panel-hsync")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-hsync", &dts_value, len);
+ panel->h_back_porch = fdt32_to_cpu(dts_value[0]);
+ panel->h_pulse_width = fdt32_to_cpu(dts_value[1]);
+ panel->h_front_porch = fdt32_to_cpu(dts_value[2]);
+
+ /* vsync */
+ if ((len = OF_getproplen(node, "panel-vsync")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-vsync", &dts_value, len);
+ panel->v_back_porch = fdt32_to_cpu(dts_value[0]);
+ panel->v_pulse_width = fdt32_to_cpu(dts_value[1]);
+ panel->v_front_porch = fdt32_to_cpu(dts_value[2]);
+
+ /* clk divider */
+ if ((len = OF_getproplen(node, "panel-clk-div")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-clk-div", &dts_value, len);
+ panel->clk_div = fdt32_to_cpu(dts_value[0]);
+
+ /* backlight pin */
+ if ((len = OF_getproplen(node, "panel-backlight-pin")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-backlight-pin", &dts_value, len);
+ panel->backlight_pin = fdt32_to_cpu(dts_value[0]);
+
+ return (0);
+}
+
+static int
+dcu_init(struct dcu_softc *sc)
+{
+ struct panel_info *panel;
+ int reg;
+ int i;
+
+ panel = sc->panel;
+
+ /* Configure DCU */
+ reg = ((sc->sc_info.fb_height) << DELTA_Y_S);
+ reg |= (sc->sc_info.fb_width / 16);
+ WRITE4(sc, DCU_DISP_SIZE, reg);
+
+ reg = (panel->h_back_porch << BP_H_SHIFT);
+ reg |= (panel->h_pulse_width << PW_H_SHIFT);
+ reg |= (panel->h_front_porch << FP_H_SHIFT);
+ WRITE4(sc, DCU_HSYN_PARA, reg);
+
+ reg = (panel->v_back_porch << BP_V_SHIFT);
+ reg |= (panel->v_pulse_width << PW_V_SHIFT);
+ reg |= (panel->v_front_porch << FP_V_SHIFT);
+ WRITE4(sc, DCU_VSYN_PARA, reg);
+
+ WRITE4(sc, DCU_BGND, 0);
+ WRITE4(sc, DCU_DIV_RATIO, panel->clk_div);
+
+ reg = (INV_VS | INV_HS);
+ WRITE4(sc, DCU_SYNPOL, reg);
+
+ /* TODO: export to panel info */
+ reg = (0x3 << LS_BF_VS_SHIFT);
+ reg |= (0x78 << OUT_BUF_HIGH_SHIFT);
+ reg |= (0 << OUT_BUF_LOW_SHIFT);
+ WRITE4(sc, DCU_THRESHOLD, reg);
+
+ /* Mask all the interrupts */
+ WRITE4(sc, DCU_INT_MASK, 0xffffffff);
+
+ /* Reset all layers */
+ for (i = 0; i < NUM_LAYERS; i++) {
+ WRITE4(sc, DCU_CTRLDESCLn_1(i), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_2(i), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_3(i), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_4(i), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_5(i), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_6(i), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_7(i), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_8(i), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_9(i), 0x0);
+ }
+
+ /* Setup first layer */
+ reg = (sc->sc_info.fb_width | (sc->sc_info.fb_height << 16));
+ WRITE4(sc, DCU_CTRLDESCLn_1(0), reg);
+ WRITE4(sc, DCU_CTRLDESCLn_2(0), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_3(0), sc->sc_info.fb_pbase);
+ reg = (BPP24 << BPP_SHIFT);
+ reg |= EN_LAYER;
+ reg |= (0xFF << TRANS_SHIFT); /* completely opaque */
+ WRITE4(sc, DCU_CTRLDESCLn_4(0), reg);
+ WRITE4(sc, DCU_CTRLDESCLn_5(0), 0xffffff);
+ WRITE4(sc, DCU_CTRLDESCLn_6(0), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_7(0), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_8(0), 0x0);
+ WRITE4(sc, DCU_CTRLDESCLn_9(0), 0x0);
+
+ /* Enable DCU in normal mode */
+ reg = READ4(sc, DCU_DCU_MODE);
+ reg &= ~(DCU_MODE_M << DCU_MODE_S);
+ reg |= (DCU_MODE_NORMAL << DCU_MODE_S);
+ reg |= (RASTER_EN);
+ WRITE4(sc, DCU_DCU_MODE, reg);
+ WRITE4(sc, DCU_UPDATE_MODE, READREG);
+
+ return (0);
+}
+
+static int
+dcu_attach(device_t dev)
+{
+ struct panel_info panel;
+ struct dcu_softc *sc;
+ device_t gpio_dev;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, dcu_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Setup interrupt handler */
+ err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, dcu_intr, sc, &sc->ih);
+ if (err) {
+ device_printf(dev, "Unable to alloc interrupt resource.\n");
+ return (ENXIO);
+ }
+
+ if (get_panel_info(sc, &panel)) {
+ device_printf(dev, "Can't get panel info\n");
+ return (ENXIO);
+ }
+
+ sc->panel = &panel;
+
+ /* Bypass timing control (used for raw lcd panels) */
+ tcon_bypass();
+
+ /* Get the GPIO device, we need this to give power to USB */
+ gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (gpio_dev == NULL) {
+ device_printf(sc->dev, "Error: failed to get the GPIO dev\n");
+ return (1);
+ }
+
+ /* Turn on backlight */
+ /* TODO: Use FlexTimer/PWM */
+ GPIO_PIN_SETFLAGS(gpio_dev, panel.backlight_pin, GPIO_PIN_OUTPUT);
+ GPIO_PIN_SET(gpio_dev, panel.backlight_pin, GPIO_PIN_HIGH);
+
+ sc->sc_info.fb_width = panel.width;
+ sc->sc_info.fb_height = panel.height;
+ sc->sc_info.fb_stride = sc->sc_info.fb_width * 3;
+ sc->sc_info.fb_bpp = sc->sc_info.fb_depth = 24;
+ sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride;
+ sc->sc_info.fb_vbase = (intptr_t)contigmalloc(sc->sc_info.fb_size,
+ M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0);
+ sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase);
+
+#if 0
+ printf("%dx%d [%d]\n", sc->sc_info.fb_width, sc->sc_info.fb_height,
+ sc->sc_info.fb_stride);
+ printf("pbase == 0x%08x\n", sc->sc_info.fb_pbase);
+#endif
+
+ memset((int8_t *)sc->sc_info.fb_vbase, 0x0, sc->sc_info.fb_size);
+
+ dcu_init(sc);
+
+ sc->sc_info.fb_name = device_get_nameunit(dev);
+
+ /* Ask newbus to attach framebuffer device to me. */
+ sc->sc_fbd = device_add_child(dev, "fbd", device_get_unit(dev));
+ if (sc->sc_fbd == NULL)
+ device_printf(dev, "Can't attach fbd device\n");
+
+ if (device_probe_and_attach(sc->sc_fbd) != 0) {
+ device_printf(sc->dev, "Failed to attach fbd device\n");
+ }
+
+ return (0);
+}
+
+static struct fb_info *
+dcu4_fb_getinfo(device_t dev)
+{
+ struct dcu_softc *sc = device_get_softc(dev);
+
+ return (&sc->sc_info);
+}
+
+static device_method_t dcu_methods[] = {
+ DEVMETHOD(device_probe, dcu_probe),
+ DEVMETHOD(device_attach, dcu_attach),
+
+ /* Framebuffer service methods */
+ DEVMETHOD(fb_getinfo, dcu4_fb_getinfo),
+ { 0, 0 }
+};
+
+static driver_t dcu_driver = {
+ "fb",
+ dcu_methods,
+ sizeof(struct dcu_softc),
+};
+
+static devclass_t dcu_devclass;
+
+DRIVER_MODULE(fb, simplebus, dcu_driver, dcu_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_dcu4.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_dmamux.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_dmamux.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_dmamux.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,156 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Direct Memory Access Multiplexer (DMAMUX)
+ * Chapter 22, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_dmamux.c 266170 2014-05-15 18:38:19Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_common.h>
+#include <arm/freescale/vybrid/vf_dmamux.h>
+
+#define DMAMUX_CHCFG(n) (0x1 * n) /* Channels 0-15 Cfg Reg */
+#define CHCFG_ENBL (1 << 7) /* Channel Enable */
+#define CHCFG_TRIG (1 << 6) /* Channel Trigger Enable */
+#define CHCFG_SOURCE_MASK 0x3f /* Channel Source (Slot) */
+#define CHCFG_SOURCE_SHIFT 0
+
+struct dmamux_softc {
+ struct resource *res[4];
+ bus_space_tag_t bst[4];
+ bus_space_handle_t bsh[4];
+};
+
+struct dmamux_softc *dmamux_sc;
+
+static struct resource_spec dmamux_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* DMAMUX0 */
+ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* DMAMUX1 */
+ { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* DMAMUX2 */
+ { SYS_RES_MEMORY, 3, RF_ACTIVE }, /* DMAMUX3 */
+ { -1, 0 }
+};
+
+static int
+dmamux_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-dmamux"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family Direct Memory Access Multiplexer");
+ return (BUS_PROBE_DEFAULT);
+}
+
+int
+dmamux_configure(int mux, int source, int channel, int enable)
+{
+ struct dmamux_softc *sc;
+ int reg;
+
+ sc = dmamux_sc;
+
+ MUX_WRITE1(sc, mux, DMAMUX_CHCFG(channel), 0x0);
+
+ reg = 0;
+ if (enable)
+ reg |= (CHCFG_ENBL);
+
+ reg &= ~(CHCFG_SOURCE_MASK << CHCFG_SOURCE_SHIFT);
+ reg |= (source << CHCFG_SOURCE_SHIFT);
+
+ MUX_WRITE1(sc, mux, DMAMUX_CHCFG(channel), reg);
+
+ return (0);
+}
+
+static int
+dmamux_attach(device_t dev)
+{
+ struct dmamux_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, dmamux_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ for (i = 0; i < 4; i++) {
+ sc->bst[i] = rman_get_bustag(sc->res[i]);
+ sc->bsh[i] = rman_get_bushandle(sc->res[i]);
+ }
+
+ dmamux_sc = sc;
+
+ return (0);
+}
+
+static device_method_t dmamux_methods[] = {
+ DEVMETHOD(device_probe, dmamux_probe),
+ DEVMETHOD(device_attach, dmamux_attach),
+ { 0, 0 }
+};
+
+static driver_t dmamux_driver = {
+ "dmamux",
+ dmamux_methods,
+ sizeof(struct dmamux_softc),
+};
+
+static devclass_t dmamux_devclass;
+
+DRIVER_MODULE(dmamux, simplebus, dmamux_driver, dmamux_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_dmamux.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_dmamux.h
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_dmamux.h (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_dmamux.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,49 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_dmamux.h 266170 2014-05-15 18:38:19Z ian $
+ */
+
+int dmamux_configure(int mux, int source, int channel, int enable);
+
+enum mux_num {
+ MUX0,
+ MUX1,
+ MUX2,
+ MUX3,
+};
+
+enum mux_grp {
+ MUXGRP0, /* MUX[0,3] */
+ MUXGRP1, /* MUX[1,2] */
+};
+
+/* DMAMUX */
+#define MUX_READ1(_sc, _mux, _reg) \
+ bus_space_read_1(_sc->bst[_mux], _sc->bsh[_mux], _reg)
+
+#define MUX_WRITE1(_sc, _mux, _reg, _val) \
+ bus_space_write_1(_sc->bst[_mux], _sc->bsh[_mux], _reg, _val)
Property changes on: trunk/sys/arm/freescale/vybrid/vf_dmamux.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_edma.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_edma.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_edma.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,339 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Enhanced Direct Memory Access Controller (eDMA)
+ * Chapter 21, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_edma.c 266170 2014-05-15 18:38:19Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_edma.h>
+#include <arm/freescale/vybrid/vf_dmamux.h>
+#include <arm/freescale/vybrid/vf_common.h>
+
+struct edma_channel {
+ uint32_t enabled;
+ uint32_t mux_num;
+ uint32_t mux_src;
+ uint32_t mux_chn;
+ uint32_t (*ih) (void *, int);
+ void *ih_user;
+};
+
+static struct edma_channel edma_map[EDMA_NUM_CHANNELS];
+
+static struct resource_spec edma_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* TCD */
+ { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Transfer complete */
+ { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Error Interrupt */
+ { -1, 0 }
+};
+
+static int
+edma_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-edma"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family eDMA Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static void
+edma_transfer_complete_intr(void *arg)
+{
+ struct edma_channel *ch;
+ struct edma_softc *sc;
+ int interrupts;
+ int i;
+
+ sc = arg;
+
+ interrupts = READ4(sc, DMA_INT);
+ WRITE1(sc, DMA_CINT, CINT_CAIR);
+
+ for (i = 0; i < EDMA_NUM_CHANNELS; i++) {
+ if (interrupts & (0x1 << i)) {
+ ch = &edma_map[i];
+ if (ch->enabled == 1) {
+ if (ch->ih != NULL) {
+ ch->ih(ch->ih_user, i);
+ }
+ }
+ }
+ }
+}
+
+static void
+edma_err_intr(void *arg)
+{
+ struct edma_softc *sc;
+ int reg;
+
+ sc = arg;
+
+ reg = READ4(sc, DMA_ERR);
+
+#if 0
+ device_printf(sc->dev, "DMA_ERR 0x%08x, ES 0x%08x\n",
+ reg, READ4(sc, DMA_ES));
+#endif
+
+ WRITE1(sc, DMA_CERR, CERR_CAEI);
+}
+
+static int
+channel_free(struct edma_softc *sc, int chnum)
+{
+ struct edma_channel *ch;
+
+ ch = &edma_map[chnum];
+ ch->enabled = 0;
+
+ dmamux_configure(ch->mux_num, ch->mux_src, ch->mux_chn, 0);
+
+ return (0);
+}
+
+static int
+channel_configure(struct edma_softc *sc, int mux_grp, int mux_src)
+{
+ struct edma_channel *ch;
+ int channel_first;
+ int mux_num;
+ int chnum;
+ int i;
+
+ if ((sc->device_id == 0 && mux_grp == 1) || \
+ (sc->device_id == 1 && mux_grp == 0)) {
+ channel_first = NCHAN_PER_MUX;
+ mux_num = (sc->device_id * 2) + 1;
+ } else {
+ channel_first = 0;
+ mux_num = sc->device_id * 2;
+ };
+
+ /* Take first unused eDMA channel */
+ ch = NULL;
+ for (i = channel_first; i < (channel_first + NCHAN_PER_MUX); i++) {
+ ch = &edma_map[i];
+ if (ch->enabled == 0) {
+ break;
+ }
+ ch = NULL;
+ };
+
+ if (ch == NULL) {
+ /* Can't find free channel */
+ return (-1);
+ };
+
+ chnum = i;
+
+ ch->enabled = 1;
+ ch->mux_num = mux_num;
+ ch->mux_src = mux_src;
+ ch->mux_chn = (chnum - channel_first); /* 0 to 15 */
+
+ dmamux_configure(ch->mux_num, ch->mux_src, ch->mux_chn, 1);
+
+ return (chnum);
+}
+
+static int
+dma_stop(struct edma_softc *sc, int chnum)
+{
+ int reg;
+
+ reg = READ4(sc, DMA_ERQ);
+ reg &= ~(0x1 << chnum);
+ WRITE4(sc, DMA_ERQ, reg);
+
+ return (0);
+}
+
+static int
+dma_setup(struct edma_softc *sc, struct tcd_conf *tcd)
+{
+ struct edma_channel *ch;
+ int chnum;
+ int reg;
+
+ chnum = tcd->channel;
+
+ ch = &edma_map[chnum];
+ ch->ih = tcd->ih;
+ ch->ih_user = tcd->ih_user;
+
+ TCD_WRITE4(sc, DMA_TCDn_SADDR(chnum), tcd->saddr);
+ TCD_WRITE4(sc, DMA_TCDn_DADDR(chnum), tcd->daddr);
+
+ reg = (tcd->smod << TCD_ATTR_SMOD_SHIFT);
+ reg |= (tcd->dmod << TCD_ATTR_DMOD_SHIFT);
+ reg |= (tcd->ssize << TCD_ATTR_SSIZE_SHIFT);
+ reg |= (tcd->dsize << TCD_ATTR_DSIZE_SHIFT);
+ TCD_WRITE2(sc, DMA_TCDn_ATTR(chnum), reg);
+
+ TCD_WRITE2(sc, DMA_TCDn_SOFF(chnum), tcd->soff);
+ TCD_WRITE2(sc, DMA_TCDn_DOFF(chnum), tcd->doff);
+ TCD_WRITE4(sc, DMA_TCDn_SLAST(chnum), tcd->slast);
+ TCD_WRITE4(sc, DMA_TCDn_DLASTSGA(chnum), tcd->dlast_sga);
+ TCD_WRITE4(sc, DMA_TCDn_NBYTES_MLOFFYES(chnum), tcd->nbytes);
+
+ reg = tcd->nmajor; /* Current Major Iteration Count */
+ TCD_WRITE2(sc, DMA_TCDn_CITER_ELINKNO(chnum), reg);
+ TCD_WRITE2(sc, DMA_TCDn_BITER_ELINKNO(chnum), reg);
+
+ reg = (TCD_CSR_INTMAJOR);
+ if(tcd->majorelink == 1) {
+ reg |= TCD_CSR_MAJORELINK;
+ reg |= (tcd->majorelinkch << TCD_CSR_MAJORELINKCH_SHIFT);
+ }
+ TCD_WRITE2(sc, DMA_TCDn_CSR(chnum), reg);
+
+ /* Enable requests */
+ reg = READ4(sc, DMA_ERQ);
+ reg |= (0x1 << chnum);
+ WRITE4(sc, DMA_ERQ, reg);
+
+ /* Enable error interrupts */
+ reg = READ4(sc, DMA_EEI);
+ reg |= (0x1 << chnum);
+ WRITE4(sc, DMA_EEI, reg);
+
+ return (0);
+}
+
+static int
+dma_request(struct edma_softc *sc, int chnum)
+{
+ int reg;
+
+ /* Start */
+ reg = TCD_READ2(sc, DMA_TCDn_CSR(chnum));
+ reg |= TCD_CSR_START;
+ TCD_WRITE2(sc, DMA_TCDn_CSR(chnum), reg);
+
+ return (0);
+}
+
+static int
+edma_attach(device_t dev)
+{
+ struct edma_softc *sc;
+ phandle_t node;
+ int dts_value;
+ int len;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if ((node = ofw_bus_get_node(sc->dev)) == -1)
+ return (ENXIO);
+
+ if ((len = OF_getproplen(node, "device-id")) <= 0)
+ return (ENXIO);
+
+ OF_getprop(node, "device-id", &dts_value, len);
+ sc->device_id = fdt32_to_cpu(dts_value);
+
+ sc->dma_stop = dma_stop;
+ sc->dma_setup = dma_setup;
+ sc->dma_request = dma_request;
+ sc->channel_configure = channel_configure;
+ sc->channel_free = channel_free;
+
+ if (bus_alloc_resources(dev, edma_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+ sc->bst_tcd = rman_get_bustag(sc->res[1]);
+ sc->bsh_tcd = rman_get_bushandle(sc->res[1]);
+
+ /* Setup interrupt handlers */
+ if (bus_setup_intr(dev, sc->res[2], INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, edma_transfer_complete_intr, sc, &sc->tc_ih)) {
+ device_printf(dev, "Unable to alloc DMA intr resource.\n");
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->res[3], INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, edma_err_intr, sc, &sc->err_ih)) {
+ device_printf(dev, "Unable to alloc DMA Err intr resource.\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static device_method_t edma_methods[] = {
+ DEVMETHOD(device_probe, edma_probe),
+ DEVMETHOD(device_attach, edma_attach),
+ { 0, 0 }
+};
+
+static driver_t edma_driver = {
+ "edma",
+ edma_methods,
+ sizeof(struct edma_softc),
+};
+
+static devclass_t edma_devclass;
+
+DRIVER_MODULE(edma, simplebus, edma_driver, edma_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_edma.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_edma.h
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_edma.h (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_edma.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,187 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_edma.h 266170 2014-05-15 18:38:19Z ian $
+ */
+
+#define DMA_CR 0x000 /* Control */
+#define DMA_ES 0x004 /* Error Status */
+#define DMA_ERQ 0x00C /* Enable Request */
+#define DMA_EEI 0x014 /* Enable Error Interrupt */
+#define DMA_CEEI 0x018 /* Clear Enable Error Interrupt */
+#define DMA_SEEI 0x019 /* Set Enable Error Interrupt */
+#define DMA_CERQ 0x01A /* Clear Enable Request */
+#define DMA_SERQ 0x01B /* Set Enable Request */
+#define DMA_CDNE 0x01C /* Clear DONE Status Bit */
+#define DMA_SSRT 0x01D /* Set START Bit */
+#define DMA_CERR 0x01E /* Clear Error */
+#define CERR_CAEI (1 << 6) /* Clear All Error Indicators */
+#define DMA_CINT 0x01F /* Clear Interrupt Request */
+#define CINT_CAIR (1 << 6) /* Clear All Interrupt Requests */
+#define DMA_INT 0x024 /* Interrupt Request */
+#define DMA_ERR 0x02C /* Error */
+#define DMA_HRS 0x034 /* Hardware Request Status */
+#define DMA_EARS 0x044 /* Enable Asynchronous Request in Stop */
+#define DMA_DCHPRI3 0x100 /* Channel n Priority */
+#define DMA_DCHPRI2 0x101 /* Channel n Priority */
+#define DMA_DCHPRI1 0x102 /* Channel n Priority */
+#define DMA_DCHPRI0 0x103 /* Channel n Priority */
+#define DMA_DCHPRI7 0x104 /* Channel n Priority */
+#define DMA_DCHPRI6 0x105 /* Channel n Priority */
+#define DMA_DCHPRI5 0x106 /* Channel n Priority */
+#define DMA_DCHPRI4 0x107 /* Channel n Priority */
+#define DMA_DCHPRI11 0x108 /* Channel n Priority */
+#define DMA_DCHPRI10 0x109 /* Channel n Priority */
+#define DMA_DCHPRI9 0x10A /* Channel n Priority */
+#define DMA_DCHPRI8 0x10B /* Channel n Priority */
+#define DMA_DCHPRI15 0x10C /* Channel n Priority */
+#define DMA_DCHPRI14 0x10D /* Channel n Priority */
+#define DMA_DCHPRI13 0x10E /* Channel n Priority */
+#define DMA_DCHPRI12 0x10F /* Channel n Priority */
+#define DMA_DCHPRI19 0x110 /* Channel n Priority */
+#define DMA_DCHPRI18 0x111 /* Channel n Priority */
+#define DMA_DCHPRI17 0x112 /* Channel n Priority */
+#define DMA_DCHPRI16 0x113 /* Channel n Priority */
+#define DMA_DCHPRI23 0x114 /* Channel n Priority */
+#define DMA_DCHPRI22 0x115 /* Channel n Priority */
+#define DMA_DCHPRI21 0x116 /* Channel n Priority */
+#define DMA_DCHPRI20 0x117 /* Channel n Priority */
+#define DMA_DCHPRI27 0x118 /* Channel n Priority */
+#define DMA_DCHPRI26 0x119 /* Channel n Priority */
+#define DMA_DCHPRI25 0x11A /* Channel n Priority */
+#define DMA_DCHPRI24 0x11B /* Channel n Priority */
+#define DMA_DCHPRI31 0x11C /* Channel n Priority */
+#define DMA_DCHPRI30 0x11D /* Channel n Priority */
+#define DMA_DCHPRI29 0x11E /* Channel n Priority */
+#define DMA_DCHPRI28 0x11F /* Channel n Priority */
+
+#define DMA_TCDn_SADDR(n) (0x00 + 0x20 * n) /* Source Address */
+#define DMA_TCDn_SOFF(n) (0x04 + 0x20 * n) /* Signed Source Address Offset */
+#define DMA_TCDn_ATTR(n) (0x06 + 0x20 * n) /* Transfer Attributes */
+#define DMA_TCDn_NBYTES_MLNO(n) (0x08 + 0x20 * n) /* Minor Byte Count */
+#define DMA_TCDn_NBYTES_MLOFFNO(n) (0x08 + 0x20 * n) /* Signed Minor Loop Offset */
+#define DMA_TCDn_NBYTES_MLOFFYES(n) (0x08 + 0x20 * n) /* Signed Minor Loop Offset */
+#define DMA_TCDn_SLAST(n) (0x0C + 0x20 * n) /* Last Source Address Adjustment */
+#define DMA_TCDn_DADDR(n) (0x10 + 0x20 * n) /* Destination Address */
+#define DMA_TCDn_DOFF(n) (0x14 + 0x20 * n) /* Signed Destination Address Offset */
+#define DMA_TCDn_CITER_ELINKYES(n) (0x16 + 0x20 * n) /* Current Minor Loop Link, Major Loop Count */
+#define DMA_TCDn_CITER_ELINKNO(n) (0x16 + 0x20 * n)
+#define DMA_TCDn_DLASTSGA(n) (0x18 + 0x20 * n) /* Last Dst Addr Adjustment/Scatter Gather Address */
+#define DMA_TCDn_CSR(n) (0x1C + 0x20 * n) /* Control and Status */
+#define DMA_TCDn_BITER_ELINKYES(n) (0x1E + 0x20 * n) /* Beginning Minor Loop Link, Major Loop Count */
+#define DMA_TCDn_BITER_ELINKNO(n) (0x1E + 0x20 * n) /* Beginning Minor Loop Link, Major Loop Count */
+
+#define TCD_CSR_START (1 << 0)
+#define TCD_CSR_INTMAJOR (1 << 1)
+#define TCD_CSR_INTHALF (1 << 2)
+#define TCD_CSR_DREQ (1 << 3)
+#define TCD_CSR_ESG (1 << 4)
+#define TCD_CSR_MAJORELINK (1 << 5)
+#define TCD_CSR_ACTIVE (1 << 6)
+#define TCD_CSR_DONE (1 << 7)
+#define TCD_CSR_MAJORELINKCH_SHIFT 8
+
+#define TCD_ATTR_SMOD_SHIFT 11 /* Source Address Modulo */
+#define TCD_ATTR_SSIZE_SHIFT 8 /* Source Data Transfer Size */
+#define TCD_ATTR_DMOD_SHIFT 3 /* Dst Address Modulo */
+#define TCD_ATTR_DSIZE_SHIFT 0 /* Dst Data Transfer Size */
+
+#define TCD_READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst_tcd, _sc->bsh_tcd, _reg)
+#define TCD_WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst_tcd, _sc->bsh_tcd, _reg, _val)
+#define TCD_READ2(_sc, _reg) \
+ bus_space_read_2(_sc->bst_tcd, _sc->bsh_tcd, _reg)
+#define TCD_WRITE2(_sc, _reg, _val) \
+ bus_space_write_2(_sc->bst_tcd, _sc->bsh_tcd, _reg, _val)
+#define TCD_READ1(_sc, _reg) \
+ bus_space_read_1(_sc->bst_tcd, _sc->bsh_tcd, _reg)
+#define TCD_WRITE1(_sc, _reg, _val) \
+ bus_space_write_1(_sc->bst_tcd, _sc->bsh_tcd, _reg, _val)
+
+#define EDMA_NUM_DEVICES 2
+#define EDMA_NUM_CHANNELS 32
+#define NCHAN_PER_MUX 16
+
+struct tcd_conf {
+ bus_addr_t saddr;
+ bus_addr_t daddr;
+ uint32_t nbytes;
+ uint32_t nmajor;
+ uint32_t majorelink;
+ uint32_t majorelinkch;
+ uint32_t esg;
+ uint32_t smod;
+ uint32_t dmod;
+ uint32_t soff;
+ uint32_t doff;
+ uint32_t ssize;
+ uint32_t dsize;
+ uint32_t slast;
+ uint32_t dlast_sga;
+ uint32_t channel;
+ uint32_t (*ih)(void *, int);
+ void *ih_user;
+};
+
+/*
+ * TCD struct is described at
+ * Vybrid Reference Manual, Rev. 5, 07/2013
+ *
+ * Should be used for Scatter/Gathering feature.
+ */
+
+struct TCD {
+ uint32_t saddr;
+ uint16_t attr;
+ uint16_t soff;
+ uint32_t nbytes;
+ uint32_t slast;
+ uint32_t daddr;
+ uint16_t citer;
+ uint16_t doff;
+ uint32_t dlast_sga;
+ uint16_t biter;
+ uint16_t csr;
+} __packed;
+
+struct edma_softc {
+ device_t dev;
+ struct resource *res[4];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ bus_space_tag_t bst_tcd;
+ bus_space_handle_t bsh_tcd;
+ void *tc_ih;
+ void *err_ih;
+ uint32_t device_id;
+
+ int (*channel_configure) (struct edma_softc *, int, int);
+ int (*channel_free) (struct edma_softc *, int);
+ int (*dma_request) (struct edma_softc *, int);
+ int (*dma_setup) (struct edma_softc *, struct tcd_conf *);
+ int (*dma_stop) (struct edma_softc *, int);
+};
Property changes on: trunk/sys/arm/freescale/vybrid/vf_edma.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_ehci.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_ehci.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_ehci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,421 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Universal Serial Bus (USB) Controller
+ * Chapter 44-45, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_ehci.c 278278 2015-02-05 20:03:02Z hselasky $");
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/rman.h>
+#include <sys/gpio.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include "gpio_if.h"
+#include "opt_platform.h"
+
+#define ENUTMILEVEL3 (1 << 15)
+#define ENUTMILEVEL2 (1 << 14)
+
+#define GPIO_USB_PWR 134
+
+#define USB_ID 0x000 /* Identification register */
+#define USB_HWGENERAL 0x004 /* Hardware General */
+#define USB_HWHOST 0x008 /* Host Hardware Parameters */
+#define USB_HWDEVICE 0x00C /* Device Hardware Parameters */
+#define USB_HWTXBUF 0x010 /* TX Buffer Hardware Parameters */
+#define USB_HWRXBUF 0x014 /* RX Buffer Hardware Parameters */
+#define USB_HCSPARAMS 0x104 /* Host Controller Structural Parameters */
+
+#define USBPHY_PWD 0x00 /* PHY Power-Down Register */
+#define USBPHY_PWD_SET 0x04 /* PHY Power-Down Register */
+#define USBPHY_PWD_CLR 0x08 /* PHY Power-Down Register */
+#define USBPHY_PWD_TOG 0x0C /* PHY Power-Down Register */
+#define USBPHY_TX 0x10 /* PHY Transmitter Control Register */
+#define USBPHY_RX 0x20 /* PHY Receiver Control Register */
+#define USBPHY_RX_SET 0x24 /* PHY Receiver Control Register */
+#define USBPHY_RX_CLR 0x28 /* PHY Receiver Control Register */
+#define USBPHY_RX_TOG 0x2C /* PHY Receiver Control Register */
+#define USBPHY_CTRL 0x30 /* PHY General Control Register */
+#define USBPHY_CTRL_SET 0x34 /* PHY General Control Register */
+#define USBPHY_CTRL_CLR 0x38 /* PHY General Control Register */
+#define USBPHY_CTRL_TOG 0x3C /* PHY General Control Register */
+#define USBPHY_STATUS 0x40 /* PHY Status Register */
+#define USBPHY_DEBUG 0x50 /* PHY Debug Register */
+#define USBPHY_DEBUG_SET 0x54 /* PHY Debug Register */
+#define USBPHY_DEBUG_CLR 0x58 /* PHY Debug Register */
+#define USBPHY_DEBUG_TOG 0x5C /* PHY Debug Register */
+#define USBPHY_DEBUG0_STATUS 0x60 /* UTMI Debug Status Register 0 */
+#define USBPHY_DEBUG1 0x70 /* UTMI Debug Status Register 1 */
+#define USBPHY_DEBUG1_SET 0x74 /* UTMI Debug Status Register 1 */
+#define USBPHY_DEBUG1_CLR 0x78 /* UTMI Debug Status Register 1 */
+#define USBPHY_DEBUG1_TOG 0x7C /* UTMI Debug Status Register 1 */
+#define USBPHY_VERSION 0x80 /* UTMI RTL Version */
+#define USBPHY_IP 0x90 /* PHY IP Block Register */
+#define USBPHY_IP_SET 0x94 /* PHY IP Block Register */
+#define USBPHY_IP_CLR 0x98 /* PHY IP Block Register */
+#define USBPHY_IP_TOG 0x9C /* PHY IP Block Register */
+
+#define USBPHY_CTRL_SFTRST (1 << 31)
+#define USBPHY_CTRL_CLKGATE (1 << 30)
+#define USBPHY_DEBUG_CLKGATE (1 << 30)
+
+#define PHY_READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst_phy, _sc->bsh_phy, _reg)
+#define PHY_WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst_phy, _sc->bsh_phy, _reg, _val)
+
+#define USBC_READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst_usbc, _sc->bsh_usbc, _reg)
+#define USBC_WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst_usbc, _sc->bsh_usbc, _reg, _val)
+
+/* Forward declarations */
+static int vybrid_ehci_attach(device_t dev);
+static int vybrid_ehci_detach(device_t dev);
+static int vybrid_ehci_probe(device_t dev);
+
+struct vybrid_ehci_softc {
+ ehci_softc_t base;
+ device_t dev;
+ struct resource *res[6];
+ bus_space_tag_t bst_phy;
+ bus_space_handle_t bsh_phy;
+ bus_space_tag_t bst_usbc;
+ bus_space_handle_t bsh_usbc;
+};
+
+static struct resource_spec vybrid_ehci_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, vybrid_ehci_probe),
+ DEVMETHOD(device_attach, vybrid_ehci_attach),
+ DEVMETHOD(device_detach, vybrid_ehci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+ { 0, 0 }
+};
+
+/* kobj_class definition */
+static driver_t ehci_driver = {
+ "ehci",
+ ehci_methods,
+ sizeof(ehci_softc_t)
+};
+
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
+MODULE_DEPEND(ehci, usb, 1, 1, 1);
+
+/*
+ * Public methods
+ */
+static int
+vybrid_ehci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "fsl,mvf600-usb-ehci") == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family integrated USB controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+phy_init(struct vybrid_ehci_softc *esc)
+{
+ device_t sc_gpio_dev;
+ int reg;
+
+ /* Reset phy */
+ reg = PHY_READ4(esc, USBPHY_CTRL);
+ reg |= (USBPHY_CTRL_SFTRST);
+ PHY_WRITE4(esc, USBPHY_CTRL, reg);
+
+ /* Minimum reset time */
+ DELAY(10000);
+
+ reg &= ~(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE);
+ PHY_WRITE4(esc, USBPHY_CTRL, reg);
+
+ reg = (ENUTMILEVEL2 | ENUTMILEVEL3);
+ PHY_WRITE4(esc, USBPHY_CTRL_SET, reg);
+
+ /* Get the GPIO device, we need this to give power to USB */
+ sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (sc_gpio_dev == NULL) {
+ device_printf(esc->dev, "Error: failed to get the GPIO dev\n");
+ return (1);
+ }
+
+ /* Give power to USB */
+ GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB_PWR, GPIO_PIN_OUTPUT);
+ GPIO_PIN_SET(sc_gpio_dev, GPIO_USB_PWR, GPIO_PIN_HIGH);
+
+ /* Power up PHY */
+ PHY_WRITE4(esc, USBPHY_PWD, 0x00);
+
+ /* Ungate clocks */
+ reg = PHY_READ4(esc, USBPHY_DEBUG);
+ reg &= ~(USBPHY_DEBUG_CLKGATE);
+ PHY_WRITE4(esc, USBPHY_DEBUG, reg);
+
+#if 0
+ printf("USBPHY_CTRL == 0x%08x\n",
+ PHY_READ4(esc, USBPHY_CTRL));
+ printf("USBPHY_IP == 0x%08x\n",
+ PHY_READ4(esc, USBPHY_IP));
+ printf("USBPHY_STATUS == 0x%08x\n",
+ PHY_READ4(esc, USBPHY_STATUS));
+ printf("USBPHY_DEBUG == 0x%08x\n",
+ PHY_READ4(esc, USBPHY_DEBUG));
+ printf("USBPHY_DEBUG0_STATUS == 0x%08x\n",
+ PHY_READ4(esc, USBPHY_DEBUG0_STATUS));
+ printf("USBPHY_DEBUG1 == 0x%08x\n",
+ PHY_READ4(esc, USBPHY_DEBUG1));
+#endif
+
+ return (0);
+}
+
+static int
+vybrid_ehci_attach(device_t dev)
+{
+ struct vybrid_ehci_softc *esc;
+ ehci_softc_t *sc;
+ bus_space_handle_t bsh;
+ int err;
+ int reg;
+
+ esc = device_get_softc(dev);
+ esc->dev = dev;
+
+ sc = &esc->base;
+ sc->sc_bus.parent = dev;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
+
+ if (bus_alloc_resources(dev, vybrid_ehci_spec, esc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* EHCI registers */
+ sc->sc_io_tag = rman_get_bustag(esc->res[0]);
+ bsh = rman_get_bushandle(esc->res[0]);
+ sc->sc_io_size = rman_get_size(esc->res[0]);
+
+ esc->bst_usbc = rman_get_bustag(esc->res[1]);
+ esc->bsh_usbc = rman_get_bushandle(esc->res[1]);
+
+ esc->bst_phy = rman_get_bustag(esc->res[2]);
+ esc->bsh_phy = rman_get_bushandle(esc->res[2]);
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev),
+ &ehci_iterate_hw_softc))
+ return (ENXIO);
+
+#if 0
+ printf("USBx_HCSPARAMS is 0x%08x\n",
+ bus_space_read_4(sc->sc_io_tag, bsh, USB_HCSPARAMS));
+ printf("USB_ID == 0x%08x\n",
+ bus_space_read_4(sc->sc_io_tag, bsh, USB_ID));
+ printf("USB_HWGENERAL == 0x%08x\n",
+ bus_space_read_4(sc->sc_io_tag, bsh, USB_HWGENERAL));
+ printf("USB_HWHOST == 0x%08x\n",
+ bus_space_read_4(sc->sc_io_tag, bsh, USB_HWHOST));
+ printf("USB_HWDEVICE == 0x%08x\n",
+ bus_space_read_4(sc->sc_io_tag, bsh, USB_HWDEVICE));
+ printf("USB_HWTXBUF == 0x%08x\n",
+ bus_space_read_4(sc->sc_io_tag, bsh, USB_HWTXBUF));
+ printf("USB_HWRXBUF == 0x%08x\n",
+ bus_space_read_4(sc->sc_io_tag, bsh, USB_HWRXBUF));
+#endif
+
+ if (phy_init(esc)) {
+ device_printf(dev, "Could not setup PHY\n");
+ return (1);
+ }
+
+ /*
+ * Set handle to USB related registers subregion used by
+ * generic EHCI driver.
+ */
+ err = bus_space_subregion(sc->sc_io_tag, bsh, 0x100,
+ sc->sc_io_size, &sc->sc_io_hdl);
+ if (err != 0)
+ return (ENXIO);
+
+ /* Setup interrupt handler */
+ err = bus_setup_intr(dev, esc->res[3], INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)ehci_interrupt, sc,
+ &sc->sc_intr_hdl);
+ if (err) {
+ device_printf(dev, "Could not setup irq, "
+ "%d\n", err);
+ return (1);
+ }
+
+ /* Add USB device */
+ sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(dev, "Could not add USB device\n");
+ err = bus_teardown_intr(dev, esc->res[5],
+ sc->sc_intr_hdl);
+ if (err)
+ device_printf(dev, "Could not tear down irq,"
+ " %d\n", err);
+ return (1);
+ }
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+
+ strlcpy(sc->sc_vendor, "Freescale", sizeof(sc->sc_vendor));
+
+ /* Set host mode */
+ reg = bus_space_read_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8);
+ reg |= 0x3;
+ bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8, reg);
+
+ /* Set flags */
+ sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_NORESTERM;
+
+ err = ehci_init(sc);
+ if (!err) {
+ sc->sc_flags |= EHCI_SCFLG_DONEINIT;
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ } else {
+ device_printf(dev, "USB init failed err=%d\n", err);
+
+ device_delete_child(dev, sc->sc_bus.bdev);
+ sc->sc_bus.bdev = NULL;
+
+ err = bus_teardown_intr(dev, esc->res[5],
+ sc->sc_intr_hdl);
+ if (err)
+ device_printf(dev, "Could not tear down irq,"
+ " %d\n", err);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+vybrid_ehci_detach(device_t dev)
+{
+ struct vybrid_ehci_softc *esc;
+ ehci_softc_t *sc;
+ int err;
+
+ esc = device_get_softc(dev);
+ sc = &esc->base;
+
+ if (sc->sc_flags & EHCI_SCFLG_DONEINIT)
+ return (0);
+
+ /*
+ * only call ehci_detach() after ehci_init()
+ */
+ if (sc->sc_flags & EHCI_SCFLG_DONEINIT) {
+ ehci_detach(sc);
+ sc->sc_flags &= ~EHCI_SCFLG_DONEINIT;
+ }
+
+ /*
+ * Disable interrupts that might have been switched on in
+ * ehci_init.
+ */
+ if (sc->sc_io_tag && sc->sc_io_hdl)
+ bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl,
+ EHCI_USBINTR, 0);
+
+ if (esc->res[5] && sc->sc_intr_hdl) {
+ err = bus_teardown_intr(dev, esc->res[5],
+ sc->sc_intr_hdl);
+ if (err) {
+ device_printf(dev, "Could not tear down irq,"
+ " %d\n", err);
+ return (err);
+ }
+ sc->sc_intr_hdl = NULL;
+ }
+
+ if (sc->sc_bus.bdev) {
+ device_delete_child(dev, sc->sc_bus.bdev);
+ sc->sc_bus.bdev = NULL;
+ }
+
+ /* During module unload there are lots of children leftover */
+ device_delete_children(dev);
+
+ bus_release_resources(dev, vybrid_ehci_spec, esc->res);
+
+ return (0);
+}
Property changes on: trunk/sys/arm/freescale/vybrid/vf_ehci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_gpio.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_gpio.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,370 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family General-Purpose Input/Output (GPIO)
+ * Chapter 7, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_gpio.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include "gpio_if.h"
+
+#include <arm/freescale/vybrid/vf_common.h>
+#include <arm/freescale/vybrid/vf_port.h>
+
+#define GPIO_PDOR(n) (0x00 + 0x40 * (n >> 5))
+#define GPIO_PSOR(n) (0x04 + 0x40 * (n >> 5))
+#define GPIO_PCOR(n) (0x08 + 0x40 * (n >> 5))
+#define GPIO_PTOR(n) (0x0C + 0x40 * (n >> 5))
+#define GPIO_PDIR(n) (0x10 + 0x40 * (n >> 5))
+
+#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+
+#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
+
+/*
+ * GPIO interface
+ */
+static int vf_gpio_pin_max(device_t, int *);
+static int vf_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
+static int vf_gpio_pin_getname(device_t, uint32_t, char *);
+static int vf_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
+static int vf_gpio_pin_setflags(device_t, uint32_t, uint32_t);
+static int vf_gpio_pin_set(device_t, uint32_t, unsigned int);
+static int vf_gpio_pin_get(device_t, uint32_t, unsigned int *);
+static int vf_gpio_pin_toggle(device_t, uint32_t pin);
+
+struct vf_gpio_softc {
+ struct resource *res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+
+ struct mtx sc_mtx;
+ int gpio_npins;
+ struct gpio_pin gpio_pins[NGPIO];
+};
+
+struct vf_gpio_softc *gpio_sc;
+
+static struct resource_spec vf_gpio_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+vf_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-gpio"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family GPIO Unit");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+vf_gpio_attach(device_t dev)
+{
+ struct vf_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ if (bus_alloc_resources(dev, vf_gpio_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ gpio_sc = sc;
+
+ sc->gpio_npins = NGPIO;
+
+ for (i = 0; i < sc->gpio_npins; i++) {
+ sc->gpio_pins[i].gp_pin = i;
+ sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
+ sc->gpio_pins[i].gp_flags =
+ (READ4(sc, GPIO_PDOR(i)) & (1 << (i % 32))) ?
+ GPIO_PIN_OUTPUT: GPIO_PIN_INPUT;
+ snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
+ "vf_gpio%d.%d", device_get_unit(dev), i);
+ }
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+vf_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = NGPIO - 1;
+ return (0);
+}
+
+static int
+vf_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct vf_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+vf_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct vf_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *caps = sc->gpio_pins[i].gp_caps;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+vf_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct vf_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *flags = sc->gpio_pins[i].gp_flags;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+vf_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct vf_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *val = (READ4(sc, GPIO_PDOR(i)) & (1 << (i % 32)));
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+vf_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct vf_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ WRITE4(sc, GPIO_PTOR(i), (1 << (i % 32)));
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+
+static void
+vf_gpio_pin_configure(struct vf_gpio_softc *sc, struct gpio_pin *pin,
+ unsigned int flags)
+{
+
+ GPIO_LOCK(sc);
+
+ /*
+ * Manage input/output
+ */
+ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
+ pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
+ if (flags & GPIO_PIN_OUTPUT) {
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+
+ } else {
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ WRITE4(sc, GPIO_PCOR(pin->gp_pin),
+ (1 << (pin->gp_pin % 32)));
+ }
+ }
+
+ GPIO_UNLOCK(sc);
+}
+
+
+static int
+vf_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct vf_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ vf_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
+
+ return (0);
+}
+
+static int
+vf_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct vf_gpio_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ if (value)
+ WRITE4(sc, GPIO_PSOR(i), (1 << (i % 32)));
+ else
+ WRITE4(sc, GPIO_PCOR(i), (1 << (i % 32)));
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static device_method_t vf_gpio_methods[] = {
+ DEVMETHOD(device_probe, vf_gpio_probe),
+ DEVMETHOD(device_attach, vf_gpio_attach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, vf_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, vf_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getcaps, vf_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_getflags, vf_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_get, vf_gpio_pin_get),
+ DEVMETHOD(gpio_pin_toggle, vf_gpio_pin_toggle),
+ DEVMETHOD(gpio_pin_setflags, vf_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_set, vf_gpio_pin_set),
+ { 0, 0 }
+};
+
+static driver_t vf_gpio_driver = {
+ "gpio",
+ vf_gpio_methods,
+ sizeof(struct vf_gpio_softc),
+};
+
+static devclass_t vf_gpio_devclass;
+
+DRIVER_MODULE(vf_gpio, simplebus, vf_gpio_driver, vf_gpio_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_i2c.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_i2c.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_i2c.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,472 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Inter-Integrated Circuit (I2C)
+ * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+/*
+ * This driver is based on the I2C driver for i.MX
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_i2c.c 289666 2015-10-20 21:20:34Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include "iicbus_if.h"
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_common.h>
+
+#define I2C_IBAD 0x0 /* I2C Bus Address Register */
+#define I2C_IBFD 0x1 /* I2C Bus Frequency Divider Register */
+#define I2C_IBCR 0x2 /* I2C Bus Control Register */
+#define IBCR_MDIS (1 << 7) /* Module disable. */
+#define IBCR_IBIE (1 << 6) /* I-Bus Interrupt Enable. */
+#define IBCR_MSSL (1 << 5) /* Master/Slave mode select. */
+#define IBCR_TXRX (1 << 4) /* Transmit/Receive mode select. */
+#define IBCR_NOACK (1 << 3) /* Data Acknowledge disable. */
+#define IBCR_RSTA (1 << 2) /* Repeat Start. */
+#define IBCR_DMAEN (1 << 1) /* DMA Enable. */
+#define I2C_IBSR 0x3 /* I2C Bus Status Register */
+#define IBSR_TCF (1 << 7) /* Transfer complete. */
+#define IBSR_IAAS (1 << 6) /* Addressed as a slave. */
+#define IBSR_IBB (1 << 5) /* Bus busy. */
+#define IBSR_IBAL (1 << 4) /* Arbitration Lost. */
+#define IBSR_SRW (1 << 2) /* Slave Read/Write. */
+#define IBSR_IBIF (1 << 1) /* I-Bus Interrupt Flag. */
+#define IBSR_RXAK (1 << 0) /* Received Acknowledge. */
+#define I2C_IBDR 0x4 /* I2C Bus Data I/O Register */
+#define I2C_IBIC 0x5 /* I2C Bus Interrupt Config Register */
+#define IBIC_BIIE (1 << 7) /* Bus Idle Interrupt Enable bit. */
+#define I2C_IBDBG 0x6 /* I2C Bus Debug Register */
+
+#ifdef DEBUG
+#define vf_i2c_dbg(_sc, fmt, args...) \
+ device_printf((_sc)->dev, fmt, ##args)
+#else
+#define vf_i2c_dbg(_sc, fmt, args...)
+#endif
+
+static int i2c_repeated_start(device_t, u_char, int);
+static int i2c_start(device_t, u_char, int);
+static int i2c_stop(device_t);
+static int i2c_reset(device_t, u_char, u_char, u_char *);
+static int i2c_read(device_t, char *, int, int *, int, int);
+static int i2c_write(device_t, const char *, int, int *, int);
+
+struct i2c_softc {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ device_t iicbus;
+ struct mtx mutex;
+};
+
+static struct resource_spec i2c_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+i2c_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-i2c"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family Inter-Integrated Circuit (I2C)");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+i2c_attach(device_t dev)
+{
+ struct i2c_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF);
+
+ if (bus_alloc_resources(dev, i2c_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ WRITE1(sc, I2C_IBIC, IBIC_BIIE);
+
+ sc->iicbus = device_add_child(dev, "iicbus", -1);
+ if (sc->iicbus == NULL) {
+ device_printf(dev, "could not add iicbus child");
+ mtx_destroy(&sc->mutex);
+ return (ENXIO);
+ }
+
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+/* Wait for transfer interrupt flag */
+static int
+wait_for_iif(struct i2c_softc *sc)
+{
+ int retry;
+
+ retry = 1000;
+ while (retry --) {
+ if (READ1(sc, I2C_IBSR) & IBSR_IBIF) {
+ WRITE1(sc, I2C_IBSR, IBSR_IBIF);
+ return (IIC_NOERR);
+ }
+ DELAY(10);
+ }
+
+ return (IIC_ETIMEOUT);
+}
+
+/* Wait for free bus */
+static int
+wait_for_nibb(struct i2c_softc *sc)
+{
+ int retry;
+
+ retry = 1000;
+ while (retry --) {
+ if ((READ1(sc, I2C_IBSR) & IBSR_IBB) == 0)
+ return (IIC_NOERR);
+ DELAY(10);
+ }
+
+ return (IIC_ETIMEOUT);
+}
+
+/* Wait for transfer complete+interrupt flag */
+static int
+wait_for_icf(struct i2c_softc *sc)
+{
+ int retry;
+
+ retry = 1000;
+ while (retry --) {
+ if (READ1(sc, I2C_IBSR) & IBSR_TCF) {
+ if (READ1(sc, I2C_IBSR) & IBSR_IBIF) {
+ WRITE1(sc, I2C_IBSR, IBSR_IBIF);
+ return (IIC_NOERR);
+ }
+ }
+ DELAY(10);
+ }
+
+ return (IIC_ETIMEOUT);
+}
+
+static int
+i2c_repeated_start(device_t dev, u_char slave, int timeout)
+{
+ struct i2c_softc *sc;
+ int error;
+ int reg;
+
+ sc = device_get_softc(dev);
+
+ vf_i2c_dbg(sc, "i2c repeated start\n");
+
+ mtx_lock(&sc->mutex);
+
+ WRITE1(sc, I2C_IBAD, slave);
+
+ if ((READ1(sc, I2C_IBSR) & IBSR_IBB) == 0) {
+ mtx_unlock(&sc->mutex);
+ return (IIC_EBUSERR);
+ }
+
+ /* Set repeated start condition */
+ DELAY(10);
+
+ reg = READ1(sc, I2C_IBCR);
+ reg |= (IBCR_RSTA | IBCR_IBIE);
+ WRITE1(sc, I2C_IBCR, reg);
+
+ DELAY(10);
+
+ /* Write target address - LSB is R/W bit */
+ WRITE1(sc, I2C_IBDR, slave);
+
+ error = wait_for_iif(sc);
+
+ mtx_unlock(&sc->mutex);
+
+ if (error)
+ return (error);
+
+ return (IIC_NOERR);
+}
+
+static int
+i2c_start(device_t dev, u_char slave, int timeout)
+{
+ struct i2c_softc *sc;
+ int error;
+ int reg;
+
+ sc = device_get_softc(dev);
+
+ vf_i2c_dbg(sc, "i2c start\n");
+
+ mtx_lock(&sc->mutex);
+
+ WRITE1(sc, I2C_IBAD, slave);
+
+ if (READ1(sc, I2C_IBSR) & IBSR_IBB) {
+ mtx_unlock(&sc->mutex);
+ vf_i2c_dbg(sc, "cant i2c start: IIC_EBUSBSY\n");
+ return (IIC_EBUSERR);
+ }
+
+ /* Set start condition */
+ reg = (IBCR_MSSL | IBCR_NOACK | IBCR_IBIE);
+ WRITE1(sc, I2C_IBCR, reg);
+
+ DELAY(100);
+
+ reg |= (IBCR_TXRX);
+ WRITE1(sc, I2C_IBCR, reg);
+
+ /* Write target address - LSB is R/W bit */
+ WRITE1(sc, I2C_IBDR, slave);
+
+ error = wait_for_iif(sc);
+
+ mtx_unlock(&sc->mutex);
+ if (error) {
+ vf_i2c_dbg(sc, "cant i2c start: iif error\n");
+ return (error);
+ }
+
+ return (IIC_NOERR);
+}
+
+static int
+i2c_stop(device_t dev)
+{
+ struct i2c_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ vf_i2c_dbg(sc, "i2c stop\n");
+
+ mtx_lock(&sc->mutex);
+
+ WRITE1(sc, I2C_IBCR, IBCR_NOACK | IBCR_IBIE);
+
+ DELAY(100);
+
+ /* Reset controller if bus still busy after STOP */
+ if (wait_for_nibb(sc) == IIC_ETIMEOUT) {
+ WRITE1(sc, I2C_IBCR, IBCR_MDIS);
+ DELAY(1000);
+ WRITE1(sc, I2C_IBCR, IBCR_NOACK);
+ }
+ mtx_unlock(&sc->mutex);
+
+ return (IIC_NOERR);
+}
+
+static int
+i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
+{
+ struct i2c_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ vf_i2c_dbg(sc, "i2c reset\n");
+
+ switch (speed) {
+ case IIC_FAST:
+ case IIC_SLOW:
+ case IIC_UNKNOWN:
+ case IIC_FASTEST:
+ default:
+ break;
+ }
+
+ mtx_lock(&sc->mutex);
+ WRITE1(sc, I2C_IBCR, IBCR_MDIS);
+
+ DELAY(1000);
+
+ WRITE1(sc, I2C_IBFD, 20);
+ WRITE1(sc, I2C_IBCR, 0x0); /* Enable i2c */
+
+ DELAY(1000);
+
+ mtx_unlock(&sc->mutex);
+
+ return (IIC_NOERR);
+}
+
+static int
+i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay)
+{
+ struct i2c_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ vf_i2c_dbg(sc, "i2c read\n");
+
+ *read = 0;
+
+ mtx_lock(&sc->mutex);
+
+ if (len) {
+ if (len == 1)
+ WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | \
+ IBCR_NOACK);
+ else
+ WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL);
+
+ /* dummy read */
+ READ1(sc, I2C_IBDR);
+ DELAY(1000);
+ }
+
+ while (*read < len) {
+ error = wait_for_icf(sc);
+ if (error) {
+ mtx_unlock(&sc->mutex);
+ return (error);
+ }
+
+ if ((*read == len - 2) && last) {
+ /* NO ACK on last byte */
+ WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | \
+ IBCR_NOACK);
+ }
+
+ if ((*read == len - 1) && last) {
+ /* Transfer done, remove master bit */
+ WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_NOACK);
+ }
+
+ *buf++ = READ1(sc, I2C_IBDR);
+ (*read)++;
+ }
+ mtx_unlock(&sc->mutex);
+
+ return (IIC_NOERR);
+}
+
+static int
+i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout)
+{
+ struct i2c_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ vf_i2c_dbg(sc, "i2c write\n");
+
+ *sent = 0;
+
+ mtx_lock(&sc->mutex);
+ while (*sent < len) {
+
+ WRITE1(sc, I2C_IBDR, *buf++);
+
+ error = wait_for_iif(sc);
+ if (error) {
+ mtx_unlock(&sc->mutex);
+ return (error);
+ }
+
+ (*sent)++;
+ }
+ mtx_unlock(&sc->mutex);
+
+ return (IIC_NOERR);
+}
+
+static device_method_t i2c_methods[] = {
+ DEVMETHOD(device_probe, i2c_probe),
+ DEVMETHOD(device_attach, i2c_attach),
+
+ DEVMETHOD(iicbus_callback, iicbus_null_callback),
+ DEVMETHOD(iicbus_repeated_start, i2c_repeated_start),
+ DEVMETHOD(iicbus_start, i2c_start),
+ DEVMETHOD(iicbus_stop, i2c_stop),
+ DEVMETHOD(iicbus_reset, i2c_reset),
+ DEVMETHOD(iicbus_read, i2c_read),
+ DEVMETHOD(iicbus_write, i2c_write),
+ DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
+
+ { 0, 0 }
+};
+
+static driver_t i2c_driver = {
+ "i2c",
+ i2c_methods,
+ sizeof(struct i2c_softc),
+};
+
+static devclass_t i2c_devclass;
+
+DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0);
+DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_i2c.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_iomuxc.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_iomuxc.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_iomuxc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,213 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Input/Output Multiplexer Controller (IOMUXC)
+ * Chapter 5, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_iomuxc.c 266203 2014-05-16 00:14:50Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_iomuxc.h>
+#include <arm/freescale/vybrid/vf_common.h>
+
+#define MUX_MODE_MASK 7
+#define MUX_MODE_SHIFT 20
+#define MUX_MODE_GPIO 0
+#define MUX_MODE_VBUS_EN_OTG 2
+
+#define IBE (1 << 0) /* Input Buffer Enable Field */
+#define OBE (1 << 1) /* Output Buffer Enable Field. */
+#define PUE (1 << 2) /* Pull / Keep Select Field. */
+#define PKE (1 << 3) /* Pull / Keep Enable Field. */
+#define HYS (1 << 9) /* Hysteresis Enable Field */
+#define ODE (1 << 10) /* Open Drain Enable Field. */
+#define SRE (1 << 11) /* Slew Rate Field. */
+
+#define SPEED_SHIFT 12
+#define SPEED_MASK 0x3
+#define SPEED_LOW 0 /* 50 MHz */
+#define SPEED_MEDIUM 0x1 /* 100 MHz */
+#define SPEED_HIGH 0x3 /* 200 MHz */
+
+#define PUS_SHIFT 4 /* Pull Up / Down Config Field Shift */
+#define PUS_MASK 0x3
+#define PUS_100_KOHM_PULL_DOWN 0
+#define PUS_47_KOHM_PULL_UP 0x1
+#define PUS_100_KOHM_PULL_UP 0x2
+#define PUS_22_KOHM_PULL_UP 0x3
+
+#define DSE_SHIFT 6 /* Drive Strength Field Shift */
+#define DSE_MASK 0x7
+#define DSE_DISABLED 0 /* Output driver disabled */
+#define DSE_150_OHM 0x1
+#define DSE_75_OHM 0x2
+#define DSE_50_OHM 0x3
+#define DSE_37_OHM 0x4
+#define DSE_30_OHM 0x5
+#define DSE_25_OHM 0x6
+#define DSE_20_OHM 0x7
+
+#define MAX_MUX_LEN 1024
+
+struct iomuxc_softc {
+ struct resource *tmr_res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+};
+
+static struct resource_spec iomuxc_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+iomuxc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-iomuxc"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family IOMUXC Unit");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+pinmux_set(struct iomuxc_softc *sc)
+{
+ phandle_t child, parent, root;
+ pcell_t iomux_config[MAX_MUX_LEN];
+ int len;
+ int values;
+ int pin;
+ int pin_cfg;
+ int i;
+
+ root = OF_finddevice("/");
+ len = 0;
+ parent = root;
+
+ /* Find 'iomux_config' prop in the nodes */
+ for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
+
+ /* Find a 'leaf'. Start the search from this node. */
+ while (OF_child(child)) {
+ parent = child;
+ child = OF_child(child);
+ }
+
+ if (!fdt_is_enabled(child))
+ continue;
+
+ if ((len = OF_getproplen(child, "iomux_config")) > 0) {
+ OF_getprop(child, "iomux_config", &iomux_config, len);
+
+ values = len / (sizeof(uint32_t));
+ for (i = 0; i < values; i += 2) {
+ pin = fdt32_to_cpu(iomux_config[i]);
+ pin_cfg = fdt32_to_cpu(iomux_config[i+1]);
+#if 0
+ device_printf(sc->dev, "Set pin %d to 0x%08x\n",
+ pin, pin_cfg);
+#endif
+ WRITE4(sc, IOMUXC(pin), pin_cfg);
+ }
+ }
+
+ if (OF_peer(child) == 0) {
+ /* No more siblings. */
+ child = parent;
+ parent = OF_parent(child);
+ }
+ }
+
+ return (0);
+}
+
+static int
+iomuxc_attach(device_t dev)
+{
+ struct iomuxc_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, iomuxc_spec, sc->tmr_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->tmr_res[0]);
+ sc->bsh = rman_get_bushandle(sc->tmr_res[0]);
+
+ pinmux_set(sc);
+
+ return (0);
+}
+
+static device_method_t iomuxc_methods[] = {
+ DEVMETHOD(device_probe, iomuxc_probe),
+ DEVMETHOD(device_attach, iomuxc_attach),
+ { 0, 0 }
+};
+
+static driver_t iomuxc_driver = {
+ "iomuxc",
+ iomuxc_methods,
+ sizeof(struct iomuxc_softc),
+};
+
+static devclass_t iomuxc_devclass;
+
+DRIVER_MODULE(iomuxc, simplebus, iomuxc_driver, iomuxc_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_iomuxc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_iomuxc.h
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_iomuxc.h (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_iomuxc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,166 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_iomuxc.h 258057 2013-11-12 18:02:56Z br $
+ */
+
+#define IOMUXC(n) (n * 0x04)
+#define IOMUXCN 135
+#define IOMUXC_PTA6 0x000 /* Software MUX Pad Control Register 0 */
+#define IOMUXC_PTA8 0x004 /* Software MUX Pad Control Register 1 */
+#define IOMUXC_PTA9 0x008 /* Software MUX Pad Control Register 2 */
+#define IOMUXC_PTA10 0x00C /* Software MUX Pad Control Register 3 */
+#define IOMUXC_PTA11 0x010 /* Software MUX Pad Control Register 4 */
+#define IOMUXC_PTA12 0x014 /* Software MUX Pad Control Register 5 */
+#define IOMUXC_PTA16 0x018 /* Software MUX Pad Control Register 6 */
+#define IOMUXC_PTA17 0x01C /* Software MUX Pad Control Register 7 */
+#define IOMUXC_PTA18 0x020 /* Software MUX Pad Control Register 8 */
+#define IOMUXC_PTA19 0x024 /* Software MUX Pad Control Register 9 */
+#define IOMUXC_PTA20 0x028 /* Software MUX Pad Control Register 10 */
+#define IOMUXC_PTA21 0x02C /* Software MUX Pad Control Register 11 */
+#define IOMUXC_PTA22 0x030 /* Software MUX Pad Control Register 12 */
+#define IOMUXC_PTA23 0x034 /* Software MUX Pad Control Register 13 */
+#define IOMUXC_PTA24 0x038 /* Software MUX Pad Control Register 14 */
+#define IOMUXC_PTA25 0x03C /* Software MUX Pad Control Register 15 */
+#define IOMUXC_PTA26 0x040 /* Software MUX Pad Control Register 16 */
+#define IOMUXC_PTA27 0x044 /* Software MUX Pad Control Register 17 */
+#define IOMUXC_PTA28 0x048 /* Software MUX Pad Control Register 18 */
+#define IOMUXC_PTA29 0x04C /* Software MUX Pad Control Register 19 */
+#define IOMUXC_PTA30 0x050 /* Software MUX Pad Control Register 20 */
+#define IOMUXC_PTA31 0x054 /* Software MUX Pad Control Register 21 */
+#define IOMUXC_PTB0 0x058 /* Software MUX Pad Control Register 22 */
+#define IOMUXC_PTB1 0x05C /* Software MUX Pad Control Register 23 */
+#define IOMUXC_PTB2 0x060 /* Software MUX Pad Control Register 24 */
+#define IOMUXC_PTB3 0x064 /* Software MUX Pad Control Register 25 */
+#define IOMUXC_PTB4 0x068 /* Software MUX Pad Control Register 26 */
+#define IOMUXC_PTB5 0x06C /* Software MUX Pad Control Register 27 */
+#define IOMUXC_PTB6 0x070 /* Software MUX Pad Control Register 28 */
+#define IOMUXC_PTB7 0x074 /* Software MUX Pad Control Register 29 */
+#define IOMUXC_PTB8 0x078 /* Software MUX Pad Control Register 30 */
+#define IOMUXC_PTB9 0x07C /* Software MUX Pad Control Register 31 */
+#define IOMUXC_PTB10 0x080 /* Software MUX Pad Control Register 32 */
+#define IOMUXC_PTB11 0x084 /* Software MUX Pad Control Register 33 */
+#define IOMUXC_PTB12 0x088 /* Software MUX Pad Control Register 34 */
+#define IOMUXC_PTB13 0x08C /* Software MUX Pad Control Register 35 */
+#define IOMUXC_PTB14 0x090 /* Software MUX Pad Control Register 36 */
+#define IOMUXC_PTB15 0x094 /* Software MUX Pad Control Register 37 */
+#define IOMUXC_PTB16 0x098 /* Software MUX Pad Control Register 38 */
+#define IOMUXC_PTB17 0x09C /* Software MUX Pad Control Register 39 */
+#define IOMUXC_PTB18 0x0A0 /* Software MUX Pad Control Register 40 */
+#define IOMUXC_PTB19 0x0A4 /* Software MUX Pad Control Register 41 */
+#define IOMUXC_PTB20 0x0A8 /* Software MUX Pad Control Register 42 */
+#define IOMUXC_PTB21 0x0AC /* Software MUX Pad Control Register 43 */
+#define IOMUXC_PTB22 0x0B0 /* Software MUX Pad Control Register 44 */
+#define IOMUXC_PTC0 0x0B4 /* Software MUX Pad Control Register 45 */
+#define IOMUXC_PTC1 0x0B8 /* Software MUX Pad Control Register 46 */
+#define IOMUXC_PTC2 0x0BC /* Software MUX Pad Control Register 47 */
+#define IOMUXC_PTC3 0x0C0 /* Software MUX Pad Control Register 48 */
+#define IOMUXC_PTC4 0x0C4 /* Software MUX Pad Control Register 49 */
+#define IOMUXC_PTC5 0x0C8 /* Software MUX Pad Control Register 50 */
+#define IOMUXC_PTC6 0x0CC /* Software MUX Pad Control Register 51 */
+#define IOMUXC_PTC7 0x0D0 /* Software MUX Pad Control Register 52 */
+#define IOMUXC_PTC8 0x0D4 /* Software MUX Pad Control Register 53 */
+#define IOMUXC_PTC9 0x0D8 /* Software MUX Pad Control Register 54 */
+#define IOMUXC_PTC10 0x0DC /* Software MUX Pad Control Register 55 */
+#define IOMUXC_PTC11 0x0E0 /* Software MUX Pad Control Register 56 */
+#define IOMUXC_PTC12 0x0E4 /* Software MUX Pad Control Register 57 */
+#define IOMUXC_PTC13 0x0E8 /* Software MUX Pad Control Register 58 */
+#define IOMUXC_PTC14 0x0EC /* Software MUX Pad Control Register 59 */
+#define IOMUXC_PTC15 0x0F0 /* Software MUX Pad Control Register 60 */
+#define IOMUXC_PTC16 0x0F4 /* Software MUX Pad Control Register 61 */
+#define IOMUXC_PTC17 0x0F8 /* Software MUX Pad Control Register 62 */
+#define IOMUXC_PTD31 0x0FC /* Software MUX Pad Control Register 63 */
+#define IOMUXC_PTD30 0x100 /* Software MUX Pad Control Register 64 */
+#define IOMUXC_PTD29 0x104 /* Software MUX Pad Control Register 65 */
+#define IOMUXC_PTD28 0x108 /* Software MUX Pad Control Register 66 */
+#define IOMUXC_PTD27 0x10C /* Software MUX Pad Control Register 67 */
+#define IOMUXC_PTD26 0x110 /* Software MUX Pad Control Register 68 */
+#define IOMUXC_PTD25 0x114 /* Software MUX Pad Control Register 69 */
+#define IOMUXC_PTD24 0x118 /* Software MUX Pad Control Register 70 */
+#define IOMUXC_PTD23 0x11C /* Software MUX Pad Control Register 71 */
+#define IOMUXC_PTD22 0x120 /* Software MUX Pad Control Register 72 */
+#define IOMUXC_PTD21 0x124 /* Software MUX Pad Control Register 73 */
+#define IOMUXC_PTD20 0x128 /* Software MUX Pad Control Register 74 */
+#define IOMUXC_PTD19 0x12C /* Software MUX Pad Control Register 75 */
+#define IOMUXC_PTD18 0x130 /* Software MUX Pad Control Register 76 */
+#define IOMUXC_PTD17 0x134 /* Software MUX Pad Control Register 77 */
+#define IOMUXC_PTD16 0x138 /* Software MUX Pad Control Register 78 */
+#define IOMUXC_PTD0 0x13C /* Software MUX Pad Control Register 79 */
+#define IOMUXC_PTD1 0x140 /* Software MUX Pad Control Register 80 */
+#define IOMUXC_PTD2 0x144 /* Software MUX Pad Control Register 81 */
+#define IOMUXC_PTD3 0x148 /* Software MUX Pad Control Register 82 */
+#define IOMUXC_PTD4 0x14C /* Software MUX Pad Control Register 83 */
+#define IOMUXC_PTD5 0x150 /* Software MUX Pad Control Register 84 */
+#define IOMUXC_PTD6 0x154 /* Software MUX Pad Control Register 85 */
+#define IOMUXC_PTD7 0x158 /* Software MUX Pad Control Register 86 */
+#define IOMUXC_PTD8 0x15C /* Software MUX Pad Control Register 87 */
+#define IOMUXC_PTD9 0x160 /* Software MUX Pad Control Register 88 */
+#define IOMUXC_PTD10 0x164 /* Software MUX Pad Control Register 89 */
+#define IOMUXC_PTD11 0x168 /* Software MUX Pad Control Register 90 */
+#define IOMUXC_PTD12 0x16C /* Software MUX Pad Control Register 91 */
+#define IOMUXC_PTD13 0x170 /* Software MUX Pad Control Register 92 */
+#define IOMUXC_PTB23 0x174 /* Software MUX Pad Control Register 93 */
+#define IOMUXC_PTB24 0x178 /* Software MUX Pad Control Register 94 */
+#define IOMUXC_PTB25 0x17C /* Software MUX Pad Control Register 95 */
+#define IOMUXC_PTB26 0x180 /* Software MUX Pad Control Register 96 */
+#define IOMUXC_PTB27 0x184 /* Software MUX Pad Control Register 97 */
+#define IOMUXC_PTB28 0x188 /* Software MUX Pad Control Register 98 */
+#define IOMUXC_PTC26 0x18C /* Software MUX Pad Control Register 99 */
+#define IOMUXC_PTC27 0x190 /* Software MUX Pad Control Register 100 */
+#define IOMUXC_PTC28 0x194 /* Software MUX Pad Control Register 101 */
+#define IOMUXC_PTC29 0x198 /* Software MUX Pad Control Register 102 */
+#define IOMUXC_PTC30 0x19C /* Software MUX Pad Control Register 103 */
+#define IOMUXC_PTC31 0x1A0 /* Software MUX Pad Control Register 104 */
+#define IOMUXC_PTE0 0x1A4 /* Software MUX Pad Control Register 105 */
+#define IOMUXC_PTE1 0x1A8 /* Software MUX Pad Control Register 106 */
+#define IOMUXC_PTE2 0x1AC /* Software MUX Pad Control Register 107 */
+#define IOMUXC_PTE3 0x1B0 /* Software MUX Pad Control Register 108 */
+#define IOMUXC_PTE4 0x1B4 /* Software MUX Pad Control Register 109 */
+#define IOMUXC_PTE5 0x1B8 /* Software MUX Pad Control Register 110 */
+#define IOMUXC_PTE6 0x1BC /* Software MUX Pad Control Register 111 */
+#define IOMUXC_PTE7 0x1C0 /* Software MUX Pad Control Register 112 */
+#define IOMUXC_PTE8 0x1C4 /* Software MUX Pad Control Register 113 */
+#define IOMUXC_PTE9 0x1C8 /* Software MUX Pad Control Register 114 */
+#define IOMUXC_PTE10 0x1CC /* Software MUX Pad Control Register 115 */
+#define IOMUXC_PTE11 0x1D0 /* Software MUX Pad Control Register 116 */
+#define IOMUXC_PTE12 0x1D4 /* Software MUX Pad Control Register 117 */
+#define IOMUXC_PTE13 0x1D8 /* Software MUX Pad Control Register 118 */
+#define IOMUXC_PTE14 0x1DC /* Software MUX Pad Control Register 119 */
+#define IOMUXC_PTE15 0x1E0 /* Software MUX Pad Control Register 120 */
+#define IOMUXC_PTE16 0x1E4 /* Software MUX Pad Control Register 121 */
+#define IOMUXC_PTE17 0x1E8 /* Software MUX Pad Control Register 122 */
+#define IOMUXC_PTE18 0x1EC /* Software MUX Pad Control Register 123 */
+#define IOMUXC_PTE19 0x1F0 /* Software MUX Pad Control Register 124 */
+#define IOMUXC_PTE20 0x1F4 /* Software MUX Pad Control Register 125 */
+#define IOMUXC_PTE21 0x1F8 /* Software MUX Pad Control Register 126 */
+#define IOMUXC_PTE22 0x1FC /* Software MUX Pad Control Register 127 */
+#define IOMUXC_PTE23 0x200 /* Software MUX Pad Control Register 128 */
+#define IOMUXC_PTE24 0x204 /* Software MUX Pad Control Register 129 */
+#define IOMUXC_PTE25 0x208 /* Software MUX Pad Control Register 130 */
+#define IOMUXC_PTE26 0x20C /* Software MUX Pad Control Register 131 */
+#define IOMUXC_PTE27 0x210 /* Software MUX Pad Control Register 132 */
+#define IOMUXC_PTE28 0x214 /* Software MUX Pad Control Register 133 */
+#define IOMUXC_PTA7 0x218 /* Software MUX Pad Control Register 134 */
Property changes on: trunk/sys/arm/freescale/vybrid/vf_iomuxc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_machdep.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_machdep.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,94 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_machdep.c 258057 2013-11-12 18:02:56Z br $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <dev/fdt/fdt_common.h>
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+
+}
+
+void
+initarm_gpio_init(void)
+{
+
+}
+
+void
+initarm_late_init(void)
+{
+
+}
+
+int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(0x40000000, 0x100000);
+
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
Property changes on: trunk/sys/arm/freescale/vybrid/vf_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_mscm.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_mscm.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_mscm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,127 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Miscellaneous System Control Module (MSCM)
+ * Chapter 66, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_mscm.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_common.h>
+
+#define VF_NINT 112 /* Total number of interrupts */
+
+/* Int Router Shared Peripheral Routing Control */
+#define MSCM_IRSPRC(n) (0x880 + 2 * n)
+
+struct mscm_softc {
+ struct resource *res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct resource_spec mscm_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+mscm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-mscm"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family Miscellaneous System Control Module");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+mscm_attach(device_t dev)
+{
+ struct mscm_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, mscm_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Route all the interrupts to CP0 */
+ for (i = 0; i < VF_NINT; i++)
+ WRITE2(sc, MSCM_IRSPRC(i), 1);
+
+ return (0);
+}
+
+static device_method_t mscm_methods[] = {
+ DEVMETHOD(device_probe, mscm_probe),
+ DEVMETHOD(device_attach, mscm_attach),
+ { 0, 0 }
+};
+
+static driver_t mscm_driver = {
+ "mscm",
+ mscm_methods,
+ sizeof(struct mscm_softc),
+};
+
+static devclass_t mscm_devclass;
+
+DRIVER_MODULE(mscm, simplebus, mscm_driver, mscm_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_mscm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_nfc.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_nfc.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_nfc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,528 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family NAND Flash Controller (NFC)
+ * Chapter 31, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_nfc.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/time.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/nand/nand.h>
+#include <dev/nand/nandbus.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include "nfc_if.h"
+
+#include <arm/freescale/vybrid/vf_common.h>
+
+enum addr_type {
+ ADDR_NONE,
+ ADDR_ID,
+ ADDR_ROW,
+ ADDR_ROWCOL
+};
+
+struct fsl_nfc_fcm {
+ uint32_t addr_bits;
+ enum addr_type addr_type;
+ uint32_t col_addr_bits;
+ uint32_t row_addr_bits;
+ u_int read_ptr;
+ u_int addr_ptr;
+ u_int command;
+ u_int code;
+};
+
+struct vf_nand_softc {
+ struct nand_softc nand_dev;
+ bus_space_handle_t bsh;
+ bus_space_tag_t bst;
+ struct resource *res[2];
+ struct fsl_nfc_fcm fcm;
+};
+
+static struct resource_spec nfc_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int vf_nand_attach(device_t);
+static int vf_nand_probe(device_t);
+static int vf_nand_send_command(device_t, uint8_t);
+static int vf_nand_send_address(device_t, uint8_t);
+static int vf_nand_start_command(device_t);
+static uint8_t vf_nand_read_byte(device_t);
+static void vf_nand_read_buf(device_t, void *, uint32_t);
+static void vf_nand_write_buf(device_t, void *, uint32_t);
+static int vf_nand_select_cs(device_t, uint8_t);
+static int vf_nand_read_rnb(device_t);
+
+#define CMD_READ_PAGE 0x7EE0
+#define CMD_PROG_PAGE 0x7FC0
+#define CMD_PROG_PAGE_DMA 0xFFC8
+#define CMD_ERASE 0x4EC0
+#define CMD_READ_ID 0x4804
+#define CMD_READ_STATUS 0x4068
+#define CMD_RESET 0x4040
+#define CMD_RANDOM_IN 0x7140
+#define CMD_RANDOM_OUT 0x70E0
+
+#define CMD_BYTE2_PROG_PAGE 0x10
+#define CMD_BYTE2_PAGE_READ 0x30
+#define CMD_BYTE2_ERASE 0xD0
+
+#define NFC_CMD1 0x3F00 /* Flash command 1 */
+#define NFC_CMD2 0x3F04 /* Flash command 2 */
+#define NFC_CAR 0x3F08 /* Column address */
+#define NFC_RAR 0x3F0C /* Row address */
+#define NFC_RPT 0x3F10 /* Flash command repeat */
+#define NFC_RAI 0x3F14 /* Row address increment */
+#define NFC_SR1 0x3F18 /* Flash status 1 */
+#define NFC_SR2 0x3F1C /* Flash status 2 */
+#define NFC_DMA_CH1 0x3F20 /* DMA channel 1 address */
+#define NFC_DMACFG 0x3F24 /* DMA configuration */
+#define NFC_SWAP 0x3F28 /* Cach swap */
+#define NFC_SECSZ 0x3F2C /* Sector size */
+#define NFC_CFG 0x3F30 /* Flash configuration */
+#define NFC_DMA_CH2 0x3F34 /* DMA channel 2 address */
+#define NFC_ISR 0x3F38 /* Interrupt status */
+
+#define ECCMODE_SHIFT 17
+#define AIAD_SHIFT 5
+#define AIBN_SHIFT 4
+#define PAGECOUNT_SHIFT 0
+#define BITWIDTH_SHIFT 7
+#define BITWIDTH8 0
+#define BITWIDTH16 1
+#define PAGECOUNT_MASK 0xf
+
+#define CMD2_BYTE1_SHIFT 24
+#define CMD2_CODE_SHIFT 8
+#define CMD2_BUFNO_SHIFT 1
+#define CMD2_START_SHIFT 0
+
+static device_method_t vf_nand_methods[] = {
+ DEVMETHOD(device_probe, vf_nand_probe),
+ DEVMETHOD(device_attach, vf_nand_attach),
+ DEVMETHOD(nfc_start_command, vf_nand_start_command),
+ DEVMETHOD(nfc_send_command, vf_nand_send_command),
+ DEVMETHOD(nfc_send_address, vf_nand_send_address),
+ DEVMETHOD(nfc_read_byte, vf_nand_read_byte),
+ DEVMETHOD(nfc_read_buf, vf_nand_read_buf),
+ DEVMETHOD(nfc_write_buf, vf_nand_write_buf),
+ DEVMETHOD(nfc_select_cs, vf_nand_select_cs),
+ DEVMETHOD(nfc_read_rnb, vf_nand_read_rnb),
+ { 0, 0 },
+};
+
+static driver_t vf_nand_driver = {
+ "nand",
+ vf_nand_methods,
+ sizeof(struct vf_nand_softc),
+};
+
+static devclass_t vf_nand_devclass;
+DRIVER_MODULE(vf_nand, simplebus, vf_nand_driver, vf_nand_devclass, 0, 0);
+
+static int
+vf_nand_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-nand"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family NAND controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+vf_nand_attach(device_t dev)
+{
+ struct vf_nand_softc *sc;
+ int err;
+ int reg;
+
+ sc = device_get_softc(dev);
+ if (bus_alloc_resources(dev, nfc_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources!\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Size in bytes of one elementary transfer unit */
+ WRITE4(sc, NFC_SECSZ, 2048);
+
+ /* Flash mode width */
+ reg = READ4(sc, NFC_CFG);
+ reg |= (BITWIDTH16 << BITWIDTH_SHIFT);
+
+ /* No correction, ECC bypass */
+ reg &= ~(0x7 << ECCMODE_SHIFT);
+
+ /* Disable Auto-incrementing of flash row address */
+ reg &= ~(0x1 << AIAD_SHIFT);
+
+ /* Disable Auto-incrementing of buffer numbers */
+ reg &= ~(0x1 << AIBN_SHIFT);
+
+ /*
+ * Number of virtual pages (in one physical flash page)
+ * to be programmed or read, etc.
+ */
+ reg &= ~(PAGECOUNT_MASK);
+ reg |= (1 << PAGECOUNT_SHIFT);
+ WRITE4(sc, NFC_CFG, reg);
+
+ nand_init(&sc->nand_dev, dev, NAND_ECC_NONE, 0, 0, NULL, NULL);
+ err = nandbus_create(dev);
+ return (err);
+}
+
+static int
+vf_nand_start_command(device_t dev)
+{
+ struct vf_nand_softc *sc;
+ struct fsl_nfc_fcm *fcm;
+ int reg;
+
+ sc = device_get_softc(dev);
+ fcm = &sc->fcm;
+
+ nand_debug(NDBG_DRV,"vf_nand: start command %x", fcm->command);
+
+ /* CMD2 */
+ reg = READ4(sc, NFC_CMD2);
+ reg &= ~(0xff << CMD2_BYTE1_SHIFT);
+ reg |= (fcm->command << CMD2_BYTE1_SHIFT);
+ WRITE4(sc, NFC_CMD2, reg);
+
+ /* CMD1 */
+ if ((fcm->command == NAND_CMD_READ) ||
+ (fcm->command == NAND_CMD_PROG) ||
+ (fcm->command == NAND_CMD_ERASE)) {
+ reg = READ4(sc, NFC_CMD1);
+ reg &= ~(0xff << 24);
+
+ if (fcm->command == NAND_CMD_READ)
+ reg |= (CMD_BYTE2_PAGE_READ << 24);
+ else if (fcm->command == NAND_CMD_PROG)
+ reg |= (CMD_BYTE2_PROG_PAGE << 24);
+ else if (fcm->command == NAND_CMD_ERASE)
+ reg |= (CMD_BYTE2_ERASE << 24);
+
+ WRITE4(sc, NFC_CMD1, reg);
+ }
+
+ /* We work with 1st buffer */
+ reg = READ4(sc, NFC_CMD2);
+ reg &= ~(0xf << CMD2_BUFNO_SHIFT);
+ reg |= (0 << CMD2_BUFNO_SHIFT);
+ WRITE4(sc, NFC_CMD2, reg);
+
+ /* Cmd CODE */
+ reg = READ4(sc, NFC_CMD2);
+ reg &= ~(0xffff << CMD2_CODE_SHIFT);
+ reg |= (fcm->code << CMD2_CODE_SHIFT);
+ WRITE4(sc, NFC_CMD2, reg);
+
+ /* Col */
+ if (fcm->addr_type == ADDR_ROWCOL) {
+ reg = READ4(sc, NFC_CAR);
+ reg &= ~(0xffff);
+ reg |= fcm->col_addr_bits;
+ nand_debug(NDBG_DRV,"setting CAR to 0x%08x\n", reg);
+ WRITE4(sc, NFC_CAR, reg);
+ }
+
+ /* Row */
+ reg = READ4(sc, NFC_RAR);
+ reg &= ~(0xffffff);
+ if (fcm->addr_type == ADDR_ID)
+ reg |= fcm->addr_bits;
+ else
+ reg |= fcm->row_addr_bits;
+ WRITE4(sc, NFC_RAR, reg);
+
+ /* Start */
+ reg = READ4(sc, NFC_CMD2);
+ reg |= (1 << CMD2_START_SHIFT);
+ WRITE4(sc, NFC_CMD2, reg);
+
+ /* Wait command completion */
+ while (READ4(sc, NFC_CMD2) & (1 << CMD2_START_SHIFT))
+ ;
+
+ return (0);
+}
+
+static int
+vf_nand_send_command(device_t dev, uint8_t command)
+{
+ struct vf_nand_softc *sc;
+ struct fsl_nfc_fcm *fcm;
+
+ nand_debug(NDBG_DRV,"vf_nand: send command %x", command);
+
+ sc = device_get_softc(dev);
+ fcm = &sc->fcm;
+
+ if ((command == NAND_CMD_READ_END) ||
+ (command == NAND_CMD_PROG_END) ||
+ (command == NAND_CMD_ERASE_END)) {
+ return (0);
+ }
+
+ fcm->command = command;
+
+ fcm->code = 0;
+ fcm->read_ptr = 0;
+ fcm->addr_type = 0;
+ fcm->addr_bits = 0;
+
+ fcm->addr_ptr = 0;
+ fcm->col_addr_bits = 0;
+ fcm->row_addr_bits = 0;
+
+ switch (command) {
+ case NAND_CMD_READ:
+ fcm->code = CMD_READ_PAGE;
+ fcm->addr_type = ADDR_ROWCOL;
+ break;
+ case NAND_CMD_PROG:
+ fcm->code = CMD_PROG_PAGE;
+ fcm->addr_type = ADDR_ROWCOL;
+ break;
+ case NAND_CMD_PROG_END:
+ break;
+ case NAND_CMD_ERASE_END:
+ break;
+ case NAND_CMD_RESET:
+ fcm->code = CMD_RESET;
+ break;
+ case NAND_CMD_READ_ID:
+ fcm->code = CMD_READ_ID;
+ fcm->addr_type = ADDR_ID;
+ break;
+ case NAND_CMD_READ_PARAMETER:
+ fcm->code = CMD_READ_PAGE;
+ fcm->addr_type = ADDR_ID;
+ break;
+ case NAND_CMD_STATUS:
+ fcm->code = CMD_READ_STATUS;
+ break;
+ case NAND_CMD_ERASE:
+ fcm->code = CMD_ERASE;
+ fcm->addr_type = ADDR_ROW;
+ break;
+ default:
+ nand_debug(NDBG_DRV, "unknown command %d\n", command);
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+vf_nand_send_address(device_t dev, uint8_t addr)
+{
+ struct vf_nand_softc *sc;
+ struct fsl_nfc_fcm *fcm;
+
+ nand_debug(NDBG_DRV,"vf_nand: send address %x", addr);
+ sc = device_get_softc(dev);
+ fcm = &sc->fcm;
+
+ nand_debug(NDBG_DRV, "setting addr #%d to 0x%02x\n", fcm->addr_ptr, addr);
+
+ if (fcm->addr_type == ADDR_ID) {
+ fcm->addr_bits = addr;
+ } else if (fcm->addr_type == ADDR_ROWCOL) {
+
+ if (fcm->addr_ptr < 2)
+ fcm->col_addr_bits |= (addr << (fcm->addr_ptr * 8));
+ else
+ fcm->row_addr_bits |= (addr << ((fcm->addr_ptr - 2) * 8));
+
+ } else if (fcm->addr_type == ADDR_ROW)
+ fcm->row_addr_bits |= (addr << (fcm->addr_ptr * 8));
+
+ fcm->addr_ptr += 1;
+
+ return (0);
+}
+
+static uint8_t
+vf_nand_read_byte(device_t dev)
+{
+ struct vf_nand_softc *sc;
+ struct fsl_nfc_fcm *fcm;
+ uint8_t data;
+ int sr1, sr2;
+ int b;
+
+ sc = device_get_softc(dev);
+ fcm = &sc->fcm;
+
+ sr1 = READ4(sc, NFC_SR1);
+ sr2 = READ4(sc, NFC_SR2);
+
+ data = 0;
+ if (fcm->addr_type == ADDR_ID) {
+ b = 32 - ((fcm->read_ptr + 1) * 8);
+ data = (sr1 >> b) & 0xff;
+ fcm->read_ptr++;
+ } else if (fcm->command == NAND_CMD_STATUS) {
+ data = sr2 & 0xff;
+ }
+
+ nand_debug(NDBG_DRV,"vf_nand: read %x", data);
+ return (data);
+}
+
+static void
+vf_nand_read_buf(device_t dev, void* buf, uint32_t len)
+{
+ struct vf_nand_softc *sc;
+ struct fsl_nfc_fcm *fcm;
+ uint16_t *tmp;
+ uint8_t *b;
+ int i;
+
+ b = (uint8_t*)buf;
+ sc = device_get_softc(dev);
+ fcm = &sc->fcm;
+
+ nand_debug(NDBG_DRV, "vf_nand: read_buf len %d", len);
+
+ if (fcm->command == NAND_CMD_READ_PARAMETER) {
+ tmp = malloc(len, M_DEVBUF, M_NOWAIT);
+ bus_read_region_2(sc->res[0], 0x0, tmp, len);
+
+ for (i = 0; i < len; i += 2) {
+ b[i] = tmp[i+1];
+ b[i+1] = tmp[i];
+ }
+
+ free(tmp, M_DEVBUF);
+
+#ifdef NAND_DEBUG
+ for (i = 0; i < len; i++) {
+ if (!(i % 16))
+ printf("%s", i == 0 ? "vf_nand:\n" : "\n");
+ printf(" %x", b[i]);
+ if (i == len - 1)
+ printf("\n");
+ }
+#endif
+
+ } else {
+
+ for (i = 0; i < len; i++) {
+ b[i] = READ1(sc, i);
+
+#ifdef NAND_DEBUG
+ if (!(i % 16))
+ printf("%s", i == 0 ? "vf_nand:\n" : "\n");
+ printf(" %x", b[i]);
+ if (i == len - 1)
+ printf("\n");
+#endif
+ }
+
+ }
+}
+
+static void
+vf_nand_write_buf(device_t dev, void* buf, uint32_t len)
+{
+ struct vf_nand_softc *sc;
+ struct fsl_nfc_fcm *fcm;
+ uint8_t *b;
+ int i;
+
+ b = (uint8_t*)buf;
+ sc = device_get_softc(dev);
+ fcm = &sc->fcm;
+
+ nand_debug(NDBG_DRV,"vf_nand: write_buf len %d", len);
+
+ for (i = 0; i < len; i++) {
+ WRITE1(sc, i, b[i]);
+
+#ifdef NAND_DEBUG
+ if (!(i % 16))
+ printf("%s", i == 0 ? "vf_nand:\n" : "\n");
+ printf(" %x", b[i]);
+ if (i == len - 1)
+ printf("\n");
+#endif
+
+ }
+}
+
+static int
+vf_nand_select_cs(device_t dev, uint8_t cs)
+{
+
+ if (cs > 0)
+ return (ENODEV);
+
+ return (0);
+}
+
+static int
+vf_nand_read_rnb(device_t dev)
+{
+
+ /* no-op */
+ return (0); /* ready */
+}
Property changes on: trunk/sys/arm/freescale/vybrid/vf_nfc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_port.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_port.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_port.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,251 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Port control and interrupts (PORT)
+ * Chapter 6, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_port.c 266274 2014-05-16 23:27:18Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_port.h>
+#include <arm/freescale/vybrid/vf_common.h>
+
+/* Pin Control Register */
+#define PORT_PCR(n) (0x1000 * (n >> 5) + 0x4 * (n % 32))
+#define PCR_IRQC_S 16
+#define PCR_IRQC_M 0xF
+#define PCR_DMA_RE 0x1
+#define PCR_DMA_FE 0x2
+#define PCR_DMA_EE 0x3
+#define PCR_INT_LZ 0x8
+#define PCR_INT_RE 0x9
+#define PCR_INT_FE 0xA
+#define PCR_INT_EE 0xB
+#define PCR_INT_LO 0xC
+#define PCR_ISF (1 << 24)
+#define PORT0_ISFR 0xA0 /* Interrupt Status Flag Register */
+#define PORT0_DFER 0xC0 /* Digital Filter Enable Register */
+#define PORT0_DFCR 0xC4 /* Digital Filter Clock Register */
+#define PORT0_DFWR 0xC8 /* Digital Filter Width Register */
+
+struct port_event {
+ uint32_t enabled;
+ uint32_t mux_num;
+ uint32_t mux_src;
+ uint32_t mux_chn;
+ void (*ih) (void *);
+ void *ih_user;
+ enum ev_type pevt;
+};
+
+static struct port_event event_map[NGPIO];
+
+struct port_softc {
+ struct resource *res[6];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ void *gpio_ih[NGPIO];
+};
+
+struct port_softc *port_sc;
+
+static struct resource_spec port_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { SYS_RES_IRQ, 4, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+port_intr(void *arg)
+{
+ struct port_event *pev;
+ struct port_softc *sc;
+ int reg;
+ int i;
+
+ sc = arg;
+
+ for (i = 0; i < NGPIO; i++) {
+ reg = READ4(sc, PORT_PCR(i));
+ if (reg & PCR_ISF) {
+
+ /* Clear interrupt */
+ WRITE4(sc, PORT_PCR(i), reg);
+
+ /* Handle event */
+ pev = &event_map[i];
+ if (pev->enabled == 1) {
+ if (pev->ih != NULL) {
+ pev->ih(pev->ih_user);
+ }
+ }
+ }
+ }
+
+ return (FILTER_HANDLED);
+}
+
+int
+port_setup(int pnum, enum ev_type pevt, void (*ih)(void *), void *ih_user)
+{
+ struct port_event *pev;
+ struct port_softc *sc;
+ int reg;
+ int val;
+
+ sc = port_sc;
+
+ switch (pevt) {
+ case DMA_RISING_EDGE:
+ val = PCR_DMA_RE;
+ break;
+ case DMA_FALLING_EDGE:
+ val = PCR_DMA_FE;
+ break;
+ case DMA_EITHER_EDGE:
+ val = PCR_DMA_EE;
+ break;
+ case INT_LOGIC_ZERO:
+ val = PCR_INT_LZ;
+ break;
+ case INT_RISING_EDGE:
+ val = PCR_INT_RE;
+ break;
+ case INT_FALLING_EDGE:
+ val = PCR_INT_FE;
+ break;
+ case INT_EITHER_EDGE:
+ val = PCR_INT_RE;
+ break;
+ case INT_LOGIC_ONE:
+ val = PCR_INT_LO;
+ break;
+ default:
+ return (-1);
+ };
+
+ reg = READ4(sc, PORT_PCR(pnum));
+ reg &= ~(PCR_IRQC_M << PCR_IRQC_S);
+ reg |= (val << PCR_IRQC_S);
+ WRITE4(sc, PORT_PCR(pnum), reg);
+
+ pev = &event_map[pnum];
+ pev->ih = ih;
+ pev->ih_user = ih_user;
+ pev->pevt = pevt;
+ pev->enabled = 1;
+
+ return (0);
+}
+
+static int
+port_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-port"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family Port control and interrupts");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+port_attach(device_t dev)
+{
+ struct port_softc *sc;
+ int irq;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, port_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ port_sc = sc;
+
+ for (irq = 0; irq < NPORTS; irq ++) {
+ if ((bus_setup_intr(dev, sc->res[1 + irq], INTR_TYPE_MISC,
+ port_intr, NULL, sc, &sc->gpio_ih[irq]))) {
+ device_printf(dev,
+ "ERROR: Unable to register interrupt handler\n");
+ return (ENXIO);
+ }
+ }
+
+ return (0);
+}
+
+static device_method_t port_methods[] = {
+ DEVMETHOD(device_probe, port_probe),
+ DEVMETHOD(device_attach, port_attach),
+ { 0, 0 }
+};
+
+static driver_t port_driver = {
+ "port",
+ port_methods,
+ sizeof(struct port_softc),
+};
+
+static devclass_t port_devclass;
+
+DRIVER_MODULE(port, simplebus, port_driver, port_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_port.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_port.h
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_port.h (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_port.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,44 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_port.h 266274 2014-05-16 23:27:18Z ian $
+ */
+
+#define NPORTS 5
+#define NGPIO (NPORTS * 32)
+
+enum ev_type {
+ DMA_RISING_EDGE,
+ DMA_FALLING_EDGE,
+ DMA_EITHER_EDGE,
+ INT_LOGIC_ZERO,
+ INT_RISING_EDGE,
+ INT_FALLING_EDGE,
+ INT_EITHER_EDGE,
+ INT_LOGIC_ONE,
+};
+
+int port_setup(int, enum ev_type, void (*ih)(void *), void *ih_user);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_port.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_sai.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_sai.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_sai.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,806 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Synchronous Audio Interface (SAI)
+ * Chapter 51, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_sai.c 273652 2014-10-26 01:30:46Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/chip.h>
+#include <mixer_if.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_common.h>
+#include <arm/freescale/vybrid/vf_dmamux.h>
+#include <arm/freescale/vybrid/vf_edma.h>
+
+#define I2S_TCSR 0x00 /* SAI Transmit Control */
+#define I2S_TCR1 0x04 /* SAI Transmit Configuration 1 */
+#define I2S_TCR2 0x08 /* SAI Transmit Configuration 2 */
+#define I2S_TCR3 0x0C /* SAI Transmit Configuration 3 */
+#define I2S_TCR4 0x10 /* SAI Transmit Configuration 4 */
+#define I2S_TCR5 0x14 /* SAI Transmit Configuration 5 */
+#define I2S_TDR0 0x20 /* SAI Transmit Data */
+#define I2S_TFR0 0x40 /* SAI Transmit FIFO */
+#define I2S_TMR 0x60 /* SAI Transmit Mask */
+#define I2S_RCSR 0x80 /* SAI Receive Control */
+#define I2S_RCR1 0x84 /* SAI Receive Configuration 1 */
+#define I2S_RCR2 0x88 /* SAI Receive Configuration 2 */
+#define I2S_RCR3 0x8C /* SAI Receive Configuration 3 */
+#define I2S_RCR4 0x90 /* SAI Receive Configuration 4 */
+#define I2S_RCR5 0x94 /* SAI Receive Configuration 5 */
+#define I2S_RDR0 0xA0 /* SAI Receive Data */
+#define I2S_RFR0 0xC0 /* SAI Receive FIFO */
+#define I2S_RMR 0xE0 /* SAI Receive Mask */
+
+#define TCR1_TFW_M 0x1f /* Transmit FIFO Watermark Mask */
+#define TCR1_TFW_S 0 /* Transmit FIFO Watermark Shift */
+#define TCR2_MSEL_M 0x3 /* MCLK Select Mask*/
+#define TCR2_MSEL_S 26 /* MCLK Select Shift*/
+#define TCR2_BCP (1 << 25) /* Bit Clock Polarity */
+#define TCR2_BCD (1 << 24) /* Bit Clock Direction */
+#define TCR3_TCE (1 << 16) /* Transmit Channel Enable */
+#define TCR4_FRSZ_M 0x1f /* Frame size Mask */
+#define TCR4_FRSZ_S 16 /* Frame size Shift */
+#define TCR4_SYWD_M 0x1f /* Sync Width Mask */
+#define TCR4_SYWD_S 8 /* Sync Width Shift */
+#define TCR4_MF (1 << 4) /* MSB First */
+#define TCR4_FSE (1 << 3) /* Frame Sync Early */
+#define TCR4_FSP (1 << 1) /* Frame Sync Polarity Low */
+#define TCR4_FSD (1 << 0) /* Frame Sync Direction Master */
+#define TCR5_FBT_M 0x1f /* First Bit Shifted */
+#define TCR5_FBT_S 8 /* First Bit Shifted */
+#define TCR5_W0W_M 0x1f /* Word 0 Width */
+#define TCR5_W0W_S 16 /* Word 0 Width */
+#define TCR5_WNW_M 0x1f /* Word N Width */
+#define TCR5_WNW_S 24 /* Word N Width */
+#define TCSR_TE (1 << 31) /* Transmitter Enable */
+#define TCSR_BCE (1 << 28) /* Bit Clock Enable */
+#define TCSR_FRDE (1 << 0) /* FIFO Request DMA Enable */
+
+#define SAI_NCHANNELS 1
+
+static MALLOC_DEFINE(M_SAI, "sai", "sai audio");
+
+struct sai_rate {
+ uint32_t speed;
+ uint32_t div; /* Bit Clock Divide. Division value is (div + 1) * 2. */
+ uint32_t mfi; /* PLL4 Multiplication Factor Integer */
+ uint32_t mfn; /* PLL4 Multiplication Factor Numerator */
+ uint32_t mfd; /* PLL4 Multiplication Factor Denominator */
+};
+
+/*
+ * Bit clock divider formula
+ * (div + 1) * 2 = MCLK/(nch * LRCLK * bits/1000000),
+ * where:
+ * MCLK - master clock
+ * nch - number of channels
+ * LRCLK - left right clock
+ * e.g. (div + 1) * 2 = 16.9344/(2 * 44100 * 24/1000000)
+ *
+ * Example for 96khz, 24bit, 18.432 Mhz mclk (192fs)
+ * { 96000, 1, 18, 40176000, 93000000 },
+ */
+
+static struct sai_rate rate_map[] = {
+ { 44100, 7, 33, 80798400, 93000000 }, /* 33.8688 Mhz */
+ { 96000, 3, 36, 80352000, 93000000 }, /* 36.864 Mhz */
+ { 192000, 1, 36, 80352000, 93000000 }, /* 36.864 Mhz */
+ { 0, 0 },
+};
+
+struct sc_info {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ struct mtx *lock;
+ uint32_t speed;
+ uint32_t period;
+ void *ih;
+ int pos;
+ int dma_size;
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+ bus_addr_t buf_base_phys;
+ uint32_t *buf_base;
+ struct tcd_conf *tcd;
+ struct sai_rate *sr;
+ struct edma_softc *edma_sc;
+ int edma_chnum;
+};
+
+/* Channel registers */
+struct sc_chinfo {
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_pcminfo *parent;
+
+ /* Channel information */
+ uint32_t dir;
+ uint32_t format;
+
+ /* Flags */
+ uint32_t run;
+};
+
+/* PCM device private data */
+struct sc_pcminfo {
+ device_t dev;
+ uint32_t (*ih) (struct sc_pcminfo *scp);
+ uint32_t chnum;
+ struct sc_chinfo chan[SAI_NCHANNELS];
+ struct sc_info *sc;
+};
+
+static struct resource_spec sai_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int setup_dma(struct sc_pcminfo *scp);
+static void setup_sai(struct sc_info *);
+static void sai_configure_clock(struct sc_info *);
+
+/*
+ * Mixer interface.
+ */
+
+static int
+saimixer_init(struct snd_mixer *m)
+{
+ struct sc_pcminfo *scp;
+ struct sc_info *sc;
+ int mask;
+
+ scp = mix_getdevinfo(m);
+ sc = scp->sc;
+
+ if (sc == NULL)
+ return -1;
+
+ mask = SOUND_MASK_PCM;
+
+ snd_mtxlock(sc->lock);
+ pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL);
+ mix_setdevs(m, mask);
+ snd_mtxunlock(sc->lock);
+
+ return (0);
+}
+
+static int
+saimixer_set(struct snd_mixer *m, unsigned dev,
+ unsigned left, unsigned right)
+{
+ struct sc_pcminfo *scp;
+
+ scp = mix_getdevinfo(m);
+
+#if 0
+ device_printf(scp->dev, "saimixer_set() %d %d\n",
+ left, right);
+#endif
+
+ return (0);
+}
+
+static kobj_method_t saimixer_methods[] = {
+ KOBJMETHOD(mixer_init, saimixer_init),
+ KOBJMETHOD(mixer_set, saimixer_set),
+ KOBJMETHOD_END
+};
+MIXER_DECLARE(saimixer);
+
+/*
+ * Channel interface.
+ */
+
+static void *
+saichan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
+ struct pcm_channel *c, int dir)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+
+ scp = (struct sc_pcminfo *)devinfo;
+ sc = scp->sc;
+
+ snd_mtxlock(sc->lock);
+ ch = &scp->chan[0];
+ ch->dir = dir;
+ ch->run = 0;
+ ch->buffer = b;
+ ch->channel = c;
+ ch->parent = scp;
+ snd_mtxunlock(sc->lock);
+
+ if (sndbuf_setup(ch->buffer, sc->buf_base, sc->dma_size) != 0) {
+ device_printf(scp->dev, "Can't setup sndbuf.\n");
+ return NULL;
+ }
+
+ return ch;
+}
+
+static int
+saichan_free(kobj_t obj, void *data)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_pcminfo *scp = ch->parent;
+ struct sc_info *sc = scp->sc;
+
+#if 0
+ device_printf(scp->dev, "saichan_free()\n");
+#endif
+
+ snd_mtxlock(sc->lock);
+ /* TODO: free channel buffer */
+ snd_mtxunlock(sc->lock);
+
+ return (0);
+}
+
+static int
+saichan_setformat(kobj_t obj, void *data, uint32_t format)
+{
+ struct sc_chinfo *ch = data;
+
+ ch->format = format;
+
+ return (0);
+}
+
+static uint32_t
+saichan_setspeed(kobj_t obj, void *data, uint32_t speed)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct sai_rate *sr;
+ struct sc_info *sc;
+ int threshold;
+ int i;
+
+ ch = data;
+ scp = ch->parent;
+ sc = scp->sc;
+
+ sr = NULL;
+
+ /* First look for equal frequency. */
+ for (i = 0; rate_map[i].speed != 0; i++) {
+ if (rate_map[i].speed == speed)
+ sr = &rate_map[i];
+ }
+
+ /* If no match, just find nearest. */
+ if (sr == NULL) {
+ for (i = 0; rate_map[i].speed != 0; i++) {
+ sr = &rate_map[i];
+ threshold = sr->speed + ((rate_map[i + 1].speed != 0) ?
+ ((rate_map[i + 1].speed - sr->speed) >> 1) : 0);
+ if (speed < threshold)
+ break;
+ }
+ }
+
+ sc->sr = sr;
+
+ sai_configure_clock(sc);
+
+ return (sr->speed);
+}
+
+static void
+sai_configure_clock(struct sc_info *sc)
+{
+ struct sai_rate *sr;
+ int reg;
+
+ sr = sc->sr;
+
+ /*
+ * Manual says that TCR/RCR registers must not be
+ * altered when TCSR[TE] is set.
+ * We ignore it since we have problem sometimes
+ * after re-enabling transmitter (DMA goes stall).
+ */
+
+ reg = READ4(sc, I2S_TCR2);
+ reg &= ~(0xff << 0);
+ reg |= (sr->div << 0);
+ WRITE4(sc, I2S_TCR2, reg);
+
+ pll4_configure_output(sr->mfi, sr->mfn, sr->mfd);
+}
+
+static uint32_t
+saichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_pcminfo *scp = ch->parent;
+ struct sc_info *sc = scp->sc;
+
+ sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize);
+
+ sc->period = sndbuf_getblksz(ch->buffer);
+ return (sc->period);
+}
+
+uint32_t sai_dma_intr(void *arg, int chn);
+uint32_t
+sai_dma_intr(void *arg, int chn)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+ struct tcd_conf *tcd;
+
+ scp = arg;
+ ch = &scp->chan[0];
+
+ sc = scp->sc;
+ tcd = sc->tcd;
+
+ sc->pos += (tcd->nbytes * tcd->nmajor);
+ if (sc->pos >= sc->dma_size)
+ sc->pos -= sc->dma_size;
+
+ if (ch->run)
+ chn_intr(ch->channel);
+
+ return (0);
+}
+
+static int
+find_edma_controller(struct sc_info *sc)
+{
+ struct edma_softc *edma_sc;
+ phandle_t node, edma_node;
+ int edma_src_transmit;
+ int edma_mux_group;
+ int edma_device_id;
+ device_t edma_dev;
+ int dts_value;
+ int len;
+ int i;
+
+ if ((node = ofw_bus_get_node(sc->dev)) == -1)
+ return (ENXIO);
+
+ if ((len = OF_getproplen(node, "edma-controller")) <= 0)
+ return (ENXIO);
+ if ((len = OF_getproplen(node, "edma-src-transmit")) <= 0)
+ return (ENXIO);
+ if ((len = OF_getproplen(node, "edma-mux-group")) <= 0)
+ return (ENXIO);
+
+ OF_getprop(node, "edma-src-transmit", &dts_value, len);
+ edma_src_transmit = fdt32_to_cpu(dts_value);
+ OF_getprop(node, "edma-mux-group", &dts_value, len);
+ edma_mux_group = fdt32_to_cpu(dts_value);
+ OF_getprop(node, "edma-controller", &dts_value, len);
+ edma_node = OF_node_from_xref(fdt32_to_cpu(dts_value));
+
+ if ((len = OF_getproplen(edma_node, "device-id")) <= 0) {
+ return (ENXIO);
+ };
+
+ OF_getprop(edma_node, "device-id", &dts_value, len);
+ edma_device_id = fdt32_to_cpu(dts_value);
+
+ edma_sc = NULL;
+
+ for (i = 0; i < EDMA_NUM_DEVICES; i++) {
+ edma_dev = devclass_get_device(devclass_find("edma"), i);
+ if (edma_dev) {
+ edma_sc = device_get_softc(edma_dev);
+ if (edma_sc->device_id == edma_device_id) {
+ /* found */
+ break;
+ };
+
+ edma_sc = NULL;
+ };
+ };
+
+ if (edma_sc == NULL) {
+ device_printf(sc->dev, "no eDMA. can't operate\n");
+ return (ENXIO);
+ };
+
+ sc->edma_sc = edma_sc;
+
+ sc->edma_chnum = edma_sc->channel_configure(edma_sc, edma_mux_group,
+ edma_src_transmit);
+ if (sc->edma_chnum < 0) {
+ /* cant setup eDMA */
+ return (ENXIO);
+ };
+
+ return (0);
+};
+
+static int
+setup_dma(struct sc_pcminfo *scp)
+{
+ struct tcd_conf *tcd;
+ struct sc_info *sc;
+
+ sc = scp->sc;
+
+ tcd = malloc(sizeof(struct tcd_conf), M_DEVBUF, M_WAITOK | M_ZERO);
+ tcd->channel = sc->edma_chnum;
+ tcd->ih = sai_dma_intr;
+ tcd->ih_user = scp;
+ tcd->saddr = sc->buf_base_phys;
+ tcd->daddr = rman_get_start(sc->res[0]) + I2S_TDR0;
+
+ /*
+ * Bytes to transfer per each minor loop.
+ * Hardware FIFO buffer size is 32x32bits.
+ */
+ tcd->nbytes = 64;
+
+ tcd->nmajor = 512;
+ tcd->smod = 17; /* dma_size range */
+ tcd->dmod = 0;
+ tcd->esg = 0;
+ tcd->soff = 0x4;
+ tcd->doff = 0;
+ tcd->ssize = 0x2;
+ tcd->dsize = 0x2;
+ tcd->slast = 0;
+ tcd->dlast_sga = 0;
+
+ sc->tcd = tcd;
+
+ sc->edma_sc->dma_setup(sc->edma_sc, sc->tcd);
+
+ return (0);
+}
+
+static int
+saichan_trigger(kobj_t obj, void *data, int go)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_pcminfo *scp = ch->parent;
+ struct sc_info *sc = scp->sc;
+
+ snd_mtxlock(sc->lock);
+
+ switch (go) {
+ case PCMTRIG_START:
+#if 0
+ device_printf(scp->dev, "trigger start\n");
+#endif
+ ch->run = 1;
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+#if 0
+ device_printf(scp->dev, "trigger stop or abort\n");
+#endif
+ ch->run = 0;
+ break;
+ }
+
+ snd_mtxunlock(sc->lock);
+
+ return (0);
+}
+
+static uint32_t
+saichan_getptr(kobj_t obj, void *data)
+{
+ struct sc_pcminfo *scp;
+ struct sc_chinfo *ch;
+ struct sc_info *sc;
+
+ ch = data;
+ scp = ch->parent;
+ sc = scp->sc;
+
+ return (sc->pos);
+}
+
+static uint32_t sai_pfmt[] = {
+ /*
+ * eDMA doesn't allow 24-bit coping,
+ * so we use 32.
+ */
+ SND_FORMAT(AFMT_S32_LE, 2, 0),
+ 0
+};
+
+static struct pcmchan_caps sai_pcaps = {44100, 192000, sai_pfmt, 0};
+
+static struct pcmchan_caps *
+saichan_getcaps(kobj_t obj, void *data)
+{
+
+ return (&sai_pcaps);
+}
+
+static kobj_method_t saichan_methods[] = {
+ KOBJMETHOD(channel_init, saichan_init),
+ KOBJMETHOD(channel_free, saichan_free),
+ KOBJMETHOD(channel_setformat, saichan_setformat),
+ KOBJMETHOD(channel_setspeed, saichan_setspeed),
+ KOBJMETHOD(channel_setblocksize, saichan_setblocksize),
+ KOBJMETHOD(channel_trigger, saichan_trigger),
+ KOBJMETHOD(channel_getptr, saichan_getptr),
+ KOBJMETHOD(channel_getcaps, saichan_getcaps),
+ KOBJMETHOD_END
+};
+CHANNEL_DECLARE(saichan);
+
+static int
+sai_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-sai"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family Synchronous Audio Interface");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static void
+sai_intr(void *arg)
+{
+ struct sc_pcminfo *scp;
+ struct sc_info *sc;
+
+ scp = arg;
+ sc = scp->sc;
+
+ device_printf(sc->dev, "Error I2S_TCSR == 0x%08x\n",
+ READ4(sc, I2S_TCSR));
+}
+
+static void
+setup_sai(struct sc_info *sc)
+{
+ int reg;
+
+ /*
+ * TCR/RCR registers must not be altered when TCSR[TE] is set.
+ */
+
+ reg = READ4(sc, I2S_TCSR);
+ reg &= ~(TCSR_BCE | TCSR_TE | TCSR_FRDE);
+ WRITE4(sc, I2S_TCSR, reg);
+
+ reg = READ4(sc, I2S_TCR3);
+ reg &= ~(TCR3_TCE);
+ WRITE4(sc, I2S_TCR3, reg);
+
+ reg = (64 << TCR1_TFW_S);
+ WRITE4(sc, I2S_TCR1, reg);
+
+ reg = READ4(sc, I2S_TCR2);
+ reg &= ~(TCR2_MSEL_M << TCR2_MSEL_S);
+ reg |= (1 << TCR2_MSEL_S);
+ reg |= (TCR2_BCP | TCR2_BCD);
+ WRITE4(sc, I2S_TCR2, reg);
+
+ sai_configure_clock(sc);
+
+ reg = READ4(sc, I2S_TCR3);
+ reg |= (TCR3_TCE);
+ WRITE4(sc, I2S_TCR3, reg);
+
+ /* Configure to 32-bit I2S mode */
+ reg = READ4(sc, I2S_TCR4);
+ reg &= ~(TCR4_FRSZ_M << TCR4_FRSZ_S);
+ reg |= (1 << TCR4_FRSZ_S); /* 2 words per frame */
+ reg &= ~(TCR4_SYWD_M << TCR4_SYWD_S);
+ reg |= (23 << TCR4_SYWD_S);
+ reg |= (TCR4_MF | TCR4_FSE | TCR4_FSP | TCR4_FSD);
+ WRITE4(sc, I2S_TCR4, reg);
+
+ reg = READ4(sc, I2S_TCR5);
+ reg &= ~(TCR5_W0W_M << TCR5_W0W_S);
+ reg |= (23 << TCR5_W0W_S);
+ reg &= ~(TCR5_WNW_M << TCR5_WNW_S);
+ reg |= (23 << TCR5_WNW_S);
+ reg &= ~(TCR5_FBT_M << TCR5_FBT_S);
+ reg |= (31 << TCR5_FBT_S);
+ WRITE4(sc, I2S_TCR5, reg);
+
+ /* Enable transmitter */
+ reg = READ4(sc, I2S_TCSR);
+ reg |= (TCSR_BCE | TCSR_TE | TCSR_FRDE);
+ reg |= (1 << 10); /* FEIE */
+ WRITE4(sc, I2S_TCSR, reg);
+}
+
+
+static void
+sai_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+
+ addr = (bus_addr_t*)arg;
+ *addr = segs[0].ds_addr;
+}
+
+static int
+sai_attach(device_t dev)
+{
+ char status[SND_STATUSLEN];
+ struct sc_pcminfo *scp;
+ struct sc_info *sc;
+ int err;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->dev = dev;
+ sc->sr = &rate_map[0];
+ sc->pos = 0;
+
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sai softc");
+ if (sc->lock == NULL) {
+ device_printf(dev, "Cant create mtx\n");
+ return (ENXIO);
+ }
+
+ if (bus_alloc_resources(dev, sai_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /* eDMA */
+ if (find_edma_controller(sc)) {
+ device_printf(dev, "could not find active eDMA\n");
+ return (ENXIO);
+ }
+
+ /* Setup PCM */
+ scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ scp->sc = sc;
+ scp->dev = dev;
+
+ /* DMA */
+ sc->dma_size = 131072;
+
+ /*
+ * Must use dma_size boundary as modulo feature required.
+ * Modulo feature allows setup circular buffer.
+ */
+
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev),
+ 4, sc->dma_size, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ sc->dma_size, 1, /* maxsize, nsegments */
+ sc->dma_size, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->dma_tag);
+
+ err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->buf_base,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->dma_map);
+ if (err) {
+ device_printf(dev, "cannot allocate framebuffer\n");
+ return (ENXIO);
+ }
+
+ err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->buf_base,
+ sc->dma_size, sai_dmamap_cb, &sc->buf_base_phys, BUS_DMA_NOWAIT);
+ if (err) {
+ device_printf(dev, "cannot load DMA map\n");
+ return (ENXIO);
+ }
+
+ bzero(sc->buf_base, sc->dma_size);
+
+ /* Setup interrupt handler */
+ err = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_AV,
+ NULL, sai_intr, scp, &sc->ih);
+ if (err) {
+ device_printf(dev, "Unable to alloc interrupt resource.\n");
+ return (ENXIO);
+ }
+
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
+
+ err = pcm_register(dev, scp, 1, 0);
+ if (err) {
+ device_printf(dev, "Can't register pcm.\n");
+ return (ENXIO);
+ }
+
+ scp->chnum = 0;
+ pcm_addchan(dev, PCMDIR_PLAY, &saichan_class, scp);
+ scp->chnum++;
+
+ snprintf(status, SND_STATUSLEN, "at simplebus");
+ pcm_setstatus(dev, status);
+
+ mixer_init(dev, &saimixer_class, scp);
+
+ setup_dma(scp);
+ setup_sai(sc);
+
+ return (0);
+}
+
+static device_method_t sai_pcm_methods[] = {
+ DEVMETHOD(device_probe, sai_probe),
+ DEVMETHOD(device_attach, sai_attach),
+ { 0, 0 }
+};
+
+static driver_t sai_pcm_driver = {
+ "pcm",
+ sai_pcm_methods,
+ PCM_SOFTC_SIZE,
+};
+
+DRIVER_MODULE(sai, simplebus, sai_pcm_driver, pcm_devclass, 0, 0);
+MODULE_DEPEND(sai, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
+MODULE_VERSION(sai, 1);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_sai.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_src.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_src.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_src.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,151 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family System Reset Controller (SRC)
+ * Chapter 18, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_src.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_src.h>
+#include <arm/freescale/vybrid/vf_common.h>
+
+#define SRC_SCR 0x00 /* SRC Control Register */
+#define SRC_SBMR1 0x04 /* SRC Boot Mode Register 1 */
+#define SRC_SRSR 0x08 /* SRC Status Register */
+#define SRC_SECR 0x0C /* SRC_SECR */
+#define SRC_SICR 0x14 /* SRC Reset Interrupt Configuration Register */
+#define SRC_SIMR 0x18 /* SRC Interrupt Masking Register */
+#define SRC_SBMR2 0x1C /* SRC Boot Mode Register 2 */
+#define SRC_GPR0 0x20 /* General Purpose Register */
+#define SRC_GPR1 0x24 /* General Purpose Register */
+#define SRC_GPR2 0x28 /* General Purpose Register */
+#define SRC_GPR3 0x2C /* General Purpose Register */
+#define SRC_GPR4 0x30 /* General Purpose Register */
+#define SRC_MISC0 0x4C /* MISC0 */
+#define SRC_MISC1 0x50 /* MISC1 */
+#define SRC_MISC2 0x54 /* MISC2 */
+#define SRC_MISC3 0x58 /* MISC3 */
+
+struct src_softc {
+ struct resource *res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+struct src_softc *src_sc;
+
+static struct resource_spec src_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+int
+src_swreset(void)
+{
+
+ if (src_sc == NULL)
+ return (1);
+
+ WRITE4(src_sc, SRC_SCR, SW_RST);
+
+ return (0);
+}
+
+static int
+src_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-src"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family System Reset Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+src_attach(device_t dev)
+{
+ struct src_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, src_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ src_sc = sc;
+
+ return (0);
+}
+
+static device_method_t src_methods[] = {
+ DEVMETHOD(device_probe, src_probe),
+ DEVMETHOD(device_attach, src_attach),
+ { 0, 0 }
+};
+
+static driver_t src_driver = {
+ "src",
+ src_methods,
+ sizeof(struct src_softc),
+};
+
+static devclass_t src_devclass;
+
+DRIVER_MODULE(src, simplebus, src_driver, src_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_src.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_src.h
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_src.h (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_src.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,31 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_src.h 258057 2013-11-12 18:02:56Z br $
+ */
+
+#define SW_RST (1 << 12) /* Software reset */
+int src_swreset(void);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_src.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_tcon.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_tcon.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_tcon.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,139 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Timing Controller (TCON)
+ * Chapter 58, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_tcon.c 266155 2014-05-15 16:23:24Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_common.h>
+
+#define TCON0_CTRL1 0x00
+#define TCON_BYPASS (1 << 29)
+
+struct tcon_softc {
+ struct resource *res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+struct tcon_softc *tcon_sc;
+
+static struct resource_spec tcon_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+uint32_t
+tcon_bypass(void)
+{
+ struct tcon_softc *sc;
+
+ if (tcon_sc == NULL)
+ return (1);
+
+ sc = tcon_sc;
+
+ WRITE4(tcon_sc, TCON0_CTRL1, TCON_BYPASS);
+
+ return (0);
+}
+
+static int
+tcon_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,mvf600-tcon"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Vybrid Family Timing Controller (TCON)");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tcon_attach(device_t dev)
+{
+ struct tcon_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, tcon_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ tcon_sc = sc;
+
+ return (0);
+}
+
+static device_method_t tcon_methods[] = {
+ DEVMETHOD(device_probe, tcon_probe),
+ DEVMETHOD(device_attach, tcon_attach),
+ { 0, 0 }
+};
+
+static driver_t tcon_driver = {
+ "tcon",
+ tcon_methods,
+ sizeof(struct tcon_softc),
+};
+
+static devclass_t tcon_devclass;
+
+DRIVER_MODULE(tcon, simplebus, tcon_driver, tcon_devclass, 0, 0);
Property changes on: trunk/sys/arm/freescale/vybrid/vf_tcon.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/freescale/vybrid/vf_uart.c
===================================================================
--- trunk/sys/arm/freescale/vybrid/vf_uart.c (rev 0)
+++ trunk/sys/arm/freescale/vybrid/vf_uart.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,517 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Universal Asynchronous Receiver/Transmitter
+ * Chapter 49, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_uart.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kdb.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+
+#include "uart_if.h"
+
+#define UART_BDH 0x00 /* Baud Rate Registers: High */
+#define UART_BDL 0x01 /* Baud Rate Registers: Low */
+#define UART_C1 0x02 /* Control Register 1 */
+#define UART_C2 0x03 /* Control Register 2 */
+#define UART_S1 0x04 /* Status Register 1 */
+#define UART_S2 0x05 /* Status Register 2 */
+#define UART_C3 0x06 /* Control Register 3 */
+#define UART_D 0x07 /* Data Register */
+#define UART_MA1 0x08 /* Match Address Registers 1 */
+#define UART_MA2 0x09 /* Match Address Registers 2 */
+#define UART_C4 0x0A /* Control Register 4 */
+#define UART_C5 0x0B /* Control Register 5 */
+#define UART_ED 0x0C /* Extended Data Register */
+#define UART_MODEM 0x0D /* Modem Register */
+#define UART_IR 0x0E /* Infrared Register */
+#define UART_PFIFO 0x10 /* FIFO Parameters */
+#define UART_CFIFO 0x11 /* FIFO Control Register */
+#define UART_SFIFO 0x12 /* FIFO Status Register */
+#define UART_TWFIFO 0x13 /* FIFO Transmit Watermark */
+#define UART_TCFIFO 0x14 /* FIFO Transmit Count */
+#define UART_RWFIFO 0x15 /* FIFO Receive Watermark */
+#define UART_RCFIFO 0x16 /* FIFO Receive Count */
+#define UART_C7816 0x18 /* 7816 Control Register */
+#define UART_IE7816 0x19 /* 7816 Interrupt Enable Register */
+#define UART_IS7816 0x1A /* 7816 Interrupt Status Register */
+#define UART_WP7816T0 0x1B /* 7816 Wait Parameter Register */
+#define UART_WP7816T1 0x1B /* 7816 Wait Parameter Register */
+#define UART_WN7816 0x1C /* 7816 Wait N Register */
+#define UART_WF7816 0x1D /* 7816 Wait FD Register */
+#define UART_ET7816 0x1E /* 7816 Error Threshold Register */
+#define UART_TL7816 0x1F /* 7816 Transmit Length Register */
+#define UART_C6 0x21 /* CEA709.1-B Control Register 6 */
+#define UART_PCTH 0x22 /* CEA709.1-B Packet Cycle Time Counter High */
+#define UART_PCTL 0x23 /* CEA709.1-B Packet Cycle Time Counter Low */
+#define UART_B1T 0x24 /* CEA709.1-B Beta1 Timer */
+#define UART_SDTH 0x25 /* CEA709.1-B Secondary Delay Timer High */
+#define UART_SDTL 0x26 /* CEA709.1-B Secondary Delay Timer Low */
+#define UART_PRE 0x27 /* CEA709.1-B Preamble */
+#define UART_TPL 0x28 /* CEA709.1-B Transmit Packet Length */
+#define UART_IE 0x29 /* CEA709.1-B Interrupt Enable Register */
+#define UART_WB 0x2A /* CEA709.1-B WBASE */
+#define UART_S3 0x2B /* CEA709.1-B Status Register */
+#define UART_S4 0x2C /* CEA709.1-B Status Register */
+#define UART_RPL 0x2D /* CEA709.1-B Received Packet Length */
+#define UART_RPREL 0x2E /* CEA709.1-B Received Preamble Length */
+#define UART_CPW 0x2F /* CEA709.1-B Collision Pulse Width */
+#define UART_RIDT 0x30 /* CEA709.1-B Receive Indeterminate Time */
+#define UART_TIDT 0x31 /* CEA709.1-B Transmit Indeterminate Time */
+
+#define UART_C2_TE (1 << 3) /* Transmitter Enable */
+#define UART_C2_TIE (1 << 7) /* Transmitter Interrupt Enable */
+#define UART_C2_RE (1 << 2) /* Receiver Enable */
+#define UART_C2_RIE (1 << 5) /* Receiver Interrupt Enable */
+#define UART_S1_TDRE (1 << 7) /* Transmit Data Register Empty Flag */
+#define UART_S1_RDRF (1 << 5) /* Receive Data Register Full Flag */
+#define UART_S2_LBKDIF (1 << 7) /* LIN Break Detect Interrupt Flag */
+
+#define UART_C4_BRFA 0x1f /* Baud Rate Fine Adjust */
+#define UART_BDH_SBR 0x1f /* UART Baud Rate Bits */
+
+/*
+ * Low-level UART interface.
+ */
+static int vf_uart_probe(struct uart_bas *bas);
+static void vf_uart_init(struct uart_bas *bas, int, int, int, int);
+static void vf_uart_term(struct uart_bas *bas);
+static void vf_uart_putc(struct uart_bas *bas, int);
+static int vf_uart_rxready(struct uart_bas *bas);
+static int vf_uart_getc(struct uart_bas *bas, struct mtx *);
+
+void uart_reinit(struct uart_softc *,int,int);
+
+static struct uart_ops uart_vybrid_ops = {
+ .probe = vf_uart_probe,
+ .init = vf_uart_init,
+ .term = vf_uart_term,
+ .putc = vf_uart_putc,
+ .rxready = vf_uart_rxready,
+ .getc = vf_uart_getc,
+};
+
+static int
+vf_uart_probe(struct uart_bas *bas)
+{
+
+ return (0);
+}
+
+static void
+vf_uart_init(struct uart_bas *bas, int baudrate, int databits,
+ int stopbits, int parity)
+{
+
+}
+
+static void
+vf_uart_term(struct uart_bas *bas)
+{
+
+}
+
+static void
+vf_uart_putc(struct uart_bas *bas, int c)
+{
+
+ while (!(uart_getreg(bas, UART_S1) & UART_S1_TDRE))
+ ;
+
+ uart_setreg(bas, UART_D, c);
+}
+
+static int
+vf_uart_rxready(struct uart_bas *bas)
+{
+ int usr1;
+
+ usr1 = uart_getreg(bas, UART_S1);
+ if (usr1 & UART_S1_RDRF) {
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+vf_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
+{
+ int c;
+
+ uart_lock(hwmtx);
+
+ while (!(uart_getreg(bas, UART_S1) & UART_S1_RDRF))
+ ;
+
+ c = uart_getreg(bas, UART_D);
+ uart_unlock(hwmtx);
+
+ return (c & 0xff);
+}
+
+/*
+ * High-level UART interface.
+ */
+struct vf_uart_softc {
+ struct uart_softc base;
+};
+
+void
+uart_reinit(struct uart_softc *sc, int clkspeed, int baud)
+{
+ struct uart_bas *bas;
+ int sbr;
+ int brfa;
+ int reg;
+
+ bas = &sc->sc_bas;
+ if (!bas) {
+ printf("Error: cant reconfigure bas\n");
+ return;
+ }
+
+ uart_setreg(bas, UART_MODEM, 0x00);
+
+ /*
+ * Disable transmitter and receiver
+ * for a while.
+ */
+ reg = uart_getreg(bas, UART_C2);
+ reg &= ~(UART_C2_RE | UART_C2_TE);
+ uart_setreg(bas, UART_C2, 0x00);
+
+ uart_setreg(bas, UART_C1, 0x00);
+
+ sbr = (uint16_t) (clkspeed / (baud * 16));
+ brfa = (clkspeed / baud) - (sbr * 16);
+
+ reg = uart_getreg(bas, UART_BDH);
+ reg &= ~UART_BDH_SBR;
+ reg |= ((sbr & 0x1f00) >> 8);
+ uart_setreg(bas, UART_BDH, reg);
+
+ reg = sbr & 0x00ff;
+ uart_setreg(bas, UART_BDL, reg);
+
+ reg = uart_getreg(bas, UART_C4);
+ reg &= ~UART_C4_BRFA;
+ reg |= (brfa & UART_C4_BRFA);
+ uart_setreg(bas, UART_C4, reg);
+
+ reg = uart_getreg(bas, UART_C2);
+ reg |= (UART_C2_RE | UART_C2_TE);
+ uart_setreg(bas, UART_C2, reg);
+
+}
+
+static int vf_uart_bus_attach(struct uart_softc *);
+static int vf_uart_bus_detach(struct uart_softc *);
+static int vf_uart_bus_flush(struct uart_softc *, int);
+static int vf_uart_bus_getsig(struct uart_softc *);
+static int vf_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int vf_uart_bus_ipend(struct uart_softc *);
+static int vf_uart_bus_param(struct uart_softc *, int, int, int, int);
+static int vf_uart_bus_probe(struct uart_softc *);
+static int vf_uart_bus_receive(struct uart_softc *);
+static int vf_uart_bus_setsig(struct uart_softc *, int);
+static int vf_uart_bus_transmit(struct uart_softc *);
+
+static kobj_method_t vf_uart_methods[] = {
+ KOBJMETHOD(uart_attach, vf_uart_bus_attach),
+ KOBJMETHOD(uart_detach, vf_uart_bus_detach),
+ KOBJMETHOD(uart_flush, vf_uart_bus_flush),
+ KOBJMETHOD(uart_getsig, vf_uart_bus_getsig),
+ KOBJMETHOD(uart_ioctl, vf_uart_bus_ioctl),
+ KOBJMETHOD(uart_ipend, vf_uart_bus_ipend),
+ KOBJMETHOD(uart_param, vf_uart_bus_param),
+ KOBJMETHOD(uart_probe, vf_uart_bus_probe),
+ KOBJMETHOD(uart_receive, vf_uart_bus_receive),
+ KOBJMETHOD(uart_setsig, vf_uart_bus_setsig),
+ KOBJMETHOD(uart_transmit, vf_uart_bus_transmit),
+ { 0, 0 }
+};
+
+static struct uart_class uart_vybrid_class = {
+ "vybrid",
+ vf_uart_methods,
+ sizeof(struct vf_uart_softc),
+ .uc_ops = &uart_vybrid_ops,
+ .uc_range = 0x100,
+ .uc_rclk = 24000000 /* TODO: get value from CCM */
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,mvf600-uart", (uintptr_t)&uart_vybrid_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+
+static int
+vf_uart_bus_attach(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int reg;
+
+ bas = &sc->sc_bas;
+
+ sc->sc_hwiflow = 0;
+ sc->sc_hwoflow = 0;
+
+ uart_reinit(sc, 66000000, 115200);
+
+ reg = uart_getreg(bas, UART_C2);
+ if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
+ reg &= ~UART_C2_RIE;
+ } else {
+ reg |= UART_C2_RIE;
+ }
+ uart_setreg(bas, UART_C2, reg);
+
+ return (0);
+}
+
+static int
+vf_uart_bus_detach(struct uart_softc *sc)
+{
+
+ /* TODO */
+ return (0);
+}
+
+static int
+vf_uart_bus_flush(struct uart_softc *sc, int what)
+{
+
+ /* TODO */
+ return (0);
+}
+
+static int
+vf_uart_bus_getsig(struct uart_softc *sc)
+{
+
+ /* TODO */
+ return (0);
+}
+
+static int
+vf_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+ struct uart_bas *bas;
+ int error;
+
+ bas = &sc->sc_bas;
+ error = 0;
+ uart_lock(sc->sc_hwmtx);
+ switch (request) {
+ case UART_IOCTL_BREAK:
+ /* TODO */
+ break;
+ case UART_IOCTL_BAUD:
+ /* TODO */
+ *(int*)data = 115200;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ uart_unlock(sc->sc_hwmtx);
+
+ return (error);
+}
+
+static int
+vf_uart_bus_ipend(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int ipend;
+ uint32_t usr1, usr2;
+ int reg;
+ int sfifo;
+
+ bas = &sc->sc_bas;
+ ipend = 0;
+
+ uart_lock(sc->sc_hwmtx);
+
+ usr1 = uart_getreg(bas, UART_S1);
+ usr2 = uart_getreg(bas, UART_S2);
+ sfifo = uart_getreg(bas, UART_SFIFO);
+
+ /* ack usr2 */
+ uart_setreg(bas, UART_S2, usr2);
+
+ if (usr1 & UART_S1_TDRE) {
+ reg = uart_getreg(bas, UART_C2);
+ reg &= ~(UART_C2_TIE);
+ uart_setreg(bas, UART_C2, reg);
+
+ if (sc->sc_txbusy != 0) {
+ ipend |= SER_INT_TXIDLE;
+ }
+ }
+
+ if (usr1 & UART_S1_RDRF) {
+ reg = uart_getreg(bas, UART_C2);
+ reg &= ~(UART_C2_RIE);
+ uart_setreg(bas, UART_C2, reg);
+
+ ipend |= SER_INT_RXREADY;
+ }
+
+ if (usr2 & UART_S2_LBKDIF) {
+ ipend |= SER_INT_BREAK;
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (ipend);
+}
+
+static int
+vf_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+
+ uart_lock(sc->sc_hwmtx);
+ vf_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity);
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static int
+vf_uart_bus_probe(struct uart_softc *sc)
+{
+ int error;
+
+ error = vf_uart_probe(&sc->sc_bas);
+ if (error)
+ return (error);
+
+ sc->sc_rxfifosz = 1;
+ sc->sc_txfifosz = 1;
+
+ device_set_desc(sc->sc_dev, "Vybrid Family UART");
+ return (0);
+}
+
+static int
+vf_uart_bus_receive(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int reg;
+ int c;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+
+ /* Read FIFO */
+ while (uart_getreg(bas, UART_S1) & UART_S1_RDRF) {
+ if (uart_rx_full(sc)) {
+ /* No space left in input buffer */
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+ break;
+ }
+
+ c = uart_getreg(bas, UART_D);
+ uart_rx_put(sc, c);
+ }
+
+ /* Reenable Data Ready interrupt */
+ reg = uart_getreg(bas, UART_C2);
+ reg |= (UART_C2_RIE);
+ uart_setreg(bas, UART_C2, reg);
+
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+static int
+vf_uart_bus_setsig(struct uart_softc *sc, int sig)
+{
+ struct uart_bas *bas;
+ int reg;
+
+ /* TODO: implement (?) */
+
+ /* XXX workaround to have working console on mount prompt */
+ /* Enable RX interrupt */
+ bas = &sc->sc_bas;
+ if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
+ reg = uart_getreg(bas, UART_C2);
+ reg |= (UART_C2_RIE);
+ uart_setreg(bas, UART_C2, reg);
+ }
+
+ return (0);
+}
+
+static int
+vf_uart_bus_transmit(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+ int i;
+ int reg;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+
+ /* Fill TX FIFO */
+ for (i = 0; i < sc->sc_txdatasz; i++) {
+ uart_setreg(bas, UART_D, sc->sc_txbuf[i] & 0xff);
+ uart_barrier(&sc->sc_bas);
+ }
+
+ sc->sc_txbusy = 1;
+
+ /* Call me when ready */
+ reg = uart_getreg(bas, UART_C2);
+ reg |= (UART_C2_TIE);
+ uart_setreg(bas, UART_C2, reg);
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
Property changes on: trunk/sys/arm/freescale/vybrid/vf_uart.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/_align.h
===================================================================
--- trunk/sys/arm/include/_align.h (rev 0)
+++ trunk/sys/arm/include/_align.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,53 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)param.h 5.8 (Berkeley) 6/28/91
+ * $FreeBSD: stable/10/sys/arm/include/_align.h 196994 2009-09-08 20:45:40Z phk $
+ */
+
+#ifndef _ARM_INCLUDE__ALIGN_H_
+#define _ARM_INCLUDE__ALIGN_H_
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value
+ * for all data types (int, long, ...). The result is unsigned int
+ * and must be cast to any desired pointer type.
+ */
+#define _ALIGNBYTES (sizeof(int) - 1)
+#define _ALIGN(p) (((unsigned)(p) + _ALIGNBYTES) & ~_ALIGNBYTES)
+
+#endif /* !_ARM_INCLUDE__ALIGN_H_ */
Property changes on: trunk/sys/arm/include/_align.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/_bus.h
===================================================================
--- trunk/sys/arm/include/_bus.h (rev 0)
+++ trunk/sys/arm/include/_bus.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,47 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 M. Warner Losh.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/_bus.h 176589 2008-02-26 11:45:32Z rwatson $
+ */
+
+#ifndef ARM_INCLUDE__BUS_H
+#define ARM_INCLUDE__BUS_H
+
+/*
+ * Addresses (in bus space).
+ */
+typedef u_long bus_addr_t;
+typedef u_long bus_size_t;
+
+/*
+ * Access methods for bus space.
+ */
+typedef struct bus_space *bus_space_tag_t;
+typedef u_long bus_space_handle_t;
+
+#endif /* ARM_INCLUDE__BUS_H */
Property changes on: trunk/sys/arm/include/_bus.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/_inttypes.h
===================================================================
--- trunk/sys/arm/include/_inttypes.h (rev 0)
+++ trunk/sys/arm/include/_inttypes.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,214 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * From: $NetBSD: int_fmtio.h,v 1.2 2001/04/26 16:25:21 kleink Exp $
+ * $FreeBSD: stable/10/sys/arm/include/_inttypes.h 203974 2010-02-16 21:59:17Z imp $
+ */
+
+#ifndef _MACHINE_INTTYPES_H_
+#define _MACHINE_INTTYPES_H_
+
+/*
+ * Macros for format specifiers.
+ */
+
+/* fprintf(3) macros for signed integers. */
+
+#define PRId8 "d" /* int8_t */
+#define PRId16 "d" /* int16_t */
+#define PRId32 "d" /* int32_t */
+#define PRId64 "lld" /* int64_t */
+#define PRIdLEAST8 "d" /* int_least8_t */
+#define PRIdLEAST16 "d" /* int_least16_t */
+#define PRIdLEAST32 "d" /* int_least32_t */
+#define PRIdLEAST64 "lld" /* int_least64_t */
+#define PRIdFAST8 "d" /* int_fast8_t */
+#define PRIdFAST16 "d" /* int_fast16_t */
+#define PRIdFAST32 "d" /* int_fast32_t */
+#define PRIdFAST64 "lld" /* int_fast64_t */
+#define PRIdMAX "jd" /* intmax_t */
+#define PRIdPTR "d" /* intptr_t */
+
+#define PRIi8 "i" /* int8_t */
+#define PRIi16 "i" /* int16_t */
+#define PRIi32 "i" /* int32_t */
+#define PRIi64 "lli" /* int64_t */
+#define PRIiLEAST8 "i" /* int_least8_t */
+#define PRIiLEAST16 "i" /* int_least16_t */
+#define PRIiLEAST32 "i" /* int_least32_t */
+#define PRIiLEAST64 "lli" /* int_least64_t */
+#define PRIiFAST8 "i" /* int_fast8_t */
+#define PRIiFAST16 "i" /* int_fast16_t */
+#define PRIiFAST32 "i" /* int_fast32_t */
+#define PRIiFAST64 "lli" /* int_fast64_t */
+#define PRIiMAX "ji" /* intmax_t */
+#define PRIiPTR "i" /* intptr_t */
+
+/* fprintf(3) macros for unsigned integers. */
+
+#define PRIo8 "o" /* uint8_t */
+#define PRIo16 "o" /* uint16_t */
+#define PRIo32 "o" /* uint32_t */
+#define PRIo64 "llo" /* uint64_t */
+#define PRIoLEAST8 "o" /* uint_least8_t */
+#define PRIoLEAST16 "o" /* uint_least16_t */
+#define PRIoLEAST32 "o" /* uint_least32_t */
+#define PRIoLEAST64 "llo" /* uint_least64_t */
+#define PRIoFAST8 "o" /* uint_fast8_t */
+#define PRIoFAST16 "o" /* uint_fast16_t */
+#define PRIoFAST32 "o" /* uint_fast32_t */
+#define PRIoFAST64 "llo" /* uint_fast64_t */
+#define PRIoMAX "jo" /* uintmax_t */
+#define PRIoPTR "o" /* uintptr_t */
+
+#define PRIu8 "u" /* uint8_t */
+#define PRIu16 "u" /* uint16_t */
+#define PRIu32 "u" /* uint32_t */
+#define PRIu64 "llu" /* uint64_t */
+#define PRIuLEAST8 "u" /* uint_least8_t */
+#define PRIuLEAST16 "u" /* uint_least16_t */
+#define PRIuLEAST32 "u" /* uint_least32_t */
+#define PRIuLEAST64 "llu" /* uint_least64_t */
+#define PRIuFAST8 "u" /* uint_fast8_t */
+#define PRIuFAST16 "u" /* uint_fast16_t */
+#define PRIuFAST32 "u" /* uint_fast32_t */
+#define PRIuFAST64 "llu" /* uint_fast64_t */
+#define PRIuMAX "ju" /* uintmax_t */
+#define PRIuPTR "u" /* uintptr_t */
+
+#define PRIx8 "x" /* uint8_t */
+#define PRIx16 "x" /* uint16_t */
+#define PRIx32 "x" /* uint32_t */
+#define PRIx64 "llx" /* uint64_t */
+#define PRIxLEAST8 "x" /* uint_least8_t */
+#define PRIxLEAST16 "x" /* uint_least16_t */
+#define PRIxLEAST32 "x" /* uint_least32_t */
+#define PRIxLEAST64 "llx" /* uint_least64_t */
+#define PRIxFAST8 "x" /* uint_fast8_t */
+#define PRIxFAST16 "x" /* uint_fast16_t */
+#define PRIxFAST32 "x" /* uint_fast32_t */
+#define PRIxFAST64 "llx" /* uint_fast64_t */
+#define PRIxMAX "jx" /* uintmax_t */
+#define PRIxPTR "x" /* uintptr_t */
+
+#define PRIX8 "X" /* uint8_t */
+#define PRIX16 "X" /* uint16_t */
+#define PRIX32 "X" /* uint32_t */
+#define PRIX64 "llX" /* uint64_t */
+#define PRIXLEAST8 "X" /* uint_least8_t */
+#define PRIXLEAST16 "X" /* uint_least16_t */
+#define PRIXLEAST32 "X" /* uint_least32_t */
+#define PRIXLEAST64 "llX" /* uint_least64_t */
+#define PRIXFAST8 "X" /* uint_fast8_t */
+#define PRIXFAST16 "X" /* uint_fast16_t */
+#define PRIXFAST32 "X" /* uint_fast32_t */
+#define PRIXFAST64 "llX" /* uint_fast64_t */
+#define PRIXMAX "jX" /* uintmax_t */
+#define PRIXPTR "X" /* uintptr_t */
+
+/* fscanf(3) macros for signed integers. */
+
+#define SCNd8 "hhd" /* int8_t */
+#define SCNd16 "hd" /* int16_t */
+#define SCNd32 "d" /* int32_t */
+#define SCNd64 "lld" /* int64_t */
+#define SCNdLEAST8 "hhd" /* int_least8_t */
+#define SCNdLEAST16 "hd" /* int_least16_t */
+#define SCNdLEAST32 "d" /* int_least32_t */
+#define SCNdLEAST64 "lld" /* int_least64_t */
+#define SCNdFAST8 "d" /* int_fast8_t */
+#define SCNdFAST16 "d" /* int_fast16_t */
+#define SCNdFAST32 "d" /* int_fast32_t */
+#define SCNdFAST64 "lld" /* int_fast64_t */
+#define SCNdMAX "jd" /* intmax_t */
+#define SCNdPTR "d" /* intptr_t */
+
+#define SCNi8 "hhi" /* int8_t */
+#define SCNi16 "hi" /* int16_t */
+#define SCNi32 "i" /* int32_t */
+#define SCNi64 "lli" /* int64_t */
+#define SCNiLEAST8 "hhi" /* int_least8_t */
+#define SCNiLEAST16 "hi" /* int_least16_t */
+#define SCNiLEAST32 "i" /* int_least32_t */
+#define SCNiLEAST64 "lli" /* int_least64_t */
+#define SCNiFAST8 "i" /* int_fast8_t */
+#define SCNiFAST16 "i" /* int_fast16_t */
+#define SCNiFAST32 "i" /* int_fast32_t */
+#define SCNiFAST64 "lli" /* int_fast64_t */
+#define SCNiMAX "ji" /* intmax_t */
+#define SCNiPTR "i" /* intptr_t */
+
+/* fscanf(3) macros for unsigned integers. */
+
+#define SCNo8 "hho" /* uint8_t */
+#define SCNo16 "ho" /* uint16_t */
+#define SCNo32 "o" /* uint32_t */
+#define SCNo64 "llo" /* uint64_t */
+#define SCNoLEAST8 "hho" /* uint_least8_t */
+#define SCNoLEAST16 "ho" /* uint_least16_t */
+#define SCNoLEAST32 "o" /* uint_least32_t */
+#define SCNoLEAST64 "llo" /* uint_least64_t */
+#define SCNoFAST8 "o" /* uint_fast8_t */
+#define SCNoFAST16 "o" /* uint_fast16_t */
+#define SCNoFAST32 "o" /* uint_fast32_t */
+#define SCNoFAST64 "llo" /* uint_fast64_t */
+#define SCNoMAX "jo" /* uintmax_t */
+#define SCNoPTR "o" /* uintptr_t */
+
+#define SCNu8 "hhu" /* uint8_t */
+#define SCNu16 "hu" /* uint16_t */
+#define SCNu32 "u" /* uint32_t */
+#define SCNu64 "llu" /* uint64_t */
+#define SCNuLEAST8 "hhu" /* uint_least8_t */
+#define SCNuLEAST16 "hu" /* uint_least16_t */
+#define SCNuLEAST32 "u" /* uint_least32_t */
+#define SCNuLEAST64 "llu" /* uint_least64_t */
+#define SCNuFAST8 "u" /* uint_fast8_t */
+#define SCNuFAST16 "u" /* uint_fast16_t */
+#define SCNuFAST32 "u" /* uint_fast32_t */
+#define SCNuFAST64 "llu" /* uint_fast64_t */
+#define SCNuMAX "ju" /* uintmax_t */
+#define SCNuPTR "u" /* uintptr_t */
+
+#define SCNx8 "hhx" /* uint8_t */
+#define SCNx16 "hx" /* uint16_t */
+#define SCNx32 "x" /* uint32_t */
+#define SCNx64 "llx" /* uint64_t */
+#define SCNxLEAST8 "hhx" /* uint_least8_t */
+#define SCNxLEAST16 "hx" /* uint_least16_t */
+#define SCNxLEAST32 "x" /* uint_least32_t */
+#define SCNxLEAST64 "llx" /* uint_least64_t */
+#define SCNxFAST8 "x" /* uint_fast8_t */
+#define SCNxFAST16 "x" /* uint_fast16_t */
+#define SCNxFAST32 "x" /* uint_fast32_t */
+#define SCNxFAST64 "llx" /* uint_fast64_t */
+#define SCNxMAX "jx" /* uintmax_t */
+#define SCNxPTR "x" /* uintptr_t */
+
+#endif /* !_MACHINE_INTTYPES_H_ */
Property changes on: trunk/sys/arm/include/_inttypes.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/_limits.h
===================================================================
--- trunk/sys/arm/include/_limits.h (rev 0)
+++ trunk/sys/arm/include/_limits.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,88 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)limits.h 8.3 (Berkeley) 1/4/94
+ * $FreeBSD: stable/10/sys/arm/include/_limits.h 217145 2011-01-08 11:13:34Z tijl $
+ */
+
+#ifndef _MACHINE__LIMITS_H_
+#define _MACHINE__LIMITS_H_
+
+/*
+ * According to ANSI (section 2.2.4.2), the values below must be usable by
+ * #if preprocessing directives. Additionally, the expression must have the
+ * same type as would an expression that is an object of the corresponding
+ * type converted according to the integral promotions. The subtraction for
+ * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an
+ * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2).
+ */
+
+#define __CHAR_BIT 8 /* number of bits in a char */
+
+#define __SCHAR_MAX 0x7f /* max value for a signed char */
+#define __SCHAR_MIN (-0x7f - 1) /* min value for a signed char */
+
+#define __UCHAR_MAX 0xff /* max value for an unsigned char */
+
+#define __USHRT_MAX 0xffff /* max value for an unsigned short */
+#define __SHRT_MAX 0x7fff /* max value for a short */
+#define __SHRT_MIN (-0x7fff - 1) /* min value for a short */
+
+#define __UINT_MAX 0xffffffff /* max value for an unsigned int */
+#define __INT_MAX 0x7fffffff /* max value for an int */
+#define __INT_MIN (-0x7fffffff - 1) /* min value for an int */
+
+#define __ULONG_MAX 0xffffffffUL /* max value for an unsigned long */
+#define __LONG_MAX 0x7fffffffL /* max value for a long */
+#define __LONG_MIN (-0x7fffffffL - 1) /* min value for a long */
+
+ /* max value for an unsigned long long */
+#define __ULLONG_MAX 0xffffffffffffffffULL
+#define __LLONG_MAX 0x7fffffffffffffffLL /* max value for a long long */
+#define __LLONG_MIN (-0x7fffffffffffffffLL - 1) /* min for a long long */
+
+#define __SSIZE_MAX __INT_MAX /* max value for a ssize_t */
+
+#define __SIZE_T_MAX __UINT_MAX /* max value for a size_t */
+
+#define __OFF_MAX __LLONG_MAX /* max value for a off_t */
+#define __OFF_MIN __LLONG_MIN /* min value for a off_t */
+
+/* Quads and long longs are the same size. Ensure they stay in sync. */
+#define __UQUAD_MAX __ULLONG_MAX /* max value for a uquad_t */
+#define __QUAD_MAX __LLONG_MAX /* max value for a quad_t */
+#define __QUAD_MIN __LLONG_MIN /* min value for a quad_t */
+
+#define __LONG_BIT 32
+#define __WORD_BIT 32
+
+/* Minimum signal stack size. */
+#define __MINSIGSTKSZ (1024 * 4)
+
+#endif /* !_MACHINE__LIMITS_H_ */
Property changes on: trunk/sys/arm/include/_limits.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/_stdint.h
===================================================================
--- trunk/sys/arm/include/_stdint.h (rev 0)
+++ trunk/sys/arm/include/_stdint.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,159 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001, 2002 Mike Barcroft <mike at FreeBSD.org>
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/_stdint.h 237517 2012-06-24 04:15:58Z andrew $
+ */
+
+#ifndef _MACHINE__STDINT_H_
+#define _MACHINE__STDINT_H_
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS)
+
+#define INT8_C(c) (c)
+#define INT16_C(c) (c)
+#define INT32_C(c) (c)
+#define INT64_C(c) (c ## LL)
+
+#define UINT8_C(c) (c)
+#define UINT16_C(c) (c)
+#define UINT32_C(c) (c ## U)
+#define UINT64_C(c) (c ## ULL)
+
+#define INTMAX_C(c) INT64_C(c)
+#define UINTMAX_C(c) UINT64_C(c)
+
+#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.1 Limits of exact-width integer types
+ */
+/* Minimum values of exact-width signed integer types. */
+#define INT8_MIN (-0x7f-1)
+#define INT16_MIN (-0x7fff-1)
+#define INT32_MIN (-0x7fffffff-1)
+#define INT64_MIN (-0x7fffffffffffffffLL-1)
+
+/* Maximum values of exact-width signed integer types. */
+#define INT8_MAX 0x7f
+#define INT16_MAX 0x7fff
+#define INT32_MAX 0x7fffffff
+#define INT64_MAX 0x7fffffffffffffffLL
+
+/* Maximum values of exact-width unsigned integer types. */
+#define UINT8_MAX 0xff
+#define UINT16_MAX 0xffff
+#define UINT32_MAX 0xffffffffU
+#define UINT64_MAX 0xffffffffffffffffULL
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.2 Limits of minimum-width integer types
+ */
+/* Minimum values of minimum-width signed integer types. */
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST64_MIN INT64_MIN
+
+/* Maximum values of minimum-width signed integer types. */
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MAX INT64_MAX
+
+/* Maximum values of minimum-width unsigned integer types. */
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.3 Limits of fastest minimum-width integer types
+ */
+/* Minimum values of fastest minimum-width signed integer types. */
+#define INT_FAST8_MIN INT32_MIN
+#define INT_FAST16_MIN INT32_MIN
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST64_MIN INT64_MIN
+
+/* Maximum values of fastest minimum-width signed integer types. */
+#define INT_FAST8_MAX INT32_MAX
+#define INT_FAST16_MAX INT32_MAX
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MAX INT64_MAX
+
+/* Maximum values of fastest minimum-width unsigned integer types. */
+#define UINT_FAST8_MAX UINT32_MAX
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.4 Limits of integer types capable of holding object pointers
+ */
+#define INTPTR_MIN INT32_MIN
+#define INTPTR_MAX INT32_MAX
+#define UINTPTR_MAX UINT32_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.5 Limits of greatest-width integer types
+ */
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.3 Limits of other integer types
+ */
+/* Limits of ptrdiff_t. */
+#define PTRDIFF_MIN INT32_MIN
+#define PTRDIFF_MAX INT32_MAX
+
+/* Limits of sig_atomic_t. */
+#define SIG_ATOMIC_MIN INT32_MIN
+#define SIG_ATOMIC_MAX INT32_MAX
+
+/* Limit of size_t. */
+#define SIZE_MAX UINT32_MAX
+
+/* Limits of wint_t. */
+#define WINT_MIN INT32_MIN
+#define WINT_MAX INT32_MAX
+
+#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */
+
+#endif /* !_MACHINE__STDINT_H_ */
Property changes on: trunk/sys/arm/include/_stdint.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/_types.h
===================================================================
--- trunk/sys/arm/include/_types.h (rev 0)
+++ trunk/sys/arm/include/_types.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,133 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike at FreeBSD.org>
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94
+ * From: @(#)types.h 8.3 (Berkeley) 1/5/94
+ * $FreeBSD: stable/10/sys/arm/include/_types.h 264496 2014-04-15 09:41:52Z tijl $
+ */
+
+#ifndef _MACHINE__TYPES_H_
+#define _MACHINE__TYPES_H_
+
+#ifndef _SYS_CDEFS_H_
+#error this file needs sys/cdefs.h as a prerequisite
+#endif
+
+/*
+ * Basic types upon which most other types are built.
+ */
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef short __int16_t;
+typedef unsigned short __uint16_t;
+typedef int __int32_t;
+typedef unsigned int __uint32_t;
+#ifndef lint
+__extension__
+#endif
+/* LONGLONG */
+typedef long long __int64_t;
+#ifndef lint
+__extension__
+#endif
+/* LONGLONG */
+typedef unsigned long long __uint64_t;
+
+/*
+ * Standard type definitions.
+ */
+typedef __uint32_t __clock_t; /* clock()... */
+typedef __int32_t __critical_t;
+typedef double __double_t;
+typedef float __float_t;
+typedef __int32_t __intfptr_t;
+typedef __int64_t __intmax_t;
+typedef __int32_t __intptr_t;
+typedef __int32_t __int_fast8_t;
+typedef __int32_t __int_fast16_t;
+typedef __int32_t __int_fast32_t;
+typedef __int64_t __int_fast64_t;
+typedef __int8_t __int_least8_t;
+typedef __int16_t __int_least16_t;
+typedef __int32_t __int_least32_t;
+typedef __int64_t __int_least64_t;
+typedef __int32_t __ptrdiff_t; /* ptr1 - ptr2 */
+typedef __int32_t __register_t;
+typedef __int32_t __segsz_t; /* segment size (in pages) */
+typedef __uint32_t __size_t; /* sizeof() */
+typedef __int32_t __ssize_t; /* byte count or error */
+typedef __int64_t __time_t; /* time()... */
+typedef __uint32_t __uintfptr_t;
+typedef __uint64_t __uintmax_t;
+typedef __uint32_t __uintptr_t;
+typedef __uint32_t __uint_fast8_t;
+typedef __uint32_t __uint_fast16_t;
+typedef __uint32_t __uint_fast32_t;
+typedef __uint64_t __uint_fast64_t;
+typedef __uint8_t __uint_least8_t;
+typedef __uint16_t __uint_least16_t;
+typedef __uint32_t __uint_least32_t;
+typedef __uint64_t __uint_least64_t;
+typedef __uint32_t __u_register_t;
+typedef __uint32_t __vm_offset_t;
+typedef __int64_t __vm_ooffset_t;
+typedef __uint32_t __vm_paddr_t;
+typedef __uint64_t __vm_pindex_t;
+typedef __uint32_t __vm_size_t;
+
+#ifdef __ARM_EABI__
+typedef unsigned int ___wchar_t;
+#define __WCHAR_MIN 0 /* min value for a wchar_t */
+#define __WCHAR_MAX __UINT_MAX /* max value for a wchar_t */
+#else
+typedef int ___wchar_t;
+#define __WCHAR_MIN __INT_MIN /* min value for a wchar_t */
+#define __WCHAR_MAX __INT_MAX /* max value for a wchar_t */
+#endif
+
+/*
+ * Unusual type definitions.
+ */
+#ifdef __GNUCLIKE_BUILTIN_VARARGS
+typedef __builtin_va_list __va_list; /* internally known to gcc */
+#else
+typedef char * __va_list;
+#endif /* __GNUCLIKE_BUILTIN_VARARGS */
+#if defined(__GNUCLIKE_BUILTIN_VAALIST) && !defined(__GNUC_VA_LIST) \
+ && !defined(__NO_GNUC_VA_LIST)
+#define __GNUC_VA_LIST
+typedef __va_list __gnuc_va_list; /* compatibility w/GNU headers*/
+#endif
+
+#endif /* !_MACHINE__TYPES_H_ */
Property changes on: trunk/sys/arm/include/_types.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/acle-compat.h
===================================================================
--- trunk/sys/arm/include/acle-compat.h (rev 0)
+++ trunk/sys/arm/include/acle-compat.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,186 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2014 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/acle-compat.h 273827 2014-10-29 16:24:02Z andrew $
+ */
+
+#ifndef __ARM_ARCH
+
+/* ACLE standardises a set of pre-defines that describe the ARM architecture.
+ These were mostly implemented in GCC around GCC-4.8; older versions
+ have no, or only partial support. To provide a level of backwards
+ compatibility we try to work out what the definitions should be, given
+ the older pre-defines that GCC did produce. This isn't complete, but
+ it should be enough for use by routines that depend on this header. */
+
+/* No need to handle ARMv8, GCC had ACLE support before that. */
+
+#define __ARM_ACLE 101
+
+# ifdef __ARM_ARCH_7__
+/* The common subset of ARMv7 in all profiles. */
+# define __ARM_ARCH 7
+# define __ARM_ARCH_ISA_THUMB 2
+# define __ARM_FEATURE_CLZ
+# define __ARM_FEATURE_LDREX 7
+# define __ARM_FEATURE_UNALIGNED
+# endif
+
+# if defined (__ARM_ARCH_7A__) || defined (__ARM_ARCH_7R__)
+# define __ARM_ARCH 7
+# define __ARM_ARCH_ISA_THUMB 2
+# define __ARM_ARCH_ISA_ARM
+# define __ARM_FEATURE_CLZ
+# define __ARM_FEATURE_SIMD32
+# define __ARM_FEATURE_DSP
+# define __ARM_FEATURE_QBIT
+# define __ARM_FEATURE_SAT
+# define __ARM_FEATURE_LDREX 15
+# define __ARM_FEATURE_UNALIGNED
+# ifdef __ARM_ARCH_7A__
+# define __ARM_ARCH_PROFILE 'A'
+# else
+# define __ARM_ARCH_PROFILE 'R'
+# endif
+# endif
+
+# ifdef __ARM_ARCH_7EM__
+# define __ARM_ARCH 7
+# define __ARM_ARCH_ISA_THUMB 2
+# define __ARM_FEATURE_CLZ
+# define __ARM_FEATURE_SIMD32
+# define __ARM_FEATURE_DSP
+# define __ARM_FEATURE_QBIT
+# define __ARM_FEATURE_SAT
+# define __ARM_FEATURE_LDREX 7
+# define __ARM_FEATURE_UNALIGNED
+# define __ARM_ARCH_PROFILE 'M'
+# endif
+
+# ifdef __ARM_ARCH_7M__
+# define __ARM_ARCH 7
+# define __ARM_ARCH_ISA_THUMB 2
+# define __ARM_FEATURE_CLZ
+# define __ARM_FEATURE_QBIT
+# define __ARM_FEATURE_SAT
+# define __ARM_FEATURE_LDREX 7
+# define __ARM_FEATURE_UNALIGNED
+# define __ARM_ARCH_PROFILE 'M'
+# endif
+
+# ifdef __ARM_ARCH_6T2__
+# define __ARM_ARCH 6
+# define __ARM_ARCH_ISA_THUMB 2
+# define __ARM_ARCH_ISA_ARM
+# define __ARM_FEATURE_CLZ
+# define __ARM_FEATURE_SIMD32
+# define __ARM_FEATURE_DSP
+# define __ARM_FEATURE_QBIT
+# define __ARM_FEATURE_SAT
+# define __ARM_FEATURE_LDREX 4
+# define __ARM_FEATURE_UNALIGNED
+# endif
+
+# ifdef __ARM_ARCH_6M__
+# define __ARM_ARCH 6
+# define __ARM_ARCH_ISA_THUMB 1
+# define __ARM_ARCH_PROFILE 'M'
+# endif
+
+# if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) \
+ || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6Z__) \
+ || defined (__ARM_ARCH_6ZK__)
+# define __ARM_ARCH 6
+# define __ARM_ARCH_ISA_THUMB 1
+# define __ARM_ARCH_ISA_ARM
+# define __ARM_FEATURE_CLZ
+# define __ARM_FEATURE_SIMD32
+# define __ARM_FEATURE_DSP
+# define __ARM_FEATURE_QBIT
+# define __ARM_FEATURE_SAT
+# define __ARM_FEATURE_UNALIGNED
+# ifndef __thumb__
+# if defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__)
+# define __ARM_FEATURE_LDREX 15
+# else
+# define __ARM_FEATURE_LDREX 4
+# endif
+# endif
+# endif
+
+# if defined (__ARM_ARCH_5TE__) || defined (__ARM_ARCH_5E__)
+# define __ARM_ARCH 5
+# define __ARM_ARCH_ISA_ARM
+# ifdef __ARM_ARCH_5TE__
+# define __ARM_ARCH_ISA_THUMB 1
+# endif
+# define __ARM_FEATURE_CLZ
+# define __ARM_FEATURE_DSP
+# endif
+
+# if defined (__ARM_ARCH_5T__) || defined (__ARM_ARCH_5__)
+# define __ARM_ARCH 5
+# define __ARM_ARCH_ISA_ARM
+# ifdef __ARM_ARCH_5TE__
+# define __ARM_ARCH_ISA_THUMB 1
+# endif
+# define __ARM_FEATURE_CLZ
+# endif
+
+# ifdef __ARM_ARCH_4T__
+# define __ARM_ARCH 4
+# define __ARM_ARCH_ISA_ARM
+# define __ARM_ARCH_ISA_THUMB 1
+# endif
+
+# ifdef __ARM_ARCH_4__
+# define __ARM_ARCH 4
+# define __ARM_ARCH_ISA_ARM
+# endif
+
+# if defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__)
+# define __ARM_ARCH 3
+# define __ARM_ARCH_ISA_ARM
+# endif
+
+# ifdef __ARM_ARCH_2__
+# define __ARM_ARCH 2
+# define __ARM_ARCH_ISA_ARM
+# endif
+
+# ifdef __ARMEB__
+# define __ARM_BIG_ENDIAN
+# endif
+
+/* If we still don't know what the target architecture is, then we're
+ probably not using GCC. */
+# ifndef __ARM_ARCH
+# error Unable to determine architecture version.
+# endif
+
+#endif /* __ARM_ARCH */
Property changes on: trunk/sys/arm/include/acle-compat.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/armreg.h
===================================================================
--- trunk/sys/arm/include/armreg.h (rev 0)
+++ trunk/sys/arm/include/armreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,444 @@
+/* $MidnightBSD$ */
+/* $NetBSD: armreg.h,v 1.37 2007/01/06 00:50:54 christos Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2001 Ben Harris
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/armreg.h 283335 2015-05-23 22:48:54Z ian $
+ */
+
+#ifndef MACHINE_ARMREG_H
+#define MACHINE_ARMREG_H
+
+#include <machine/acle-compat.h>
+
+#define INSN_SIZE 4
+#define INSN_COND_MASK 0xf0000000 /* Condition mask */
+#define PSR_MODE 0x0000001f /* mode mask */
+#define PSR_USR32_MODE 0x00000010
+#define PSR_FIQ32_MODE 0x00000011
+#define PSR_IRQ32_MODE 0x00000012
+#define PSR_SVC32_MODE 0x00000013
+#define PSR_MON32_MODE 0x00000016
+#define PSR_ABT32_MODE 0x00000017
+#define PSR_HYP32_MODE 0x0000001a
+#define PSR_UND32_MODE 0x0000001b
+#define PSR_SYS32_MODE 0x0000001f
+#define PSR_32_MODE 0x00000010
+#define PSR_T 0x00000020 /* Instruction set bit */
+#define PSR_F 0x00000040 /* FIQ disable bit */
+#define PSR_I 0x00000080 /* IRQ disable bit */
+#define PSR_A 0x00000100 /* Imprecise abort bit */
+#define PSR_E 0x00000200 /* Data endianess bit */
+#define PSR_GE 0x000f0000 /* Greater than or equal to bits */
+#define PSR_J 0x01000000 /* Java bit */
+#define PSR_Q 0x08000000 /* Sticky overflow bit */
+#define PSR_V 0x10000000 /* Overflow bit */
+#define PSR_C 0x20000000 /* Carry bit */
+#define PSR_Z 0x40000000 /* Zero bit */
+#define PSR_N 0x80000000 /* Negative bit */
+#define PSR_FLAGS 0xf0000000 /* Flags mask. */
+
+/* The high-order byte is always the implementor */
+#define CPU_ID_IMPLEMENTOR_MASK 0xff000000
+#define CPU_ID_ARM_LTD 0x41000000 /* 'A' */
+#define CPU_ID_DEC 0x44000000 /* 'D' */
+#define CPU_ID_INTEL 0x69000000 /* 'i' */
+#define CPU_ID_TI 0x54000000 /* 'T' */
+#define CPU_ID_FARADAY 0x66000000 /* 'f' */
+
+/* How to decide what format the CPUID is in. */
+#define CPU_ID_ISOLD(x) (((x) & 0x0000f000) == 0x00000000)
+#define CPU_ID_IS7(x) (((x) & 0x0000f000) == 0x00007000)
+#define CPU_ID_ISNEW(x) (!CPU_ID_ISOLD(x) && !CPU_ID_IS7(x))
+
+/* On recent ARMs this byte holds the architecture and variant (sub-model) */
+#define CPU_ID_ARCH_MASK 0x000f0000
+#define CPU_ID_ARCH_V3 0x00000000
+#define CPU_ID_ARCH_V4 0x00010000
+#define CPU_ID_ARCH_V4T 0x00020000
+#define CPU_ID_ARCH_V5 0x00030000
+#define CPU_ID_ARCH_V5T 0x00040000
+#define CPU_ID_ARCH_V5TE 0x00050000
+#define CPU_ID_ARCH_V5TEJ 0x00060000
+#define CPU_ID_ARCH_V6 0x00070000
+#define CPU_ID_CPUID_SCHEME 0x000f0000
+#define CPU_ID_VARIANT_MASK 0x00f00000
+
+/* Next three nybbles are part number */
+#define CPU_ID_PARTNO_MASK 0x0000fff0
+
+/* Intel XScale has sub fields in part number */
+#define CPU_ID_XSCALE_COREGEN_MASK 0x0000e000 /* core generation */
+#define CPU_ID_XSCALE_COREREV_MASK 0x00001c00 /* core revision */
+#define CPU_ID_XSCALE_PRODUCT_MASK 0x000003f0 /* product number */
+
+/* And finally, the revision number. */
+#define CPU_ID_REVISION_MASK 0x0000000f
+
+/* Individual CPUs are probably best IDed by everything but the revision. */
+#define CPU_ID_CPU_MASK 0xfffffff0
+
+/* ARM9 and later CPUs */
+#define CPU_ID_ARM920T 0x41129200
+#define CPU_ID_ARM920T_ALT 0x41009200
+#define CPU_ID_ARM922T 0x41029220
+#define CPU_ID_ARM926EJS 0x41069260
+#define CPU_ID_ARM940T 0x41029400 /* XXX no MMU */
+#define CPU_ID_ARM946ES 0x41049460 /* XXX no MMU */
+#define CPU_ID_ARM966ES 0x41049660 /* XXX no MMU */
+#define CPU_ID_ARM966ESR1 0x41059660 /* XXX no MMU */
+#define CPU_ID_ARM1020E 0x4115a200 /* (AKA arm10 rev 1) */
+#define CPU_ID_ARM1022ES 0x4105a220
+#define CPU_ID_ARM1026EJS 0x4106a260
+#define CPU_ID_ARM1136JS 0x4107b360
+#define CPU_ID_ARM1136JSR1 0x4117b360
+#define CPU_ID_ARM1176JZS 0x410fb760
+#define CPU_ID_CORTEXA7 0x410fc070
+#define CPU_ID_CORTEXA8R1 0x411fc080
+#define CPU_ID_CORTEXA8R2 0x412fc080
+#define CPU_ID_CORTEXA8R3 0x413fc080
+#define CPU_ID_CORTEXA9R1 0x411fc090
+#define CPU_ID_CORTEXA9R2 0x412fc090
+#define CPU_ID_CORTEXA9R3 0x413fc090
+#define CPU_ID_CORTEXA15R0 0x410fc0f0
+#define CPU_ID_CORTEXA15R1 0x411fc0f0
+#define CPU_ID_CORTEXA15R2 0x412fc0f0
+#define CPU_ID_CORTEXA15R3 0x413fc0f0
+#define CPU_ID_KRAIT 0x510f06f0 /* Snapdragon S4 Pro/APQ8064 */
+#define CPU_ID_TI925T 0x54029250
+#define CPU_ID_MV88FR131 0x56251310 /* Marvell Feroceon 88FR131 Core */
+#define CPU_ID_MV88FR331 0x56153310 /* Marvell Feroceon 88FR331 Core */
+#define CPU_ID_MV88FR571_VD 0x56155710 /* Marvell Feroceon 88FR571-VD Core (ID from datasheet) */
+
+/*
+ * LokiPlus core has also ID set to 0x41159260 and this define cause execution of unsupported
+ * L2-cache instructions so need to disable it. 0x41159260 is a generic ARM926E-S ID.
+ */
+#ifdef SOC_MV_LOKIPLUS
+#define CPU_ID_MV88FR571_41 0x00000000
+#else
+#define CPU_ID_MV88FR571_41 0x41159260 /* Marvell Feroceon 88FR571-VD Core (actual ID from CPU reg) */
+#endif
+
+#define CPU_ID_MV88SV581X_V7 0x561F5810 /* Marvell Sheeva 88SV581x v7 Core */
+#define CPU_ID_MV88SV584X_V7 0x562F5840 /* Marvell Sheeva 88SV584x v7 Core */
+/* Marvell's CPUIDs with ARM ID in implementor field */
+#define CPU_ID_ARM_88SV581X_V7 0x413FC080 /* Marvell Sheeva 88SV581x v7 Core */
+
+#define CPU_ID_FA526 0x66015260
+#define CPU_ID_FA626TE 0x66056260
+#define CPU_ID_80200 0x69052000
+#define CPU_ID_PXA250 0x69052100 /* sans core revision */
+#define CPU_ID_PXA210 0x69052120
+#define CPU_ID_PXA250A 0x69052100 /* 1st version Core */
+#define CPU_ID_PXA210A 0x69052120 /* 1st version Core */
+#define CPU_ID_PXA250B 0x69052900 /* 3rd version Core */
+#define CPU_ID_PXA210B 0x69052920 /* 3rd version Core */
+#define CPU_ID_PXA250C 0x69052d00 /* 4th version Core */
+#define CPU_ID_PXA210C 0x69052d20 /* 4th version Core */
+#define CPU_ID_PXA27X 0x69054110
+#define CPU_ID_80321_400 0x69052420
+#define CPU_ID_80321_600 0x69052430
+#define CPU_ID_80321_400_B0 0x69052c20
+#define CPU_ID_80321_600_B0 0x69052c30
+#define CPU_ID_80219_400 0x69052e20 /* A0 stepping/revision. */
+#define CPU_ID_80219_600 0x69052e30 /* A0 stepping/revision. */
+#define CPU_ID_81342 0x69056810
+#define CPU_ID_IXP425 0x690541c0
+#define CPU_ID_IXP425_533 0x690541c0
+#define CPU_ID_IXP425_400 0x690541d0
+#define CPU_ID_IXP425_266 0x690541f0
+#define CPU_ID_IXP435 0x69054040
+#define CPU_ID_IXP465 0x69054200
+
+/* CPUID registers */
+#define ARM_PFR0_ARM_ISA_MASK 0x0000000f
+
+#define ARM_PFR0_THUMB_MASK 0x000000f0
+#define ARM_PFR0_THUMB 0x10
+#define ARM_PFR0_THUMB2 0x30
+
+#define ARM_PFR0_JAZELLE_MASK 0x00000f00
+#define ARM_PFR0_THUMBEE_MASK 0x0000f000
+
+#define ARM_PFR1_ARMV4_MASK 0x0000000f
+#define ARM_PFR1_SEC_EXT_MASK 0x000000f0
+#define ARM_PFR1_MICROCTRL_MASK 0x00000f00
+
+/*
+ * Post-ARM3 CP15 registers:
+ *
+ * 1 Control register
+ *
+ * 2 Translation Table Base
+ *
+ * 3 Domain Access Control
+ *
+ * 4 Reserved
+ *
+ * 5 Fault Status
+ *
+ * 6 Fault Address
+ *
+ * 7 Cache/write-buffer Control
+ *
+ * 8 TLB Control
+ *
+ * 9 Cache Lockdown
+ *
+ * 10 TLB Lockdown
+ *
+ * 11 Reserved
+ *
+ * 12 Reserved
+ *
+ * 13 Process ID (for FCSE)
+ *
+ * 14 Reserved
+ *
+ * 15 Implementation Dependent
+ */
+
+/* Some of the definitions below need cleaning up for V3/V4 architectures */
+
+/* CPU control register (CP15 register 1) */
+#define CPU_CONTROL_MMU_ENABLE 0x00000001 /* M: MMU/Protection unit enable */
+#define CPU_CONTROL_AFLT_ENABLE 0x00000002 /* A: Alignment fault enable */
+#define CPU_CONTROL_DC_ENABLE 0x00000004 /* C: IDC/DC enable */
+#define CPU_CONTROL_WBUF_ENABLE 0x00000008 /* W: Write buffer enable */
+#define CPU_CONTROL_32BP_ENABLE 0x00000010 /* P: 32-bit exception handlers */
+#define CPU_CONTROL_32BD_ENABLE 0x00000020 /* D: 32-bit addressing */
+#define CPU_CONTROL_LABT_ENABLE 0x00000040 /* L: Late abort enable */
+#define CPU_CONTROL_BEND_ENABLE 0x00000080 /* B: Big-endian mode */
+#define CPU_CONTROL_SYST_ENABLE 0x00000100 /* S: System protection bit */
+#define CPU_CONTROL_ROM_ENABLE 0x00000200 /* R: ROM protection bit */
+#define CPU_CONTROL_CPCLK 0x00000400 /* F: Implementation defined */
+#define CPU_CONTROL_SW_ENABLE 0x00000400 /* SW: SWP instruction enable */
+#define CPU_CONTROL_BPRD_ENABLE 0x00000800 /* Z: Branch prediction enable */
+#define CPU_CONTROL_IC_ENABLE 0x00001000 /* I: IC enable */
+#define CPU_CONTROL_VECRELOC 0x00002000 /* V: Vector relocation */
+#define CPU_CONTROL_ROUNDROBIN 0x00004000 /* RR: Predictable replacement */
+#define CPU_CONTROL_V4COMPAT 0x00008000 /* L4: ARMv4 compat LDR R15 etc */
+#define CPU_CONTROL_HAF_ENABLE 0x00020000 /* HA: Hardware Access Flag Enable */
+#define CPU_CONTROL_FI_ENABLE 0x00200000 /* FI: Low interrupt latency */
+#define CPU_CONTROL_UNAL_ENABLE 0x00400000 /* U: unaligned data access */
+#define CPU_CONTROL_V6_EXTPAGE 0x00800000 /* XP: ARMv6 extended page tables */
+#define CPU_CONTROL_V_ENABLE 0x01000000 /* VE: Interrupt vectors enable */
+#define CPU_CONTROL_EX_BEND 0x02000000 /* EE: exception endianness */
+#define CPU_CONTROL_L2_ENABLE 0x04000000 /* L2 Cache enabled */
+#define CPU_CONTROL_NMFI 0x08000000 /* NMFI: Non maskable FIQ */
+#define CPU_CONTROL_TR_ENABLE 0x10000000 /* TRE: TEX Remap*/
+#define CPU_CONTROL_AF_ENABLE 0x20000000 /* AFE: Access Flag enable */
+#define CPU_CONTROL_TE_ENABLE 0x40000000 /* TE: Thumb Exception enable */
+
+#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE
+
+/* ARM11x6 Auxiliary Control Register (CP15 register 1, opcode2 1) */
+#define ARM11X6_AUXCTL_RS 0x00000001 /* return stack */
+#define ARM11X6_AUXCTL_DB 0x00000002 /* dynamic branch prediction */
+#define ARM11X6_AUXCTL_SB 0x00000004 /* static branch prediction */
+#define ARM11X6_AUXCTL_TR 0x00000008 /* MicroTLB replacement strat. */
+#define ARM11X6_AUXCTL_EX 0x00000010 /* exclusive L1/L2 cache */
+#define ARM11X6_AUXCTL_RA 0x00000020 /* clean entire cache disable */
+#define ARM11X6_AUXCTL_RV 0x00000040 /* block transfer cache disable */
+#define ARM11X6_AUXCTL_CZ 0x00000080 /* restrict cache size */
+
+/* ARM1136 Auxiliary Control Register (CP15 register 1, opcode2 1) */
+#define ARM1136_AUXCTL_PFI 0x80000000 /* PFI: partial FI mode. */
+ /* This is an undocumented flag
+ * used to work around a cache bug
+ * in r0 steppings. See errata
+ * 364296.
+ */
+/* ARM1176 Auxiliary Control Register (CP15 register 1, opcode2 1) */
+#define ARM1176_AUXCTL_PHD 0x10000000 /* inst. prefetch halting disable */
+#define ARM1176_AUXCTL_BFD 0x20000000 /* branch folding disable */
+#define ARM1176_AUXCTL_FSD 0x40000000 /* force speculative ops disable */
+#define ARM1176_AUXCTL_FIO 0x80000000 /* low intr latency override */
+
+/* XScale Auxillary Control Register (CP15 register 1, opcode2 1) */
+#define XSCALE_AUXCTL_K 0x00000001 /* dis. write buffer coalescing */
+#define XSCALE_AUXCTL_P 0x00000002 /* ECC protect page table access */
+/* Note: XSCale core 3 uses those for LLR DCcahce attributes */
+#define XSCALE_AUXCTL_MD_WB_RA 0x00000000 /* mini-D$ wb, read-allocate */
+#define XSCALE_AUXCTL_MD_WB_RWA 0x00000010 /* mini-D$ wb, read/write-allocate */
+#define XSCALE_AUXCTL_MD_WT 0x00000020 /* mini-D$ wt, read-allocate */
+#define XSCALE_AUXCTL_MD_MASK 0x00000030
+
+/* Xscale Core 3 only */
+#define XSCALE_AUXCTL_LLR 0x00000400 /* Enable L2 for LLR Cache */
+
+/* Marvell Extra Features Register (CP15 register 1, opcode2 0) */
+#define MV_DC_REPLACE_LOCK 0x80000000 /* Replace DCache Lock */
+#define MV_DC_STREAM_ENABLE 0x20000000 /* DCache Streaming Switch */
+#define MV_WA_ENABLE 0x10000000 /* Enable Write Allocate */
+#define MV_L2_PREFETCH_DISABLE 0x01000000 /* L2 Cache Prefetch Disable */
+#define MV_L2_INV_EVICT_ERR 0x00800000 /* L2 Invalidates Uncorrectable Error Line Eviction */
+#define MV_L2_ENABLE 0x00400000 /* L2 Cache enable */
+#define MV_IC_REPLACE_LOCK 0x00080000 /* Replace ICache Lock */
+#define MV_BGH_ENABLE 0x00040000 /* Branch Global History Register Enable */
+#define MV_BTB_DISABLE 0x00020000 /* Branch Target Buffer Disable */
+#define MV_L1_PARERR_ENABLE 0x00010000 /* L1 Parity Error Enable */
+
+/* Cache type register definitions */
+#define CPU_CT_ISIZE(x) ((x) & 0xfff) /* I$ info */
+#define CPU_CT_DSIZE(x) (((x) >> 12) & 0xfff) /* D$ info */
+#define CPU_CT_S (1U << 24) /* split cache */
+#define CPU_CT_CTYPE(x) (((x) >> 25) & 0xf) /* cache type */
+#define CPU_CT_FORMAT(x) ((x) >> 29)
+/* Cache type register definitions for ARM v7 */
+#define CPU_CT_IMINLINE(x) ((x) & 0xf) /* I$ min line size */
+#define CPU_CT_DMINLINE(x) (((x) >> 16) & 0xf) /* D$ min line size */
+
+#define CPU_CT_CTYPE_WT 0 /* write-through */
+#define CPU_CT_CTYPE_WB1 1 /* write-back, clean w/ read */
+#define CPU_CT_CTYPE_WB2 2 /* w/b, clean w/ cp15,7 */
+#define CPU_CT_CTYPE_WB6 6 /* w/b, cp15,7, lockdown fmt A */
+#define CPU_CT_CTYPE_WB7 7 /* w/b, cp15,7, lockdown fmt B */
+
+#define CPU_CT_xSIZE_LEN(x) ((x) & 0x3) /* line size */
+#define CPU_CT_xSIZE_M (1U << 2) /* multiplier */
+#define CPU_CT_xSIZE_ASSOC(x) (((x) >> 3) & 0x7) /* associativity */
+#define CPU_CT_xSIZE_SIZE(x) (((x) >> 6) & 0x7) /* size */
+
+#define CPU_CT_ARMV7 0x4
+/* ARM v7 Cache type definitions */
+#define CPUV7_CT_CTYPE_WT (1U << 31)
+#define CPUV7_CT_CTYPE_WB (1 << 30)
+#define CPUV7_CT_CTYPE_RA (1 << 29)
+#define CPUV7_CT_CTYPE_WA (1 << 28)
+
+#define CPUV7_CT_xSIZE_LEN(x) ((x) & 0x7) /* line size */
+#define CPUV7_CT_xSIZE_ASSOC(x) (((x) >> 3) & 0x3ff) /* associativity */
+#define CPUV7_CT_xSIZE_SET(x) (((x) >> 13) & 0x7fff) /* num sets */
+
+#define CPU_CLIDR_CTYPE(reg,x) (((reg) >> ((x) * 3)) & 0x7)
+#define CPU_CLIDR_LOUIS(reg) (((reg) >> 21) & 0x7)
+#define CPU_CLIDR_LOC(reg) (((reg) >> 24) & 0x7)
+#define CPU_CLIDR_LOUU(reg) (((reg) >> 27) & 0x7)
+
+#define CACHE_ICACHE 1
+#define CACHE_DCACHE 2
+#define CACHE_SEP_CACHE 3
+#define CACHE_UNI_CACHE 4
+
+/* Fault status register definitions */
+#define FAULT_USER 0x10
+
+#if __ARM_ARCH < 6
+#define FAULT_TYPE_MASK 0x0f
+#define FAULT_WRTBUF_0 0x00 /* Vector Exception */
+#define FAULT_WRTBUF_1 0x02 /* Terminal Exception */
+#define FAULT_BUSERR_0 0x04 /* External Abort on Linefetch -- Section */
+#define FAULT_BUSERR_1 0x06 /* External Abort on Linefetch -- Page */
+#define FAULT_BUSERR_2 0x08 /* External Abort on Non-linefetch -- Section */
+#define FAULT_BUSERR_3 0x0a /* External Abort on Non-linefetch -- Page */
+#define FAULT_BUSTRNL1 0x0c /* External abort on Translation -- Level 1 */
+#define FAULT_BUSTRNL2 0x0e /* External abort on Translation -- Level 2 */
+#define FAULT_ALIGN_0 0x01 /* Alignment */
+#define FAULT_ALIGN_1 0x03 /* Alignment */
+#define FAULT_TRANS_S 0x05 /* Translation -- Section */
+#define FAULT_TRANS_F 0x06 /* Translation -- Flag */
+#define FAULT_TRANS_P 0x07 /* Translation -- Page */
+#define FAULT_DOMAIN_S 0x09 /* Domain -- Section */
+#define FAULT_DOMAIN_P 0x0b /* Domain -- Page */
+#define FAULT_PERM_S 0x0d /* Permission -- Section */
+#define FAULT_PERM_P 0x0f /* Permission -- Page */
+
+#define FAULT_IMPRECISE 0x400 /* Imprecise exception (XSCALE) */
+#define FAULT_EXTERNAL 0x400 /* External abort (armv6+) */
+#define FAULT_WNR 0x800 /* Write-not-Read access (armv6+) */
+
+#else /* __ARM_ARCH < 6 */
+
+#define FAULT_ALIGN 0x001 /* Alignment Fault */
+#define FAULT_DEBUG 0x002 /* Debug Event */
+#define FAULT_ACCESS_L1 0x003 /* Access Bit (L1) */
+#define FAULT_ICACHE 0x004 /* Instruction cache maintenance */
+#define FAULT_TRAN_L1 0x005 /* Translation Fault (L1) */
+#define FAULT_ACCESS_L2 0x006 /* Access Bit (L2) */
+#define FAULT_TRAN_L2 0x007 /* Translation Fault (L2) */
+#define FAULT_EA_PREC 0x008 /* External Abort */
+#define FAULT_DOMAIN_L1 0x009 /* Domain Fault (L1) */
+#define FAULT_DOMAIN_L2 0x00B /* Domain Fault (L2) */
+#define FAULT_EA_TRAN_L1 0x00C /* External Translation Abort (L1) */
+#define FAULT_PERM_L1 0x00D /* Permission Fault (L1) */
+#define FAULT_EA_TRAN_L2 0x00E /* External Translation Abort (L2) */
+#define FAULT_PERM_L2 0x00F /* Permission Fault (L2) */
+#define FAULT_TLB_CONFLICT 0x010 /* Permission Fault (L2) */
+#define FAULT_EA_IMPREC 0x016 /* Asynchronous External Abort */
+#define FAULT_PE_IMPREC 0x018 /* Asynchronous Parity Error */
+#define FAULT_PARITY 0x019 /* Parity Error */
+#define FAULT_PE_TRAN_L1 0x01C /* Parity Error on Translation (L1) */
+#define FAULT_PE_TRAN_L2 0x01E /* Parity Error on Translation (L2) */
+
+#define FSR_TO_FAULT(fsr) (((fsr) & 0xF) | \
+ ((((fsr) & (1 << 10)) >> (10 - 4))))
+#define FSR_LPAE (1 << 9) /* LPAE indicator */
+#define FSR_WNR (1 << 11) /* Write-not-Read access */
+#define FSR_EXT (1 << 12) /* DECERR/SLVERR for external*/
+#define FSR_CM (1 << 13) /* Cache maintenance fault */
+#endif /* !__ARM_ARCH < 6 */
+
+/*
+ * Address of the vector page, low and high versions.
+ */
+#ifndef __ASSEMBLER__
+#define ARM_VECTORS_LOW 0x00000000U
+#define ARM_VECTORS_HIGH 0xffff0000U
+#else
+#define ARM_VECTORS_LOW 0
+#define ARM_VECTORS_HIGH 0xffff0000
+#endif
+
+/*
+ * ARM Instructions
+ *
+ * 3 3 2 2 2
+ * 1 0 9 8 7 0
+ * +-------+-------------------------------------------------------+
+ * | cond | instruction dependant |
+ * |c c c c| |
+ * +-------+-------------------------------------------------------+
+ */
+
+#define INSN_SIZE 4 /* Always 4 bytes */
+#define INSN_COND_MASK 0xf0000000 /* Condition mask */
+#define INSN_COND_AL 0xe0000000 /* Always condition */
+
+#define THUMB_INSN_SIZE 2 /* Some are 4 bytes. */
+
+#endif /* !MACHINE_ARMREG_H */
Property changes on: trunk/sys/arm/include/armreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/asm.h
===================================================================
--- trunk/sys/arm/include/asm.h (rev 0)
+++ trunk/sys/arm/include/asm.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,244 @@
+/* $MidnightBSD$ */
+/* $NetBSD: asm.h,v 1.5 2003/08/07 16:26:53 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)asm.h 5.5 (Berkeley) 5/7/91
+ *
+ * $FreeBSD: stable/10/sys/arm/include/asm.h 278652 2015-02-13 00:49:47Z ian $
+ */
+
+#ifndef _MACHINE_ASM_H_
+#define _MACHINE_ASM_H_
+#include <sys/cdefs.h>
+#include <machine/acle-compat.h>
+#include <machine/sysreg.h>
+
+#define _C_LABEL(x) x
+#define _ASM_LABEL(x) x
+
+#ifndef _ALIGN_TEXT
+# define _ALIGN_TEXT .align 2
+#endif
+
+#if defined(__ARM_EABI__) && !defined(_STANDALONE)
+#define STOP_UNWINDING .cantunwind
+#define _FNSTART .fnstart
+#define _FNEND .fnend
+#else
+#define STOP_UNWINDING
+#define _FNSTART
+#define _FNEND
+#endif
+
+/*
+ * gas/arm uses @ as a single comment character and thus cannot be used here.
+ * It recognises the # instead of an @ symbol in .type directives.
+ */
+#define _ASM_TYPE_FUNCTION #function
+#define _ASM_TYPE_OBJECT #object
+
+/* XXX Is this still the right prologue for profiling? */
+#ifdef GPROF
+#define _PROF_PROLOGUE \
+ mov ip, lr; \
+ bl __mcount
+#else
+#define _PROF_PROLOGUE
+#endif
+
+/*
+ * EENTRY()/EEND() mark "extra" entry/exit points from a function.
+ * LEENTRY()/LEEND() are the the same for local symbols.
+ * The unwind info cannot handle the concept of a nested function, or a function
+ * with multiple .fnstart directives, but some of our assembler code is written
+ * with multiple labels to allow entry at several points. The EENTRY() macro
+ * defines such an extra entry point without a new .fnstart, so that it's
+ * basically just a label that you can jump to. The EEND() macro does nothing
+ * at all, except document the exit point associated with the same-named entry.
+ */
+#define GLOBAL(x) .global x
+
+#define _LEENTRY(x) .type x,_ASM_TYPE_FUNCTION; x:
+#define _LEEND(x) /* nothing */
+#define _EENTRY(x) GLOBAL(x); _LEENTRY(x)
+#define _EEND(x) _LEEND(x)
+
+#define _LENTRY(x) .text; _ALIGN_TEXT; _LEENTRY(x); _FNSTART
+#define _LEND(x) .size x, . - x; _FNEND
+#define _ENTRY(x) .text; _ALIGN_TEXT; _EENTRY(x); _FNSTART
+#define _END(x) _LEND(x)
+
+#define ENTRY(y) _ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
+#define EENTRY(y) _EENTRY(_C_LABEL(y));
+#define ENTRY_NP(y) _ENTRY(_C_LABEL(y))
+#define EENTRY_NP(y) _EENTRY(_C_LABEL(y))
+#define END(y) _END(_C_LABEL(y))
+#define EEND(y) _EEND(_C_LABEL(y))
+#define ASENTRY(y) _ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
+#define ASLENTRY(y) _LENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
+#define ASEENTRY(y) _EENTRY(_ASM_LABEL(y));
+#define ASLEENTRY(y) _LEENTRY(_ASM_LABEL(y));
+#define ASENTRY_NP(y) _ENTRY(_ASM_LABEL(y))
+#define ASLENTRY_NP(y) _LENTRY(_ASM_LABEL(y))
+#define ASEENTRY_NP(y) _EENTRY(_ASM_LABEL(y))
+#define ASLEENTRY_NP(y) _LEENTRY(_ASM_LABEL(y))
+#define ASEND(y) _END(_ASM_LABEL(y))
+#define ASLEND(y) _LEND(_ASM_LABEL(y))
+#define ASEEND(y) _EEND(_ASM_LABEL(y))
+#define ASLEEND(y) _LEEND(_ASM_LABEL(y))
+
+#define ASMSTR .asciz
+
+#if defined(PIC)
+#define PLT_SYM(x) PIC_SYM(x, PLT)
+#define GOT_SYM(x) PIC_SYM(x, GOT)
+#define GOT_GET(x,got,sym) \
+ ldr x, sym; \
+ ldr x, [x, got]
+#define GOT_INIT(got,gotsym,pclabel) \
+ ldr got, gotsym; \
+ pclabel: add got, got, pc
+#ifdef __thumb__
+#define GOT_INITSYM(gotsym,pclabel) \
+ .align 2; \
+ gotsym: .word _C_LABEL(_GLOBAL_OFFSET_TABLE_) - (pclabel+4)
+#else
+#define GOT_INITSYM(gotsym,pclabel) \
+ .align 2; \
+ gotsym: .word _C_LABEL(_GLOBAL_OFFSET_TABLE_) - (pclabel+8)
+#endif
+
+#ifdef __STDC__
+#define PIC_SYM(x,y) x ## ( ## y ## )
+#else
+#define PIC_SYM(x,y) x/**/(/**/y/**/)
+#endif
+
+#else
+#define PLT_SYM(x) x
+#define GOT_SYM(x) x
+#define GOT_GET(x,got,sym) \
+ ldr x, sym;
+#define GOT_INIT(got,gotsym,pclabel)
+#define GOT_INITSYM(gotsym,pclabel)
+#define PIC_SYM(x,y) x
+#endif /* PIC */
+
+#undef __FBSDID
+#if !defined(lint) && !defined(STRIP_FBSDID)
+#define __FBSDID(s) .ident s
+#else
+#define __FBSDID(s) /* nothing */
+#endif
+
+
+#define WEAK_ALIAS(alias,sym) \
+ .weak alias; \
+ alias = sym
+
+#ifdef __STDC__
+#define WARN_REFERENCES(sym,msg) \
+ .stabs msg ## ,30,0,0,0 ; \
+ .stabs __STRING(_C_LABEL(sym)) ## ,1,0,0,0
+#else
+#define WARN_REFERENCES(sym,msg) \
+ .stabs msg,30,0,0,0 ; \
+ .stabs __STRING(sym),1,0,0,0
+#endif /* __STDC__ */
+
+/* Exactly one of the __ARM_ARCH_*__ macros will be defined by the compiler. */
+/* The _ARM_ARCH_* macros are deprecated and will be removed soon. */
+/* This should be moved into another header so it can be used in
+ * both asm and C code. machine/asm.h cannot be included in C code. */
+#if defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
+#define _ARM_ARCH_7
+#define _HAVE_ARMv7_INSTRUCTIONS 1
+#endif
+
+#if defined (_HAVE_ARMv7_INSTRUCTIONS) || defined (__ARM_ARCH_6__) || \
+ defined (__ARM_ARCH_6J__) || defined (__ARM_ARCH_6K__) || \
+ defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6ZK__)
+#define _ARM_ARCH_6
+#define _HAVE_ARMv6_INSTRUCTIONS 1
+#endif
+
+#if defined (_HAVE_ARMv6_INSTRUCTIONS) || defined (__ARM_ARCH_5TE__) || \
+ defined (__ARM_ARCH_5TEJ__) || defined (__ARM_ARCH_5E__)
+#define _ARM_ARCH_5E
+#define _HAVE_ARMv5E_INSTRUCTIONS 1
+#endif
+
+#if defined (_HAVE_ARMv5E_INSTRUCTIONS) || defined (__ARM_ARCH_5__) || \
+ defined (__ARM_ARCH_5T__)
+#define _ARM_ARCH_5
+#define _HAVE_ARMv5_INSTRUCTIONS 1
+#endif
+
+#if defined (_HAVE_ARMv5_INSTRUCTIONS) || defined (__ARM_ARCH_4T__)
+#define _ARM_ARCH_4T
+#define _HAVE_ARMv4T_INSTRUCTIONS 1
+#endif
+
+/* FreeBSD requires ARMv4, so this is always set. */
+#define _HAVE_ARMv4_INSTRUCTIONS 1
+
+#if defined (_HAVE_ARMv4T_INSTRUCTIONS)
+# define RET bx lr
+# define RETeq bxeq lr
+# define RETne bxne lr
+# define RETc(c) bx##c lr
+#else
+# define RET mov pc, lr
+# define RETeq moveq pc, lr
+# define RETne movne pc, lr
+# define RETc(c) mov##c pc, lr
+#endif
+
+#if __ARM_ARCH >= 7
+#define ISB isb
+#define DSB dsb
+#define DMB dmb
+#define WFI wfi
+#elif __ARM_ARCH == 6
+#define ISB mcr CP15_CP15ISB
+#define DSB mcr CP15_CP15DSB
+#define DMB mcr CP15_CP15DMB
+#define WFI mcr CP15_CP15WFI
+#else
+#define ISB mcr CP15_CP15ISB
+#define DSB mcr CP15_CP15DSB /* DSB and DMB are the */
+#define DMB mcr CP15_CP15DSB /* same prior to v6.*/
+/* No form of WFI available on v4, define nothing to get an error on use. */
+#endif
+
+#endif /* !_MACHINE_ASM_H_ */
Property changes on: trunk/sys/arm/include/asm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/asmacros.h
===================================================================
--- trunk/sys/arm/include/asmacros.h (rev 0)
+++ trunk/sys/arm/include/asmacros.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,53 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard <cognet at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/asmacros.h 266311 2014-05-17 13:53:38Z ian $
+ */
+
+#ifndef _MACHINE_ASMACROS_H_
+#define _MACHINE_ASMACROS_H_
+
+#include <machine/asm.h>
+
+#ifdef _KERNEL
+
+#ifdef LOCORE
+#include "opt_global.h"
+
+#ifdef _ARM_ARCH_6
+#define GET_CURTHREAD_PTR(tmp) \
+ mrc p15, 0, tmp, c13, c0, 4
+#else
+#define GET_CURTHREAD_PTR(tmp) \
+ ldr tmp, =_C_LABEL(__pcpu);\
+ ldr tmp, [tmp, #PC_CURTHREAD]
+#endif
+
+#endif /* LOCORE */
+
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_ASMACROS_H_ */
Property changes on: trunk/sys/arm/include/asmacros.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/at91_gpio.h
===================================================================
--- trunk/sys/arm/include/at91_gpio.h (rev 0)
+++ trunk/sys/arm/include/at91_gpio.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,109 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (C) 2012 Ian Lepore. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/at91_gpio.h 248911 2013-03-29 19:52:57Z ian $
+ */
+
+#ifndef _ARM_AT91_GPIO_H
+#define _ARM_AT91_GPIO_H
+
+#ifndef _KERNEL
+#include <sys/types.h>
+#endif
+#include <sys/ioccom.h>
+
+/* Userland GPIO API for Atmel AT91 series SOC.
+ *
+ * Open /dev/pioN (where N is 0 for PIOA, 1 for PIOB, etc), and use ioctl(2)
+ * calls to configure the pin(s) as needed.
+ *
+ * The userland interrupt support allows you to use read(2) and/or select(2) to
+ * get notified of interrupts on PIO pins for which you enabled interrupt
+ * notifications. Each time an interrupt occurs on a given pin, that pin number
+ * is written into a buffer as a uint8_t. Thus, reading from /dev/pioN delivers
+ * info on which interrupt(s) have occurred since the last read. You can also
+ * use select() to block until an interrupt occurs (you still need to read() to
+ * consume the interrupt number bytes from the buffer.)
+ */
+
+struct at91_gpio_info
+{
+ uint32_t output_status; /* Current state of output pins */
+ uint32_t input_status; /* 1->out 0->in bitmask */
+ uint32_t highz_status; /* 1->highz 0->driven bitmask */
+ uint32_t pullup_status; /* 1->floating 0->pullup engaged */
+ uint32_t glitch_status; /* 0-> no glitch filter 1->gf */
+ uint32_t enabled_status; /* 1->used for pio 0->other */
+ uint32_t periph_status; /* 0->A periph 1->B periph */
+ uint32_t intr_status; /* 1-> ISR enabled, 0->disabled */
+ uint32_t extra_status[8];/* Extra status info, device depend */
+};
+
+struct at91_gpio_cfg
+{
+ uint32_t cfgmask; /* which things change */
+#define AT91_GPIO_CFG_INPUT 0x01 /* configure input/output pins */
+#define AT91_GPIO_CFG_HI_Z 0x02 /* HiZ */
+#define AT91_GPIO_CFG_PULLUP 0x04 /* Enable/disable pullup resistors */
+#define AT91_GPIO_CFG_GLITCH 0x08 /* Glitch filtering */
+#define AT91_GPIO_CFG_GPIO 0x10 /* Use pin for PIO or peripheral */
+#define AT91_GPIO_CFG_PERIPH 0x20 /* Select which peripheral to use */
+#define AT91_GPIO_CFG_INTR 0x40 /* Select pin for interrupts */
+ uint32_t iomask; /* Mask of bits to change */
+ uint32_t input; /* or output */
+ uint32_t hi_z; /* Disable output */
+ uint32_t pullup; /* Enable pullup resistor */
+ uint32_t glitch; /* Glitch filtering */
+ uint32_t gpio; /* Enabled for PIO (1) or periph (0) */
+ uint32_t periph; /* Select periph A (0) or periph B (1) */
+ uint32_t intr; /* Enable interrupt (1), or not (0) */
+};
+
+struct at91_gpio_bang
+{
+ uint32_t clockpin; /* clock pin MASK */
+ uint32_t datapin; /* Data pin MASK */
+ uint32_t bits; /* bits to clock out (all 32) */
+};
+
+struct at91_gpio_bang_many
+{
+ uint32_t clockpin; /* clock pin MASK */
+ uint32_t datapin; /* Data pin MASK */
+ void *bits; /* bits to clock out */
+ uint32_t numbits; /* Number of bits to clock out */
+};
+
+#define AT91_GPIO_SET _IOW('g', 0, uint32_t) /* Turn bits on */
+#define AT91_GPIO_CLR _IOW('g', 1, uint32_t) /* Turn bits off */
+#define AT91_GPIO_READ _IOR('g', 2, uint32_t) /* Read input bit state */
+#define AT91_GPIO_INFO _IOR('g', 3, struct at91_gpio_info) /* State of pio cfg */
+#define AT91_GPIO_CFG _IOW('g', 4, struct at91_gpio_cfg) /* Configure pio */
+#define AT91_GPIO_BANG _IOW('g', 5, struct at91_gpio_bang) /* bit bang 32 bits */
+#define AT91_GPIO_BANG_MANY _IOW('g', 6, struct at91_gpio_bang_many)/* bit bang >32 bits */
+
+#endif /* _ARM_AT91_GPIO_H */
+
Property changes on: trunk/sys/arm/include/at91_gpio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/atags.h
===================================================================
--- trunk/sys/arm/include/atags.h (rev 0)
+++ trunk/sys/arm/include/atags.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,130 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 M. Warner Losh.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/atags.h 237069 2012-06-14 14:38:55Z imp $
+ */
+
+#ifndef __MACHINE_ATAGS_H__
+#define __MACHINE_ATAGS_H__
+
+/*
+ * Linux boot ABI compatable ATAG definitions. All these structures
+ * assume tight packing, but since they are all uint32_t's, I've not
+ * bothered to do the usual alignment dance.
+ */
+
+#define LBABI_MAX_COMMAND_LINE 1024
+
+struct arm_lbabi_header
+{
+ uint32_t size; /* Size of this node, including header */
+ uint32_t tag; /* Node type */
+};
+
+#define ATAG_NONE 0x00000000 /* End of atags list */
+#define ATAG_CORE 0x54410001 /* List must start with ATAG_CORE */
+#define ATAG_MEM 0x54410002 /* Multiple ATAG_MEM nodes possible */
+#define ATAG_VIDEOTEXT 0x54410003 /* Video parameters */
+#define ATAG_RAMDISK 0x54410004 /* Describes the ramdisk parameters */
+#define ATAG_INITRD 0x54410005 /* Deprecated ramdisk -- used va not pa */
+#define ATAG_INITRD2 0x54420005 /* compressed ramdisk image */
+#define ATAG_SERIAL 0x54410006 /* 64-bits of serial number */
+#define ATAG_REVISION 0x54410007 /* Board revision */
+#define ATAG_VIDEOLFB 0x54410008 /* vesafb framebuffer */
+#define ATAG_CMDLINE 0x54410009 /* Command line */
+
+/*
+ * ATAG_CORE data
+ */
+struct arm_lbabi_core
+{
+ uint32_t flags; /* bit 0 == read-only */
+ uint32_t pagesize;
+ uint32_t rootdev;
+};
+
+/*
+ * ATAG_MEM data -- Can be more than one to describe different
+ * banks.
+ */
+struct arm_lbabi_mem32
+{
+ uint32_t size;
+ uint32_t start; /* start of physical memory */
+};
+
+/*
+ * ATAG_INITRD2 - Compressed ramdisk image details
+ */
+struct arm_lbabi_initrd
+{
+ uint32_t start; /* pa of start */
+ uint32_t size; /* How big the ram disk is */
+};
+
+/*
+ * ATAG_SERIAL - serial number
+ */
+struct arm_lbabi_serial_number
+{
+ uint32_t low;
+ uint32_t high;
+};
+
+/*
+ * ATAG_REVISION - board revision
+ */
+struct arm_lbabi_revision
+{
+ uint32_t rev;
+};
+
+/*
+ * ATAG_CMDLINE - Command line from uboot
+ */
+struct arm_lbabi_command_line
+{
+ char command[1]; /* Minimum command length */
+};
+
+struct arm_lbabi_tag
+{
+ struct arm_lbabi_header tag_hdr;
+ union {
+ struct arm_lbabi_core tag_core;
+ struct arm_lbabi_mem32 tag_mem;
+ struct arm_lbabi_initrd tag_initrd;
+ struct arm_lbabi_serial_number tag_sn;
+ struct arm_lbabi_revision tag_rev;
+ struct arm_lbabi_command_line tag_cmd;
+ } u;
+};
+
+#define ATAG_TAG(a) (a)->tag_hdr.tag
+#define ATAG_SIZE(a) (a)->tag_hdr.size
+#define ATAG_NEXT(a) (struct arm_lbabi_tag *)((char *)(a) + ATAG_SIZE(a))
+
+#endif /* __MACHINE_ATAGS_H__ */
Property changes on: trunk/sys/arm/include/atags.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/atomic.h
===================================================================
--- trunk/sys/arm/include/atomic.h (rev 0)
+++ trunk/sys/arm/include/atomic.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1135 @@
+/* $MidnightBSD$ */
+/* $NetBSD: atomic.h,v 1.1 2002/10/19 12:22:34 bsh Exp $ */
+
+/*-
+ * Copyright (C) 2003-2004 Olivier Houchard
+ * Copyright (C) 1994-1997 Mark Brinicombe
+ * Copyright (C) 1994 Brini
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of Brini may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/atomic.h 283317 2015-05-23 17:30:30Z ian $
+ */
+
+#ifndef _MACHINE_ATOMIC_H_
+#define _MACHINE_ATOMIC_H_
+
+#include <sys/types.h>
+#include <machine/armreg.h>
+
+#ifndef _KERNEL
+#include <machine/sysarch.h>
+#else
+#include <machine/cpuconf.h>
+#endif
+
+#if defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
+#define isb() __asm __volatile("isb" : : : "memory")
+#define dsb() __asm __volatile("dsb" : : : "memory")
+#define dmb() __asm __volatile("dmb" : : : "memory")
+#elif defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) || \
+ defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6T2__) || \
+ defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6ZK__)
+#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("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() dsb()
+#endif
+
+#define mb() dmb()
+#define wmb() dmb()
+#define rmb() dmb()
+
+
+
+/*
+ * It would be nice to use _HAVE_ARMv6_INSTRUCTIONS from machine/asm.h
+ * here, but that header can't be included here because this is C
+ * code. I would like to move the _HAVE_ARMv6_INSTRUCTIONS definition
+ * out of asm.h so it can be used in both asm and C code. - kientzle@
+ */
+#if defined (__ARM_ARCH_7__) || \
+ defined (__ARM_ARCH_7A__) || \
+ defined (__ARM_ARCH_6__) || \
+ defined (__ARM_ARCH_6J__) || \
+ defined (__ARM_ARCH_6K__) || \
+ defined (__ARM_ARCH_6T2__) || \
+ defined (__ARM_ARCH_6Z__) || \
+ defined (__ARM_ARCH_6ZK__)
+#define ARM_HAVE_ATOMIC64
+
+static __inline void
+__do_dmb(void)
+{
+
+#if defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
+ __asm __volatile("dmb" : : : "memory");
+#else
+ __asm __volatile("mcr p15, 0, r0, c7, c10, 5" : : : "memory");
+#endif
+}
+
+#define ATOMIC_ACQ_REL_LONG(NAME) \
+static __inline void \
+atomic_##NAME##_acq_long(__volatile u_long *p, u_long v) \
+{ \
+ atomic_##NAME##_long(p, v); \
+ __do_dmb(); \
+} \
+ \
+static __inline void \
+atomic_##NAME##_rel_long(__volatile u_long *p, u_long v) \
+{ \
+ __do_dmb(); \
+ atomic_##NAME##_long(p, v); \
+}
+
+#define ATOMIC_ACQ_REL(NAME, WIDTH) \
+static __inline void \
+atomic_##NAME##_acq_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\
+{ \
+ atomic_##NAME##_##WIDTH(p, v); \
+ __do_dmb(); \
+} \
+ \
+static __inline void \
+atomic_##NAME##_rel_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\
+{ \
+ __do_dmb(); \
+ atomic_##NAME##_##WIDTH(p, v); \
+}
+
+static __inline void
+atomic_set_32(volatile uint32_t *address, uint32_t setmask)
+{
+ uint32_t tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%2]\n"
+ "orr %0, %0, %3\n"
+ "strex %1, %0, [%2]\n"
+ "cmp %1, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ , "+r" (address), "+r" (setmask) : : "cc", "memory");
+
+}
+
+static __inline void
+atomic_set_64(volatile uint64_t *p, uint64_t val)
+{
+ uint64_t tmp;
+ uint32_t exflag;
+
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[tmp], [%[ptr]]\n"
+ " orr %Q[tmp], %Q[val]\n"
+ " orr %R[tmp], %R[val]\n"
+ " strexd %[exf], %[tmp], [%[ptr]]\n"
+ " teq %[exf], #0\n"
+ " it ne \n"
+ " bne 1b\n"
+ : [exf] "=&r" (exflag),
+ [tmp] "=&r" (tmp)
+ : [ptr] "r" (p),
+ [val] "r" (val)
+ : "cc", "memory");
+}
+
+static __inline void
+atomic_set_long(volatile u_long *address, u_long setmask)
+{
+ u_long tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%2]\n"
+ "orr %0, %0, %3\n"
+ "strex %1, %0, [%2]\n"
+ "cmp %1, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ , "+r" (address), "+r" (setmask) : : "cc", "memory");
+
+}
+
+static __inline void
+atomic_clear_32(volatile uint32_t *address, uint32_t setmask)
+{
+ uint32_t tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%2]\n"
+ "bic %0, %0, %3\n"
+ "strex %1, %0, [%2]\n"
+ "cmp %1, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (address), "+r" (setmask) : : "cc", "memory");
+}
+
+static __inline void
+atomic_clear_64(volatile uint64_t *p, uint64_t val)
+{
+ uint64_t tmp;
+ uint32_t exflag;
+
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[tmp], [%[ptr]]\n"
+ " bic %Q[tmp], %Q[val]\n"
+ " bic %R[tmp], %R[val]\n"
+ " strexd %[exf], %[tmp], [%[ptr]]\n"
+ " teq %[exf], #0\n"
+ " it ne \n"
+ " bne 1b\n"
+ : [exf] "=&r" (exflag),
+ [tmp] "=&r" (tmp)
+ : [ptr] "r" (p),
+ [val] "r" (val)
+ : "cc", "memory");
+}
+
+static __inline void
+atomic_clear_long(volatile u_long *address, u_long setmask)
+{
+ u_long tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%2]\n"
+ "bic %0, %0, %3\n"
+ "strex %1, %0, [%2]\n"
+ "cmp %1, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (address), "+r" (setmask) : : "cc", "memory");
+}
+
+static __inline u_int32_t
+atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
+{
+ uint32_t ret;
+
+ __asm __volatile("1: ldrex %0, [%1]\n"
+ "cmp %0, %2\n"
+ "itt ne\n"
+ "movne %0, #0\n"
+ "bne 2f\n"
+ "strex %0, %3, [%1]\n"
+ "cmp %0, #0\n"
+ "ite eq\n"
+ "moveq %0, #1\n"
+ "bne 1b\n"
+ "2:"
+ : "=&r" (ret)
+ ,"+r" (p), "+r" (cmpval), "+r" (newval) : : "cc",
+ "memory");
+ return (ret);
+}
+
+static __inline int
+atomic_cmpset_64(volatile uint64_t *p, uint64_t cmpval, uint64_t newval)
+{
+ uint64_t tmp;
+ uint32_t ret;
+
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[tmp], [%[ptr]]\n"
+ " teq %Q[tmp], %Q[cmpval]\n"
+ " itee eq \n"
+ " teqeq %R[tmp], %R[cmpval]\n"
+ " movne %[ret], #0\n"
+ " bne 2f\n"
+ " strexd %[ret], %[newval], [%[ptr]]\n"
+ " teq %[ret], #0\n"
+ " it ne \n"
+ " bne 1b\n"
+ " mov %[ret], #1\n"
+ "2: \n"
+ : [ret] "=&r" (ret),
+ [tmp] "=&r" (tmp)
+ : [ptr] "r" (p),
+ [cmpval] "r" (cmpval),
+ [newval] "r" (newval)
+ : "cc", "memory");
+ return (ret);
+}
+
+static __inline u_long
+atomic_cmpset_long(volatile u_long *p, volatile u_long cmpval, volatile u_long newval)
+{
+ u_long ret;
+
+ __asm __volatile("1: ldrex %0, [%1]\n"
+ "cmp %0, %2\n"
+ "itt ne\n"
+ "movne %0, #0\n"
+ "bne 2f\n"
+ "strex %0, %3, [%1]\n"
+ "cmp %0, #0\n"
+ "ite eq\n"
+ "moveq %0, #1\n"
+ "bne 1b\n"
+ "2:"
+ : "=&r" (ret)
+ ,"+r" (p), "+r" (cmpval), "+r" (newval) : : "cc",
+ "memory");
+ return (ret);
+}
+
+static __inline u_int32_t
+atomic_cmpset_acq_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
+{
+ u_int32_t ret = atomic_cmpset_32(p, cmpval, newval);
+
+ __do_dmb();
+ return (ret);
+}
+
+static __inline uint64_t
+atomic_cmpset_acq_64(volatile uint64_t *p, volatile uint64_t cmpval, volatile uint64_t newval)
+{
+ uint64_t ret = atomic_cmpset_64(p, cmpval, newval);
+
+ __do_dmb();
+ return (ret);
+}
+
+static __inline u_long
+atomic_cmpset_acq_long(volatile u_long *p, volatile u_long cmpval, volatile u_long newval)
+{
+ u_long ret = atomic_cmpset_long(p, cmpval, newval);
+
+ __do_dmb();
+ return (ret);
+}
+
+static __inline u_int32_t
+atomic_cmpset_rel_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
+{
+
+ __do_dmb();
+ return (atomic_cmpset_32(p, cmpval, newval));
+}
+
+static __inline uint64_t
+atomic_cmpset_rel_64(volatile uint64_t *p, volatile uint64_t cmpval, volatile uint64_t newval)
+{
+
+ __do_dmb();
+ return (atomic_cmpset_64(p, cmpval, newval));
+}
+
+static __inline u_long
+atomic_cmpset_rel_long(volatile u_long *p, volatile u_long cmpval, volatile u_long newval)
+{
+
+ __do_dmb();
+ return (atomic_cmpset_long(p, cmpval, newval));
+}
+
+
+static __inline void
+atomic_add_32(volatile u_int32_t *p, u_int32_t val)
+{
+ uint32_t tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%2]\n"
+ "add %0, %0, %3\n"
+ "strex %1, %0, [%2]\n"
+ "cmp %1, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (p), "+r" (val) : : "cc", "memory");
+}
+
+static __inline void
+atomic_add_64(volatile uint64_t *p, uint64_t val)
+{
+ uint64_t tmp;
+ uint32_t exflag;
+
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[tmp], [%[ptr]]\n"
+ " adds %Q[tmp], %Q[val]\n"
+ " adc %R[tmp], %R[val]\n"
+ " strexd %[exf], %[tmp], [%[ptr]]\n"
+ " teq %[exf], #0\n"
+ " it ne \n"
+ " bne 1b\n"
+ : [exf] "=&r" (exflag),
+ [tmp] "=&r" (tmp)
+ : [ptr] "r" (p),
+ [val] "r" (val)
+ : "cc", "memory");
+}
+
+static __inline void
+atomic_add_long(volatile u_long *p, u_long val)
+{
+ u_long tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%2]\n"
+ "add %0, %0, %3\n"
+ "strex %1, %0, [%2]\n"
+ "cmp %1, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (p), "+r" (val) : : "cc", "memory");
+}
+
+static __inline void
+atomic_subtract_32(volatile u_int32_t *p, u_int32_t val)
+{
+ uint32_t tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%2]\n"
+ "sub %0, %0, %3\n"
+ "strex %1, %0, [%2]\n"
+ "cmp %1, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (p), "+r" (val) : : "cc", "memory");
+}
+
+static __inline void
+atomic_subtract_64(volatile uint64_t *p, uint64_t val)
+{
+ uint64_t tmp;
+ uint32_t exflag;
+
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[tmp], [%[ptr]]\n"
+ " subs %Q[tmp], %Q[val]\n"
+ " sbc %R[tmp], %R[val]\n"
+ " strexd %[exf], %[tmp], [%[ptr]]\n"
+ " teq %[exf], #0\n"
+ " it ne \n"
+ " bne 1b\n"
+ : [exf] "=&r" (exflag),
+ [tmp] "=&r" (tmp)
+ : [ptr] "r" (p),
+ [val] "r" (val)
+ : "cc", "memory");
+}
+
+static __inline void
+atomic_subtract_long(volatile u_long *p, u_long val)
+{
+ u_long tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%2]\n"
+ "sub %0, %0, %3\n"
+ "strex %1, %0, [%2]\n"
+ "cmp %1, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (p), "+r" (val) : : "cc", "memory");
+}
+
+ATOMIC_ACQ_REL(clear, 32)
+ATOMIC_ACQ_REL(add, 32)
+ATOMIC_ACQ_REL(subtract, 32)
+ATOMIC_ACQ_REL(set, 32)
+ATOMIC_ACQ_REL(clear, 64)
+ATOMIC_ACQ_REL(add, 64)
+ATOMIC_ACQ_REL(subtract, 64)
+ATOMIC_ACQ_REL(set, 64)
+ATOMIC_ACQ_REL_LONG(clear)
+ATOMIC_ACQ_REL_LONG(add)
+ATOMIC_ACQ_REL_LONG(subtract)
+ATOMIC_ACQ_REL_LONG(set)
+
+#undef ATOMIC_ACQ_REL
+#undef ATOMIC_ACQ_REL_LONG
+
+static __inline uint32_t
+atomic_fetchadd_32(volatile uint32_t *p, uint32_t val)
+{
+ uint32_t tmp = 0, tmp2 = 0, ret = 0;
+
+ __asm __volatile("1: ldrex %0, [%3]\n"
+ "add %1, %0, %4\n"
+ "strex %2, %1, [%3]\n"
+ "cmp %2, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "+r" (ret), "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (p), "+r" (val) : : "cc", "memory");
+ return (ret);
+}
+
+static __inline uint32_t
+atomic_readandclear_32(volatile u_int32_t *p)
+{
+ uint32_t ret, tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%3]\n"
+ "mov %1, #0\n"
+ "strex %2, %1, [%3]\n"
+ "cmp %2, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=r" (ret), "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (p) : : "cc", "memory");
+ return (ret);
+}
+
+static __inline uint32_t
+atomic_load_acq_32(volatile uint32_t *p)
+{
+ uint32_t v;
+
+ v = *p;
+ __do_dmb();
+ return (v);
+}
+
+static __inline void
+atomic_store_rel_32(volatile uint32_t *p, uint32_t v)
+{
+
+ __do_dmb();
+ *p = v;
+}
+
+static __inline uint64_t
+atomic_fetchadd_64(volatile uint64_t *p, uint64_t val)
+{
+ uint64_t ret, tmp;
+ uint32_t exflag;
+
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[ret], [%[ptr]]\n"
+ " adds %Q[tmp], %Q[ret], %Q[val]\n"
+ " adc %R[tmp], %R[ret], %R[val]\n"
+ " strexd %[exf], %[tmp], [%[ptr]]\n"
+ " teq %[exf], #0\n"
+ " it ne \n"
+ " bne 1b\n"
+ : [ret] "=&r" (ret),
+ [exf] "=&r" (exflag),
+ [tmp] "=&r" (tmp)
+ : [ptr] "r" (p),
+ [val] "r" (val)
+ : "cc", "memory");
+ return (ret);
+}
+
+static __inline uint64_t
+atomic_readandclear_64(volatile uint64_t *p)
+{
+ uint64_t ret, tmp;
+ uint32_t exflag;
+
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[ret], [%[ptr]]\n"
+ " mov %Q[tmp], #0\n"
+ " mov %R[tmp], #0\n"
+ " strexd %[exf], %[tmp], [%[ptr]]\n"
+ " teq %[exf], #0\n"
+ " it ne \n"
+ " bne 1b\n"
+ : [ret] "=&r" (ret),
+ [exf] "=&r" (exflag),
+ [tmp] "=&r" (tmp)
+ : [ptr] "r" (p)
+ : "cc", "memory");
+ return (ret);
+}
+
+static __inline uint64_t
+atomic_load_64(volatile uint64_t *p)
+{
+ uint64_t ret;
+
+ /*
+ * The only way to atomically load 64 bits is with LDREXD which puts the
+ * exclusive monitor into the exclusive state, so reset it to open state
+ * with CLREX because we don't actually need to store anything.
+ */
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[ret], [%[ptr]]\n"
+ " clrex \n"
+ : [ret] "=&r" (ret)
+ : [ptr] "r" (p)
+ : "cc", "memory");
+ return (ret);
+}
+
+static __inline uint64_t
+atomic_load_acq_64(volatile uint64_t *p)
+{
+ uint64_t ret;
+
+ ret = atomic_load_64(p);
+ __do_dmb();
+ return (ret);
+}
+
+static __inline void
+atomic_store_64(volatile uint64_t *p, uint64_t val)
+{
+ uint64_t tmp;
+ uint32_t exflag;
+
+ /*
+ * The only way to atomically store 64 bits is with STREXD, which will
+ * succeed only if paired up with a preceeding LDREXD using the same
+ * address, so we read and discard the existing value before storing.
+ */
+ __asm __volatile(
+ "1: \n"
+ " ldrexd %[tmp], [%[ptr]]\n"
+ " strexd %[exf], %[val], [%[ptr]]\n"
+ " teq %[exf], #0\n"
+ " it ne \n"
+ " bne 1b\n"
+ : [tmp] "=&r" (tmp),
+ [exf] "=&r" (exflag)
+ : [ptr] "r" (p),
+ [val] "r" (val)
+ : "cc", "memory");
+}
+
+static __inline void
+atomic_store_rel_64(volatile uint64_t *p, uint64_t val)
+{
+
+ __do_dmb();
+ atomic_store_64(p, val);
+}
+
+static __inline u_long
+atomic_fetchadd_long(volatile u_long *p, u_long val)
+{
+ u_long tmp = 0, tmp2 = 0, ret = 0;
+
+ __asm __volatile("1: ldrex %0, [%3]\n"
+ "add %1, %0, %4\n"
+ "strex %2, %1, [%3]\n"
+ "cmp %2, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "+r" (ret), "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (p), "+r" (val) : : "cc", "memory");
+ return (ret);
+}
+
+static __inline u_long
+atomic_readandclear_long(volatile u_long *p)
+{
+ u_long ret, tmp = 0, tmp2 = 0;
+
+ __asm __volatile("1: ldrex %0, [%3]\n"
+ "mov %1, #0\n"
+ "strex %2, %1, [%3]\n"
+ "cmp %2, #0\n"
+ "it ne\n"
+ "bne 1b\n"
+ : "=r" (ret), "=&r" (tmp), "+r" (tmp2)
+ ,"+r" (p) : : "cc", "memory");
+ return (ret);
+}
+
+static __inline u_long
+atomic_load_acq_long(volatile u_long *p)
+{
+ u_long v;
+
+ v = *p;
+ __do_dmb();
+ return (v);
+}
+
+static __inline void
+atomic_store_rel_long(volatile u_long *p, u_long v)
+{
+
+ __do_dmb();
+ *p = v;
+}
+#else /* < armv6 */
+
+#define __with_interrupts_disabled(expr) \
+ do { \
+ u_int cpsr_save, tmp; \
+ \
+ __asm __volatile( \
+ "mrs %0, cpsr;" \
+ "orr %1, %0, %2;" \
+ "msr cpsr_fsxc, %1;" \
+ : "=r" (cpsr_save), "=r" (tmp) \
+ : "I" (PSR_I | PSR_F) \
+ : "cc" ); \
+ (expr); \
+ __asm __volatile( \
+ "msr cpsr_fsxc, %0" \
+ : /* no output */ \
+ : "r" (cpsr_save) \
+ : "cc" ); \
+ } while(0)
+
+static __inline uint32_t
+__swp(uint32_t val, volatile uint32_t *ptr)
+{
+ __asm __volatile("swp %0, %2, [%3]"
+ : "=&r" (val), "=m" (*ptr)
+ : "r" (val), "r" (ptr), "m" (*ptr)
+ : "memory");
+ return (val);
+}
+
+
+#ifdef _KERNEL
+#define ARM_HAVE_ATOMIC64
+
+static __inline void
+atomic_set_32(volatile uint32_t *address, uint32_t setmask)
+{
+ __with_interrupts_disabled(*address |= setmask);
+}
+
+static __inline void
+atomic_set_64(volatile uint64_t *address, uint64_t setmask)
+{
+ __with_interrupts_disabled(*address |= setmask);
+}
+
+static __inline void
+atomic_clear_32(volatile uint32_t *address, uint32_t clearmask)
+{
+ __with_interrupts_disabled(*address &= ~clearmask);
+}
+
+static __inline void
+atomic_clear_64(volatile uint64_t *address, uint64_t clearmask)
+{
+ __with_interrupts_disabled(*address &= ~clearmask);
+}
+
+static __inline u_int32_t
+atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
+{
+ int ret;
+
+ __with_interrupts_disabled(
+ {
+ if (*p == cmpval) {
+ *p = newval;
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ });
+ return (ret);
+}
+
+static __inline u_int64_t
+atomic_cmpset_64(volatile u_int64_t *p, volatile u_int64_t cmpval, volatile u_int64_t newval)
+{
+ int ret;
+
+ __with_interrupts_disabled(
+ {
+ if (*p == cmpval) {
+ *p = newval;
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ });
+ return (ret);
+}
+
+static __inline void
+atomic_add_32(volatile u_int32_t *p, u_int32_t val)
+{
+ __with_interrupts_disabled(*p += val);
+}
+
+static __inline void
+atomic_add_64(volatile u_int64_t *p, u_int64_t val)
+{
+ __with_interrupts_disabled(*p += val);
+}
+
+static __inline void
+atomic_subtract_32(volatile u_int32_t *p, u_int32_t val)
+{
+ __with_interrupts_disabled(*p -= val);
+}
+
+static __inline void
+atomic_subtract_64(volatile u_int64_t *p, u_int64_t val)
+{
+ __with_interrupts_disabled(*p -= val);
+}
+
+static __inline uint32_t
+atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
+{
+ uint32_t value;
+
+ __with_interrupts_disabled(
+ {
+ value = *p;
+ *p += v;
+ });
+ return (value);
+}
+
+static __inline uint64_t
+atomic_fetchadd_64(volatile uint64_t *p, uint64_t v)
+{
+ uint64_t value;
+
+ __with_interrupts_disabled(
+ {
+ value = *p;
+ *p += v;
+ });
+ return (value);
+}
+
+static __inline uint64_t
+atomic_load_64(volatile uint64_t *p)
+{
+ uint64_t value;
+
+ __with_interrupts_disabled(value = *p);
+ return (value);
+}
+
+static __inline void
+atomic_store_64(volatile uint64_t *p, uint64_t value)
+{
+ __with_interrupts_disabled(*p = value);
+}
+
+#else /* !_KERNEL */
+
+static __inline u_int32_t
+atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
+{
+ register int done, ras_start = ARM_RAS_START;
+
+ __asm __volatile("1:\n"
+ "adr %1, 1b\n"
+ "str %1, [%0]\n"
+ "adr %1, 2f\n"
+ "str %1, [%0, #4]\n"
+ "ldr %1, [%2]\n"
+ "cmp %1, %3\n"
+ "streq %4, [%2]\n"
+ "2:\n"
+ "mov %1, #0\n"
+ "str %1, [%0]\n"
+ "mov %1, #0xffffffff\n"
+ "str %1, [%0, #4]\n"
+ "moveq %1, #1\n"
+ "movne %1, #0\n"
+ : "+r" (ras_start), "=r" (done)
+ ,"+r" (p), "+r" (cmpval), "+r" (newval) : : "cc", "memory");
+ return (done);
+}
+
+static __inline void
+atomic_add_32(volatile u_int32_t *p, u_int32_t val)
+{
+ int start, ras_start = ARM_RAS_START;
+
+ __asm __volatile("1:\n"
+ "adr %1, 1b\n"
+ "str %1, [%0]\n"
+ "adr %1, 2f\n"
+ "str %1, [%0, #4]\n"
+ "ldr %1, [%2]\n"
+ "add %1, %1, %3\n"
+ "str %1, [%2]\n"
+ "2:\n"
+ "mov %1, #0\n"
+ "str %1, [%0]\n"
+ "mov %1, #0xffffffff\n"
+ "str %1, [%0, #4]\n"
+ : "+r" (ras_start), "=r" (start), "+r" (p), "+r" (val)
+ : : "memory");
+}
+
+static __inline void
+atomic_subtract_32(volatile u_int32_t *p, u_int32_t val)
+{
+ int start, ras_start = ARM_RAS_START;
+
+ __asm __volatile("1:\n"
+ "adr %1, 1b\n"
+ "str %1, [%0]\n"
+ "adr %1, 2f\n"
+ "str %1, [%0, #4]\n"
+ "ldr %1, [%2]\n"
+ "sub %1, %1, %3\n"
+ "str %1, [%2]\n"
+ "2:\n"
+ "mov %1, #0\n"
+ "str %1, [%0]\n"
+ "mov %1, #0xffffffff\n"
+ "str %1, [%0, #4]\n"
+
+ : "+r" (ras_start), "=r" (start), "+r" (p), "+r" (val)
+ : : "memory");
+}
+
+static __inline void
+atomic_set_32(volatile uint32_t *address, uint32_t setmask)
+{
+ int start, ras_start = ARM_RAS_START;
+
+ __asm __volatile("1:\n"
+ "adr %1, 1b\n"
+ "str %1, [%0]\n"
+ "adr %1, 2f\n"
+ "str %1, [%0, #4]\n"
+ "ldr %1, [%2]\n"
+ "orr %1, %1, %3\n"
+ "str %1, [%2]\n"
+ "2:\n"
+ "mov %1, #0\n"
+ "str %1, [%0]\n"
+ "mov %1, #0xffffffff\n"
+ "str %1, [%0, #4]\n"
+
+ : "+r" (ras_start), "=r" (start), "+r" (address), "+r" (setmask)
+ : : "memory");
+}
+
+static __inline void
+atomic_clear_32(volatile uint32_t *address, uint32_t clearmask)
+{
+ int start, ras_start = ARM_RAS_START;
+
+ __asm __volatile("1:\n"
+ "adr %1, 1b\n"
+ "str %1, [%0]\n"
+ "adr %1, 2f\n"
+ "str %1, [%0, #4]\n"
+ "ldr %1, [%2]\n"
+ "bic %1, %1, %3\n"
+ "str %1, [%2]\n"
+ "2:\n"
+ "mov %1, #0\n"
+ "str %1, [%0]\n"
+ "mov %1, #0xffffffff\n"
+ "str %1, [%0, #4]\n"
+ : "+r" (ras_start), "=r" (start), "+r" (address), "+r" (clearmask)
+ : : "memory");
+
+}
+
+static __inline uint32_t
+atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
+{
+ uint32_t start, tmp, ras_start = ARM_RAS_START;
+
+ __asm __volatile("1:\n"
+ "adr %1, 1b\n"
+ "str %1, [%0]\n"
+ "adr %1, 2f\n"
+ "str %1, [%0, #4]\n"
+ "ldr %1, [%3]\n"
+ "mov %2, %1\n"
+ "add %2, %2, %4\n"
+ "str %2, [%3]\n"
+ "2:\n"
+ "mov %2, #0\n"
+ "str %2, [%0]\n"
+ "mov %2, #0xffffffff\n"
+ "str %2, [%0, #4]\n"
+ : "+r" (ras_start), "=r" (start), "=r" (tmp), "+r" (p), "+r" (v)
+ : : "memory");
+ return (start);
+}
+
+#endif /* _KERNEL */
+
+
+static __inline uint32_t
+atomic_readandclear_32(volatile u_int32_t *p)
+{
+
+ return (__swp(0, p));
+}
+
+#define atomic_cmpset_rel_32 atomic_cmpset_32
+#define atomic_cmpset_acq_32 atomic_cmpset_32
+#define atomic_set_rel_32 atomic_set_32
+#define atomic_set_acq_32 atomic_set_32
+#define atomic_clear_rel_32 atomic_clear_32
+#define atomic_clear_acq_32 atomic_clear_32
+#define atomic_add_rel_32 atomic_add_32
+#define atomic_add_acq_32 atomic_add_32
+#define atomic_subtract_rel_32 atomic_subtract_32
+#define atomic_subtract_acq_32 atomic_subtract_32
+#define atomic_store_rel_32 atomic_store_32
+#define atomic_store_rel_long atomic_store_long
+#define atomic_load_acq_32 atomic_load_32
+#define atomic_load_acq_long atomic_load_long
+#define atomic_add_acq_long atomic_add_long
+#define atomic_add_rel_long atomic_add_long
+#define atomic_subtract_acq_long atomic_subtract_long
+#define atomic_subtract_rel_long atomic_subtract_long
+#define atomic_clear_acq_long atomic_clear_long
+#define atomic_clear_rel_long atomic_clear_long
+#define atomic_set_acq_long atomic_set_long
+#define atomic_set_rel_long atomic_set_long
+#define atomic_cmpset_acq_long atomic_cmpset_long
+#define atomic_cmpset_rel_long atomic_cmpset_long
+#define atomic_load_acq_long atomic_load_long
+#undef __with_interrupts_disabled
+
+static __inline void
+atomic_add_long(volatile u_long *p, u_long v)
+{
+
+ atomic_add_32((volatile uint32_t *)p, v);
+}
+
+static __inline void
+atomic_clear_long(volatile u_long *p, u_long v)
+{
+
+ atomic_clear_32((volatile uint32_t *)p, v);
+}
+
+static __inline int
+atomic_cmpset_long(volatile u_long *dst, u_long old, u_long newe)
+{
+
+ return (atomic_cmpset_32((volatile uint32_t *)dst, old, newe));
+}
+
+static __inline u_long
+atomic_fetchadd_long(volatile u_long *p, u_long v)
+{
+
+ return (atomic_fetchadd_32((volatile uint32_t *)p, v));
+}
+
+static __inline void
+atomic_readandclear_long(volatile u_long *p)
+{
+
+ atomic_readandclear_32((volatile uint32_t *)p);
+}
+
+static __inline void
+atomic_set_long(volatile u_long *p, u_long v)
+{
+
+ atomic_set_32((volatile uint32_t *)p, v);
+}
+
+static __inline void
+atomic_subtract_long(volatile u_long *p, u_long v)
+{
+
+ atomic_subtract_32((volatile uint32_t *)p, v);
+}
+
+
+
+#endif /* Arch >= v6 */
+
+static __inline int
+atomic_load_32(volatile uint32_t *v)
+{
+
+ return (*v);
+}
+
+static __inline void
+atomic_store_32(volatile uint32_t *dst, uint32_t src)
+{
+ *dst = src;
+}
+
+static __inline int
+atomic_load_long(volatile u_long *v)
+{
+
+ return (*v);
+}
+
+static __inline void
+atomic_store_long(volatile u_long *dst, u_long src)
+{
+ *dst = src;
+}
+
+#define atomic_clear_ptr atomic_clear_32
+#define atomic_set_ptr atomic_set_32
+#define atomic_cmpset_ptr atomic_cmpset_32
+#define atomic_cmpset_rel_ptr atomic_cmpset_rel_32
+#define atomic_cmpset_acq_ptr atomic_cmpset_acq_32
+#define atomic_store_ptr atomic_store_32
+#define atomic_store_rel_ptr atomic_store_rel_32
+
+#define atomic_add_int atomic_add_32
+#define atomic_add_acq_int atomic_add_acq_32
+#define atomic_add_rel_int atomic_add_rel_32
+#define atomic_subtract_int atomic_subtract_32
+#define atomic_subtract_acq_int atomic_subtract_acq_32
+#define atomic_subtract_rel_int atomic_subtract_rel_32
+#define atomic_clear_int atomic_clear_32
+#define atomic_clear_acq_int atomic_clear_acq_32
+#define atomic_clear_rel_int atomic_clear_rel_32
+#define atomic_set_int atomic_set_32
+#define atomic_set_acq_int atomic_set_acq_32
+#define atomic_set_rel_int atomic_set_rel_32
+#define atomic_cmpset_int atomic_cmpset_32
+#define atomic_cmpset_acq_int atomic_cmpset_acq_32
+#define atomic_cmpset_rel_int atomic_cmpset_rel_32
+#define atomic_fetchadd_int atomic_fetchadd_32
+#define atomic_readandclear_int atomic_readandclear_32
+#define atomic_load_acq_int atomic_load_acq_32
+#define atomic_store_rel_int atomic_store_rel_32
+
+#endif /* _MACHINE_ATOMIC_H_ */
Property changes on: trunk/sys/arm/include/atomic.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/blockio.h
===================================================================
--- trunk/sys/arm/include/blockio.h (rev 0)
+++ trunk/sys/arm/include/blockio.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,57 @@
+/* $MidnightBSD$ */
+/* $NetBSD: blockio.h,v 1.2 2001/06/02 10:44:56 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ben Harris
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/blockio.h 236992 2012-06-13 05:02:51Z imp $
+ *
+ */
+/*
+ * blockio.h - low level functions for bulk PIO data transfer
+ */
+
+#ifndef _MACHINE_BLOCKIO_H_
+#define _MACHINE_BLOCKIO_H_
+
+/*
+ * All these take three arguments:
+ * I/O address
+ * Memory address
+ * Number of bytes to copy
+ */
+
+void read_multi_1(u_int, void *, u_int);
+void write_multi_1(u_int, const void *, u_int);
+#define read_multi_2 insw16
+#define write_multi_2 outsw16
+
+void insw(u_int, void *, u_int);
+void outsw(u_int, void *, u_int);
+void insw16(u_int, void *, u_int);
+void outsw16(u_int, void *, u_int);
+
+#endif /* !_MACHINE_BLOCKIO_H_ */
Property changes on: trunk/sys/arm/include/blockio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/board.h
===================================================================
--- trunk/sys/arm/include/board.h (rev 0)
+++ trunk/sys/arm/include/board.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,63 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/include/board.h 238189 2012-07-07 05:02:39Z imp $ */
+
+#ifndef _ARM_INCLUDE_BOARD_H_
+#define _ARM_INCLUDE_BOARD_H_
+
+#include <sys/linker_set.h>
+
+typedef long (arm_board_init_fn)(void);
+
+struct arm_board {
+ int board_id; /* Board ID from the boot loader */
+ const char *board_name; /* Human readable name */
+ arm_board_init_fn *board_init; /* Board initialize code */
+};
+
+#if defined(ARM_MANY_BOARD)
+
+#include "board_id.h"
+
+#define ARM_BOARD(id, name) \
+ static struct arm_board this_board = { \
+ .board_id = ARM_BOARD_ID_ ## id, \
+ .board_name = name, \
+ .board_init = board_init, \
+ }; \
+ DATA_SET(arm_boards, this_board);
+#define BOARD_INIT static
+
+#else /* !ARM_MANY_BOARD */
+
+#define ARM_BOARD(id, name)
+extern arm_board_init_fn board_init;
+#define BOARD_INIT
+
+#endif /* ARM_MANY_BOARD */
+
+#endif /* _ARM_INCLUDE_BOARD_H_ */
Property changes on: trunk/sys/arm/include/board.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/bootconfig.h
===================================================================
--- trunk/sys/arm/include/bootconfig.h (rev 0)
+++ trunk/sys/arm/include/bootconfig.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,59 @@
+/* $MidnightBSD$ */
+/* $NetBSD: bootconfig.h,v 1.1 2001/05/13 13:46:23 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/bootconfig.h 167752 2007-03-21 03:28:16Z kevlo $
+ */
+
+#ifndef _MACHINE_BOOTCONFIG_H_
+#define _MACHINE_BOOTCONFIG_H_
+
+#ifdef _KERNEL
+#define BOOTOPT_TYPE_BOOLEAN 0
+#define BOOTOPT_TYPE_STRING 1
+#define BOOTOPT_TYPE_INT 2
+#define BOOTOPT_TYPE_BININT 3
+#define BOOTOPT_TYPE_HEXINT 4
+#define BOOTOPT_TYPE_MASK 7
+
+int get_bootconf_option (char *, char *, int, void *);
+
+extern char *boot_args;
+extern char *boot_file;
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_BOOTCONFIG_H_ */
Property changes on: trunk/sys/arm/include/bootconfig.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/bus.h
===================================================================
--- trunk/sys/arm/include/bus.h (rev 0)
+++ trunk/sys/arm/include/bus.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,766 @@
+/* $MidnightBSD$ */
+/* $NetBSD: bus.h,v 1.11 2003/07/28 17:35:54 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/bus.h 278727 2015-02-13 22:32:02Z ian $
+ */
+
+#ifndef _MACHINE_BUS_H_
+#define _MACHINE_BUS_H_
+
+#include <machine/_bus.h>
+
+/*
+ * int bus_space_map (bus_space_tag_t t, bus_addr_t addr,
+ * bus_size_t size, int flags, bus_space_handle_t *bshp);
+ *
+ * Map a region of bus space.
+ */
+
+#define BUS_SPACE_MAP_CACHEABLE 0x01
+#define BUS_SPACE_MAP_LINEAR 0x02
+#define BUS_SPACE_MAP_PREFETCHABLE 0x04
+
+/*
+ * Bus space for ARM.
+ *
+ * The functions used most often are grouped together at the beginning to ensure
+ * that all the data fits into a single cache line. The inline implementations
+ * of single read/write access these values a lot.
+ */
+struct bus_space {
+ /* Read/write single and barrier: the most commonly used functions. */
+ uint8_t (*bs_r_1)(bus_space_tag_t, bus_space_handle_t, bus_size_t);
+ uint32_t (*bs_r_4)(bus_space_tag_t, bus_space_handle_t, bus_size_t);
+ void (*bs_w_1)(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint8_t);
+ void (*bs_w_4)(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint32_t);
+ void (*bs_barrier)(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, bus_size_t, int);
+
+ /* Backlink to parent (if copied), and implementation private data. */
+ struct bus_space *bs_parent;
+ void *bs_privdata;
+
+ /* mapping/unmapping */
+ int (*bs_map) (bus_space_tag_t, bus_addr_t, bus_size_t,
+ int, bus_space_handle_t *);
+ void (*bs_unmap) (bus_space_tag_t, bus_space_handle_t, bus_size_t);
+ int (*bs_subregion) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, bus_size_t, bus_space_handle_t *);
+
+ /* allocation/deallocation */
+ int (*bs_alloc) (bus_space_tag_t, bus_addr_t, bus_addr_t,
+ bus_size_t, bus_size_t, bus_size_t, int,
+ bus_addr_t *, bus_space_handle_t *);
+ void (*bs_free) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t);
+
+ /* Read single, the less commonly used functions. */
+ uint16_t (*bs_r_2) (bus_space_tag_t, bus_space_handle_t, bus_size_t);
+ uint64_t (*bs_r_8) (bus_space_tag_t, bus_space_handle_t, bus_size_t);
+
+ /* read multiple */
+ void (*bs_rm_1) (bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ uint8_t *, bus_size_t);
+ void (*bs_rm_2) (bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ uint16_t *, bus_size_t);
+ void (*bs_rm_4) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint32_t *, bus_size_t);
+ void (*bs_rm_8) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint64_t *, bus_size_t);
+
+ /* read region */
+ void (*bs_rr_1) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint8_t *, bus_size_t);
+ void (*bs_rr_2) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint16_t *, bus_size_t);
+ void (*bs_rr_4) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint32_t *, bus_size_t);
+ void (*bs_rr_8) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint64_t *, bus_size_t);
+
+ /* Write single, the less commonly used functions. */
+ void (*bs_w_2) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint16_t);
+ void (*bs_w_8) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint64_t);
+
+ /* write multiple */
+ void (*bs_wm_1) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint8_t *, bus_size_t);
+ void (*bs_wm_2) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint16_t *, bus_size_t);
+ void (*bs_wm_4) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint32_t *, bus_size_t);
+ void (*bs_wm_8) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint64_t *, bus_size_t);
+
+ /* write region */
+ void (*bs_wr_1) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint8_t *, bus_size_t);
+ void (*bs_wr_2) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint16_t *, bus_size_t);
+ void (*bs_wr_4) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint32_t *, bus_size_t);
+ void (*bs_wr_8) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint64_t *, bus_size_t);
+
+ /* set multiple */
+ void (*bs_sm_1) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint8_t, bus_size_t);
+ void (*bs_sm_2) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint16_t, bus_size_t);
+ void (*bs_sm_4) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint32_t, bus_size_t);
+ void (*bs_sm_8) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint64_t, bus_size_t);
+
+ /* set region */
+ void (*bs_sr_1) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint8_t, bus_size_t);
+ void (*bs_sr_2) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint16_t, bus_size_t);
+ void (*bs_sr_4) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint32_t, bus_size_t);
+ void (*bs_sr_8) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint64_t, bus_size_t);
+
+ /* copy */
+ void (*bs_c_1) (bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ bus_space_handle_t, bus_size_t, bus_size_t);
+ void (*bs_c_2) (bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ bus_space_handle_t, bus_size_t, bus_size_t);
+ void (*bs_c_4) (bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ bus_space_handle_t, bus_size_t, bus_size_t);
+ void (*bs_c_8) (bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ bus_space_handle_t, bus_size_t, bus_size_t);
+
+ /* read stream (single) */
+ uint8_t (*bs_r_1_s) (bus_space_tag_t, bus_space_handle_t, bus_size_t);
+ uint16_t (*bs_r_2_s) (bus_space_tag_t, bus_space_handle_t, bus_size_t);
+ uint32_t (*bs_r_4_s) (bus_space_tag_t, bus_space_handle_t, bus_size_t);
+ uint64_t (*bs_r_8_s) (bus_space_tag_t, bus_space_handle_t, bus_size_t);
+
+ /* read multiple stream */
+ void (*bs_rm_1_s) (bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ uint8_t *, bus_size_t);
+ void (*bs_rm_2_s) (bus_space_tag_t, bus_space_handle_t, bus_size_t,
+ uint16_t *, bus_size_t);
+ void (*bs_rm_4_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint32_t *, bus_size_t);
+ void (*bs_rm_8_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint64_t *, bus_size_t);
+
+ /* read region stream */
+ void (*bs_rr_1_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint8_t *, bus_size_t);
+ void (*bs_rr_2_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint16_t *, bus_size_t);
+ void (*bs_rr_4_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint32_t *, bus_size_t);
+ void (*bs_rr_8_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint64_t *, bus_size_t);
+
+ /* write stream (single) */
+ void (*bs_w_1_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint8_t);
+ void (*bs_w_2_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint16_t);
+ void (*bs_w_4_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint32_t);
+ void (*bs_w_8_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, uint64_t);
+
+ /* write multiple stream */
+ void (*bs_wm_1_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint8_t *, bus_size_t);
+ void (*bs_wm_2_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint16_t *, bus_size_t);
+ void (*bs_wm_4_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint32_t *, bus_size_t);
+ void (*bs_wm_8_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint64_t *, bus_size_t);
+
+ /* write region stream */
+ void (*bs_wr_1_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint8_t *, bus_size_t);
+ void (*bs_wr_2_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint16_t *, bus_size_t);
+ void (*bs_wr_4_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint32_t *, bus_size_t);
+ void (*bs_wr_8_s) (bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, const uint64_t *, bus_size_t);
+};
+
+extern bus_space_tag_t arm_base_bs_tag;
+
+/*
+ * Utility macros; INTERNAL USE ONLY.
+ */
+#define __bs_c(a,b) __CONCAT(a,b)
+#define __bs_opname(op,size) __bs_c(__bs_c(__bs_c(bs_,op),_),size)
+
+#define __bs_nonsingle(type, sz, t, h, o, a, c) \
+ (*(t)->__bs_opname(type,sz))((t), h, o, a, c)
+#define __bs_set(type, sz, t, h, o, v, c) \
+ (*(t)->__bs_opname(type,sz))((t), h, o, v, c)
+#define __bs_copy(sz, t, h1, o1, h2, o2, cnt) \
+ (*(t)->__bs_opname(c,sz))((t), h1, o1, h2, o2, cnt)
+
+#define __bs_opname_s(op,size) __bs_c(__bs_c(__bs_c(__bs_c(bs_,op),_),size),_s)
+#define __bs_rs_s(sz, t, h, o) \
+ (*(t)->__bs_opname_s(r,sz))((t), h, o)
+#define __bs_ws_s(sz, t, h, o, v) \
+ (*(t)->__bs_opname_s(w,sz))((t), h, o, v)
+#define __bs_nonsingle_s(type, sz, t, h, o, a, c) \
+ (*(t)->__bs_opname_s(type,sz))((t), h, o, a, c)
+
+
+#define __generate_inline_bs_rs(IFN, MBR, TYP) \
+ static inline TYP \
+ IFN(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) \
+ { \
+ \
+ if (__predict_true(t->MBR == NULL)) \
+ return (*(volatile TYP *)(h + o)); \
+ else \
+ return (t->MBR(t, h, o)); \
+ }
+
+#define __generate_inline_bs_ws(IFN, MBR, TYP) \
+ static inline void \
+ IFN(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, TYP v)\
+ { \
+ \
+ if (__predict_true(t->MBR == NULL)) \
+ *(volatile TYP *)(h + o) = v; \
+ else \
+ t->MBR(t, h, o, v); \
+ }
+
+/*
+ * Mapping and unmapping operations.
+ */
+#define bus_space_map(t, a, s, c, hp) \
+ (*(t)->bs_map)((t), (a), (s), (c), (hp))
+#define bus_space_unmap(t, h, s) \
+ (*(t)->bs_unmap)((t), (h), (s))
+#define bus_space_subregion(t, h, o, s, hp) \
+ (*(t)->bs_subregion)((t), (h), (o), (s), (hp))
+
+
+/*
+ * Allocation and deallocation operations.
+ */
+#define bus_space_alloc(t, rs, re, s, a, b, c, ap, hp) \
+ (*(t)->bs_alloc)((t), (rs), (re), (s), (a), (b), \
+ (c), (ap), (hp))
+#define bus_space_free(t, h, s) \
+ (*(t)->bs_free)((t), (h), (s))
+
+/*
+ * Bus barrier operations.
+ */
+#define bus_space_barrier(t, h, o, l, f) \
+ (*(t)->bs_barrier)((t), (h), (o), (l), (f))
+
+#define BUS_SPACE_BARRIER_READ 0x01
+#define BUS_SPACE_BARRIER_WRITE 0x02
+
+/*
+ * Bus read (single) operations.
+ */
+__generate_inline_bs_rs(bus_space_read_1, bs_r_1, uint8_t);
+__generate_inline_bs_rs(bus_space_read_2, bs_r_2, uint16_t);
+__generate_inline_bs_rs(bus_space_read_4, bs_r_4, uint32_t);
+__generate_inline_bs_rs(bus_space_read_8, bs_r_8, uint64_t);
+
+__generate_inline_bs_rs(bus_space_read_stream_1, bs_r_1_s, uint8_t);
+__generate_inline_bs_rs(bus_space_read_stream_2, bs_r_2_s, uint16_t);
+__generate_inline_bs_rs(bus_space_read_stream_4, bs_r_4_s, uint32_t);
+__generate_inline_bs_rs(bus_space_read_stream_8, bs_r_8_s, uint64_t);
+
+/*
+ * Bus read multiple operations.
+ */
+#define bus_space_read_multi_1(t, h, o, a, c) \
+ __bs_nonsingle(rm,1,(t),(h),(o),(a),(c))
+#define bus_space_read_multi_2(t, h, o, a, c) \
+ __bs_nonsingle(rm,2,(t),(h),(o),(a),(c))
+#define bus_space_read_multi_4(t, h, o, a, c) \
+ __bs_nonsingle(rm,4,(t),(h),(o),(a),(c))
+#define bus_space_read_multi_8(t, h, o, a, c) \
+ __bs_nonsingle(rm,8,(t),(h),(o),(a),(c))
+
+#define bus_space_read_multi_stream_1(t, h, o, a, c) \
+ __bs_nonsingle_s(rm,1,(t),(h),(o),(a),(c))
+#define bus_space_read_multi_stream_2(t, h, o, a, c) \
+ __bs_nonsingle_s(rm,2,(t),(h),(o),(a),(c))
+#define bus_space_read_multi_stream_4(t, h, o, a, c) \
+ __bs_nonsingle_s(rm,4,(t),(h),(o),(a),(c))
+#define bus_space_read_multi_stream_8(t, h, o, a, c) \
+ __bs_nonsingle_s(rm,8,(t),(h),(o),(a),(c))
+
+
+/*
+ * Bus read region operations.
+ */
+#define bus_space_read_region_1(t, h, o, a, c) \
+ __bs_nonsingle(rr,1,(t),(h),(o),(a),(c))
+#define bus_space_read_region_2(t, h, o, a, c) \
+ __bs_nonsingle(rr,2,(t),(h),(o),(a),(c))
+#define bus_space_read_region_4(t, h, o, a, c) \
+ __bs_nonsingle(rr,4,(t),(h),(o),(a),(c))
+#define bus_space_read_region_8(t, h, o, a, c) \
+ __bs_nonsingle(rr,8,(t),(h),(o),(a),(c))
+
+#define bus_space_read_region_stream_1(t, h, o, a, c) \
+ __bs_nonsingle_s(rr,1,(t),(h),(o),(a),(c))
+#define bus_space_read_region_stream_2(t, h, o, a, c) \
+ __bs_nonsingle_s(rr,2,(t),(h),(o),(a),(c))
+#define bus_space_read_region_stream_4(t, h, o, a, c) \
+ __bs_nonsingle_s(rr,4,(t),(h),(o),(a),(c))
+#define bus_space_read_region_stream_8(t, h, o, a, c) \
+ __bs_nonsingle_s(rr,8,(t),(h),(o),(a),(c))
+
+
+/*
+ * Bus write (single) operations.
+ */
+__generate_inline_bs_ws(bus_space_write_1, bs_w_1, uint8_t);
+__generate_inline_bs_ws(bus_space_write_2, bs_w_2, uint16_t);
+__generate_inline_bs_ws(bus_space_write_4, bs_w_4, uint32_t);
+__generate_inline_bs_ws(bus_space_write_8, bs_w_8, uint64_t);
+
+__generate_inline_bs_ws(bus_space_write_stream_1, bs_w_1_s, uint8_t);
+__generate_inline_bs_ws(bus_space_write_stream_2, bs_w_2_s, uint16_t);
+__generate_inline_bs_ws(bus_space_write_stream_4, bs_w_4_s, uint32_t);
+__generate_inline_bs_ws(bus_space_write_stream_8, bs_w_8_s, uint64_t);
+
+
+/*
+ * Bus write multiple operations.
+ */
+#define bus_space_write_multi_1(t, h, o, a, c) \
+ __bs_nonsingle(wm,1,(t),(h),(o),(a),(c))
+#define bus_space_write_multi_2(t, h, o, a, c) \
+ __bs_nonsingle(wm,2,(t),(h),(o),(a),(c))
+#define bus_space_write_multi_4(t, h, o, a, c) \
+ __bs_nonsingle(wm,4,(t),(h),(o),(a),(c))
+#define bus_space_write_multi_8(t, h, o, a, c) \
+ __bs_nonsingle(wm,8,(t),(h),(o),(a),(c))
+
+#define bus_space_write_multi_stream_1(t, h, o, a, c) \
+ __bs_nonsingle_s(wm,1,(t),(h),(o),(a),(c))
+#define bus_space_write_multi_stream_2(t, h, o, a, c) \
+ __bs_nonsingle_s(wm,2,(t),(h),(o),(a),(c))
+#define bus_space_write_multi_stream_4(t, h, o, a, c) \
+ __bs_nonsingle_s(wm,4,(t),(h),(o),(a),(c))
+#define bus_space_write_multi_stream_8(t, h, o, a, c) \
+ __bs_nonsingle_s(wm,8,(t),(h),(o),(a),(c))
+
+
+/*
+ * Bus write region operations.
+ */
+#define bus_space_write_region_1(t, h, o, a, c) \
+ __bs_nonsingle(wr,1,(t),(h),(o),(a),(c))
+#define bus_space_write_region_2(t, h, o, a, c) \
+ __bs_nonsingle(wr,2,(t),(h),(o),(a),(c))
+#define bus_space_write_region_4(t, h, o, a, c) \
+ __bs_nonsingle(wr,4,(t),(h),(o),(a),(c))
+#define bus_space_write_region_8(t, h, o, a, c) \
+ __bs_nonsingle(wr,8,(t),(h),(o),(a),(c))
+
+#define bus_space_write_region_stream_1(t, h, o, a, c) \
+ __bs_nonsingle_s(wr,1,(t),(h),(o),(a),(c))
+#define bus_space_write_region_stream_2(t, h, o, a, c) \
+ __bs_nonsingle_s(wr,2,(t),(h),(o),(a),(c))
+#define bus_space_write_region_stream_4(t, h, o, a, c) \
+ __bs_nonsingle_s(wr,4,(t),(h),(o),(a),(c))
+#define bus_space_write_region_stream_8(t, h, o, a, c) \
+ __bs_nonsingle_s(wr,8,(t),(h),(o),(a),(c))
+
+
+/*
+ * Set multiple operations.
+ */
+#define bus_space_set_multi_1(t, h, o, v, c) \
+ __bs_set(sm,1,(t),(h),(o),(v),(c))
+#define bus_space_set_multi_2(t, h, o, v, c) \
+ __bs_set(sm,2,(t),(h),(o),(v),(c))
+#define bus_space_set_multi_4(t, h, o, v, c) \
+ __bs_set(sm,4,(t),(h),(o),(v),(c))
+#define bus_space_set_multi_8(t, h, o, v, c) \
+ __bs_set(sm,8,(t),(h),(o),(v),(c))
+
+
+/*
+ * Set region operations.
+ */
+#define bus_space_set_region_1(t, h, o, v, c) \
+ __bs_set(sr,1,(t),(h),(o),(v),(c))
+#define bus_space_set_region_2(t, h, o, v, c) \
+ __bs_set(sr,2,(t),(h),(o),(v),(c))
+#define bus_space_set_region_4(t, h, o, v, c) \
+ __bs_set(sr,4,(t),(h),(o),(v),(c))
+#define bus_space_set_region_8(t, h, o, v, c) \
+ __bs_set(sr,8,(t),(h),(o),(v),(c))
+
+
+/*
+ * Copy operations.
+ */
+#define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \
+ __bs_copy(1, t, h1, o1, h2, o2, c)
+#define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \
+ __bs_copy(2, t, h1, o1, h2, o2, c)
+#define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \
+ __bs_copy(4, t, h1, o1, h2, o2, c)
+#define bus_space_copy_region_8(t, h1, o1, h2, o2, c) \
+ __bs_copy(8, t, h1, o1, h2, o2, c)
+
+/*
+ * Macros to provide prototypes for all the functions used in the
+ * bus_space structure
+ */
+
+#define bs_map_proto(f) \
+int __bs_c(f,_bs_map) (bus_space_tag_t t, bus_addr_t addr, \
+ bus_size_t size, int cacheable, bus_space_handle_t *bshp);
+
+#define bs_unmap_proto(f) \
+void __bs_c(f,_bs_unmap) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t size);
+
+#define bs_subregion_proto(f) \
+int __bs_c(f,_bs_subregion) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, bus_size_t size, \
+ bus_space_handle_t *nbshp);
+
+#define bs_alloc_proto(f) \
+int __bs_c(f,_bs_alloc) (bus_space_tag_t t, bus_addr_t rstart, \
+ bus_addr_t rend, bus_size_t size, bus_size_t align, \
+ bus_size_t boundary, int cacheable, bus_addr_t *addrp, \
+ bus_space_handle_t *bshp);
+
+#define bs_free_proto(f) \
+void __bs_c(f,_bs_free) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t size);
+
+#define bs_mmap_proto(f) \
+int __bs_c(f,_bs_mmap) (struct cdev *, vm_offset_t, vm_paddr_t *, int);
+
+#define bs_barrier_proto(f) \
+void __bs_c(f,_bs_barrier) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, bus_size_t len, int flags);
+
+#define bs_r_1_proto(f) \
+uint8_t __bs_c(f,_bs_r_1) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset);
+
+#define bs_r_2_proto(f) \
+uint16_t __bs_c(f,_bs_r_2) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset);
+
+#define bs_r_4_proto(f) \
+uint32_t __bs_c(f,_bs_r_4) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset);
+
+#define bs_r_8_proto(f) \
+uint64_t __bs_c(f,_bs_r_8) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset);
+
+#define bs_r_1_s_proto(f) \
+uint8_t __bs_c(f,_bs_r_1_s) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset);
+
+#define bs_r_2_s_proto(f) \
+uint16_t __bs_c(f,_bs_r_2_s) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset);
+
+#define bs_r_4_s_proto(f) \
+uint32_t __bs_c(f,_bs_r_4_s) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset);
+
+#define bs_w_1_proto(f) \
+void __bs_c(f,_bs_w_1) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint8_t value);
+
+#define bs_w_2_proto(f) \
+void __bs_c(f,_bs_w_2) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint16_t value);
+
+#define bs_w_4_proto(f) \
+void __bs_c(f,_bs_w_4) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint32_t value);
+
+#define bs_w_8_proto(f) \
+void __bs_c(f,_bs_w_8) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint64_t value);
+
+#define bs_w_1_s_proto(f) \
+void __bs_c(f,_bs_w_1_s) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint8_t value);
+
+#define bs_w_2_s_proto(f) \
+void __bs_c(f,_bs_w_2_s) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint16_t value);
+
+#define bs_w_4_s_proto(f) \
+void __bs_c(f,_bs_w_4_s) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint32_t value);
+
+#define bs_rm_1_proto(f) \
+void __bs_c(f,_bs_rm_1) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint8_t *addr, bus_size_t count);
+
+#define bs_rm_2_proto(f) \
+void __bs_c(f,_bs_rm_2) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint16_t *addr, bus_size_t count);
+
+#define bs_rm_4_proto(f) \
+void __bs_c(f,_bs_rm_4) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint32_t *addr, bus_size_t count);
+
+#define bs_rm_8_proto(f) \
+void __bs_c(f,_bs_rm_8) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint64_t *addr, bus_size_t count);
+
+#define bs_wm_1_proto(f) \
+void __bs_c(f,_bs_wm_1) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, const uint8_t *addr, bus_size_t count);
+
+#define bs_wm_2_proto(f) \
+void __bs_c(f,_bs_wm_2) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, const uint16_t *addr, bus_size_t count);
+
+#define bs_wm_4_proto(f) \
+void __bs_c(f,_bs_wm_4) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, const uint32_t *addr, bus_size_t count);
+
+#define bs_wm_8_proto(f) \
+void __bs_c(f,_bs_wm_8) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, const uint64_t *addr, bus_size_t count);
+
+#define bs_rr_1_proto(f) \
+void __bs_c(f, _bs_rr_1) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint8_t *addr, bus_size_t count);
+
+#define bs_rr_2_proto(f) \
+void __bs_c(f, _bs_rr_2) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint16_t *addr, bus_size_t count);
+
+#define bs_rr_4_proto(f) \
+void __bs_c(f, _bs_rr_4) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint32_t *addr, bus_size_t count);
+
+#define bs_rr_8_proto(f) \
+void __bs_c(f, _bs_rr_8) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint64_t *addr, bus_size_t count);
+
+#define bs_wr_1_proto(f) \
+void __bs_c(f, _bs_wr_1) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, const uint8_t *addr, bus_size_t count);
+
+#define bs_wr_2_proto(f) \
+void __bs_c(f, _bs_wr_2) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, const uint16_t *addr, bus_size_t count);
+
+#define bs_wr_4_proto(f) \
+void __bs_c(f, _bs_wr_4) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, const uint32_t *addr, bus_size_t count);
+
+#define bs_wr_8_proto(f) \
+void __bs_c(f, _bs_wr_8) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, const uint64_t *addr, bus_size_t count);
+
+#define bs_sm_1_proto(f) \
+void __bs_c(f,_bs_sm_1) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint8_t value, bus_size_t count);
+
+#define bs_sm_2_proto(f) \
+void __bs_c(f,_bs_sm_2) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint16_t value, bus_size_t count);
+
+#define bs_sm_4_proto(f) \
+void __bs_c(f,_bs_sm_4) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint32_t value, bus_size_t count);
+
+#define bs_sm_8_proto(f) \
+void __bs_c(f,_bs_sm_8) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint64_t value, bus_size_t count);
+
+#define bs_sr_1_proto(f) \
+void __bs_c(f,_bs_sr_1) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint8_t value, bus_size_t count);
+
+#define bs_sr_2_proto(f) \
+void __bs_c(f,_bs_sr_2) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint16_t value, bus_size_t count);
+
+#define bs_sr_4_proto(f) \
+void __bs_c(f,_bs_sr_4) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint32_t value, bus_size_t count);
+
+#define bs_sr_8_proto(f) \
+void __bs_c(f,_bs_sr_8) (bus_space_tag_t t, bus_space_handle_t bsh, \
+ bus_size_t offset, uint64_t value, bus_size_t count);
+
+#define bs_c_1_proto(f) \
+void __bs_c(f,_bs_c_1) (bus_space_tag_t t, bus_space_handle_t bsh1, \
+ bus_size_t offset1, bus_space_handle_t bsh2, \
+ bus_size_t offset2, bus_size_t count);
+
+#define bs_c_2_proto(f) \
+void __bs_c(f,_bs_c_2) (bus_space_tag_t t, bus_space_handle_t bsh1, \
+ bus_size_t offset1, bus_space_handle_t bsh2, \
+ bus_size_t offset2, bus_size_t count);
+
+#define bs_c_4_proto(f) \
+void __bs_c(f,_bs_c_4) (bus_space_tag_t t, bus_space_handle_t bsh1, \
+ bus_size_t offset1, bus_space_handle_t bsh2, \
+ bus_size_t offset2, bus_size_t count);
+
+#define bs_c_8_proto(f) \
+void __bs_c(f,_bs_c_8) (bus_space_tag_t t, bus_space_handle_t bsh1, \
+ bus_size_t offset1, bus_space_handle_t bsh2, \
+ bus_size_t offset2, bus_size_t count);
+
+#define bs_protos(f) \
+bs_map_proto(f); \
+bs_unmap_proto(f); \
+bs_subregion_proto(f); \
+bs_alloc_proto(f); \
+bs_free_proto(f); \
+bs_mmap_proto(f); \
+bs_barrier_proto(f); \
+bs_r_1_proto(f); \
+bs_r_2_proto(f); \
+bs_r_4_proto(f); \
+bs_r_8_proto(f); \
+bs_r_1_s_proto(f); \
+bs_r_2_s_proto(f); \
+bs_r_4_s_proto(f); \
+bs_w_1_proto(f); \
+bs_w_2_proto(f); \
+bs_w_4_proto(f); \
+bs_w_8_proto(f); \
+bs_w_1_s_proto(f); \
+bs_w_2_s_proto(f); \
+bs_w_4_s_proto(f); \
+bs_rm_1_proto(f); \
+bs_rm_2_proto(f); \
+bs_rm_4_proto(f); \
+bs_rm_8_proto(f); \
+bs_wm_1_proto(f); \
+bs_wm_2_proto(f); \
+bs_wm_4_proto(f); \
+bs_wm_8_proto(f); \
+bs_rr_1_proto(f); \
+bs_rr_2_proto(f); \
+bs_rr_4_proto(f); \
+bs_rr_8_proto(f); \
+bs_wr_1_proto(f); \
+bs_wr_2_proto(f); \
+bs_wr_4_proto(f); \
+bs_wr_8_proto(f); \
+bs_sm_1_proto(f); \
+bs_sm_2_proto(f); \
+bs_sm_4_proto(f); \
+bs_sm_8_proto(f); \
+bs_sr_1_proto(f); \
+bs_sr_2_proto(f); \
+bs_sr_4_proto(f); \
+bs_sr_8_proto(f); \
+bs_c_1_proto(f); \
+bs_c_2_proto(f); \
+bs_c_4_proto(f); \
+bs_c_8_proto(f);
+
+void generic_bs_unimplemented(void);
+#define BS_UNIMPLEMENTED (void *)generic_bs_unimplemented
+
+#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
+
+#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
+#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
+#define BUS_SPACE_MAXADDR 0xFFFFFFFF
+#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
+#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
+#define BUS_SPACE_MAXSIZE 0xFFFFFFFF
+
+#define BUS_SPACE_UNRESTRICTED (~0)
+
+#include <machine/bus_dma.h>
+
+/*
+ * Get the physical address of a bus space memory-mapped resource.
+ * Doing this as a macro is a temporary solution until a more robust fix is
+ * designed. It also serves to mark the locations needing that fix.
+ */
+#define BUS_SPACE_PHYSADDR(res, offs) \
+ ((u_int)(rman_get_start(res)+(offs)))
+
+#endif /* _MACHINE_BUS_H_ */
Property changes on: trunk/sys/arm/include/bus.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/bus_dma.h
===================================================================
--- trunk/sys/arm/include/bus_dma.h (rev 0)
+++ trunk/sys/arm/include/bus_dma.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,102 @@
+/* $MidnightBSD$ */
+/* $NetBSD: bus.h,v 1.11 2003/07/28 17:35:54 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/bus_dma.h 203974 2010-02-16 21:59:17Z imp $
+ */
+
+#ifndef _ARM_BUS_DMA_H
+#define _ARM_BUS_DMA_H
+
+#include <sys/bus_dma.h>
+
+/* Bus Space DMA macros */
+
+#define BUS_DMA_TAG_VALID(t) ((t) != (bus_dma_tag_t)0)
+
+#ifdef _ARM32_BUS_DMA_PRIVATE
+/*
+ * arm32_dma_range
+ *
+ * This structure describes a valid DMA range.
+ */
+struct arm32_dma_range {
+ bus_addr_t dr_sysbase; /* system base address */
+ bus_addr_t dr_busbase; /* appears here on bus */
+ bus_size_t dr_len; /* length of range */
+};
+
+/* _dm_buftype */
+#define ARM32_BUFTYPE_INVALID 0
+#define ARM32_BUFTYPE_LINEAR 1
+#define ARM32_BUFTYPE_MBUF 2
+#define ARM32_BUFTYPE_UIO 3
+#define ARM32_BUFTYPE_RAW 4
+
+struct arm32_dma_range *bus_dma_get_range(void);
+int bus_dma_get_range_nb(void);
+
+extern bus_dma_tag_t arm_root_dma_tag;
+
+#endif /* _ARM32_BUS_DMA_PRIVATE */
+
+#endif /* _ARM_BUS_DMA_H */
Property changes on: trunk/sys/arm/include/bus_dma.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/clock.h
===================================================================
--- trunk/sys/arm/include/clock.h (rev 0)
+++ trunk/sys/arm/include/clock.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,33 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/clock.h 162954 2006-10-02 12:59:59Z phk $
+ */
+
+#ifndef _MACHINE_CLOCK_H_
+#define _MACHINE_CLOCK_H_
+
+#endif /* !_MACHINE_CLOCK_H_ */
Property changes on: trunk/sys/arm/include/clock.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/counter.h
===================================================================
--- trunk/sys/arm/include/counter.h (rev 0)
+++ trunk/sys/arm/include/counter.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,95 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Konstantin Belousov <kib at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/counter.h 252434 2013-07-01 02:48:27Z kib $
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+#ifdef INVARIANTS
+#include <sys/proc.h>
+#endif
+
+#define counter_enter() critical_enter()
+#define counter_exit() critical_exit()
+
+#ifdef IN_SUBR_COUNTER_C
+/* XXXKIB non-atomic 64bit read */
+static inline uint64_t
+counter_u64_read_one(uint64_t *p, int cpu)
+{
+
+ return (*(uint64_t *)((char *)p + sizeof(struct pcpu) * cpu));
+}
+
+static inline uint64_t
+counter_u64_fetch_inline(uint64_t *p)
+{
+ uint64_t r;
+ int i;
+
+ r = 0;
+ for (i = 0; i < mp_ncpus; i++)
+ r += counter_u64_read_one((uint64_t *)p, i);
+
+ return (r);
+}
+
+/* XXXKIB non-atomic 64bit store, might interrupt increment */
+static void
+counter_u64_zero_one_cpu(void *arg)
+{
+
+ *((uint64_t *)((char *)arg + sizeof(struct pcpu) *
+ PCPU_GET(cpuid))) = 0;
+}
+
+static inline void
+counter_u64_zero_inline(counter_u64_t c)
+{
+
+ smp_rendezvous(smp_no_rendevous_barrier, counter_u64_zero_one_cpu,
+ smp_no_rendevous_barrier, c);
+}
+#endif
+
+#define counter_u64_add_protected(c, inc) do { \
+ CRITICAL_ASSERT(curthread); \
+ *(uint64_t *)zpcpu_get(c) += (inc); \
+} while (0)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+ counter_enter();
+ counter_u64_add_protected(c, inc);
+ counter_exit();
+}
+
+#endif /* ! __MACHINE_COUNTER_H__ */
Property changes on: trunk/sys/arm/include/counter.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/cpu-v6.h
===================================================================
--- trunk/sys/arm/include/cpu-v6.h (rev 0)
+++ trunk/sys/arm/include/cpu-v6.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,442 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Svatopluk Kraus <onwahe at gmail.com>
+ * Copyright 2014 Michal Meloun <meloun at miracle.cz>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/cpu-v6.h 283336 2015-05-23 23:05:31Z ian $
+ */
+#ifndef MACHINE_CPU_V6_H
+#define MACHINE_CPU_V6_H
+
+#include "machine/atomic.h"
+#include "machine/cpufunc.h"
+#include "machine/cpuinfo.h"
+#include "machine/sysreg.h"
+
+
+#define CPU_ASID_KERNEL 0
+
+vm_offset_t dcache_wb_pou_checked(vm_offset_t, vm_size_t);
+vm_offset_t icache_inv_pou_checked(vm_offset_t, vm_size_t);
+
+/*
+ * Macros to generate CP15 (system control processor) read/write functions.
+ */
+#define _FX(s...) #s
+
+#define _RF0(fname, aname...) \
+static __inline register_t \
+fname(void) \
+{ \
+ register_t reg; \
+ __asm __volatile("mrc\t" _FX(aname): "=r" (reg)); \
+ return(reg); \
+}
+
+#define _WF0(fname, aname...) \
+static __inline void \
+fname(void) \
+{ \
+ __asm __volatile("mcr\t" _FX(aname)); \
+}
+
+#define _WF1(fname, aname...) \
+static __inline void \
+fname(register_t reg) \
+{ \
+ __asm __volatile("mcr\t" _FX(aname):: "r" (reg)); \
+}
+
+/*
+ * Raw CP15 maintenance operations
+ * !!! not for external use !!!
+ */
+
+/* TLB */
+
+_WF0(_CP15_TLBIALL, CP15_TLBIALL) /* Invalidate entire unified TLB */
+#if __ARM_ARCH >= 7 && defined SMP
+_WF0(_CP15_TLBIALLIS, CP15_TLBIALLIS) /* Invalidate entire unified TLB IS */
+#endif
+_WF1(_CP15_TLBIASID, CP15_TLBIASID(%0)) /* Invalidate unified TLB by ASID */
+#if __ARM_ARCH >= 7 && defined SMP
+_WF1(_CP15_TLBIASIDIS, CP15_TLBIASIDIS(%0)) /* Invalidate unified TLB by ASID IS */
+#endif
+_WF1(_CP15_TLBIMVAA, CP15_TLBIMVAA(%0)) /* Invalidate unified TLB by MVA, all ASID */
+#if __ARM_ARCH >= 7 && defined SMP
+_WF1(_CP15_TLBIMVAAIS, CP15_TLBIMVAAIS(%0)) /* Invalidate unified TLB by MVA, all ASID IS */
+#endif
+_WF1(_CP15_TLBIMVA, CP15_TLBIMVA(%0)) /* Invalidate unified TLB by MVA */
+
+_WF1(_CP15_TTB_SET, CP15_TTBR0(%0))
+
+/* Cache and Branch predictor */
+
+_WF0(_CP15_BPIALL, CP15_BPIALL) /* Branch predictor invalidate all */
+#if __ARM_ARCH >= 7 && defined SMP
+_WF0(_CP15_BPIALLIS, CP15_BPIALLIS) /* Branch predictor invalidate all IS */
+#endif
+_WF1(_CP15_BPIMVA, CP15_BPIMVA(%0)) /* Branch predictor invalidate by MVA */
+_WF1(_CP15_DCCIMVAC, CP15_DCCIMVAC(%0)) /* Data cache clean and invalidate by MVA PoC */
+_WF1(_CP15_DCCISW, CP15_DCCISW(%0)) /* Data cache clean and invalidate by set/way */
+_WF1(_CP15_DCCMVAC, CP15_DCCMVAC(%0)) /* Data cache clean by MVA PoC */
+#if __ARM_ARCH >= 7
+_WF1(_CP15_DCCMVAU, CP15_DCCMVAU(%0)) /* Data cache clean by MVA PoU */
+#endif
+_WF1(_CP15_DCCSW, CP15_DCCSW(%0)) /* Data cache clean by set/way */
+_WF1(_CP15_DCIMVAC, CP15_DCIMVAC(%0)) /* Data cache invalidate by MVA PoC */
+_WF1(_CP15_DCISW, CP15_DCISW(%0)) /* Data cache invalidate by set/way */
+_WF0(_CP15_ICIALLU, CP15_ICIALLU) /* Instruction cache invalidate all PoU */
+#if __ARM_ARCH >= 7 && defined SMP
+_WF0(_CP15_ICIALLUIS, CP15_ICIALLUIS) /* Instruction cache invalidate all PoU IS */
+#endif
+_WF1(_CP15_ICIMVAU, CP15_ICIMVAU(%0)) /* Instruction cache invalidate */
+
+/*
+ * Publicly accessible functions
+ */
+
+/* Various control registers */
+
+_RF0(cp15_dfsr_get, CP15_DFSR(%0))
+_RF0(cp15_ifsr_get, CP15_IFSR(%0))
+_WF1(cp15_prrr_set, CP15_PRRR(%0))
+_WF1(cp15_nmrr_set, CP15_NMRR(%0))
+_RF0(cp15_ttbr_get, CP15_TTBR0(%0))
+_RF0(cp15_dfar_get, CP15_DFAR(%0))
+#if __ARM_ARCH >= 7
+_RF0(cp15_ifar_get, CP15_IFAR(%0))
+#endif
+
+/*CPU id registers */
+_RF0(cp15_midr_get, CP15_MIDR(%0))
+_RF0(cp15_ctr_get, CP15_CTR(%0))
+_RF0(cp15_tcmtr_get, CP15_TCMTR(%0))
+_RF0(cp15_tlbtr_get, CP15_TLBTR(%0))
+_RF0(cp15_mpidr_get, CP15_MPIDR(%0))
+_RF0(cp15_revidr_get, CP15_REVIDR(%0))
+_RF0(cp15_aidr_get, CP15_AIDR(%0))
+_RF0(cp15_id_pfr0_get, CP15_ID_PFR0(%0))
+_RF0(cp15_id_pfr1_get, CP15_ID_PFR1(%0))
+_RF0(cp15_id_dfr0_get, CP15_ID_DFR0(%0))
+_RF0(cp15_id_afr0_get, CP15_ID_AFR0(%0))
+_RF0(cp15_id_mmfr0_get, CP15_ID_MMFR0(%0))
+_RF0(cp15_id_mmfr1_get, CP15_ID_MMFR1(%0))
+_RF0(cp15_id_mmfr2_get, CP15_ID_MMFR2(%0))
+_RF0(cp15_id_mmfr3_get, CP15_ID_MMFR3(%0))
+_RF0(cp15_id_isar0_get, CP15_ID_ISAR0(%0))
+_RF0(cp15_id_isar1_get, CP15_ID_ISAR1(%0))
+_RF0(cp15_id_isar2_get, CP15_ID_ISAR2(%0))
+_RF0(cp15_id_isar3_get, CP15_ID_ISAR3(%0))
+_RF0(cp15_id_isar4_get, CP15_ID_ISAR4(%0))
+_RF0(cp15_id_isar5_get, CP15_ID_ISAR5(%0))
+_RF0(cp15_cbar_get, CP15_CBAR(%0))
+
+/* Performance Monitor registers */
+
+#if __ARM_ARCH == 6 && defined(CPU_ARM1176)
+_RF0(cp15_pmccntr_get, CP15_PMCCNTR(%0))
+_WF1(cp15_pmccntr_set, CP15_PMCCNTR(%0))
+#elif __ARM_ARCH > 6
+_RF0(cp15_pmcr_get, CP15_PMCR(%0))
+_WF1(cp15_pmcr_set, CP15_PMCR(%0))
+_RF0(cp15_pmcnten_get, CP15_PMCNTENSET(%0))
+_WF1(cp15_pmcnten_set, CP15_PMCNTENSET(%0))
+_WF1(cp15_pmcnten_clr, CP15_PMCNTENCLR(%0))
+_RF0(cp15_pmovsr_get, CP15_PMOVSR(%0))
+_WF1(cp15_pmovsr_set, CP15_PMOVSR(%0))
+_WF1(cp15_pmswinc_set, CP15_PMSWINC(%0))
+_RF0(cp15_pmselr_get, CP15_PMSELR(%0))
+_WF1(cp15_pmselr_set, CP15_PMSELR(%0))
+_RF0(cp15_pmccntr_get, CP15_PMCCNTR(%0))
+_WF1(cp15_pmccntr_set, CP15_PMCCNTR(%0))
+_RF0(cp15_pmxevtyper_get, CP15_PMXEVTYPER(%0))
+_WF1(cp15_pmxevtyper_set, CP15_PMXEVTYPER(%0))
+_RF0(cp15_pmxevcntr_get, CP15_PMXEVCNTRR(%0))
+_WF1(cp15_pmxevcntr_set, CP15_PMXEVCNTRR(%0))
+_RF0(cp15_pmuserenr_get, CP15_PMUSERENR(%0))
+_WF1(cp15_pmuserenr_set, CP15_PMUSERENR(%0))
+_RF0(cp15_pminten_get, CP15_PMINTENSET(%0))
+_WF1(cp15_pminten_set, CP15_PMINTENSET(%0))
+_WF1(cp15_pminten_clr, CP15_PMINTENCLR(%0))
+#endif
+
+#undef _FX
+#undef _RF0
+#undef _WF0
+#undef _WF1
+
+/*
+ * TLB maintenance operations.
+ */
+
+/* Local (i.e. not broadcasting ) operations. */
+
+/* Flush all TLB entries (even global). */
+static __inline void
+tlb_flush_all_local(void)
+{
+
+ dsb();
+ _CP15_TLBIALL();
+ dsb();
+}
+
+/* Flush all not global TLB entries. */
+static __inline void
+tlb_flush_all_ng_local(void)
+{
+
+ dsb();
+ _CP15_TLBIASID(CPU_ASID_KERNEL);
+ dsb();
+}
+
+/* Flush single TLB entry (even global). */
+static __inline void
+tlb_flush_local(vm_offset_t sva)
+{
+
+ dsb();
+ _CP15_TLBIMVA((sva & ~PAGE_MASK ) | CPU_ASID_KERNEL);
+ dsb();
+}
+
+/* Flush range of TLB entries (even global). */
+static __inline void
+tlb_flush_range_local(vm_offset_t sva, vm_size_t size)
+{
+ vm_offset_t va;
+ vm_offset_t eva = sva + size;
+
+ dsb();
+ for (va = sva; va < eva; va += PAGE_SIZE)
+ _CP15_TLBIMVA((va & ~PAGE_MASK ) | CPU_ASID_KERNEL);
+ dsb();
+}
+
+/* Broadcasting operations. */
+#if __ARM_ARCH >= 7 && defined SMP
+
+static __inline void
+tlb_flush_all(void)
+{
+
+ dsb();
+ _CP15_TLBIALLIS();
+ dsb();
+}
+
+static __inline void
+tlb_flush_all_ng(void)
+{
+
+ dsb();
+ _CP15_TLBIASIDIS(CPU_ASID_KERNEL);
+ dsb();
+}
+
+static __inline void
+tlb_flush(vm_offset_t sva)
+{
+
+ dsb();
+ _CP15_TLBIMVAAIS(sva);
+ dsb();
+}
+
+static __inline void
+tlb_flush_range(vm_offset_t sva, vm_size_t size)
+{
+ vm_offset_t va;
+ vm_offset_t eva = sva + size;
+
+ dsb();
+ for (va = sva; va < eva; va += PAGE_SIZE)
+ _CP15_TLBIMVAAIS(va);
+ dsb();
+}
+#else /* SMP */
+
+#define tlb_flush_all() tlb_flush_all_local()
+#define tlb_flush_all_ng() tlb_flush_all_ng_local()
+#define tlb_flush(sva) tlb_flush_local(sva)
+#define tlb_flush_range(sva, size) tlb_flush_range_local(sva, size)
+
+#endif /* SMP */
+
+/*
+ * Cache maintenance operations.
+ */
+
+/* Sync I and D caches to PoU */
+static __inline void
+icache_sync(vm_offset_t sva, vm_size_t size)
+{
+ vm_offset_t va;
+ vm_offset_t eva = sva + size;
+
+ dsb();
+ for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
+#if __ARM_ARCH >= 7 && defined SMP
+ _CP15_DCCMVAU(va);
+#else
+ _CP15_DCCMVAC(va);
+#endif
+ }
+ dsb();
+#if __ARM_ARCH >= 7 && defined SMP
+ _CP15_ICIALLUIS();
+#else
+ _CP15_ICIALLU();
+#endif
+ dsb();
+ isb();
+}
+
+/* Invalidate I cache */
+static __inline void
+icache_inv_all(void)
+{
+#if __ARM_ARCH >= 7 && defined SMP
+ _CP15_ICIALLUIS();
+#else
+ _CP15_ICIALLU();
+#endif
+ dsb();
+ isb();
+}
+
+/* Invalidate branch predictor buffer */
+static __inline void
+bpb_inv_all(void)
+{
+#if __ARM_ARCH >= 7 && defined SMP
+ _CP15_BPIALLIS();
+#else
+ _CP15_BPIALL();
+#endif
+ dsb();
+ isb();
+}
+
+/* Write back D-cache to PoU */
+static __inline void
+dcache_wb_pou(vm_offset_t sva, vm_size_t size)
+{
+ vm_offset_t va;
+ vm_offset_t eva = sva + size;
+
+ dsb();
+ for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
+#if __ARM_ARCH >= 7 && defined SMP
+ _CP15_DCCMVAU(va);
+#else
+ _CP15_DCCMVAC(va);
+#endif
+ }
+ dsb();
+}
+
+/* Invalidate D-cache to PoC */
+static __inline void
+dcache_inv_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size)
+{
+ vm_offset_t va;
+ vm_offset_t eva = sva + size;
+
+ /* invalidate L1 first */
+ for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
+ _CP15_DCIMVAC(va);
+ }
+ dsb();
+
+ /* then L2 */
+ cpu_l2cache_inv_range(pa, size);
+ dsb();
+
+ /* then L1 again */
+ for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
+ _CP15_DCIMVAC(va);
+ }
+ dsb();
+}
+
+/* Write back D-cache to PoC */
+static __inline void
+dcache_wb_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size)
+{
+ vm_offset_t va;
+ vm_offset_t eva = sva + size;
+
+ dsb();
+
+ for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
+ _CP15_DCCMVAC(va);
+ }
+ dsb();
+
+ cpu_l2cache_wb_range(pa, size);
+}
+
+/* Write back and invalidate D-cache to PoC */
+static __inline void
+dcache_wbinv_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size)
+{
+ vm_offset_t va;
+ vm_offset_t eva = sva + size;
+
+ dsb();
+
+ /* write back L1 first */
+ for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
+ _CP15_DCCMVAC(va);
+ }
+ dsb();
+
+ /* then write back and invalidate L2 */
+ cpu_l2cache_wbinv_range(pa, size);
+
+ /* then invalidate L1 */
+ for (va = sva; va < eva; va += cpuinfo.dcache_line_size) {
+ _CP15_DCIMVAC(va);
+ }
+ dsb();
+}
+
+/* Set TTB0 register */
+static __inline void
+cp15_ttbr_set(uint32_t reg)
+{
+ dsb();
+ _CP15_TTB_SET(reg);
+ dsb();
+ _CP15_BPIALL();
+ dsb();
+ isb();
+ tlb_flush_all_ng_local();
+}
+
+#endif /* !MACHINE_CPU_V6_H */
Property changes on: trunk/sys/arm/include/cpu-v6.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/cpu.h
===================================================================
--- trunk/sys/arm/include/cpu.h (rev 0)
+++ trunk/sys/arm/include/cpu.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,69 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpu.h,v 1.2 2001/02/23 21:23:52 reinoud Exp $ */
+/* $FreeBSD: stable/10/sys/arm/include/cpu.h 278684 2015-02-13 17:53:11Z ian $ */
+
+#ifndef MACHINE_CPU_H
+#define MACHINE_CPU_H
+
+#include <machine/acle-compat.h>
+#include <machine/armreg.h>
+#include <machine/frame.h>
+
+void cpu_halt(void);
+void swi_vm(void *);
+
+#ifdef _KERNEL
+#if __ARM_ARCH >= 6
+#include <machine/cpu-v6.h>
+#endif
+static __inline uint64_t
+get_cyclecount(void)
+{
+#if __ARM_ARCH >= 6
+ return cp15_pmccntr_get();
+#else /* No performance counters, so use binuptime(9). This is slooooow */
+ struct bintime bt;
+
+ binuptime(&bt);
+ return ((uint64_t)bt.sec << 56 | bt.frac >> 8);
+#endif
+}
+#endif
+
+#define TRAPF_USERMODE(frame) ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
+
+#define TRAPF_PC(tfp) ((tfp)->tf_pc)
+
+#define cpu_getstack(td) ((td)->td_frame->tf_usr_sp)
+#define cpu_setstack(td, sp) ((td)->td_frame->tf_usr_sp = (sp))
+#define cpu_spinwait() /* nothing */
+
+#define ARM_NVEC 8
+#define ARM_VEC_ALL 0xffffffff
+
+extern vm_offset_t vector_page;
+
+/*
+ * Params passed into initarm. If you change the size of this you will
+ * need to update locore.S to allocate more memory on the stack before
+ * it calls initarm.
+ */
+struct arm_boot_params {
+ register_t abp_size; /* Size of this structure */
+ register_t abp_r0; /* r0 from the boot loader */
+ register_t abp_r1; /* r1 from the boot loader */
+ register_t abp_r2; /* r2 from the boot loader */
+ register_t abp_r3; /* r3 from the boot loader */
+ vm_offset_t abp_physaddr; /* The kernel physical address */
+ vm_offset_t abp_pagetable; /* The early page table */
+};
+
+void arm_vector_init(vm_offset_t, int);
+void fork_trampoline(void);
+void identify_arm_cpu(void);
+void *initarm(struct arm_boot_params *);
+
+extern char btext[];
+extern char etext[];
+int badaddr_read(void *, size_t, void *);
+#endif /* !MACHINE_CPU_H */
Property changes on: trunk/sys/arm/include/cpu.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/cpuconf.h
===================================================================
--- trunk/sys/arm/include/cpuconf.h (rev 0)
+++ trunk/sys/arm/include/cpuconf.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,204 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpuconf.h,v 1.8 2003/09/06 08:55:42 rearnsha Exp $ */
+
+/*-
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/cpuconf.h 276312 2014-12-27 17:36:49Z ian $
+ *
+ */
+
+#ifndef _MACHINE_CPUCONF_H_
+#define _MACHINE_CPUCONF_H_
+
+/*
+ * IF YOU CHANGE THIS FILE, MAKE SURE TO UPDATE THE DEFINITION OF
+ * "PMAP_NEEDS_PTE_SYNC" IN <arm/arm32/pmap.h> FOR THE CPU TYPE
+ * YOU ARE ADDING SUPPORT FOR.
+ */
+
+/*
+ * Step 1: Count the number of CPU types configured into the kernel.
+ */
+#define CPU_NTYPES (defined(CPU_ARM9) + \
+ defined(CPU_ARM9E) + \
+ defined(CPU_ARM10) + \
+ defined(CPU_ARM1136) + \
+ defined(CPU_ARM1176) + \
+ defined(CPU_XSCALE_80200) + \
+ defined(CPU_XSCALE_80321) + \
+ defined(CPU_XSCALE_PXA2X0) + \
+ defined(CPU_FA526) + \
+ defined(CPU_FA626TE) + \
+ defined(CPU_XSCALE_IXP425)) + \
+ defined(CPU_CORTEXA) + \
+ defined(CPU_KRAIT) + \
+ defined(CPU_MV_PJ4B)
+
+/*
+ * Step 2: Determine which ARM architecture versions are configured.
+ */
+#if defined(CPU_ARM9) || defined(CPU_FA526)
+#define ARM_ARCH_4 1
+#else
+#define ARM_ARCH_4 0
+#endif
+
+#if (defined(CPU_ARM9E) || defined(CPU_ARM10) || \
+ defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_FA626TE))
+#define ARM_ARCH_5 1
+#else
+#define ARM_ARCH_5 0
+#endif
+
+#if !defined(ARM_ARCH_6)
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+#define ARM_ARCH_6 1
+#else
+#define ARM_ARCH_6 0
+#endif
+#endif
+
+#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) || defined(CPU_MV_PJ4B)
+#define ARM_ARCH_7A 1
+#else
+#define ARM_ARCH_7A 0
+#endif
+
+#define ARM_NARCH (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 | ARM_ARCH_7A)
+
+/*
+ * Compatibility for userland builds that have no CPUTYPE defined. Use the ARCH
+ * constants predefined by the compiler to define our old-school arch constants.
+ * This is a stopgap measure to tide us over until the conversion of all code
+ * to the newer ACLE constants defined by ARM (see acle-compat.h).
+ */
+#if ARM_NARCH == 0
+#if defined(__ARM_ARCH_4T__)
+#undef ARM_ARCH_4
+#undef ARM_NARCH
+#define ARM_ARCH_4 1
+#define ARM_NARCH 1
+#define CPU_ARM9 1
+#elif defined(__ARM_ARCH_6ZK__)
+#undef ARM_ARCH_6
+#undef ARM_NARCH
+#define ARM_ARCH_6 1
+#define ARM_NARCH 1
+#define CPU_ARM1176 1
+#endif
+#endif
+
+#if ARM_NARCH == 0 && !defined(KLD_MODULE) && defined(_KERNEL)
+#error ARM_NARCH is 0
+#endif
+
+#if ARM_ARCH_5 || ARM_ARCH_6 || ARM_ARCH_7A
+/*
+ * We could support Thumb code on v4T, but the lack of clean interworking
+ * makes that hard.
+ */
+#define THUMB_CODE
+#endif
+
+/*
+ * Step 3: Define which MMU classes are configured:
+ *
+ * ARM_MMU_MEMC Prehistoric, external memory controller
+ * and MMU for ARMv2 CPUs.
+ *
+ * ARM_MMU_GENERIC Generic ARM MMU, compatible with ARMv4 and v5.
+ *
+ * ARM_MMU_V6 ARMv6 MMU.
+ *
+ * ARM_MMU_V7 ARMv7 MMU.
+ *
+ * ARM_MMU_XSCALE XScale MMU. Compatible with generic ARM
+ * MMU, but also has several extensions which
+ * require different PTE layout to use.
+ */
+#if (defined(CPU_ARM9) || defined(CPU_ARM9E) || \
+ defined(CPU_ARM10) || defined(CPU_FA526) || \
+ defined(CPU_FA626TE))
+#define ARM_MMU_GENERIC 1
+#else
+#define ARM_MMU_GENERIC 0
+#endif
+
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+#define ARM_MMU_V6 1
+#else
+#define ARM_MMU_V6 0
+#endif
+
+#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) || defined(CPU_MV_PJ4B)
+#define ARM_MMU_V7 1
+#else
+#define ARM_MMU_V7 0
+#endif
+
+#if (defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342))
+#define ARM_MMU_XSCALE 1
+#else
+#define ARM_MMU_XSCALE 0
+#endif
+
+#define ARM_NMMUS (ARM_MMU_GENERIC + ARM_MMU_V6 + \
+ ARM_MMU_V7 + ARM_MMU_XSCALE)
+#if ARM_NMMUS == 0 && !defined(KLD_MODULE) && defined(_KERNEL)
+#error ARM_NMMUS is 0
+#endif
+
+/*
+ * Step 4: Define features that may be present on a subset of CPUs
+ *
+ * ARM_XSCALE_PMU Performance Monitoring Unit on 80200 and 80321
+ */
+
+#if (defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342))
+#define ARM_XSCALE_PMU 1
+#else
+#define ARM_XSCALE_PMU 0
+#endif
+
+#if defined(CPU_XSCALE_81342)
+#define CPU_XSCALE_CORE3
+#endif
+#endif /* _MACHINE_CPUCONF_H_ */
Property changes on: trunk/sys/arm/include/cpuconf.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/cpufunc.h
===================================================================
--- trunk/sys/arm/include/cpufunc.h (rev 0)
+++ trunk/sys/arm/include/cpufunc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,680 @@
+/* $MidnightBSD$ */
+/* $NetBSD: cpufunc.h,v 1.29 2003/09/06 09:08:35 rearnsha Exp $ */
+
+/*-
+ * Copyright (c) 1997 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Causality Limited.
+ * 4. The name of Causality Limited may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpufunc.h
+ *
+ * Prototypes for cpu, mmu and tlb related functions.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/cpufunc.h 278635 2015-02-12 21:10:24Z ian $
+ */
+
+#ifndef _MACHINE_CPUFUNC_H_
+#define _MACHINE_CPUFUNC_H_
+
+#ifdef _KERNEL
+
+#include <sys/types.h>
+#include <machine/cpuconf.h>
+#include <machine/katelib.h> /* For in[bwl] and out[bwl] */
+
+static __inline void
+breakpoint(void)
+{
+ __asm(".word 0xe7ffffff");
+}
+
+struct cpu_functions {
+
+ /* CPU functions */
+
+ u_int (*cf_id) (void);
+ void (*cf_cpwait) (void);
+
+ /* MMU functions */
+
+ u_int (*cf_control) (u_int bic, u_int eor);
+ void (*cf_domains) (u_int domains);
+ void (*cf_setttb) (u_int ttb);
+ u_int (*cf_faultstatus) (void);
+ u_int (*cf_faultaddress) (void);
+
+ /* TLB functions */
+
+ void (*cf_tlb_flushID) (void);
+ void (*cf_tlb_flushID_SE) (u_int va);
+ void (*cf_tlb_flushI) (void);
+ void (*cf_tlb_flushI_SE) (u_int va);
+ void (*cf_tlb_flushD) (void);
+ void (*cf_tlb_flushD_SE) (u_int va);
+
+ /*
+ * Cache operations:
+ *
+ * We define the following primitives:
+ *
+ * icache_sync_all Synchronize I-cache
+ * icache_sync_range Synchronize I-cache range
+ *
+ * dcache_wbinv_all Write-back and Invalidate D-cache
+ * dcache_wbinv_range Write-back and Invalidate D-cache range
+ * dcache_inv_range Invalidate D-cache range
+ * dcache_wb_range Write-back D-cache range
+ *
+ * idcache_wbinv_all Write-back and Invalidate D-cache,
+ * Invalidate I-cache
+ * idcache_wbinv_range Write-back and Invalidate D-cache,
+ * Invalidate I-cache range
+ *
+ * Note that the ARM term for "write-back" is "clean". We use
+ * the term "write-back" since it's a more common way to describe
+ * the operation.
+ *
+ * There are some rules that must be followed:
+ *
+ * ID-cache Invalidate All:
+ * Unlike other functions, this one must never write back.
+ * It is used to intialize the MMU when it is in an unknown
+ * state (such as when it may have lines tagged as valid
+ * that belong to a previous set of mappings).
+ *
+ * I-cache Synch (all or range):
+ * The goal is to synchronize the instruction stream,
+ * so you may beed to write-back dirty D-cache blocks
+ * first. If a range is requested, and you can't
+ * synchronize just a range, you have to hit the whole
+ * thing.
+ *
+ * D-cache Write-Back and Invalidate range:
+ * If you can't WB-Inv a range, you must WB-Inv the
+ * entire D-cache.
+ *
+ * D-cache Invalidate:
+ * If you can't Inv the D-cache, you must Write-Back
+ * and Invalidate. Code that uses this operation
+ * MUST NOT assume that the D-cache will not be written
+ * back to memory.
+ *
+ * D-cache Write-Back:
+ * If you can't Write-back without doing an Inv,
+ * that's fine. Then treat this as a WB-Inv.
+ * Skipping the invalidate is merely an optimization.
+ *
+ * All operations:
+ * Valid virtual addresses must be passed to each
+ * cache operation.
+ */
+ void (*cf_icache_sync_all) (void);
+ void (*cf_icache_sync_range) (vm_offset_t, vm_size_t);
+
+ void (*cf_dcache_wbinv_all) (void);
+ void (*cf_dcache_wbinv_range) (vm_offset_t, vm_size_t);
+ void (*cf_dcache_inv_range) (vm_offset_t, vm_size_t);
+ void (*cf_dcache_wb_range) (vm_offset_t, vm_size_t);
+
+ void (*cf_idcache_inv_all) (void);
+ void (*cf_idcache_wbinv_all) (void);
+ void (*cf_idcache_wbinv_range) (vm_offset_t, vm_size_t);
+ void (*cf_l2cache_wbinv_all) (void);
+ void (*cf_l2cache_wbinv_range) (vm_offset_t, vm_size_t);
+ void (*cf_l2cache_inv_range) (vm_offset_t, vm_size_t);
+ void (*cf_l2cache_wb_range) (vm_offset_t, vm_size_t);
+ void (*cf_l2cache_drain_writebuf) (void);
+
+ /* Other functions */
+
+ void (*cf_flush_prefetchbuf) (void);
+ void (*cf_drain_writebuf) (void);
+ void (*cf_flush_brnchtgt_C) (void);
+ void (*cf_flush_brnchtgt_E) (u_int va);
+
+ void (*cf_sleep) (int mode);
+
+ /* Soft functions */
+
+ int (*cf_dataabt_fixup) (void *arg);
+ int (*cf_prefetchabt_fixup) (void *arg);
+
+ void (*cf_context_switch) (void);
+
+ void (*cf_setup) (char *string);
+};
+
+extern struct cpu_functions cpufuncs;
+extern u_int cputype;
+
+#define cpu_id() cpufuncs.cf_id()
+#define cpu_cpwait() cpufuncs.cf_cpwait()
+
+#define cpu_control(c, e) cpufuncs.cf_control(c, e)
+#define cpu_domains(d) cpufuncs.cf_domains(d)
+#define cpu_setttb(t) cpufuncs.cf_setttb(t)
+#define cpu_faultstatus() cpufuncs.cf_faultstatus()
+#define cpu_faultaddress() cpufuncs.cf_faultaddress()
+
+#ifndef SMP
+
+#define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID()
+#define cpu_tlb_flushID_SE(e) cpufuncs.cf_tlb_flushID_SE(e)
+#define cpu_tlb_flushI() cpufuncs.cf_tlb_flushI()
+#define cpu_tlb_flushI_SE(e) cpufuncs.cf_tlb_flushI_SE(e)
+#define cpu_tlb_flushD() cpufuncs.cf_tlb_flushD()
+#define cpu_tlb_flushD_SE(e) cpufuncs.cf_tlb_flushD_SE(e)
+
+#else
+void tlb_broadcast(int);
+
+#if defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT)
+#define TLB_BROADCAST /* No need to explicitely send an IPI */
+#else
+#define TLB_BROADCAST tlb_broadcast(7)
+#endif
+
+#define cpu_tlb_flushID() do { \
+ cpufuncs.cf_tlb_flushID(); \
+ TLB_BROADCAST; \
+} while(0)
+
+#define cpu_tlb_flushID_SE(e) do { \
+ cpufuncs.cf_tlb_flushID_SE(e); \
+ TLB_BROADCAST; \
+} while(0)
+
+
+#define cpu_tlb_flushI() do { \
+ cpufuncs.cf_tlb_flushI(); \
+ TLB_BROADCAST; \
+} while(0)
+
+
+#define cpu_tlb_flushI_SE(e) do { \
+ cpufuncs.cf_tlb_flushI_SE(e); \
+ TLB_BROADCAST; \
+} while(0)
+
+
+#define cpu_tlb_flushD() do { \
+ cpufuncs.cf_tlb_flushD(); \
+ TLB_BROADCAST; \
+} while(0)
+
+
+#define cpu_tlb_flushD_SE(e) do { \
+ cpufuncs.cf_tlb_flushD_SE(e); \
+ TLB_BROADCAST; \
+} while(0)
+
+#endif
+
+#define cpu_icache_sync_all() cpufuncs.cf_icache_sync_all()
+#define cpu_icache_sync_range(a, s) cpufuncs.cf_icache_sync_range((a), (s))
+
+#define cpu_dcache_wbinv_all() cpufuncs.cf_dcache_wbinv_all()
+#define cpu_dcache_wbinv_range(a, s) cpufuncs.cf_dcache_wbinv_range((a), (s))
+#define cpu_dcache_inv_range(a, s) cpufuncs.cf_dcache_inv_range((a), (s))
+#define cpu_dcache_wb_range(a, s) cpufuncs.cf_dcache_wb_range((a), (s))
+
+#define cpu_idcache_inv_all() cpufuncs.cf_idcache_inv_all()
+#define cpu_idcache_wbinv_all() cpufuncs.cf_idcache_wbinv_all()
+#define cpu_idcache_wbinv_range(a, s) cpufuncs.cf_idcache_wbinv_range((a), (s))
+#define cpu_l2cache_wbinv_all() cpufuncs.cf_l2cache_wbinv_all()
+#define cpu_l2cache_wb_range(a, s) cpufuncs.cf_l2cache_wb_range((a), (s))
+#define cpu_l2cache_inv_range(a, s) cpufuncs.cf_l2cache_inv_range((a), (s))
+#define cpu_l2cache_wbinv_range(a, s) cpufuncs.cf_l2cache_wbinv_range((a), (s))
+#define cpu_l2cache_drain_writebuf() cpufuncs.cf_l2cache_drain_writebuf()
+
+#define cpu_flush_prefetchbuf() cpufuncs.cf_flush_prefetchbuf()
+#define cpu_drain_writebuf() cpufuncs.cf_drain_writebuf()
+#define cpu_flush_brnchtgt_C() cpufuncs.cf_flush_brnchtgt_C()
+#define cpu_flush_brnchtgt_E(e) cpufuncs.cf_flush_brnchtgt_E(e)
+
+#define cpu_sleep(m) cpufuncs.cf_sleep(m)
+
+#define cpu_dataabt_fixup(a) cpufuncs.cf_dataabt_fixup(a)
+#define cpu_prefetchabt_fixup(a) cpufuncs.cf_prefetchabt_fixup(a)
+#define ABORT_FIXUP_OK 0 /* fixup succeeded */
+#define ABORT_FIXUP_FAILED 1 /* fixup failed */
+#define ABORT_FIXUP_RETURN 2 /* abort handler should return */
+
+#define cpu_setup(a) cpufuncs.cf_setup(a)
+
+int set_cpufuncs (void);
+#define ARCHITECTURE_NOT_PRESENT 1 /* known but not configured */
+#define ARCHITECTURE_NOT_SUPPORTED 2 /* not known */
+
+void cpufunc_nullop (void);
+int cpufunc_null_fixup (void *);
+int early_abort_fixup (void *);
+int late_abort_fixup (void *);
+u_int cpufunc_id (void);
+u_int cpufunc_cpuid (void);
+u_int cpufunc_control (u_int clear, u_int bic);
+void cpufunc_domains (u_int domains);
+u_int cpufunc_faultstatus (void);
+u_int cpufunc_faultaddress (void);
+u_int cpu_pfr (int);
+
+#if defined(CPU_FA526) || defined(CPU_FA626TE)
+void fa526_setup (char *arg);
+void fa526_setttb (u_int ttb);
+void fa526_context_switch (void);
+void fa526_cpu_sleep (int);
+void fa526_tlb_flushI_SE (u_int);
+void fa526_tlb_flushID_SE (u_int);
+void fa526_flush_prefetchbuf (void);
+void fa526_flush_brnchtgt_E (u_int);
+
+void fa526_icache_sync_all (void);
+void fa526_icache_sync_range(vm_offset_t start, vm_size_t end);
+void fa526_dcache_wbinv_all (void);
+void fa526_dcache_wbinv_range(vm_offset_t start, vm_size_t end);
+void fa526_dcache_inv_range (vm_offset_t start, vm_size_t end);
+void fa526_dcache_wb_range (vm_offset_t start, vm_size_t end);
+void fa526_idcache_wbinv_all(void);
+void fa526_idcache_wbinv_range(vm_offset_t start, vm_size_t end);
+#endif
+
+
+#ifdef CPU_ARM9
+void arm9_setttb (u_int);
+
+void arm9_tlb_flushID_SE (u_int va);
+
+void arm9_icache_sync_all (void);
+void arm9_icache_sync_range (vm_offset_t, vm_size_t);
+
+void arm9_dcache_wbinv_all (void);
+void arm9_dcache_wbinv_range (vm_offset_t, vm_size_t);
+void arm9_dcache_inv_range (vm_offset_t, vm_size_t);
+void arm9_dcache_wb_range (vm_offset_t, vm_size_t);
+
+void arm9_idcache_wbinv_all (void);
+void arm9_idcache_wbinv_range (vm_offset_t, vm_size_t);
+
+void arm9_context_switch (void);
+
+void arm9_setup (char *string);
+
+extern unsigned arm9_dcache_sets_max;
+extern unsigned arm9_dcache_sets_inc;
+extern unsigned arm9_dcache_index_max;
+extern unsigned arm9_dcache_index_inc;
+#endif
+
+#if defined(CPU_ARM9E) || defined(CPU_ARM10)
+void arm10_setttb (u_int);
+
+void arm10_tlb_flushID_SE (u_int);
+void arm10_tlb_flushI_SE (u_int);
+
+void arm10_icache_sync_all (void);
+void arm10_icache_sync_range (vm_offset_t, vm_size_t);
+
+void arm10_dcache_wbinv_all (void);
+void arm10_dcache_wbinv_range (vm_offset_t, vm_size_t);
+void arm10_dcache_inv_range (vm_offset_t, vm_size_t);
+void arm10_dcache_wb_range (vm_offset_t, vm_size_t);
+
+void arm10_idcache_wbinv_all (void);
+void arm10_idcache_wbinv_range (vm_offset_t, vm_size_t);
+
+void arm10_context_switch (void);
+
+void arm10_setup (char *string);
+
+extern unsigned arm10_dcache_sets_max;
+extern unsigned arm10_dcache_sets_inc;
+extern unsigned arm10_dcache_index_max;
+extern unsigned arm10_dcache_index_inc;
+
+u_int sheeva_control_ext (u_int, u_int);
+void sheeva_cpu_sleep (int);
+void sheeva_setttb (u_int);
+void sheeva_dcache_wbinv_range (vm_offset_t, vm_size_t);
+void sheeva_dcache_inv_range (vm_offset_t, vm_size_t);
+void sheeva_dcache_wb_range (vm_offset_t, vm_size_t);
+void sheeva_idcache_wbinv_range (vm_offset_t, vm_size_t);
+
+void sheeva_l2cache_wbinv_range (vm_offset_t, vm_size_t);
+void sheeva_l2cache_inv_range (vm_offset_t, vm_size_t);
+void sheeva_l2cache_wb_range (vm_offset_t, vm_size_t);
+void sheeva_l2cache_wbinv_all (void);
+#endif
+
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || \
+ defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
+void arm11_setttb (u_int);
+void arm11_sleep (int);
+
+void arm11_tlb_flushID_SE (u_int);
+void arm11_tlb_flushI_SE (u_int);
+
+void arm11_context_switch (void);
+
+void arm11_setup (char *string);
+void arm11_tlb_flushID (void);
+void arm11_tlb_flushI (void);
+void arm11_tlb_flushD (void);
+void arm11_tlb_flushD_SE (u_int va);
+
+void arm11_drain_writebuf (void);
+
+void pj4b_setttb (u_int);
+
+void pj4b_drain_readbuf (void);
+void pj4b_flush_brnchtgt_all (void);
+void pj4b_flush_brnchtgt_va (u_int);
+void pj4b_sleep (int);
+
+void armv6_icache_sync_all (void);
+void armv6_icache_sync_range (vm_offset_t, vm_size_t);
+
+void armv6_dcache_wbinv_all (void);
+void armv6_dcache_wbinv_range (vm_offset_t, vm_size_t);
+void armv6_dcache_inv_range (vm_offset_t, vm_size_t);
+void armv6_dcache_wb_range (vm_offset_t, vm_size_t);
+
+void armv6_idcache_inv_all (void);
+void armv6_idcache_wbinv_all (void);
+void armv6_idcache_wbinv_range (vm_offset_t, vm_size_t);
+
+void armv7_setttb (u_int);
+void armv7_tlb_flushID (void);
+void armv7_tlb_flushID_SE (u_int);
+void armv7_icache_sync_all (void);
+void armv7_icache_sync_range (vm_offset_t, vm_size_t);
+void armv7_idcache_wbinv_range (vm_offset_t, vm_size_t);
+void armv7_idcache_inv_all (void);
+void armv7_dcache_wbinv_all (void);
+void armv7_idcache_wbinv_all (void);
+void armv7_dcache_wbinv_range (vm_offset_t, vm_size_t);
+void armv7_dcache_inv_range (vm_offset_t, vm_size_t);
+void armv7_dcache_wb_range (vm_offset_t, vm_size_t);
+void armv7_cpu_sleep (int);
+void armv7_setup (char *string);
+void armv7_context_switch (void);
+void armv7_drain_writebuf (void);
+void armv7_sev (void);
+void armv7_sleep (int unused);
+u_int armv7_auxctrl (u_int, u_int);
+void pj4bv7_setup (char *string);
+void pj4b_config (void);
+
+int get_core_id (void);
+
+void armadaxp_idcache_wbinv_all (void);
+
+void cortexa_setup (char *);
+#endif
+
+#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
+void arm11x6_setttb (u_int);
+void arm11x6_idcache_wbinv_all (void);
+void arm11x6_dcache_wbinv_all (void);
+void arm11x6_icache_sync_all (void);
+void arm11x6_flush_prefetchbuf (void);
+void arm11x6_icache_sync_range (vm_offset_t, vm_size_t);
+void arm11x6_idcache_wbinv_range (vm_offset_t, vm_size_t);
+void arm11x6_setup (char *string);
+void arm11x6_sleep (int); /* no ref. for errata */
+#endif
+#if defined(CPU_ARM1136)
+void arm1136_sleep_rev0 (int); /* for errata 336501 */
+#endif
+
+#if defined(CPU_ARM9E) || defined (CPU_ARM10)
+void armv5_ec_setttb(u_int);
+
+void armv5_ec_icache_sync_all(void);
+void armv5_ec_icache_sync_range(vm_offset_t, vm_size_t);
+
+void armv5_ec_dcache_wbinv_all(void);
+void armv5_ec_dcache_wbinv_range(vm_offset_t, vm_size_t);
+void armv5_ec_dcache_inv_range(vm_offset_t, vm_size_t);
+void armv5_ec_dcache_wb_range(vm_offset_t, vm_size_t);
+
+void armv5_ec_idcache_wbinv_all(void);
+void armv5_ec_idcache_wbinv_range(vm_offset_t, vm_size_t);
+#endif
+
+#if defined (CPU_ARM10)
+void armv5_setttb(u_int);
+
+void armv5_icache_sync_all(void);
+void armv5_icache_sync_range(vm_offset_t, vm_size_t);
+
+void armv5_dcache_wbinv_all(void);
+void armv5_dcache_wbinv_range(vm_offset_t, vm_size_t);
+void armv5_dcache_inv_range(vm_offset_t, vm_size_t);
+void armv5_dcache_wb_range(vm_offset_t, vm_size_t);
+
+void armv5_idcache_wbinv_all(void);
+void armv5_idcache_wbinv_range(vm_offset_t, vm_size_t);
+
+extern unsigned armv5_dcache_sets_max;
+extern unsigned armv5_dcache_sets_inc;
+extern unsigned armv5_dcache_index_max;
+extern unsigned armv5_dcache_index_inc;
+#endif
+
+#if defined(CPU_ARM9) || defined(CPU_ARM9E) || defined(CPU_ARM10) || \
+ defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_FA526) || defined(CPU_FA626TE) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
+
+void armv4_tlb_flushID (void);
+void armv4_tlb_flushI (void);
+void armv4_tlb_flushD (void);
+void armv4_tlb_flushD_SE (u_int va);
+
+void armv4_drain_writebuf (void);
+void armv4_idcache_inv_all (void);
+#endif
+
+#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
+void xscale_cpwait (void);
+
+void xscale_cpu_sleep (int mode);
+
+u_int xscale_control (u_int clear, u_int bic);
+
+void xscale_setttb (u_int ttb);
+
+void xscale_tlb_flushID_SE (u_int va);
+
+void xscale_cache_flushID (void);
+void xscale_cache_flushI (void);
+void xscale_cache_flushD (void);
+void xscale_cache_flushD_SE (u_int entry);
+
+void xscale_cache_cleanID (void);
+void xscale_cache_cleanD (void);
+void xscale_cache_cleanD_E (u_int entry);
+
+void xscale_cache_clean_minidata (void);
+
+void xscale_cache_purgeID (void);
+void xscale_cache_purgeID_E (u_int entry);
+void xscale_cache_purgeD (void);
+void xscale_cache_purgeD_E (u_int entry);
+
+void xscale_cache_syncI (void);
+void xscale_cache_cleanID_rng (vm_offset_t start, vm_size_t end);
+void xscale_cache_cleanD_rng (vm_offset_t start, vm_size_t end);
+void xscale_cache_purgeID_rng (vm_offset_t start, vm_size_t end);
+void xscale_cache_purgeD_rng (vm_offset_t start, vm_size_t end);
+void xscale_cache_syncI_rng (vm_offset_t start, vm_size_t end);
+void xscale_cache_flushD_rng (vm_offset_t start, vm_size_t end);
+
+void xscale_context_switch (void);
+
+void xscale_setup (char *string);
+#endif /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
+ CPU_XSCALE_80219 */
+
+#ifdef CPU_XSCALE_81342
+
+void xscalec3_l2cache_purge (void);
+void xscalec3_cache_purgeID (void);
+void xscalec3_cache_purgeD (void);
+void xscalec3_cache_cleanID (void);
+void xscalec3_cache_cleanD (void);
+void xscalec3_cache_syncI (void);
+
+void xscalec3_cache_purgeID_rng (vm_offset_t start, vm_size_t end);
+void xscalec3_cache_purgeD_rng (vm_offset_t start, vm_size_t end);
+void xscalec3_cache_cleanID_rng (vm_offset_t start, vm_size_t end);
+void xscalec3_cache_cleanD_rng (vm_offset_t start, vm_size_t end);
+void xscalec3_cache_syncI_rng (vm_offset_t start, vm_size_t end);
+
+void xscalec3_l2cache_flush_rng (vm_offset_t, vm_size_t);
+void xscalec3_l2cache_clean_rng (vm_offset_t start, vm_size_t end);
+void xscalec3_l2cache_purge_rng (vm_offset_t start, vm_size_t end);
+
+
+void xscalec3_setttb (u_int ttb);
+void xscalec3_context_switch (void);
+
+#endif /* CPU_XSCALE_81342 */
+
+#define setttb cpu_setttb
+#define drain_writebuf cpu_drain_writebuf
+
+/*
+ * Macros for manipulating CPU interrupts
+ */
+static __inline u_int32_t __set_cpsr_c(u_int bic, u_int eor) __attribute__((__unused__));
+
+static __inline u_int32_t
+__set_cpsr_c(u_int bic, u_int eor)
+{
+ u_int32_t tmp, ret;
+
+ __asm __volatile(
+ "mrs %0, cpsr\n" /* Get the CPSR */
+ "bic %1, %0, %2\n" /* Clear bits */
+ "eor %1, %1, %3\n" /* XOR bits */
+ "msr cpsr_c, %1\n" /* Set the control field of CPSR */
+ : "=&r" (ret), "=&r" (tmp)
+ : "r" (bic), "r" (eor) : "memory");
+
+ return ret;
+}
+
+#define ARM_CPSR_F32 (1 << 6) /* FIQ disable */
+#define ARM_CPSR_I32 (1 << 7) /* IRQ disable */
+
+#define disable_interrupts(mask) \
+ (__set_cpsr_c((mask) & (ARM_CPSR_I32 | ARM_CPSR_F32), \
+ (mask) & (ARM_CPSR_I32 | ARM_CPSR_F32)))
+
+#define enable_interrupts(mask) \
+ (__set_cpsr_c((mask) & (ARM_CPSR_I32 | ARM_CPSR_F32), 0))
+
+#define restore_interrupts(old_cpsr) \
+ (__set_cpsr_c((ARM_CPSR_I32 | ARM_CPSR_F32), \
+ (old_cpsr) & (ARM_CPSR_I32 | ARM_CPSR_F32)))
+
+static __inline register_t
+intr_disable(void)
+{
+ register_t s;
+
+ s = disable_interrupts(ARM_CPSR_I32 | ARM_CPSR_F32);
+ return (s);
+}
+
+static __inline void
+intr_restore(register_t s)
+{
+
+ restore_interrupts(s);
+}
+
+/* Functions to manipulate the CPSR. */
+u_int SetCPSR(u_int bic, u_int eor);
+u_int GetCPSR(void);
+
+/*
+ * Functions to manipulate cpu r13
+ * (in arm/arm32/setstack.S)
+ */
+
+void set_stackptr (u_int mode, u_int address);
+u_int get_stackptr (u_int mode);
+
+/*
+ * Miscellany
+ */
+
+int get_pc_str_offset (void);
+
+/*
+ * CPU functions from locore.S
+ */
+
+void cpu_reset (void) __attribute__((__noreturn__));
+
+/*
+ * Cache info variables.
+ */
+
+/* PRIMARY CACHE VARIABLES */
+extern int arm_picache_size;
+extern int arm_picache_line_size;
+extern int arm_picache_ways;
+
+extern int arm_pdcache_size; /* and unified */
+extern int arm_pdcache_line_size;
+extern int arm_pdcache_ways;
+
+extern int arm_pcache_type;
+extern int arm_pcache_unified;
+
+extern int arm_dcache_align;
+extern int arm_dcache_align_mask;
+
+extern u_int arm_cache_level;
+extern u_int arm_cache_loc;
+extern u_int arm_cache_type[14];
+
+#endif /* _KERNEL */
+#endif /* _MACHINE_CPUFUNC_H_ */
+
+/* End of cpufunc.h */
Property changes on: trunk/sys/arm/include/cpufunc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/cpuinfo.h
===================================================================
--- trunk/sys/arm/include/cpuinfo.h (rev 0)
+++ trunk/sys/arm/include/cpuinfo.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,98 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Svatopluk Kraus <onwahe at gmail.com>
+ * Copyright 2014 Michal Meloun <meloun at miracle.cz>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/cpuinfo.h 283336 2015-05-23 23:05:31Z ian $
+ */
+
+#ifndef _MACHINE_CPUINFO_H_
+#define _MACHINE_CPUINFO_H_
+
+#include <sys/types.h>
+
+struct cpuinfo {
+ /* raw id registers */
+ uint32_t midr;
+ uint32_t ctr;
+ uint32_t tcmtr;
+ uint32_t tlbtr;
+ uint32_t mpidr;
+ uint32_t revidr;
+ uint32_t id_pfr0;
+ uint32_t id_pfr1;
+ uint32_t id_dfr0;
+ uint32_t id_afr0;
+ uint32_t id_mmfr0;
+ uint32_t id_mmfr1;
+ uint32_t id_mmfr2;
+ uint32_t id_mmfr3;
+ uint32_t id_isar0;
+ uint32_t id_isar1;
+ uint32_t id_isar2;
+ uint32_t id_isar3;
+ uint32_t id_isar4;
+ uint32_t id_isar5;
+ uint32_t cbar;
+
+ /* Parsed bits of above registers... */
+
+ /* midr */
+ int implementer;
+ int revision;
+ int architecture;
+ int part_number;
+ int patch;
+
+ /* id_mmfr0 */
+ int outermost_shareability;
+ int shareability_levels;
+ int auxiliary_registers;
+ int innermost_shareability;
+
+ /* id_mmfr1 */
+ int mem_barrier;
+
+ /* id_mmfr3 */
+ int coherent_walk;
+ int maintenance_broadcast;
+
+ /* id_pfr1 */
+ int generic_timer_ext;
+ int virtualization_ext;
+ int security_ext;
+
+ /* L1 cache info */
+ int dcache_line_size;
+ int dcache_line_mask;
+ int icache_line_size;
+ int icache_line_mask;
+};
+
+extern struct cpuinfo cpuinfo;
+
+void cpuinfo_init(void);
+
+#endif /* _MACHINE_CPUINFO_H_ */
Property changes on: trunk/sys/arm/include/cpuinfo.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/db_machdep.h
===================================================================
--- trunk/sys/arm/include/db_machdep.h (rev 0)
+++ trunk/sys/arm/include/db_machdep.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,99 @@
+/* $MidnightBSD$ */
+/*-
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: FreeBSD: src/sys/i386/include/db_machdep.h,v 1.16 1999/10/04
+ * $FreeBSD: stable/10/sys/arm/include/db_machdep.h 278614 2015-02-12 04:15:55Z ian $
+ */
+
+#ifndef _MACHINE_DB_MACHDEP_H_
+#define _MACHINE_DB_MACHDEP_H_
+
+#include <machine/frame.h>
+#include <machine/trap.h>
+#include <machine/armreg.h>
+
+#define T_BREAKPOINT (1)
+typedef vm_offset_t db_addr_t;
+typedef int db_expr_t;
+
+#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_regs.sf_pc)
+
+#define BKPT_INST (KERNEL_BREAKPOINT)
+#define BKPT_SIZE (INSN_SIZE)
+#define BKPT_SET(inst) (BKPT_INST)
+
+#define BKPT_SKIP do { \
+ kdb_frame->tf_pc += BKPT_SIZE; \
+} while (0)
+
+#define SOFTWARE_SSTEP 1
+
+#define IS_BREAKPOINT_TRAP(type, code) (type == T_BREAKPOINT)
+#define IS_WATCHPOINT_TRAP(type, code) (0)
+
+
+#define inst_trap_return(ins) (0)
+/* ldmxx reg, {..., pc}
+ 01800000 stack mode
+ 000f0000 register
+ 0000ffff register list */
+/* mov pc, reg
+ 0000000f register */
+#define inst_return(ins) (((ins) & 0x0e108000) == 0x08108000 || \
+ ((ins) & 0x0ff0fff0) == 0x01a0f000 || \
+ ((ins) & 0x0ffffff0) == 0x012fff10) /* bx */
+/* bl ...
+ 00ffffff offset>>2 */
+#define inst_call(ins) (((ins) & 0x0f000000) == 0x0b000000)
+/* b ...
+ 00ffffff offset>>2 */
+/* ldr pc, [pc, reg, lsl #2]
+ 0000000f register */
+
+#define inst_branch(ins) (((ins) & 0x0f000000) == 0x0a000000 || \
+ ((ins) & 0x0fdffff0) == 0x079ff100 || \
+ ((ins) & 0x0cf0f000) == 0x0490f000 || \
+ ((ins) & 0x0ffffff0) == 0x012fff30 || /* blx */ \
+ ((ins) & 0x0de0f000) == 0x0080f000)
+
+#define inst_load(ins) (0)
+#define inst_store(ins) (0)
+
+#define next_instr_address(pc, bd) ((bd) ? (pc) : ((pc) + INSN_SIZE))
+
+#define DB_SMALL_VALUE_MAX (0x7fffffff)
+#define DB_SMALL_VALUE_MIN (-0x40001)
+
+#define DB_ELFSIZE 32
+
+int db_validate_address(vm_offset_t);
+
+u_int branch_taken (u_int insn, u_int pc);
+
+#ifdef __ARMEB__
+#define BYTE_MSF (1)
+#endif
+#endif /* !_MACHINE_DB_MACHDEP_H_ */
Property changes on: trunk/sys/arm/include/db_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/devmap.h
===================================================================
--- trunk/sys/arm/include/devmap.h (rev 0)
+++ trunk/sys/arm/include/devmap.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,94 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/devmap.h 266086 2014-05-14 20:17:31Z ian $
+ */
+
+#ifndef _MACHINE_DEVMAP_H_
+#define _MACHINE_DEVMAP_H_
+
+/*
+ * This structure is used by MD code to describe static mappings of devices
+ * which are established as part of bringing up the MMU early in the boot.
+ */
+struct arm_devmap_entry {
+ vm_offset_t pd_va; /* virtual address */
+ vm_paddr_t pd_pa; /* physical address */
+ vm_size_t pd_size; /* size of region */
+ vm_prot_t pd_prot; /* protection code */
+ int pd_cache; /* cache attributes */
+};
+
+/*
+ * Return the lowest KVA address used in any entry in the registered devmap
+ * table. This works with whatever table is registered, including the internal
+ * table used by arm_devmap_add_entry() if that routine was used. Platforms can
+ * implement initarm_lastaddr() by calling this if static device mappings are
+ * their only use of high KVA space.
+ */
+vm_offset_t arm_devmap_lastaddr(void);
+
+/*
+ * Automatically allocate KVA (from the top of the address space downwards) and
+ * make static device mapping entries in an internal table. The internal table
+ * is automatically registered on the first call to this.
+ */
+void arm_devmap_add_entry(vm_paddr_t pa, vm_size_t sz);
+
+/*
+ * Register a platform-local table to be bootstrapped by the generic
+ * initarm() in arm/machdep.c. This is used by newer code that allocates and
+ * fills in its own local table but does not have its own initarm() routine.
+ */
+void arm_devmap_register_table(const struct arm_devmap_entry * _table);
+
+/*
+ * Establish mappings for all the entries in the table. This is called
+ * automatically from the common initarm() in arm/machdep.c, and also from the
+ * custom initarm() routines in older code. If the table pointer is NULL, this
+ * will use the table installed previously by arm_devmap_register_table().
+ */
+void arm_devmap_bootstrap(vm_offset_t _l1pt,
+ const struct arm_devmap_entry *_table);
+
+/*
+ * Translate between virtual and physical addresses within a region that is
+ * static-mapped by the devmap code. If the given address range isn't
+ * static-mapped, then ptov returns NULL and vtop returns DEVMAP_PADDR_NOTFOUND.
+ * The latter implies that you can't vtop just the last byte of physical address
+ * space. This is not as limiting as it might sound, because even if a device
+ * occupies the end of the physical address space, you're only prevented from
+ * doing vtop for that single byte. If you vtop a size bigger than 1 it works.
+ */
+#define DEVMAP_PADDR_NOTFOUND ((vm_paddr_t)(-1))
+
+void * arm_devmap_ptov(vm_paddr_t _pa, vm_size_t _sz);
+vm_paddr_t arm_devmap_vtop(void * _va, vm_size_t _sz);
+
+/* Print the static mapping table; used for bootverbose output. */
+void arm_devmap_print_table(void);
+
+#endif
Property changes on: trunk/sys/arm/include/devmap.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/disassem.h
===================================================================
--- trunk/sys/arm/include/disassem.h (rev 0)
+++ trunk/sys/arm/include/disassem.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,55 @@
+/* $MidnightBSD$ */
+/* $NetBSD: disassem.h,v 1.4 2001/03/04 04:15:58 matt Exp $ */
+
+/*-
+ * Copyright (c) 1997 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Define the interface structure required by the disassembler.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/disassem.h 208052 2010-05-14 00:00:19Z cognet $
+ */
+
+#ifndef _MACHINE_DISASSEM_H_
+#define _MACHINE_DISASSEM_H_
+typedef struct {
+ u_int (*di_readword)(u_int);
+ void (*di_printaddr)(u_int);
+ int (*di_printf)(const char *, ...) __printflike(1, 2);
+} disasm_interface_t;
+
+/* Prototypes for callable functions */
+
+vm_offset_t disasm(const disasm_interface_t *, vm_offset_t, int);
+void disassemble(u_int);
+
+#endif /* !_MACHINE_DISASSEM_H_ */
Property changes on: trunk/sys/arm/include/disassem.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/elf.h
===================================================================
--- trunk/sys/arm/include/elf.h (rev 0)
+++ trunk/sys/arm/include/elf.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,115 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ * Copyright (c) 1996-1997 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/elf.h 269792 2014-08-10 22:26:29Z ian $
+ */
+
+#ifndef _MACHINE_ELF_H_
+#define _MACHINE_ELF_H_ 1
+
+/*
+ * EABI ELF definitions for the StrongARM architecture.
+ * See "ARM ELF", document no. `SWS ESPC 0003 A-08' for details.
+ */
+
+#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
+
+#define __ELF_WORD_SIZE 32 /* Used by <sys/elf_generic.h> */
+#include <sys/elf_generic.h>
+
+typedef struct { /* Auxiliary vector entry on initial stack */
+ int a_type; /* Entry type. */
+ union {
+ long a_val; /* Integer value. */
+ void *a_ptr; /* Address. */
+ void (*a_fcn)(void); /* Function pointer (not used). */
+ } a_un;
+} Elf32_Auxinfo;
+
+__ElfType(Auxinfo);
+
+#define ELF_ARCH EM_ARM
+
+#define ELF_MACHINE_OK(x) ((x) == EM_ARM)
+
+/* Unwind info section type */
+#define PT_ARM_EXIDX (PT_LOPROC + 1)
+
+/*
+ * Relocation types.
+ */
+
+/* Values for a_type. */
+#define AT_NULL 0 /* Terminates the vector. */
+#define AT_IGNORE 1 /* Ignored entry. */
+#define AT_EXECFD 2 /* File descriptor of program to load. */
+#define AT_PHDR 3 /* Program header of program already loaded. */
+#define AT_PHENT 4 /* Size of each program header entry. */
+#define AT_PHNUM 5 /* Number of program header entries. */
+#define AT_PAGESZ 6 /* Page size in bytes. */
+#define AT_BASE 7 /* Interpreter's base address. */
+#define AT_FLAGS 8 /* Flags (unused). */
+#define AT_ENTRY 9 /* Where interpreter should transfer control. */
+#define AT_NOTELF 10 /* Program is not ELF ?? */
+#define AT_UID 11 /* Real uid. */
+#define AT_EUID 12 /* Effective uid. */
+#define AT_GID 13 /* Real gid. */
+#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
+#define AT_CANARY 16 /* Canary for SSP */
+#define AT_CANARYLEN 17 /* Length of the canary. */
+#define AT_OSRELDATE 18 /* OSRELDATE. */
+#define AT_NCPUS 19 /* Number of CPUs. */
+#define AT_PAGESIZES 20 /* Pagesizes. */
+#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */
+#define AT_TIMEKEEP 22 /* Pointer to timehands. */
+#define AT_STACKPROT 23 /* Initial stack protection. */
+
+#define AT_COUNT 24 /* Count of defined aux entry types. */
+
+#define R_ARM_COUNT 33 /* Count of defined relocation types. */
+
+
+/* Define "machine" characteristics */
+#define ELF_TARG_CLASS ELFCLASS32
+#ifdef __ARMEB__
+#define ELF_TARG_DATA ELFDATA2MSB
+#else
+#define ELF_TARG_DATA ELFDATA2LSB
+#endif
+#define ELF_TARG_MACH EM_ARM
+#define ELF_TARG_VER 1
+
+/*
+ * Magic number for the elf trampoline, chosen wisely to be an immediate
+ * value.
+ */
+#define MAGIC_TRAMP_NUMBER 0x5c000003
+
+#define ET_DYN_LOAD_ADDR 0x12000
+
+#endif /* !_MACHINE_ELF_H_ */
Property changes on: trunk/sys/arm/include/elf.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/endian.h
===================================================================
--- trunk/sys/arm/include/endian.h (rev 0)
+++ trunk/sys/arm/include/endian.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,141 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)endian.h 8.1 (Berkeley) 6/10/93
+ * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $
+ * $FreeBSD: stable/10/sys/arm/include/endian.h 236992 2012-06-13 05:02:51Z imp $
+ */
+
+#ifndef _ENDIAN_H_
+#define _ENDIAN_H_
+
+#include <sys/_types.h>
+
+/*
+ * Definitions for byte order, according to byte significance from low
+ * address to high.
+ */
+#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
+#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */
+#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */
+
+#ifdef __ARMEB__
+#define _BYTE_ORDER _BIG_ENDIAN
+#else
+#define _BYTE_ORDER _LITTLE_ENDIAN
+#endif /* __ARMEB__ */
+
+#if __BSD_VISIBLE
+#define LITTLE_ENDIAN _LITTLE_ENDIAN
+#define BIG_ENDIAN _BIG_ENDIAN
+#define PDP_ENDIAN _PDP_ENDIAN
+#define BYTE_ORDER _BYTE_ORDER
+#endif
+
+#ifdef __ARMEB__
+#define _QUAD_HIGHWORD 0
+#define _QUAD_LOWWORD 1
+#define __ntohl(x) ((__uint32_t)(x))
+#define __ntohs(x) ((__uint16_t)(x))
+#define __htonl(x) ((__uint32_t)(x))
+#define __htons(x) ((__uint16_t)(x))
+#else
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+#define __ntohl(x) (__bswap32(x))
+#define __ntohs(x) (__bswap16(x))
+#define __htonl(x) (__bswap32(x))
+#define __htons(x) (__bswap16(x))
+#endif /* __ARMEB__ */
+
+static __inline __uint64_t
+__bswap64(__uint64_t _x)
+{
+
+ return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) |
+ ((_x >> 8) & 0xff000000) | ((_x << 8) & ((__uint64_t)0xff << 32)) |
+ ((_x << 24) & ((__uint64_t)0xff << 40)) |
+ ((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56)));
+}
+
+static __inline __uint32_t
+__bswap32_var(__uint32_t v)
+{
+ __uint32_t t1;
+
+ __asm __volatile("eor %1, %0, %0, ror #16\n"
+ "bic %1, %1, #0x00ff0000\n"
+ "mov %0, %0, ror #8\n"
+ "eor %0, %0, %1, lsr #8\n"
+ : "+r" (v), "=r" (t1));
+
+ return (v);
+}
+
+static __inline __uint16_t
+__bswap16_var(__uint16_t v)
+{
+ __uint32_t ret = v & 0xffff;
+
+ __asm __volatile(
+ "mov %0, %0, ror #8\n"
+ "orr %0, %0, %0, lsr #16\n"
+ "bic %0, %0, %0, lsl #16"
+ : "+r" (ret));
+
+ return ((__uint16_t)ret);
+}
+
+#ifdef __OPTIMIZE__
+
+#define __bswap32_constant(x) \
+ ((((x) & 0xff000000U) >> 24) | \
+ (((x) & 0x00ff0000U) >> 8) | \
+ (((x) & 0x0000ff00U) << 8) | \
+ (((x) & 0x000000ffU) << 24))
+
+#define __bswap16_constant(x) \
+ ((((x) & 0xff00) >> 8) | \
+ (((x) & 0x00ff) << 8))
+
+#define __bswap16(x) \
+ ((__uint16_t)(__builtin_constant_p(x) ? \
+ __bswap16_constant(x) : \
+ __bswap16_var(x)))
+
+#define __bswap32(x) \
+ ((__uint32_t)(__builtin_constant_p(x) ? \
+ __bswap32_constant(x) : \
+ __bswap32_var(x)))
+
+#else
+#define __bswap16(x) __bswap16_var(x)
+#define __bswap32(x) __bswap32_var(x)
+
+#endif /* __OPTIMIZE__ */
+#endif /* !_ENDIAN_H_ */
Property changes on: trunk/sys/arm/include/endian.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/exec.h
===================================================================
--- trunk/sys/arm/include/exec.h (rev 0)
+++ trunk/sys/arm/include/exec.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,38 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/exec.h 142107 2005-02-19 21:16:48Z ru $
+ */
+
+#ifndef _MACHINE_EXEC_H_
+#define _MACHINE_EXEC_H_
+
+#define __LDPGSZ 4096
+
+#endif /* !_MACHINE_EXEC_H_ */
Property changes on: trunk/sys/arm/include/exec.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/fdt.h
===================================================================
--- trunk/sys/arm/include/fdt.h (rev 0)
+++ trunk/sys/arm/include/fdt.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,59 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/fdt.h 266084 2014-05-14 19:18:58Z ian $
+ */
+
+#ifndef _MACHINE_FDT_H_
+#define _MACHINE_FDT_H_
+
+#include <dev/ofw/openfirm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+/* Max interrupt number */
+#define FDT_INTR_MAX NIRQ
+
+/* Map phandle/intpin pair to global IRQ number */
+#define FDT_MAP_IRQ(node, pin) (pin)
+
+/*
+ * Bus space tag. XXX endianess info needs to be derived from the blob.
+ */
+extern bus_space_tag_t fdtbus_bs_tag;
+
+struct arm_devmap_entry;
+
+int fdt_localbus_devmap(phandle_t, struct arm_devmap_entry *, int, int *);
+
+#endif /* _MACHINE_FDT_H_ */
Property changes on: trunk/sys/arm/include/fdt.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/fiq.h
===================================================================
--- trunk/sys/arm/include/fiq.h (rev 0)
+++ trunk/sys/arm/include/fiq.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,72 @@
+/* $MidnightBSD$ */
+/* $NetBSD: fiq.h,v 1.1 2001/12/20 01:20:23 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/fiq.h 139735 2005-01-05 21:58:49Z imp $
+ *
+ */
+
+#ifndef _MACHINE_FIQ_H_
+#define _MACHINE_FIQ_H_
+
+#include <sys/queue.h>
+
+struct fiqregs {
+ u_int fr_r8; /* FIQ mode r8 */
+ u_int fr_r9; /* FIQ mode r9 */
+ u_int fr_r10; /* FIQ mode r10 */
+ u_int fr_r11; /* FIQ mode r11 */
+ u_int fr_r12; /* FIQ mode r12 */
+ u_int fr_r13; /* FIQ mode r13 */
+};
+
+struct fiqhandler {
+ TAILQ_ENTRY(fiqhandler) fh_list;/* link in the FIQ handler stack */
+ void *fh_func; /* FIQ handler routine */
+ size_t fh_size; /* size of FIQ handler */
+ int fh_flags; /* flags; see below */
+ struct fiqregs *fh_regs; /* pointer to regs structure */
+};
+
+#define FH_CANPUSH 0x01 /* can push this handler out of the way */
+
+int fiq_claim(struct fiqhandler *);
+void fiq_release(struct fiqhandler *);
+
+void fiq_getregs(struct fiqregs *);
+void fiq_setregs(struct fiqregs *);
+
+#endif /* _MACHINE_FIQ_H_ */
Property changes on: trunk/sys/arm/include/fiq.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/float.h
===================================================================
--- trunk/sys/arm/include/float.h (rev 0)
+++ trunk/sys/arm/include/float.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,103 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)float.h 7.1 (Berkeley) 5/8/90
+ * $FreeBSD: stable/10/sys/arm/include/float.h 230475 2012-01-23 06:36:41Z das $
+ */
+
+#ifndef _MACHINE_FLOAT_H_
+#define _MACHINE_FLOAT_H_ 1
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int __flt_rounds(void);
+__END_DECLS
+
+#define FLT_RADIX 2 /* b */
+#ifndef _ARM_HARD_FLOAT
+#define FLT_ROUNDS __flt_rounds()
+#else
+#define FLT_ROUNDS (-1)
+#endif
+#if __ISO_C_VISIBLE >= 1999
+#define FLT_EVAL_METHOD 0
+#define DECIMAL_DIG 17 /* max precision in decimal digits */
+#endif
+
+#define FLT_MANT_DIG 24 /* p */
+#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */
+#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */
+#define FLT_MIN_EXP (-125) /* emin */
+#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */
+#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */
+#define FLT_MAX_EXP 128 /* emax */
+#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */
+#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */
+#if __ISO_C_VISIBLE >= 2011
+#define FLT_TRUE_MIN 1.40129846E-45F /* b**(emin-p) */
+#define FLT_DECIMAL_DIG 9 /* ceil(1+p*log10(b)) */
+#define FLT_HAS_SUBNORM 1
+#endif /* __ISO_C_VISIBLE >= 2011 */
+
+#define DBL_MANT_DIG 53
+#define DBL_EPSILON 2.2204460492503131E-16
+#define DBL_DIG 15
+#define DBL_MIN_EXP (-1021)
+#define DBL_MIN 2.2250738585072014E-308
+#define DBL_MIN_10_EXP (-307)
+#define DBL_MAX_EXP 1024
+#define DBL_MAX 1.7976931348623157E+308
+#define DBL_MAX_10_EXP 308
+#if __ISO_C_VISIBLE >= 2011
+#define DBL_TRUE_MIN 4.9406564584124654E-324
+#define DBL_DECIMAL_DIG 17
+#define DBL_HAS_SUBNORM 1
+#endif /* __ISO_C_VISIBLE >= 2011 */
+
+#define LDBL_MANT_DIG DBL_MANT_DIG
+#define LDBL_EPSILON ((long double)DBL_EPSILON)
+#define LDBL_DIG DBL_DIG
+#define LDBL_MIN_EXP DBL_MIN_EXP
+#define LDBL_MIN ((long double)DBL_MIN)
+#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+#define LDBL_MAX_EXP DBL_MAX_EXP
+#define LDBL_MAX ((long double)DBL_MAX)
+#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
+#if __ISO_C_VISIBLE >= 2011
+#define LDBL_TRUE_MIN ((long double)DBL_TRUE_MIN)
+#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG
+#define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM
+#endif /* __ISO_C_VISIBLE >= 2011 */
+
+#endif /* _MACHINE_FLOAT_H_ */
Property changes on: trunk/sys/arm/include/float.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/floatingpoint.h
===================================================================
--- trunk/sys/arm/include/floatingpoint.h (rev 0)
+++ trunk/sys/arm/include/floatingpoint.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,43 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1993 Andrew Moore, Talke Studio
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#) floatingpoint.h 1.0 (Berkeley) 9/23/93
+ * $FreeBSD: stable/10/sys/arm/include/floatingpoint.h 129198 2004-05-14 11:46:45Z cognet $
+ */
+
+#ifndef _FLOATINGPOINT_H_
+#define _FLOATINGPOINT_H_
+
+#include <machine/ieeefp.h>
+
+#endif /* !_FLOATINGPOINT_H_ */
Property changes on: trunk/sys/arm/include/floatingpoint.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/fp.h
===================================================================
--- trunk/sys/arm/include/fp.h (rev 0)
+++ trunk/sys/arm/include/fp.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,90 @@
+/* $MidnightBSD$ */
+/* $NetBSD: fp.h,v 1.1 2001/01/10 19:02:06 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fp.h
+ *
+ * FP info
+ *
+ * Created : 10/10/95
+ *
+ * $FreeBSD: stable/10/sys/arm/include/fp.h 266341 2014-05-17 19:37:04Z ian $
+ */
+
+#ifndef _MACHINE_FP_H
+#define _MACHINE_FP_H
+
+/*
+ * An extended precision floating point number
+ */
+
+typedef struct fp_extended_precision {
+ u_int32_t fp_exponent;
+ u_int32_t fp_mantissa_hi;
+ u_int32_t fp_mantissa_lo;
+} fp_extended_precision_t;
+
+typedef struct fp_extended_precision fp_reg_t;
+
+/*
+ * Information about the FPE-SP state that is stored in the pcb
+ *
+ * This needs to move and be hidden from userland.
+ */
+
+struct vfp_state {
+ u_int64_t reg[32];
+ u_int32_t fpscr;
+ u_int32_t fpexec;
+ u_int32_t fpinst;
+ u_int32_t fpinst2;
+};
+
+/*
+ * Type for a saved FP context, if we want to translate the context to a
+ * user-readable form
+ */
+
+typedef struct {
+ u_int32_t fpsr;
+ fp_extended_precision_t regs[8];
+} fp_state_t;
+
+#endif /* _MACHINE_FP_H_ */
+
+/* End of fp.h */
Property changes on: trunk/sys/arm/include/fp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/frame.h
===================================================================
--- trunk/sys/arm/include/frame.h (rev 0)
+++ trunk/sys/arm/include/frame.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,136 @@
+/* $MidnightBSD$ */
+/* $NetBSD: frame.h,v 1.5 2002/10/19 00:10:54 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1994-1997 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * frame.h
+ *
+ * Stack frames structures
+ *
+ * Created : 30/09/94
+ *
+ * $FreeBSD: stable/10/sys/arm/include/frame.h 278614 2015-02-12 04:15:55Z ian $
+ *
+ */
+
+#ifndef _MACHINE_FRAME_H_
+#define _MACHINE_FRAME_H_
+
+#ifndef _LOCORE
+
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+
+
+/*
+ * Trap frame. Pushed onto the kernel stack on a trap (synchronous exception).
+ */
+
+struct trapframe {
+ register_t tf_spsr; /* Zero on arm26 */
+ register_t tf_r0;
+ register_t tf_r1;
+ register_t tf_r2;
+ register_t tf_r3;
+ register_t tf_r4;
+ register_t tf_r5;
+ register_t tf_r6;
+ register_t tf_r7;
+ register_t tf_r8;
+ register_t tf_r9;
+ register_t tf_r10;
+ register_t tf_r11;
+ register_t tf_r12;
+ register_t tf_usr_sp;
+ register_t tf_usr_lr;
+ register_t tf_svc_sp; /* Not used on arm26 */
+ register_t tf_svc_lr; /* Not used on arm26 */
+ register_t tf_pc;
+ register_t tf_pad;
+};
+
+/* Register numbers */
+#define tf_r13 tf_usr_sp
+#define tf_r14 tf_usr_lr
+#define tf_r15 tf_pc
+
+/*
+ * Signal frame. Pushed onto user stack before calling sigcode.
+ * The pointers are used in the trampoline code to locate the ucontext.
+ */
+struct sigframe {
+ siginfo_t sf_si; /* actual saved siginfo */
+ ucontext_t sf_uc; /* actual saved ucontext */
+};
+
+
+/*
+ * Switch frame.
+ *
+ * It is important this is a multiple of 8 bytes so the stack is correctly
+ * aligned when we create new threads.
+ */
+struct switchframe
+{
+ register_t sf_r4;
+ register_t sf_r5;
+ register_t sf_r6;
+ register_t sf_r7;
+ register_t sf_r8;
+ register_t sf_r9;
+ register_t sf_r10;
+ register_t sf_r11;
+ register_t sf_r12;
+ register_t sf_sp;
+ register_t sf_lr;
+ register_t sf_pc;
+};
+
+
+/*
+ * Stack frame. Used during stack traces (db_trace.c)
+ */
+struct frame {
+ u_int fr_fp;
+ u_int fr_sp;
+ u_int fr_lr;
+ u_int fr_pc;
+};
+
+#endif /* !_LOCORE */
+
+#endif /* _MACHINE_FRAME_H_ */
Property changes on: trunk/sys/arm/include/frame.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/gdb_machdep.h
===================================================================
--- trunk/sys/arm/include/gdb_machdep.h (rev 0)
+++ trunk/sys/arm/include/gdb_machdep.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,53 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/gdb_machdep.h 160332 2006-07-14 00:50:51Z cognet $
+ */
+
+#ifndef _MACHINE_GDB_MACHDEP_H_
+#define _MACHINE_GDB_MACHDEP_H_
+
+#define GDB_BUFSZ 400
+#define GDB_NREGS 26
+#define GDB_REG_PC 15
+
+static __inline size_t
+gdb_cpu_regsz(int regnum __unused)
+{
+ return (sizeof(int));
+}
+
+static __inline int
+gdb_cpu_query(void)
+{
+ return (0);
+}
+
+void *gdb_cpu_getreg(int, size_t *);
+void gdb_cpu_setreg(int, void *);
+int gdb_cpu_signal(int, int);
+
+#endif /* !_MACHINE_GDB_MACHDEP_H_ */
Property changes on: trunk/sys/arm/include/gdb_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/ieee.h
===================================================================
--- trunk/sys/arm/include/ieee.h (rev 0)
+++ trunk/sys/arm/include/ieee.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,166 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ieee754.h,v 1.4 2003/10/27 02:30:26 simonb Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ieee.h 8.1 (Berkeley) 6/11/93
+ *
+ * $FreeBSD: stable/10/sys/arm/include/ieee.h 255361 2013-09-07 14:04:10Z andrew $
+ *
+ */
+
+/*
+ * NOTICE: This is not a standalone file. To use it, #include it in
+ * your port's ieee.h header.
+ */
+
+#include <machine/endian.h>
+
+/*
+ * <sys/ieee754.h> defines the layout of IEEE 754 floating point types.
+ * Only single-precision and double-precision types are defined here;
+ * extended types, if available, are defined in the machine-dependent
+ * header.
+ */
+
+/*
+ * Define the number of bits in each fraction and exponent.
+ *
+ * k k+1
+ * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
+ *
+ * (-exp_bias+1)
+ * as fractions that look like 0.fffff x 2 . This means that
+ *
+ * -126
+ * the number 0.10000 x 2 , for instance, is the same as the normalized
+ *
+ * -127 -128
+ * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
+ *
+ * -129
+ * in the fraction; to represent 2 , we need two, and so on. This
+ *
+ * (-exp_bias-fracbits+1)
+ * implies that the smallest denormalized number is 2
+ *
+ * for whichever format we are talking about: for single precision, for
+ *
+ * -126 -149
+ * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
+ *
+ * -149 == -127 - 23 + 1.
+ */
+#define SNG_EXPBITS 8
+#define SNG_FRACBITS 23
+
+#define DBL_EXPBITS 11
+#define DBL_FRACBITS 52
+
+#if defined(__VFP_FP__) || defined(__ARM_EABI__)
+#define _IEEE_WORD_ORDER _BYTE_ORDER
+#else
+#define _IEEE_WORD_ORDER _BIG_ENDIAN
+#endif
+
+struct ieee_single {
+#if _BYTE_ORDER == _BIG_ENDIAN
+ u_int sng_sign:1;
+ u_int sng_exp:8;
+ u_int sng_frac:23;
+#else
+ u_int sng_frac:23;
+ u_int sng_exp:8;
+ u_int sng_sign:1;
+#endif
+};
+
+struct ieee_double {
+#if _BYTE_ORDER == _BIG_ENDIAN
+ u_int dbl_sign:1;
+ u_int dbl_exp:11;
+ u_int dbl_frach:20;
+ u_int dbl_fracl;
+#else
+#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
+ u_int dbl_fracl;
+#endif
+ u_int dbl_frach:20;
+ u_int dbl_exp:11;
+ u_int dbl_sign:1;
+#if _IEEE_WORD_ORDER == _BIG_ENDIAN
+ u_int dbl_fracl;
+#endif
+#endif
+};
+
+/*
+ * Floats whose exponent is in [1..INFNAN) (of whatever type) are
+ * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
+ * Floats whose exponent is zero are either zero (iff all fraction
+ * bits are zero) or subnormal values.
+ *
+ * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
+ * high fraction; if the bit is set, it is a `quiet NaN'.
+ */
+#define SNG_EXP_INFNAN 255
+#define DBL_EXP_INFNAN 2047
+
+#if 0
+#define SNG_QUIETNAN (1 << 22)
+#define DBL_QUIETNAN (1 << 19)
+#endif
+
+/*
+ * Exponent biases.
+ */
+#define SNG_EXP_BIAS 127
+#define DBL_EXP_BIAS 1023
+
+/*
+ * Convenience data structures.
+ */
+union ieee_single_u {
+ float sngu_f;
+ struct ieee_single sngu_sng;
+};
+
+union ieee_double_u {
+ double dblu_d;
+ struct ieee_double dblu_dbl;
+};
Property changes on: trunk/sys/arm/include/ieee.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/ieeefp.h
===================================================================
--- trunk/sys/arm/include/ieeefp.h (rev 0)
+++ trunk/sys/arm/include/ieeefp.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,54 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ieeefp.h,v 1.1 2001/01/10 19:02:06 bjh21 Exp $ */
+/* $FreeBSD: stable/10/sys/arm/include/ieeefp.h 226607 2011-10-21 06:41:46Z das $ */
+/*-
+ * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995
+ * Public domain.
+ */
+
+#ifndef _MACHINE_IEEEFP_H_
+#define _MACHINE_IEEEFP_H_
+
+/* Deprecated historical FPU control interface */
+
+/* FP exception codes */
+#define FP_EXCEPT_INV 0
+#define FP_EXCEPT_DZ 1
+#define FP_EXCEPT_OFL 2
+#define FP_EXCEPT_UFL 3
+#define FP_EXCEPT_IMP 4
+
+/* Exception type (used by fpsetmask() et al.) */
+
+typedef int fp_except;
+
+/* Bit defines for fp_except */
+
+#define FP_X_INV (1 << FP_EXCEPT_INV) /* invalid operation exception */
+#define FP_X_DZ (1 << FP_EXCEPT_DZ) /* divide-by-zero exception */
+#define FP_X_OFL (1 << FP_EXCEPT_OFL) /* overflow exception */
+#define FP_X_UFL (1 << FP_EXCEPT_UFL) /* underflow exception */
+#define FP_X_IMP (1 << FP_EXCEPT_IMP) /* imprecise (loss of precision; "inexact") */
+
+/* Rounding modes */
+
+typedef enum {
+ FP_RN=0, /* round to nearest representable number */
+ FP_RP=1, /* round toward positive infinity */
+ FP_RM=2, /* round toward negative infinity */
+ FP_RZ=3 /* round to zero (truncate) */
+} fp_rnd_t;
+
+/*
+ * FP precision modes
+ */
+typedef enum {
+ FP_PS=0, /* 24 bit (single-precision) */
+ FP_PRS, /* reserved */
+ FP_PD, /* 53 bit (double-precision) */
+ FP_PE /* 64 bit (extended-precision) */
+} fp_prec_t;
+
+#define fp_except_t int
+
+#endif /* _MACHINE_IEEEFP_H_ */
Property changes on: trunk/sys/arm/include/ieeefp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/in_cksum.h
===================================================================
--- trunk/sys/arm/include/in_cksum.h (rev 0)
+++ trunk/sys/arm/include/in_cksum.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,69 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from tahoe: in_cksum.c 1.2 86/01/05
+ * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91
+ * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp
+ * $FreeBSD: stable/10/sys/arm/include/in_cksum.h 236992 2012-06-13 05:02:51Z imp $
+ */
+
+#ifndef _MACHINE_IN_CKSUM_H_
+#define _MACHINE_IN_CKSUM_H_ 1
+
+#include <sys/cdefs.h>
+
+#ifdef _KERNEL
+u_short in_cksum(struct mbuf *m, int len);
+u_short in_addword(u_short sum, u_short b);
+u_short in_cksum_skip(struct mbuf *m, int len, int skip);
+u_int do_cksum(const void *, int);
+#if defined(IPVERSION) && (IPVERSION == 4)
+u_int in_cksum_hdr(const struct ip *);
+#endif
+
+static __inline u_short
+in_pseudo(u_int sum, u_int b, u_int c)
+{
+ __asm __volatile("adds %0, %0, %1\n"
+ "adcs %0, %0, %2\n"
+ "adc %0, %0, #0\n"
+ : "+r" (sum)
+ : "r" (b), "r" (c));
+ sum = (sum & 0xffff) + (sum >> 16);
+ if (sum > 0xffff)
+ sum -= 0xffff;
+ return (sum);
+}
+
+#endif /* _KERNEL */
+#endif /* _MACHINE_IN_CKSUM_H_ */
Property changes on: trunk/sys/arm/include/in_cksum.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/intr.h
===================================================================
--- trunk/sys/arm/include/intr.h (rev 0)
+++ trunk/sys/arm/include/intr.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,89 @@
+/* $MidnightBSD$ */
+/* $NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1997 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/intr.h 273672 2014-10-26 03:52:45Z ian $
+ *
+ */
+
+#ifndef _MACHINE_INTR_H_
+#define _MACHINE_INTR_H_
+
+/* XXX move to std.* files? */
+#ifdef CPU_XSCALE_81342
+#define NIRQ 128
+#elif defined(CPU_XSCALE_PXA2X0)
+#include <arm/xscale/pxa/pxareg.h>
+#define NIRQ IRQ_GPIO_MAX
+#elif defined(SOC_MV_DISCOVERY)
+#define NIRQ 96
+#elif defined(CPU_ARM9) || defined(SOC_MV_KIRKWOOD) || \
+ defined(CPU_XSCALE_IXP435)
+#define NIRQ 64
+#elif defined(CPU_CORTEXA)
+#define NIRQ 160
+#elif defined(CPU_KRAIT)
+#define NIRQ 288
+#elif defined(CPU_ARM1136) || defined(CPU_ARM1176)
+#define NIRQ 128
+#elif defined(SOC_MV_ARMADAXP)
+#define MAIN_IRQ_NUM 116
+#define ERR_IRQ_NUM 32
+#define ERR_IRQ (MAIN_IRQ_NUM)
+#define MSI_IRQ_NUM 32
+#define MSI_IRQ (ERR_IRQ + ERR_IRQ_NUM)
+#define NIRQ (MAIN_IRQ_NUM + ERR_IRQ_NUM + MSI_IRQ_NUM)
+#else
+#define NIRQ 32
+#endif
+
+
+int arm_get_next_irq(int);
+void arm_mask_irq(uintptr_t);
+void arm_unmask_irq(uintptr_t);
+void arm_intrnames_init(void);
+void arm_setup_irqhandler(const char *, int (*)(void*), void (*)(void*),
+ void *, int, int, void **);
+int arm_remove_irqhandler(int, void *);
+extern void (*arm_post_filter)(void *);
+extern int (*arm_config_irq)(int irq, enum intr_trigger trig,
+ enum intr_polarity pol);
+
+void arm_irq_memory_barrier(uintptr_t);
+
+void gic_init_secondary(void);
+int gic_decode_fdt(uint32_t iparentnode, uint32_t *intrcells, int *interrupt,
+ int *trig, int *pol);
+
+#endif /* _MACHINE_INTR_H */
Property changes on: trunk/sys/arm/include/intr.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/katelib.h
===================================================================
--- trunk/sys/arm/include/katelib.h (rev 0)
+++ trunk/sys/arm/include/katelib.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,104 @@
+/* $MidnightBSD$ */
+/* $NetBSD: katelib.h,v 1.3 2001/11/23 19:21:48 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * katelib.h
+ *
+ * Prototypes for machine specific functions. Most of these
+ * could be inlined.
+ *
+ * This should not really be a separate header file. Eventually I will merge
+ * this into other header files once I have decided where the declarations
+ * should go.
+ *
+ * Created : 18/09/94
+ *
+ * Based on kate/katelib/prototypes.h
+ *
+ * $FreeBSD: stable/10/sys/arm/include/katelib.h 236992 2012-06-13 05:02:51Z imp $
+ */
+
+/*
+ * USE OF THIS FILE IS DEPRECATED
+ */
+
+#ifndef _MACHINE_KATELIB_H_
+#define _MACHINE_KATELIB_H_
+#include <sys/types.h>
+#include <machine/cpufunc.h>
+
+#ifdef _KERNEL
+
+/* Assembly modules */
+
+/* In blockio.S */
+#include <machine/blockio.h>
+
+/* Macros for reading and writing words, shorts, bytes */
+
+#define WriteWord(a, b) \
+*((volatile unsigned int *)(a)) = (b)
+
+#define ReadWord(a) \
+(*((volatile unsigned int *)(a)))
+
+#define WriteShort(a, b) \
+*((volatile unsigned int *)(a)) = ((b) | ((b) << 16))
+
+#define ReadShort(a) \
+((*((volatile unsigned int *)(a))) & 0xffff)
+
+#define WriteByte(a, b) \
+*((volatile unsigned char *)(a)) = (b)
+
+#define ReadByte(a) \
+(*((volatile unsigned char *)(a)))
+
+/* Define in/out macros */
+
+#define inb(port) ReadByte((port))
+#define outb(port, byte) WriteByte((port), (byte))
+#define inw(port) ReadShort((port))
+#define outw(port, word) WriteShort((port), (word))
+#define inl(port) ReadWord((port))
+#define outl(port, lword) WriteWord((port), (lword))
+
+#endif
+
+#endif /* !_MACHINE_KATELIB_H_ */
+/* End of katelib.h */
Property changes on: trunk/sys/arm/include/katelib.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/kdb.h
===================================================================
--- trunk/sys/arm/include/kdb.h (rev 0)
+++ trunk/sys/arm/include/kdb.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,61 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/kdb.h 266373 2014-05-17 22:50:16Z ian $
+ */
+
+#ifndef _MACHINE_KDB_H_
+#define _MACHINE_KDB_H_
+
+#include <machine/frame.h>
+#include <machine/psl.h>
+#include <machine/cpufunc.h>
+
+#define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid]
+
+static __inline void
+kdb_cpu_clear_singlestep(void)
+{
+}
+
+static __inline void
+kdb_cpu_set_singlestep(void)
+{
+}
+
+static __inline void
+kdb_cpu_sync_icache(unsigned char *addr, size_t size)
+{
+
+ cpu_icache_sync_range((vm_offset_t)addr, size);
+}
+
+static __inline void
+kdb_cpu_trap(int type, int code)
+{
+}
+
+#endif /* _MACHINE_KDB_H_ */
Property changes on: trunk/sys/arm/include/kdb.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/limits.h
===================================================================
--- trunk/sys/arm/include/limits.h (rev 0)
+++ trunk/sys/arm/include/limits.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,45 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)limits.h 8.3 (Berkeley) 1/4/94
+ * $FreeBSD: stable/10/sys/arm/include/limits.h 143063 2005-03-02 21:33:29Z joerg $
+ */
+
+#ifndef _MACHINE_LIMITS_H_
+#define _MACHINE_LIMITS_H_
+
+#include <sys/cdefs.h>
+
+#ifdef __CC_SUPPORTS_WARNING
+#warning "machine/limits.h is deprecated. Include sys/limits.h instead."
+#endif
+
+#include <sys/limits.h>
+
+#endif /* !_MACHINE_LIMITS_H_ */
Property changes on: trunk/sys/arm/include/limits.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/machdep.h
===================================================================
--- trunk/sys/arm/include/machdep.h (rev 0)
+++ trunk/sys/arm/include/machdep.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,75 @@
+/* $MidnightBSD$ */
+/* $NetBSD: machdep.h,v 1.7 2002/02/21 02:52:21 thorpej Exp $ */
+/* $FreeBSD: stable/10/sys/arm/include/machdep.h 278630 2015-02-12 19:35:46Z ian $ */
+
+#ifndef _MACHDEP_BOOT_MACHDEP_H_
+#define _MACHDEP_BOOT_MACHDEP_H_
+
+/* Structs that need to be initialised by initarm */
+struct pv_addr;
+extern struct pv_addr irqstack;
+extern struct pv_addr undstack;
+extern struct pv_addr abtstack;
+
+/* Define various stack sizes in pages */
+#define IRQ_STACK_SIZE 1
+#define ABT_STACK_SIZE 1
+#define UND_STACK_SIZE 1
+
+/* misc prototypes used by the many arm machdeps */
+struct trapframe;
+void arm_lock_cache_line(vm_offset_t);
+void init_proc0(vm_offset_t kstack);
+void halt(void);
+void abort_handler(struct trapframe *, int );
+void set_stackptrs(int cpu);
+void undefinedinstruction_bounce(struct trapframe *);
+
+/* Early boot related helper functions */
+struct arm_boot_params;
+vm_offset_t default_parse_boot_param(struct arm_boot_params *abp);
+vm_offset_t freebsd_parse_boot_param(struct arm_boot_params *abp);
+vm_offset_t linux_parse_boot_param(struct arm_boot_params *abp);
+vm_offset_t fake_preload_metadata(struct arm_boot_params *abp);
+vm_offset_t parse_boot_param(struct arm_boot_params *abp);
+void arm_generic_initclocks(void);
+
+/*
+ * Initialization functions called by the common initarm() function in
+ * arm/machdep.c (but not necessarily from the custom initarm() functions of
+ * older code).
+ *
+ * - initarm_early_init() is called very early, after parsing the boot params
+ * and after physical memory has been located and sized.
+ *
+ * - platform_devmap_init() is called as one of the last steps of early virtual
+ * memory initialization, shortly before the new page tables are installed.
+ *
+ * - initarm_lastaddr() is called after platform_devmap_init(), and must return
+ * the address of the first byte of unusable KVA space. This allows a
+ * platform to carve out of the top of the KVA space whatever reserves it
+ * needs for things like static device mapping, and this is called to get the
+ * value before calling pmap_bootstrap() which uses the value to size the
+ * available KVA.
+ *
+ * - initarm_gpio_init() is called after the static device mappings are
+ * established and just before cninit(). The intention is that the routine
+ * can do any hardware setup (such as gpio or pinmux) necessary to make the
+ * console functional.
+ *
+ * - initarm_late_init() is called just after cninit(). This is the first of
+ * the init routines that can use printf() and expect the output to appear on
+ * a standard console.
+ *
+ */
+void initarm_early_init(void);
+int initarm_devmap_init(void);
+vm_offset_t initarm_lastaddr(void);
+void initarm_gpio_init(void);
+void initarm_late_init(void);
+
+/* Board-specific attributes */
+void board_set_serial(uint64_t);
+void board_set_revision(uint32_t);
+
+#endif /* !_MACHINE_MACHDEP_H_ */
Property changes on: trunk/sys/arm/include/machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/md_var.h
===================================================================
--- trunk/sys/arm/include/md_var.h (rev 0)
+++ trunk/sys/arm/include/md_var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,75 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1995 Bruce D. Evans.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the author nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: src/sys/i386/include/md_var.h,v 1.40 2001/07/12
+ * $FreeBSD: stable/10/sys/arm/include/md_var.h 278730 2015-02-13 23:30:48Z ian $
+ */
+
+#ifndef _MACHINE_MD_VAR_H_
+#define _MACHINE_MD_VAR_H_
+
+extern long Maxmem;
+extern char sigcode[];
+extern int szsigcode;
+extern uint32_t *vm_page_dump;
+extern int vm_page_dump_size;
+
+extern int (*_arm_memcpy)(void *, void *, int, int);
+extern int (*_arm_bzero)(void *, int, int);
+
+extern int _min_memcpy_size;
+extern int _min_bzero_size;
+
+#define DST_IS_USER 0x1
+#define SRC_IS_USER 0x2
+#define IS_PHYSICAL 0x4
+
+enum cpu_class {
+ CPU_CLASS_NONE,
+ CPU_CLASS_ARM9TDMI,
+ CPU_CLASS_ARM9ES,
+ CPU_CLASS_ARM9EJS,
+ CPU_CLASS_ARM10E,
+ CPU_CLASS_ARM10EJ,
+ CPU_CLASS_CORTEXA,
+ CPU_CLASS_KRAIT,
+ CPU_CLASS_XSCALE,
+ CPU_CLASS_ARM11J,
+ CPU_CLASS_MARVELL
+};
+extern enum cpu_class cpu_class;
+
+struct dumperinfo;
+extern int busdma_swi_pending;
+void busdma_swi(void);
+void dump_add_page(vm_paddr_t);
+void dump_drop_page(vm_paddr_t);
+void minidumpsys(struct dumperinfo *);
+
+#endif /* !_MACHINE_MD_VAR_H_ */
Property changes on: trunk/sys/arm/include/md_var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/memdev.h
===================================================================
--- trunk/sys/arm/include/memdev.h (rev 0)
+++ trunk/sys/arm/include/memdev.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,41 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/memdev.h 217515 2011-01-17 22:58:28Z jkim $
+ */
+
+#ifndef _MACHINE_MEMDEV_H_
+#define _MACHINE_MEMDEV_H_
+
+#define CDEV_MINOR_MEM 0
+#define CDEV_MINOR_KMEM 1
+
+d_open_t memopen;
+d_read_t memrw;
+d_mmap_t memmmap;
+#define memioctl (d_ioctl_t *)NULL
+
+#endif /* _MACHINE_MEMDEV_H_ */
Property changes on: trunk/sys/arm/include/memdev.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/metadata.h
===================================================================
--- trunk/sys/arm/include/metadata.h (rev 0)
+++ trunk/sys/arm/include/metadata.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,36 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Peter Wemm <peter at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/metadata.h 217290 2011-01-11 22:07:39Z marcel $
+ */
+
+#ifndef _MACHINE_METADATA_H_
+#define _MACHINE_METADATA_H_
+
+#define MODINFOMD_BOOTINFO 0x1001
+#define MODINFOMD_DTBP 0x1002
+
+#endif /* !_MACHINE_METADATA_H_ */
Property changes on: trunk/sys/arm/include/metadata.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/minidump.h
===================================================================
--- trunk/sys/arm/include/minidump.h (rev 0)
+++ trunk/sys/arm/include/minidump.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,46 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * From: FreeBSD: src/sys/i386/include/minidump.h,v 1.1 2006/04/21 04:28:43
+ * $FreeBSD: stable/10/sys/arm/include/minidump.h 184728 2008-11-06 16:20:27Z raj $
+ */
+
+#ifndef _MACHINE_MINIDUMP_H_
+#define _MACHINE_MINIDUMP_H_ 1
+
+#define MINIDUMP_MAGIC "minidump FreeBSD/arm"
+#define MINIDUMP_VERSION 1
+
+struct minidumphdr {
+ char magic[24];
+ uint32_t version;
+ uint32_t msgbufsize;
+ uint32_t bitmapsize;
+ uint32_t ptesize;
+ uint32_t kernbase;
+};
+
+#endif /* _MACHINE_MINIDUMP_H_ */
Property changes on: trunk/sys/arm/include/minidump.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/ofw_machdep.h
===================================================================
--- trunk/sys/arm/include/ofw_machdep.h (rev 0)
+++ trunk/sys/arm/include/ofw_machdep.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,45 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/ofw_machdep.h 266084 2014-05-14 19:18:58Z ian $
+ */
+
+#ifndef _MACHINE_OFW_MACHDEP_H_
+#define _MACHINE_OFW_MACHDEP_H_
+
+#include <vm/vm.h>
+
+typedef uint32_t cell_t;
+
+struct mem_region {
+ vm_offset_t mr_start;
+ vm_size_t mr_size;
+};
+
+#endif /* _MACHINE_OFW_MACHDEP_H_ */
Property changes on: trunk/sys/arm/include/ofw_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/param.h
===================================================================
--- trunk/sys/arm/include/param.h (rev 0)
+++ trunk/sys/arm/include/param.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,157 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)param.h 5.8 (Berkeley) 6/28/91
+ * $FreeBSD: stable/10/sys/arm/include/param.h 274648 2014-11-18 12:53:32Z kib $
+ */
+
+#ifndef _ARM_INCLUDE_PARAM_H_
+#define _ARM_INCLUDE_PARAM_H_
+
+/*
+ * Machine dependent constants for StrongARM
+ */
+
+#include <machine/_align.h>
+#include <machine/acle-compat.h>
+
+#define STACKALIGNBYTES (8 - 1)
+#define STACKALIGN(p) ((u_int)(p) & ~STACKALIGNBYTES)
+
+#define __PCI_REROUTE_INTERRUPT
+
+#if __ARM_ARCH >= 6
+#define _V6_SUFFIX "v6"
+#else
+#define _V6_SUFFIX ""
+#endif
+
+#ifdef __ARM_PCS_VFP
+#define _HF_SUFFIX "hf"
+#else
+#define _HF_SUFFIX ""
+#endif
+
+#ifdef __ARM_BIG_ENDIAN
+#define _EB_SUFFIX "eb"
+#else
+#define _EB_SUFFIX ""
+#endif
+
+#ifndef MACHINE
+#define MACHINE "arm"
+#endif
+#ifndef MACHINE_ARCH
+#define MACHINE_ARCH "arm" _V6_SUFFIX _HF_SUFFIX _EB_SUFFIX
+#endif
+
+#if defined(SMP) || defined(KLD_MODULE)
+#ifndef MAXCPU
+#define MAXCPU 4
+#endif
+#else
+#define MAXCPU 1
+#endif /* SMP || KLD_MODULE */
+
+#ifndef MAXMEMDOM
+#define MAXMEMDOM 1
+#endif
+
+#define ALIGNBYTES _ALIGNBYTES
+#define ALIGN(p) _ALIGN(p)
+/*
+ * ALIGNED_POINTER is a boolean macro that checks whether an address
+ * is valid to fetch data elements of type t from on this architecture.
+ * This does not reflect the optimal alignment, just the possibility
+ * (within reasonable limits).
+ */
+#define ALIGNED_POINTER(p, t) ((((unsigned)(p)) & (sizeof(t)-1)) == 0)
+
+/*
+ * CACHE_LINE_SIZE is the compile-time maximum cache line size for an
+ * architecture. It should be used with appropriate caution.
+ */
+#define CACHE_LINE_SHIFT 6
+#define CACHE_LINE_SIZE (1 << CACHE_LINE_SHIFT)
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */
+#define PAGE_MASK (PAGE_SIZE - 1)
+#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t)))
+
+#define PDR_SHIFT 20 /* log2(NBPDR) */
+#define NBPDR (1 << PDR_SHIFT)
+#define PDRMASK (NBPDR - 1)
+#define NPDEPG (1 << (32 - PDR_SHIFT))
+
+#define MAXPAGESIZES 2 /* maximum number of supported page sizes */
+
+#ifndef KSTACK_PAGES
+#define KSTACK_PAGES 2
+#endif /* !KSTACK_PAGES */
+
+#ifndef FPCONTEXTSIZE
+#define FPCONTEXTSIZE (0x100)
+#endif
+
+#ifndef KSTACK_GUARD_PAGES
+#define KSTACK_GUARD_PAGES 1
+#endif /* !KSTACK_GUARD_PAGES */
+
+#define USPACE_SVC_STACK_TOP (KSTACK_PAGES * PAGE_SIZE)
+
+/*
+ * Mach derived conversion macros
+ */
+#define trunc_page(x) ((x) & ~PAGE_MASK)
+#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK)
+#define trunc_1mpage(x) ((unsigned)(x) & ~PDRMASK)
+#define round_1mpage(x) ((((unsigned)(x)) + PDRMASK) & ~PDRMASK)
+
+#define atop(x) ((unsigned)(x) >> PAGE_SHIFT)
+#define ptoa(x) ((unsigned)(x) << PAGE_SHIFT)
+
+#define arm32_btop(x) ((unsigned)(x) >> PAGE_SHIFT)
+#define arm32_ptob(x) ((unsigned)(x) << PAGE_SHIFT)
+
+#define pgtok(x) ((x) * (PAGE_SIZE / 1024))
+
+#ifdef _KERNEL
+#define NO_FUEWORD 1
+#endif
+
+#endif /* !_ARM_INCLUDE_PARAM_H_ */
Property changes on: trunk/sys/arm/include/param.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/pcb.h
===================================================================
--- trunk/sys/arm/include/pcb.h (rev 0)
+++ trunk/sys/arm/include/pcb.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,83 @@
+/* $MidnightBSD$ */
+/* $NetBSD: pcb.h,v 1.10 2003/10/13 21:46:39 scw Exp $ */
+
+/*-
+ * Copyright (c) 2001 Matt Thomas <matt at 3am-software.com>.
+ * Copyright (c) 1994 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/pcb.h 278614 2015-02-12 04:15:55Z ian $
+ */
+
+#ifndef _MACHINE_PCB_H_
+#define _MACHINE_PCB_H_
+
+#include <machine/fp.h>
+#include <machine/frame.h>
+
+
+/*
+ * WARNING!
+ * Keep pcb_regs first for faster access in switch.S
+ */
+struct pcb {
+ struct switchframe pcb_regs; /* CPU state */
+ u_int pcb_flags;
+#define PCB_OWNFPU 0x00000001
+#define PCB_NOALIGNFLT 0x00000002
+ caddr_t pcb_onfault; /* On fault handler */
+ vm_offset_t pcb_pagedir; /* PT hooks */
+ uint32_t *pcb_pl1vec; /* PTR to vector_base L1 entry*/
+ uint32_t pcb_l1vec; /* Value to stuff on ctx sw */
+ u_int pcb_dacr; /* Domain Access Control Reg */
+
+ struct vfp_state pcb_vfpstate; /* VP/NEON state */
+ u_int pcb_vfpcpu; /* VP/NEON last cpu */
+} __aligned(8); /*
+ * We need the PCB to be aligned on 8 bytes, as we may
+ * access it using ldrd/strd, and ARM ABI require it
+ * to by aligned on 8 bytes.
+ */
+
+/*
+ * No additional data for core dumps.
+ */
+struct md_coredump {
+ int md_empty;
+};
+
+void makectx(struct trapframe *tf, struct pcb *pcb);
+
+#ifdef _KERNEL
+
+void savectx(struct pcb *) __returns_twice;
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_PCB_H_ */
Property changes on: trunk/sys/arm/include/pcb.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/pcpu.h
===================================================================
--- trunk/sys/arm/include/pcpu.h (rev 0)
+++ trunk/sys/arm/include/pcpu.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,126 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999 Luoqi Chen <luoqi at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: src/sys/i386/include/globaldata.h,v 1.27 2001/04/27
+ * $FreeBSD: stable/10/sys/arm/include/pcpu.h 266277 2014-05-17 00:53:12Z ian $
+ */
+
+#ifndef _MACHINE_PCPU_H_
+#define _MACHINE_PCPU_H_
+
+#ifdef _KERNEL
+
+#include <machine/cpuconf.h>
+
+#define ALT_STACK_SIZE 128
+
+struct vmspace;
+
+#endif /* _KERNEL */
+
+#ifdef VFP
+#define PCPU_MD_FIELDS \
+ unsigned int pc_cpu; \
+ unsigned int pc_vfpsid; \
+ unsigned int pc_vfpmvfr0; \
+ unsigned int pc_vfpmvfr1; \
+ struct pmap *pc_curpmap; \
+ char __pad[137]
+#else
+#define PCPU_MD_FIELDS \
+ char __pad[157]
+#endif
+
+#ifdef _KERNEL
+
+struct pcb;
+struct pcpu;
+
+extern struct pcpu *pcpup;
+#if ARM_ARCH_6 || ARM_ARCH_7A
+/* or ARM_TP_ADDRESS mark REMOVE ME NOTE */
+
+#define CPU_MASK (0xf)
+
+#ifndef SMP
+#define get_pcpu() (pcpup)
+#else
+#define get_pcpu() __extension__ ({ \
+ int id; \
+ __asm __volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (id)); \
+ (pcpup + (id & CPU_MASK)); \
+ })
+#endif
+
+static inline struct thread *
+get_curthread(void)
+{
+ void *ret;
+
+ __asm __volatile("mrc p15, 0, %0, c13, c0, 4" : "=r" (ret));
+ return (ret);
+}
+
+static inline void
+set_curthread(struct thread *td)
+{
+
+ __asm __volatile("mcr p15, 0, %0, c13, c0, 4" : : "r" (td));
+}
+
+
+static inline void *
+get_tls(void)
+{
+ void *tls;
+
+ __asm __volatile("mrc p15, 0, %0, c13, c0, 3" : "=r" (tls));
+ return (tls);
+}
+
+static inline void
+set_tls(void *tls)
+{
+
+ __asm __volatile("mcr p15, 0, %0, c13, c0, 3" : : "r" (tls));
+}
+
+#define curthread get_curthread()
+
+#else
+#define get_pcpu() pcpup
+#endif
+
+#define PCPU_GET(member) (get_pcpu()->pc_ ## member)
+#define PCPU_ADD(member, value) (get_pcpu()->pc_ ## member += (value))
+#define PCPU_INC(member) PCPU_ADD(member, 1)
+#define PCPU_PTR(member) (&get_pcpu()->pc_ ## member)
+#define PCPU_SET(member,value) (get_pcpu()->pc_ ## member = (value))
+
+void pcpu0_init(void);
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_PCPU_H_ */
Property changes on: trunk/sys/arm/include/pcpu.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/physmem.h
===================================================================
--- trunk/sys/arm/include/physmem.h (rev 0)
+++ trunk/sys/arm/include/physmem.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,92 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/physmem.h 266201 2014-05-15 22:50:06Z ian $
+ */
+
+#ifndef _MACHINE_PHYSMEM_H_
+#define _MACHINE_PHYSMEM_H_
+
+/*
+ * The physical address at which the kernel was loaded.
+ */
+extern vm_paddr_t arm_physmem_kernaddr;
+
+/*
+ * Routines to help configure physical ram.
+ *
+ * Multiple regions of contiguous physical ram can be added (in any order).
+ *
+ * Multiple regions of physical ram that should be excluded from crash dumps, or
+ * memory allocation, or both, can be added (in any order).
+ *
+ * After all early kernel init is done and it's time to configure all
+ * remainining non-excluded physical ram for use by other parts of the kernel,
+ * arm_physmem_init_kernel_globals() processes the hardware regions and
+ * exclusion regions to generate the global dump_avail and phys_avail arrays
+ * that communicate physical ram configuration to other parts of the kernel.
+ */
+
+#define EXFLAG_NODUMP 0x01
+#define EXFLAG_NOALLOC 0x02
+
+void arm_physmem_hardware_region(vm_paddr_t pa, vm_size_t sz);
+void arm_physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t flags);
+void arm_physmem_init_kernel_globals(void);
+void arm_physmem_print_tables(void);
+
+/*
+ * Convenience routines for FDT.
+ */
+
+#ifdef FDT
+
+#include <machine/ofw_machdep.h>
+
+static inline void
+arm_physmem_hardware_regions(struct mem_region * mrptr, int mrcount)
+{
+ while (mrcount--) {
+ arm_physmem_hardware_region(mrptr->mr_start, mrptr->mr_size);
+ ++mrptr;
+ }
+}
+
+static inline void
+arm_physmem_exclude_regions(struct mem_region * mrptr, int mrcount,
+ uint32_t exflags)
+{
+ while (mrcount--) {
+ arm_physmem_exclude_region(mrptr->mr_start, mrptr->mr_size,
+ exflags);
+ ++mrptr;
+ }
+}
+
+#endif /* FDT */
+
+#endif
+
Property changes on: trunk/sys/arm/include/physmem.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/pl310.h
===================================================================
--- trunk/sys/arm/include/pl310.h (rev 0)
+++ trunk/sys/arm/include/pl310.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,189 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * $FreeBSD: stable/10/sys/arm/include/pl310.h 270075 2014-08-17 01:28:03Z ian $
+ */
+
+#ifndef PL310_H_
+#define PL310_H_
+
+/**
+ * PL310 - L2 Cache Controller register offsets.
+ *
+ */
+#define PL310_CACHE_ID 0x000
+#define CACHE_ID_RELEASE_SHIFT 0
+#define CACHE_ID_RELEASE_MASK 0x3f
+#define CACHE_ID_RELEASE_r0p0 0x00
+#define CACHE_ID_RELEASE_r1p0 0x02
+#define CACHE_ID_RELEASE_r2p0 0x04
+#define CACHE_ID_RELEASE_r3p0 0x05
+#define CACHE_ID_RELEASE_r3p1 0x06
+#define CACHE_ID_RELEASE_r3p2 0x08
+#define CACHE_ID_RELEASE_r3p3 0x09
+#define CACHE_ID_PARTNUM_SHIFT 6
+#define CACHE_ID_PARTNUM_MASK 0xf
+#define CACHE_ID_PARTNUM_VALUE 0x3
+#define PL310_CACHE_TYPE 0x004
+#define PL310_CTRL 0x100
+#define CTRL_ENABLED 0x01
+#define CTRL_DISABLED 0x00
+#define PL310_AUX_CTRL 0x104
+#define AUX_CTRL_MASK 0xc0000fff
+#define AUX_CTRL_ASSOCIATIVITY_SHIFT 16
+#define AUX_CTRL_WAY_SIZE_SHIFT 17
+#define AUX_CTRL_WAY_SIZE_MASK (0x7 << 17)
+#define AUX_CTRL_SHARE_OVERRIDE (1 << 22)
+#define AUX_CTRL_NS_LOCKDOWN (1 << 26)
+#define AUX_CTRL_NS_INT_CTRL (1 << 27)
+#define AUX_CTRL_DATA_PREFETCH (1 << 28)
+#define AUX_CTRL_INSTR_PREFETCH (1 << 29)
+#define AUX_CTRL_EARLY_BRESP (1 << 30)
+#define PL310_TAG_RAM_CTRL 0x108
+#define PL310_DATA_RAM_CTRL 0x10C
+#define RAM_CTRL_WRITE_SHIFT 8
+#define RAM_CTRL_WRITE_MASK (0x7 << 8)
+#define RAM_CTRL_READ_SHIFT 4
+#define RAM_CTRL_READ_MASK (0x7 << 4)
+#define RAM_CTRL_SETUP_SHIFT 0
+#define RAM_CTRL_SETUP_MASK (0x7 << 0)
+#define PL310_EVENT_COUNTER_CTRL 0x200
+#define EVENT_COUNTER_CTRL_ENABLED (1 << 0)
+#define EVENT_COUNTER_CTRL_C0_RESET (1 << 1)
+#define EVENT_COUNTER_CTRL_C1_RESET (1 << 2)
+#define PL310_EVENT_COUNTER1_CONF 0x204
+#define PL310_EVENT_COUNTER0_CONF 0x208
+#define EVENT_COUNTER_CONF_NOINTR 0
+#define EVENT_COUNTER_CONF_INCR 1
+#define EVENT_COUNTER_CONF_OVFW 2
+#define EVENT_COUNTER_CONF_NOEV (0 << 2)
+#define EVENT_COUNTER_CONF_CO (1 << 2)
+#define EVENT_COUNTER_CONF_DRHIT (2 << 2)
+#define EVENT_COUNTER_CONF_DRREQ (3 << 2)
+#define EVENT_COUNTER_CONF_DWHIT (4 << 2)
+#define EVENT_COUNTER_CONF_DWREQ (5 << 2)
+#define EVENT_COUNTER_CONF_DWTREQ (6 << 2)
+#define EVENT_COUNTER_CONF_DIRHIT (7 << 2)
+#define EVENT_COUNTER_CONF_DIRREQ (8 << 2)
+#define EVENT_COUNTER_CONF_WA (9 << 2)
+#define PL310_EVENT_COUNTER1_VAL 0x20C
+#define PL310_EVENT_COUNTER0_VAL 0x210
+#define PL310_INTR_MASK 0x214
+#define PL310_MASKED_INTR_STAT 0x218
+#define PL310_RAW_INTR_STAT 0x21C
+#define PL310_INTR_CLEAR 0x220
+#define INTR_MASK_ALL ((1 << 9) - 1)
+#define INTR_MASK_ECNTR (1 << 0)
+#define INTR_MASK_PARRT (1 << 1)
+#define INTR_MASK_PARRD (1 << 2)
+#define INTR_MASK_ERRWT (1 << 3)
+#define INTR_MASK_ERRWD (1 << 4)
+#define INTR_MASK_ERRRT (1 << 5)
+#define INTR_MASK_ERRRD (1 << 6)
+#define INTR_MASK_SLVERR (1 << 7)
+#define INTR_MASK_DECERR (1 << 8)
+#define PL310_CACHE_SYNC 0x730
+#define PL310_INV_LINE_PA 0x770
+#define PL310_INV_WAY 0x77C
+#define PL310_CLEAN_LINE_PA 0x7B0
+#define PL310_CLEAN_LINE_IDX 0x7B8
+#define PL310_CLEAN_WAY 0x7BC
+#define PL310_CLEAN_INV_LINE_PA 0x7F0
+#define PL310_CLEAN_INV_LINE_IDX 0x7F8
+#define PL310_CLEAN_INV_WAY 0x7FC
+#define PL310_LOCKDOWN_D_WAY(x) (0x900 + ((x) * 8))
+#define PL310_LOCKDOWN_I_WAY(x) (0x904 + ((x) * 8))
+#define PL310_LOCKDOWN_LINE_ENABLE 0x950
+#define PL310_UNLOCK_ALL_LINES_WAY 0x954
+#define PL310_ADDR_FILTER_STAR 0xC00
+#define PL310_ADDR_FILTER_END 0xC04
+#define PL310_DEBUG_CTRL 0xF40
+#define DEBUG_CTRL_DISABLE_LINEFILL (1 << 0)
+#define DEBUG_CTRL_DISABLE_WRITEBACK (1 << 1)
+#define DEBUG_CTRL_SPNIDEN (1 << 2)
+#define PL310_PREFETCH_CTRL 0xF60
+#define PREFETCH_CTRL_OFFSET_MASK (0x1f)
+#define PREFETCH_CTRL_NOTSAMEID (1 << 21)
+#define PREFETCH_CTRL_INCR_DL (1 << 23)
+#define PREFETCH_CTRL_PREFETCH_DROP (1 << 24)
+#define PREFETCH_CTRL_DL_ON_WRAP (1 << 27)
+#define PREFETCH_CTRL_DATA_PREFETCH (1 << 28)
+#define PREFETCH_CTRL_INSTR_PREFETCH (1 << 29)
+#define PREFETCH_CTRL_DL (1 << 30)
+#define PL310_POWER_CTRL 0xF60
+#define POWER_CTRL_ENABLE_GATING (1 << 0)
+#define POWER_CTRL_ENABLE_STANDBY (1 << 1)
+
+struct intr_config_hook;
+
+struct pl310_softc {
+ device_t sc_dev;
+ struct resource *sc_mem_res;
+ struct resource *sc_irq_res;
+ void* sc_irq_h;
+ int sc_enabled;
+ struct mtx sc_mtx;
+ u_int sc_rtl_revision;
+ struct intr_config_hook *sc_ich;
+};
+
+/**
+ * pl310_read4 - read a 32-bit value from the PL310 registers
+ * pl310_write4 - write a 32-bit value from the PL310 registers
+ * @off: byte offset within the register set to read from
+ * @val: the value to write into the register
+ *
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * nothing in case of write function, if read function returns the value read.
+ */
+static __inline uint32_t
+pl310_read4(struct pl310_softc *sc, bus_size_t off)
+{
+
+ return bus_read_4(sc->sc_mem_res, off);
+}
+
+static __inline void
+pl310_write4(struct pl310_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->sc_mem_res, off, val);
+}
+
+void pl310_print_config(struct pl310_softc *sc);
+void pl310_set_ram_latency(struct pl310_softc *sc, uint32_t which_reg,
+ uint32_t read, uint32_t write, uint32_t setup);
+
+void platform_pl310_init(struct pl310_softc *);
+void platform_pl310_write_ctrl(struct pl310_softc *, uint32_t);
+void platform_pl310_write_debug(struct pl310_softc *, uint32_t);
+
+#endif /* PL310_H_ */
Property changes on: trunk/sys/arm/include/pl310.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/pmap.h
===================================================================
--- trunk/sys/arm/include/pmap.h (rev 0)
+++ trunk/sys/arm/include/pmap.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,709 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and William Jolitz of UUNET Technologies Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Derived from hp300 version by Mike Hibler, this version by William
+ * Jolitz uses a recursive map [a pde points to the page directory] to
+ * map the page tables using the pagetables themselves. This is done to
+ * reduce the impact on kernel virtual memory for lots of sparse address
+ * space, and to reduce the cost of memory to each process.
+ *
+ * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90
+ * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91
+ * from: FreeBSD: src/sys/i386/include/pmap.h,v 1.70 2000/11/30
+ *
+ * $FreeBSD: stable/10/sys/arm/include/pmap.h 278614 2015-02-12 04:15:55Z ian $
+ */
+
+#ifndef _MACHINE_PMAP_H_
+#define _MACHINE_PMAP_H_
+
+#include <machine/pte.h>
+#include <machine/cpuconf.h>
+/*
+ * Pte related macros
+ */
+#if ARM_ARCH_6 || ARM_ARCH_7A
+#ifdef SMP
+#define PTE_NOCACHE 2
+#else
+#define PTE_NOCACHE 1
+#endif
+#define PTE_CACHE 6
+#define PTE_DEVICE 2
+#define PTE_PAGETABLE 6
+#else
+#define PTE_NOCACHE 1
+#define PTE_CACHE 2
+#define PTE_DEVICE PTE_NOCACHE
+#define PTE_PAGETABLE 3
+#endif
+
+enum mem_type {
+ STRONG_ORD = 0,
+ DEVICE_NOSHARE,
+ DEVICE_SHARE,
+ NRML_NOCACHE,
+ NRML_IWT_OWT,
+ NRML_IWB_OWB,
+ NRML_IWBA_OWBA
+};
+
+#ifndef LOCORE
+
+#include <sys/queue.h>
+#include <sys/_cpuset.h>
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+
+#define PDESIZE sizeof(pd_entry_t) /* for assembly files */
+#define PTESIZE sizeof(pt_entry_t) /* for assembly files */
+
+#ifdef _KERNEL
+
+#define vtophys(va) pmap_kextract((vm_offset_t)(va))
+
+#endif
+
+#define pmap_page_get_memattr(m) ((m)->md.pv_memattr)
+#define pmap_page_is_write_mapped(m) (((m)->aflags & PGA_WRITEABLE) != 0)
+#if (ARM_MMU_V6 + ARM_MMU_V7) > 0
+boolean_t pmap_page_is_mapped(vm_page_t);
+#else
+#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
+#endif
+void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma);
+
+/*
+ * Pmap stuff
+ */
+
+/*
+ * This structure is used to hold a virtual<->physical address
+ * association and is used mostly by bootstrap code
+ */
+struct pv_addr {
+ SLIST_ENTRY(pv_addr) pv_list;
+ vm_offset_t pv_va;
+ vm_paddr_t pv_pa;
+};
+
+struct pv_entry;
+struct pv_chunk;
+
+struct md_page {
+ int pvh_attrs;
+ vm_memattr_t pv_memattr;
+#if (ARM_MMU_V6 + ARM_MMU_V7) == 0
+ vm_offset_t pv_kva; /* first kernel VA mapping */
+#endif
+ TAILQ_HEAD(,pv_entry) pv_list;
+};
+
+struct l1_ttable;
+struct l2_dtable;
+
+
+/*
+ * The number of L2 descriptor tables which can be tracked by an l2_dtable.
+ * A bucket size of 16 provides for 16MB of contiguous virtual address
+ * space per l2_dtable. Most processes will, therefore, require only two or
+ * three of these to map their whole working set.
+ */
+#define L2_BUCKET_LOG2 4
+#define L2_BUCKET_SIZE (1 << L2_BUCKET_LOG2)
+/*
+ * Given the above "L2-descriptors-per-l2_dtable" constant, the number
+ * of l2_dtable structures required to track all possible page descriptors
+ * mappable by an L1 translation table is given by the following constants:
+ */
+#define L2_LOG2 ((32 - L1_S_SHIFT) - L2_BUCKET_LOG2)
+#define L2_SIZE (1 << L2_LOG2)
+
+struct pmap {
+ struct mtx pm_mtx;
+ u_int8_t pm_domain;
+ struct l1_ttable *pm_l1;
+ struct l2_dtable *pm_l2[L2_SIZE];
+ cpuset_t pm_active; /* active on cpus */
+ struct pmap_statistics pm_stats; /* pmap statictics */
+#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
+ TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */
+#else
+ TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */
+#endif
+};
+
+typedef struct pmap *pmap_t;
+
+#ifdef _KERNEL
+extern struct pmap kernel_pmap_store;
+#define kernel_pmap (&kernel_pmap_store)
+#define pmap_kernel() kernel_pmap
+
+#define PMAP_ASSERT_LOCKED(pmap) \
+ mtx_assert(&(pmap)->pm_mtx, MA_OWNED)
+#define PMAP_LOCK(pmap) mtx_lock(&(pmap)->pm_mtx)
+#define PMAP_LOCK_DESTROY(pmap) mtx_destroy(&(pmap)->pm_mtx)
+#define PMAP_LOCK_INIT(pmap) mtx_init(&(pmap)->pm_mtx, "pmap", \
+ NULL, MTX_DEF | MTX_DUPOK)
+#define PMAP_OWNED(pmap) mtx_owned(&(pmap)->pm_mtx)
+#define PMAP_MTX(pmap) (&(pmap)->pm_mtx)
+#define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx)
+#define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx)
+#endif
+
+
+/*
+ * For each vm_page_t, there is a list of all currently valid virtual
+ * mappings of that page. An entry is a pv_entry_t, the list is pv_list.
+ */
+typedef struct pv_entry {
+ vm_offset_t pv_va; /* virtual address for mapping */
+ TAILQ_ENTRY(pv_entry) pv_list;
+ int pv_flags; /* flags (wired, etc...) */
+#if (ARM_MMU_V6 + ARM_MMU_V7) == 0
+ pmap_t pv_pmap; /* pmap where mapping lies */
+ TAILQ_ENTRY(pv_entry) pv_plist;
+#endif
+} *pv_entry_t;
+
+/*
+ * pv_entries are allocated in chunks per-process. This avoids the
+ * need to track per-pmap assignments.
+ */
+#define _NPCM 8
+#define _NPCPV 252
+
+struct pv_chunk {
+ pmap_t pc_pmap;
+ TAILQ_ENTRY(pv_chunk) pc_list;
+ uint32_t pc_map[_NPCM]; /* bitmap; 1 = free */
+ uint32_t pc_dummy[3]; /* aligns pv_chunk to 4KB */
+ TAILQ_ENTRY(pv_chunk) pc_lru;
+ struct pv_entry pc_pventry[_NPCPV];
+};
+
+#ifdef _KERNEL
+
+boolean_t pmap_get_pde_pte(pmap_t, vm_offset_t, pd_entry_t **, pt_entry_t **);
+
+/*
+ * virtual address to page table entry and
+ * to physical address. Likewise for alternate address space.
+ * Note: these work recursively, thus vtopte of a pte will give
+ * the corresponding pde that in turn maps it.
+ */
+
+/*
+ * The current top of kernel VM.
+ */
+extern vm_offset_t pmap_curmaxkvaddr;
+
+struct pcb;
+
+void pmap_set_pcb_pagedir(pmap_t, struct pcb *);
+/* Virtual address to page table entry */
+static __inline pt_entry_t *
+vtopte(vm_offset_t va)
+{
+ pd_entry_t *pdep;
+ pt_entry_t *ptep;
+
+ if (pmap_get_pde_pte(pmap_kernel(), va, &pdep, &ptep) == FALSE)
+ return (NULL);
+ return (ptep);
+}
+
+extern vm_paddr_t phys_avail[];
+extern vm_offset_t virtual_avail;
+extern vm_offset_t virtual_end;
+
+void pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt);
+int pmap_change_attr(vm_offset_t, vm_size_t, int);
+void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
+void pmap_kenter_nocache(vm_offset_t va, vm_paddr_t pa);
+void pmap_kenter_device(vm_offset_t va, vm_paddr_t pa);
+void *pmap_kenter_temporary(vm_paddr_t pa, int i);
+void pmap_kenter_user(vm_offset_t va, vm_paddr_t pa);
+vm_paddr_t pmap_kextract(vm_offset_t va);
+void pmap_kremove(vm_offset_t);
+void *pmap_mapdev(vm_offset_t, vm_size_t);
+void pmap_unmapdev(vm_offset_t, vm_size_t);
+vm_page_t pmap_use_pt(pmap_t, vm_offset_t);
+void pmap_debug(int);
+#if (ARM_MMU_V6 + ARM_MMU_V7) == 0
+void pmap_map_section(vm_offset_t, vm_offset_t, vm_offset_t, int, int);
+#endif
+void pmap_link_l2pt(vm_offset_t, vm_offset_t, struct pv_addr *);
+vm_size_t pmap_map_chunk(vm_offset_t, vm_offset_t, vm_offset_t, vm_size_t, int, int);
+void
+pmap_map_entry(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, int prot,
+ int cache);
+int pmap_fault_fixup(pmap_t, vm_offset_t, vm_prot_t, int);
+int pmap_dmap_iscurrent(pmap_t pmap);
+
+/*
+ * Definitions for MMU domains
+ */
+#define PMAP_DOMAINS 15 /* 15 'user' domains (1-15) */
+#define PMAP_DOMAIN_KERNEL 0 /* The kernel uses domain #0 */
+
+/*
+ * The new pmap ensures that page-tables are always mapping Write-Thru.
+ * Thus, on some platforms we can run fast and loose and avoid syncing PTEs
+ * on every change.
+ *
+ * Unfortunately, not all CPUs have a write-through cache mode. So we
+ * define PMAP_NEEDS_PTE_SYNC for C code to conditionally do PTE syncs,
+ * and if there is the chance for PTE syncs to be needed, we define
+ * PMAP_INCLUDE_PTE_SYNC so e.g. assembly code can include (and run)
+ * the code.
+ */
+extern int pmap_needs_pte_sync;
+
+/*
+ * These macros define the various bit masks in the PTE.
+ *
+ * We use these macros since we use different bits on different processor
+ * models.
+ */
+
+#define L1_S_CACHE_MASK_generic (L1_S_B|L1_S_C)
+#define L1_S_CACHE_MASK_xscale (L1_S_B|L1_S_C|L1_S_XSCALE_TEX(TEX_XSCALE_X)|\
+ L1_S_XSCALE_TEX(TEX_XSCALE_T))
+
+#define L2_L_CACHE_MASK_generic (L2_B|L2_C)
+#define L2_L_CACHE_MASK_xscale (L2_B|L2_C|L2_XSCALE_L_TEX(TEX_XSCALE_X) | \
+ L2_XSCALE_L_TEX(TEX_XSCALE_T))
+
+#define L2_S_PROT_U_generic (L2_AP(AP_U))
+#define L2_S_PROT_W_generic (L2_AP(AP_W))
+#define L2_S_PROT_MASK_generic (L2_S_PROT_U|L2_S_PROT_W)
+
+#define L2_S_PROT_U_xscale (L2_AP0(AP_U))
+#define L2_S_PROT_W_xscale (L2_AP0(AP_W))
+#define L2_S_PROT_MASK_xscale (L2_S_PROT_U|L2_S_PROT_W)
+
+#define L2_S_CACHE_MASK_generic (L2_B|L2_C)
+#define L2_S_CACHE_MASK_xscale (L2_B|L2_C|L2_XSCALE_T_TEX(TEX_XSCALE_X)| \
+ L2_XSCALE_T_TEX(TEX_XSCALE_X))
+
+#define L1_S_PROTO_generic (L1_TYPE_S | L1_S_IMP)
+#define L1_S_PROTO_xscale (L1_TYPE_S)
+
+#define L1_C_PROTO_generic (L1_TYPE_C | L1_C_IMP2)
+#define L1_C_PROTO_xscale (L1_TYPE_C)
+
+#define L2_L_PROTO (L2_TYPE_L)
+
+#define L2_S_PROTO_generic (L2_TYPE_S)
+#define L2_S_PROTO_xscale (L2_TYPE_XSCALE_XS)
+
+/*
+ * User-visible names for the ones that vary with MMU class.
+ */
+#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
+#define L2_AP(x) (L2_AP0(x))
+#else
+#define L2_AP(x) (L2_AP0(x) | L2_AP1(x) | L2_AP2(x) | L2_AP3(x))
+#endif
+
+#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
+/*
+ * AP[2:1] access permissions model:
+ *
+ * AP[2](APX) - Write Disable
+ * AP[1] - User Enable
+ * AP[0] - Reference Flag
+ *
+ * AP[2] AP[1] Kernel User
+ * 0 0 R/W N
+ * 0 1 R/W R/W
+ * 1 0 R N
+ * 1 1 R R
+ *
+ */
+#define L2_S_PROT_R (0) /* kernel read */
+#define L2_S_PROT_U (L2_AP0(2)) /* user read */
+#define L2_S_REF (L2_AP0(1)) /* reference flag */
+
+#define L2_S_PROT_MASK (L2_S_PROT_U|L2_S_PROT_R|L2_APX)
+#define L2_S_EXECUTABLE(pte) (!(pte & L2_XN))
+#define L2_S_WRITABLE(pte) (!(pte & L2_APX))
+#define L2_S_REFERENCED(pte) (!!(pte & L2_S_REF))
+
+#ifndef SMP
+#define L1_S_CACHE_MASK (L1_S_TEX_MASK|L1_S_B|L1_S_C)
+#define L2_L_CACHE_MASK (L2_L_TEX_MASK|L2_B|L2_C)
+#define L2_S_CACHE_MASK (L2_S_TEX_MASK|L2_B|L2_C)
+#else
+#define L1_S_CACHE_MASK (L1_S_TEX_MASK|L1_S_B|L1_S_C|L1_SHARED)
+#define L2_L_CACHE_MASK (L2_L_TEX_MASK|L2_B|L2_C|L2_SHARED)
+#define L2_S_CACHE_MASK (L2_S_TEX_MASK|L2_B|L2_C|L2_SHARED)
+#endif /* SMP */
+
+#define L1_S_PROTO (L1_TYPE_S)
+#define L1_C_PROTO (L1_TYPE_C)
+#define L2_S_PROTO (L2_TYPE_S)
+
+/*
+ * Promotion to a 1MB (SECTION) mapping requires that the corresponding
+ * 4KB (SMALL) page mappings have identical settings for the following fields:
+ */
+#define L2_S_PROMOTE (L2_S_REF | L2_SHARED | L2_S_PROT_MASK | \
+ L2_XN | L2_S_PROTO)
+
+/*
+ * In order to compare 1MB (SECTION) entry settings with the 4KB (SMALL)
+ * page mapping it is necessary to read and shift appropriate bits from
+ * L1 entry to positions of the corresponding bits in the L2 entry.
+ */
+#define L1_S_DEMOTE(l1pd) ((((l1pd) & L1_S_PROTO) >> 0) | \
+ (((l1pd) & L1_SHARED) >> 6) | \
+ (((l1pd) & L1_S_REF) >> 6) | \
+ (((l1pd) & L1_S_PROT_MASK) >> 6) | \
+ (((l1pd) & L1_S_XN) >> 4))
+
+#ifndef SMP
+#define ARM_L1S_STRONG_ORD (0)
+#define ARM_L1S_DEVICE_NOSHARE (L1_S_TEX(2))
+#define ARM_L1S_DEVICE_SHARE (L1_S_B)
+#define ARM_L1S_NRML_NOCACHE (L1_S_TEX(1))
+#define ARM_L1S_NRML_IWT_OWT (L1_S_C)
+#define ARM_L1S_NRML_IWB_OWB (L1_S_C|L1_S_B)
+#define ARM_L1S_NRML_IWBA_OWBA (L1_S_TEX(1)|L1_S_C|L1_S_B)
+
+#define ARM_L2L_STRONG_ORD (0)
+#define ARM_L2L_DEVICE_NOSHARE (L2_L_TEX(2))
+#define ARM_L2L_DEVICE_SHARE (L2_B)
+#define ARM_L2L_NRML_NOCACHE (L2_L_TEX(1))
+#define ARM_L2L_NRML_IWT_OWT (L2_C)
+#define ARM_L2L_NRML_IWB_OWB (L2_C|L2_B)
+#define ARM_L2L_NRML_IWBA_OWBA (L2_L_TEX(1)|L2_C|L2_B)
+
+#define ARM_L2S_STRONG_ORD (0)
+#define ARM_L2S_DEVICE_NOSHARE (L2_S_TEX(2))
+#define ARM_L2S_DEVICE_SHARE (L2_B)
+#define ARM_L2S_NRML_NOCACHE (L2_S_TEX(1))
+#define ARM_L2S_NRML_IWT_OWT (L2_C)
+#define ARM_L2S_NRML_IWB_OWB (L2_C|L2_B)
+#define ARM_L2S_NRML_IWBA_OWBA (L2_S_TEX(1)|L2_C|L2_B)
+#else
+#define ARM_L1S_STRONG_ORD (0)
+#define ARM_L1S_DEVICE_NOSHARE (L1_S_TEX(2))
+#define ARM_L1S_DEVICE_SHARE (L1_S_B)
+#define ARM_L1S_NRML_NOCACHE (L1_S_TEX(1)|L1_SHARED)
+#define ARM_L1S_NRML_IWT_OWT (L1_S_C|L1_SHARED)
+#define ARM_L1S_NRML_IWB_OWB (L1_S_C|L1_S_B|L1_SHARED)
+#define ARM_L1S_NRML_IWBA_OWBA (L1_S_TEX(1)|L1_S_C|L1_S_B|L1_SHARED)
+
+#define ARM_L2L_STRONG_ORD (0)
+#define ARM_L2L_DEVICE_NOSHARE (L2_L_TEX(2))
+#define ARM_L2L_DEVICE_SHARE (L2_B)
+#define ARM_L2L_NRML_NOCACHE (L2_L_TEX(1)|L2_SHARED)
+#define ARM_L2L_NRML_IWT_OWT (L2_C|L2_SHARED)
+#define ARM_L2L_NRML_IWB_OWB (L2_C|L2_B|L2_SHARED)
+#define ARM_L2L_NRML_IWBA_OWBA (L2_L_TEX(1)|L2_C|L2_B|L2_SHARED)
+
+#define ARM_L2S_STRONG_ORD (0)
+#define ARM_L2S_DEVICE_NOSHARE (L2_S_TEX(2))
+#define ARM_L2S_DEVICE_SHARE (L2_B)
+#define ARM_L2S_NRML_NOCACHE (L2_S_TEX(1)|L2_SHARED)
+#define ARM_L2S_NRML_IWT_OWT (L2_C|L2_SHARED)
+#define ARM_L2S_NRML_IWB_OWB (L2_C|L2_B|L2_SHARED)
+#define ARM_L2S_NRML_IWBA_OWBA (L2_S_TEX(1)|L2_C|L2_B|L2_SHARED)
+#endif /* SMP */
+
+#elif ARM_NMMUS > 1
+/* More than one MMU class configured; use variables. */
+#define L2_S_PROT_U pte_l2_s_prot_u
+#define L2_S_PROT_W pte_l2_s_prot_w
+#define L2_S_PROT_MASK pte_l2_s_prot_mask
+
+#define L1_S_CACHE_MASK pte_l1_s_cache_mask
+#define L2_L_CACHE_MASK pte_l2_l_cache_mask
+#define L2_S_CACHE_MASK pte_l2_s_cache_mask
+
+#define L1_S_PROTO pte_l1_s_proto
+#define L1_C_PROTO pte_l1_c_proto
+#define L2_S_PROTO pte_l2_s_proto
+
+#elif ARM_MMU_GENERIC != 0
+#define L2_S_PROT_U L2_S_PROT_U_generic
+#define L2_S_PROT_W L2_S_PROT_W_generic
+#define L2_S_PROT_MASK L2_S_PROT_MASK_generic
+
+#define L1_S_CACHE_MASK L1_S_CACHE_MASK_generic
+#define L2_L_CACHE_MASK L2_L_CACHE_MASK_generic
+#define L2_S_CACHE_MASK L2_S_CACHE_MASK_generic
+
+#define L1_S_PROTO L1_S_PROTO_generic
+#define L1_C_PROTO L1_C_PROTO_generic
+#define L2_S_PROTO L2_S_PROTO_generic
+
+#elif ARM_MMU_XSCALE == 1
+#define L2_S_PROT_U L2_S_PROT_U_xscale
+#define L2_S_PROT_W L2_S_PROT_W_xscale
+#define L2_S_PROT_MASK L2_S_PROT_MASK_xscale
+
+#define L1_S_CACHE_MASK L1_S_CACHE_MASK_xscale
+#define L2_L_CACHE_MASK L2_L_CACHE_MASK_xscale
+#define L2_S_CACHE_MASK L2_S_CACHE_MASK_xscale
+
+#define L1_S_PROTO L1_S_PROTO_xscale
+#define L1_C_PROTO L1_C_PROTO_xscale
+#define L2_S_PROTO L2_S_PROTO_xscale
+
+#endif /* ARM_NMMUS > 1 */
+
+#if defined(CPU_XSCALE_81342) || ARM_ARCH_6 || ARM_ARCH_7A
+#define PMAP_NEEDS_PTE_SYNC 1
+#define PMAP_INCLUDE_PTE_SYNC
+#else
+#define PMAP_NEEDS_PTE_SYNC 0
+#endif
+
+/*
+ * These macros return various bits based on kernel/user and protection.
+ * Note that the compiler will usually fold these at compile time.
+ */
+#if (ARM_MMU_V6 + ARM_MMU_V7) == 0
+
+#define L1_S_PROT_U (L1_S_AP(AP_U))
+#define L1_S_PROT_W (L1_S_AP(AP_W))
+#define L1_S_PROT_MASK (L1_S_PROT_U|L1_S_PROT_W)
+#define L1_S_WRITABLE(pd) ((pd) & L1_S_PROT_W)
+
+#define L1_S_PROT(ku, pr) ((((ku) == PTE_USER) ? L1_S_PROT_U : 0) | \
+ (((pr) & VM_PROT_WRITE) ? L1_S_PROT_W : 0))
+
+#define L2_L_PROT_U (L2_AP(AP_U))
+#define L2_L_PROT_W (L2_AP(AP_W))
+#define L2_L_PROT_MASK (L2_L_PROT_U|L2_L_PROT_W)
+
+#define L2_L_PROT(ku, pr) ((((ku) == PTE_USER) ? L2_L_PROT_U : 0) | \
+ (((pr) & VM_PROT_WRITE) ? L2_L_PROT_W : 0))
+
+#define L2_S_PROT(ku, pr) ((((ku) == PTE_USER) ? L2_S_PROT_U : 0) | \
+ (((pr) & VM_PROT_WRITE) ? L2_S_PROT_W : 0))
+#else
+#define L1_S_PROT_U (L1_S_AP(AP_U))
+#define L1_S_PROT_W (L1_S_APX) /* Write disable */
+#define L1_S_PROT_MASK (L1_S_PROT_W|L1_S_PROT_U)
+#define L1_S_REF (L1_S_AP(AP_REF)) /* Reference flag */
+#define L1_S_WRITABLE(pd) (!((pd) & L1_S_PROT_W))
+#define L1_S_EXECUTABLE(pd) (!((pd) & L1_S_XN))
+#define L1_S_REFERENCED(pd) ((pd) & L1_S_REF)
+
+#define L1_S_PROT(ku, pr) (((((ku) == PTE_KERNEL) ? 0 : L1_S_PROT_U) | \
+ (((pr) & VM_PROT_WRITE) ? 0 : L1_S_PROT_W) | \
+ (((pr) & VM_PROT_EXECUTE) ? 0 : L1_S_XN)))
+
+#define L2_L_PROT_MASK (L2_APX|L2_AP0(0x3))
+#define L2_L_PROT(ku, pr) (L2_L_PROT_MASK & ~((((ku) == PTE_KERNEL) ? L2_S_PROT_U : 0) | \
+ (((pr) & VM_PROT_WRITE) ? L2_APX : 0)))
+
+#define L2_S_PROT(ku, pr) (L2_S_PROT_MASK & ~((((ku) == PTE_KERNEL) ? L2_S_PROT_U : 0) | \
+ (((pr) & VM_PROT_WRITE) ? L2_APX : 0)))
+
+#endif
+
+/*
+ * Macros to test if a mapping is mappable with an L1 Section mapping
+ * or an L2 Large Page mapping.
+ */
+#define L1_S_MAPPABLE_P(va, pa, size) \
+ ((((va) | (pa)) & L1_S_OFFSET) == 0 && (size) >= L1_S_SIZE)
+
+#define L2_L_MAPPABLE_P(va, pa, size) \
+ ((((va) | (pa)) & L2_L_OFFSET) == 0 && (size) >= L2_L_SIZE)
+
+/*
+ * Provide a fallback in case we were not able to determine it at
+ * compile-time.
+ */
+#ifndef PMAP_NEEDS_PTE_SYNC
+#define PMAP_NEEDS_PTE_SYNC pmap_needs_pte_sync
+#define PMAP_INCLUDE_PTE_SYNC
+#endif
+
+#ifdef ARM_L2_PIPT
+#define _sync_l2(pte, size) cpu_l2cache_wb_range(vtophys(pte), size)
+#else
+#define _sync_l2(pte, size) cpu_l2cache_wb_range(pte, size)
+#endif
+
+#define PTE_SYNC(pte) \
+do { \
+ if (PMAP_NEEDS_PTE_SYNC) { \
+ cpu_dcache_wb_range((vm_offset_t)(pte), sizeof(pt_entry_t));\
+ cpu_drain_writebuf(); \
+ _sync_l2((vm_offset_t)(pte), sizeof(pt_entry_t));\
+ } else \
+ cpu_drain_writebuf(); \
+} while (/*CONSTCOND*/0)
+
+#define PTE_SYNC_RANGE(pte, cnt) \
+do { \
+ if (PMAP_NEEDS_PTE_SYNC) { \
+ cpu_dcache_wb_range((vm_offset_t)(pte), \
+ (cnt) << 2); /* * sizeof(pt_entry_t) */ \
+ cpu_drain_writebuf(); \
+ _sync_l2((vm_offset_t)(pte), \
+ (cnt) << 2); /* * sizeof(pt_entry_t) */ \
+ } else \
+ cpu_drain_writebuf(); \
+} while (/*CONSTCOND*/0)
+
+extern pt_entry_t pte_l1_s_cache_mode;
+extern pt_entry_t pte_l1_s_cache_mask;
+
+extern pt_entry_t pte_l2_l_cache_mode;
+extern pt_entry_t pte_l2_l_cache_mask;
+
+extern pt_entry_t pte_l2_s_cache_mode;
+extern pt_entry_t pte_l2_s_cache_mask;
+
+extern pt_entry_t pte_l1_s_cache_mode_pt;
+extern pt_entry_t pte_l2_l_cache_mode_pt;
+extern pt_entry_t pte_l2_s_cache_mode_pt;
+
+extern pt_entry_t pte_l2_s_prot_u;
+extern pt_entry_t pte_l2_s_prot_w;
+extern pt_entry_t pte_l2_s_prot_mask;
+
+extern pt_entry_t pte_l1_s_proto;
+extern pt_entry_t pte_l1_c_proto;
+extern pt_entry_t pte_l2_s_proto;
+
+extern void (*pmap_copy_page_func)(vm_paddr_t, vm_paddr_t);
+extern void (*pmap_copy_page_offs_func)(vm_paddr_t a_phys,
+ vm_offset_t a_offs, vm_paddr_t b_phys, vm_offset_t b_offs, int cnt);
+extern void (*pmap_zero_page_func)(vm_paddr_t, int, int);
+
+#if (ARM_MMU_GENERIC + ARM_MMU_V6 + ARM_MMU_V7) != 0 || defined(CPU_XSCALE_81342)
+void pmap_copy_page_generic(vm_paddr_t, vm_paddr_t);
+void pmap_zero_page_generic(vm_paddr_t, int, int);
+
+void pmap_pte_init_generic(void);
+#if defined(CPU_ARM9)
+void pmap_pte_init_arm9(void);
+#endif /* CPU_ARM9 */
+#if defined(CPU_ARM10)
+void pmap_pte_init_arm10(void);
+#endif /* CPU_ARM10 */
+#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
+void pmap_pte_init_mmu_v6(void);
+#endif /* (ARM_MMU_V6 + ARM_MMU_V7) != 0 */
+#endif /* (ARM_MMU_GENERIC + ARM_MMU_V6 + ARM_MMU_V7) != 0 */
+
+#if ARM_MMU_XSCALE == 1
+void pmap_copy_page_xscale(vm_paddr_t, vm_paddr_t);
+void pmap_zero_page_xscale(vm_paddr_t, int, int);
+
+void pmap_pte_init_xscale(void);
+
+void xscale_setup_minidata(vm_offset_t, vm_offset_t, vm_offset_t);
+
+void pmap_use_minicache(vm_offset_t, vm_size_t);
+#endif /* ARM_MMU_XSCALE == 1 */
+#if defined(CPU_XSCALE_81342)
+#define ARM_HAVE_SUPERSECTIONS
+#endif
+
+#define PTE_KERNEL 0
+#define PTE_USER 1
+#define l1pte_valid(pde) ((pde) != 0)
+#define l1pte_section_p(pde) (((pde) & L1_TYPE_MASK) == L1_TYPE_S)
+#define l1pte_page_p(pde) (((pde) & L1_TYPE_MASK) == L1_TYPE_C)
+#define l1pte_fpage_p(pde) (((pde) & L1_TYPE_MASK) == L1_TYPE_F)
+
+#define l2pte_index(v) (((v) & L2_ADDR_BITS) >> L2_S_SHIFT)
+#define l2pte_valid(pte) ((pte) != 0)
+#define l2pte_pa(pte) ((pte) & L2_S_FRAME)
+#define l2pte_minidata(pte) (((pte) & \
+ (L2_B | L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X)))\
+ == (L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X)))
+
+/* L1 and L2 page table macros */
+#define pmap_pde_v(pde) l1pte_valid(*(pde))
+#define pmap_pde_section(pde) l1pte_section_p(*(pde))
+#define pmap_pde_page(pde) l1pte_page_p(*(pde))
+#define pmap_pde_fpage(pde) l1pte_fpage_p(*(pde))
+
+#define pmap_pte_v(pte) l2pte_valid(*(pte))
+#define pmap_pte_pa(pte) l2pte_pa(*(pte))
+
+/*
+ * Flags that indicate attributes of pages or mappings of pages.
+ *
+ * The PVF_MOD and PVF_REF flags are stored in the mdpage for each
+ * page. PVF_WIRED, PVF_WRITE, and PVF_NC are kept in individual
+ * pv_entry's for each page. They live in the same "namespace" so
+ * that we can clear multiple attributes at a time.
+ *
+ * Note the "non-cacheable" flag generally means the page has
+ * multiple mappings in a given address space.
+ */
+#define PVF_MOD 0x01 /* page is modified */
+#define PVF_REF 0x02 /* page is referenced */
+#define PVF_WIRED 0x04 /* mapping is wired */
+#define PVF_WRITE 0x08 /* mapping is writable */
+#define PVF_EXEC 0x10 /* mapping is executable */
+#define PVF_NC 0x20 /* mapping is non-cacheable */
+#define PVF_MWC 0x40 /* mapping is used multiple times in userland */
+#define PVF_UNMAN 0x80 /* mapping is unmanaged */
+
+void vector_page_setprot(int);
+
+#define SECTION_CACHE 0x1
+#define SECTION_PT 0x2
+void pmap_kenter_section(vm_offset_t, vm_paddr_t, int flags);
+#ifdef ARM_HAVE_SUPERSECTIONS
+void pmap_kenter_supersection(vm_offset_t, uint64_t, int flags);
+#endif
+
+extern char *_tmppt;
+
+void pmap_postinit(void);
+
+extern vm_paddr_t dump_avail[];
+#endif /* _KERNEL */
+
+#endif /* !LOCORE */
+
+#endif /* !_MACHINE_PMAP_H_ */
Property changes on: trunk/sys/arm/include/pmap.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/pmc_mdep.h
===================================================================
--- trunk/sys/arm/include/pmc_mdep.h (rev 0)
+++ trunk/sys/arm/include/pmc_mdep.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,79 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Rui Paulo <rpaulo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/pmc_mdep.h 236997 2012-06-13 06:38:25Z fabient $
+ */
+
+#ifndef _MACHINE_PMC_MDEP_H_
+#define _MACHINE_PMC_MDEP_H_
+
+#define PMC_MDEP_CLASS_INDEX_XSCALE 1
+/*
+ * On the ARM platform we support the following PMCs.
+ *
+ * XSCALE Intel XScale processors
+ */
+#include <dev/hwpmc/hwpmc_xscale.h>
+
+union pmc_md_op_pmcallocate {
+ uint64_t __pad[4];
+};
+
+/* Logging */
+#define PMCLOG_READADDR PMCLOG_READ32
+#define PMCLOG_EMITADDR PMCLOG_EMIT32
+
+#ifdef _KERNEL
+union pmc_md_pmc {
+ struct pmc_md_xscale_pmc pm_xscale;
+};
+
+#define PMC_IN_KERNEL_STACK(S,START,END) \
+ ((S) >= (START) && (S) < (END))
+#define PMC_IN_KERNEL(va) (((va) >= USRSTACK) && \
+ ((va) < VM_MAX_KERNEL_ADDRESS))
+
+#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
+
+#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_pc)
+#define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_r11)
+#define PMC_TRAPFRAME_TO_SVC_SP(TF) ((TF)->tf_svc_sp)
+#define PMC_TRAPFRAME_TO_USR_SP(TF) ((TF)->tf_usr_sp)
+
+/* Build a fake kernel trapframe from current instruction pointer. */
+#define PMC_FAKE_TRAPFRAME(TF) \
+ do { \
+ __asm __volatile("mov %0, pc" : "=r" ((TF)->tf_pc)); \
+ } while (0)
+
+/*
+ * Prototypes
+ */
+struct pmc_mdep *pmc_xscale_initialize(void);
+void pmc_xscale_finalize(struct pmc_mdep *_md);
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_PMC_MDEP_H_ */
Property changes on: trunk/sys/arm/include/pmc_mdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/proc.h
===================================================================
--- trunk/sys/arm/include/proc.h (rev 0)
+++ trunk/sys/arm/include/proc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,83 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)proc.h 7.1 (Berkeley) 5/15/91
+ * from: FreeBSD: src/sys/i386/include/proc.h,v 1.11 2001/06/29
+ * $FreeBSD: stable/10/sys/arm/include/proc.h 278656 2015-02-13 02:02:12Z ian $
+ */
+
+#ifndef _MACHINE_PROC_H_
+#define _MACHINE_PROC_H_
+
+#include <machine/utrap.h>
+
+struct md_utrap {
+ utrap_entry_t *ut_precise[UT_MAX]; /* must be first */
+ int ut_refcnt;
+};
+
+struct mdthread {
+ int md_spinlock_count; /* (k) */
+ register_t md_saved_cspr; /* (k) */
+ register_t md_spurflt_addr; /* (k) Spurious page fault address. */
+ int md_ptrace_instr;
+ int md_ptrace_addr;
+ register_t md_tp;
+ void *md_ras_start;
+ void *md_ras_end;
+};
+
+struct mdproc {
+ struct md_utrap *md_utrap;
+ void *md_sigtramp;
+};
+
+#ifdef __ARM_EABI__
+#define KINFO_PROC_SIZE 816
+#else
+#define KINFO_PROC_SIZE 792
+#endif
+
+#define MAXARGS 8
+struct syscall_args {
+ u_int code;
+ struct sysent *callp;
+ register_t args[MAXARGS];
+ int narg;
+ u_int nap;
+#ifndef __ARM_EABI__
+ u_int32_t insn;
+#endif
+};
+
+#endif /* !_MACHINE_PROC_H_ */
Property changes on: trunk/sys/arm/include/proc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/profile.h
===================================================================
--- trunk/sys/arm/include/profile.h (rev 0)
+++ trunk/sys/arm/include/profile.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,126 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)profile.h 8.1 (Berkeley) 6/11/93
+ * $FreeBSD: stable/10/sys/arm/include/profile.h 278652 2015-02-13 00:49:47Z ian $
+ */
+
+#ifndef _MACHINE_PROFILE_H_
+#define _MACHINE_PROFILE_H_
+
+/*
+ * Config generates something to tell the compiler to align functions on 32
+ * byte boundaries. A strict alignment is good for keeping the tables small.
+ */
+#define FUNCTION_ALIGNMENT 16
+
+
+#define _MCOUNT_DECL void mcount
+
+typedef u_long fptrdiff_t;
+
+/*
+ * Cannot implement mcount in C as GCC will trash the ip register when it
+ * pushes a trapframe. Pity we cannot insert assembly before the function
+ * prologue.
+ */
+
+#ifndef PLTSYM
+#define PLTSYM
+#endif
+
+#define MCOUNT \
+ __asm__(".text"); \
+ __asm__(".align 2"); \
+ __asm__(".type __mcount ,%function"); \
+ __asm__(".global __mcount"); \
+ __asm__("__mcount:"); \
+ /* \
+ * Preserve registers that are trashed during mcount \
+ */ \
+ __asm__("stmfd sp!, {r0-r3, ip, lr}"); \
+ /* \
+ * find the return address for mcount, \
+ * and the return address for mcount's caller. \
+ * \
+ * frompcindex = pc pushed by call into self. \
+ */ \
+ __asm__("mov r0, ip"); \
+ /* \
+ * selfpc = pc pushed by mcount call \
+ */ \
+ __asm__("mov r1, lr"); \
+ /* \
+ * Call the real mcount code \
+ */ \
+ __asm__("bl mcount"); \
+ /* \
+ * Restore registers that were trashed during mcount \
+ */ \
+ __asm__("ldmfd sp!, {r0-r3, lr, pc}");
+void bintr(void);
+void btrap(void);
+void eintr(void);
+void user(void);
+
+#define MCOUNT_FROMPC_USER(pc) \
+ ((pc < (uintfptr_t)VM_MAXUSER_ADDRESS) ? (uintfptr_t)user : pc)
+
+#define MCOUNT_FROMPC_INTR(pc) \
+ ((pc >= (uintfptr_t)btrap && pc < (uintfptr_t)eintr) ? \
+ ((pc >= (uintfptr_t)bintr) ? (uintfptr_t)bintr : \
+ (uintfptr_t)btrap) : ~0U)
+
+
+#ifdef _KERNEL
+
+#define MCOUNT_DECL(s) register_t s;
+
+#include <machine/asm.h>
+#include <machine/cpufunc.h>
+/*
+ * splhigh() and splx() are heavyweight, and call mcount(). Therefore
+ * we disabled interrupts (IRQ, but not FIQ) directly on the CPU.
+ *
+ * We're lucky that the CPSR and 's' both happen to be 'int's.
+ */
+#define MCOUNT_ENTER(s) {s = intr_disable(); } /* kill IRQ */
+#define MCOUNT_EXIT(s) {intr_restore(s); } /* restore old value */
+
+void mcount(uintfptr_t frompc, uintfptr_t selfpc);
+
+#else
+typedef u_int uintfptr_t;
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_PROFILE_H_ */
Property changes on: trunk/sys/arm/include/profile.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/psl.h
===================================================================
--- trunk/sys/arm/include/psl.h (rev 0)
+++ trunk/sys/arm/include/psl.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,83 @@
+/* $MidnightBSD$ */
+/* $NetBSD: psl.h,v 1.6 2003/06/16 20:00:58 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * psl.h
+ *
+ * spl prototypes.
+ * Eventually this will become a set of defines.
+ *
+ * Created : 21/07/95
+ *
+ * $FreeBSD: stable/10/sys/arm/include/psl.h 266084 2014-05-14 19:18:58Z ian $
+ */
+
+#ifndef _MACHINE_PSL_H_
+#define _MACHINE_PSL_H_
+
+/*
+ * These are the different SPL states
+ *
+ * Each state has an interrupt mask associated with it which
+ * indicate which interrupts are allowed.
+ */
+
+#define _SPL_0 0
+#define _SPL_SOFTCLOCK 1
+#define _SPL_SOFTNET 2
+#define _SPL_BIO 3
+#define _SPL_NET 4
+#define _SPL_SOFTSERIAL 5
+#define _SPL_TTY 6
+#define _SPL_VM 7
+#define _SPL_AUDIO 8
+#define _SPL_CLOCK 9
+#define _SPL_STATCLOCK 10
+#define _SPL_HIGH 11
+#define _SPL_SERIAL 12
+#define _SPL_LEVELS 13
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+extern int current_spl_level;
+
+extern u_int spl_masks[_SPL_LEVELS + 1];
+extern u_int spl_smasks[_SPL_LEVELS];
+#endif /* _LOCORE */
+#endif /* _KERNEL */
+
+#endif /* _ARM_PSL_H_ */
+/* End of psl.h */
Property changes on: trunk/sys/arm/include/psl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/pte.h
===================================================================
--- trunk/sys/arm/include/pte.h (rev 0)
+++ trunk/sys/arm/include/pte.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,357 @@
+/* $MidnightBSD$ */
+/* $NetBSD: pte.h,v 1.1 2001/11/23 17:39:04 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1994 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/pte.h 254918 2013-08-26 17:12:30Z raj $
+ */
+
+#ifndef _MACHINE_PTE_H_
+#define _MACHINE_PTE_H_
+
+#ifndef LOCORE
+typedef uint32_t pd_entry_t; /* page directory entry */
+typedef uint32_t pt_entry_t; /* page table entry */
+#endif
+
+#define PG_FRAME 0xfffff000
+
+/* The PT_SIZE definition is misleading... A page table is only 0x400
+ * bytes long. But since VM mapping can only be done to 0x1000 a single
+ * 1KB blocks cannot be steered to a va by itself. Therefore the
+ * pages tables are allocated in blocks of 4. i.e. if a 1 KB block
+ * was allocated for a PT then the other 3KB would also get mapped
+ * whenever the 1KB was mapped.
+ */
+
+#define PT_RSIZE 0x0400 /* Real page table size */
+#define PT_SIZE 0x1000
+#define PD_SIZE 0x4000
+
+/* Page table types and masks */
+#define L1_PAGE 0x01 /* L1 page table mapping */
+#define L1_SECTION 0x02 /* L1 section mapping */
+#define L1_FPAGE 0x03 /* L1 fine page mapping */
+#define L1_MASK 0x03 /* Mask for L1 entry type */
+#define L2_LPAGE 0x01 /* L2 large page (64KB) */
+#define L2_SPAGE 0x02 /* L2 small page (4KB) */
+#define L2_MASK 0x03 /* Mask for L2 entry type */
+#define L2_INVAL 0x00 /* L2 invalid type */
+
+/* L1 and L2 address masks */
+#define L1_ADDR_MASK 0xfffffc00
+#define L2_ADDR_MASK 0xfffff000
+
+/*
+ * The ARM MMU architecture was introduced with ARM v3 (previous ARM
+ * architecture versions used an optional off-CPU memory controller
+ * to perform address translation).
+ *
+ * The ARM MMU consists of a TLB and translation table walking logic.
+ * There is typically one TLB per memory interface (or, put another
+ * way, one TLB per software-visible cache).
+ *
+ * The ARM MMU is capable of mapping memory in the following chunks:
+ *
+ * 1M Sections (L1 table)
+ *
+ * 64K Large Pages (L2 table)
+ *
+ * 4K Small Pages (L2 table)
+ *
+ * 1K Tiny Pages (L2 table)
+ *
+ * There are two types of L2 tables: Coarse Tables and Fine Tables.
+ * Coarse Tables can map Large and Small Pages. Fine Tables can
+ * map Tiny Pages.
+ *
+ * Coarse Tables can define 4 Subpages within Large and Small pages.
+ * Subpages define different permissions for each Subpage within
+ * a Page.
+ *
+ * Coarse Tables are 1K in length. Fine tables are 4K in length.
+ *
+ * The Translation Table Base register holds the pointer to the
+ * L1 Table. The L1 Table is a 16K contiguous chunk of memory
+ * aligned to a 16K boundary. Each entry in the L1 Table maps
+ * 1M of virtual address space, either via a Section mapping or
+ * via an L2 Table.
+ *
+ * In addition, the Fast Context Switching Extension (FCSE) is available
+ * on some ARM v4 and ARM v5 processors. FCSE is a way of eliminating
+ * TLB/cache flushes on context switch by use of a smaller address space
+ * and a "process ID" that modifies the virtual address before being
+ * presented to the translation logic.
+ */
+
+/* ARMv6 super-sections. */
+#define L1_SUP_SIZE 0x01000000 /* 16M */
+#define L1_SUP_OFFSET (L1_SUP_SIZE - 1)
+#define L1_SUP_FRAME (~L1_SUP_OFFSET)
+#define L1_SUP_SHIFT 24
+
+#define L1_S_SIZE 0x00100000 /* 1M */
+#define L1_S_OFFSET (L1_S_SIZE - 1)
+#define L1_S_FRAME (~L1_S_OFFSET)
+#define L1_S_SHIFT 20
+
+#define L2_L_SIZE 0x00010000 /* 64K */
+#define L2_L_OFFSET (L2_L_SIZE - 1)
+#define L2_L_FRAME (~L2_L_OFFSET)
+#define L2_L_SHIFT 16
+
+#define L2_S_SIZE 0x00001000 /* 4K */
+#define L2_S_OFFSET (L2_S_SIZE - 1)
+#define L2_S_FRAME (~L2_S_OFFSET)
+#define L2_S_SHIFT 12
+
+#define L2_T_SIZE 0x00000400 /* 1K */
+#define L2_T_OFFSET (L2_T_SIZE - 1)
+#define L2_T_FRAME (~L2_T_OFFSET)
+#define L2_T_SHIFT 10
+
+/*
+ * The NetBSD VM implementation only works on whole pages (4K),
+ * whereas the ARM MMU's Coarse tables are sized in terms of 1K
+ * (16K L1 table, 1K L2 table).
+ *
+ * So, we allocate L2 tables 4 at a time, thus yielding a 4K L2
+ * table.
+ */
+#define L1_ADDR_BITS 0xfff00000 /* L1 PTE address bits */
+#define L2_ADDR_BITS 0x000ff000 /* L2 PTE address bits */
+
+#define L1_TABLE_SIZE 0x4000 /* 16K */
+#define L2_TABLE_SIZE 0x1000 /* 4K */
+/*
+ * The new pmap deals with the 1KB coarse L2 tables by
+ * allocating them from a pool. Until every port has been converted,
+ * keep the old L2_TABLE_SIZE define lying around. Converted ports
+ * should use L2_TABLE_SIZE_REAL until then.
+ */
+#define L2_TABLE_SIZE_REAL 0x400 /* 1K */
+
+/* Total number of page table entries in L2 table */
+#define L2_PTE_NUM_TOTAL (L2_TABLE_SIZE_REAL / sizeof(pt_entry_t))
+
+/*
+ * ARM L1 Descriptors
+ */
+
+#define L1_TYPE_INV 0x00 /* Invalid (fault) */
+#define L1_TYPE_C 0x01 /* Coarse L2 */
+#define L1_TYPE_S 0x02 /* Section */
+#define L1_TYPE_F 0x03 /* Fine L2 */
+#define L1_TYPE_MASK 0x03 /* mask of type bits */
+
+/* L1 Section Descriptor */
+#define L1_S_B 0x00000004 /* bufferable Section */
+#define L1_S_C 0x00000008 /* cacheable Section */
+#define L1_S_IMP 0x00000010 /* implementation defined */
+#define L1_S_XN (1 << 4) /* execute not */
+#define L1_S_DOM(x) ((x) << 5) /* domain */
+#define L1_S_DOM_MASK L1_S_DOM(0xf)
+#define L1_S_AP(x) ((x) << 10) /* access permissions */
+#define L1_S_ADDR_MASK 0xfff00000 /* phys address of section */
+#define L1_S_TEX(x) (((x) & 0x7) << 12) /* Type Extension */
+#define L1_S_TEX_MASK (0x7 << 12) /* Type Extension */
+#define L1_S_APX (1 << 15)
+#define L1_SHARED (1 << 16)
+
+#define L1_S_XSCALE_P 0x00000200 /* ECC enable for this section */
+#define L1_S_XSCALE_TEX(x) ((x) << 12) /* Type Extension */
+
+#define L1_S_SUPERSEC ((1) << 18) /* Section is a super-section. */
+
+/* L1 Coarse Descriptor */
+#define L1_C_IMP0 0x00000004 /* implementation defined */
+#define L1_C_IMP1 0x00000008 /* implementation defined */
+#define L1_C_IMP2 0x00000010 /* implementation defined */
+#define L1_C_DOM(x) ((x) << 5) /* domain */
+#define L1_C_DOM_MASK L1_C_DOM(0xf)
+#define L1_C_ADDR_MASK 0xfffffc00 /* phys address of L2 Table */
+
+#define L1_C_XSCALE_P 0x00000200 /* ECC enable for this section */
+
+/* L1 Fine Descriptor */
+#define L1_F_IMP0 0x00000004 /* implementation defined */
+#define L1_F_IMP1 0x00000008 /* implementation defined */
+#define L1_F_IMP2 0x00000010 /* implementation defined */
+#define L1_F_DOM(x) ((x) << 5) /* domain */
+#define L1_F_DOM_MASK L1_F_DOM(0xf)
+#define L1_F_ADDR_MASK 0xfffff000 /* phys address of L2 Table */
+
+#define L1_F_XSCALE_P 0x00000200 /* ECC enable for this section */
+
+/*
+ * ARM L2 Descriptors
+ */
+
+#define L2_TYPE_INV 0x00 /* Invalid (fault) */
+#define L2_TYPE_L 0x01 /* Large Page */
+#define L2_TYPE_S 0x02 /* Small Page */
+#define L2_TYPE_T 0x03 /* Tiny Page */
+#define L2_TYPE_MASK 0x03 /* mask of type bits */
+
+ /*
+ * This L2 Descriptor type is available on XScale processors
+ * when using a Coarse L1 Descriptor. The Extended Small
+ * Descriptor has the same format as the XScale Tiny Descriptor,
+ * but describes a 4K page, rather than a 1K page.
+ */
+#define L2_TYPE_XSCALE_XS 0x03 /* XScale Extended Small Page */
+
+#define L2_B 0x00000004 /* Bufferable page */
+#define L2_C 0x00000008 /* Cacheable page */
+#define L2_AP0(x) ((x) << 4) /* access permissions (sp 0) */
+#define L2_AP1(x) ((x) << 6) /* access permissions (sp 1) */
+#define L2_AP2(x) ((x) << 8) /* access permissions (sp 2) */
+#define L2_AP3(x) ((x) << 10) /* access permissions (sp 3) */
+
+#define L2_SHARED (1 << 10)
+#define L2_APX (1 << 9)
+#define L2_XN (1 << 0)
+#define L2_L_TEX_MASK (0x7 << 12) /* Type Extension */
+#define L2_L_TEX(x) (((x) & 0x7) << 12)
+#define L2_S_TEX_MASK (0x7 << 6) /* Type Extension */
+#define L2_S_TEX(x) (((x) & 0x7) << 6)
+
+#define L2_XSCALE_L_TEX(x) ((x) << 12) /* Type Extension */
+#define L2_XSCALE_L_S(x) (1 << 15) /* Shared */
+#define L2_XSCALE_T_TEX(x) ((x) << 6) /* Type Extension */
+
+/*
+ * Access Permissions for L1 and L2 Descriptors.
+ */
+#define AP_W 0x01 /* writable */
+#define AP_REF 0x01 /* referenced flag */
+#define AP_U 0x02 /* user */
+
+/*
+ * Short-hand for common AP_* constants.
+ *
+ * Note: These values assume the S (System) bit is set and
+ * the R (ROM) bit is clear in CP15 register 1.
+ */
+#define AP_KR 0x00 /* kernel read */
+#define AP_KRW 0x01 /* kernel read/write */
+#define AP_KRWUR 0x02 /* kernel read/write usr read */
+#define AP_KRWURW 0x03 /* kernel read/write usr read/write */
+
+/*
+ * Domain Types for the Domain Access Control Register.
+ */
+#define DOMAIN_FAULT 0x00 /* no access */
+#define DOMAIN_CLIENT 0x01 /* client */
+#define DOMAIN_RESERVED 0x02 /* reserved */
+#define DOMAIN_MANAGER 0x03 /* manager */
+
+/*
+ * Type Extension bits for XScale processors.
+ *
+ * Behavior of C and B when X == 0:
+ *
+ * C B Cacheable Bufferable Write Policy Line Allocate Policy
+ * 0 0 N N - -
+ * 0 1 N Y - -
+ * 1 0 Y Y Write-through Read Allocate
+ * 1 1 Y Y Write-back Read Allocate
+ *
+ * Behavior of C and B when X == 1:
+ * C B Cacheable Bufferable Write Policy Line Allocate Policy
+ * 0 0 - - - - DO NOT USE
+ * 0 1 N Y - -
+ * 1 0 Mini-Data - - -
+ * 1 1 Y Y Write-back R/W Allocate
+ */
+#define TEX_XSCALE_X 0x01 /* X modifies C and B */
+#define TEX_XSCALE_E 0x02
+#define TEX_XSCALE_T 0x04
+
+/* Xscale core 3 */
+
+/*
+ *
+ * Cache attributes with L2 present, S = 0
+ * T E X C B L1 i-cache L1 d-cache L1 DC WP L2 cacheable write coalesce
+ * 0 0 0 0 0 N N - N N
+ * 0 0 0 0 1 N N - N Y
+ * 0 0 0 1 0 Y Y WT N Y
+ * 0 0 0 1 1 Y Y WB Y Y
+ * 0 0 1 0 0 N N - Y Y
+ * 0 0 1 0 1 N N - N N
+ * 0 0 1 1 0 Y Y - - N
+ * 0 0 1 1 1 Y Y WT Y Y
+ * 0 1 0 0 0 N N - N N
+ * 0 1 0 0 1 N/A N/A N/A N/A N/A
+ * 0 1 0 1 0 N/A N/A N/A N/A N/A
+ * 0 1 0 1 1 N/A N/A N/A N/A N/A
+ * 0 1 1 X X N/A N/A N/A N/A N/A
+ * 1 X 0 0 0 N N - N Y
+ * 1 X 0 0 1 Y N WB N Y
+ * 1 X 0 1 0 Y N WT N Y
+ * 1 X 0 1 1 Y N WB Y Y
+ * 1 X 1 0 0 N N - Y Y
+ * 1 X 1 0 1 Y Y WB Y Y
+ * 1 X 1 1 0 Y Y WT Y Y
+ * 1 X 1 1 1 Y Y WB Y Y
+ *
+ *
+ *
+ *
+ * Cache attributes with L2 present, S = 1
+ * T E X C B L1 i-cache L1 d-cache L1 DC WP L2 cacheable write coalesce
+ * 0 0 0 0 0 N N - N N
+ * 0 0 0 0 1 N N - N Y
+ * 0 0 0 1 0 Y Y - N Y
+ * 0 0 0 1 1 Y Y WT Y Y
+ * 0 0 1 0 0 N N - Y Y
+ * 0 0 1 0 1 N N - N N
+ * 0 0 1 1 0 Y Y - - N
+ * 0 0 1 1 1 Y Y WT Y Y
+ * 0 1 0 0 0 N N - N N
+ * 0 1 0 0 1 N/A N/A N/A N/A N/A
+ * 0 1 0 1 0 N/A N/A N/A N/A N/A
+ * 0 1 0 1 1 N/A N/A N/A N/A N/A
+ * 0 1 1 X X N/A N/A N/A N/A N/A
+ * 1 X 0 0 0 N N - N Y
+ * 1 X 0 0 1 Y N - N Y
+ * 1 X 0 1 0 Y N - N Y
+ * 1 X 0 1 1 Y N - Y Y
+ * 1 X 1 0 0 N N - Y Y
+ * 1 X 1 0 1 Y Y WT Y Y
+ * 1 X 1 1 0 Y Y WT Y Y
+ * 1 X 1 1 1 Y Y WT Y Y
+ */
+#endif /* !_MACHINE_PTE_H_ */
+
+/* End of pte.h */
Property changes on: trunk/sys/arm/include/pte.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/ptrace.h
===================================================================
--- trunk/sys/arm/include/ptrace.h (rev 0)
+++ trunk/sys/arm/include/ptrace.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ptrace.h,v 1.2 2001/02/23 21:23:52 reinoud Exp $ */
+/* $FreeBSD: stable/10/sys/arm/include/ptrace.h 129198 2004-05-14 11:46:45Z cognet $ */
+
+#ifndef _MACHINE_PTRACE_H_
+#define _MACHINE_PTRACE_H_
+
+#endif /* !_MACHINE_PTRACE_H */
+
Property changes on: trunk/sys/arm/include/ptrace.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/reg.h
===================================================================
--- trunk/sys/arm/include/reg.h (rev 0)
+++ trunk/sys/arm/include/reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,35 @@
+/* $MidnightBSD$ */
+/* $NetBSD: reg.h,v 1.2 2001/02/23 21:23:52 reinoud Exp $ */
+/* $FreeBSD: stable/10/sys/arm/include/reg.h 137229 2004-11-04 19:20:54Z cognet $ */
+#ifndef MACHINE_REG_H
+#define MACHINE_REG_H
+
+#include <machine/fp.h>
+
+struct reg {
+ unsigned int r[13];
+ unsigned int r_sp;
+ unsigned int r_lr;
+ unsigned int r_pc;
+ unsigned int r_cpsr;
+};
+
+struct fpreg {
+ unsigned int fpr_fpsr;
+ fp_reg_t fpr[8];
+};
+
+struct dbreg {
+ unsigned int dr[8]; /* debug registers */
+};
+
+#ifdef _KERNEL
+int fill_regs(struct thread *, struct reg *);
+int set_regs(struct thread *, struct reg *);
+int fill_fpregs(struct thread *, struct fpreg *);
+int set_fpregs(struct thread *, struct fpreg *);
+int fill_dbregs(struct thread *, struct dbreg *);
+int set_dbregs(struct thread *, struct dbreg *);
+#endif
+
+#endif /* !MACHINE_REG_H */
Property changes on: trunk/sys/arm/include/reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/reloc.h
===================================================================
--- trunk/sys/arm/include/reloc.h (rev 0)
+++ trunk/sys/arm/include/reloc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,54 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)reloc.h 8.1 (Berkeley) 6/10/93
+ * $FreeBSD: stable/10/sys/arm/include/reloc.h 129198 2004-05-14 11:46:45Z cognet $
+ */
+
+#ifndef _MACHINE_RELOC_H_
+#define _MACHINE_RELOC_H_
+
+/* Relocation format. */
+struct relocation_info {
+ int r_address; /* offset in text or data segment */
+ unsigned int r_symbolnum : 24, /* ordinal number of add symbol */
+ r_pcrel : 1, /* 1 if value should be pc-relative */
+ r_length : 2, /* log base 2 of value's width */
+ r_extern : 1, /* 1 if need to add symbol to value */
+ r_baserel : 1, /* linkage table relative */
+ r_jmptable : 1, /* relocate to jump table */
+ r_relative : 1, /* load address relative */
+ r_copy : 1; /* run time copy */
+};
+
+#endif
Property changes on: trunk/sys/arm/include/reloc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/resource.h
===================================================================
--- trunk/sys/arm/include/resource.h (rev 0)
+++ trunk/sys/arm/include/resource.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,47 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 1998 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/resource.h 236992 2012-06-13 05:02:51Z imp $
+ */
+
+#ifndef _MACHINE_RESOURCE_H_
+#define _MACHINE_RESOURCE_H_ 1
+
+/*
+ * Definitions of resource types for Intel Architecture machines
+ * with support for legacy ISA devices and drivers.
+ */
+
+#define SYS_RES_IRQ 1 /* interrupt lines */
+#define SYS_RES_DRQ 2 /* isa dma lines */
+#define SYS_RES_MEMORY 3 /* i/o memory */
+#define SYS_RES_IOPORT 4 /* i/o ports */
+#define SYS_RES_GPIO 5 /* general purpose i/o */
+
+#endif /* !_MACHINE_RESOURCE_H_ */
Property changes on: trunk/sys/arm/include/resource.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/runq.h
===================================================================
--- trunk/sys/arm/include/runq.h (rev 0)
+++ trunk/sys/arm/include/runq.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,47 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 Jake Burkholder <jake at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/runq.h 139735 2005-01-05 21:58:49Z imp $
+ */
+
+#ifndef _MACHINE_RUNQ_H_
+#define _MACHINE_RUNQ_H_
+
+#define RQB_LEN (2) /* Number of priority status words. */
+#define RQB_L2BPW (5) /* Log2(sizeof(rqb_word_t) * NBBY)). */
+#define RQB_BPW (1<<RQB_L2BPW) /* Bits in an rqb_word_t. */
+
+#define RQB_BIT(pri) (1 << ((pri) & (RQB_BPW - 1)))
+#define RQB_WORD(pri) ((pri) >> RQB_L2BPW)
+
+#define RQB_FFS(word) (ffs(word) - 1)
+
+/*
+ * Type of run queue status word.
+ */
+typedef u_int32_t rqb_word_t;
+
+#endif
Property changes on: trunk/sys/arm/include/runq.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/sc_machdep.h
===================================================================
--- trunk/sys/arm/include/sc_machdep.h (rev 0)
+++ trunk/sys/arm/include/sc_machdep.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,72 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/sc_machdep.h 239696 2012-08-25 23:59:31Z gonzo $
+ */
+
+#ifndef _MACHINE_SC_MACHDEP_H_
+#define _MACHINE_SC_MACHDEP_H_
+
+/* Color attributes for foreground text */
+
+#define FG_BLACK 0x0
+#define FG_BLUE 0x1
+#define FG_GREEN 0x2
+#define FG_CYAN 0x3
+#define FG_RED 0x4
+#define FG_MAGENTA 0x5
+#define FG_BROWN 0x6
+#define FG_LIGHTGREY 0x7 /* aka white */
+#define FG_DARKGREY 0x8
+#define FG_LIGHTBLUE 0x9
+#define FG_LIGHTGREEN 0xa
+#define FG_LIGHTCYAN 0xb
+#define FG_LIGHTRED 0xc
+#define FG_LIGHTMAGENTA 0xd
+#define FG_YELLOW 0xe
+#define FG_WHITE 0xf /* aka bright white */
+#define FG_BLINK 0x80
+
+/* Color attributes for text background */
+
+#define BG_BLACK 0x00
+#define BG_BLUE 0x10
+#define BG_GREEN 0x20
+#define BG_CYAN 0x30
+#define BG_RED 0x40
+#define BG_MAGENTA 0x50
+#define BG_BROWN 0x60
+#define BG_LIGHTGREY 0x70
+#define BG_DARKGREY 0x80
+#define BG_LIGHTBLUE 0x90
+#define BG_LIGHTGREEN 0xa0
+#define BG_LIGHTCYAN 0xb0
+#define BG_LIGHTRED 0xc0
+#define BG_LIGHTMAGENTA 0xd0
+#define BG_YELLOW 0xe0
+#define BG_WHITE 0xf0
+
+#endif /* !_MACHINE_SC_MACHDEP_H_ */
Property changes on: trunk/sys/arm/include/sc_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/setjmp.h
===================================================================
--- trunk/sys/arm/include/setjmp.h (rev 0)
+++ trunk/sys/arm/include/setjmp.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,108 @@
+/* $MidnightBSD$ */
+/* $NetBSD: setjmp.h,v 1.5 2013/01/11 13:56:32 matt Exp $ */
+/* $FreeBSD: stable/10/sys/arm/include/setjmp.h 251517 2013-06-08 07:16:22Z andrew $ */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ */
+
+#ifndef _MACHINE_SETJMP_H_
+#define _MACHINE_SETJMP_H_
+
+#define _JBLEN 64 /* size, in longs, of a jmp_buf */
+
+/*
+ * NOTE: The internal structure of a jmp_buf is *PRIVATE*
+ * This information is provided as there is software
+ * that fiddles with this with obtain the stack pointer
+ * (yes really ! and its commercial !).
+ *
+ * Description of the setjmp buffer
+ *
+ * word 0 magic number (dependent on creator)
+ * 13 fpscr vfp status control register
+ * 14 r4 register 4
+ * 15 r5 register 5
+ * 16 r6 register 6
+ * 17 r7 register 7
+ * 18 r8 register 8
+ * 19 r9 register 9
+ * 20 r10 register 10 (sl)
+ * 21 r11 register 11 (fp)
+ * 22 r12 register 12 (ip)
+ * 23 r13 register 13 (sp)
+ * 24 r14 register 14 (lr)
+ * 25 signal mask (dependent on magic)
+ * 26 (con't)
+ * 27 (con't)
+ * 28 (con't)
+ * 32-33 d8 (vfp register d8)
+ * 34-35 d9 (vfp register d9)
+ * 36-37 d10 (vfp register d10)
+ * 38-39 d11 (vfp register d11)
+ * 40-41 d12 (vfp register d12)
+ * 42-43 d13 (vfp register d13)
+ * 44-45 d14 (vfp register d14)
+ * 46-47 d15 (vfp register d15)
+ *
+ * The magic number number identifies the jmp_buf and
+ * how the buffer was created as well as providing
+ * a sanity check
+ *
+ * A side note I should mention - Please do not tamper
+ * with the floating point fields. While they are
+ * always saved and restored at the moment this cannot
+ * be garenteed especially if the compiler happens
+ * to be generating soft-float code so no fp
+ * registers will be used.
+ *
+ * Whilst this can be seen an encouraging people to
+ * use the setjmp buffer in this way I think that it
+ * is for the best then if changes occur compiles will
+ * break rather than just having new builds falling over
+ * mysteriously.
+ */
+
+#define _JB_MAGIC__SETJMP 0x4278f500
+#define _JB_MAGIC_SETJMP 0x4278f501
+#define _JB_MAGIC__SETJMP_VFP 0x4278f502
+#define _JB_MAGIC_SETJMP_VFP 0x4278f503
+
+/* Valid for all jmp_buf's */
+
+#define _JB_MAGIC 0
+#define _JB_REG_FPSCR 13
+#define _JB_REG_R4 14
+#define _JB_REG_R5 15
+#define _JB_REG_R6 16
+#define _JB_REG_R7 17
+#define _JB_REG_R8 18
+#define _JB_REG_R9 19
+#define _JB_REG_R10 20
+#define _JB_REG_R11 21
+#define _JB_REG_R12 22
+#define _JB_REG_R13 23
+#define _JB_REG_R14 24
+
+/* Only valid with the _JB_MAGIC_SETJMP magic */
+
+#define _JB_SIGMASK 25
+
+#define _JB_REG_D8 32
+#define _JB_REG_D9 34
+#define _JB_REG_D10 36
+#define _JB_REG_D11 38
+#define _JB_REG_D12 40
+#define _JB_REG_D13 42
+#define _JB_REG_D14 44
+#define _JB_REG_D15 46
+
+#ifndef __ASSEMBLER__
+#if __BSD_VISIBLE || __POSIX_VISIBLE || __XSI_VISIBLE
+typedef struct _sigjmp_buf { int _sjb[_JBLEN + 1]; } sigjmp_buf[1];
+#endif
+
+typedef struct _jmp_buf { int _jb[_JBLEN + 1]; } jmp_buf[1];
+#endif
+
+#endif /* !_MACHINE_SETJMP_H_ */
Property changes on: trunk/sys/arm/include/setjmp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/sf_buf.h
===================================================================
--- trunk/sys/arm/include/sf_buf.h (rev 0)
+++ trunk/sys/arm/include/sf_buf.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,62 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Alan L. Cox <alc at cs.rice.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/sf_buf.h 266175 2014-05-15 19:09:31Z ian $
+ */
+
+#ifndef _MACHINE_SF_BUF_H_
+#define _MACHINE_SF_BUF_H_
+
+#include <sys/queue.h>
+
+struct vm_page;
+
+struct sf_buf {
+ LIST_ENTRY(sf_buf) list_entry; /* list of buffers */
+ TAILQ_ENTRY(sf_buf) free_entry; /* list of buffers */
+ struct vm_page *m; /* currently mapped page */
+ vm_offset_t kva; /* va of mapping */
+ int ref_count; /* usage of this mapping */
+};
+
+static __inline vm_offset_t
+sf_buf_kva(struct sf_buf *sf)
+{
+
+ return (sf->kva);
+}
+
+static __inline struct vm_page *
+sf_buf_page(struct sf_buf *sf)
+{
+
+ return (sf->m);
+}
+
+struct sf_buf * sf_buf_alloc(struct vm_page *m, int flags);
+void sf_buf_free(struct sf_buf *sf);
+
+#endif /* !_MACHINE_SF_BUF_H_ */
Property changes on: trunk/sys/arm/include/sf_buf.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/sigframe.h
===================================================================
--- trunk/sys/arm/include/sigframe.h (rev 0)
+++ trunk/sys/arm/include/sigframe.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,3 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/arm/include/sigframe.h 129198 2004-05-14 11:46:45Z cognet $ */
+#include <machine/frame.h>
Property changes on: trunk/sys/arm/include/sigframe.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/signal.h
===================================================================
--- trunk/sys/arm/include/signal.h (rev 0)
+++ trunk/sys/arm/include/signal.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,51 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1986, 1989, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)signal.h 8.1 (Berkeley) 6/11/93
+ * from: FreeBSD: src/sys/i386/include/signal.h,v 1.13 2000/11/09
+ * from: FreeBSD: src/sys/sparc64/include/signal.h,v 1.6 2001/09/30 18:52:17
+ * $FreeBSD: stable/10/sys/arm/include/signal.h 248153 2013-03-11 10:56:46Z cognet $
+ */
+
+#ifndef _MACHINE_SIGNAL_H_
+#define _MACHINE_SIGNAL_H_
+
+#include <sys/cdefs.h>
+
+typedef long sig_atomic_t;
+
+#if __BSD_VISIBLE
+
+struct sigcontext {
+ int _dummy;
+};
+
+#endif
+
+#endif /* !_MACHINE_SIGNAL_H_ */
Property changes on: trunk/sys/arm/include/signal.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/smp.h
===================================================================
--- trunk/sys/arm/include/smp.h (rev 0)
+++ trunk/sys/arm/include/smp.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,41 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/arm/include/smp.h 266374 2014-05-17 23:03:04Z ian $ */
+
+#ifndef _MACHINE_SMP_H_
+#define _MACHINE_SMP_H_
+
+#include <sys/_cpuset.h>
+#include <machine/pcb.h>
+
+#define IPI_AST 0
+#define IPI_PREEMPT 2
+#define IPI_RENDEZVOUS 3
+#define IPI_STOP 4
+#define IPI_STOP_HARD 4
+#define IPI_HARDCLOCK 6
+#define IPI_TLB 7
+
+void init_secondary(int cpu);
+void mpentry(void);
+
+void ipi_all_but_self(u_int ipi);
+void ipi_cpu(int cpu, u_int ipi);
+void ipi_selected(cpuset_t cpus, u_int ipi);
+
+/* PIC interface */
+void pic_ipi_send(cpuset_t cpus, u_int ipi);
+void pic_ipi_clear(int ipi);
+int pic_ipi_get(int arg);
+
+/* Platform interface */
+void platform_mp_setmaxid(void);
+int platform_mp_probe(void);
+void platform_mp_start_ap(void);
+void platform_mp_init_secondary(void);
+
+void platform_ipi_send(cpuset_t cpus, u_int ipi);
+
+/* global data in mp_machdep.c */
+extern struct pcb stoppcbs[];
+
+#endif /* !_MACHINE_SMP_H_ */
Property changes on: trunk/sys/arm/include/smp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/stack.h
===================================================================
--- trunk/sys/arm/include/stack.h (rev 0)
+++ trunk/sys/arm/include/stack.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,43 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2000, 2001 Ben Harris
+ * Copyright (c) 1996 Scott K. Stevens
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/stack.h 236992 2012-06-13 05:02:51Z imp $
+ */
+
+#ifndef _MACHINE_STACK_H_
+#define _MACHINE_STACK_H_
+
+#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
+
+#define FR_SCP (0)
+#define FR_RLV (-1)
+#define FR_RSP (-2)
+#define FR_RFP (-3)
+
+#endif /* !_MACHINE_STACK_H_ */
Property changes on: trunk/sys/arm/include/stack.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/stdarg.h
===================================================================
--- trunk/sys/arm/include/stdarg.h (rev 0)
+++ trunk/sys/arm/include/stdarg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,82 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2002 David E. O'Brien. All rights reserved.
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)stdarg.h 8.1 (Berkeley) 6/10/93
+ * $FreeBSD: stable/10/sys/arm/include/stdarg.h 162487 2006-09-21 01:37:02Z kan $
+ */
+
+#ifndef _MACHINE_STDARG_H_
+#define _MACHINE_STDARG_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#ifndef _VA_LIST_DECLARED
+#define _VA_LIST_DECLARED
+typedef __va_list va_list;
+#endif
+
+#ifdef __GNUCLIKE_BUILTIN_STDARG
+
+#define va_start(ap, last) \
+ __builtin_va_start((ap), (last))
+
+#define va_arg(ap, type) \
+ __builtin_va_arg((ap), type)
+
+#if __ISO_C_VISIBLE >= 1999
+#define va_copy(dest, src) \
+ __builtin_va_copy((dest), (src))
+#endif
+
+#define va_end(ap) \
+ __builtin_va_end(ap)
+
+#else /* !__GNUCLIKE_BUILTIN_STDARG */
+
+#define __va_size(type) \
+ (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+#ifdef __GNUCLIKE_BUILTIN_NEXT_ARG
+#define va_start(ap, last) \
+ ((ap) = (va_list)__builtin_next_arg(last))
+#else /* !__GNUCLIKE_BUILTIN_NEXT_ARG */
+#define va_start(ap, last) \
+ ((ap) = (va_list)&(last) + __va_size(last))
+#endif /* __GNUCLIKE_BUILTIN_NEXT_ARG */
+
+#define va_arg(ap, type) \
+ (*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
+
+#define va_end(ap)
+
+#endif /* __GNUCLIKE_BUILTIN_STDARG */
+
+#endif /* !_MACHINE_STDARG_H_ */
Property changes on: trunk/sys/arm/include/stdarg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/swi.h
===================================================================
--- trunk/sys/arm/include/swi.h (rev 0)
+++ trunk/sys/arm/include/swi.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,24 @@
+/* $MidnightBSD$ */
+/* $NetBSD: swi.h,v 1.1 2002/01/13 15:03:06 bjh21 Exp $ */
+/* $FreeBSD: stable/10/sys/arm/include/swi.h 139735 2005-01-05 21:58:49Z imp $ */
+
+/*-
+ * This file is in the Public Domain.
+ * Ben Harris, 2002.
+ */
+
+#ifndef _MACHINE_SWI_H_
+#define _MACHINE_SWI_H_
+
+#define SWI_OS_MASK 0xf00000
+#define SWI_OS_RISCOS 0x000000
+#define SWI_OS_RISCIX 0x800000
+#define SWI_OS_LINUX 0x900000
+#define SWI_OS_NETBSD 0xa00000
+#define SWI_OS_ARM 0xf00000
+
+#define SWI_IMB 0xf00000
+#define SWI_IMBrange 0xf00001
+
+#endif /* !_MACHINE_SWI_H_ */
+
Property changes on: trunk/sys/arm/include/swi.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/sysarch.h
===================================================================
--- trunk/sys/arm/include/sysarch.h (rev 0)
+++ trunk/sys/arm/include/sysarch.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,102 @@
+/* $MidnightBSD$ */
+/* $NetBSD: sysarch.h,v 1.5 2003/09/11 09:40:12 kleink Exp $ */
+
+/*-
+ * Copyright (c) 1996-1997 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/include/sysarch.h 266311 2014-05-17 13:53:38Z ian $ */
+
+#ifndef _ARM_SYSARCH_H_
+#define _ARM_SYSARCH_H_
+
+#include <machine/armreg.h>
+/*
+ * The ARM_TP_ADDRESS points to a special purpose page, which is used as local
+ * store for the ARM per-thread data and Restartable Atomic Sequences support.
+ * Put it just above the "high" vectors' page.
+ * The cpu_switch() code assumes ARM_RAS_START is ARM_TP_ADDRESS + 4, and
+ * ARM_RAS_END is ARM_TP_ADDRESS + 8, so if that ever changes, be sure to
+ * update the cpu_switch() (and cpu_throw()) code as well.
+ * In addition, code in arm/include/atomic.h and arm/arm/exception.S
+ * assumes that ARM_RAS_END is at ARM_RAS_START+4, so be sure to update those
+ * if ARM_RAS_END moves in relation to ARM_RAS_START (look for occurrences
+ * of ldr/str rm,[rn, #4]).
+ */
+
+/* ARM_TP_ADDRESS is needed for processors that don't support
+ * the exclusive-access opcodes introduced with ARMv6K. */
+/* TODO: #if !defined(_HAVE_ARMv6K_INSTRUCTIONS) */
+#if !defined (__ARM_ARCH_7__) && \
+ !defined (__ARM_ARCH_7A__) && \
+ !defined (__ARM_ARCH_6K__) && \
+ !defined (__ARM_ARCH_6ZK__)
+#define ARM_TP_ADDRESS (ARM_VECTORS_HIGH + 0x1000)
+#define ARM_RAS_START (ARM_TP_ADDRESS + 4)
+#define ARM_RAS_END (ARM_TP_ADDRESS + 8)
+#endif
+
+#ifndef LOCORE
+#ifndef __ASSEMBLER__
+
+#include <sys/cdefs.h>
+
+/*
+ * Pickup definition of uintptr_t
+ */
+#include <sys/stdint.h>
+
+/*
+ * Architecture specific syscalls (arm)
+ */
+
+#define ARM_SYNC_ICACHE 0
+#define ARM_DRAIN_WRITEBUF 1
+#define ARM_SET_TP 2
+#define ARM_GET_TP 3
+
+struct arm_sync_icache_args {
+ uintptr_t addr; /* Virtual start address */
+ size_t len; /* Region size */
+};
+
+#ifndef _KERNEL
+__BEGIN_DECLS
+int arm_sync_icache (u_int addr, int len);
+int arm_drain_writebuf (void);
+int sysarch(int, void *);
+__END_DECLS
+#endif
+
+#endif /* __ASSEMBLER__ */
+#endif /* LOCORE */
+
+#endif /* !_ARM_SYSARCH_H_ */
Property changes on: trunk/sys/arm/include/sysarch.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/sysreg.h
===================================================================
--- trunk/sys/arm/include/sysreg.h (rev 0)
+++ trunk/sys/arm/include/sysreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,265 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Svatopluk Kraus <onwahe at gmail.com>
+ * Copyright 2014 Michal Meloun <meloun at miracle.cz>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/sysreg.h 278684 2015-02-13 17:53:11Z ian $
+ */
+
+/*
+ * Macros to make working with the System Control Registers simpler.
+ *
+ * Note that when register r0 is hard-coded in these definitions it means the
+ * cp15 operation neither reads nor writes the register, and r0 is used only
+ * because some syntatically-valid register name has to appear at that point to
+ * keep the asm parser happy.
+ */
+
+#ifndef MACHINE_SYSREG_H
+#define MACHINE_SYSREG_H
+
+#include <machine/acle-compat.h>
+
+/*
+ * CP15 C0 registers
+ */
+#define CP15_MIDR(rr) p15, 0, rr, c0, c0, 0 /* Main ID Register */
+#define CP15_CTR(rr) p15, 0, rr, c0, c0, 1 /* Cache Type Register */
+#define CP15_TCMTR(rr) p15, 0, rr, c0, c0, 2 /* TCM Type Register */
+#define CP15_TLBTR(rr) p15, 0, rr, c0, c0, 3 /* TLB Type Register */
+#define CP15_MPIDR(rr) p15, 0, rr, c0, c0, 5 /* Multiprocessor Affinity Register */
+#define CP15_REVIDR(rr) p15, 0, rr, c0, c0, 6 /* Revision ID Register */
+
+#define CP15_ID_PFR0(rr) p15, 0, rr, c0, c1, 0 /* Processor Feature Register 0 */
+#define CP15_ID_PFR1(rr) p15, 0, rr, c0, c1, 1 /* Processor Feature Register 1 */
+#define CP15_ID_DFR0(rr) p15, 0, rr, c0, c1, 2 /* Debug Feature Register 0 */
+#define CP15_ID_AFR0(rr) p15, 0, rr, c0, c1, 3 /* Auxiliary Feature Register 0 */
+#define CP15_ID_MMFR0(rr) p15, 0, rr, c0, c1, 4 /* Memory Model Feature Register 0 */
+#define CP15_ID_MMFR1(rr) p15, 0, rr, c0, c1, 5 /* Memory Model Feature Register 1 */
+#define CP15_ID_MMFR2(rr) p15, 0, rr, c0, c1, 6 /* Memory Model Feature Register 2 */
+#define CP15_ID_MMFR3(rr) p15, 0, rr, c0, c1, 7 /* Memory Model Feature Register 3 */
+
+#define CP15_ID_ISAR0(rr) p15, 0, rr, c0, c2, 0 /* Instruction Set Attribute Register 0 */
+#define CP15_ID_ISAR1(rr) p15, 0, rr, c0, c2, 1 /* Instruction Set Attribute Register 1 */
+#define CP15_ID_ISAR2(rr) p15, 0, rr, c0, c2, 2 /* Instruction Set Attribute Register 2 */
+#define CP15_ID_ISAR3(rr) p15, 0, rr, c0, c2, 3 /* Instruction Set Attribute Register 3 */
+#define CP15_ID_ISAR4(rr) p15, 0, rr, c0, c2, 4 /* Instruction Set Attribute Register 4 */
+#define CP15_ID_ISAR5(rr) p15, 0, rr, c0, c2, 5 /* Instruction Set Attribute Register 5 */
+
+#define CP15_CCSIDR(rr) p15, 1, rr, c0, c0, 0 /* Cache Size ID Registers */
+#define CP15_CLIDR(rr) p15, 1, rr, c0, c0, 1 /* Cache Level ID Register */
+#define CP15_AIDR(rr) p15, 1, rr, c0, c0, 7 /* Auxiliary ID Register */
+
+#define CP15_CSSELR(rr) p15, 2, rr, c0, c0, 0 /* Cache Size Selection Register */
+
+/*
+ * CP15 C1 registers
+ */
+#define CP15_SCTLR(rr) p15, 0, rr, c1, c0, 0 /* System Control Register */
+#define CP15_ACTLR(rr) p15, 0, rr, c1, c0, 1 /* IMPLEMENTATION DEFINED Auxiliary Control Register */
+#define CP15_CPACR(rr) p15, 0, rr, c1, c0, 2 /* Coprocessor Access Control Register */
+
+#define CP15_SCR(rr) p15, 0, rr, c1, c1, 0 /* Secure Configuration Register */
+#define CP15_SDER(rr) p15, 0, rr, c1, c1, 1 /* Secure Debug Enable Register */
+#define CP15_NSACR(rr) p15, 0, rr, c1, c1, 2 /* Non-Secure Access Control Register */
+
+/*
+ * CP15 C2 registers
+ */
+#define CP15_TTBR0(rr) p15, 0, rr, c2, c0, 0 /* Translation Table Base Register 0 */
+#define CP15_TTBR1(rr) p15, 0, rr, c2, c0, 1 /* Translation Table Base Register 1 */
+#define CP15_TTBCR(rr) p15, 0, rr, c2, c0, 2 /* Translation Table Base Control Register */
+
+/*
+ * CP15 C3 registers
+ */
+#define CP15_DACR(rr) p15, 0, rr, c3, c0, 0 /* Domain Access Control Register */
+
+/*
+ * CP15 C5 registers
+ */
+#define CP15_DFSR(rr) p15, 0, rr, c5, c0, 0 /* Data Fault Status Register */
+
+#if __ARM_ARCH >= 6
+/* From ARMv6: */
+#define CP15_IFSR(rr) p15, 0, rr, c5, c0, 1 /* Instruction Fault Status Register */
+#endif
+#if __ARM_ARCH >= 7
+/* From ARMv7: */
+#define CP15_ADFSR(rr) p15, 0, rr, c5, c1, 0 /* Auxiliary Data Fault Status Register */
+#define CP15_AIFSR(rr) p15, 0, rr, c5, c1, 1 /* Auxiliary Instruction Fault Status Register */
+#endif
+
+/*
+ * CP15 C6 registers
+ */
+#define CP15_DFAR(rr) p15, 0, rr, c6, c0, 0 /* Data Fault Address Register */
+
+#if __ARM_ARCH >= 6
+/* From ARMv6k: */
+#define CP15_IFAR(rr) p15, 0, rr, c6, c0, 2 /* Instruction Fault Address Register */
+#endif
+
+/*
+ * CP15 C7 registers
+ */
+#if __ARM_ARCH >= 7 && defined(SMP)
+/* From ARMv7: */
+#define CP15_ICIALLUIS p15, 0, r0, c7, c1, 0 /* Instruction cache invalidate all PoU, IS */
+#define CP15_BPIALLIS p15, 0, r0, c7, c1, 6 /* Branch predictor invalidate all IS */
+#endif
+
+#define CP15_PAR p15, 0, r0, c7, c4, 0 /* Physical Address Register */
+
+#define CP15_ICIALLU p15, 0, r0, c7, c5, 0 /* Instruction cache invalidate all PoU */
+#define CP15_ICIMVAU(rr) p15, 0, rr, c7, c5, 1 /* Instruction cache invalidate */
+#if __ARM_ARCH == 6
+/* Deprecated in ARMv7 */
+#define CP15_CP15ISB p15, 0, r0, c7, c5, 4 /* ISB */
+#endif
+#define CP15_BPIALL p15, 0, r0, c7, c5, 6 /* Branch predictor invalidate all */
+#define CP15_BPIMVA p15, 0, rr, c7, c5, 7 /* Branch predictor invalidate by MVA */
+
+#if __ARM_ARCH == 6
+/* Only ARMv6: */
+#define CP15_DCIALL p15, 0, r0, c7, c6, 0 /* Data cache invalidate all */
+#endif
+#define CP15_DCIMVAC(rr) p15, 0, rr, c7, c6, 1 /* Data cache invalidate by MVA PoC */
+#define CP15_DCISW(rr) p15, 0, rr, c7, c6, 2 /* Data cache invalidate by set/way */
+
+#define CP15_ATS1CPR(rr) p15, 0, rr, c7, c8, 0 /* Stage 1 Current state PL1 read */
+#define CP15_ATS1CPW(rr) p15, 0, rr, c7, c8, 1 /* Stage 1 Current state PL1 write */
+#define CP15_ATS1CUR(rr) p15, 0, rr, c7, c8, 2 /* Stage 1 Current state unprivileged read */
+#define CP15_ATS1CUW(rr) p15, 0, rr, c7, c8, 3 /* Stage 1 Current state unprivileged write */
+
+#if __ARM_ARCH >= 7
+/* From ARMv7: */
+#define CP15_ATS12NSOPR(rr) p15, 0, rr, c7, c8, 4 /* Stages 1 and 2 Non-secure only PL1 read */
+#define CP15_ATS12NSOPW(rr) p15, 0, rr, c7, c8, 5 /* Stages 1 and 2 Non-secure only PL1 write */
+#define CP15_ATS12NSOUR(rr) p15, 0, rr, c7, c8, 6 /* Stages 1 and 2 Non-secure only unprivileged read */
+#define CP15_ATS12NSOUW(rr) p15, 0, rr, c7, c8, 7 /* Stages 1 and 2 Non-secure only unprivileged write */
+#endif
+
+#if __ARM_ARCH == 6
+/* Only ARMv6: */
+#define CP15_DCCALL p15, 0, r0, c7, c10, 0 /* Data cache clean all */
+#endif
+#define CP15_DCCMVAC(rr) p15, 0, rr, c7, c10, 1 /* Data cache clean by MVA PoC */
+#define CP15_DCCSW(rr) p15, 0, rr, c7, c10, 2 /* Data cache clean by set/way */
+#if __ARM_ARCH == 6
+/* Only ARMv6: */
+#define CP15_CP15DSB p15, 0, r0, c7, c10, 4 /* DSB */
+#define CP15_CP15DMB p15, 0, r0, c7, c10, 5 /* DMB */
+#define CP15_CP15WFI p15, 0, r0, c7, c0, 4 /* WFI */
+#endif
+
+#if __ARM_ARCH >= 7
+/* From ARMv7: */
+#define CP15_DCCMVAU(rr) p15, 0, rr, c7, c11, 1 /* Data cache clean by MVA PoU */
+#endif
+
+#if __ARM_ARCH == 6
+/* Only ARMv6: */
+#define CP15_DCCIALL p15, 0, r0, c7, c14, 0 /* Data cache clean and invalidate all */
+#endif
+#define CP15_DCCIMVAC(rr) p15, 0, rr, c7, c14, 1 /* Data cache clean and invalidate by MVA PoC */
+#define CP15_DCCISW(rr) p15, 0, rr, c7, c14, 2 /* Data cache clean and invalidate by set/way */
+
+/*
+ * CP15 C8 registers
+ */
+#if __ARM_ARCH >= 7 && defined(SMP)
+/* From ARMv7: */
+#define CP15_TLBIALLIS p15, 0, r0, c8, c3, 0 /* Invalidate entire unified TLB IS */
+#define CP15_TLBIMVAIS(rr) p15, 0, rr, c8, c3, 1 /* Invalidate unified TLB by MVA IS */
+#define CP15_TLBIASIDIS(rr) p15, 0, rr, c8, c3, 2 /* Invalidate unified TLB by ASID IS */
+#define CP15_TLBIMVAAIS(rr) p15, 0, rr, c8, c3, 3 /* Invalidate unified TLB by MVA, all ASID IS */
+#endif
+
+#define CP15_TLBIALL p15, 0, r0, c8, c7, 0 /* Invalidate entire unified TLB */
+#define CP15_TLBIMVA(rr) p15, 0, rr, c8, c7, 1 /* Invalidate unified TLB by MVA */
+#define CP15_TLBIASID(rr) p15, 0, rr, c8, c7, 2 /* Invalidate unified TLB by ASID */
+
+#if __ARM_ARCH >= 6
+/* From ARMv6: */
+#define CP15_TLBIMVAA(rr) p15, 0, rr, c8, c7, 3 /* Invalidate unified TLB by MVA, all ASID */
+#endif
+
+/*
+ * CP15 C9 registers
+ */
+#if __ARM_ARCH == 6 && defined(CPU_ARM1176)
+#define CP15_PMCCNTR(rr) p15, 0, rr, c15, c12, 1 /* PM Cycle Count Register */
+#elif __ARM_ARCH > 6
+#define CP15_PMCR(rr) p15, 0, rr, c9, c12, 0 /* Performance Monitor Control Register */
+#define CP15_PMCNTENSET(rr) p15, 0, rr, c9, c12, 1 /* PM Count Enable Set Register */
+#define CP15_PMCNTENCLR(rr) p15, 0, rr, c9, c12, 2 /* PM Count Enable Clear Register */
+#define CP15_PMOVSR(rr) p15, 0, rr, c9, c12, 3 /* PM Overflow Flag Status Register */
+#define CP15_PMSWINC(rr) p15, 0, rr, c9, c12, 4 /* PM Software Increment Register */
+#define CP15_PMSELR(rr) p15, 0, rr, c9, c12, 5 /* PM Event Counter Selection Register */
+#define CP15_PMCCNTR(rr) p15, 0, rr, c9, c13, 0 /* PM Cycle Count Register */
+#define CP15_PMXEVTYPER(rr) p15, 0, rr, c9, c13, 1 /* PM Event Type Select Register */
+#define CP15_PMXEVCNTRR(rr) p15, 0, rr, c9, c13, 2 /* PM Event Count Register */
+#define CP15_PMUSERENR(rr) p15, 0, rr, c9, c14, 0 /* PM User Enable Register */
+#define CP15_PMINTENSET(rr) p15, 0, rr, c9, c14, 1 /* PM Interrupt Enable Set Register */
+#define CP15_PMINTENCLR(rr) p15, 0, rr, c9, c14, 2 /* PM Interrupt Enable Clear Register */
+#endif
+
+/*
+ * CP15 C10 registers
+ */
+/* Without LPAE this is PRRR, with LPAE it's MAIR0 */
+#define CP15_PRRR(rr) p15, 0, rr, c10, c2, 0 /* Primary Region Remap Register */
+#define CP15_MAIR0(rr) p15, 0, rr, c10, c2, 0 /* Memory Attribute Indirection Register 0 */
+/* Without LPAE this is NMRR, with LPAE it's MAIR1 */
+#define CP15_NMRR(rr) p15, 0, rr, c10, c2, 1 /* Normal Memory Remap Register */
+#define CP15_MAIR1(rr) p15, 0, rr, c10, c2, 1 /* Memory Attribute Indirection Register 1 */
+
+#define CP15_AMAIR0(rr) p15, 0, rr, c10, c3, 0 /* Auxiliary Memory Attribute Indirection Register 0 */
+#define CP15_AMAIR1(rr) p15, 0, rr, c10, c3, 1 /* Auxiliary Memory Attribute Indirection Register 1 */
+
+/*
+ * CP15 C12 registers
+ */
+#define CP15_VBAR(rr) p15, 0, rr, c12, c0, 0 /* Vector Base Address Register */
+#define CP15_MVBAR(rr) p15, 0, rr, c12, c0, 1 /* Monitor Vector Base Address Register */
+
+#define CP15_ISR(rr) p15, 0, rr, c12, c1, 0 /* Interrupt Status Register */
+
+/*
+ * CP15 C13 registers
+ */
+#define CP15_FCSEIDR(rr) p15, 0, rr, c13, c0, 0 /* FCSE Process ID Register */
+#define CP15_CONTEXTIDR(rr) p15, 0, rr, c13, c0, 1 /* Context ID Register */
+#define CP15_TPIDRURW(rr) p15, 0, rr, c13, c0, 2 /* User Read/Write Thread ID Register */
+#define CP15_TPIDRURO(rr) p15, 0, rr, c13, c0, 3 /* User Read-Only Thread ID Register */
+#define CP15_TPIDRPRW(rr) p15, 0, rr, c13, c0, 4 /* PL1 only Thread ID Register */
+
+/*
+ * CP15 C15 registers
+ */
+#define CP15_CBAR(rr) p15, 4, rr, c15, c0, 0 /* Configuration Base Address Register */
+
+#endif /* !MACHINE_SYSREG_H */
Property changes on: trunk/sys/arm/include/sysreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/trap.h
===================================================================
--- trunk/sys/arm/include/trap.h (rev 0)
+++ trunk/sys/arm/include/trap.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,11 @@
+/* $MidnightBSD$ */
+/* $NetBSD: trap.h,v 1.1 2001/02/23 03:48:19 ichiro Exp $ */
+/* $FreeBSD: stable/10/sys/arm/include/trap.h 140001 2005-01-10 22:43:16Z cognet $ */
+
+#ifndef _MACHINE_TRAP_H_
+#define _MACHINE_TRAP_H_
+#define GDB_BREAKPOINT 0xe6000011
+#define GDB5_BREAKPOINT 0xe7ffdefe
+#define PTRACE_BREAKPOINT 0xe7fffff0
+#define KERNEL_BREAKPOINT 0xe7ffffff
+#endif /* _MACHINE_TRAP_H_ */
Property changes on: trunk/sys/arm/include/trap.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/ucontext.h
===================================================================
--- trunk/sys/arm/include/ucontext.h (rev 0)
+++ trunk/sys/arm/include/ucontext.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,109 @@
+/* $MidnightBSD$ */
+/* $NetBSD: mcontext.h,v 1.4 2003/10/08 22:43:01 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein and by Jason R. Thorpe of Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/ucontext.h 203974 2010-02-16 21:59:17Z imp $
+ */
+
+#ifndef _MACHINE_MCONTEXT_H_
+#define _MACHINE_MCONTEXT_H_
+/*
+ * General register state
+ */
+#define _NGREG 17
+typedef unsigned int __greg_t;
+typedef __greg_t __gregset_t[_NGREG];
+
+#define _REG_R0 0
+#define _REG_R1 1
+#define _REG_R2 2
+#define _REG_R3 3
+#define _REG_R4 4
+#define _REG_R5 5
+#define _REG_R6 6
+#define _REG_R7 7
+#define _REG_R8 8
+#define _REG_R9 9
+#define _REG_R10 10
+#define _REG_R11 11
+#define _REG_R12 12
+#define _REG_R13 13
+#define _REG_R14 14
+#define _REG_R15 15
+#define _REG_CPSR 16
+/* Convenience synonyms */
+#define _REG_FP _REG_R11
+#define _REG_SP _REG_R13
+#define _REG_LR _REG_R14
+#define _REG_PC _REG_R15
+
+/*
+ * Floating point register state
+ */
+/* Note: the storage layout of this structure must be identical to ARMFPE! */
+typedef struct {
+ unsigned int __fp_fpsr;
+ struct {
+ unsigned int __fp_exponent;
+ unsigned int __fp_mantissa_hi;
+ unsigned int __fp_mantissa_lo;
+ } __fp_fr[8];
+} __fpregset_t;
+
+typedef struct {
+ unsigned int __vfp_fpscr;
+ unsigned int __vfp_fstmx[33];
+ unsigned int __vfp_fpsid;
+} __vfpregset_t;
+
+typedef struct {
+ __gregset_t __gregs;
+ union {
+ __fpregset_t __fpregs;
+ __vfpregset_t __vfpregs;
+ } __fpu;
+} mcontext_t;
+
+/* Machine-dependent uc_flags */
+#define _UC_ARM_VFP 0x00010000 /* FPU field is VFP */
+
+/* used by signal delivery to indicate status of signal stack */
+#define _UC_SETSTACK 0x00020000
+#define _UC_CLRSTACK 0x00040000
+
+#define _UC_MACHINE_PAD 3 /* Padding appended to ucontext_t */
+
+#define _UC_MACHINE_SP(uc) ((uc)->uc_mcontext.__gregs[_REG_SP])
+#define _UC_MACHINE_PC(uc) ((uc)->uc_mcontext.__gregs[_REG_PC])
+#define _UC_MACHINE_INTRV(uc) ((uc)->uc_mcontext.__gregs[_REG_R0])
+
+#define _UC_MACHINE_SET_PC(uc, pc) _UC_MACHINE_PC(uc) = (pc)
+
+#endif /* !_MACHINE_MCONTEXT_H_ */
Property changes on: trunk/sys/arm/include/ucontext.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/undefined.h
===================================================================
--- trunk/sys/arm/include/undefined.h (rev 0)
+++ trunk/sys/arm/include/undefined.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,93 @@
+/* $MidnightBSD$ */
+/* $NetBSD: undefined.h,v 1.4 2001/12/20 01:20:23 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1995-1996 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * undefined.h
+ *
+ * Undefined instruction types, symbols and prototypes
+ *
+ * Created : 08/02/95
+ *
+ * $FreeBSD: stable/10/sys/arm/include/undefined.h 259329 2013-12-13 20:43:11Z ian $
+ */
+
+
+#ifndef _MACHINE_UNDEFINED_H_
+#define _MACHINE_UNDEFINED_H_
+#ifdef _KERNEL
+
+#include <sys/queue.h>
+
+struct trapframe;
+
+typedef int (*undef_handler_t) (unsigned int, unsigned int, struct trapframe *, int);
+
+#define FP_COPROC 1
+#define FP_COPROC2 2
+#define MAX_COPROCS 16
+
+/* Prototypes for undefined.c */
+
+void *install_coproc_handler (int, undef_handler_t);
+void remove_coproc_handler (void *);
+void undefined_init (void);
+
+/*
+ * XXX Stuff below here is for use before malloc() is available. Most code
+ * shouldn't use it.
+ */
+
+struct undefined_handler {
+ LIST_ENTRY(undefined_handler) uh_link;
+ undef_handler_t uh_handler;
+};
+
+/*
+ * Handlers installed using install_coproc_handler_static shouldn't be
+ * removed.
+ */
+void install_coproc_handler_static (int, struct undefined_handler *);
+
+/* Calls up to undefined.c from trap handlers */
+void undefinedinstruction(struct trapframe *);
+
+#endif
+
+/* End of undefined.h */
+
+#endif /* _MACHINE_UNDEFINED_H_ */
Property changes on: trunk/sys/arm/include/undefined.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/utrap.h
===================================================================
--- trunk/sys/arm/include/utrap.h (rev 0)
+++ trunk/sys/arm/include/utrap.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,111 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/utrap.h 129198 2004-05-14 11:46:45Z cognet $
+ */
+
+#ifndef _MACHINE_UTRAP_H_
+#define _MACHINE_UTRAP_H_
+
+#define UT_INSTRUCTION_EXCEPTION 1
+#define UT_INSTRUCTION_ERROR 2
+#define UT_INSTRUCTION_PROTECTION 3
+#define UT_ILLTRAP_INSTRUCTION 4
+#define UT_ILLEGAL_INSTRUCTION 5
+#define UT_PRIVILEGED_OPCODE 6
+#define UT_FP_DISABLED 7
+#define UT_FP_EXCEPTION_IEEE_754 8
+#define UT_FP_EXCEPTION_OTHER 9
+#define UT_TAG_OFERFLOW 10
+#define UT_DIVISION_BY_ZERO 11
+#define UT_DATA_EXCEPTION 12
+#define UT_DATA_ERROR 13
+#define UT_DATA_PROTECTION 14
+#define UT_MEM_ADDRESS_NOT_ALIGNED 15
+#define UT_PRIVILEGED_ACTION 16
+#define UT_ASYNC_DATA_ERROR 17
+#define UT_TRAP_INSTRUCTION_16 18
+#define UT_TRAP_INSTRUCTION_17 19
+#define UT_TRAP_INSTRUCTION_18 20
+#define UT_TRAP_INSTRUCTION_19 21
+#define UT_TRAP_INSTRUCTION_20 22
+#define UT_TRAP_INSTRUCTION_21 23
+#define UT_TRAP_INSTRUCTION_22 24
+#define UT_TRAP_INSTRUCTION_23 25
+#define UT_TRAP_INSTRUCTION_24 26
+#define UT_TRAP_INSTRUCTION_25 27
+#define UT_TRAP_INSTRUCTION_26 28
+#define UT_TRAP_INSTRUCTION_27 29
+#define UT_TRAP_INSTRUCTION_28 30
+#define UT_TRAP_INSTRUCTION_29 31
+#define UT_TRAP_INSTRUCTION_30 32
+#define UT_TRAP_INSTRUCTION_31 33
+#define UT_INSTRUCTION_MISS 34
+#define UT_DATA_MISS 35
+#define UT_MAX 36
+
+#define ST_SUNOS_SYSCALL 0
+#define ST_BREAKPOINT 1
+#define ST_DIVISION_BY_ZERO 2
+#define ST_FLUSH_WINDOWS 3 /* XXX implement! */
+#define ST_CLEAN_WINDOW 4
+#define ST_RANGE_CHECK 5
+#define ST_FIX_ALIGNMENT 6
+#define ST_INTEGER_OVERFLOW 7
+/* 8 is 32-bit ABI syscall (old solaris syscall?) */
+#define ST_BSD_SYSCALL 9
+#define ST_FP_RESTORE 10
+/* 11-15 are available */
+/* 16 is linux 32 bit syscall (but supposed to be reserved, grr) */
+/* 17 is old linux 64 bit syscall (but supposed to be reserved, grr) */
+/* 16-31 are reserved for user applications (utraps) */
+#define ST_GETCC 32 /* XXX implement! */
+#define ST_SETCC 33 /* XXX implement! */
+#define ST_GETPSR 34 /* XXX implement! */
+#define ST_SETPSR 35 /* XXX implement! */
+/* 36-63 are available */
+#define ST_SOLARIS_SYSCALL 64
+#define ST_SYSCALL 65
+#define ST_SYSCALL32 66
+/* 67 is reserved to OS source licensee */
+/* 68 is return from deferred trap (not supported) */
+/* 69-95 are reserved to SPARC international */
+/* 96-108 are available */
+/* 109 is linux 64 bit syscall */
+/* 110 is linux 64 bit getcontext (?) */
+/* 111 is linux 64 bit setcontext (?) */
+/* 112-255 are available */
+
+#define UTH_NOCHANGE (-1)
+
+#ifndef __ASM__
+
+typedef int utrap_entry_t;
+typedef void *utrap_handler_t;
+
+#endif
+
+#endif
Property changes on: trunk/sys/arm/include/utrap.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/vdso.h
===================================================================
--- trunk/sys/arm/include/vdso.h (rev 0)
+++ trunk/sys/arm/include/vdso.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,35 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2012 Konstantin Belousov <kib at FreeBSD.ORG>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/vdso.h 237433 2012-06-22 07:06:40Z kib $
+ */
+
+#ifndef _ARM_VDSO_H
+#define _ARM_VDSO_H
+
+#define VDSO_TIMEHANDS_MD \
+ uint32_t th_res[8];
+
+#endif
Property changes on: trunk/sys/arm/include/vdso.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/vfp.h
===================================================================
--- trunk/sys/arm/include/vfp.h (rev 0)
+++ trunk/sys/arm/include/vfp.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,141 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2012 Mark Tinguely
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * $FreeBSD: stable/10/sys/arm/include/vfp.h 266341 2014-05-17 19:37:04Z ian $
+ */
+
+
+#ifndef _MACHINE__VFP_H_
+#define _MACHINE__VFP_H_
+
+/* fpsid, fpscr, fpexc are defined in the newer gas */
+#define VFPSID cr0
+#define VFPSCR cr1
+#define VMVFR1 cr6
+#define VMVFR0 cr7
+#define VFPEXC cr8
+#define VFPINST cr9 /* vfp 1 and 2 except instruction */
+#define VFPINST2 cr10 /* vfp 2? */
+
+/* VFPSID */
+#define VFPSID_IMPLEMENTOR_OFF 24
+#define VFPSID_IMPLEMENTOR_MASK (0xff000000)
+#define VFPSID_HARDSOFT_IMP (0x00800000)
+#define VFPSID_SINGLE_PREC 20 /* version 1 and 2 */
+#define VFPSID_SUBVERSION_OFF 16
+#define VFPSID_SUBVERSION2_MASK (0x000f0000) /* version 1 and 2 */
+#define VFPSID_SUBVERSION3_MASK (0x007f0000) /* version 3 */
+#define VFP_ARCH1 0x0
+#define VFP_ARCH2 0x1
+#define VFP_ARCH3 0x2
+#define VFPSID_PARTNUMBER_OFF 8
+#define VFPSID_PARTNUMBER_MASK (0x0000ff00)
+#define VFPSID_VARIANT_OFF 4
+#define VFPSID_VARIANT_MASK (0x000000f0)
+#define VFPSID_REVISION_MASK 0x0f
+
+/* VFPSCR */
+#define VFPSCR_CC_N (0x80000000) /* comparison less than */
+#define VFPSCR_CC_Z (0x40000000) /* comparison equal */
+#define VFPSCR_CC_C (0x20000000) /* comparison = > unordered */
+#define VFPSCR_CC_V (0x10000000) /* comparison unordered */
+#define VFPSCR_QC (0x08000000) /* saturation cululative */
+#define VFPSCR_DN (0x02000000) /* default NaN enable */
+#define VFPSCR_FZ (0x01000000) /* flush to zero enabled */
+
+#define VFPSCR_RMODE_OFF 22 /* rounding mode offset */
+#define VFPSCR_RMODE_MASK (0x00c00000) /* rounding mode mask */
+#define VFPSCR_RMODE_RN (0x00000000) /* round nearest */
+#define VFPSCR_RMODE_RPI (0x00400000) /* round to plus infinity */
+#define VFPSCR_RMODE_RNI (0x00800000) /* round to neg infinity */
+#define VFPSCR_RMODE_RM (0x00c00000) /* round to zero */
+
+#define VFPSCR_STRIDE_OFF 20 /* vector stride -1 */
+#define VFPSCR_STRIDE_MASK (0x00300000)
+#define VFPSCR_LEN_OFF 16 /* vector length -1 */
+#define VFPSCR_LEN_MASK (0x00070000)
+#define VFPSCR_IDE (0x00008000) /* input subnormal exc enable */
+#define VFPSCR_IXE (0x00001000) /* inexact exception enable */
+#define VFPSCR_UFE (0x00000800) /* underflow exception enable */
+#define VFPSCR_OFE (0x00000400) /* overflow exception enable */
+#define VFPSCR_DNZ (0x00000200) /* div by zero exception en */
+#define VFPSCR_IOE (0x00000100) /* invalid op exec enable */
+#define VFPSCR_IDC (0x00000080) /* input subnormal cumul */
+#define VFPSCR_IXC (0x00000010) /* Inexact cumulative flag */
+#define VFPSCR_UFC (0x00000008) /* underflow cumulative flag */
+#define VFPSCR_OFC (0x00000004) /* overflow cumulative flag */
+#define VFPSCR_DZC (0x00000002) /* division by zero flag */
+#define VFPSCR_IOC (0x00000001) /* invalid operation cumul */
+
+/* VFPEXC */
+#define VFPEXC_EX (0x80000000) /* exception v1 v2 */
+#define VFPEXC_EN (0x40000000) /* vfp enable */
+#define VFPEXC_FP2V (0x10000000) /* FPINST2 valid */
+#define VFPEXC_INV (0x00000080) /* Input exception */
+#define VFPEXC_UFC (0x00000008) /* Underflow exception */
+#define VFPEXC_OFC (0x00000004) /* Overflow exception */
+#define VFPEXC_IOC (0x00000001) /* Invlaid operation */
+
+/* version 3 registers */
+/* VMVFR0 */
+#define VMVFR0_RM_OFF 28
+#define VMVFR0_RM_MASK (0xf0000000) /* VFP rounding modes */
+
+#define VMVFR0_SV_OFF 24
+#define VMVFR0_SV_MASK (0x0f000000) /* VFP short vector supp */
+#define VMVFR0_SR_OFF 20
+#define VMVFR0_SR (0x00f00000) /* VFP hw sqrt supp */
+#define VMVFR0_D_OFF 16
+#define VMVFR0_D_MASK (0x000f0000) /* VFP divide supp */
+#define VMVFR0_TE_OFF 12
+#define VMVFR0_TE_MASK (0x0000f000) /* VFP trap exception supp */
+#define VMVFR0_DP_OFF 8
+#define VMVFR0_DP_MASK (0x00000f00) /* VFP double prec support */
+#define VMVFR0_SP_OFF 4
+#define VMVFR0_SP_MASK (0x000000f0) /* VFP single prec support */
+#define VMVFR0_RB_MASK (0x0000000f) /* VFP 64 bit media support */
+
+/* VMVFR1 */
+#define VMVFR1_SP_OFF 16
+#define VMVFR1_SP_MASK (0x000f0000) /* Neon single prec support */
+#define VMVFR1_I_OFF 12
+#define VMVFR1_I_MASK (0x0000f000) /* Neon integer support */
+#define VMVFR1_LS_OFF 8
+#define VMVFR1_LS_MASK (0x00000f00) /* Neon ld/st instr support */
+#define VMVFR1_DN_OFF 4
+#define VMVFR1_DN_MASK (0x000000f0) /* Neon prop NaN support */
+#define VMVFR1_FZ_MASK (0x0000000f) /* Neon denormal arith supp */
+
+#define COPROC10 (0x3 << 20)
+#define COPROC11 (0x3 << 22)
+
+#ifndef LOCORE
+void vfp_init(void);
+void vfp_store(struct vfp_state *, boolean_t);
+void vfp_discard(struct thread *);
+#endif
+
+#endif
Property changes on: trunk/sys/arm/include/vfp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/vm.h
===================================================================
--- trunk/sys/arm/include/vm.h (rev 0)
+++ trunk/sys/arm/include/vm.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Alan L. Cox <alc at cs.rice.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/vm.h 244414 2012-12-19 00:24:31Z cognet $
+ */
+
+#ifndef _MACHINE_VM_H_
+#define _MACHINE_VM_H_
+
+/* Memory attribute configuration. */
+#define VM_MEMATTR_DEFAULT 0
+#define VM_MEMATTR_UNCACHEABLE 1
+
+#endif /* !_MACHINE_VM_H_ */
Property changes on: trunk/sys/arm/include/vm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/include/vmparam.h
===================================================================
--- trunk/sys/arm/include/vmparam.h (rev 0)
+++ trunk/sys/arm/include/vmparam.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,176 @@
+/* $MidnightBSD$ */
+/* $NetBSD: vmparam.h,v 1.26 2003/08/07 16:27:47 agc Exp $ */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/include/vmparam.h 283339 2015-05-23 23:27:00Z ian $
+ */
+
+#ifndef _MACHINE_VMPARAM_H_
+#define _MACHINE_VMPARAM_H_
+
+/*
+ * Machine dependent constants for ARM.
+ */
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#ifndef MAXTSIZ
+#define MAXTSIZ (64UL*1024*1024) /* max text size */
+#endif
+#ifndef DFLDSIZ
+#define DFLDSIZ (128UL*1024*1024) /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define MAXDSIZ (512UL*1024*1024) /* max data size */
+#endif
+#ifndef DFLSSIZ
+#define DFLSSIZ (2UL*1024*1024) /* initial stack size limit */
+#endif
+#ifndef MAXSSIZ
+#define MAXSSIZ (8UL*1024*1024) /* max stack size */
+#endif
+#ifndef SGROWSIZ
+#define SGROWSIZ (128UL*1024) /* amount to grow stack */
+#endif
+
+/*
+ * Address space constants
+ */
+
+/*
+ * The line between user space and kernel space
+ * Mappings >= KERNEL_BASE are constant across all processes
+ */
+#ifndef KERNBASE
+#define KERNBASE 0xc0000000
+#endif
+
+/*
+ * max number of non-contig chunks of physical RAM you can have
+ */
+
+#define VM_PHYSSEG_MAX 32
+
+/*
+ * The physical address space may be sparsely populated on some ARM systems.
+ */
+#define VM_PHYSSEG_SPARSE
+
+/*
+ * Create two free page pools. Since the ARM kernel virtual address
+ * space does not include a mapping onto the machine's entire physical
+ * memory, VM_FREEPOOL_DIRECT is defined as an alias for the default
+ * pool, VM_FREEPOOL_DEFAULT.
+ */
+#define VM_NFREEPOOL 2
+#define VM_FREEPOOL_CACHE 1
+#define VM_FREEPOOL_DEFAULT 0
+#define VM_FREEPOOL_DIRECT 0
+
+/*
+ * We need just one free list: DEFAULT.
+ */
+#define VM_NFREELIST 1
+#define VM_FREELIST_DEFAULT 0
+
+/*
+ * The largest allocation size is 1MB.
+ */
+#define VM_NFREEORDER 9
+
+/*
+ * Enable superpage reservations: 1 level.
+ */
+#ifndef VM_NRESERVLEVEL
+#define VM_NRESERVLEVEL 1
+#endif
+
+/*
+ * Level 0 reservations consist of 256 pages.
+ */
+#ifndef VM_LEVEL_0_ORDER
+#define VM_LEVEL_0_ORDER 8
+#endif
+
+#define UPT_MAX_ADDRESS VADDR(UPTPTDI + 3, 0)
+#define UPT_MIN_ADDRESS VADDR(UPTPTDI, 0)
+
+#define VM_MIN_ADDRESS (0x00001000)
+#ifndef VM_MAXUSER_ADDRESS
+#define VM_MAXUSER_ADDRESS KERNBASE
+#endif /* VM_MAXUSER_ADDRESS */
+#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS
+
+#define USRSTACK VM_MAXUSER_ADDRESS
+
+/* initial pagein size of beginning of executable file */
+#ifndef VM_INITIAL_PAGEIN
+#define VM_INITIAL_PAGEIN 16
+#endif
+
+#ifndef VM_MIN_KERNEL_ADDRESS
+#define VM_MIN_KERNEL_ADDRESS KERNBASE
+#endif
+
+#define VM_MAX_KERNEL_ADDRESS (vm_max_kernel_address)
+
+/*
+ * How many physical pages per kmem arena virtual page.
+ */
+#ifndef VM_KMEM_SIZE_SCALE
+#define VM_KMEM_SIZE_SCALE (3)
+#endif
+
+/*
+ * Optional floor (in bytes) on the size of the kmem arena.
+ */
+#ifndef VM_KMEM_SIZE_MIN
+#define VM_KMEM_SIZE_MIN (12 * 1024 * 1024)
+#endif
+
+/*
+ * Optional ceiling (in bytes) on the size of the kmem arena: 40% of the
+ * kernel map.
+ */
+#ifndef VM_KMEM_SIZE_MAX
+#define VM_KMEM_SIZE_MAX ((vm_max_kernel_address - \
+ VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5)
+#endif
+
+extern vm_offset_t vm_max_kernel_address;
+
+#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */
+
+#ifndef VM_MAX_AUTOTUNE_MAXUSERS
+#define VM_MAX_AUTOTUNE_MAXUSERS 384
+#endif
+
+#endif /* _MACHINE_VMPARAM_H_ */
Property changes on: trunk/sys/arm/include/vmparam.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/files.lpc
===================================================================
--- trunk/sys/arm/lpc/files.lpc (rev 0)
+++ trunk/sys/arm/lpc/files.lpc 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,20 @@
+# $FreeBSD: stable/10/sys/arm/lpc/files.lpc 278727 2015-02-13 22:32:02Z ian $
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_arm9.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/lpc/lpc_machdep.c standard
+arm/lpc/lpc_pwr.c standard
+arm/lpc/lpc_intc.c standard
+arm/lpc/lpc_timer.c standard
+arm/lpc/lpc_rtc.c standard
+arm/lpc/if_lpe.c optional lpe
+arm/lpc/lpc_ohci.c optional ohci
+arm/lpc/lpc_mmc.c optional lpcmmc
+arm/lpc/lpc_fb.c optional lpcfb
+arm/lpc/lpc_gpio.c optional lpcgpio
+arm/lpc/lpc_spi.c optional lpcspi
+arm/lpc/lpc_dmac.c optional dmac
+arm/lpc/ssd1289.c optional ssd1289
+dev/uart/uart_dev_lpc.c optional uart
+kern/kern_clocksource.c standard
Property changes on: trunk/sys/arm/lpc/files.lpc
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/lpc/if_lpe.c
===================================================================
--- trunk/sys/arm/lpc/if_lpe.c (rev 0)
+++ trunk/sys/arm/lpc/if_lpe.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1233 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/if_lpe.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/bus.h>
+#include <sys/socket.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+
+#include <net/bpf.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+#include <arm/lpc/if_lpereg.h>
+
+#include "miibus_if.h"
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+struct lpe_dmamap_arg {
+ bus_addr_t lpe_dma_busaddr;
+};
+
+struct lpe_rxdesc {
+ struct mbuf * lpe_rxdesc_mbuf;
+ bus_dmamap_t lpe_rxdesc_dmamap;
+};
+
+struct lpe_txdesc {
+ int lpe_txdesc_first;
+ struct mbuf * lpe_txdesc_mbuf;
+ bus_dmamap_t lpe_txdesc_dmamap;
+};
+
+struct lpe_chain_data {
+ bus_dma_tag_t lpe_parent_tag;
+ bus_dma_tag_t lpe_tx_ring_tag;
+ bus_dmamap_t lpe_tx_ring_map;
+ bus_dma_tag_t lpe_tx_status_tag;
+ bus_dmamap_t lpe_tx_status_map;
+ bus_dma_tag_t lpe_tx_buf_tag;
+ bus_dma_tag_t lpe_rx_ring_tag;
+ bus_dmamap_t lpe_rx_ring_map;
+ bus_dma_tag_t lpe_rx_status_tag;
+ bus_dmamap_t lpe_rx_status_map;
+ bus_dma_tag_t lpe_rx_buf_tag;
+ struct lpe_rxdesc lpe_rx_desc[LPE_RXDESC_NUM];
+ struct lpe_txdesc lpe_tx_desc[LPE_TXDESC_NUM];
+ int lpe_tx_prod;
+ int lpe_tx_last;
+ int lpe_tx_used;
+};
+
+struct lpe_ring_data {
+ struct lpe_hwdesc * lpe_rx_ring;
+ struct lpe_hwstatus * lpe_rx_status;
+ bus_addr_t lpe_rx_ring_phys;
+ bus_addr_t lpe_rx_status_phys;
+ struct lpe_hwdesc * lpe_tx_ring;
+ struct lpe_hwstatus * lpe_tx_status;
+ bus_addr_t lpe_tx_ring_phys;
+ bus_addr_t lpe_tx_status_phys;
+};
+
+struct lpe_softc {
+ struct ifnet * lpe_ifp;
+ struct mtx lpe_mtx;
+ phandle_t lpe_ofw;
+ device_t lpe_dev;
+ device_t lpe_miibus;
+ uint8_t lpe_enaddr[6];
+ struct resource * lpe_mem_res;
+ struct resource * lpe_irq_res;
+ void * lpe_intrhand;
+ bus_space_tag_t lpe_bst;
+ bus_space_handle_t lpe_bsh;
+#define LPE_FLAG_LINK (1 << 0)
+ uint32_t lpe_flags;
+ int lpe_watchdog_timer;
+ struct callout lpe_tick;
+ struct lpe_chain_data lpe_cdata;
+ struct lpe_ring_data lpe_rdata;
+};
+
+static int lpe_probe(device_t);
+static int lpe_attach(device_t);
+static int lpe_detach(device_t);
+static int lpe_miibus_readreg(device_t, int, int);
+static int lpe_miibus_writereg(device_t, int, int, int);
+static void lpe_miibus_statchg(device_t);
+
+static void lpe_reset(struct lpe_softc *);
+static void lpe_init(void *);
+static void lpe_init_locked(struct lpe_softc *);
+static void lpe_start(struct ifnet *);
+static void lpe_start_locked(struct ifnet *);
+static void lpe_stop(struct lpe_softc *);
+static void lpe_stop_locked(struct lpe_softc *);
+static int lpe_ioctl(struct ifnet *, u_long, caddr_t);
+static void lpe_set_rxmode(struct lpe_softc *);
+static void lpe_set_rxfilter(struct lpe_softc *);
+static void lpe_intr(void *);
+static void lpe_rxintr(struct lpe_softc *);
+static void lpe_txintr(struct lpe_softc *);
+static void lpe_tick(void *);
+static void lpe_watchdog(struct lpe_softc *);
+static int lpe_encap(struct lpe_softc *, struct mbuf **);
+static int lpe_dma_alloc(struct lpe_softc *);
+static int lpe_dma_alloc_rx(struct lpe_softc *);
+static int lpe_dma_alloc_tx(struct lpe_softc *);
+static int lpe_init_rx(struct lpe_softc *);
+static int lpe_init_rxbuf(struct lpe_softc *, int);
+static void lpe_discard_rxbuf(struct lpe_softc *, int);
+static void lpe_dmamap_cb(void *, bus_dma_segment_t *, int, int);
+static int lpe_ifmedia_upd(struct ifnet *);
+static void lpe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+#define lpe_lock(_sc) mtx_lock(&(_sc)->lpe_mtx)
+#define lpe_unlock(_sc) mtx_unlock(&(_sc)->lpe_mtx)
+#define lpe_lock_assert(sc) mtx_assert(&(_sc)->lpe_mtx, MA_OWNED)
+
+#define lpe_read_4(_sc, _reg) \
+ bus_space_read_4((_sc)->lpe_bst, (_sc)->lpe_bsh, (_reg))
+#define lpe_write_4(_sc, _reg, _val) \
+ bus_space_write_4((_sc)->lpe_bst, (_sc)->lpe_bsh, (_reg), (_val))
+
+#define LPE_HWDESC_RXERRS (LPE_HWDESC_CRCERROR | LPE_HWDESC_SYMBOLERROR | \
+ LPE_HWDESC_LENGTHERROR | LPE_HWDESC_ALIGNERROR | LPE_HWDESC_OVERRUN | \
+ LPE_HWDESC_RXNODESCR)
+
+#define LPE_HWDESC_TXERRS (LPE_HWDESC_EXCDEFER | LPE_HWDESC_EXCCOLL | \
+ LPE_HWDESC_LATECOLL | LPE_HWDESC_UNDERRUN | LPE_HWDESC_TXNODESCR)
+
+static int
+lpe_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,ethernet"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 10/100 Ethernet");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpe_attach(device_t dev)
+{
+ struct lpe_softc *sc = device_get_softc(dev);
+ struct ifnet *ifp;
+ int rid, i;
+ uint32_t val;
+
+ sc->lpe_dev = dev;
+ sc->lpe_ofw = ofw_bus_get_node(dev);
+
+ i = OF_getprop(sc->lpe_ofw, "local-mac-address", (void *)&sc->lpe_enaddr, 6);
+ if (i != 6) {
+ sc->lpe_enaddr[0] = 0x00;
+ sc->lpe_enaddr[1] = 0x11;
+ sc->lpe_enaddr[2] = 0x22;
+ sc->lpe_enaddr[3] = 0x33;
+ sc->lpe_enaddr[4] = 0x44;
+ sc->lpe_enaddr[5] = 0x55;
+ }
+
+ mtx_init(&sc->lpe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+ MTX_DEF);
+
+ callout_init_mtx(&sc->lpe_tick, &sc->lpe_mtx, 0);
+
+ rid = 0;
+ sc->lpe_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->lpe_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ goto fail;
+ }
+
+ sc->lpe_bst = rman_get_bustag(sc->lpe_mem_res);
+ sc->lpe_bsh = rman_get_bushandle(sc->lpe_mem_res);
+
+ rid = 0;
+ sc->lpe_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->lpe_irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ goto fail;
+ }
+
+ sc->lpe_ifp = if_alloc(IFT_ETHER);
+ if (!sc->lpe_ifp) {
+ device_printf(dev, "cannot allocated ifnet\n");
+ goto fail;
+ }
+
+ ifp = sc->lpe_ifp;
+
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = lpe_start;
+ ifp->if_ioctl = lpe_ioctl;
+ ifp->if_init = lpe_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ether_ifattach(ifp, sc->lpe_enaddr);
+
+ if (bus_setup_intr(dev, sc->lpe_irq_res, INTR_TYPE_NET, NULL,
+ lpe_intr, sc, &sc->lpe_intrhand)) {
+ device_printf(dev, "cannot establish interrupt handler\n");
+ ether_ifdetach(ifp);
+ goto fail;
+ }
+
+ /* Enable Ethernet clock */
+ lpc_pwr_write(dev, LPC_CLKPWR_MACCLK_CTRL,
+ LPC_CLKPWR_MACCLK_CTRL_REG |
+ LPC_CLKPWR_MACCLK_CTRL_SLAVE |
+ LPC_CLKPWR_MACCLK_CTRL_MASTER |
+ LPC_CLKPWR_MACCLK_CTRL_HDWINF(3));
+
+ /* Reset chip */
+ lpe_reset(sc);
+
+ /* Initialize MII */
+ val = lpe_read_4(sc, LPE_COMMAND);
+ lpe_write_4(sc, LPE_COMMAND, val | LPE_COMMAND_RMII);
+
+ if (mii_attach(dev, &sc->lpe_miibus, ifp, lpe_ifmedia_upd,
+ lpe_ifmedia_sts, BMSR_DEFCAPMASK, 0x01,
+ MII_OFFSET_ANY, 0)) {
+ device_printf(dev, "cannot find PHY\n");
+ goto fail;
+ }
+
+ lpe_dma_alloc(sc);
+
+ return (0);
+
+fail:
+ if (sc->lpe_ifp)
+ if_free(sc->lpe_ifp);
+ if (sc->lpe_intrhand)
+ bus_teardown_intr(dev, sc->lpe_irq_res, sc->lpe_intrhand);
+ if (sc->lpe_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lpe_irq_res);
+ if (sc->lpe_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lpe_mem_res);
+ return (ENXIO);
+}
+
+static int
+lpe_detach(device_t dev)
+{
+ struct lpe_softc *sc = device_get_softc(dev);
+
+ lpe_stop(sc);
+
+ if_free(sc->lpe_ifp);
+ bus_teardown_intr(dev, sc->lpe_irq_res, sc->lpe_intrhand);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lpe_irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lpe_mem_res);
+
+ return (0);
+}
+
+static int
+lpe_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct lpe_softc *sc = device_get_softc(dev);
+ uint32_t val;
+ int result;
+
+ lpe_write_4(sc, LPE_MCMD, LPE_MCMD_READ);
+ lpe_write_4(sc, LPE_MADR,
+ (reg & LPE_MADR_REGMASK) << LPE_MADR_REGSHIFT |
+ (phy & LPE_MADR_PHYMASK) << LPE_MADR_PHYSHIFT);
+
+ val = lpe_read_4(sc, LPE_MIND);
+
+ /* Wait until request is completed */
+ while (val & LPE_MIND_BUSY) {
+ val = lpe_read_4(sc, LPE_MIND);
+ DELAY(10);
+ }
+
+ if (val & LPE_MIND_INVALID)
+ return (0);
+
+ lpe_write_4(sc, LPE_MCMD, 0);
+ result = (lpe_read_4(sc, LPE_MRDD) & LPE_MRDD_DATAMASK);
+ debugf("phy=%d reg=%d result=0x%04x\n", phy, reg, result);
+
+ return (result);
+}
+
+static int
+lpe_miibus_writereg(device_t dev, int phy, int reg, int data)
+{
+ struct lpe_softc *sc = device_get_softc(dev);
+ uint32_t val;
+
+ debugf("phy=%d reg=%d data=0x%04x\n", phy, reg, data);
+
+ lpe_write_4(sc, LPE_MCMD, LPE_MCMD_WRITE);
+ lpe_write_4(sc, LPE_MADR,
+ (reg & LPE_MADR_REGMASK) << LPE_MADR_REGSHIFT |
+ (phy & LPE_MADR_PHYMASK) << LPE_MADR_PHYSHIFT);
+
+ lpe_write_4(sc, LPE_MWTD, (data & LPE_MWTD_DATAMASK));
+
+ val = lpe_read_4(sc, LPE_MIND);
+
+ /* Wait until request is completed */
+ while (val & LPE_MIND_BUSY) {
+ val = lpe_read_4(sc, LPE_MIND);
+ DELAY(10);
+ }
+
+ return (0);
+}
+
+static void
+lpe_miibus_statchg(device_t dev)
+{
+ struct lpe_softc *sc = device_get_softc(dev);
+ struct mii_data *mii = device_get_softc(sc->lpe_miibus);
+
+ lpe_lock(sc);
+
+ if ((mii->mii_media_status & IFM_ACTIVE) &&
+ (mii->mii_media_status & IFM_AVALID))
+ sc->lpe_flags |= LPE_FLAG_LINK;
+ else
+ sc->lpe_flags &= ~LPE_FLAG_LINK;
+
+ lpe_unlock(sc);
+}
+
+static void
+lpe_reset(struct lpe_softc *sc)
+{
+ uint32_t mac1;
+
+ /* Enter soft reset mode */
+ mac1 = lpe_read_4(sc, LPE_MAC1);
+ lpe_write_4(sc, LPE_MAC1, mac1 | LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX |
+ LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX);
+
+ /* Reset registers, Tx path and Rx path */
+ lpe_write_4(sc, LPE_COMMAND, LPE_COMMAND_REGRESET |
+ LPE_COMMAND_TXRESET | LPE_COMMAND_RXRESET);
+
+ /* Set station address */
+ lpe_write_4(sc, LPE_SA2, sc->lpe_enaddr[1] << 8 | sc->lpe_enaddr[0]);
+ lpe_write_4(sc, LPE_SA1, sc->lpe_enaddr[3] << 8 | sc->lpe_enaddr[2]);
+ lpe_write_4(sc, LPE_SA0, sc->lpe_enaddr[5] << 8 | sc->lpe_enaddr[4]);
+
+ /* Leave soft reset mode */
+ mac1 = lpe_read_4(sc, LPE_MAC1);
+ lpe_write_4(sc, LPE_MAC1, mac1 & ~(LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX |
+ LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX));
+}
+
+static void
+lpe_init(void *arg)
+{
+ struct lpe_softc *sc = (struct lpe_softc *)arg;
+
+ lpe_lock(sc);
+ lpe_init_locked(sc);
+ lpe_unlock(sc);
+}
+
+static void
+lpe_init_locked(struct lpe_softc *sc)
+{
+ struct ifnet *ifp = sc->lpe_ifp;
+ uint32_t cmd, mac1;
+
+ lpe_lock_assert(sc);
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ return;
+
+ /* Enable Tx and Rx */
+ cmd = lpe_read_4(sc, LPE_COMMAND);
+ lpe_write_4(sc, LPE_COMMAND, cmd | LPE_COMMAND_RXENABLE |
+ LPE_COMMAND_TXENABLE | LPE_COMMAND_PASSRUNTFRAME);
+
+ /* Enable receive */
+ mac1 = lpe_read_4(sc, LPE_MAC1);
+ lpe_write_4(sc, LPE_MAC1, /*mac1 |*/ LPE_MAC1_RXENABLE | LPE_MAC1_PASSALL);
+
+ lpe_write_4(sc, LPE_MAC2, LPE_MAC2_CRCENABLE | LPE_MAC2_PADCRCENABLE |
+ LPE_MAC2_FULLDUPLEX);
+
+ lpe_write_4(sc, LPE_MCFG, LPE_MCFG_CLKSEL(7));
+
+ /* Set up Rx filter */
+ lpe_set_rxmode(sc);
+
+ /* Enable interrupts */
+ lpe_write_4(sc, LPE_INTENABLE, LPE_INT_RXOVERRUN | LPE_INT_RXERROR |
+ LPE_INT_RXFINISH | LPE_INT_RXDONE | LPE_INT_TXUNDERRUN |
+ LPE_INT_TXERROR | LPE_INT_TXFINISH | LPE_INT_TXDONE);
+
+ sc->lpe_cdata.lpe_tx_prod = 0;
+ sc->lpe_cdata.lpe_tx_last = 0;
+ sc->lpe_cdata.lpe_tx_used = 0;
+
+ lpe_init_rx(sc);
+
+ /* Initialize Rx packet and status descriptor heads */
+ lpe_write_4(sc, LPE_RXDESC, sc->lpe_rdata.lpe_rx_ring_phys);
+ lpe_write_4(sc, LPE_RXSTATUS, sc->lpe_rdata.lpe_rx_status_phys);
+ lpe_write_4(sc, LPE_RXDESC_NUMBER, LPE_RXDESC_NUM - 1);
+ lpe_write_4(sc, LPE_RXDESC_CONS, 0);
+
+ /* Initialize Tx packet and status descriptor heads */
+ lpe_write_4(sc, LPE_TXDESC, sc->lpe_rdata.lpe_tx_ring_phys);
+ lpe_write_4(sc, LPE_TXSTATUS, sc->lpe_rdata.lpe_tx_status_phys);
+ lpe_write_4(sc, LPE_TXDESC_NUMBER, LPE_TXDESC_NUM - 1);
+ lpe_write_4(sc, LPE_TXDESC_PROD, 0);
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ callout_reset(&sc->lpe_tick, hz, lpe_tick, sc);
+}
+
+static void
+lpe_start(struct ifnet *ifp)
+{
+ struct lpe_softc *sc = (struct lpe_softc *)ifp->if_softc;
+
+ lpe_lock(sc);
+ lpe_start_locked(ifp);
+ lpe_unlock(sc);
+}
+
+static void
+lpe_start_locked(struct ifnet *ifp)
+{
+ struct lpe_softc *sc = (struct lpe_softc *)ifp->if_softc;
+ struct mbuf *m_head;
+ int encap = 0;
+
+ lpe_lock_assert(sc);
+
+ while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+ if (lpe_read_4(sc, LPE_TXDESC_PROD) ==
+ lpe_read_4(sc, LPE_TXDESC_CONS) - 5)
+ break;
+
+ /* Dequeue first packet */
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
+ if (!m_head)
+ break;
+
+ lpe_encap(sc, &m_head);
+
+ encap++;
+ }
+
+ /* Submit new descriptor list */
+ if (encap) {
+ lpe_write_4(sc, LPE_TXDESC_PROD, sc->lpe_cdata.lpe_tx_prod);
+ sc->lpe_watchdog_timer = 5;
+ }
+
+}
+
+static int
+lpe_encap(struct lpe_softc *sc, struct mbuf **m_head)
+{
+ struct lpe_txdesc *txd;
+ struct lpe_hwdesc *hwd;
+ bus_dma_segment_t segs[LPE_MAXFRAGS];
+ int i, err, nsegs, prod;
+
+ lpe_lock_assert(sc);
+ M_ASSERTPKTHDR((*m_head));
+
+ prod = sc->lpe_cdata.lpe_tx_prod;
+ txd = &sc->lpe_cdata.lpe_tx_desc[prod];
+
+ debugf("starting with prod=%d\n", prod);
+
+ err = bus_dmamap_load_mbuf_sg(sc->lpe_cdata.lpe_tx_buf_tag,
+ txd->lpe_txdesc_dmamap, *m_head, segs, &nsegs, BUS_DMA_NOWAIT);
+
+ if (err)
+ return (err);
+
+ if (nsegs == 0) {
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (EIO);
+ }
+
+ bus_dmamap_sync(sc->lpe_cdata.lpe_tx_buf_tag, txd->lpe_txdesc_dmamap,
+ BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(sc->lpe_cdata.lpe_tx_ring_tag, sc->lpe_cdata.lpe_tx_ring_map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ txd->lpe_txdesc_first = 1;
+ txd->lpe_txdesc_mbuf = *m_head;
+
+ for (i = 0; i < nsegs; i++) {
+ hwd = &sc->lpe_rdata.lpe_tx_ring[prod];
+ hwd->lhr_data = segs[i].ds_addr;
+ hwd->lhr_control = segs[i].ds_len - 1;
+
+ if (i == nsegs - 1) {
+ hwd->lhr_control |= LPE_HWDESC_LASTFLAG;
+ hwd->lhr_control |= LPE_HWDESC_INTERRUPT;
+ hwd->lhr_control |= LPE_HWDESC_CRC;
+ hwd->lhr_control |= LPE_HWDESC_PAD;
+ }
+
+ LPE_INC(prod, LPE_TXDESC_NUM);
+ }
+
+ bus_dmamap_sync(sc->lpe_cdata.lpe_tx_ring_tag, sc->lpe_cdata.lpe_tx_ring_map,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ sc->lpe_cdata.lpe_tx_used += nsegs;
+ sc->lpe_cdata.lpe_tx_prod = prod;
+
+ return (0);
+}
+
+static void
+lpe_stop(struct lpe_softc *sc)
+{
+ lpe_lock(sc);
+ lpe_stop_locked(sc);
+ lpe_unlock(sc);
+}
+
+static void
+lpe_stop_locked(struct lpe_softc *sc)
+{
+ lpe_lock_assert(sc);
+
+ callout_stop(&sc->lpe_tick);
+
+ /* Disable interrupts */
+ lpe_write_4(sc, LPE_INTCLEAR, 0xffffffff);
+
+ /* Stop EMAC */
+ lpe_write_4(sc, LPE_MAC1, 0);
+ lpe_write_4(sc, LPE_MAC2, 0);
+ lpe_write_4(sc, LPE_COMMAND, 0);
+
+ sc->lpe_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ sc->lpe_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+}
+
+static int
+lpe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct lpe_softc *sc = ifp->if_softc;
+ struct mii_data *mii = device_get_softc(sc->lpe_miibus);
+ struct ifreq *ifr = (struct ifreq *)data;
+ int err = 0;
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ lpe_lock(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ lpe_set_rxmode(sc);
+ lpe_set_rxfilter(sc);
+ } else
+ lpe_init_locked(sc);
+ } else
+ lpe_stop(sc);
+ lpe_unlock(sc);
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ lpe_lock(sc);
+ lpe_set_rxfilter(sc);
+ lpe_unlock(sc);
+ }
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ err = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ break;
+ default:
+ err = ether_ioctl(ifp, cmd, data);
+ break;
+ }
+
+ return (err);
+}
+
+static void lpe_set_rxmode(struct lpe_softc *sc)
+{
+ struct ifnet *ifp = sc->lpe_ifp;
+ uint32_t rxfilt;
+
+ rxfilt = LPE_RXFILTER_UNIHASH | LPE_RXFILTER_MULTIHASH | LPE_RXFILTER_PERFECT;
+
+ if (ifp->if_flags & IFF_BROADCAST)
+ rxfilt |= LPE_RXFILTER_BROADCAST;
+
+ if (ifp->if_flags & IFF_PROMISC)
+ rxfilt |= LPE_RXFILTER_UNICAST | LPE_RXFILTER_MULTICAST;
+
+ if (ifp->if_flags & IFF_ALLMULTI)
+ rxfilt |= LPE_RXFILTER_MULTICAST;
+
+ lpe_write_4(sc, LPE_RXFILTER_CTRL, rxfilt);
+}
+
+static void lpe_set_rxfilter(struct lpe_softc *sc)
+{
+ struct ifnet *ifp = sc->lpe_ifp;
+ struct ifmultiaddr *ifma;
+ int index;
+ uint32_t hashl, hashh;
+
+ hashl = 0;
+ hashh = 0;
+
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+
+ index = ether_crc32_be(LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr), ETHER_ADDR_LEN) >> 23 & 0x3f;
+
+ if (index > 31)
+ hashh |= (1 << (index - 32));
+ else
+ hashl |= (1 << index);
+ }
+ if_maddr_runlock(ifp);
+
+ /* Program new hash filter */
+ lpe_write_4(sc, LPE_HASHFILTER_L, hashl);
+ lpe_write_4(sc, LPE_HASHFILTER_H, hashh);
+}
+
+static void
+lpe_intr(void *arg)
+{
+ struct lpe_softc *sc = (struct lpe_softc *)arg;
+ uint32_t intstatus;
+
+ debugf("status=0x%08x\n", lpe_read_4(sc, LPE_INTSTATUS));
+
+ lpe_lock(sc);
+
+ while ((intstatus = lpe_read_4(sc, LPE_INTSTATUS))) {
+ if (intstatus & LPE_INT_RXDONE)
+ lpe_rxintr(sc);
+
+ if (intstatus & LPE_INT_TXDONE)
+ lpe_txintr(sc);
+
+ lpe_write_4(sc, LPE_INTCLEAR, 0xffff);
+ }
+
+ lpe_unlock(sc);
+}
+
+static void
+lpe_rxintr(struct lpe_softc *sc)
+{
+ struct ifnet *ifp = sc->lpe_ifp;
+ struct lpe_hwdesc *hwd;
+ struct lpe_hwstatus *hws;
+ struct lpe_rxdesc *rxd;
+ struct mbuf *m;
+ int prod, cons;
+
+ for (;;) {
+ prod = lpe_read_4(sc, LPE_RXDESC_PROD);
+ cons = lpe_read_4(sc, LPE_RXDESC_CONS);
+
+ if (prod == cons)
+ break;
+
+ rxd = &sc->lpe_cdata.lpe_rx_desc[cons];
+ hwd = &sc->lpe_rdata.lpe_rx_ring[cons];
+ hws = &sc->lpe_rdata.lpe_rx_status[cons];
+
+ /* Check received frame for errors */
+ if (hws->lhs_info & LPE_HWDESC_RXERRS) {
+ ifp->if_ierrors++;
+ lpe_discard_rxbuf(sc, cons);
+ lpe_init_rxbuf(sc, cons);
+ goto skip;
+ }
+
+ m = rxd->lpe_rxdesc_mbuf;
+ m->m_pkthdr.rcvif = ifp;
+ m->m_data += 2;
+
+ ifp->if_ipackets++;
+
+ lpe_unlock(sc);
+ (*ifp->if_input)(ifp, m);
+ lpe_lock(sc);
+
+ lpe_init_rxbuf(sc, cons);
+skip:
+ LPE_INC(cons, LPE_RXDESC_NUM);
+ lpe_write_4(sc, LPE_RXDESC_CONS, cons);
+ }
+}
+
+static void
+lpe_txintr(struct lpe_softc *sc)
+{
+ struct ifnet *ifp = sc->lpe_ifp;
+ struct lpe_hwdesc *hwd;
+ struct lpe_hwstatus *hws;
+ struct lpe_txdesc *txd;
+ int cons, last;
+
+ for (;;) {
+ cons = lpe_read_4(sc, LPE_TXDESC_CONS);
+ last = sc->lpe_cdata.lpe_tx_last;
+
+ if (cons == last)
+ break;
+
+ txd = &sc->lpe_cdata.lpe_tx_desc[last];
+ hwd = &sc->lpe_rdata.lpe_tx_ring[last];
+ hws = &sc->lpe_rdata.lpe_tx_status[last];
+
+ bus_dmamap_sync(sc->lpe_cdata.lpe_tx_buf_tag,
+ txd->lpe_txdesc_dmamap, BUS_DMASYNC_POSTWRITE);
+
+ ifp->if_collisions += LPE_HWDESC_COLLISIONS(hws->lhs_info);
+
+ if (hws->lhs_info & LPE_HWDESC_TXERRS)
+ ifp->if_oerrors++;
+ else
+ ifp->if_opackets++;
+
+ if (txd->lpe_txdesc_first) {
+ bus_dmamap_unload(sc->lpe_cdata.lpe_tx_buf_tag,
+ txd->lpe_txdesc_dmamap);
+
+ m_freem(txd->lpe_txdesc_mbuf);
+ txd->lpe_txdesc_mbuf = NULL;
+ txd->lpe_txdesc_first = 0;
+ }
+
+ sc->lpe_cdata.lpe_tx_used--;
+ LPE_INC(sc->lpe_cdata.lpe_tx_last, LPE_TXDESC_NUM);
+ }
+
+ if (!sc->lpe_cdata.lpe_tx_used)
+ sc->lpe_watchdog_timer = 0;
+}
+
+static void
+lpe_tick(void *arg)
+{
+ struct lpe_softc *sc = (struct lpe_softc *)arg;
+ struct mii_data *mii = device_get_softc(sc->lpe_miibus);
+
+ lpe_lock_assert(sc);
+
+ mii_tick(mii);
+ lpe_watchdog(sc);
+
+ callout_reset(&sc->lpe_tick, hz, lpe_tick, sc);
+}
+
+static void
+lpe_watchdog(struct lpe_softc *sc)
+{
+ struct ifnet *ifp = sc->lpe_ifp;
+
+ lpe_lock_assert(sc);
+
+ if (sc->lpe_watchdog_timer == 0 || sc->lpe_watchdog_timer--)
+ return;
+
+ /* Chip has stopped responding */
+ device_printf(sc->lpe_dev, "WARNING: chip hangup, restarting...\n");
+ lpe_stop_locked(sc);
+ lpe_init_locked(sc);
+
+ /* Try to resend packets */
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ lpe_start_locked(ifp);
+}
+
+static int
+lpe_dma_alloc(struct lpe_softc *sc)
+{
+ int err;
+
+ /* Create parent DMA tag */
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(sc->lpe_dev),
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ BUS_SPACE_MAXSIZE_32BIT, 0, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lpe_cdata.lpe_parent_tag);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create parent DMA tag\n");
+ return (err);
+ }
+
+ err = lpe_dma_alloc_rx(sc);
+ if (err)
+ return (err);
+
+ err = lpe_dma_alloc_tx(sc);
+ if (err)
+ return (err);
+
+ return (0);
+}
+
+static int
+lpe_dma_alloc_rx(struct lpe_softc *sc)
+{
+ struct lpe_rxdesc *rxd;
+ struct lpe_dmamap_arg ctx;
+ int err, i;
+
+ /* Create tag for Rx ring */
+ err = bus_dma_tag_create(
+ sc->lpe_cdata.lpe_parent_tag,
+ LPE_DESC_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ LPE_RXDESC_SIZE, 1, /* maxsize, nsegments */
+ LPE_RXDESC_SIZE, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lpe_cdata.lpe_rx_ring_tag);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create Rx ring DMA tag\n");
+ goto fail;
+ }
+
+ /* Create tag for Rx status ring */
+ err = bus_dma_tag_create(
+ sc->lpe_cdata.lpe_parent_tag,
+ LPE_DESC_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ LPE_RXSTATUS_SIZE, 1, /* maxsize, nsegments */
+ LPE_RXSTATUS_SIZE, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lpe_cdata.lpe_rx_status_tag);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create Rx status ring DMA tag\n");
+ goto fail;
+ }
+
+ /* Create tag for Rx buffers */
+ err = bus_dma_tag_create(
+ sc->lpe_cdata.lpe_parent_tag,
+ LPE_DESC_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MCLBYTES * LPE_RXDESC_NUM, /* maxsize */
+ LPE_RXDESC_NUM, /* segments */
+ MCLBYTES, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lpe_cdata.lpe_rx_buf_tag);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create Rx buffers DMA tag\n");
+ goto fail;
+ }
+
+ /* Allocate Rx DMA ring */
+ err = bus_dmamem_alloc(sc->lpe_cdata.lpe_rx_ring_tag,
+ (void **)&sc->lpe_rdata.lpe_rx_ring, BUS_DMA_WAITOK | BUS_DMA_COHERENT |
+ BUS_DMA_ZERO, &sc->lpe_cdata.lpe_rx_ring_map);
+
+ err = bus_dmamap_load(sc->lpe_cdata.lpe_rx_ring_tag,
+ sc->lpe_cdata.lpe_rx_ring_map, sc->lpe_rdata.lpe_rx_ring,
+ LPE_RXDESC_SIZE, lpe_dmamap_cb, &ctx, 0);
+
+ sc->lpe_rdata.lpe_rx_ring_phys = ctx.lpe_dma_busaddr;
+
+ /* Allocate Rx status ring */
+ err = bus_dmamem_alloc(sc->lpe_cdata.lpe_rx_status_tag,
+ (void **)&sc->lpe_rdata.lpe_rx_status, BUS_DMA_WAITOK | BUS_DMA_COHERENT |
+ BUS_DMA_ZERO, &sc->lpe_cdata.lpe_rx_status_map);
+
+ err = bus_dmamap_load(sc->lpe_cdata.lpe_rx_status_tag,
+ sc->lpe_cdata.lpe_rx_status_map, sc->lpe_rdata.lpe_rx_status,
+ LPE_RXDESC_SIZE, lpe_dmamap_cb, &ctx, 0);
+
+ sc->lpe_rdata.lpe_rx_status_phys = ctx.lpe_dma_busaddr;
+
+
+ /* Create Rx buffers DMA map */
+ for (i = 0; i < LPE_RXDESC_NUM; i++) {
+ rxd = &sc->lpe_cdata.lpe_rx_desc[i];
+ rxd->lpe_rxdesc_mbuf = NULL;
+ rxd->lpe_rxdesc_dmamap = NULL;
+
+ err = bus_dmamap_create(sc->lpe_cdata.lpe_rx_buf_tag, 0,
+ &rxd->lpe_rxdesc_dmamap);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create Rx DMA map\n");
+ return (err);
+ }
+ }
+
+ return (0);
+fail:
+ return (err);
+}
+
+static int
+lpe_dma_alloc_tx(struct lpe_softc *sc)
+{
+ struct lpe_txdesc *txd;
+ struct lpe_dmamap_arg ctx;
+ int err, i;
+
+ /* Create tag for Tx ring */
+ err = bus_dma_tag_create(
+ sc->lpe_cdata.lpe_parent_tag,
+ LPE_DESC_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ LPE_TXDESC_SIZE, 1, /* maxsize, nsegments */
+ LPE_TXDESC_SIZE, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lpe_cdata.lpe_tx_ring_tag);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create Tx ring DMA tag\n");
+ goto fail;
+ }
+
+ /* Create tag for Tx status ring */
+ err = bus_dma_tag_create(
+ sc->lpe_cdata.lpe_parent_tag,
+ LPE_DESC_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ LPE_TXSTATUS_SIZE, 1, /* maxsize, nsegments */
+ LPE_TXSTATUS_SIZE, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lpe_cdata.lpe_tx_status_tag);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create Tx status ring DMA tag\n");
+ goto fail;
+ }
+
+ /* Create tag for Tx buffers */
+ err = bus_dma_tag_create(
+ sc->lpe_cdata.lpe_parent_tag,
+ LPE_DESC_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MCLBYTES * LPE_TXDESC_NUM, /* maxsize */
+ LPE_TXDESC_NUM, /* segments */
+ MCLBYTES, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lpe_cdata.lpe_tx_buf_tag);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create Tx buffers DMA tag\n");
+ goto fail;
+ }
+
+ /* Allocate Tx DMA ring */
+ err = bus_dmamem_alloc(sc->lpe_cdata.lpe_tx_ring_tag,
+ (void **)&sc->lpe_rdata.lpe_tx_ring, BUS_DMA_WAITOK | BUS_DMA_COHERENT |
+ BUS_DMA_ZERO, &sc->lpe_cdata.lpe_tx_ring_map);
+
+ err = bus_dmamap_load(sc->lpe_cdata.lpe_tx_ring_tag,
+ sc->lpe_cdata.lpe_tx_ring_map, sc->lpe_rdata.lpe_tx_ring,
+ LPE_RXDESC_SIZE, lpe_dmamap_cb, &ctx, 0);
+
+ sc->lpe_rdata.lpe_tx_ring_phys = ctx.lpe_dma_busaddr;
+
+ /* Allocate Tx status ring */
+ err = bus_dmamem_alloc(sc->lpe_cdata.lpe_tx_status_tag,
+ (void **)&sc->lpe_rdata.lpe_tx_status, BUS_DMA_WAITOK | BUS_DMA_COHERENT |
+ BUS_DMA_ZERO, &sc->lpe_cdata.lpe_tx_status_map);
+
+ err = bus_dmamap_load(sc->lpe_cdata.lpe_tx_status_tag,
+ sc->lpe_cdata.lpe_tx_status_map, sc->lpe_rdata.lpe_tx_status,
+ LPE_RXDESC_SIZE, lpe_dmamap_cb, &ctx, 0);
+
+ sc->lpe_rdata.lpe_tx_status_phys = ctx.lpe_dma_busaddr;
+
+
+ /* Create Tx buffers DMA map */
+ for (i = 0; i < LPE_TXDESC_NUM; i++) {
+ txd = &sc->lpe_cdata.lpe_tx_desc[i];
+ txd->lpe_txdesc_mbuf = NULL;
+ txd->lpe_txdesc_dmamap = NULL;
+ txd->lpe_txdesc_first = 0;
+
+ err = bus_dmamap_create(sc->lpe_cdata.lpe_tx_buf_tag, 0,
+ &txd->lpe_txdesc_dmamap);
+
+ if (err) {
+ device_printf(sc->lpe_dev, "cannot create Tx DMA map\n");
+ return (err);
+ }
+ }
+
+ return (0);
+fail:
+ return (err);
+}
+
+static int
+lpe_init_rx(struct lpe_softc *sc)
+{
+ int i, err;
+
+ for (i = 0; i < LPE_RXDESC_NUM; i++) {
+ err = lpe_init_rxbuf(sc, i);
+ if (err)
+ return (err);
+ }
+
+ return (0);
+}
+
+static int
+lpe_init_rxbuf(struct lpe_softc *sc, int n)
+{
+ struct lpe_rxdesc *rxd;
+ struct lpe_hwdesc *hwd;
+ struct lpe_hwstatus *hws;
+ struct mbuf *m;
+ bus_dma_segment_t segs[1];
+ int nsegs;
+
+ rxd = &sc->lpe_cdata.lpe_rx_desc[n];
+ hwd = &sc->lpe_rdata.lpe_rx_ring[n];
+ hws = &sc->lpe_rdata.lpe_rx_status[n];
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+
+ if (!m) {
+ device_printf(sc->lpe_dev, "WARNING: mbufs exhausted!\n");
+ return (ENOBUFS);
+ }
+
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
+
+ bus_dmamap_unload(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap);
+
+ if (bus_dmamap_load_mbuf_sg(sc->lpe_cdata.lpe_rx_buf_tag,
+ rxd->lpe_rxdesc_dmamap, m, segs, &nsegs, 0)) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+
+ bus_dmamap_sync(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap,
+ BUS_DMASYNC_PREREAD);
+
+ rxd->lpe_rxdesc_mbuf = m;
+ hwd->lhr_data = segs[0].ds_addr + 2;
+ hwd->lhr_control = (segs[0].ds_len - 1) | LPE_HWDESC_INTERRUPT;
+
+ return (0);
+}
+
+static void
+lpe_discard_rxbuf(struct lpe_softc *sc, int n)
+{
+ struct lpe_rxdesc *rxd;
+ struct lpe_hwdesc *hwd;
+
+ rxd = &sc->lpe_cdata.lpe_rx_desc[n];
+ hwd = &sc->lpe_rdata.lpe_rx_ring[n];
+
+ bus_dmamap_unload(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap);
+
+ hwd->lhr_data = 0;
+ hwd->lhr_control = 0;
+
+ if (rxd->lpe_rxdesc_mbuf) {
+ m_freem(rxd->lpe_rxdesc_mbuf);
+ rxd->lpe_rxdesc_mbuf = NULL;
+ }
+}
+
+static void
+lpe_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ struct lpe_dmamap_arg *ctx;
+
+ if (error)
+ return;
+
+ ctx = (struct lpe_dmamap_arg *)arg;
+ ctx->lpe_dma_busaddr = segs[0].ds_addr;
+}
+
+static int
+lpe_ifmedia_upd(struct ifnet *ifp)
+{
+ return (0);
+}
+
+static void
+lpe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct lpe_softc *sc = ifp->if_softc;
+ struct mii_data *mii = device_get_softc(sc->lpe_miibus);
+
+ lpe_lock(sc);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ lpe_unlock(sc);
+}
+
+static device_method_t lpe_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpe_probe),
+ DEVMETHOD(device_attach, lpe_attach),
+ DEVMETHOD(device_detach, lpe_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, lpe_miibus_readreg),
+ DEVMETHOD(miibus_writereg, lpe_miibus_writereg),
+ DEVMETHOD(miibus_statchg, lpe_miibus_statchg),
+ { 0, 0 }
+};
+
+static driver_t lpe_driver = {
+ "lpe",
+ lpe_methods,
+ sizeof(struct lpe_softc),
+};
+
+static devclass_t lpe_devclass;
+
+DRIVER_MODULE(lpe, simplebus, lpe_driver, lpe_devclass, 0, 0);
+DRIVER_MODULE(miibus, lpe, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(lpe, obio, 1, 1, 1);
+MODULE_DEPEND(lpe, miibus, 1, 1, 1);
+MODULE_DEPEND(lpe, ether, 1, 1, 1);
Property changes on: trunk/sys/arm/lpc/if_lpe.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/if_lpereg.h
===================================================================
--- trunk/sys/arm/lpc/if_lpereg.h (rev 0)
+++ trunk/sys/arm/lpc/if_lpereg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,209 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/lpc/if_lpereg.h 261455 2014-02-04 03:36:42Z eadler $
+ */
+
+#ifndef _ARM_LPC_IF_LPEREG_H
+#define _ARM_LPC_IF_LPEREG_H
+
+#define LPE_MAC1 0x000
+#define LPE_MAC1_RXENABLE (1 << 0)
+#define LPE_MAC1_PASSALL (1 << 1)
+#define LPE_MAC1_RXFLOWCTRL (1 << 2)
+#define LPE_MAC1_TXFLOWCTRL (1 << 3)
+#define LPE_MAC1_LOOPBACK (1 << 4)
+#define LPE_MAC1_RESETTX (1 << 8)
+#define LPE_MAC1_RESETMCSTX (1 << 9)
+#define LPE_MAC1_RESETRX (1 << 10)
+#define LPE_MAC1_RESETMCSRX (1 << 11)
+#define LPE_MAC1_SIMRESET (1 << 14)
+#define LPE_MAC1_SOFTRESET (1 << 15)
+#define LPE_MAC2 0x004
+#define LPE_MAC2_FULLDUPLEX (1 << 0)
+#define LPE_MAC2_FRAMELENCHECK (1 << 1)
+#define LPE_MAC2_HUGEFRAME (1 << 2)
+#define LPE_MAC2_DELAYEDCRC (1 << 3)
+#define LPE_MAC2_CRCENABLE (1 << 4)
+#define LPE_MAC2_PADCRCENABLE (1 << 5)
+#define LPE_MAC2_VLANPADENABLE (1 << 6)
+#define LPE_MAC2_AUTOPADENABLE (1 << 7)
+#define LPE_MAC2_PUREPREAMBLE (1 << 8)
+#define LPE_MAC2_LONGPREAMBLE (1 << 9)
+#define LPE_MAC2_NOBACKOFF (1 << 12)
+#define LPE_MAC2_BACKPRESSURE (1 << 13)
+#define LPE_MAC2_EXCESSDEFER (1 << 14)
+#define LPE_IPGT 0x008
+#define LPE_IPGR 0x00c
+#define LPE_CLRT 0x010
+#define LPE_MAXF 0x014
+#define LPE_SUPP 0x018
+#define LPE_SUPP_SPEED (1 << 8)
+#define LPE_TEST 0x01c
+#define LPE_MCFG 0x020
+#define LPE_MCFG_SCANINCR (1 << 0)
+#define LPE_MCFG_SUPPREAMBLE (1 << 1)
+#define LPE_MCFG_CLKSEL(_n) ((_n & 0x7) << 2)
+#define LPC_MCFG_RESETMII (1 << 15)
+#define LPE_MCMD 0x024
+#define LPE_MCMD_READ (1 << 0)
+#define LPE_MCMD_WRITE (0 << 0)
+#define LPE_MCMD_SCAN (1 << 1)
+#define LPE_MADR 0x028
+#define LPE_MADR_REGMASK 0x1f
+#define LPE_MADR_REGSHIFT 0
+#define LPE_MADR_PHYMASK 0x1f
+#define LPE_MADR_PHYSHIFT 8
+#define LPE_MWTD 0x02c
+#define LPE_MWTD_DATAMASK 0xffff
+#define LPE_MRDD 0x030
+#define LPE_MRDD_DATAMASK 0xffff
+#define LPE_MIND 0x034
+#define LPE_MIND_BUSY (1 << 0)
+#define LPE_MIND_SCANNING (1 << 1)
+#define LPE_MIND_INVALID (1 << 2)
+#define LPE_MIND_MIIFAIL (1 << 3)
+#define LPE_SA0 0x040
+#define LPE_SA1 0x044
+#define LPE_SA2 0x048
+#define LPE_COMMAND 0x100
+#define LPE_COMMAND_RXENABLE (1 << 0)
+#define LPE_COMMAND_TXENABLE (1 << 1)
+#define LPE_COMMAND_REGRESET (1 << 3)
+#define LPE_COMMAND_TXRESET (1 << 4)
+#define LPE_COMMAND_RXRESET (1 << 5)
+#define LPE_COMMAND_PASSRUNTFRAME (1 << 6)
+#define LPE_COMMAND_PASSRXFILTER (1 << 7)
+#define LPE_COMMAND_TXFLOWCTL (1 << 8)
+#define LPE_COMMAND_RMII (1 << 9)
+#define LPE_COMMAND_FULLDUPLEX (1 << 10)
+#define LPE_STATUS 0x104
+#define LPE_STATUS_RXACTIVE (1 << 0)
+#define LPE_STATUS_TXACTIVE (1 << 1)
+#define LPE_RXDESC 0x108
+#define LPE_RXSTATUS 0x10c
+#define LPE_RXDESC_NUMBER 0x110
+#define LPE_RXDESC_PROD 0x114
+#define LPE_RXDESC_CONS 0x118
+#define LPE_TXDESC 0x11c
+#define LPE_TXSTATUS 0x120
+#define LPE_TXDESC_NUMBER 0x124
+#define LPE_TXDESC_PROD 0x128
+#define LPE_TXDESC_CONS 0x12c
+#define LPE_TSV0 0x158
+#define LPE_TSV1 0x15c
+#define LPE_RSV 0x160
+#define LPE_FLOWCONTROL_COUNTER 0x170
+#define LPE_FLOWCONTROL_STATUS 0x174
+#define LPE_RXFILTER_CTRL 0x200
+#define LPE_RXFILTER_UNICAST (1 << 0)
+#define LPE_RXFILTER_BROADCAST (1 << 1)
+#define LPE_RXFILTER_MULTICAST (1 << 2)
+#define LPE_RXFILTER_UNIHASH (1 << 3)
+#define LPE_RXFILTER_MULTIHASH (1 << 4)
+#define LPE_RXFILTER_PERFECT (1 << 5)
+#define LPE_RXFILTER_WOL (1 << 12)
+#define LPE_RXFILTER_FILTWOL (1 << 13)
+#define LPE_RXFILTER_WOL_STATUS 0x204
+#define LPE_RXFILTER_WOL_CLEAR 0x208
+#define LPE_HASHFILTER_L 0x210
+#define LPE_HASHFILTER_H 0x214
+#define LPE_INTSTATUS 0xfe0
+#define LPE_INTENABLE 0xfe4
+#define LPE_INTCLEAR 0xfe8
+#define LPE_INTSET 0xfec
+#define LPE_INT_RXOVERRUN (1 << 0)
+#define LPE_INT_RXERROR (1 << 1)
+#define LPE_INT_RXFINISH (1 << 2)
+#define LPE_INT_RXDONE (1 << 3)
+#define LPE_INT_TXUNDERRUN (1 << 4)
+#define LPE_INT_TXERROR (1 << 5)
+#define LPE_INT_TXFINISH (1 << 6)
+#define LPE_INT_TXDONE (1 << 7)
+#define LPE_INT_SOFTINT (1 << 12)
+#define LPE_INTWAKEUPINT (1 << 13)
+#define LPE_POWERDOWN 0xff4
+
+#define LPE_DESC_ALIGN 8
+#define LPE_TXDESC_NUM 128
+#define LPE_RXDESC_NUM 128
+#define LPE_TXDESC_SIZE (LPE_TXDESC_NUM * sizeof(struct lpe_hwdesc))
+#define LPE_RXDESC_SIZE (LPE_RXDESC_NUM * sizeof(struct lpe_hwdesc))
+#define LPE_TXSTATUS_SIZE (LPE_TXDESC_NUM * sizeof(struct lpe_hwstatus))
+#define LPE_RXSTATUS_SIZE (LPE_RXDESC_NUM * sizeof(struct lpe_hwstatus))
+#define LPE_MAXFRAGS 8
+
+struct lpe_hwdesc {
+ uint32_t lhr_data;
+ uint32_t lhr_control;
+};
+
+struct lpe_hwstatus {
+ uint32_t lhs_info;
+ uint32_t lhs_crc;
+};
+
+#define LPE_INC(x, y) (x) = ((x) == ((y)-1)) ? 0 : (x)+1
+
+/* These are valid for both Rx and Tx descriptors */
+#define LPE_HWDESC_SIZE_MASK (1 << 10)
+#define LPE_HWDESC_INTERRUPT (1U << 31)
+
+/* These are valid for Tx descriptors */
+#define LPE_HWDESC_LAST (1 << 30)
+#define LPE_HWDESC_CRC (1 << 29)
+#define LPE_HWDESC_PAD (1 << 28)
+#define LPE_HWDESC_HUGE (1 << 27)
+#define LPE_HWDESC_OVERRIDE (1 << 26)
+
+/* These are valid for Tx status descriptors */
+#define LPE_HWDESC_COLLISIONS(_n) (((_n) >> 21) & 0x7)
+#define LPE_HWDESC_DEFER (1 << 25)
+#define LPE_HWDESC_EXCDEFER (1 << 26)
+#define LPE_HWDESC_EXCCOLL (1 << 27)
+#define LPE_HWDESC_LATECOLL (1 << 28)
+#define LPE_HWDESC_UNDERRUN (1 << 29)
+#define LPE_HWDESC_TXNODESCR (1 << 30)
+#define LPE_HWDESC_ERROR (1U << 31)
+
+/* These are valid for Rx status descriptors */
+#define LPE_HWDESC_CONTROL (1 << 18)
+#define LPE_HWDESC_VLAN (1 << 19)
+#define LPE_HWDESC_FAILFILTER (1 << 20)
+#define LPE_HWDESC_MULTICAST (1 << 21)
+#define LPE_HWDESC_BROADCAST (1 << 22)
+#define LPE_HWDESC_CRCERROR (1 << 23)
+#define LPE_HWDESC_SYMBOLERROR (1 << 24)
+#define LPE_HWDESC_LENGTHERROR (1 << 25)
+#define LPE_HWDESC_RANGEERROR (1 << 26)
+#define LPE_HWDESC_ALIGNERROR (1 << 27)
+#define LPE_HWDESC_OVERRUN (1 << 28)
+#define LPE_HWDESC_RXNODESCR (1 << 29)
+#define LPE_HWDESC_LASTFLAG (1 << 30)
+#define LPE_HWDESC_ERROR (1U << 31)
+
+
+#endif /* _ARM_LPC_IF_LPEREG_H */
Property changes on: trunk/sys/arm/lpc/if_lpereg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_dmac.c
===================================================================
--- trunk/sys/arm/lpc/lpc_dmac.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_dmac.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,293 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_dmac.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <sys/kdb.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+struct lpc_dmac_channel
+{
+ struct lpc_dmac_channel_config *ldc_config;
+ int ldc_flags;
+};
+
+struct lpc_dmac_softc
+{
+ device_t ld_dev;
+ struct mtx ld_mtx;
+ struct resource * ld_mem_res;
+ struct resource * ld_irq_res;
+ bus_space_tag_t ld_bst;
+ bus_space_handle_t ld_bsh;
+ void * ld_intrhand;
+ struct lpc_dmac_channel ld_channels[8];
+};
+
+static struct lpc_dmac_softc *lpc_dmac_sc = NULL;
+
+static int lpc_dmac_probe(device_t);
+static int lpc_dmac_attach(device_t);
+static void lpc_dmac_intr(void *);
+
+#define lpc_dmac_read_4(_sc, _reg) \
+ bus_space_read_4(_sc->ld_bst, _sc->ld_bsh, _reg)
+#define lpc_dmac_write_4(_sc, _reg, _value) \
+ bus_space_write_4(_sc->ld_bst, _sc->ld_bsh, _reg, _value)
+#define lpc_dmac_read_ch_4(_sc, _n, _reg) \
+ bus_space_read_4(_sc->ld_bst, _sc->ld_bsh, (_reg + LPC_DMAC_CHADDR(_n)))
+#define lpc_dmac_write_ch_4(_sc, _n, _reg, _value) \
+ bus_space_write_4(_sc->ld_bst, _sc->ld_bsh, (_reg + LPC_DMAC_CHADDR(_n)), _value)
+
+static int lpc_dmac_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,dmac"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 General Purpose DMA controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int lpc_dmac_attach(device_t dev)
+{
+ struct lpc_dmac_softc *sc = device_get_softc(dev);
+ int rid;
+
+ rid = 0;
+ sc->ld_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->ld_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->ld_bst = rman_get_bustag(sc->ld_mem_res);
+ sc->ld_bsh = rman_get_bushandle(sc->ld_mem_res);
+
+ rid = 0;
+ sc->ld_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->ld_irq_res) {
+ device_printf(dev, "cannot allocate cmd interrupt\n");
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->ld_mem_res);
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->ld_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, lpc_dmac_intr, sc, &sc->ld_intrhand))
+ {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->ld_mem_res);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ld_irq_res);
+ device_printf(dev, "cannot setup interrupt handler\n");
+ return (ENXIO);
+ }
+
+ lpc_dmac_sc = sc;
+
+ lpc_pwr_write(dev, LPC_CLKPWR_DMACLK_CTRL, LPC_CLKPWR_DMACLK_CTRL_EN);
+ lpc_dmac_write_4(sc, LPC_DMAC_CONFIG, LPC_DMAC_CONFIG_ENABLE);
+
+ lpc_dmac_write_4(sc, LPC_DMAC_INTTCCLEAR, 0xff);
+ lpc_dmac_write_4(sc, LPC_DMAC_INTERRCLEAR, 0xff);
+
+ return (0);
+}
+
+static void lpc_dmac_intr(void *arg)
+{
+ struct lpc_dmac_softc *sc = (struct lpc_dmac_softc *)arg;
+ struct lpc_dmac_channel *ch;
+ uint32_t intstat, tcstat, errstat;
+ int i;
+
+ do {
+ intstat = lpc_dmac_read_4(sc, LPC_DMAC_INTSTAT);
+
+ for (i = 0; i < LPC_DMAC_CHNUM; i++) {
+ if ((intstat & (1 << i)) == 0)
+ continue;
+
+ ch = &sc->ld_channels[i];
+ tcstat = lpc_dmac_read_4(sc, LPC_DMAC_INTTCSTAT);
+ errstat = lpc_dmac_read_4(sc, LPC_DMAC_INTERRSTAT);
+
+ if (tcstat & (1 << i)) {
+ ch->ldc_config->ldc_success_handler(
+ ch->ldc_config->ldc_handler_arg);
+ lpc_dmac_write_4(sc, LPC_DMAC_INTTCCLEAR, (1 << i));
+ }
+
+ if (errstat & (1 << i)) {
+ ch->ldc_config->ldc_error_handler(
+ ch->ldc_config->ldc_handler_arg);
+ lpc_dmac_write_4(sc, LPC_DMAC_INTERRCLEAR, (1 << i));
+ }
+ }
+
+ } while (intstat);
+}
+
+int
+lpc_dmac_config_channel(device_t dev, int chno, struct lpc_dmac_channel_config *cfg)
+{
+ struct lpc_dmac_softc *sc = lpc_dmac_sc;
+ struct lpc_dmac_channel *ch;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ ch = &sc->ld_channels[chno];
+ ch->ldc_config = cfg;
+
+ return 0;
+}
+
+int
+lpc_dmac_setup_transfer(device_t dev, int chno, bus_addr_t src, bus_addr_t dst,
+ bus_size_t size, int flags)
+{
+ struct lpc_dmac_softc *sc = lpc_dmac_sc;
+ struct lpc_dmac_channel *ch;
+ uint32_t ctrl, cfg;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ ch = &sc->ld_channels[chno];
+
+ ctrl = LPC_DMAC_CH_CONTROL_I |
+ (ch->ldc_config->ldc_dst_incr ? LPC_DMAC_CH_CONTROL_DI : 0) |
+ (ch->ldc_config->ldc_src_incr ? LPC_DMAC_CH_CONTROL_SI : 0) |
+ LPC_DMAC_CH_CONTROL_DWIDTH(ch->ldc_config->ldc_dst_width) |
+ LPC_DMAC_CH_CONTROL_SWIDTH(ch->ldc_config->ldc_src_width) |
+ LPC_DMAC_CH_CONTROL_DBSIZE(ch->ldc_config->ldc_dst_burst) |
+ LPC_DMAC_CH_CONTROL_SBSIZE(ch->ldc_config->ldc_src_burst) |
+ size;
+
+ cfg = LPC_DMAC_CH_CONFIG_ITC | LPC_DMAC_CH_CONFIG_IE |
+ LPC_DMAC_CH_CONFIG_FLOWCNTL(ch->ldc_config->ldc_fcntl) |
+ LPC_DMAC_CH_CONFIG_DESTP(ch->ldc_config->ldc_dst_periph) |
+ LPC_DMAC_CH_CONFIG_SRCP(ch->ldc_config->ldc_src_periph) | LPC_DMAC_CH_CONFIG_E;
+ lpc_dmac_write_ch_4(sc, chno, LPC_DMAC_CH_SRCADDR, src);
+ lpc_dmac_write_ch_4(sc, chno, LPC_DMAC_CH_DSTADDR, dst);
+ lpc_dmac_write_ch_4(sc, chno, LPC_DMAC_CH_LLI, 0);
+ lpc_dmac_write_ch_4(sc, chno, LPC_DMAC_CH_CONTROL, ctrl);
+ lpc_dmac_write_ch_4(sc, chno, LPC_DMAC_CH_CONFIG, cfg);
+
+ return 0;
+}
+
+int
+lpc_dmac_enable_channel(device_t dev, int chno)
+{
+ struct lpc_dmac_softc *sc = lpc_dmac_sc;
+ uint32_t cfg;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ cfg = lpc_dmac_read_ch_4(sc, chno, LPC_DMAC_CH_CONFIG);
+ cfg |= LPC_DMAC_CH_CONFIG_E;
+
+ lpc_dmac_write_ch_4(sc, chno, LPC_DMAC_CH_CONFIG, cfg);
+
+ return 0;
+}
+
+int
+lpc_dmac_disable_channel(device_t dev, int chno)
+{
+ struct lpc_dmac_softc *sc = lpc_dmac_sc;
+ uint32_t cfg;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ cfg = lpc_dmac_read_ch_4(sc, chno, LPC_DMAC_CH_CONFIG);
+ cfg &= ~LPC_DMAC_CH_CONFIG_E;
+
+ lpc_dmac_write_ch_4(sc, chno, LPC_DMAC_CH_CONFIG, cfg);
+
+ return 0;
+}
+
+int
+lpc_dmac_start_burst(device_t dev, int id)
+{
+ struct lpc_dmac_softc *sc = lpc_dmac_sc;
+
+ lpc_dmac_write_4(sc, LPC_DMAC_SOFTBREQ, (1 << id));
+ return (0);
+}
+
+static device_method_t lpc_dmac_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpc_dmac_probe),
+ DEVMETHOD(device_attach, lpc_dmac_attach),
+
+ { 0, 0 },
+};
+
+static devclass_t lpc_dmac_devclass;
+
+static driver_t lpc_dmac_driver = {
+ "dmac",
+ lpc_dmac_methods,
+ sizeof(struct lpc_dmac_softc),
+};
+
+DRIVER_MODULE(dmac, simplebus, lpc_dmac_driver, lpc_dmac_devclass, 0, 0);
Property changes on: trunk/sys/arm/lpc/lpc_dmac.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_fb.c
===================================================================
--- trunk/sys/arm/lpc/lpc_fb.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_fb.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,470 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_fb.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+
+struct lpc_fb_dmamap_arg {
+ bus_addr_t lf_dma_busaddr;
+};
+
+struct lpc_lcd_config {
+ int lc_xres;
+ int lc_yres;
+ int lc_bpp;
+ uint32_t lc_pixelclock;
+ int lc_left_margin;
+ int lc_right_margin;
+ int lc_upper_margin;
+ int lc_lower_margin;
+ int lc_hsync_len;
+ int lc_vsync_len;
+};
+
+struct lpc_fb_softc {
+ device_t lf_dev;
+ struct cdev * lf_cdev;
+ struct mtx lf_mtx;
+ struct resource * lf_mem_res;
+ struct resource * lf_irq_res;
+ bus_space_tag_t lf_bst;
+ bus_space_handle_t lf_bsh;
+ void * lf_intrhand;
+ bus_dma_tag_t lf_dma_tag;
+ bus_dmamap_t lf_dma_map;
+ void * lf_buffer;
+ bus_addr_t lf_buffer_phys;
+ bus_size_t lf_buffer_size;
+ struct lpc_lcd_config lf_lcd_config;
+ int lf_initialized;
+ int lf_opened;
+};
+
+extern void ssd1289_configure(void);
+
+#define lpc_fb_lock(_sc) mtx_lock(&(_sc)->lf_mtx)
+#define lpc_fb_unlock(_sc) mtx_unlock(&(_sc)->lf_mtx)
+#define lpc_fb_lock_assert(sc) mtx_assert(&(_sc)->lf_mtx, MA_OWNED)
+
+#define lpc_fb_read_4(_sc, _reg) \
+ bus_space_read_4((_sc)->lf_bst, (_sc)->lf_bsh, (_reg))
+#define lpc_fb_write_4(_sc, _reg, _val) \
+ bus_space_write_4((_sc)->lf_bst, (_sc)->lf_bsh, (_reg), (_val))
+
+
+
+static int lpc_fb_probe(device_t);
+static int lpc_fb_attach(device_t);
+static void lpc_fb_intr(void *);
+static void lpc_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err);
+
+static int lpc_fb_fdt_read(phandle_t, const char *, uint32_t *);
+static int lpc_fb_read_lcd_config(phandle_t, struct lpc_lcd_config *);
+
+static int lpc_fb_open(struct cdev *, int, int, struct thread *);
+static int lpc_fb_close(struct cdev *, int, int, struct thread *);
+static int lpc_fb_ioctl(struct cdev *, u_long, caddr_t, int, struct thread *);
+static int lpc_fb_mmap(struct cdev *, vm_ooffset_t, vm_paddr_t *, int, vm_memattr_t *);
+
+static void lpc_fb_blank(struct lpc_fb_softc *);
+
+static struct cdevsw lpc_fb_cdevsw = {
+ .d_open = lpc_fb_open,
+ .d_close = lpc_fb_close,
+ .d_ioctl = lpc_fb_ioctl,
+ .d_mmap = lpc_fb_mmap,
+ .d_name = "lpcfb",
+ .d_version = D_VERSION,
+};
+
+static int
+lpc_fb_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,fb"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 framebuffer device");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_fb_attach(device_t dev)
+{
+ struct lpc_fb_softc *sc = device_get_softc(dev);
+ struct lpc_fb_dmamap_arg ctx;
+ phandle_t node;
+ int mode, rid, err = 0;
+
+ sc->lf_dev = dev;
+ mtx_init(&sc->lf_mtx, "lpcfb", "fb", MTX_DEF);
+
+ rid = 0;
+ sc->lf_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->lf_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->lf_bst = rman_get_bustag(sc->lf_mem_res);
+ sc->lf_bsh = rman_get_bushandle(sc->lf_mem_res);
+
+ rid = 0;
+ sc->lf_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->lf_irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lf_mem_res);
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->lf_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, lpc_fb_intr, sc, &sc->lf_intrhand))
+ {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lf_mem_res);
+ bus_release_resource(dev, SYS_RES_IRQ, 1, sc->lf_irq_res);
+ device_printf(dev, "cannot setup interrupt handler\n");
+ return (ENXIO);
+ }
+
+ node = ofw_bus_get_node(dev);
+
+ err = lpc_fb_read_lcd_config(node, &sc->lf_lcd_config);
+ if (err) {
+ device_printf(dev, "cannot read LCD configuration\n");
+ goto fail;
+ }
+
+ sc->lf_buffer_size = sc->lf_lcd_config.lc_xres *
+ sc->lf_lcd_config.lc_yres *
+ (sc->lf_lcd_config.lc_bpp == 24 ? 3 : 2);
+
+ device_printf(dev, "%dx%d LCD, %d bits per pixel, %dkHz pixel clock\n",
+ sc->lf_lcd_config.lc_xres, sc->lf_lcd_config.lc_yres,
+ sc->lf_lcd_config.lc_bpp, sc->lf_lcd_config.lc_pixelclock / 1000);
+
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(sc->lf_dev),
+ 4, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ sc->lf_buffer_size, 1, /* maxsize, nsegments */
+ sc->lf_buffer_size, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lf_dma_tag);
+
+ err = bus_dmamem_alloc(sc->lf_dma_tag, (void **)&sc->lf_buffer,
+ 0, &sc->lf_dma_map);
+ if (err) {
+ device_printf(dev, "cannot allocate framebuffer\n");
+ goto fail;
+ }
+
+ err = bus_dmamap_load(sc->lf_dma_tag, sc->lf_dma_map, sc->lf_buffer,
+ sc->lf_buffer_size, lpc_fb_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
+ if (err) {
+ device_printf(dev, "cannot load DMA map\n");
+ goto fail;
+ }
+
+ switch (sc->lf_lcd_config.lc_bpp) {
+ case 12:
+ mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_12;
+ break;
+ case 15:
+ mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_15;
+ break;
+ case 16:
+ mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_16;
+ break;
+ case 24:
+ mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_24;
+ break;
+ default:
+ panic("unsupported bpp");
+ }
+
+ lpc_pwr_write(sc->lf_dev, LPC_CLKPWR_LCDCLK_CTRL,
+ LPC_CLKPWR_LCDCLK_CTRL_MODE(mode) |
+ LPC_CLKPWR_LCDCLK_CTRL_HCLKEN);
+
+ sc->lf_buffer_phys = ctx.lf_dma_busaddr;
+ sc->lf_cdev = make_dev(&lpc_fb_cdevsw, 0, UID_ROOT, GID_WHEEL,
+ 0600, "lpcfb");
+
+ sc->lf_cdev->si_drv1 = sc;
+
+ return (0);
+fail:
+ return (ENXIO);
+}
+
+static void
+lpc_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ struct lpc_fb_dmamap_arg *ctx;
+
+ if (err)
+ return;
+
+ ctx = (struct lpc_fb_dmamap_arg *)arg;
+ ctx->lf_dma_busaddr = segs[0].ds_addr;
+}
+
+static void
+lpc_fb_intr(void *arg)
+{
+}
+
+static int
+lpc_fb_fdt_read(phandle_t node, const char *name, uint32_t *ret)
+{
+ if (OF_getprop(node, name, ret, sizeof(uint32_t)) <= 0)
+ return (ENOENT);
+
+ *ret = fdt32_to_cpu(*ret);
+ return (0);
+}
+
+static int
+lpc_fb_read_lcd_config(phandle_t node, struct lpc_lcd_config *cfg)
+{
+ if (lpc_fb_fdt_read(node, "horizontal-resolution", &cfg->lc_xres))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "vertical-resolution", &cfg->lc_yres))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "bits-per-pixel", &cfg->lc_bpp))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "pixel-clock", &cfg->lc_pixelclock))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "left-margin", &cfg->lc_left_margin))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "right-margin", &cfg->lc_right_margin))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "upper-margin", &cfg->lc_upper_margin))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "lower-margin", &cfg->lc_lower_margin))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "hsync-len", &cfg->lc_hsync_len))
+ return (ENXIO);
+
+ if (lpc_fb_fdt_read(node, "vsync-len", &cfg->lc_vsync_len))
+ return (ENXIO);
+
+ return (0);
+}
+
+static void
+lpc_fb_setup(struct lpc_fb_softc *sc)
+{
+ struct lpc_lcd_config *cfg = &sc->lf_lcd_config;
+ uint32_t bpp;
+
+ lpc_fb_write_4(sc, LPC_LCD_TIMH,
+ LPC_LCD_TIMH_PPL(cfg->lc_xres) |
+ LPC_LCD_TIMH_HSW(cfg->lc_hsync_len - 1) |
+ LPC_LCD_TIMH_HFP(cfg->lc_right_margin - 1) |
+ LPC_LCD_TIMH_HBP(cfg->lc_left_margin - 1));
+
+ lpc_fb_write_4(sc, LPC_LCD_TIMV,
+ LPC_LCD_TIMV_LPP(cfg->lc_yres - 1) |
+ LPC_LCD_TIMV_VSW(cfg->lc_vsync_len - 1) |
+ LPC_LCD_TIMV_VFP(cfg->lc_lower_margin) |
+ LPC_LCD_TIMV_VBP(cfg->lc_upper_margin));
+
+ /* XXX LPC_LCD_POL_PCD_LO */
+ lpc_fb_write_4(sc, LPC_LCD_POL,
+ LPC_LCD_POL_IHS | LPC_LCD_POL_IVS |
+ LPC_LCD_POL_CPL(cfg->lc_xres - 1) |
+ LPC_LCD_POL_PCD_LO(4));
+
+ lpc_fb_write_4(sc, LPC_LCD_UPBASE, sc->lf_buffer_phys);
+
+ switch (cfg->lc_bpp) {
+ case 1:
+ bpp = LPC_LCD_CTRL_BPP1;
+ break;
+ case 2:
+ bpp = LPC_LCD_CTRL_BPP2;
+ break;
+ case 4:
+ bpp = LPC_LCD_CTRL_BPP4;
+ break;
+ case 8:
+ bpp = LPC_LCD_CTRL_BPP8;
+ break;
+ case 12:
+ bpp = LPC_LCD_CTRL_BPP12_444;
+ break;
+ case 15:
+ bpp = LPC_LCD_CTRL_BPP16;
+ break;
+ case 16:
+ bpp = LPC_LCD_CTRL_BPP16_565;
+ break;
+ case 24:
+ bpp = LPC_LCD_CTRL_BPP24;
+ break;
+ default:
+ panic("LCD unknown bpp: %d", cfg->lc_bpp);
+ }
+
+ lpc_fb_write_4(sc, LPC_LCD_CTRL,
+ LPC_LCD_CTRL_LCDVCOMP(1) |
+ LPC_LCD_CTRL_LCDPWR |
+ LPC_LCD_CTRL_BGR |
+ LPC_LCD_CTRL_LCDTFT |
+ LPC_LCD_CTRL_LCDBPP(bpp) |
+ LPC_LCD_CTRL_LCDEN);
+}
+
+
+static int
+lpc_fb_open(struct cdev *cdev, int oflags, int devtype, struct thread *td)
+{
+ struct lpc_fb_softc *sc = cdev->si_drv1;
+
+ lpc_fb_lock(sc);
+
+ if (sc->lf_opened)
+ return (EBUSY);
+
+ sc->lf_opened = 1;
+
+ lpc_fb_unlock(sc);
+
+ if (!sc->lf_initialized) {
+ ssd1289_configure();
+ lpc_fb_setup(sc);
+ lpc_fb_blank(sc);
+ sc->lf_initialized = 1;
+ }
+
+ return (0);
+}
+
+static int
+lpc_fb_close(struct cdev *cdev, int fflag, int devtype, struct thread *td)
+{
+ struct lpc_fb_softc *sc = cdev->si_drv1;
+
+ lpc_fb_lock(sc);
+ sc->lf_opened = 0;
+ lpc_fb_unlock(sc);
+
+ return (0);
+}
+
+static int
+lpc_fb_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int x,
+ struct thread *td)
+{
+
+ return (EINVAL);
+}
+
+static int
+lpc_fb_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int nprot, vm_memattr_t *memattr)
+{
+ struct lpc_fb_softc *sc = cdev->si_drv1;
+
+ *paddr = (vm_paddr_t)(sc->lf_buffer_phys + offset);
+ return (0);
+}
+
+static void
+lpc_fb_blank(struct lpc_fb_softc *sc)
+{
+ memset(sc->lf_buffer, 0xffff, sc->lf_buffer_size);
+}
+
+static device_method_t lpc_fb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpc_fb_probe),
+ DEVMETHOD(device_attach, lpc_fb_attach),
+
+ { 0, 0 }
+};
+
+static devclass_t lpc_fb_devclass;
+
+static driver_t lpc_fb_driver = {
+ "lpcfb",
+ lpc_fb_methods,
+ sizeof(struct lpc_fb_softc),
+};
+
+DRIVER_MODULE(lpcfb, simplebus, lpc_fb_driver, lpc_fb_devclass, 0, 0);
Property changes on: trunk/sys/arm/lpc/lpc_fb.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_gpio.c
===================================================================
--- trunk/sys/arm/lpc/lpc_gpio.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,557 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * GPIO on LPC32x0 consist of 4 ports:
+ * - Port0 with 8 input/output pins
+ * - Port1 with 24 input/output pins
+ * - Port2 with 13 input/output pins
+ * - Port3 with:
+ * - 26 input pins (GPI_00..GPI_09 + GPI_15..GPI_23 + GPI_25 + GPI_27..GPI_28)
+ * - 24 output pins (GPO_00..GPO_23)
+ * - 6 input/output pins (GPIO_00..GPIO_05)
+ *
+ * Pins are mapped to logical pin number as follows:
+ * [0..9] -> GPI_00..GPI_09 (port 3)
+ * [10..18] -> GPI_15..GPI_23 (port 3)
+ * [19] -> GPI_25 (port 3)
+ * [20..21] -> GPI_27..GPI_28 (port 3)
+ * [22..45] -> GPO_00..GPO_23 (port 3)
+ * [46..51] -> GPIO_00..GPIO_05 (port 3)
+ * [52..64] -> P2.0..P2.12 (port 2)
+ * [65..88] -> P1.0..P1.23 (port 1)
+ * [89..96] -> P0.0..P0.7 (port 0)
+ *
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_gpio.c 278782 2015-02-14 20:37:33Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+#include "gpio_if.h"
+
+struct lpc_gpio_softc
+{
+ device_t lg_dev;
+ struct resource * lg_res;
+ bus_space_tag_t lg_bst;
+ bus_space_handle_t lg_bsh;
+};
+
+struct lpc_gpio_pinmap
+{
+ int lp_start_idx;
+ int lp_pin_count;
+ int lp_port;
+ int lp_start_bit;
+ int lp_flags;
+};
+
+static const struct lpc_gpio_pinmap lpc_gpio_pins[] = {
+ { 0, 10, 3, 0, GPIO_PIN_INPUT },
+ { 10, 9, 3, 15, GPIO_PIN_INPUT },
+ { 19, 1, 3, 25, GPIO_PIN_INPUT },
+ { 20, 2, 3, 27, GPIO_PIN_INPUT },
+ { 22, 24, 3, 0, GPIO_PIN_OUTPUT },
+ /*
+ * -1 below is to mark special case for Port3 GPIO pins, as they
+ * have other bits in Port 3 registers as inputs and as outputs
+ */
+ { 46, 6, 3, -1, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
+ { 52, 13, 2, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
+ { 65, 24, 1, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
+ { 89, 8, 0, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
+ { -1, -1, -1, -1, -1 },
+};
+
+#define LPC_GPIO_NPINS \
+ (LPC_GPIO_P0_COUNT + LPC_GPIO_P1_COUNT + \
+ LPC_GPIO_P2_COUNT + LPC_GPIO_P3_COUNT)
+
+#define LPC_GPIO_PIN_IDX(_map, _idx) \
+ (_idx - _map->lp_start_idx)
+
+#define LPC_GPIO_PIN_BIT(_map, _idx) \
+ (_map->lp_start_bit + LPC_GPIO_PIN_IDX(_map, _idx))
+
+static int lpc_gpio_probe(device_t);
+static int lpc_gpio_attach(device_t);
+static int lpc_gpio_detach(device_t);
+
+static int lpc_gpio_pin_max(device_t, int *);
+static int lpc_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
+static int lpc_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
+static int lpc_gpio_pin_setflags(device_t, uint32_t, uint32_t);
+static int lpc_gpio_pin_getname(device_t, uint32_t, char *);
+static int lpc_gpio_pin_get(device_t, uint32_t, uint32_t *);
+static int lpc_gpio_pin_set(device_t, uint32_t, uint32_t);
+static int lpc_gpio_pin_toggle(device_t, uint32_t);
+
+static const struct lpc_gpio_pinmap *lpc_gpio_get_pinmap(int);
+
+static struct lpc_gpio_softc *lpc_gpio_sc = NULL;
+
+#define lpc_gpio_read_4(_sc, _reg) \
+ bus_space_read_4(_sc->lg_bst, _sc->lg_bsh, _reg)
+#define lpc_gpio_write_4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->lg_bst, _sc->lg_bsh, _reg, _val)
+#define lpc_gpio_get_4(_sc, _test, _reg1, _reg2) \
+ lpc_gpio_read_4(_sc, ((_test) ? _reg1 : _reg2))
+#define lpc_gpio_set_4(_sc, _test, _reg1, _reg2, _val) \
+ lpc_gpio_write_4(_sc, ((_test) ? _reg1 : _reg2), _val)
+
+static int
+lpc_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,gpio"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 GPIO");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_gpio_attach(device_t dev)
+{
+ struct lpc_gpio_softc *sc = device_get_softc(dev);
+ int rid;
+
+ sc->lg_dev = dev;
+
+ rid = 0;
+ sc->lg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->lg_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->lg_bst = rman_get_bustag(sc->lg_res);
+ sc->lg_bsh = rman_get_bushandle(sc->lg_res);
+
+ lpc_gpio_sc = sc;
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+lpc_gpio_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static int
+lpc_gpio_pin_max(device_t dev, int *npins)
+{
+ *npins = LPC_GPIO_NPINS - 1;
+ return (0);
+}
+
+static int
+lpc_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ const struct lpc_gpio_pinmap *map;
+
+ if (pin > LPC_GPIO_NPINS)
+ return (ENODEV);
+
+ map = lpc_gpio_get_pinmap(pin);
+
+ *caps = map->lp_flags;
+ return (0);
+}
+
+static int
+lpc_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct lpc_gpio_softc *sc = device_get_softc(dev);
+ const struct lpc_gpio_pinmap *map;
+ uint32_t state;
+ int dir;
+
+ if (pin > LPC_GPIO_NPINS)
+ return (ENODEV);
+
+ map = lpc_gpio_get_pinmap(pin);
+
+ /* Check whether it's bidirectional pin */
+ if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) !=
+ (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
+ *flags = map->lp_flags;
+ return (0);
+ }
+
+ switch (map->lp_port) {
+ case 0:
+ state = lpc_gpio_read_4(sc, LPC_GPIO_P0_DIR_STATE);
+ dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
+ break;
+ case 1:
+ state = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE);
+ dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
+ break;
+ case 2:
+ state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE);
+ dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
+ break;
+ case 3:
+ state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE);
+ dir = (state & (1 << (25 + LPC_GPIO_PIN_IDX(map, pin))));
+ break;
+ default:
+ panic("unknown GPIO port");
+ }
+
+ *flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
+
+ return (0);
+}
+
+static int
+lpc_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct lpc_gpio_softc *sc = device_get_softc(dev);
+ const struct lpc_gpio_pinmap *map;
+ uint32_t dir, state;
+
+ if (pin > LPC_GPIO_NPINS)
+ return (ENODEV);
+
+ map = lpc_gpio_get_pinmap(pin);
+
+ /* Check whether it's bidirectional pin */
+ if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) !=
+ (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
+ return (ENOTSUP);
+
+ if (flags & GPIO_PIN_INPUT)
+ dir = 0;
+
+ if (flags & GPIO_PIN_OUTPUT)
+ dir = 1;
+
+ switch (map->lp_port) {
+ case 0:
+ state = (1 << LPC_GPIO_PIN_IDX(map, pin));
+ lpc_gpio_set_4(sc, dir, LPC_GPIO_P0_DIR_SET,
+ LPC_GPIO_P0_DIR_CLR, state);
+ break;
+ case 1:
+ state = (1 << LPC_GPIO_PIN_IDX(map, pin));
+ lpc_gpio_set_4(sc, dir, LPC_GPIO_P1_DIR_SET,
+ LPC_GPIO_P0_DIR_CLR, state);
+ break;
+ case 2:
+ state = (1 << LPC_GPIO_PIN_IDX(map, pin));
+ lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET,
+ LPC_GPIO_P0_DIR_CLR, state);
+ break;
+ case 3:
+ state = (1 << (25 + (pin - map->lp_start_idx)));
+ lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET,
+ LPC_GPIO_P0_DIR_CLR, state);
+ break;
+ }
+
+ return (0);
+}
+
+static int
+lpc_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ const struct lpc_gpio_pinmap *map;
+ int idx;
+
+ map = lpc_gpio_get_pinmap(pin);
+ idx = LPC_GPIO_PIN_IDX(map, pin);
+
+ switch (map->lp_port) {
+ case 0:
+ case 1:
+ case 2:
+ snprintf(name, GPIOMAXNAME - 1, "P%d.%d", map->lp_port,
+ map->lp_start_bit + LPC_GPIO_PIN_IDX(map, pin));
+ break;
+ case 3:
+ if (map->lp_start_bit == -1) {
+ snprintf(name, GPIOMAXNAME - 1, "GPIO_%02d", idx);
+ break;
+ }
+
+ snprintf(name, GPIOMAXNAME - 1, "GP%c_%02d",
+ (map->lp_flags & GPIO_PIN_INPUT) ? 'I' : 'O',
+ map->lp_start_bit + idx);
+ break;
+ }
+
+ return (0);
+}
+
+static int
+lpc_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value)
+{
+ struct lpc_gpio_softc *sc = device_get_softc(dev);
+ const struct lpc_gpio_pinmap *map;
+ uint32_t state, flags;
+ int dir;
+
+ map = lpc_gpio_get_pinmap(pin);
+
+ if (lpc_gpio_pin_getflags(dev, pin, &flags))
+ return (ENXIO);
+
+ if (flags & GPIO_PIN_OUTPUT)
+ dir = 1;
+
+ if (flags & GPIO_PIN_INPUT)
+ dir = 0;
+
+ switch (map->lp_port) {
+ case 0:
+ state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P0_OUTP_STATE,
+ LPC_GPIO_P0_INP_STATE);
+ *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
+ case 1:
+ state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P1_OUTP_STATE,
+ LPC_GPIO_P1_INP_STATE);
+ *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
+ case 2:
+ state = lpc_gpio_read_4(sc, LPC_GPIO_P2_INP_STATE);
+ *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
+ case 3:
+ state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P3_OUTP_STATE,
+ LPC_GPIO_P3_INP_STATE);
+ if (map->lp_start_bit == -1) {
+ if (dir)
+ *value = !!(state & (1 << (25 +
+ LPC_GPIO_PIN_IDX(map, pin))));
+ else
+ *value = !!(state & (1 << (10 +
+ LPC_GPIO_PIN_IDX(map, pin))));
+ }
+
+ *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
+ }
+
+ return (0);
+}
+
+static int
+lpc_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value)
+{
+ struct lpc_gpio_softc *sc = device_get_softc(dev);
+ const struct lpc_gpio_pinmap *map;
+ uint32_t state, flags;
+
+ map = lpc_gpio_get_pinmap(pin);
+
+ if (lpc_gpio_pin_getflags(dev, pin, &flags))
+ return (ENXIO);
+
+ if ((flags & GPIO_PIN_OUTPUT) == 0)
+ return (EINVAL);
+
+ state = (1 << LPC_GPIO_PIN_BIT(map, pin));
+
+ switch (map->lp_port) {
+ case 0:
+ lpc_gpio_set_4(sc, value, LPC_GPIO_P0_OUTP_SET,
+ LPC_GPIO_P0_OUTP_CLR, state);
+ break;
+ case 1:
+ lpc_gpio_set_4(sc, value, LPC_GPIO_P1_OUTP_SET,
+ LPC_GPIO_P1_OUTP_CLR, state);
+ break;
+ case 2:
+ lpc_gpio_set_4(sc, value, LPC_GPIO_P2_OUTP_SET,
+ LPC_GPIO_P2_OUTP_CLR, state);
+ break;
+ case 3:
+ if (map->lp_start_bit == -1)
+ state = (1 << (25 + LPC_GPIO_PIN_IDX(map, pin)));
+
+ lpc_gpio_set_4(sc, value, LPC_GPIO_P3_OUTP_SET,
+ LPC_GPIO_P3_OUTP_CLR, state);
+ break;
+ }
+
+ return (0);
+}
+
+static int
+lpc_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ const struct lpc_gpio_pinmap *map;
+ uint32_t flags;
+
+ map = lpc_gpio_get_pinmap(pin);
+
+ if (lpc_gpio_pin_getflags(dev, pin, &flags))
+ return (ENXIO);
+
+ if ((flags & GPIO_PIN_OUTPUT) == 0)
+ return (EINVAL);
+
+ panic("not implemented yet");
+
+ return (0);
+
+}
+
+static const struct lpc_gpio_pinmap *
+lpc_gpio_get_pinmap(int pin)
+{
+ const struct lpc_gpio_pinmap *map;
+
+ for (map = &lpc_gpio_pins[0]; map->lp_start_idx != -1; map++) {
+ if (pin >= map->lp_start_idx &&
+ pin < map->lp_start_idx + map->lp_pin_count)
+ return map;
+ }
+
+ panic("pin number %d out of range", pin);
+}
+
+int
+lpc_gpio_set_flags(device_t dev, int pin, int flags)
+{
+ if (lpc_gpio_sc == NULL)
+ return (ENXIO);
+
+ return lpc_gpio_pin_setflags(lpc_gpio_sc->lg_dev, pin, flags);
+}
+
+int
+lpc_gpio_set_state(device_t dev, int pin, int state)
+{
+ if (lpc_gpio_sc == NULL)
+ return (ENXIO);
+
+ return lpc_gpio_pin_set(lpc_gpio_sc->lg_dev, pin, state);
+}
+
+int
+lpc_gpio_get_state(device_t dev, int pin, int *state)
+{
+ if (lpc_gpio_sc == NULL)
+ return (ENXIO);
+
+ return lpc_gpio_pin_get(lpc_gpio_sc->lg_dev, pin, state);
+}
+
+void
+platform_gpio_init()
+{
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+
+ bst = fdtbus_bs_tag;
+
+ /* Preset SPI devices CS pins to one */
+ bus_space_map(bst, LPC_GPIO_PHYS_BASE, LPC_GPIO_SIZE, 0, &bsh);
+ bus_space_write_4(bst, bsh, LPC_GPIO_P3_OUTP_SET,
+ 1 << (SSD1289_CS_PIN - LPC_GPIO_GPO_00(0)) |
+ 1 << (SSD1289_DC_PIN - LPC_GPIO_GPO_00(0)) |
+ 1 << (ADS7846_CS_PIN - LPC_GPIO_GPO_00(0)));
+ bus_space_unmap(bst, bsh, LPC_GPIO_SIZE);
+}
+
+static device_method_t lpc_gpio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpc_gpio_probe),
+ DEVMETHOD(device_attach, lpc_gpio_attach),
+ DEVMETHOD(device_detach, lpc_gpio_detach),
+
+ /* GPIO interface */
+ DEVMETHOD(gpio_pin_max, lpc_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getcaps, lpc_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_getflags, lpc_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_setflags, lpc_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_getname, lpc_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_set, lpc_gpio_pin_set),
+ DEVMETHOD(gpio_pin_get, lpc_gpio_pin_get),
+ DEVMETHOD(gpio_pin_toggle, lpc_gpio_pin_toggle),
+
+ { 0, 0 }
+};
+
+static devclass_t lpc_gpio_devclass;
+
+static driver_t lpc_gpio_driver = {
+ "lpcgpio",
+ lpc_gpio_methods,
+ sizeof(struct lpc_gpio_softc),
+};
+
+extern devclass_t gpiobus_devclass, gpioc_devclass;
+extern driver_t gpiobus_driver, gpioc_driver;
+
+DRIVER_MODULE(lpcgpio, simplebus, lpc_gpio_driver, lpc_gpio_devclass, 0, 0);
+DRIVER_MODULE(gpiobus, lpcgpio, gpiobus_driver, gpiobus_devclass, 0, 0);
+DRIVER_MODULE(gpioc, lpcgpio, gpioc_driver, gpioc_devclass, 0, 0);
+MODULE_VERSION(lpcgpio, 1);
Property changes on: trunk/sys/arm/lpc/lpc_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_intc.c
===================================================================
--- trunk/sys/arm/lpc/lpc_intc.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_intc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,247 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_intc.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+
+struct lpc_intc_softc {
+ struct resource * li_res;
+ bus_space_tag_t li_bst;
+ bus_space_handle_t li_bsh;
+};
+
+static int lpc_intc_probe(device_t);
+static int lpc_intc_attach(device_t);
+static void lpc_intc_eoi(void *);
+
+static struct lpc_intc_softc *intc_softc = NULL;
+
+#define intc_read_4(reg) \
+ bus_space_read_4(intc_softc->li_bst, intc_softc->li_bsh, reg)
+#define intc_write_4(reg, val) \
+ bus_space_write_4(intc_softc->li_bst, intc_softc->li_bsh, reg, val)
+
+static int
+lpc_intc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,pic"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_intc_attach(device_t dev)
+{
+ struct lpc_intc_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ if (intc_softc)
+ return (ENXIO);
+
+ sc->li_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->li_res) {
+ device_printf(dev, "could not alloc resources\n");
+ return (ENXIO);
+ }
+
+ sc->li_bst = rman_get_bustag(sc->li_res);
+ sc->li_bsh = rman_get_bushandle(sc->li_res);
+ intc_softc = sc;
+ arm_post_filter = lpc_intc_eoi;
+
+ /* Clear interrupt status registers and disable all interrupts */
+ intc_write_4(LPC_INTC_MIC_ER, 0);
+ intc_write_4(LPC_INTC_SIC1_ER, 0);
+ intc_write_4(LPC_INTC_SIC2_ER, 0);
+ intc_write_4(LPC_INTC_MIC_RSR, ~0);
+ intc_write_4(LPC_INTC_SIC1_RSR, ~0);
+ intc_write_4(LPC_INTC_SIC2_RSR, ~0);
+ return (0);
+}
+
+static device_method_t lpc_intc_methods[] = {
+ DEVMETHOD(device_probe, lpc_intc_probe),
+ DEVMETHOD(device_attach, lpc_intc_attach),
+ { 0, 0 }
+};
+
+static driver_t lpc_intc_driver = {
+ "pic",
+ lpc_intc_methods,
+ sizeof(struct lpc_intc_softc),
+};
+
+static devclass_t lpc_intc_devclass;
+
+DRIVER_MODULE(pic, simplebus, lpc_intc_driver, lpc_intc_devclass, 0, 0);
+
+int
+arm_get_next_irq(int last)
+{
+ uint32_t value;
+ int i;
+
+ /* IRQs 0-31 are mapped to LPC_INTC_MIC_SR */
+ value = intc_read_4(LPC_INTC_MIC_SR);
+ for (i = 0; i < 32; i++) {
+ if (value & (1 << i))
+ return (i);
+ }
+
+ /* IRQs 32-63 are mapped to LPC_INTC_SIC1_SR */
+ value = intc_read_4(LPC_INTC_SIC1_SR);
+ for (i = 0; i < 32; i++) {
+ if (value & (1 << i))
+ return (i + 32);
+ }
+
+ /* IRQs 64-95 are mapped to LPC_INTC_SIC2_SR */
+ value = intc_read_4(LPC_INTC_SIC2_SR);
+ for (i = 0; i < 32; i++) {
+ if (value & (1 << i))
+ return (i + 64);
+ }
+
+ return (-1);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ int reg;
+ uint32_t value;
+
+ /* Make sure that interrupt isn't active already */
+ lpc_intc_eoi((void *)nb);
+
+ if (nb > 63) {
+ nb -= 64;
+ reg = LPC_INTC_SIC2_ER;
+ } else if (nb > 31) {
+ nb -= 32;
+ reg = LPC_INTC_SIC1_ER;
+ } else
+ reg = LPC_INTC_MIC_ER;
+
+ /* Clear bit in ER register */
+ value = intc_read_4(reg);
+ value &= ~(1 << nb);
+ intc_write_4(reg, value);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ int reg;
+ uint32_t value;
+
+ if (nb > 63) {
+ nb -= 64;
+ reg = LPC_INTC_SIC2_ER;
+ } else if (nb > 31) {
+ nb -= 32;
+ reg = LPC_INTC_SIC1_ER;
+ } else
+ reg = LPC_INTC_MIC_ER;
+
+ /* Set bit in ER register */
+ value = intc_read_4(reg);
+ value |= (1 << nb);
+ intc_write_4(reg, value);
+}
+
+static void
+lpc_intc_eoi(void *data)
+{
+ int reg;
+ int nb = (int)data;
+ uint32_t value;
+
+ if (nb > 63) {
+ nb -= 64;
+ reg = LPC_INTC_SIC2_RSR;
+ } else if (nb > 31) {
+ nb -= 32;
+ reg = LPC_INTC_SIC1_RSR;
+ } else
+ reg = LPC_INTC_MIC_RSR;
+
+ /* Set bit in RSR register */
+ value = intc_read_4(reg);
+ value |= (1 << nb);
+ intc_write_4(reg, value);
+
+}
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+ if (!fdt_is_compatible(node, "lpc,pic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_pic_decode_ic,
+ NULL
+};
Property changes on: trunk/sys/arm/lpc/lpc_intc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_machdep.c
===================================================================
--- trunk/sys/arm/lpc/lpc_machdep.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,140 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/at91/kb920x_machdep.c, rev 45
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_machdep.c 266084 2014-05-14 19:18:58Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+#include <dev/fdt/fdt_common.h>
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+}
+
+void
+initarm_gpio_init(void)
+{
+
+ /*
+ * Set initial values of GPIO output ports
+ */
+ platform_gpio_init();
+}
+
+void
+initarm_late_init(void)
+{
+}
+
+/*
+ * Add a single static device mapping.
+ * The values used were taken from the ranges property of the SoC node in the
+ * dts file when this code was converted to arm_devmap_add_entry().
+ */
+int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(LPC_DEV_PHYS_BASE, LPC_DEV_SIZE);
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+void
+cpu_reset(void)
+{
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+
+ bst = fdtbus_bs_tag;
+
+ /* Enable WDT */
+ bus_space_map(bst, LPC_CLKPWR_PHYS_BASE, LPC_CLKPWR_SIZE, 0, &bsh);
+ bus_space_write_4(bst, bsh, LPC_CLKPWR_TIMCLK_CTRL,
+ LPC_CLKPWR_TIMCLK_CTRL_WATCHDOG);
+ bus_space_unmap(bst, bsh, LPC_CLKPWR_SIZE);
+
+ /* Instant assert of RESETOUT_N with pulse length 1ms */
+ bus_space_map(bst, LPC_WDTIM_PHYS_BASE, LPC_WDTIM_SIZE, 0, &bsh);
+ bus_space_write_4(bst, bsh, LPC_WDTIM_PULSE, 13000);
+ bus_space_write_4(bst, bsh, LPC_WDTIM_MCTRL, 0x70);
+ bus_space_unmap(bst, bsh, LPC_WDTIM_SIZE);
+
+ for (;;)
+ continue;
+}
+
Property changes on: trunk/sys/arm/lpc/lpc_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_mmc.c
===================================================================
--- trunk/sys/arm/lpc/lpc_mmc.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_mmc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,767 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_mmc.c 318198 2017-05-11 21:01:02Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcbrvar.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+struct lpc_mmc_dmamap_arg {
+ bus_addr_t lm_dma_busaddr;
+};
+
+struct lpc_mmc_softc {
+ device_t lm_dev;
+ struct mtx lm_mtx;
+ struct resource * lm_mem_res;
+ struct resource * lm_irq_res;
+ bus_space_tag_t lm_bst;
+ bus_space_handle_t lm_bsh;
+ void * lm_intrhand;
+ struct mmc_host lm_host;
+ struct mmc_request * lm_req;
+ struct mmc_data * lm_data;
+ uint32_t lm_flags;
+#define LPC_SD_FLAGS_IGNORECRC (1 << 0)
+ int lm_xfer_direction;
+#define DIRECTION_READ 0
+#define DIRECTION_WRITE 1
+ int lm_xfer_done;
+ int lm_bus_busy;
+ bus_dma_tag_t lm_dma_tag;
+ bus_dmamap_t lm_dma_map;
+ bus_addr_t lm_buffer_phys;
+ void * lm_buffer;
+};
+
+#define LPC_SD_MAX_BLOCKSIZE 1024
+/* XXX */
+#define LPC_MMC_DMACH_READ 1
+#define LPC_MMC_DMACH_WRITE 0
+
+
+static int lpc_mmc_probe(device_t);
+static int lpc_mmc_attach(device_t);
+static int lpc_mmc_detach(device_t);
+static void lpc_mmc_intr(void *);
+
+static void lpc_mmc_cmd(struct lpc_mmc_softc *, struct mmc_command *);
+static void lpc_mmc_setup_xfer(struct lpc_mmc_softc *, struct mmc_data *);
+
+static int lpc_mmc_update_ios(device_t, device_t);
+static int lpc_mmc_request(device_t, device_t, struct mmc_request *);
+static int lpc_mmc_get_ro(device_t, device_t);
+static int lpc_mmc_acquire_host(device_t, device_t);
+static int lpc_mmc_release_host(device_t, device_t);
+
+static void lpc_mmc_dma_rxfinish(void *);
+static void lpc_mmc_dma_rxerror(void *);
+static void lpc_mmc_dma_txfinish(void *);
+static void lpc_mmc_dma_txerror(void *);
+
+static void lpc_mmc_dmamap_cb(void *, bus_dma_segment_t *, int, int);
+
+#define lpc_mmc_lock(_sc) \
+ mtx_lock(&_sc->lm_mtx);
+#define lpc_mmc_unlock(_sc) \
+ mtx_unlock(&_sc->lm_mtx);
+#define lpc_mmc_read_4(_sc, _reg) \
+ bus_space_read_4(_sc->lm_bst, _sc->lm_bsh, _reg)
+#define lpc_mmc_write_4(_sc, _reg, _value) \
+ bus_space_write_4(_sc->lm_bst, _sc->lm_bsh, _reg, _value)
+
+static struct lpc_dmac_channel_config lpc_mmc_dma_rxconf = {
+ .ldc_fcntl = LPC_DMAC_FLOW_D_P2M,
+ .ldc_src_periph = LPC_DMAC_SD_ID,
+ .ldc_src_width = LPC_DMAC_CH_CONTROL_WIDTH_4,
+ .ldc_src_incr = 0,
+ .ldc_src_burst = LPC_DMAC_CH_CONTROL_BURST_8,
+ .ldc_dst_periph = LPC_DMAC_SD_ID,
+ .ldc_dst_width = LPC_DMAC_CH_CONTROL_WIDTH_4,
+ .ldc_dst_incr = 1,
+ .ldc_dst_burst = LPC_DMAC_CH_CONTROL_BURST_8,
+ .ldc_success_handler = lpc_mmc_dma_rxfinish,
+ .ldc_error_handler = lpc_mmc_dma_rxerror,
+};
+
+static struct lpc_dmac_channel_config lpc_mmc_dma_txconf = {
+ .ldc_fcntl = LPC_DMAC_FLOW_P_M2P,
+ .ldc_src_periph = LPC_DMAC_SD_ID,
+ .ldc_src_width = LPC_DMAC_CH_CONTROL_WIDTH_4,
+ .ldc_src_incr = 1,
+ .ldc_src_burst = LPC_DMAC_CH_CONTROL_BURST_8,
+ .ldc_dst_periph = LPC_DMAC_SD_ID,
+ .ldc_dst_width = LPC_DMAC_CH_CONTROL_WIDTH_4,
+ .ldc_dst_incr = 0,
+ .ldc_dst_burst = LPC_DMAC_CH_CONTROL_BURST_8,
+ .ldc_success_handler = lpc_mmc_dma_txfinish,
+ .ldc_error_handler = lpc_mmc_dma_txerror,
+};
+
+static int
+lpc_mmc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,mmc"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 MMC/SD controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_mmc_attach(device_t dev)
+{
+ struct lpc_mmc_softc *sc = device_get_softc(dev);
+ struct lpc_mmc_dmamap_arg ctx;
+ device_t child;
+ int rid, err;
+
+ sc->lm_dev = dev;
+ sc->lm_req = NULL;
+
+ mtx_init(&sc->lm_mtx, "lpcmmc", "mmc", MTX_DEF);
+
+ rid = 0;
+ sc->lm_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->lm_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->lm_bst = rman_get_bustag(sc->lm_mem_res);
+ sc->lm_bsh = rman_get_bushandle(sc->lm_mem_res);
+
+ debugf("virtual register space: 0x%08lx\n", sc->lm_bsh);
+
+ rid = 0;
+ sc->lm_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->lm_irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lm_mem_res);
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->lm_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, lpc_mmc_intr, sc, &sc->lm_intrhand))
+ {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lm_mem_res);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lm_irq_res);
+ device_printf(dev, "cannot setup interrupt handler\n");
+ return (ENXIO);
+ }
+
+ sc->lm_host.f_min = 312500;
+ sc->lm_host.f_max = 2500000;
+ sc->lm_host.host_ocr = MMC_OCR_300_310 | MMC_OCR_310_320 |
+ MMC_OCR_320_330 | MMC_OCR_330_340;
+#if 0
+ sc->lm_host.caps = MMC_CAP_4_BIT_DATA;
+#endif
+
+ lpc_pwr_write(dev, LPC_CLKPWR_MS_CTRL,
+ LPC_CLKPWR_MS_CTRL_CLOCK_EN | LPC_CLKPWR_MS_CTRL_SD_CLOCK | 1);
+ lpc_mmc_write_4(sc, LPC_SD_POWER, LPC_SD_POWER_CTRL_ON);
+
+ device_set_ivars(dev, &sc->lm_host);
+
+ child = device_add_child(dev, "mmc", -1);
+ if (!child) {
+ device_printf(dev, "attaching MMC bus failed!\n");
+ bus_teardown_intr(dev, sc->lm_irq_res, sc->lm_intrhand);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lm_mem_res);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lm_irq_res);
+ return (ENXIO);
+ }
+
+ /* Alloc DMA memory */
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(sc->lm_dev),
+ 4, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ LPC_SD_MAX_BLOCKSIZE, 1, /* maxsize, nsegments */
+ LPC_SD_MAX_BLOCKSIZE, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->lm_dma_tag);
+
+ err = bus_dmamem_alloc(sc->lm_dma_tag, (void **)&sc->lm_buffer,
+ 0, &sc->lm_dma_map);
+ if (err) {
+ device_printf(dev, "cannot allocate framebuffer\n");
+ goto fail;
+ }
+
+ err = bus_dmamap_load(sc->lm_dma_tag, sc->lm_dma_map, sc->lm_buffer,
+ LPC_SD_MAX_BLOCKSIZE, lpc_mmc_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
+ if (err) {
+ device_printf(dev, "cannot load DMA map\n");
+ goto fail;
+ }
+
+ sc->lm_buffer_phys = ctx.lm_dma_busaddr;
+
+ lpc_mmc_dma_rxconf.ldc_handler_arg = (void *)sc;
+ err = lpc_dmac_config_channel(dev, LPC_MMC_DMACH_READ, &lpc_mmc_dma_rxconf);
+ if (err) {
+ device_printf(dev, "cannot allocate RX DMA channel\n");
+ goto fail;
+ }
+
+
+ lpc_mmc_dma_txconf.ldc_handler_arg = (void *)sc;
+ err = lpc_dmac_config_channel(dev, LPC_MMC_DMACH_WRITE, &lpc_mmc_dma_txconf);
+ if (err) {
+ device_printf(dev, "cannot allocate TX DMA channel\n");
+ goto fail;
+ }
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+
+fail:
+ if (sc->lm_intrhand)
+ bus_teardown_intr(dev, sc->lm_irq_res, sc->lm_intrhand);
+ if (sc->lm_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lm_irq_res);
+ if (sc->lm_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lm_mem_res);
+ return (err);
+}
+
+static int
+lpc_mmc_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static void
+lpc_mmc_intr(void *arg)
+{
+ struct lpc_mmc_softc *sc = (struct lpc_mmc_softc *)arg;
+ struct mmc_command *cmd;
+ uint32_t status;
+
+ status = lpc_mmc_read_4(sc, LPC_SD_STATUS);
+
+ debugf("interrupt: 0x%08x\n", status);
+
+ if (status & LPC_SD_STATUS_CMDCRCFAIL) {
+ cmd = sc->lm_req->cmd;
+ cmd->error = sc->lm_flags & LPC_SD_FLAGS_IGNORECRC
+ ? MMC_ERR_NONE : MMC_ERR_BADCRC;
+ cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
+ sc->lm_req->done(sc->lm_req);
+ sc->lm_req = NULL;
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDCRCFAIL);
+ }
+
+ if (status & LPC_SD_STATUS_CMDACTIVE)
+ {
+ debugf("command active\n");
+ cmd = sc->lm_req->cmd;
+ cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
+ sc->lm_req->done(sc->lm_req);
+ sc->lm_req = NULL;
+ }
+
+ if (status & LPC_SD_STATUS_DATATIMEOUT) {
+ device_printf(sc->lm_dev, "data timeout\n");
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATATIMEOUT);
+ }
+
+ if (status & LPC_SD_STATUS_TXUNDERRUN) {
+ device_printf(sc->lm_dev, "TX underrun\n");
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_TXUNDERRUN);
+ }
+
+ if (status & LPC_SD_STATUS_CMDRESPEND) {
+ debugf("command response\n");
+ cmd = sc->lm_req->cmd;
+
+ if (cmd->flags & MMC_RSP_136) {
+ cmd->resp[3] = lpc_mmc_read_4(sc, LPC_SD_RESP3);
+ cmd->resp[2] = lpc_mmc_read_4(sc, LPC_SD_RESP2);
+ cmd->resp[1] = lpc_mmc_read_4(sc, LPC_SD_RESP1);
+ }
+
+ cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
+ cmd->error = MMC_ERR_NONE;
+
+ if (cmd->data && (cmd->data->flags & MMC_DATA_WRITE))
+ lpc_mmc_setup_xfer(sc, sc->lm_req->cmd->data);
+
+ if (!cmd->data) {
+ sc->lm_req->done(sc->lm_req);
+ sc->lm_req = NULL;
+ }
+
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDRESPEND);
+ }
+
+ if (status & LPC_SD_STATUS_CMDSENT) {
+ debugf("command sent\n");
+ cmd = sc->lm_req->cmd;
+ cmd->error = MMC_ERR_NONE;
+ sc->lm_req->done(sc->lm_req);
+ sc->lm_req = NULL;
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDSENT);
+ }
+
+ if (status & LPC_SD_STATUS_DATAEND) {
+ if (sc->lm_xfer_direction == DIRECTION_READ)
+ lpc_dmac_start_burst(sc->lm_dev, LPC_DMAC_SD_ID);
+
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATAEND);
+ }
+
+ if (status & LPC_SD_STATUS_CMDTIMEOUT) {
+ device_printf(sc->lm_dev, "command response timeout\n");
+ cmd = sc->lm_req->cmd;
+ cmd->error = MMC_ERR_TIMEOUT;
+ sc->lm_req->done(sc->lm_req);
+ sc->lm_req = NULL;
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDTIMEOUT);
+ return;
+ }
+
+ if (status & LPC_SD_STATUS_STARTBITERR) {
+ device_printf(sc->lm_dev, "start bit error\n");
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_STARTBITERR);
+ }
+
+ if (status & LPC_SD_STATUS_DATACRCFAIL) {
+ device_printf(sc->lm_dev, "data CRC error\n");
+ debugf("data buffer: %p\n", sc->lm_buffer);
+ cmd = sc->lm_req->cmd;
+ cmd->error = MMC_ERR_BADCRC;
+ sc->lm_req->done(sc->lm_req);
+ sc->lm_req = NULL;
+
+ if (sc->lm_xfer_direction == DIRECTION_READ)
+ lpc_dmac_start_burst(sc->lm_dev, LPC_DMAC_SD_ID);
+
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATACRCFAIL);
+ }
+
+ if (status & LPC_SD_STATUS_DATABLOCKEND) {
+ debugf("data block end\n");
+ if (sc->lm_xfer_direction == DIRECTION_READ)
+ memcpy(sc->lm_data->data, sc->lm_buffer, sc->lm_data->len);
+
+ if (sc->lm_xfer_direction == DIRECTION_WRITE) {
+ lpc_dmac_disable_channel(sc->lm_dev, LPC_MMC_DMACH_WRITE);
+ lpc_mmc_write_4(sc, LPC_SD_DATACTRL, 0);
+ }
+
+ sc->lm_req->done(sc->lm_req);
+ sc->lm_req = NULL;
+ lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATABLOCKEND);
+ }
+
+ debugf("done\n");
+}
+
+static int
+lpc_mmc_request(device_t bus, device_t child, struct mmc_request *req)
+{
+ struct lpc_mmc_softc *sc = device_get_softc(bus);
+
+ debugf("request: %p\n", req);
+
+ lpc_mmc_lock(sc);
+ if (sc->lm_req)
+ return (EBUSY);
+
+ sc->lm_req = req;
+
+ if (req->cmd->data && req->cmd->data->flags & MMC_DATA_WRITE) {
+ memcpy(sc->lm_buffer, req->cmd->data->data, req->cmd->data->len);
+ lpc_mmc_cmd(sc, req->cmd);
+ lpc_mmc_unlock(sc);
+ return (0);
+ }
+
+ if (req->cmd->data)
+ lpc_mmc_setup_xfer(sc, req->cmd->data);
+
+ lpc_mmc_cmd(sc, req->cmd);
+ lpc_mmc_unlock(sc);
+
+ return (0);
+}
+
+static void
+lpc_mmc_cmd(struct lpc_mmc_softc *sc, struct mmc_command *cmd)
+{
+ uint32_t cmdreg = 0;
+
+ debugf("cmd: %d arg: 0x%08x\n", cmd->opcode, cmd->arg);
+
+ if (lpc_mmc_read_4(sc, LPC_SD_COMMAND) & LPC_SD_COMMAND_ENABLE) {
+ lpc_mmc_write_4(sc, LPC_SD_COMMAND, 0);
+ DELAY(1000);
+ }
+
+ sc->lm_flags &= ~LPC_SD_FLAGS_IGNORECRC;
+
+ if (cmd->flags & MMC_RSP_PRESENT)
+ cmdreg |= LPC_SD_COMMAND_RESPONSE;
+
+ if (MMC_RSP(cmd->flags) == MMC_RSP_R2)
+ cmdreg |= LPC_SD_COMMAND_LONGRSP;
+
+ if (MMC_RSP(cmd->flags) == MMC_RSP_R3)
+ sc->lm_flags |= LPC_SD_FLAGS_IGNORECRC;
+
+ cmdreg |= LPC_SD_COMMAND_ENABLE;
+ cmdreg |= (cmd->opcode & LPC_SD_COMMAND_CMDINDEXMASK);
+
+ lpc_mmc_write_4(sc, LPC_SD_MASK0, 0xffffffff);
+ lpc_mmc_write_4(sc, LPC_SD_MASK1, 0xffffffff);
+ lpc_mmc_write_4(sc, LPC_SD_ARGUMENT, cmd->arg);
+ lpc_mmc_write_4(sc, LPC_SD_COMMAND, cmdreg);
+}
+
+static void
+lpc_mmc_setup_xfer(struct lpc_mmc_softc *sc, struct mmc_data *data)
+{
+ uint32_t datactrl = 0;
+ int data_words = data->len / 4;
+
+ sc->lm_data = data;
+ sc->lm_xfer_done = 0;
+
+ debugf("data: %p, len: %d, %s\n", data,
+ data->len, (data->flags & MMC_DATA_READ) ? "read" : "write");
+
+ if (data->flags & MMC_DATA_READ) {
+ sc->lm_xfer_direction = DIRECTION_READ;
+ lpc_dmac_setup_transfer(sc->lm_dev, LPC_MMC_DMACH_READ,
+ LPC_SD_PHYS_BASE + LPC_SD_FIFO, sc->lm_buffer_phys,
+ data_words, 0);
+ }
+
+ if (data->flags & MMC_DATA_WRITE) {
+ sc->lm_xfer_direction = DIRECTION_WRITE;
+ lpc_dmac_setup_transfer(sc->lm_dev, LPC_MMC_DMACH_WRITE,
+ sc->lm_buffer_phys, LPC_SD_PHYS_BASE + LPC_SD_FIFO,
+ data_words, 0);
+ }
+
+ datactrl |= (sc->lm_xfer_direction
+ ? LPC_SD_DATACTRL_WRITE
+ : LPC_SD_DATACTRL_READ);
+
+ datactrl |= LPC_SD_DATACTRL_DMAENABLE | LPC_SD_DATACTRL_ENABLE;
+ datactrl |= (ffs(data->len) - 1) << 4;
+
+ debugf("datactrl: 0x%08x\n", datactrl);
+
+ lpc_mmc_write_4(sc, LPC_SD_DATATIMER, 0xFFFF0000);
+ lpc_mmc_write_4(sc, LPC_SD_DATALENGTH, data->len);
+ lpc_mmc_write_4(sc, LPC_SD_DATACTRL, datactrl);
+}
+
+static int
+lpc_mmc_read_ivar(device_t bus, device_t child, int which,
+ uintptr_t *result)
+{
+ struct lpc_mmc_softc *sc = device_get_softc(bus);
+
+ switch (which) {
+ default:
+ return (EINVAL);
+ case MMCBR_IVAR_BUS_MODE:
+ *(int *)result = sc->lm_host.ios.bus_mode;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ *(int *)result = sc->lm_host.ios.bus_width;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ *(int *)result = sc->lm_host.ios.chip_select;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ *(int *)result = sc->lm_host.ios.clock;
+ break;
+ case MMCBR_IVAR_F_MIN:
+ *(int *)result = sc->lm_host.f_min;
+ break;
+ case MMCBR_IVAR_F_MAX:
+ *(int *)result = sc->lm_host.f_max;
+ break;
+ case MMCBR_IVAR_HOST_OCR:
+ *(int *)result = sc->lm_host.host_ocr;
+ break;
+ case MMCBR_IVAR_MODE:
+ *(int *)result = sc->lm_host.mode;
+ break;
+ case MMCBR_IVAR_OCR:
+ *(int *)result = sc->lm_host.ocr;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ *(int *)result = sc->lm_host.ios.power_mode;
+ break;
+ case MMCBR_IVAR_VDD:
+ *(int *)result = sc->lm_host.ios.vdd;
+ break;
+ case MMCBR_IVAR_CAPS:
+ *(int *)result = sc->lm_host.caps;
+ break;
+ case MMCBR_IVAR_MAX_DATA:
+ *(int *)result = 1;
+ break;
+ }
+
+ return (0);
+}
+
+static int
+lpc_mmc_write_ivar(device_t bus, device_t child, int which,
+ uintptr_t value)
+{
+ struct lpc_mmc_softc *sc = device_get_softc(bus);
+
+ switch (which) {
+ default:
+ return (EINVAL);
+ case MMCBR_IVAR_BUS_MODE:
+ sc->lm_host.ios.bus_mode = value;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ sc->lm_host.ios.bus_width = value;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ sc->lm_host.ios.chip_select = value;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ sc->lm_host.ios.clock = value;
+ break;
+ case MMCBR_IVAR_MODE:
+ sc->lm_host.mode = value;
+ break;
+ case MMCBR_IVAR_OCR:
+ sc->lm_host.ocr = value;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ sc->lm_host.ios.power_mode = value;
+ break;
+ case MMCBR_IVAR_VDD:
+ sc->lm_host.ios.vdd = value;
+ break;
+ /* These are read-only */
+ case MMCBR_IVAR_CAPS:
+ case MMCBR_IVAR_HOST_OCR:
+ case MMCBR_IVAR_F_MIN:
+ case MMCBR_IVAR_F_MAX:
+ case MMCBR_IVAR_MAX_DATA:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+lpc_mmc_update_ios(device_t bus, device_t child)
+{
+ struct lpc_mmc_softc *sc = device_get_softc(bus);
+ struct mmc_ios *ios = &sc->lm_host.ios;
+ uint32_t clkdiv = 0, pwr = 0;
+
+ if (ios->bus_width == bus_width_4)
+ clkdiv |= LPC_SD_CLOCK_WIDEBUS;
+
+ /* Calculate clock divider */
+ clkdiv = (LPC_SD_CLK / (2 * ios->clock)) - 1;
+
+ /* Clock rate should not exceed rate requested in ios */
+ if ((LPC_SD_CLK / (2 * (clkdiv + 1))) > ios->clock)
+ clkdiv++;
+
+ debugf("clock: %dHz, clkdiv: %d\n", ios->clock, clkdiv);
+
+ if (ios->bus_width == bus_width_4) {
+ debugf("using wide bus mode\n");
+ clkdiv |= LPC_SD_CLOCK_WIDEBUS;
+ }
+
+ lpc_mmc_write_4(sc, LPC_SD_CLOCK, clkdiv | LPC_SD_CLOCK_ENABLE);
+
+ switch (ios->power_mode) {
+ case power_off:
+ pwr |= LPC_SD_POWER_CTRL_OFF;
+ break;
+ case power_up:
+ pwr |= LPC_SD_POWER_CTRL_UP;
+ break;
+ case power_on:
+ pwr |= LPC_SD_POWER_CTRL_ON;
+ break;
+ }
+
+ if (ios->bus_mode == opendrain)
+ pwr |= LPC_SD_POWER_OPENDRAIN;
+
+ lpc_mmc_write_4(sc, LPC_SD_POWER, pwr);
+
+ return (0);
+}
+
+static int
+lpc_mmc_get_ro(device_t bus, device_t child)
+{
+
+ return (0);
+}
+
+static int
+lpc_mmc_acquire_host(device_t bus, device_t child)
+{
+ struct lpc_mmc_softc *sc = device_get_softc(bus);
+ int error = 0;
+
+ lpc_mmc_lock(sc);
+ while (sc->lm_bus_busy)
+ error = mtx_sleep(sc, &sc->lm_mtx, PZERO, "mmcah", 0);
+
+ sc->lm_bus_busy++;
+ lpc_mmc_unlock(sc);
+ return (error);
+}
+
+static int
+lpc_mmc_release_host(device_t bus, device_t child)
+{
+ struct lpc_mmc_softc *sc = device_get_softc(bus);
+
+ lpc_mmc_lock(sc);
+ sc->lm_bus_busy--;
+ wakeup(sc);
+ lpc_mmc_unlock(sc);
+ return (0);
+}
+
+static void lpc_mmc_dma_rxfinish(void *arg)
+{
+}
+
+static void lpc_mmc_dma_rxerror(void *arg)
+{
+ struct lpc_mmc_softc *sc = (struct lpc_mmc_softc *)arg;
+ device_printf(sc->lm_dev, "DMA RX error\n");
+}
+
+static void lpc_mmc_dma_txfinish(void *arg)
+{
+}
+
+static void lpc_mmc_dma_txerror(void *arg)
+{
+ struct lpc_mmc_softc *sc = (struct lpc_mmc_softc *)arg;
+ device_printf(sc->lm_dev, "DMA TX error\n");
+}
+
+static void
+lpc_mmc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ struct lpc_mmc_dmamap_arg *ctx;
+
+ if (err)
+ return;
+
+ ctx = (struct lpc_mmc_dmamap_arg *)arg;
+ ctx->lm_dma_busaddr = segs[0].ds_addr;
+}
+
+static device_method_t lpc_mmc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpc_mmc_probe),
+ DEVMETHOD(device_attach, lpc_mmc_attach),
+ DEVMETHOD(device_detach, lpc_mmc_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, lpc_mmc_read_ivar),
+ DEVMETHOD(bus_write_ivar, lpc_mmc_write_ivar),
+
+ /* MMC bridge interface */
+ DEVMETHOD(mmcbr_update_ios, lpc_mmc_update_ios),
+ DEVMETHOD(mmcbr_request, lpc_mmc_request),
+ DEVMETHOD(mmcbr_get_ro, lpc_mmc_get_ro),
+ DEVMETHOD(mmcbr_acquire_host, lpc_mmc_acquire_host),
+ DEVMETHOD(mmcbr_release_host, lpc_mmc_release_host),
+
+ DEVMETHOD_END
+};
+
+static devclass_t lpc_mmc_devclass;
+
+static driver_t lpc_mmc_driver = {
+ "lpcmmc",
+ lpc_mmc_methods,
+ sizeof(struct lpc_mmc_softc),
+};
+
+DRIVER_MODULE(lpcmmc, simplebus, lpc_mmc_driver, lpc_mmc_devclass, NULL, NULL);
+MMC_DECLARE_BRIDGE(lpcmmc);
Property changes on: trunk/sys/arm/lpc/lpc_mmc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_ohci.c
===================================================================
--- trunk/sys/arm/lpc/lpc_ohci.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_ohci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,360 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_ohci.c 278278 2015-02-05 20:03:02Z hselasky $");
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/rman.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <sys/kdb.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ohci.h>
+#include <dev/usb/controller/ohcireg.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+#define I2C_START_BIT (1 << 8)
+#define I2C_STOP_BIT (1 << 9)
+#define I2C_READ 0x01
+#define I2C_WRITE 0x00
+#define DUMMY_BYTE 0x55
+
+#define lpc_otg_read_4(_sc, _reg) \
+ bus_space_read_4(_sc->sc_io_tag, _sc->sc_io_hdl, _reg)
+#define lpc_otg_write_4(_sc, _reg, _value) \
+ bus_space_write_4(_sc->sc_io_tag, _sc->sc_io_hdl, _reg, _value)
+#define lpc_otg_wait_write_4(_sc, _wreg, _sreg, _value) \
+ do { \
+ lpc_otg_write_4(_sc, _wreg, _value); \
+ while ((lpc_otg_read_4(_sc, _sreg) & _value) != _value); \
+ } while (0);
+
+static int lpc_ohci_probe(device_t dev);
+static int lpc_ohci_attach(device_t dev);
+static int lpc_ohci_detach(device_t dev);
+
+static void lpc_otg_i2c_reset(struct ohci_softc *);
+
+static int lpc_isp3101_read(struct ohci_softc *, int);
+static void lpc_isp3101_write(struct ohci_softc *, int, int);
+static void lpc_isp3101_clear(struct ohci_softc *, int, int);
+static void lpc_isp3101_configure(device_t dev, struct ohci_softc *);
+
+static int
+lpc_ohci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,usb-ohci"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 USB OHCI controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_ohci_attach(device_t dev)
+{
+ struct ohci_softc *sc = device_get_softc(dev);
+ int err;
+ int rid;
+ int i = 0;
+ uint32_t usbctrl;
+ uint32_t otgstatus;
+
+ sc->sc_bus.parent = dev;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
+
+ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev),
+ &ohci_iterate_hw_softc))
+ return (ENOMEM);
+
+ rid = 0;
+ sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->sc_io_res) {
+ device_printf(dev, "cannot map OHCI register space\n");
+ goto fail;
+ }
+
+ sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+ sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+ sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ goto fail;
+ }
+
+ sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (!(sc->sc_bus.bdev))
+ goto fail;
+
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+ strlcpy(sc->sc_vendor, "NXP", sizeof(sc->sc_vendor));
+
+ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (void *)ohci_interrupt, sc, &sc->sc_intr_hdl);
+ if (err) {
+ sc->sc_intr_hdl = NULL;
+ goto fail;
+ }
+
+ usbctrl = lpc_pwr_read(dev, LPC_CLKPWR_USB_CTRL);
+ usbctrl |= LPC_CLKPWR_USB_CTRL_SLAVE_HCLK | LPC_CLKPWR_USB_CTRL_BUSKEEPER;
+ lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, usbctrl);
+
+ /* Enable OTG I2C clock */
+ lpc_otg_wait_write_4(sc, LPC_OTG_CLOCK_CTRL,
+ LPC_OTG_CLOCK_STATUS, LPC_OTG_CLOCK_CTRL_I2C_EN);
+
+ /* Reset OTG I2C bus */
+ lpc_otg_i2c_reset(sc);
+
+ lpc_isp3101_configure(dev, sc);
+
+ /* Configure PLL */
+ usbctrl &= ~(LPC_CLKPWR_USB_CTRL_CLK_EN1 | LPC_CLKPWR_USB_CTRL_CLK_EN2);
+ lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, usbctrl);
+
+ usbctrl |= LPC_CLKPWR_USB_CTRL_CLK_EN1;
+ lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, usbctrl);
+
+ usbctrl |= LPC_CLKPWR_USB_CTRL_FDBKDIV(192-1);
+ usbctrl |= LPC_CLKPWR_USB_CTRL_POSTDIV(1);
+ usbctrl |= LPC_CLKPWR_USB_CTRL_PLL_PDOWN;
+
+ lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, usbctrl);
+ do {
+ usbctrl = lpc_pwr_read(dev, LPC_CLKPWR_USB_CTRL);
+ if (i++ > 100000) {
+ device_printf(dev, "USB OTG PLL doesn't lock!\n");
+ goto fail;
+ }
+ } while ((usbctrl & LPC_CLKPWR_USB_CTRL_PLL_LOCK) == 0);
+
+ usbctrl |= LPC_CLKPWR_USB_CTRL_CLK_EN2;
+ usbctrl |= LPC_CLKPWR_USB_CTRL_HOST_NEED_CLK_EN;
+ lpc_pwr_write(dev, LPC_CLKPWR_USB_CTRL, usbctrl);
+ lpc_otg_wait_write_4(sc, LPC_OTG_CLOCK_CTRL, LPC_OTG_CLOCK_STATUS,
+ (LPC_OTG_CLOCK_CTRL_AHB_EN | LPC_OTG_CLOCK_CTRL_OTG_EN |
+ LPC_OTG_CLOCK_CTRL_I2C_EN | LPC_OTG_CLOCK_CTRL_HOST_EN));
+
+ otgstatus = lpc_otg_read_4(sc, LPC_OTG_STATUS);
+ lpc_otg_write_4(sc, LPC_OTG_STATUS, otgstatus |
+ LPC_OTG_STATUS_HOST_EN);
+
+ lpc_isp3101_write(sc, LPC_ISP3101_OTG_CONTROL_1,
+ LPC_ISP3101_OTG1_VBUS_DRV);
+
+ err = ohci_init(sc);
+ if (err)
+ goto fail;
+
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ if (err)
+ goto fail;
+
+ return (0);
+
+fail:
+ if (sc->sc_intr_hdl)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr_hdl);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_io_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_io_res);
+
+ return (ENXIO);
+}
+
+static int
+lpc_isp3101_read(struct ohci_softc *sc, int reg)
+{
+ int status;
+ int i = 0;
+
+ lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX,
+ (LPC_ISP3101_I2C_ADDR << 1) | I2C_START_BIT);
+ lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, reg);
+ lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, (LPC_ISP3101_I2C_ADDR << 1) |
+ I2C_START_BIT | I2C_READ);
+ lpc_otg_write_4(sc, LPC_OTG_I2C_TXRX, I2C_STOP_BIT | DUMMY_BYTE);
+
+ do {
+ status = lpc_otg_read_4(sc, LPC_OTG_I2C_STATUS);
+ i++;
+ } while ((status & LPC_OTG_I2C_STATUS_TDI) == 0 || i < 100000);
+
+ lpc_otg_write_4(sc, LPC_OTG_I2C_STATUS, LPC_OTG_I2C_STATUS_TDI);
+
+ return (lpc_otg_read_4(sc, LPC_OTG_I2C_TXRX) & 0xff);
+}
+
+static void
+lpc_otg_i2c_reset(struct ohci_softc *sc)
+{
+ int ctrl;
+ int i = 0;
+
+ lpc_otg_write_4(sc, LPC_OTG_I2C_CLKHI, 0x3f);
+ lpc_otg_write_4(sc, LPC_OTG_I2C_CLKLO, 0x3f);
+
+ ctrl = lpc_otg_read_4(sc, LPC_OTG_I2C_CTRL);
+ lpc_otg_write_4(sc, LPC_OTG_I2C_CTRL, ctrl | LPC_OTG_I2C_CTRL_SRST);
+
+ do {
+ ctrl = lpc_otg_read_4(sc, LPC_OTG_I2C_CTRL);
+ i++;
+ } while (ctrl & LPC_OTG_I2C_CTRL_SRST);
+}
+
+static void
+lpc_isp3101_write(struct ohci_softc *sc, int reg, int value)
+{
+ int status;
+ int i = 0;
+
+ bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, LPC_OTG_I2C_TXRX,
+ (LPC_ISP3101_I2C_ADDR << 1) | I2C_START_BIT);
+ bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, LPC_OTG_I2C_TXRX,
+ (reg | I2C_WRITE));
+ bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, LPC_OTG_I2C_TXRX,
+ (value | I2C_STOP_BIT));
+
+ do {
+ status = bus_space_read_4(sc->sc_io_tag, sc->sc_io_hdl,
+ LPC_OTG_I2C_STATUS);
+ i++;
+ } while ((status & LPC_OTG_I2C_STATUS_TDI) == 0 || i < 100000);
+
+ bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, LPC_OTG_I2C_STATUS,
+ LPC_OTG_I2C_STATUS_TDI);
+}
+
+static __inline void
+lpc_isp3101_clear(struct ohci_softc *sc, int reg, int value)
+{
+ lpc_isp3101_write(sc, (reg | LPC_ISP3101_REG_CLEAR_ADDR), value);
+}
+
+static void
+lpc_isp3101_configure(device_t dev, struct ohci_softc *sc)
+{
+ lpc_isp3101_clear(sc, LPC_ISP3101_MODE_CONTROL_1, LPC_ISP3101_MC1_UART_EN);
+ lpc_isp3101_clear(sc, LPC_ISP3101_MODE_CONTROL_1, ~LPC_ISP3101_MC1_SPEED_REG);
+ lpc_isp3101_write(sc, LPC_ISP3101_MODE_CONTROL_1, LPC_ISP3101_MC1_SPEED_REG);
+ lpc_isp3101_clear(sc, LPC_ISP3101_MODE_CONTROL_2, ~0);
+ lpc_isp3101_write(sc, LPC_ISP3101_MODE_CONTROL_2,
+ (LPC_ISP3101_MC2_BI_DI | LPC_ISP3101_MC2_PSW_EN
+ | LPC_ISP3101_MC2_SPD_SUSP_CTRL));
+
+ lpc_isp3101_clear(sc, LPC_ISP3101_OTG_CONTROL_1, ~0);
+ lpc_isp3101_write(sc, LPC_ISP3101_MODE_CONTROL_1, LPC_ISP3101_MC1_DAT_SE0);
+ lpc_isp3101_write(sc, LPC_ISP3101_OTG_CONTROL_1,
+ (LPC_ISP3101_OTG1_DM_PULLDOWN | LPC_ISP3101_OTG1_DP_PULLDOWN));
+
+ lpc_isp3101_clear(sc, LPC_ISP3101_OTG_CONTROL_1,
+ (LPC_ISP3101_OTG1_DM_PULLUP | LPC_ISP3101_OTG1_DP_PULLUP));
+
+ lpc_isp3101_clear(sc, LPC_ISP3101_OTG_INTR_LATCH, ~0);
+ lpc_isp3101_clear(sc, LPC_ISP3101_OTG_INTR_FALLING, ~0);
+ lpc_isp3101_clear(sc, LPC_ISP3101_OTG_INTR_RISING, ~0);
+
+ device_printf(dev,
+ "ISP3101 PHY <vendor:0x%04x, product:0x%04x, version:0x%04x>\n",
+ (lpc_isp3101_read(sc, 0x00) | (lpc_isp3101_read(sc, 0x01) << 8)),
+ (lpc_isp3101_read(sc, 0x03) | (lpc_isp3101_read(sc, 0x04) << 8)),
+ (lpc_isp3101_read(sc, 0x14) | (lpc_isp3101_read(sc, 0x15) << 8)));
+}
+
+static int
+lpc_ohci_detach(device_t dev)
+{
+ return (0);
+}
+
+
+static device_method_t lpc_ohci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpc_ohci_probe),
+ DEVMETHOD(device_attach, lpc_ohci_attach),
+ DEVMETHOD(device_detach, lpc_ohci_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ { 0, 0 }
+};
+
+static driver_t lpc_ohci_driver = {
+ "ohci",
+ lpc_ohci_methods,
+ sizeof(struct ohci_softc),
+};
+
+static devclass_t lpc_ohci_devclass;
+
+DRIVER_MODULE(ohci, simplebus, lpc_ohci_driver, lpc_ohci_devclass, 0, 0);
+MODULE_DEPEND(ohci, usb, 1, 1, 1);
Property changes on: trunk/sys/arm/lpc/lpc_ohci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_pll.c
===================================================================
--- trunk/sys/arm/lpc/lpc_pll.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_pll.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,29 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_pll.c 239278 2012-08-15 05:37:10Z gonzo $");
Property changes on: trunk/sys/arm/lpc/lpc_pll.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_pwr.c
===================================================================
--- trunk/sys/arm/lpc/lpc_pwr.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_pwr.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,130 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_pwr.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+struct lpc_pwr_softc {
+ device_t dp_dev;
+ struct resource * dp_mem_res;
+ bus_space_tag_t dp_bst;
+ bus_space_handle_t dp_bsh;
+};
+
+static struct lpc_pwr_softc *lpc_pwr_sc = NULL;
+
+static int lpc_pwr_probe(device_t);
+static int lpc_pwr_attach(device_t);
+
+#define lpc_pwr_read_4(_sc, _reg) \
+ bus_space_read_4((_sc)->dp_bst, (_sc)->dp_bsh, _reg)
+#define lpc_pwr_write_4(_sc, _reg, _val) \
+ bus_space_write_4((_sc)->dp_bst, (_sc)->dp_bsh, _reg, _val)
+
+static int
+lpc_pwr_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,pwr"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 Power Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_pwr_attach(device_t dev)
+{
+ struct lpc_pwr_softc *sc = device_get_softc(dev);
+ int rid;
+
+ sc->dp_dev = dev;
+
+ rid = 0;
+ sc->dp_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->dp_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->dp_bst = rman_get_bustag(sc->dp_mem_res);
+ sc->dp_bsh = rman_get_bushandle(sc->dp_mem_res);
+
+ lpc_pwr_sc = sc;
+
+ return (0);
+}
+
+uint32_t
+lpc_pwr_read(device_t dev, int reg)
+{
+ return (lpc_pwr_read_4(lpc_pwr_sc, reg));
+}
+
+void
+lpc_pwr_write(device_t dev, int reg, uint32_t value)
+{
+ lpc_pwr_write_4(lpc_pwr_sc, reg, value);
+}
+
+static device_method_t lpc_pwr_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpc_pwr_probe),
+ DEVMETHOD(device_attach, lpc_pwr_attach),
+ { 0, 0 }
+};
+
+static devclass_t lpc_pwr_devclass;
+
+static driver_t lpc_pwr_driver = {
+ "pwr",
+ lpc_pwr_methods,
+ sizeof(struct lpc_pwr_softc),
+};
+
+DRIVER_MODULE(pwr, simplebus, lpc_pwr_driver, lpc_pwr_devclass, 0, 0);
Property changes on: trunk/sys/arm/lpc/lpc_pwr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_rtc.c
===================================================================
--- trunk/sys/arm/lpc/lpc_rtc.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_rtc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,151 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_rtc.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/time.h>
+#include <sys/clock.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+
+#include "clock_if.h"
+
+struct lpc_rtc_softc {
+ device_t lr_dev;
+ struct resource * lr_mem_res;
+ bus_space_tag_t lr_bst;
+ bus_space_handle_t lr_bsh;
+};
+
+static int lpc_rtc_probe(device_t dev);
+static int lpc_rtc_attach(device_t dev);
+static int lpc_rtc_gettime(device_t dev, struct timespec *ts);
+static int lpc_rtc_settime(device_t, struct timespec *);
+
+static int
+lpc_rtc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,rtc"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 real time clock");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_rtc_attach(device_t dev)
+{
+ struct lpc_rtc_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ sc->lr_dev = dev;
+
+ clock_register(dev, 1000000);
+
+ sc->lr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->lr_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->lr_bst = rman_get_bustag(sc->lr_mem_res);
+ sc->lr_bsh = rman_get_bushandle(sc->lr_mem_res);
+
+ return (0);
+}
+
+static int
+lpc_rtc_gettime(device_t dev, struct timespec *ts)
+{
+ struct lpc_rtc_softc *sc = device_get_softc(dev);
+
+ ts->tv_sec = bus_space_read_4(sc->lr_bst, sc->lr_bsh, LPC_RTC_UCOUNT);
+ ts->tv_nsec = 0;
+
+ return (0);
+}
+
+static int
+lpc_rtc_settime(device_t dev, struct timespec *ts)
+{
+ struct lpc_rtc_softc *sc = device_get_softc(dev);
+ uint32_t ctrl;
+
+ /* Stop RTC */
+ ctrl = bus_space_read_4(sc->lr_bst, sc->lr_bsh, LPC_RTC_CTRL);
+ bus_space_write_4(sc->lr_bst, sc->lr_bsh, LPC_RTC_CTRL, ctrl | LPC_RTC_CTRL_DISABLE);
+
+ /* Write actual value */
+ bus_space_write_4(sc->lr_bst, sc->lr_bsh, LPC_RTC_UCOUNT, ts->tv_sec);
+
+ /* Start RTC */
+ ctrl = bus_space_read_4(sc->lr_bst, sc->lr_bsh, LPC_RTC_CTRL);
+ bus_space_write_4(sc->lr_bst, sc->lr_bsh, LPC_RTC_CTRL, ctrl & ~LPC_RTC_CTRL_DISABLE);
+
+ return (0);
+}
+
+static device_method_t lpc_rtc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpc_rtc_probe),
+ DEVMETHOD(device_attach, lpc_rtc_attach),
+
+ /* Clock interface */
+ DEVMETHOD(clock_gettime, lpc_rtc_gettime),
+ DEVMETHOD(clock_settime, lpc_rtc_settime),
+
+ { 0, 0 },
+};
+
+static driver_t lpc_rtc_driver = {
+ "rtc",
+ lpc_rtc_methods,
+ sizeof(struct lpc_rtc_softc),
+};
+
+static devclass_t lpc_rtc_devclass;
+
+DRIVER_MODULE(rtc, simplebus, lpc_rtc_driver, lpc_rtc_devclass, 0, 0);
Property changes on: trunk/sys/arm/lpc/lpc_rtc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_spi.c
===================================================================
--- trunk/sys/arm/lpc/lpc_spi.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_spi.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,199 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_spi.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/spibus/spi.h>
+#include <dev/spibus/spibusvar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+#include "spibus_if.h"
+
+struct lpc_spi_softc
+{
+ device_t ls_dev;
+ struct resource * ls_mem_res;
+ struct resource * ls_irq_res;
+ bus_space_tag_t ls_bst;
+ bus_space_handle_t ls_bsh;
+};
+
+static int lpc_spi_probe(device_t);
+static int lpc_spi_attach(device_t);
+static int lpc_spi_detach(device_t);
+static int lpc_spi_transfer(device_t, device_t, struct spi_command *);
+
+#define lpc_spi_read_4(_sc, _reg) \
+ bus_space_read_4(_sc->ls_bst, _sc->ls_bsh, _reg)
+#define lpc_spi_write_4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->ls_bst, _sc->ls_bsh, _reg, _val)
+
+static int
+lpc_spi_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,spi"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 PL022 SPI/SSP controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_spi_attach(device_t dev)
+{
+ struct lpc_spi_softc *sc = device_get_softc(dev);
+ int rid;
+
+ sc->ls_dev = dev;
+
+ rid = 0;
+ sc->ls_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->ls_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->ls_bst = rman_get_bustag(sc->ls_mem_res);
+ sc->ls_bsh = rman_get_bushandle(sc->ls_mem_res);
+
+ rid = 0;
+ sc->ls_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->ls_irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ bus_space_write_4(sc->ls_bst, 0xd0028100, 0, (1<<12)|(1<<10)|(1<<9)|(1<<8)|(1<<6)|(1<<5));
+ lpc_pwr_write(dev, LPC_CLKPWR_SSP_CTRL, LPC_CLKPWR_SSP_CTRL_SSP0EN);
+ lpc_spi_write_4(sc, LPC_SSP_CR0, LPC_SSP_CR0_DSS(8));
+ lpc_spi_write_4(sc, LPC_SSP_CR1, LPC_SSP_CR1_SSE);
+ lpc_spi_write_4(sc, LPC_SSP_CPSR, 128);
+
+ device_add_child(dev, "spibus", 0);
+ return (bus_generic_attach(dev));
+}
+
+static int
+lpc_spi_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static int
+lpc_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
+{
+ struct lpc_spi_softc *sc = device_get_softc(dev);
+ struct spibus_ivar *devi = SPIBUS_IVAR(child);
+ uint8_t *in_buf, *out_buf;
+ int i;
+
+ /* Set CS active */
+ lpc_gpio_set_state(child, devi->cs, 0);
+
+ /* Wait for FIFO to be ready */
+ while ((lpc_spi_read_4(sc, LPC_SSP_SR) & LPC_SSP_SR_TNF) == 0);
+
+ /* Command */
+ in_buf = cmd->rx_cmd;
+ out_buf = cmd->tx_cmd;
+ for (i = 0; i < cmd->tx_cmd_sz; i++) {
+ lpc_spi_write_4(sc, LPC_SSP_DR, out_buf[i]);
+ in_buf[i] = lpc_spi_read_4(sc, LPC_SSP_DR);
+ }
+
+ /* Data */
+ in_buf = cmd->rx_data;
+ out_buf = cmd->tx_data;
+ for (i = 0; i < cmd->tx_data_sz; i++) {
+ lpc_spi_write_4(sc, LPC_SSP_DR, out_buf[i]);
+ in_buf[i] = lpc_spi_read_4(sc, LPC_SSP_DR);
+ }
+
+ /* Set CS inactive */
+ lpc_gpio_set_state(child, devi->cs, 1);
+
+ return (0);
+}
+
+static device_method_t lpc_spi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, lpc_spi_probe),
+ DEVMETHOD(device_attach, lpc_spi_attach),
+ DEVMETHOD(device_detach, lpc_spi_detach),
+
+ /* SPI interface */
+ DEVMETHOD(spibus_transfer, lpc_spi_transfer),
+
+ { 0, 0 }
+};
+
+static devclass_t lpc_spi_devclass;
+
+static driver_t lpc_spi_driver = {
+ "spi",
+ lpc_spi_methods,
+ sizeof(struct lpc_spi_softc),
+};
+
+DRIVER_MODULE(lpcspi, simplebus, lpc_spi_driver, lpc_spi_devclass, 0, 0);
Property changes on: trunk/sys/arm/lpc/lpc_spi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpc_timer.c
===================================================================
--- trunk/sys/arm/lpc/lpc_timer.c (rev 0)
+++ trunk/sys/arm/lpc/lpc_timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,309 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_timer.c 266207 2014-05-16 02:21:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+#include <sys/timeet.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+struct lpc_timer_softc {
+ device_t lt_dev;
+ struct eventtimer lt_et;
+ struct resource * lt_res[5];
+ bus_space_tag_t lt_bst0;
+ bus_space_handle_t lt_bsh0;
+ bus_space_tag_t lt_bst1;
+ bus_space_handle_t lt_bsh1;
+ int lt_oneshot;
+ uint32_t lt_period;
+};
+
+static struct resource_spec lpc_timer_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct lpc_timer_softc *timer_softc = NULL;
+static int lpc_timer_initialized = 0;
+static int lpc_timer_probe(device_t);
+static int lpc_timer_attach(device_t);
+static int lpc_timer_start(struct eventtimer *,
+ sbintime_t first, sbintime_t period);
+static int lpc_timer_stop(struct eventtimer *et);
+static unsigned lpc_get_timecount(struct timecounter *);
+static int lpc_hardclock(void *);
+
+#define timer0_read_4(sc, reg) \
+ bus_space_read_4(sc->lt_bst0, sc->lt_bsh0, reg)
+#define timer0_write_4(sc, reg, val) \
+ bus_space_write_4(sc->lt_bst0, sc->lt_bsh0, reg, val)
+#define timer0_clear(sc) \
+ do { \
+ timer0_write_4(sc, LPC_TIMER_TC, 0); \
+ timer0_write_4(sc, LPC_TIMER_PR, 0); \
+ timer0_write_4(sc, LPC_TIMER_PC, 0); \
+ } while(0)
+
+#define timer1_read_4(sc, reg) \
+ bus_space_read_4(sc->lt_bst1, sc->lt_bsh1, reg)
+#define timer1_write_4(sc, reg, val) \
+ bus_space_write_4(sc->lt_bst1, sc->lt_bsh1, reg, val)
+#define timer1_clear(sc) \
+ do { \
+ timer1_write_4(sc, LPC_TIMER_TC, 0); \
+ timer1_write_4(sc, LPC_TIMER_PR, 0); \
+ timer1_write_4(sc, LPC_TIMER_PC, 0); \
+ } while(0)
+
+static struct timecounter lpc_timecounter = {
+ .tc_get_timecount = lpc_get_timecount,
+ .tc_name = "LPC32x0 Timer1",
+ .tc_frequency = 0, /* will be filled later */
+ .tc_counter_mask = ~0u,
+ .tc_quality = 1000,
+};
+
+static int
+lpc_timer_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "lpc,timer"))
+ return (ENXIO);
+
+ device_set_desc(dev, "LPC32x0 timer");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lpc_timer_attach(device_t dev)
+{
+ void *intrcookie;
+ struct lpc_timer_softc *sc = device_get_softc(dev);
+ phandle_t node;
+ uint32_t freq;
+
+ if (timer_softc)
+ return (ENXIO);
+
+ timer_softc = sc;
+
+ if (bus_alloc_resources(dev, lpc_timer_spec, sc->lt_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->lt_bst0 = rman_get_bustag(sc->lt_res[0]);
+ sc->lt_bsh0 = rman_get_bushandle(sc->lt_res[0]);
+ sc->lt_bst1 = rman_get_bustag(sc->lt_res[1]);
+ sc->lt_bsh1 = rman_get_bushandle(sc->lt_res[1]);
+
+ if (bus_setup_intr(dev, sc->lt_res[2], INTR_TYPE_CLK,
+ lpc_hardclock, NULL, sc, &intrcookie)) {
+ device_printf(dev, "could not setup interrupt handler\n");
+ bus_release_resources(dev, lpc_timer_spec, sc->lt_res);
+ return (ENXIO);
+ }
+
+ /* Enable timer clock */
+ lpc_pwr_write(dev, LPC_CLKPWR_TIMCLK_CTRL1,
+ LPC_CLKPWR_TIMCLK_CTRL1_TIMER0 |
+ LPC_CLKPWR_TIMCLK_CTRL1_TIMER1);
+
+ /* Get PERIPH_CLK encoded in parent bus 'bus-frequency' property */
+ node = ofw_bus_get_node(dev);
+ if (OF_getprop(OF_parent(node), "bus-frequency", &freq,
+ sizeof(pcell_t)) <= 0) {
+ bus_release_resources(dev, lpc_timer_spec, sc->lt_res);
+ bus_teardown_intr(dev, sc->lt_res[2], intrcookie);
+ device_printf(dev, "could not obtain base clock frequency\n");
+ return (ENXIO);
+ }
+
+ freq = fdt32_to_cpu(freq);
+
+ /* Set desired frequency in event timer and timecounter */
+ sc->lt_et.et_frequency = (uint64_t)freq;
+ lpc_timecounter.tc_frequency = (uint64_t)freq;
+
+ sc->lt_et.et_name = "LPC32x0 Timer0";
+ sc->lt_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
+ sc->lt_et.et_quality = 1000;
+ sc->lt_et.et_min_period = (0x00000002LLU << 32) / sc->lt_et.et_frequency;
+ sc->lt_et.et_max_period = (0xfffffffeLLU << 32) / sc->lt_et.et_frequency;
+ sc->lt_et.et_start = lpc_timer_start;
+ sc->lt_et.et_stop = lpc_timer_stop;
+ sc->lt_et.et_priv = sc;
+
+ et_register(&sc->lt_et);
+ tc_init(&lpc_timecounter);
+
+ /* Reset and enable timecounter */
+ timer1_write_4(sc, LPC_TIMER_TCR, LPC_TIMER_TCR_RESET);
+ timer1_write_4(sc, LPC_TIMER_TCR, 0);
+ timer1_clear(sc);
+ timer1_write_4(sc, LPC_TIMER_TCR, LPC_TIMER_TCR_ENABLE);
+
+ /* DELAY() now can work properly */
+ lpc_timer_initialized = 1;
+
+ return (0);
+}
+
+static int
+lpc_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct lpc_timer_softc *sc = (struct lpc_timer_softc *)et->et_priv;
+ uint32_t ticks;
+
+ if (period == 0) {
+ sc->lt_oneshot = 1;
+ sc->lt_period = 0;
+ } else {
+ sc->lt_oneshot = 0;
+ sc->lt_period = ((uint32_t)et->et_frequency * period) >> 32;
+ }
+
+ if (first == 0)
+ ticks = sc->lt_period;
+ else
+ ticks = ((uint32_t)et->et_frequency * first) >> 32;
+
+ /* Reset timer */
+ timer0_write_4(sc, LPC_TIMER_TCR, LPC_TIMER_TCR_RESET);
+ timer0_write_4(sc, LPC_TIMER_TCR, 0);
+
+ /* Start timer */
+ timer0_clear(sc);
+ timer0_write_4(sc, LPC_TIMER_MR0, ticks);
+ timer0_write_4(sc, LPC_TIMER_MCR, LPC_TIMER_MCR_MR0I | LPC_TIMER_MCR_MR0S);
+ timer0_write_4(sc, LPC_TIMER_TCR, LPC_TIMER_TCR_ENABLE);
+ return (0);
+}
+
+static int
+lpc_timer_stop(struct eventtimer *et)
+{
+ struct lpc_timer_softc *sc = (struct lpc_timer_softc *)et->et_priv;
+
+ timer0_write_4(sc, LPC_TIMER_TCR, 0);
+ return (0);
+}
+
+static device_method_t lpc_timer_methods[] = {
+ DEVMETHOD(device_probe, lpc_timer_probe),
+ DEVMETHOD(device_attach, lpc_timer_attach),
+ { 0, 0 }
+};
+
+static driver_t lpc_timer_driver = {
+ "timer",
+ lpc_timer_methods,
+ sizeof(struct lpc_timer_softc),
+};
+
+static devclass_t lpc_timer_devclass;
+
+DRIVER_MODULE(timer, simplebus, lpc_timer_driver, lpc_timer_devclass, 0, 0);
+
+static int
+lpc_hardclock(void *arg)
+{
+ struct lpc_timer_softc *sc = (struct lpc_timer_softc *)arg;
+
+ /* Reset pending interrupt */
+ timer0_write_4(sc, LPC_TIMER_IR, 0xffffffff);
+
+ /* Start timer again */
+ if (!sc->lt_oneshot) {
+ timer0_clear(sc);
+ timer0_write_4(sc, LPC_TIMER_MR0, sc->lt_period);
+ timer0_write_4(sc, LPC_TIMER_TCR, LPC_TIMER_TCR_ENABLE);
+ }
+
+ if (sc->lt_et.et_active)
+ sc->lt_et.et_event_cb(&sc->lt_et, sc->lt_et.et_arg);
+
+ return (FILTER_HANDLED);
+}
+
+static unsigned
+lpc_get_timecount(struct timecounter *tc)
+{
+ return timer1_read_4(timer_softc, LPC_TIMER_TC);
+}
+
+void
+DELAY(int usec)
+{
+ uint32_t counter;
+ uint32_t first, last;
+ int val = (lpc_timecounter.tc_frequency / 1000000 + 1) * usec;
+
+ /* Timer is not initialized yet */
+ if (!lpc_timer_initialized) {
+ for (; usec > 0; usec--)
+ for (counter = 100; counter > 0; counter--)
+ ;
+ return;
+ }
+
+ first = lpc_get_timecount(&lpc_timecounter);
+ while (val > 0) {
+ last = lpc_get_timecount(&lpc_timecounter);
+ if (last < first) {
+ /* Timer rolled over */
+ last = first;
+ }
+
+ val -= (last - first);
+ first = last;
+ }
+}
Property changes on: trunk/sys/arm/lpc/lpc_timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpcreg.h
===================================================================
--- trunk/sys/arm/lpc/lpcreg.h (rev 0)
+++ trunk/sys/arm/lpc/lpcreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,666 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/lpc/lpcreg.h 266084 2014-05-14 19:18:58Z ian $
+ */
+
+#ifndef _ARM_LPC_LPCREG_H
+#define _ARM_LPC_LPCREG_H
+
+#define LPC_DEV_PHYS_BASE 0x40000000
+#define LPC_DEV_P5_PHYS_BASE 0x20000000
+#define LPC_DEV_P6_PHYS_BASE 0x30000000
+#define LPC_DEV_SIZE 0x10000000
+
+/*
+ * Interrupt controller (from UM10326: LPC32x0 User manual, page 87)
+
+ */
+#define LPC_INTC_MIC_ER 0x0000
+#define LPC_INTC_MIC_RSR 0x0004
+#define LPC_INTC_MIC_SR 0x0008
+#define LPC_INTC_MIC_APR 0x000c
+#define LPC_INTC_MIC_ATR 0x0010
+#define LPC_INTC_MIC_ITR 0x0014
+#define LPC_INTC_SIC1_ER 0x4000
+#define LPC_INTC_SIC1_RSR 0x4004
+#define LPC_INTC_SIC1_SR 0x4008
+#define LPC_INTC_SIC1_APR 0x400c
+#define LPC_INTC_SIC1_ATR 0x4010
+#define LPC_INTC_SIC1_ITR 0x4014
+#define LPC_INTC_SIC2_ER 0x8000
+#define LPC_INTC_SIC2_RSR 0x8004
+#define LPC_INTC_SIC2_SR 0x8008
+#define LPC_INTC_SIC2_APR 0x800c
+#define LPC_INTC_SIC2_ATR 0x8010
+#define LPC_INTC_SIC2_ITR 0x8014
+
+
+/*
+ * Timer 0|1|2|3|4|5. (from UM10326: LPC32x0 User manual, page 540)
+ */
+#define LPC_TIMER_IR 0x00
+#define LPC_TIMER_TCR 0x04
+#define LPC_TIMER_TCR_ENABLE (1 << 0)
+#define LPC_TIMER_TCR_RESET (1 << 1)
+#define LPC_TIMER_TC 0x08
+#define LPC_TIMER_PR 0x0c
+#define LPC_TIMER_PC 0x10
+#define LPC_TIMER_MCR 0x14
+#define LPC_TIMER_MCR_MR0I (1 << 0)
+#define LPC_TIMER_MCR_MR0R (1 << 1)
+#define LPC_TIMER_MCR_MR0S (1 << 2)
+#define LPC_TIMER_MCR_MR1I (1 << 3)
+#define LPC_TIMER_MCR_MR1R (1 << 4)
+#define LPC_TIMER_MCR_MR1S (1 << 5)
+#define LPC_TIMER_MCR_MR2I (1 << 6)
+#define LPC_TIMER_MCR_MR2R (1 << 7)
+#define LPC_TIMER_MCR_MR2S (1 << 8)
+#define LPC_TIMER_MCR_MR3I (1 << 9)
+#define LPC_TIMER_MCR_MR3R (1 << 10)
+#define LPC_TIMER_MCR_MR3S (1 << 11)
+#define LPC_TIMER_MR0 0x18
+#define LPC_TIMER_CTCR 0x70
+
+/*
+ * Watchdog timer. (from UM10326: LPC32x0 User manual, page 572)
+ */
+#define LPC_WDTIM_PHYS_BASE (LPC_DEV_PHYS_BASE + 0x3c000)
+#define LPC_WDTIM_INT 0x00
+#define LPC_WDTIM_CTRL 0x04
+#define LPC_WDTIM_COUNTER 0x08
+#define LPC_WDTIM_MCTRL 0x0c
+#define LPC_WDTIM_MATCH0 0x10
+#define LPC_WDTIM_EMR 0x14
+#define LPC_WDTIM_PULSE 0x18
+#define LPC_WDTIM_RES 0x1c
+#define LPC_WDTIM_SIZE 0x20
+
+/*
+ * Clocking and power control. (from UM10326: LPC32x0 User manual, page 58)
+ */
+#define LPC_CLKPWR_PHYS_BASE (LPC_DEV_PHYS_BASE + 0x4000)
+#define LPC_CLKPWR_PWR_CTRL 0x44
+#define LPC_CLKPWR_OSC_CTRL 0x4c
+#define LPC_CLKPWR_SYSCLK_CTRL 0x50
+#define LPC_CLKPWR_PLL397_CTRL 0x48
+#define LPC_CLKPWR_HCLKPLL_CTRL 0x58
+#define LPC_CLKPWR_HCLKDIV_CTRL 0x40
+#define LPC_CLKPWR_TEST_CTRL 0xa4
+#define LPC_CLKPWR_AUTOCLK_CTRL 0xec
+#define LPC_CLKPWR_START_ER_PIN 0x30
+#define LPC_CLKPWR_START_ER_INT 0x20
+#define LPC_CLKPWR_P0_INTR_ER 0x18
+#define LPC_CLKPWR_START_SR_PIN 0x38
+#define LPC_CLKPWR_START_SR_INT 0x28
+#define LPC_CLKPWR_START_RSR_PIN 0x34
+#define LPC_CLKPWR_START_RSR_INT 0x24
+#define LPC_CLKPWR_START_APR_PIN 0x3c
+#define LPC_CLKPWR_START_APR_INT 0x2c
+#define LPC_CLKPWR_USB_CTRL 0x64
+#define LPC_CLKPWR_USB_CTRL_SLAVE_HCLK (1 << 24)
+#define LPC_CLKPWR_USB_CTRL_I2C_EN (1 << 23)
+#define LPC_CLKPWR_USB_CTRL_DEV_NEED_CLK_EN (1 << 22)
+#define LPC_CLKPWR_USB_CTRL_HOST_NEED_CLK_EN (1 << 21)
+#define LPC_CLKPWR_USB_CTRL_BUSKEEPER (1 << 19)
+#define LPC_CLKPWR_USB_CTRL_CLK_EN2 (1 << 18)
+#define LPC_CLKPWR_USB_CTRL_CLK_EN1 (1 << 17)
+#define LPC_CLKPWR_USB_CTRL_PLL_PDOWN (1 << 16)
+#define LPC_CLKPWR_USB_CTRL_BYPASS (1 << 15)
+#define LPC_CLKPWR_USB_CTRL_DIRECT_OUT (1 << 14)
+#define LPC_CLKPWR_USB_CTRL_FEEDBACK (1 << 13)
+#define LPC_CLKPWR_USB_CTRL_POSTDIV(_x) ((_x & 0x3) << 11)
+#define LPC_CLKPWR_USB_CTRL_PREDIV(_x) ((_x & 0x3) << 9)
+#define LPC_CLKPWR_USB_CTRL_FDBKDIV(_x) (((_x-1) & 0xff) << 1)
+#define LPC_CLKPWR_USB_CTRL_PLL_LOCK (1 << 0)
+#define LPC_CLKPWR_USBDIV_CTRL 0x1c
+#define LPC_CLKPWR_MS_CTRL 0x80
+#define LPC_CLKPWR_MS_CTRL_DISABLE_SD (1 << 10)
+#define LPC_CLKPWR_MS_CTRL_CLOCK_EN (1 << 9)
+#define LPC_CLKPWR_MS_CTRL_MSSDIO23_PAD (1 << 8)
+#define LPC_CLKPWR_MS_CTRL_MSSDIO1_PAD (1 << 7)
+#define LPC_CLKPWR_MS_CTRL_MSSDIO0_PAD (1 << 6)
+#define LPC_CLKPWR_MS_CTRL_SD_CLOCK (1 << 5)
+#define LPC_CLKPWR_MS_CTRL_CLKDIV_MASK 0xf
+#define LPC_CLKPWR_DMACLK_CTRL 0xe8
+#define LPC_CLKPWR_DMACLK_CTRL_EN (1 << 0)
+#define LPC_CLKPWR_FLASHCLK_CTRL 0xc8
+#define LPC_CLKPWR_MACCLK_CTRL 0x90
+#define LPC_CLKPWR_MACCLK_CTRL_REG (1 << 0)
+#define LPC_CLKPWR_MACCLK_CTRL_SLAVE (1 << 1)
+#define LPC_CLKPWR_MACCLK_CTRL_MASTER (1 << 2)
+#define LPC_CLKPWR_MACCLK_CTRL_HDWINF(_n) ((_n & 0x3) << 3)
+#define LPC_CLKPWR_LCDCLK_CTRL 0x54
+#define LPC_CLKPWR_LCDCLK_CTRL_DISPTYPE (1 << 8)
+#define LPC_CLKPWR_LCDCLK_CTRL_MODE(_n) ((_n & 0x3) << 6)
+#define LPC_CLKPWR_LCDCLK_CTRL_MODE_12 0x0
+#define LPC_CLKPWR_LCDCLK_CTRL_MODE_15 0x1
+#define LPC_CLKPWR_LCDCLK_CTRL_MODE_16 0x2
+#define LPC_CLKPWR_LCDCLK_CTRL_MODE_24 0x3
+#define LPC_CLKPWR_LCDCLK_CTRL_HCLKEN (1 << 5)
+#define LPC_CLKPWR_LCDCLK_CTRL_CLKDIV(_n) ((_n) & 0x1f)
+#define LPC_CLKPWR_I2S_CTRL 0x7c
+#define LPC_CLKPWR_SSP_CTRL 0x78
+#define LPC_CLKPWR_SSP_CTRL_SSP1RXDMA (1 << 5)
+#define LPC_CLKPWR_SSP_CTRL_SSP1TXDMA (1 << 4)
+#define LPC_CLKPWR_SSP_CTRL_SSP0RXDMA (1 << 3)
+#define LPC_CLKPWR_SSP_CTRL_SSP0TXDMA (1 << 2)
+#define LPC_CLKPWR_SSP_CTRL_SSP1EN (1 << 1)
+#define LPC_CLKPWR_SSP_CTRL_SSP0EN (1 << 0)
+#define LPC_CLKPWR_SPI_CTRL 0xc4
+#define LPC_CLKPWR_I2CCLK_CTRL 0xac
+#define LPC_CLKPWR_TIMCLK_CTRL1 0xc0
+#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER4 (1 << 0)
+#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER5 (1 << 1)
+#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER0 (1 << 2)
+#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER1 (1 << 3)
+#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER2 (1 << 4)
+#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER3 (1 << 5)
+#define LPC_CLKPWR_TIMCLK_CTRL1_MOTORCTL (1 << 6)
+#define LPC_CLKPWR_TIMCLK_CTRL 0xbc
+#define LPC_CLKPWR_TIMCLK_CTRL_WATCHDOG (1 << 0)
+#define LPC_CLKPWR_TIMCLK_CTRL_HSTIMER (1 << 1)
+#define LPC_CLKPWR_ADCLK_CTRL 0xb4
+#define LPC_CLKPWR_ADCLK_CTRL1 0x60
+#define LPC_CLKPWR_KEYCLK_CTRL 0xb0
+#define LPC_CLKPWR_PWMCLK_CTRL 0xb8
+#define LPC_CLKPWR_UARTCLK_CTRL 0xe4
+#define LPC_CLKPWR_POS0_IRAM_CTRL 0x110
+#define LPC_CLKPWR_POS1_IRAM_CTRL 0x114
+#define LPC_CLKPWR_SIZE 0x118
+
+/* Additional UART registers in CLKPWR address space. */
+#define LPC_CLKPWR_UART_U3CLK 0xd0
+#define LPC_CLKPWR_UART_U4CLK 0xd4
+#define LPC_CLKPWR_UART_U5CLK 0xd8
+#define LPC_CLKPWR_UART_U6CLK 0xdc
+#define LPC_CLKPWR_UART_UCLK_HCLK (1 << 16)
+#define LPC_CLKPWR_UART_UCLK_X(_n) (((_n) & 0xff) << 8)
+#define LPC_CLKPWR_UART_UCLK_Y(_n) ((_n) & 0xff)
+#define LPC_CLKPWR_UART_IRDACLK 0xe0
+
+/* Additional UART registers */
+#define LPC_UART_BASE 0x80000
+#define LPC_UART_CONTROL_BASE 0x54000
+#define LPC_UART5_BASE 0x90000
+#define LPC_UART_CTRL 0x00
+#define LPC_UART_CLKMODE 0x04
+#define LPC_UART_CLKMODE_UART3(_n) (((_n) & 0x3) << 4)
+#define LPC_UART_CLKMODE_UART4(_n) (((_n) & 0x3) << 6)
+#define LPC_UART_CLKMODE_UART5(_n) (((_n) & 0x3) << 8)
+#define LPC_UART_CLKMODE_UART6(_n) (((_n) & 0x3) << 10)
+#define LPC_UART_LOOP 0x08
+#define LPC_UART_CONTROL_SIZE 0x0c
+#define LPC_UART_FIFOSIZE 64
+
+/*
+ * Real time clock. (from UM10326: LPC32x0 User manual, page 566)
+ */
+#define LPC_RTC_UCOUNT 0x00
+#define LPC_RTC_DCOUNT 0x04
+#define LPC_RTC_MATCH0 0x08
+#define LPC_RTC_MATCH1 0x0c
+#define LPC_RTC_CTRL 0x10
+#define LPC_RTC_CTRL_ONSW (1 << 7)
+#define LPC_RTC_CTRL_DISABLE (1 << 6)
+#define LPC_RTC_CTRL_RTCRESET (1 << 4)
+#define LPC_RTC_CTRL_MATCH0ONSW (1 << 3)
+#define LPC_RTC_CTRL_MATCH1ONSW (1 << 2)
+#define LPC_RTC_CTRL_MATCH1INTR (1 << 1)
+#define LPC_RTC_CTRL_MATCH0INTR (1 << 0)
+#define LPC_RTC_INTSTAT 0x14
+#define LPC_RTC_KEY 0x18
+#define LPC_RTC_SRAM_BEGIN 0x80
+#define LPC_RTC_SRAM_END 0xff
+
+/*
+ * MMC/SD controller. (from UM10326: LPC32x0 User manual, page 436)
+ */
+#define LPC_SD_PHYS_BASE (LPC_DEV_P5_PHYS_BASE + 0x98000)
+#define LPC_SD_CLK (13 * 1000 * 1000) // 13Mhz
+#define LPC_SD_POWER 0x00
+#define LPC_SD_POWER_OPENDRAIN (1 << 6)
+#define LPC_SD_POWER_CTRL_OFF 0x00
+#define LPC_SD_POWER_CTRL_UP 0x02
+#define LPC_SD_POWER_CTRL_ON 0x03
+#define LPC_SD_CLOCK 0x04
+#define LPC_SD_CLOCK_WIDEBUS (1 << 11)
+#define LPC_SD_CLOCK_BYPASS (1 << 10)
+#define LPC_SD_CLOCK_PWRSAVE (1 << 9)
+#define LPC_SD_CLOCK_ENABLE (1 << 8)
+#define LPC_SD_CLOCK_CLKDIVMASK 0xff
+#define LPC_SD_ARGUMENT 0x08
+#define LPC_SD_COMMAND 0x0c
+#define LPC_SD_COMMAND_ENABLE (1 << 10)
+#define LPC_SD_COMMAND_PENDING (1 << 9)
+#define LPC_SD_COMMAND_INTERRUPT (1 << 8)
+#define LPC_SD_COMMAND_LONGRSP (1 << 7)
+#define LPC_SD_COMMAND_RESPONSE (1 << 6)
+#define LPC_SD_COMMAND_CMDINDEXMASK 0x3f
+#define LPC_SD_RESPCMD 0x10
+#define LPC_SD_RESP0 0x14
+#define LPC_SD_RESP1 0x18
+#define LPC_SD_RESP2 0x1c
+#define LPC_SD_RESP3 0x20
+#define LPC_SD_DATATIMER 0x24
+#define LPC_SD_DATALENGTH 0x28
+#define LPC_SD_DATACTRL 0x2c
+#define LPC_SD_DATACTRL_BLOCKSIZESHIFT 4
+#define LPC_SD_DATACTRL_BLOCKSIZEMASK 0xf
+#define LPC_SD_DATACTRL_DMAENABLE (1 << 3)
+#define LPC_SD_DATACTRL_MODE (1 << 2)
+#define LPC_SD_DATACTRL_WRITE (0 << 1)
+#define LPC_SD_DATACTRL_READ (1 << 1)
+#define LPC_SD_DATACTRL_ENABLE (1 << 0)
+#define LPC_SD_DATACNT 0x30
+#define LPC_SD_STATUS 0x34
+#define LPC_SD_STATUS_RXDATAAVLBL (1 << 21)
+#define LPC_SD_STATUS_TXDATAAVLBL (1 << 20)
+#define LPC_SD_STATUS_RXFIFOEMPTY (1 << 19)
+#define LPC_SD_STATUS_TXFIFOEMPTY (1 << 18)
+#define LPC_SD_STATUS_RXFIFOFULL (1 << 17)
+#define LPC_SD_STATUS_TXFIFOFULL (1 << 16)
+#define LPC_SD_STATUS_RXFIFOHALFFULL (1 << 15)
+#define LPC_SD_STATUS_TXFIFOHALFEMPTY (1 << 14)
+#define LPC_SD_STATUS_RXACTIVE (1 << 13)
+#define LPC_SD_STATUS_TXACTIVE (1 << 12)
+#define LPC_SD_STATUS_CMDACTIVE (1 << 11)
+#define LPC_SD_STATUS_DATABLOCKEND (1 << 10)
+#define LPC_SD_STATUS_STARTBITERR (1 << 9)
+#define LPC_SD_STATUS_DATAEND (1 << 8)
+#define LPC_SD_STATUS_CMDSENT (1 << 7)
+#define LPC_SD_STATUS_CMDRESPEND (1 << 6)
+#define LPC_SD_STATUS_RXOVERRUN (1 << 5)
+#define LPC_SD_STATUS_TXUNDERRUN (1 << 4)
+#define LPC_SD_STATUS_DATATIMEOUT (1 << 3)
+#define LPC_SD_STATUS_CMDTIMEOUT (1 << 2)
+#define LPC_SD_STATUS_DATACRCFAIL (1 << 1)
+#define LPC_SD_STATUS_CMDCRCFAIL (1 << 0)
+#define LPC_SD_CLEAR 0x38
+#define LPC_SD_MASK0 0x03c
+#define LPC_SD_MASK1 0x40
+#define LPC_SD_FIFOCNT 0x48
+#define LPC_SD_FIFO 0x80
+
+/*
+ * USB OTG controller (from UM10326: LPC32x0 User manual, page 410)
+ */
+#define LPC_OTG_INT_STATUS 0x100
+#define LPC_OTG_INT_ENABLE 0x104
+#define LPC_OTG_INT_SET 0x108
+#define LPC_OTG_INT_CLEAR 0x10c
+#define LPC_OTG_STATUS 0x110
+#define LPC_OTG_STATUS_ATOB_HNP_TRACK (1 << 9)
+#define LPC_OTG_STATUS_BTOA_HNP_TACK (1 << 8)
+#define LPC_OTG_STATUS_TRANSP_I2C_EN (1 << 7)
+#define LPC_OTG_STATUS_TIMER_RESET (1 << 6)
+#define LPC_OTG_STATUS_TIMER_EN (1 << 5)
+#define LPC_OTG_STATUS_TIMER_MODE (1 << 4)
+#define LPC_OTG_STATUS_TIMER_SCALE (1 << 2)
+#define LPC_OTG_STATUS_HOST_EN (1 << 0)
+#define LPC_OTG_TIMER 0x114
+#define LPC_OTG_I2C_TXRX 0x300
+#define LPC_OTG_I2C_STATUS 0x304
+#define LPC_OTG_I2C_STATUS_TFE (1 << 11)
+#define LPC_OTG_I2C_STATUS_TFF (1 << 10)
+#define LPC_OTG_I2C_STATUS_RFE (1 << 9)
+#define LPC_OTG_I2C_STATUS_RFF (1 << 8)
+#define LPC_OTG_I2C_STATUS_SDA (1 << 7)
+#define LPC_OTG_I2C_STATUS_SCL (1 << 6)
+#define LPC_OTG_I2C_STATUS_ACTIVE (1 << 5)
+#define LPC_OTG_I2C_STATUS_DRSI (1 << 4)
+#define LPC_OTG_I2C_STATUS_DRMI (1 << 3)
+#define LPC_OTG_I2C_STATUS_NAI (1 << 2)
+#define LPC_OTG_I2C_STATUS_AFI (1 << 1)
+#define LPC_OTG_I2C_STATUS_TDI (1 << 0)
+#define LPC_OTG_I2C_CTRL 0x308
+#define LPC_OTG_I2C_CTRL_SRST (1 << 8)
+#define LPC_OTG_I2C_CTRL_TFFIE (1 << 7)
+#define LPC_OTG_I2C_CTRL_RFDAIE (1 << 6)
+#define LPC_OTG_I2C_CTRL_RFFIE (1 << 5)
+#define LPC_OTG_I2C_CTRL_DRSIE (1 << 4)
+#define LPC_OTG_I2C_CTRL_DRMIE (1 << 3)
+#define LPC_OTG_I2C_CTRL_NAIE (1 << 2)
+#define LPC_OTG_I2C_CTRL_AFIE (1 << 1)
+#define LPC_OTG_I2C_CTRL_TDIE (1 << 0)
+#define LPC_OTG_I2C_CLKHI 0x30c
+#define LPC_OTG_I2C_CLKLO 0x310
+#define LPC_OTG_CLOCK_CTRL 0xff4
+#define LPC_OTG_CLOCK_CTRL_AHB_EN (1 << 4)
+#define LPC_OTG_CLOCK_CTRL_OTG_EN (1 << 3)
+#define LPC_OTG_CLOCK_CTRL_I2C_EN (1 << 2)
+#define LPC_OTG_CLOCK_CTRL_DEV_EN (1 << 1)
+#define LPC_OTG_CLOCK_CTRL_HOST_EN (1 << 0)
+#define LPC_OTG_CLOCK_STATUS 0xff8
+
+/*
+ * ISP3101 USB transceiver registers
+ */
+#define LPC_ISP3101_I2C_ADDR 0x2d
+#define LPC_ISP3101_MODE_CONTROL_1 0x04
+#define LPC_ISP3101_MC1_SPEED_REG (1 << 0)
+#define LPC_ISP3101_MC1_SUSPEND_REG (1 << 1)
+#define LPC_ISP3101_MC1_DAT_SE0 (1 << 2)
+#define LPC_ISP3101_MC1_TRANSPARENT (1 << 3)
+#define LPC_ISP3101_MC1_BDIS_ACON_EN (1 << 4)
+#define LPC_ISP3101_MC1_OE_INT_EN (1 << 5)
+#define LPC_ISP3101_MC1_UART_EN (1 << 6)
+#define LPC_ISP3101_MODE_CONTROL_2 0x12
+#define LPC_ISP3101_MC2_GLOBAL_PWR_DN (1 << 0)
+#define LPC_ISP3101_MC2_SPD_SUSP_CTRL (1 << 1)
+#define LPC_ISP3101_MC2_BI_DI (1 << 2)
+#define LPC_ISP3101_MC2_TRANSP_BDIR0 (1 << 3)
+#define LPC_ISP3101_MC2_TRANSP_BDIR1 (1 << 4)
+#define LPC_ISP3101_MC2_AUDIO_EN (1 << 5)
+#define LPC_ISP3101_MC2_PSW_EN (1 << 6)
+#define LPC_ISP3101_MC2_EN2V7 (1 << 7)
+#define LPC_ISP3101_OTG_CONTROL_1 0x06
+#define LPC_ISP3101_OTG1_DP_PULLUP (1 << 0)
+#define LPC_ISP3101_OTG1_DM_PULLUP (1 << 1)
+#define LPC_ISP3101_OTG1_DP_PULLDOWN (1 << 2)
+#define LPC_ISP3101_OTG1_DM_PULLDOWN (1 << 3)
+#define LPC_ISP3101_OTG1_ID_PULLDOWN (1 << 4)
+#define LPC_ISP3101_OTG1_VBUS_DRV (1 << 5)
+#define LPC_ISP3101_OTG1_VBUS_DISCHRG (1 << 6)
+#define LPC_ISP3101_OTG1_VBUS_CHRG (1 << 7)
+#define LPC_ISP3101_OTG_CONTROL_2 0x10
+#define LPC_ISP3101_OTG_INTR_LATCH 0x0a
+#define LPC_ISP3101_OTG_INTR_FALLING 0x0c
+#define LPC_ISP3101_OTG_INTR_RISING 0x0e
+#define LPC_ISP3101_REG_CLEAR_ADDR 0x01
+
+/*
+ * LCD Controller (from UM10326: LPC32x0 User manual, page 229)
+ */
+#define LPC_LCD_TIMH 0x00
+#define LPC_LCD_TIMH_HBP(_n) (((_n) & 0xff) << 24)
+#define LPC_LCD_TIMH_HFP(_n) (((_n) & 0xff) << 16)
+#define LPC_LCD_TIMH_HSW(_n) (((_n) & 0xff) << 8)
+#define LPC_LCD_TIMH_PPL(_n) (((_n) / 16 - 1) << 2)
+#define LPC_LCD_TIMV 0x04
+#define LPC_LCD_TIMV_VBP(_n) (((_n) & 0xff) << 24)
+#define LPC_LCD_TIMV_VFP(_n) (((_n) & 0xff) << 16)
+#define LPC_LCD_TIMV_VSW(_n) (((_n) & 0x3f) << 10)
+#define LPC_LCD_TIMV_LPP(_n) ((_n) & 0x1ff)
+#define LPC_LCD_POL 0x08
+#define LPC_LCD_POL_PCD_HI (((_n) & 0x1f) << 27)
+#define LPC_LCD_POL_BCD (1 << 26)
+#define LPC_LCD_POL_CPL(_n) (((_n) & 0x3ff) << 16)
+#define LPC_LCD_POL_IOE (1 << 14)
+#define LPC_LCD_POL_IPC (1 << 13)
+#define LPC_LCD_POL_IHS (1 << 12)
+#define LPC_LCD_POL_IVS (1 << 11)
+#define LPC_LCD_POL_ACB(_n) ((_n & 0x1f) << 6)
+#define LPC_LCD_POL_CLKSEL (1 << 5)
+#define LPC_LCD_POL_PCD_LO(_n) ((_n) & 0x1f)
+#define LPC_LCD_LE 0x0c
+#define LPC_LCD_LE_LEE (1 << 16)
+#define LPC_LCD_LE_LED ((_n) & 0x7f)
+#define LPC_LCD_UPBASE 0x10
+#define LPC_LCD_LPBASE 0x14
+#define LPC_LCD_CTRL 0x18
+#define LPC_LCD_CTRL_WATERMARK (1 << 16)
+#define LPC_LCD_CTRL_LCDVCOMP(_n) (((_n) & 0x3) << 12)
+#define LPC_LCD_CTRL_LCDPWR (1 << 11)
+#define LPC_LCD_CTRL_BEPO (1 << 10)
+#define LPC_LCD_CTRL_BEBO (1 << 9)
+#define LPC_LCD_CTRL_BGR (1 << 8)
+#define LPC_LCD_CTRL_LCDDUAL (1 << 7)
+#define LPC_LCD_CTRL_LCDMONO8 (1 << 6)
+#define LPC_LCD_CTRL_LCDTFT (1 << 5)
+#define LPC_LCD_CTRL_LCDBW (1 << 4)
+#define LPC_LCD_CTRL_LCDBPP(_n) (((_n) & 0x7) << 1)
+#define LPC_LCD_CTRL_BPP1 0
+#define LPC_LCD_CTRL_BPP2 1
+#define LPC_LCD_CTRL_BPP4 2
+#define LPC_LCD_CTRL_BPP8 3
+#define LPC_LCD_CTRL_BPP16 4
+#define LPC_LCD_CTRL_BPP24 5
+#define LPC_LCD_CTRL_BPP16_565 6
+#define LPC_LCD_CTRL_BPP12_444 7
+#define LPC_LCD_CTRL_LCDEN (1 << 0)
+#define LPC_LCD_INTMSK 0x1c
+#define LPC_LCD_INTRAW 0x20
+#define LPC_LCD_INTSTAT 0x24
+#define LPC_LCD_INTCLR 0x28
+#define LPC_LCD_UPCURR 0x2c
+#define LPC_LCD_LPCURR 0x30
+#define LPC_LCD_PAL 0x200
+#define LPC_LCD_CRSR_IMG 0x800
+#define LPC_LCD_CRSR_CTRL 0xc00
+#define LPC_LCD_CRSR_CFG 0xc04
+#define LPC_LCD_CRSR_PAL0 0xc08
+#define LPC_LCD_CRSR_PAL1 0xc0c
+#define LPC_LCD_CRSR_XY 0xc10
+#define LPC_LCD_CRSR_CLIP 0xc14
+#define LPC_LCD_CRSR_INTMSK 0xc20
+#define LPC_LCD_CRSR_INTCLR 0xc24
+#define LPC_LCD_CRSR_INTRAW 0xc28
+#define LPC_LCD_CRSR_INTSTAT 0xc2c
+
+/*
+ * SPI interface (from UM10326: LPC32x0 User manual, page 483)
+ */
+#define LPC_SPI_GLOBAL 0x00
+#define LPC_SPI_GLOBAL_RST (1 << 1)
+#define LPC_SPI_GLOBAL_ENABLE (1 << 0)
+#define LPC_SPI_CON 0x04
+#define LPC_SPI_CON_UNIDIR (1 << 23)
+#define LPC_SPI_CON_BHALT (1 << 22)
+#define LPC_SPI_CON_BPOL (1 << 21)
+#define LPC_SPI_CON_MSB (1 << 19)
+#define LPC_SPI_CON_MODE(_n) ((_n & 0x3) << 16)
+#define LPC_SPI_CON_RXTX (1 << 15)
+#define LPC_SPI_CON_THR (1 << 14)
+#define LPC_SPI_CON_SHIFT_OFF (1 << 13)
+#define LPC_SPI_CON_BITNUM(_n) ((_n & 0xf) << 9)
+#define LPC_SPI_CON_MS (1 << 7)
+#define LPC_SPI_CON_RATE(_n) (_n & 0x7f)
+#define LPC_SPI_FRM 0x08
+#define LPC_SPI_IER 0x0c
+#define LPC_SPI_IER_INTEOT (1 << 1)
+#define LPC_SPI_IER_INTTHR (1 << 0)
+#define LPC_SPI_STAT 0x10
+#define LPC_SPI_STAT_INTCLR (1 << 8)
+#define LPC_SPI_STAT_EOT (1 << 7)
+#define LPC_SPI_STAT_BUSYLEV (1 << 6)
+#define LPC_SPI_STAT_SHIFTACT (1 << 3)
+#define LPC_SPI_STAT_BF (1 << 2)
+#define LPC_SPI_STAT_THR (1 << 1)
+#define LPC_SPI_STAT_BE (1 << 0)
+#define LPC_SPI_DAT 0x14
+#define LPC_SPI_TIM_CTRL 0x400
+#define LPC_SPI_TIM_COUNT 0x404
+#define LPC_SPI_TIM_STAT 0x408
+
+/*
+ * SSP interface (from UM10326: LPC32x0 User manual, page 500)
+ */
+#define LPC_SSP0_BASE 0x4c00
+#define LPC_SSP1_BASE 0xc000
+#define LPC_SSP_CR0 0x00
+#define LPC_SSP_CR0_DSS(_n) ((_n-1) & 0xf)
+#define LPC_SSP_CR0_TI (1 << 4)
+#define LPC_SSP_CR0_MICROWIRE (1 << 5)
+#define LPC_SSP_CR0_CPOL (1 << 6)
+#define LPC_SSP_CR0_CPHA (1 << 7)
+#define LPC_SSP_CR0_SCR(_n) ((_x & & 0xff) << 8)
+#define LPC_SSP_CR1 0x04
+#define LPC_SSP_CR1_LBM (1 << 0)
+#define LPC_SSP_CR1_SSE (1 << 1)
+#define LPC_SSP_CR1_MS (1 << 2)
+#define LPC_SSP_CR1_SOD (1 << 3)
+#define LPC_SSP_DR 0x08
+#define LPC_SSP_SR 0x0c
+#define LPC_SSP_SR_TFE (1 << 0)
+#define LPC_SSP_SR_TNF (1 << 1)
+#define LPC_SSP_SR_RNE (1 << 2)
+#define LPC_SSP_SR_RFF (1 << 3)
+#define LPC_SSP_SR_BSY (1 << 4)
+#define LPC_SSP_CPSR 0x10
+#define LPC_SSP_IMSC 0x14
+#define LPC_SSP_IMSC_RORIM (1 << 0)
+#define LPC_SSP_IMSC_RTIM (1 << 1)
+#define LPC_SSP_IMSC_RXIM (1 << 2)
+#define LPC_SSP_IMSC_TXIM (1 << 3)
+#define LPC_SSP_RIS 0x18
+#define LPC_SSP_RIS_RORRIS (1 << 0)
+#define LPC_SSP_RIS_RTRIS (1 << 1)
+#define LPC_SSP_RIS_RXRIS (1 << 2)
+#define LPC_SSP_RIS_TXRIS (1 << 3)
+#define LPC_SSP_MIS 0x1c
+#define LPC_SSP_ICR 0x20
+#define LPC_SSP_DMACR 0x24
+
+/*
+ * GPIO (from UM10326: LPC32x0 User manual, page 606)
+ */
+#define LPC_GPIO_PHYS_BASE (LPC_DEV_PHYS_BASE + 0x28000)
+#define LPC_GPIO_P0_COUNT 8
+#define LPC_GPIO_P1_COUNT 24
+#define LPC_GPIO_P2_COUNT 13
+#define LPC_GPIO_P3_COUNT 52
+#define LPC_GPIO_P0_INP_STATE 0x40
+#define LPC_GPIO_P0_OUTP_SET 0x44
+#define LPC_GPIO_P0_OUTP_CLR 0x48
+#define LPC_GPIO_P0_OUTP_STATE 0x4c
+#define LPC_GPIO_P0_DIR_SET 0x50
+#define LPC_GPIO_P0_DIR_CLR 0x54
+#define LPC_GPIO_P0_DIR_STATE 0x58
+#define LPC_GPIO_P1_INP_STATE 0x60
+#define LPC_GPIO_P1_OUTP_SET 0x64
+#define LPC_GPIO_P1_OUTP_CLR 0x68
+#define LPC_GPIO_P1_OUTP_STATE 0x6c
+#define LPC_GPIO_P1_DIR_SET 0x70
+#define LPC_GPIO_P1_DIR_CLR 0x74
+#define LPC_GPIO_P1_DIR_STATE 0x78
+#define LPC_GPIO_P2_INP_STATE 0x1c
+#define LPC_GPIO_P2_OUTP_SET 0x20
+#define LPC_GPIO_P2_OUTP_CLR 0x24
+#define LPC_GPIO_P2_DIR_SET 0x10
+#define LPC_GPIO_P2_DIR_CLR 0x14
+#define LPC_GPIO_P2_DIR_STATE 0x14
+#define LPC_GPIO_P3_INP_STATE 0x00
+#define LPC_GPIO_P3_OUTP_SET 0x04
+#define LPC_GPIO_P3_OUTP_CLR 0x08
+#define LPC_GPIO_P3_OUTP_STATE 0x0c
+#define LPC_GPIO_SIZE 0x80
+
+/* Aliases for logical pin numbers: */
+#define LPC_GPIO_GPI_00(_n) (0 + _n)
+#define LPC_GPIO_GPI_15(_n) (10 + _n)
+#define LPC_GPIO_GPI_25 (19)
+#define LPC_GPIO_GPI_27(_n) (20 + _n)
+#define LPC_GPIO_GPO_00(_n) (22 + _n)
+#define LPC_GPIO_GPIO_00(_n) (46 + _n)
+/* SPI devices chip selects: */
+#define SSD1289_CS_PIN LPC_GPIO_GPO_00(4)
+#define SSD1289_DC_PIN LPC_GPIO_GPO_00(5)
+#define ADS7846_CS_PIN LPC_GPIO_GPO_00(11)
+#define ADS7846_INTR_PIN LPC_GPIO_GPIO_00(0)
+
+/*
+ * GPDMA controller (from UM10326: LPC32x0 User manual, page 106)
+ */
+#define LPC_DMAC_INTSTAT 0x00
+#define LPC_DMAC_INTTCSTAT 0x04
+#define LPC_DMAC_INTTCCLEAR 0x08
+#define LPC_DMAC_INTERRSTAT 0x0c
+#define LPC_DMAC_INTERRCLEAR 0x10
+#define LPC_DMAC_RAWINTTCSTAT 0x14
+#define LPC_DMAC_RAWINTERRSTAT 0x18
+#define LPC_DMAC_ENABLED_CHANNELS 0x1c
+#define LPC_DMAC_SOFTBREQ 0x20
+#define LPC_DMAC_SOFTSREQ 0x24
+#define LPC_DMAC_SOFTLBREQ 0x28
+#define LPC_DMAC_SOFTLSREQ 0x2c
+#define LPC_DMAC_CONFIG 0x30
+#define LPC_DMAC_CONFIG_M1 (1 << 2)
+#define LPC_DMAC_CONFIG_M0 (1 << 1)
+#define LPC_DMAC_CONFIG_ENABLE (1 << 0)
+#define LPC_DMAC_CHADDR(_n) (0x100 + (_n * 0x20))
+#define LPC_DMAC_CHNUM 8
+#define LPC_DMAC_CHSIZE 0x20
+#define LPC_DMAC_CH_SRCADDR 0x00
+#define LPC_DMAC_CH_DSTADDR 0x04
+#define LPC_DMAC_CH_LLI 0x08
+#define LPC_DMAC_CH_LLI_AHB1 (1 << 0)
+#define LPC_DMAC_CH_CONTROL 0x0c
+#define LPC_DMAC_CH_CONTROL_I (1U << 31)
+#define LPC_DMAC_CH_CONTROL_DI (1 << 27)
+#define LPC_DMAC_CH_CONTROL_SI (1 << 26)
+#define LPC_DMAC_CH_CONTROL_D (1 << 25)
+#define LPC_DMAC_CH_CONTROL_S (1 << 24)
+#define LPC_DMAC_CH_CONTROL_WIDTH_4 2
+#define LPC_DMAC_CH_CONTROL_DWIDTH(_n) ((_n & 0x7) << 21)
+#define LPC_DMAC_CH_CONTROL_SWIDTH(_n) ((_n & 0x7) << 18)
+#define LPC_DMAC_CH_CONTROL_BURST_8 2
+#define LPC_DMAC_CH_CONTROL_DBSIZE(_n) ((_n & 0x7) << 15)
+#define LPC_DMAC_CH_CONTROL_SBSIZE(_n) ((_n & 0x7) << 12)
+#define LPC_DMAC_CH_CONTROL_XFERLEN(_n) (_n & 0xfff)
+#define LPC_DMAC_CH_CONFIG 0x10
+#define LPC_DMAC_CH_CONFIG_H (1 << 18)
+#define LPC_DMAC_CH_CONFIG_A (1 << 17)
+#define LPC_DMAC_CH_CONFIG_L (1 << 16)
+#define LPC_DMAC_CH_CONFIG_ITC (1 << 15)
+#define LPC_DMAC_CH_CONFIG_IE (1 << 14)
+#define LPC_DMAC_CH_CONFIG_FLOWCNTL(_n) ((_n & 0x7) << 11)
+#define LPC_DMAC_CH_CONFIG_DESTP(_n) ((_n & 0x1f) << 6)
+#define LPC_DMAC_CH_CONFIG_SRCP(_n) ((_n & 0x1f) << 1)
+#define LPC_DMAC_CH_CONFIG_E (1 << 0)
+
+/* DMA flow control values */
+#define LPC_DMAC_FLOW_D_M2M 0
+#define LPC_DMAC_FLOW_D_M2P 1
+#define LPC_DMAC_FLOW_D_P2M 2
+#define LPC_DMAC_FLOW_D_P2P 3
+#define LPC_DMAC_FLOW_DP_P2P 4
+#define LPC_DMAC_FLOW_P_M2P 5
+#define LPC_DMAC_FLOW_P_P2M 6
+#define LPC_DMAC_FLOW_SP_P2P 7
+
+/* DMA peripheral ID's */
+#define LPC_DMAC_I2S0_DMA0_ID 0
+#define LPC_DMAC_NAND_ID 1
+#define LPC_DMAC_IS21_DMA0_ID 2
+#define LPC_DMAC_SSP1_ID 3
+#define LPC_DMAC_SPI2_ID 3
+#define LPC_DMAC_SD_ID 4
+#define LPC_DMAC_UART1_TX_ID 5
+#define LPC_DMAC_UART1_RX_ID 6
+#define LPC_DMAC_UART2_TX_ID 7
+#define LPC_DMAC_UART2_RX_ID 8
+#define LPC_DMAC_UART7_TX_ID 9
+#define LPC_DMAC_UART7_RX_ID 10
+#define LPC_DMAC_I2S1_DMA1_ID 10
+#define LPC_DMAC_SPI1_ID 11
+#define LPC_DMAC_SSP1_TX_ID 11
+#define LPC_DMAC_NAND2_ID 12
+#define LPC_DMAC_I2S0_DMA1_ID 13
+#define LPC_DMAC_SSP0_RX 14
+#define LPC_DMAC_SSP0_TX 15
+
+#endif /* _ARM_LPC_LPCREG_H */
Property changes on: trunk/sys/arm/lpc/lpcreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/lpcvar.h
===================================================================
--- trunk/sys/arm/lpc/lpcvar.h (rev 0)
+++ trunk/sys/arm/lpc/lpcvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/lpc/lpcvar.h 239278 2012-08-15 05:37:10Z gonzo $
+ */
+
+#ifndef _ARM_LPC_LPCVAR_H
+#define _ARM_LPC_LPCVAR_H
+
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+
+/* Clocking and power control */
+uint32_t lpc_pwr_read(device_t, int);
+void lpc_pwr_write(device_t, int, uint32_t);
+
+/* GPIO */
+void platform_gpio_init(void);
+int lpc_gpio_set_flags(device_t, int, int);
+int lpc_gpio_set_state(device_t, int, int);
+int lpc_gpio_get_state(device_t, int, int *);
+
+/* DMA */
+struct lpc_dmac_channel_config
+{
+ int ldc_fcntl;
+ int ldc_src_periph;
+ int ldc_src_width;
+ int ldc_src_incr;
+ int ldc_src_burst;
+ int ldc_dst_periph;
+ int ldc_dst_width;
+ int ldc_dst_incr;
+ int ldc_dst_burst;
+ void (*ldc_success_handler)(void *);
+ void (*ldc_error_handler)(void *);
+ void * ldc_handler_arg;
+};
+
+int lpc_dmac_config_channel(device_t, int, struct lpc_dmac_channel_config *);
+int lpc_dmac_setup_transfer(device_t, int, bus_addr_t, bus_addr_t, bus_size_t, int);
+int lpc_dmac_enable_channel(device_t, int);
+int lpc_dmac_disable_channel(device_t, int);
+int lpc_dmac_start_burst(device_t, int);
+
+#endif /* _ARM_LPC_LPCVAR_H */
Property changes on: trunk/sys/arm/lpc/lpcvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/ssd1289.c
===================================================================
--- trunk/sys/arm/lpc/ssd1289.c (rev 0)
+++ trunk/sys/arm/lpc/ssd1289.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,210 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Jakub Wojciech Klama <jceel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/ssd1289.c 239278 2012-08-15 05:37:10Z gonzo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/spibus/spi.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
+#include "spibus_if.h"
+
+struct ssd1289_softc
+{
+ device_t ss_dev;
+};
+
+static int ssd1289_probe(device_t);
+static int ssd1289_attach(device_t);
+
+static __inline void ssd1289_set_dc(struct ssd1289_softc *, int);
+static __inline void ssd1289_spi_send(struct ssd1289_softc *, uint8_t *, int);
+static void ssd1289_write_reg(struct ssd1289_softc *, uint16_t, uint16_t);
+
+static struct ssd1289_softc *ssd1289_sc = NULL;
+
+void ssd1289_configure(void);
+
+static int
+ssd1289_probe(device_t dev)
+{
+#if 0
+ if (!ofw_bus_is_compatible(dev, "ssd1289"))
+ return (ENXIO);
+#endif
+
+ device_set_desc(dev, "Solomon Systech SSD1289 LCD controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ssd1289_attach(device_t dev)
+{
+ struct ssd1289_softc *sc = device_get_softc(dev);
+
+ sc->ss_dev = dev;
+ ssd1289_sc = sc;
+
+ return (0);
+}
+
+void
+ssd1289_configure(void)
+{
+ struct ssd1289_softc *sc = ssd1289_sc;
+
+ /* XXX will be replaced with commented code */
+ ssd1289_write_reg(sc,0x00,0x0001);
+ DELAY(20);
+
+ ssd1289_write_reg(sc,0x03,0xA2A4);
+ ssd1289_write_reg(sc,0x0C,0x0004);
+ ssd1289_write_reg(sc,0x0D,0x0308);
+ ssd1289_write_reg(sc,0x0E,0x3000);
+ DELAY(50);
+
+ ssd1289_write_reg(sc,0x1E,0x00AF);
+ ssd1289_write_reg(sc,0x01,0x2B3F);
+ ssd1289_write_reg(sc,0x02,0x0600);
+ ssd1289_write_reg(sc,0x10,0x0000);
+ ssd1289_write_reg(sc,0x07,0x0233);
+ ssd1289_write_reg(sc,0x0B,0x0039);
+ ssd1289_write_reg(sc,0x0F,0x0000);
+ DELAY(50);
+
+ ssd1289_write_reg(sc,0x30,0x0707);
+ ssd1289_write_reg(sc,0x31,0x0204);
+ ssd1289_write_reg(sc,0x32,0x0204);
+ ssd1289_write_reg(sc,0x33,0x0502);
+ ssd1289_write_reg(sc,0x34,0x0507);
+ ssd1289_write_reg(sc,0x35,0x0204);
+ ssd1289_write_reg(sc,0x36,0x0204);
+ ssd1289_write_reg(sc,0x37,0x0502);
+ ssd1289_write_reg(sc,0x3A,0x0302);
+ ssd1289_write_reg(sc,0x3B,0x0302);
+
+ ssd1289_write_reg(sc,0x23,0x0000);
+ ssd1289_write_reg(sc,0x24,0x0000);
+
+ ssd1289_write_reg(sc,0x48,0x0000);
+ ssd1289_write_reg(sc,0x49,0x013F);
+ ssd1289_write_reg(sc,0x4A,0x0000);
+ ssd1289_write_reg(sc,0x4B,0x0000);
+
+ ssd1289_write_reg(sc,0x41,0x0000);
+ ssd1289_write_reg(sc,0x42,0x0000);
+
+ ssd1289_write_reg(sc,0x44,0xEF00);
+ ssd1289_write_reg(sc,0x45,0x0000);
+ ssd1289_write_reg(sc,0x46,0x013F);
+ DELAY(50);
+
+ ssd1289_write_reg(sc,0x44,0xEF00);
+ ssd1289_write_reg(sc,0x45,0x0000);
+ ssd1289_write_reg(sc,0x4E,0x0000);
+ ssd1289_write_reg(sc,0x4F,0x0000);
+ ssd1289_write_reg(sc,0x46,0x013F);
+}
+
+static __inline void
+ssd1289_spi_send(struct ssd1289_softc *sc, uint8_t *data, int len)
+{
+ struct spi_command cmd;
+ uint8_t buffer[8];
+ cmd.tx_cmd = data;
+ cmd.tx_cmd_sz = len;
+ cmd.rx_cmd = buffer;
+ cmd.rx_cmd_sz = len;
+ cmd.tx_data_sz = 0;
+ cmd.rx_data_sz = 0;
+ SPIBUS_TRANSFER(device_get_parent(sc->ss_dev), sc->ss_dev, &cmd);
+}
+
+static __inline void
+ssd1289_set_dc(struct ssd1289_softc *sc, int value)
+{
+ lpc_gpio_set_state(sc->ss_dev, SSD1289_DC_PIN, value);
+}
+
+static void
+ssd1289_write_reg(struct ssd1289_softc *sc, uint16_t addr, uint16_t value)
+{
+ uint8_t buffer[2];
+
+ ssd1289_set_dc(sc, 0);
+ buffer[0] = 0x00;
+ buffer[1] = addr & 0xff;
+ ssd1289_spi_send(sc, buffer, 2);
+
+ ssd1289_set_dc(sc, 1);
+ buffer[0] = (value >> 8) & 0xff;
+ buffer[1] = value & 0xff;
+ ssd1289_spi_send(sc, buffer, 2);
+}
+
+static device_method_t ssd1289_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ssd1289_probe),
+ DEVMETHOD(device_attach, ssd1289_attach),
+
+ { 0, 0 }
+};
+
+static devclass_t ssd1289_devclass;
+
+static driver_t ssd1289_driver = {
+ "ssd1289",
+ ssd1289_methods,
+ sizeof(struct ssd1289_softc),
+};
+
+DRIVER_MODULE(ssd1289, spibus, ssd1289_driver, ssd1289_devclass, 0, 0);
Property changes on: trunk/sys/arm/lpc/ssd1289.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/lpc/std.lpc
===================================================================
--- trunk/sys/arm/lpc/std.lpc (rev 0)
+++ trunk/sys/arm/lpc/std.lpc 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,14 @@
+# $FreeBSD: stable/10/sys/arm/lpc/std.lpc 266110 2014-05-15 02:41:23Z ian $
+#
+# DM644x
+#
+
+files "../lpc/files.lpc"
+cpu CPU_ARM9
+machine arm
+makeoptions CONF_CFLAGS="-march=armv5te"
+options PHYSADDR=0x80000000
+makeoptions KERNPHYSADDR=0x80100000
+options KERNPHYSADDR=0x80100000
+makeoptions KERNVIRTADDR=0xc0100000
+options KERNVIRTADDR=0xc0100000
Property changes on: trunk/sys/arm/lpc/std.lpc
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/armadaxp/armadaxp.c
===================================================================
--- trunk/sys/arm/mv/armadaxp/armadaxp.c (rev 0)
+++ trunk/sys/arm/mv/armadaxp/armadaxp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,308 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From: FreeBSD: src/sys/arm/mv/kirkwood/sheevaplug.c,v 1.2 2010/06/13 13:28:53
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/armadaxp/armadaxp.c 250293 2013-05-06 14:12:36Z gber $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/armreg.h>
+
+#include <arm/mv/mvwin.h>
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/fdt.h>
+
+#define CPU_FREQ_FIELD(sar) (((0x01 & (sar >> 52)) << 3) | \
+ (0x07 & (sar >> 21)))
+#define FAB_FREQ_FIELD(sar) (((0x01 & (sar >> 51)) << 4) | \
+ (0x0F & (sar >> 24)))
+
+static uint32_t count_l2clk(void);
+void armadaxp_l2_init(void);
+void armadaxp_init_coher_fabric(void);
+int platform_get_ncpus(void);
+
+#define ARMADAXP_L2_BASE (MV_BASE + 0x8000)
+#define ARMADAXP_L2_CTRL 0x100
+#define L2_ENABLE (1 << 0)
+#define ARMADAXP_L2_AUX_CTRL 0x104
+#define L2_WBWT_MODE_MASK (3 << 0)
+#define L2_WBWT_MODE_PAGE 0
+#define L2_WBWT_MODE_WB 1
+#define L2_WBWT_MODE_WT 2
+#define L2_REP_STRAT_MASK (3 << 27)
+#define L2_REP_STRAT_LSFR (1 << 27)
+#define L2_REP_STRAT_SEMIPLRU (3 << 27)
+
+#define ARMADAXP_L2_CNTR_CTRL 0x200
+#define ARMADAXP_L2_CNTR_CONF(x) (0x204 + (x) * 0xc)
+#define ARMADAXP_L2_CNTR2_VAL_LOW (0x208 + (x) * 0xc)
+#define ARMADAXP_L2_CNTR2_VAL_HI (0x20c + (x) * 0xc)
+
+#define ARMADAXP_L2_INT_CAUSE 0x220
+
+#define ARMADAXP_L2_SYNC_BARRIER 0x700
+#define ARMADAXP_L2_INV_WAY 0x778
+#define ARMADAXP_L2_CLEAN_WAY 0x7BC
+#define ARMADAXP_L2_FLUSH_PHYS 0x7F0
+#define ARMADAXP_L2_FLUSH_WAY 0x7FC
+
+#define MV_COHERENCY_FABRIC_BASE (MV_MBUS_BRIDGE_BASE + 0x200)
+#define COHER_FABRIC_CTRL 0x00
+#define COHER_FABRIC_CONF 0x04
+#define COHER_FABRIC_CFU 0x28
+#define COHER_FABRIC_CIB_CTRL 0x80
+
+/* XXX Make gpio driver optional and remove it */
+struct resource_spec mv_gpio_res[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+struct vco_freq_ratio {
+ uint8_t vco_cpu; /* VCO to CLK0(CPU) clock ratio */
+ uint8_t vco_l2c; /* VCO to NB(L2 cache) clock ratio */
+ uint8_t vco_hcl; /* VCO to HCLK(DDR controller) clock ratio */
+ uint8_t vco_ddr; /* VCO to DR(DDR memory) clock ratio */
+};
+
+static struct vco_freq_ratio freq_conf_table[] = {
+/*00*/ { 1, 1, 4, 2 },
+/*01*/ { 1, 2, 2, 2 },
+/*02*/ { 2, 2, 6, 3 },
+/*03*/ { 2, 2, 3, 3 },
+/*04*/ { 1, 2, 3, 3 },
+/*05*/ { 1, 2, 4, 2 },
+/*06*/ { 1, 1, 2, 2 },
+/*07*/ { 2, 3, 6, 6 },
+/*08*/ { 2, 3, 5, 5 },
+/*09*/ { 1, 2, 6, 3 },
+/*10*/ { 2, 4, 10, 5 },
+/*11*/ { 1, 3, 6, 6 },
+/*12*/ { 1, 2, 5, 5 },
+/*13*/ { 1, 3, 6, 3 },
+/*14*/ { 1, 2, 5, 5 },
+/*15*/ { 2, 2, 5, 5 },
+/*16*/ { 1, 1, 3, 3 },
+/*17*/ { 2, 5, 10, 10 },
+/*18*/ { 1, 3, 8, 4 },
+/*19*/ { 1, 1, 2, 1 },
+/*20*/ { 2, 3, 6, 3 },
+/*21*/ { 1, 2, 8, 4 },
+/*22*/ { 2, 5, 10, 5 }
+};
+
+static uint16_t cpu_clock_table[] = {
+ 1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000, 600, 667, 800, 1600,
+ 2133, 2200, 2400 };
+
+uint32_t
+get_tclk(void)
+{
+ uint32_t cputype;
+
+ cputype = cpufunc_id();
+ cputype &= CPU_ID_CPU_MASK;
+
+ if (cputype == CPU_ID_MV88SV584X_V7)
+ return (TCLK_250MHZ);
+ else
+ return (TCLK_200MHZ);
+}
+
+static uint32_t
+count_l2clk(void)
+{
+ uint64_t sar_reg;
+ uint32_t freq_vco, freq_l2clk;
+ uint8_t sar_cpu_freq, sar_fab_freq, array_size;
+
+ /* Get value of the SAR register and process it */
+ sar_reg = get_sar_value();
+ sar_cpu_freq = CPU_FREQ_FIELD(sar_reg);
+ sar_fab_freq = FAB_FREQ_FIELD(sar_reg);
+
+ /* Check if CPU frequency field has correct value */
+ array_size = sizeof(cpu_clock_table) / sizeof(cpu_clock_table[0]);
+ if (sar_cpu_freq >= array_size)
+ panic("Reserved value in cpu frequency configuration field: "
+ "%d", sar_cpu_freq);
+
+ /* Check if fabric frequency field has correct value */
+ array_size = sizeof(freq_conf_table) / sizeof(freq_conf_table[0]);
+ if (sar_fab_freq >= array_size)
+ panic("Reserved value in fabric frequency configuration field: "
+ "%d", sar_fab_freq);
+
+ /* Get CPU clock frequency */
+ freq_vco = cpu_clock_table[sar_cpu_freq] *
+ freq_conf_table[sar_fab_freq].vco_cpu;
+
+ /* Get L2CLK clock frequency */
+ freq_l2clk = freq_vco / freq_conf_table[sar_fab_freq].vco_l2c;
+
+ /* Round L2CLK value to integer MHz */
+ if (((freq_vco % freq_conf_table[sar_fab_freq].vco_l2c) * 10 /
+ freq_conf_table[sar_fab_freq].vco_l2c) >= 5)
+ freq_l2clk++;
+
+ return (freq_l2clk * 1000000);
+}
+
+uint32_t
+get_l2clk(void)
+{
+ static uint32_t l2clk_freq = 0;
+
+ /* If get_l2clk is called first time get L2CLK value from register */
+ if (l2clk_freq == 0)
+ l2clk_freq = count_l2clk();
+
+ return (l2clk_freq);
+}
+
+static uint32_t
+read_coher_fabric(uint32_t reg)
+{
+
+ return (bus_space_read_4(fdtbus_bs_tag, MV_COHERENCY_FABRIC_BASE, reg));
+}
+
+static void
+write_coher_fabric(uint32_t reg, uint32_t val)
+{
+
+ bus_space_write_4(fdtbus_bs_tag, MV_COHERENCY_FABRIC_BASE, reg, val);
+}
+
+int
+platform_get_ncpus(void)
+{
+#if !defined(SMP)
+ return (1);
+#else
+ return ((read_coher_fabric(COHER_FABRIC_CONF) & 0xf) + 1);
+#endif
+}
+
+void
+armadaxp_init_coher_fabric(void)
+{
+ uint32_t val, cpus, mask;
+
+ cpus = platform_get_ncpus();
+ mask = (1 << cpus) - 1;
+ val = read_coher_fabric(COHER_FABRIC_CTRL);
+ val |= (mask << 24);
+ write_coher_fabric(COHER_FABRIC_CTRL, val);
+
+ val = read_coher_fabric(COHER_FABRIC_CONF);
+ val |= (mask << 24);
+ val |= (1 << 15);
+ write_coher_fabric(COHER_FABRIC_CONF, val);
+}
+
+#define ALL_WAYS 0xffffffff
+
+/* L2 cache configuration registers */
+static uint32_t
+read_l2_cache(uint32_t reg)
+{
+
+ return (bus_space_read_4(fdtbus_bs_tag, ARMADAXP_L2_BASE, reg));
+}
+
+static void
+write_l2_cache(uint32_t reg, uint32_t val)
+{
+
+ bus_space_write_4(fdtbus_bs_tag, ARMADAXP_L2_BASE, reg, val);
+}
+
+static void
+armadaxp_l2_idcache_inv_all(void)
+{
+ write_l2_cache(ARMADAXP_L2_INV_WAY, ALL_WAYS);
+}
+
+void
+armadaxp_l2_init(void)
+{
+ u_int32_t reg;
+
+ /* Set L2 policy */
+ reg = read_l2_cache(ARMADAXP_L2_AUX_CTRL);
+ reg &= ~(L2_WBWT_MODE_MASK);
+ reg &= ~(L2_REP_STRAT_MASK);
+ reg |= L2_REP_STRAT_SEMIPLRU;
+ reg |= L2_WBWT_MODE_WT;
+ write_l2_cache(ARMADAXP_L2_AUX_CTRL, reg);
+
+ /* Invalidate l2 cache */
+ armadaxp_l2_idcache_inv_all();
+
+ /* Clear pending L2 interrupts */
+ write_l2_cache(ARMADAXP_L2_INT_CAUSE, 0x1ff);
+
+ /* Enable l2 cache */
+ reg = read_l2_cache(ARMADAXP_L2_CTRL);
+ write_l2_cache(ARMADAXP_L2_CTRL, reg | L2_ENABLE);
+
+ /*
+ * For debug purposes
+ * Configure and enable counter
+ */
+ write_l2_cache(ARMADAXP_L2_CNTR_CONF(0), 0xf0000 | (4 << 2));
+ write_l2_cache(ARMADAXP_L2_CNTR_CONF(1), 0xf0000 | (2 << 2));
+ write_l2_cache(ARMADAXP_L2_CNTR_CTRL, 0x303);
+
+ /*
+ * Enable Cache maintenance operation propagation in coherency fabric
+ * Change point of coherency and point of unification to DRAM.
+ */
+ reg = read_coher_fabric(COHER_FABRIC_CFU);
+ reg |= (1 << 17) | (1 << 18);
+ write_coher_fabric(COHER_FABRIC_CFU, reg);
+
+ /* Coherent IO Bridge initialization */
+ reg = read_coher_fabric(COHER_FABRIC_CIB_CTRL);
+ reg &= ~(7 << 16);
+ reg |= (7 << 16);
+ write_coher_fabric(COHER_FABRIC_CIB_CTRL, reg);
+}
+
Property changes on: trunk/sys/arm/mv/armadaxp/armadaxp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/armadaxp/armadaxp_mp.c
===================================================================
--- trunk/sys/arm/mv/armadaxp/armadaxp_mp.c (rev 0)
+++ trunk/sys/arm/mv/armadaxp/armadaxp_mp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,195 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/mv/armadaxp/armadaxp_mp.c 283340 2015-05-23 23:35:19Z ian $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/armreg.h>
+
+#include <arm/mv/mvwin.h>
+
+#define MV_AXP_CPU_DIVCLK_BASE (MV_BASE + 0x18700)
+#define CPU_DIVCLK_CTRL0 0x00
+#define CPU_DIVCLK_CTRL2_RATIO_FULL0 0x08
+#define CPU_DIVCLK_CTRL2_RATIO_FULL1 0x0c
+#define CPU_DIVCLK_MASK(x) (~(0xff << (8 * (x))))
+
+#define CPU_PMU(x) (MV_BASE + 0x22100 + (0x100 * (x)))
+#define CPU_PMU_BOOT 0x24
+
+#define MP (MV_BASE + 0x20800)
+#define MP_SW_RESET(x) ((x) * 8)
+
+#define CPU_RESUME_CONTROL (0x20988)
+
+void armadaxp_init_coher_fabric(void);
+int platform_get_ncpus(void);
+
+/* Coherency Fabric registers */
+static uint32_t
+read_cpu_clkdiv(uint32_t reg)
+{
+
+ return (bus_space_read_4(fdtbus_bs_tag, MV_AXP_CPU_DIVCLK_BASE, reg));
+}
+
+static void
+write_cpu_clkdiv(uint32_t reg, uint32_t val)
+{
+
+ bus_space_write_4(fdtbus_bs_tag, MV_AXP_CPU_DIVCLK_BASE, reg, val);
+}
+
+void
+platform_mp_setmaxid(void)
+{
+
+ mp_maxid = 3;
+}
+
+int
+platform_mp_probe(void)
+{
+
+ mp_ncpus = platform_get_ncpus();
+
+ return (mp_ncpus > 1);
+}
+
+void
+platform_mp_init_secondary(void)
+{
+}
+
+void mptramp(void);
+void mptramp_end(void);
+extern vm_offset_t mptramp_pmu_boot;
+
+void
+platform_mp_start_ap(void)
+{
+ uint32_t reg, *src, *dst, cpu_num, div_val, cputype;
+ vm_offset_t pmu_boot_off;
+ /*
+ * Initialization procedure depends on core revision,
+ * in this step CHIP ID is checked to choose proper procedure
+ */
+ cputype = cpufunc_id();
+ cputype &= CPU_ID_CPU_MASK;
+
+ /*
+ * Set the PA of CPU0 Boot Address Redirect register used in
+ * mptramp according to the actual SoC registers' base address.
+ */
+ pmu_boot_off = (CPU_PMU(0) - MV_BASE) + CPU_PMU_BOOT;
+ mptramp_pmu_boot = fdt_immr_pa + pmu_boot_off;
+ dst = pmap_mapdev(0xffff0000, PAGE_SIZE);
+ for (src = (uint32_t *)mptramp; src < (uint32_t *)mptramp_end;
+ src++, dst++) {
+ *dst = *src;
+ }
+ pmap_unmapdev((vm_offset_t)dst, PAGE_SIZE);
+ if (cputype == CPU_ID_MV88SV584X_V7) {
+ /* Core rev A0 */
+ div_val = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1);
+ div_val &= 0x3f;
+
+ for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) {
+ reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1);
+ reg &= CPU_DIVCLK_MASK(cpu_num);
+ reg |= div_val << (cpu_num * 8);
+ write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg);
+ }
+ } else {
+ /* Core rev Z1 */
+ div_val = 0x01;
+
+ if (mp_ncpus > 1) {
+ reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0);
+ reg &= CPU_DIVCLK_MASK(3);
+ reg |= div_val << 24;
+ write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0, reg);
+ }
+
+ for (cpu_num = 2; cpu_num < mp_ncpus; cpu_num++ ) {
+ reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1);
+ reg &= CPU_DIVCLK_MASK(cpu_num);
+ reg |= div_val << (cpu_num * 8);
+ write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg);
+ }
+ }
+
+ reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0);
+ reg |= ((0x1 << (mp_ncpus - 1)) - 1) << 21;
+ write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);
+ reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0);
+ reg |= 0x01000000;
+ write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);
+
+ DELAY(100);
+ reg &= ~(0xf << 21);
+ write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);
+ DELAY(100);
+
+ bus_space_write_4(fdtbus_bs_tag, MV_BASE, CPU_RESUME_CONTROL, 0);
+
+ for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ )
+ bus_space_write_4(fdtbus_bs_tag, CPU_PMU(cpu_num), CPU_PMU_BOOT,
+ pmap_kextract((vm_offset_t)mpentry));
+
+ cpu_idcache_wbinv_all();
+
+ for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ )
+ bus_space_write_4(fdtbus_bs_tag, MP, MP_SW_RESET(cpu_num), 0);
+
+ /* XXX: Temporary workaround for hangup after releasing AP's */
+ wmb();
+ DELAY(10);
+
+ armadaxp_init_coher_fabric();
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+
+ pic_ipi_send(cpus, ipi);
+}
Property changes on: trunk/sys/arm/mv/armadaxp/armadaxp_mp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/armadaxp/files.armadaxp
===================================================================
--- trunk/sys/arm/mv/armadaxp/files.armadaxp (rev 0)
+++ trunk/sys/arm/mv/armadaxp/files.armadaxp 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,8 @@
+# $FreeBSD: stable/10/sys/arm/mv/armadaxp/files.armadaxp 266385 2014-05-18 00:30:04Z ian $
+
+arm/mv/armadaxp/armadaxp.c standard
+arm/mv/mpic.c standard
+arm/mv/rtc.c standard
+arm/mv/armadaxp/armadaxp_mp.c optional smp
+arm/mv/armadaxp/mptramp.S optional smp
+
Property changes on: trunk/sys/arm/mv/armadaxp/files.armadaxp
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/armadaxp/mptramp.S
===================================================================
--- trunk/sys/arm/mv/armadaxp/mptramp.S (rev 0)
+++ trunk/sys/arm/mv/armadaxp/mptramp.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,62 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2011 Semihalf
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <machine/armreg.h>
+
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/armadaxp/mptramp.S 283340 2015-05-23 23:35:19Z ian $");
+
+.global _C_LABEL(mptramp_pmu_boot)
+
+ASENTRY_NP(mptramp)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c7, 0
+
+ mrs r3, cpsr
+ bic r3, r3, #(PSR_MODE)
+ orr r3, r3, #(PSR_SVC32_MODE)
+ msr cpsr_fsxc, r3
+
+ mrc p15, 0, r0, c0, c0, 5
+ and r0, #0x0f /* Get CPU ID */
+
+ /* Read boot address for CPU */
+ mov r1, #0x100
+ mul r2, r0, r1
+ ldr r1, mptramp_pmu_boot
+ add r0, r2, r1
+ ldr r1, [r0], #0x00
+
+ mov pc, r1
+
+_C_LABEL(mptramp_pmu_boot):
+ .word 0x0
+
+END(mptramp)
+
+ .global _C_LABEL(mptramp_end)
+_C_LABEL(mptramp_end):
Property changes on: trunk/sys/arm/mv/armadaxp/mptramp.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/armadaxp/std.armadaxp
===================================================================
--- trunk/sys/arm/mv/armadaxp/std.armadaxp (rev 0)
+++ trunk/sys/arm/mv/armadaxp/std.armadaxp 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,16 @@
+# $FreeBSD: stable/10/sys/arm/mv/armadaxp/std.armadaxp 266110 2014-05-15 02:41:23Z ian $
+
+# kernel gets loaded at 0x00200000 by the loader, but runs at virtual address
+# 0xc0200000. RAM starts at 0. We put the pagetable at a reasonable place
+# in memory, but may need to bounce it higher if there's a problem with this.
+# We could paper over this by loading the kernel at 0xc0000000 virtual, but
+# that leads to other complications, so we'll just reclaim the lower region of
+# ram after we're loaded. Put the page tables for startup at 1MB.
+makeoptions KERNPHYSADDR=0x00200000
+makeoptions KERNVIRTADDR=0xc0200000
+
+options KERNPHYSADDR=0x00200000
+options KERNVIRTADDR=0xc0200000
+options PHYSADDR=0x00000000
+
+options ARM_L2_PIPT
Property changes on: trunk/sys/arm/mv/armadaxp/std.armadaxp
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/armadaxp/std.mv78x60
===================================================================
--- trunk/sys/arm/mv/armadaxp/std.mv78x60 (rev 0)
+++ trunk/sys/arm/mv/armadaxp/std.mv78x60 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+# $FreeBSD: stable/10/sys/arm/mv/armadaxp/std.mv78x60 239277 2012-08-15 05:15:49Z gonzo $
+
+include "../mv/std-pj4b.mv"
+include "../mv/armadaxp/std.armadaxp"
+files "../mv/armadaxp/files.armadaxp"
Property changes on: trunk/sys/arm/mv/armadaxp/std.mv78x60
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/discovery/discovery.c
===================================================================
--- trunk/sys/arm/mv/discovery/discovery.c (rev 0)
+++ trunk/sys/arm/mv/discovery/discovery.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,112 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/discovery/discovery.c 235609 2012-05-18 14:41:14Z gber $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+#include <arm/mv/mvwin.h>
+
+/*
+ * Virtual address space layout:
+ * -----------------------------
+ * 0x0000_0000 - 0xBFFF_FFFF : User Process (3 GB)
+ * 0xC000_0000 - virtual_avail : Kernel Reserved (text, data, page tables,
+ * : stack etc.)
+ * virtual-avail - 0xEFFF_FFFF : KVA (virtual_avail is typically < 0xc0a0_0000)
+ * 0xF000_0000 - 0xF0FF_FFFF : No-Cache allocation area (16 MB)
+ * 0xF100_0000 - 0xF10F_FFFF : SoC Integrated devices registers range (1 MB)
+ * 0xF110_0000 - 0xF11F_FFFF : PCI-Express I/O space (1MB)
+ * 0xF120_0000 - 0xF12F_FFFF : PCI I/O space (1MB)
+ * 0xF130_0000 - 0xF52F_FFFF : PCI-Express memory space (64MB)
+ * 0xF530_0000 - 0xF92F_FFFF : PCI memory space (64MB)
+ * 0xF930_0000 - 0xF93F_FFFF : Device Bus: BOOT (1 MB)
+ * 0xF940_0000 - 0xF94F_FFFF : Device Bus: CS0 (1 MB)
+ * 0xF950_0000 - 0xFB4F_FFFF : Device Bus: CS1 (32 MB)
+ * 0xFB50_0000 - 0xFB5F_FFFF : Device Bus: CS2 (1 MB)
+ * 0xFB60_0000 - 0xFFFE_FFFF : Unused (~74MB)
+ * 0xFFFF_0000 - 0xFFFF_0FFF : 'High' vectors page (4 kB)
+ * 0xFFFF_1000 - 0xFFFF_1FFF : ARM_TP_ADDRESS/RAS page (4 kB)
+ * 0xFFFF_2000 - 0xFFFF_FFFF : Unused (56 kB)
+ */
+
+
+struct resource_spec mv_gpio_res[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { -1, 0 }
+};
+
+const struct decode_win idma_win_tbl[] = {
+ { 0 },
+};
+const struct decode_win *idma_wins = idma_win_tbl;
+int idma_wins_no = 0;
+
+const struct decode_win xor_win_tbl[] = {
+ { 0 },
+};
+const struct decode_win *xor_wins = xor_win_tbl;
+int xor_wins_no = 0;
+
+uint32_t
+get_tclk(void)
+{
+ uint32_t sar;
+
+ /*
+ * On Discovery TCLK is can be configured to 166 MHz or 200 MHz.
+ * Current setting is read from Sample At Reset register.
+ */
+ sar = bus_space_read_4(fdtbus_bs_tag, MV_MPP_BASE, SAMPLE_AT_RESET_HI);
+ sar = (sar & TCLK_MASK) >> TCLK_SHIFT;
+
+ switch (sar) {
+ case 0:
+ return (TCLK_166MHZ);
+ case 1:
+ return (TCLK_200MHZ);
+ default:
+ panic("Unknown TCLK settings!");
+ }
+}
Property changes on: trunk/sys/arm/mv/discovery/discovery.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/discovery/files.db78xxx
===================================================================
--- trunk/sys/arm/mv/discovery/files.db78xxx (rev 0)
+++ trunk/sys/arm/mv/discovery/files.db78xxx 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+# $FreeBSD: stable/10/sys/arm/mv/discovery/files.db78xxx 239277 2012-08-15 05:15:49Z gonzo $
+
+arm/mv/discovery/discovery.c standard
+arm/mv/ic.c standard
+
Property changes on: trunk/sys/arm/mv/discovery/files.db78xxx
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/discovery/std.db78xxx
===================================================================
--- trunk/sys/arm/mv/discovery/std.db78xxx (rev 0)
+++ trunk/sys/arm/mv/discovery/std.db78xxx 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,11 @@
+# $FreeBSD: stable/10/sys/arm/mv/discovery/std.db78xxx 266110 2014-05-15 02:41:23Z ian $
+
+include "../mv/std.mv"
+files "../mv/discovery/files.db78xxx"
+
+makeoptions KERNPHYSADDR=0x00900000
+makeoptions KERNVIRTADDR=0xc0900000
+
+options KERNPHYSADDR=0x00900000
+options KERNVIRTADDR=0xc0900000
+options PHYSADDR=0x00000000
Property changes on: trunk/sys/arm/mv/discovery/std.db78xxx
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/files.mv
===================================================================
--- trunk/sys/arm/mv/files.mv (rev 0)
+++ trunk/sys/arm/mv/files.mv 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,41 @@
+# $FreeBSD: stable/10/sys/arm/mv/files.mv 287016 2015-08-22 07:32:47Z mav $
+#
+# The Marvell CPU cores
+# - Compliant with V5TE architecture
+# - Super scalar dual issue CPU
+# - Big/Little Endian
+# - MMU/MPU
+# - L1 Cache: Supports streaming and write allocate
+# - Variable pipeline stages
+# - Out-of-order execution
+# - Branch Prediction
+# - JTAG/ICE
+# - Vector Floating Point (VFP) unit
+#
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_armv5_ec.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+arm/arm/cpufunc_asm_sheeva.S standard
+arm/arm/cpufunc_asm_pj4b.S standard
+
+arm/mv/gpio.c standard
+arm/mv/mv_common.c standard
+arm/mv/mv_localbus.c standard
+arm/mv/mv_machdep.c standard
+arm/mv/mv_pci.c optional pci
+arm/mv/mv_ts.c standard
+arm/mv/timer.c standard
+arm/mv/twsi.c optional iicbus
+
+dev/cesa/cesa.c optional cesa
+dev/mge/if_mge.c optional mge
+dev/nand/nfc_mv.c optional nand
+dev/mvs/mvs_soc.c optional mvs
+dev/uart/uart_dev_ns8250.c optional uart
+dev/usb/controller/ehci_mv.c optional ehci
+
+kern/kern_clocksource.c standard
Property changes on: trunk/sys/arm/mv/files.mv
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/gpio.c
===================================================================
--- trunk/sys/arm/mv/gpio.c (rev 0)
+++ trunk/sys/arm/mv/gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,662 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice.
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Adapted and extended for Marvell SoCs by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_gpio.c, rev 1
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/gpio.c 273652 2014-10-26 01:30:46Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/interrupt.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/queue.h>
+#include <sys/timetc.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/mv/mvvar.h>
+#include <arm/mv/mvreg.h>
+
+#define GPIO_MAX_INTR_COUNT 8
+#define GPIO_PINS_PER_REG 32
+
+struct mv_gpio_softc {
+ struct resource * res[GPIO_MAX_INTR_COUNT + 1];
+ void *ih_cookie[GPIO_MAX_INTR_COUNT];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ uint8_t pin_num; /* number of GPIO pins */
+ uint8_t irq_num; /* number of real IRQs occupied by GPIO controller */
+};
+
+extern struct resource_spec mv_gpio_res[];
+
+static struct mv_gpio_softc *mv_gpio_softc = NULL;
+static uint32_t gpio_setup[MV_GPIO_MAX_NPINS];
+
+static int mv_gpio_probe(device_t);
+static int mv_gpio_attach(device_t);
+static int mv_gpio_intr(void *);
+
+static void mv_gpio_intr_handler(int pin);
+static uint32_t mv_gpio_reg_read(uint32_t reg);
+static void mv_gpio_reg_write(uint32_t reg, uint32_t val);
+static void mv_gpio_reg_set(uint32_t reg, uint32_t val);
+static void mv_gpio_reg_clear(uint32_t reg, uint32_t val);
+
+static void mv_gpio_blink(uint32_t pin, uint8_t enable);
+static void mv_gpio_polarity(uint32_t pin, uint8_t enable);
+static void mv_gpio_level(uint32_t pin, uint8_t enable);
+static void mv_gpio_edge(uint32_t pin, uint8_t enable);
+static void mv_gpio_out_en(uint32_t pin, uint8_t enable);
+static void mv_gpio_int_ack(uint32_t pin);
+static void mv_gpio_value_set(uint32_t pin, uint8_t val);
+static uint32_t mv_gpio_value_get(uint32_t pin);
+
+static device_method_t mv_gpio_methods[] = {
+ DEVMETHOD(device_probe, mv_gpio_probe),
+ DEVMETHOD(device_attach, mv_gpio_attach),
+ { 0, 0 }
+};
+
+static driver_t mv_gpio_driver = {
+ "gpio",
+ mv_gpio_methods,
+ sizeof(struct mv_gpio_softc),
+};
+
+static devclass_t mv_gpio_devclass;
+
+DRIVER_MODULE(gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0);
+
+typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int);
+
+struct gpio_ctrl_entry {
+ const char *compat;
+ gpios_phandler_t handler;
+};
+
+int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len);
+int gpio_get_config_from_dt(void);
+
+struct gpio_ctrl_entry gpio_controllers[] = {
+ { "mrvl,gpio", &mv_handle_gpios_prop },
+ { NULL, NULL }
+};
+
+static int
+mv_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "mrvl,gpio"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell Integrated GPIO Controller");
+ return (0);
+}
+
+static int
+mv_gpio_attach(device_t dev)
+{
+ int error, i;
+ struct mv_gpio_softc *sc;
+ uint32_t dev_id, rev_id;
+
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
+ if (sc == NULL)
+ return (ENXIO);
+
+ mv_gpio_softc = sc;
+
+ /* Get chip id and revision */
+ soc_id(&dev_id, &rev_id);
+
+ if (dev_id == MV_DEV_88F5182 ||
+ dev_id == MV_DEV_88F5281 ||
+ dev_id == MV_DEV_MV78100 ||
+ dev_id == MV_DEV_MV78100_Z0 ) {
+ sc->pin_num = 32;
+ sc->irq_num = 4;
+
+ } else if (dev_id == MV_DEV_88F6281 ||
+ dev_id == MV_DEV_88F6282) {
+ sc->pin_num = 50;
+ sc->irq_num = 7;
+
+ } else {
+ device_printf(dev, "unknown chip id=0x%x\n", dev_id);
+ return (ENXIO);
+ }
+
+ error = bus_alloc_resources(dev, mv_gpio_res, sc->res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Disable and clear all interrupts */
+ bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0);
+ bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0);
+ bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0);
+
+ if (sc->pin_num > GPIO_PINS_PER_REG) {
+ bus_space_write_4(sc->bst, sc->bsh,
+ GPIO_HI_INT_EDGE_MASK, 0);
+ bus_space_write_4(sc->bst, sc->bsh,
+ GPIO_HI_INT_LEV_MASK, 0);
+ bus_space_write_4(sc->bst, sc->bsh,
+ GPIO_HI_INT_CAUSE, 0);
+ }
+
+ for (i = 0; i < sc->irq_num; i++) {
+ if (bus_setup_intr(dev, sc->res[1 + i],
+ INTR_TYPE_MISC, mv_gpio_intr, NULL,
+ sc, &sc->ih_cookie[i]) != 0) {
+ bus_release_resources(dev, mv_gpio_res, sc->res);
+ device_printf(dev, "could not set up intr %d\n", i);
+ return (ENXIO);
+ }
+ }
+
+ return (platform_gpio_init());
+}
+
+static int
+mv_gpio_intr(void *arg)
+{
+ uint32_t int_cause, gpio_val;
+ uint32_t int_cause_hi, gpio_val_hi = 0;
+ int i;
+
+ int_cause = mv_gpio_reg_read(GPIO_INT_CAUSE);
+ gpio_val = mv_gpio_reg_read(GPIO_DATA_IN);
+ gpio_val &= int_cause;
+ if (mv_gpio_softc->pin_num > GPIO_PINS_PER_REG) {
+ int_cause_hi = mv_gpio_reg_read(GPIO_HI_INT_CAUSE);
+ gpio_val_hi = mv_gpio_reg_read(GPIO_HI_DATA_IN);
+ gpio_val_hi &= int_cause_hi;
+ }
+
+ i = 0;
+ while (gpio_val != 0) {
+ if (gpio_val & 1)
+ mv_gpio_intr_handler(i);
+ gpio_val >>= 1;
+ i++;
+ }
+
+ if (mv_gpio_softc->pin_num > GPIO_PINS_PER_REG) {
+ i = 0;
+ while (gpio_val_hi != 0) {
+ if (gpio_val_hi & 1)
+ mv_gpio_intr_handler(i + GPIO_PINS_PER_REG);
+ gpio_val_hi >>= 1;
+ i++;
+ }
+ }
+
+ return (FILTER_HANDLED);
+}
+
+/*
+ * GPIO interrupt handling
+ */
+
+static struct intr_event *gpio_events[MV_GPIO_MAX_NPINS];
+
+int
+mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt,
+ void (*hand)(void *), void *arg, int pin, int flags, void **cookiep)
+{
+ struct intr_event *event;
+ int error;
+
+ if (pin < 0 || pin >= mv_gpio_softc->pin_num)
+ return (ENXIO);
+ event = gpio_events[pin];
+ if (event == NULL) {
+ error = intr_event_create(&event, (void *)pin, 0, pin,
+ (void (*)(void *))mv_gpio_intr_mask,
+ (void (*)(void *))mv_gpio_intr_unmask,
+ (void (*)(void *))mv_gpio_int_ack,
+ NULL,
+ "gpio%d:", pin);
+ if (error != 0)
+ return (error);
+ gpio_events[pin] = event;
+ }
+
+ intr_event_add_handler(event, name, filt, hand, arg,
+ intr_priority(flags), flags, cookiep);
+ return (0);
+}
+
+void
+mv_gpio_intr_mask(int pin)
+{
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (gpio_setup[pin] & MV_GPIO_IN_IRQ_EDGE)
+ mv_gpio_edge(pin, 0);
+ else
+ mv_gpio_level(pin, 0);
+}
+
+void
+mv_gpio_intr_unmask(int pin)
+{
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (gpio_setup[pin] & MV_GPIO_IN_IRQ_EDGE)
+ mv_gpio_edge(pin, 1);
+ else
+ mv_gpio_level(pin, 1);
+}
+
+static void
+mv_gpio_intr_handler(int pin)
+{
+ struct intr_event *event;
+
+ event = gpio_events[pin];
+ if (event == NULL || TAILQ_EMPTY(&event->ie_handlers))
+ return;
+
+ intr_event_handle(event, NULL);
+}
+
+static int
+mv_gpio_configure(uint32_t pin, uint32_t flags)
+{
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return (EINVAL);
+
+ if (flags & MV_GPIO_OUT_BLINK)
+ mv_gpio_blink(pin, 1);
+ if (flags & MV_GPIO_IN_POL_LOW)
+ mv_gpio_polarity(pin, 1);
+ if (flags & MV_GPIO_IN_IRQ_EDGE)
+ mv_gpio_edge(pin, 1);
+ if (flags & MV_GPIO_IN_IRQ_LEVEL)
+ mv_gpio_level(pin, 1);
+
+ gpio_setup[pin] = flags;
+
+ return (0);
+}
+
+void
+mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable)
+{
+
+ mv_gpio_value_set(pin, val);
+ mv_gpio_out_en(pin, enable);
+}
+
+uint8_t
+mv_gpio_in(uint32_t pin)
+{
+
+ return (mv_gpio_value_get(pin) ? 1 : 0);
+}
+
+static uint32_t
+mv_gpio_reg_read(uint32_t reg)
+{
+
+ return (bus_space_read_4(mv_gpio_softc->bst,
+ mv_gpio_softc->bsh, reg));
+}
+
+static void
+mv_gpio_reg_write(uint32_t reg, uint32_t val)
+{
+
+ bus_space_write_4(mv_gpio_softc->bst,
+ mv_gpio_softc->bsh, reg, val);
+}
+
+static void
+mv_gpio_reg_set(uint32_t reg, uint32_t pin)
+{
+ uint32_t reg_val;
+
+ reg_val = mv_gpio_reg_read(reg);
+ reg_val |= GPIO(pin);
+ mv_gpio_reg_write(reg, reg_val);
+}
+
+static void
+mv_gpio_reg_clear(uint32_t reg, uint32_t pin)
+{
+ uint32_t reg_val;
+
+ reg_val = mv_gpio_reg_read(reg);
+ reg_val &= ~(GPIO(pin));
+ mv_gpio_reg_write(reg, reg_val);
+}
+
+static void
+mv_gpio_out_en(uint32_t pin, uint8_t enable)
+{
+ uint32_t reg;
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (pin >= GPIO_PINS_PER_REG) {
+ reg = GPIO_HI_DATA_OUT_EN_CTRL;
+ pin -= GPIO_PINS_PER_REG;
+ } else
+ reg = GPIO_DATA_OUT_EN_CTRL;
+
+ if (enable)
+ mv_gpio_reg_clear(reg, pin);
+ else
+ mv_gpio_reg_set(reg, pin);
+}
+
+static void
+mv_gpio_blink(uint32_t pin, uint8_t enable)
+{
+ uint32_t reg;
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (pin >= GPIO_PINS_PER_REG) {
+ reg = GPIO_HI_BLINK_EN;
+ pin -= GPIO_PINS_PER_REG;
+ } else
+ reg = GPIO_BLINK_EN;
+
+ if (enable)
+ mv_gpio_reg_set(reg, pin);
+ else
+ mv_gpio_reg_clear(reg, pin);
+}
+
+static void
+mv_gpio_polarity(uint32_t pin, uint8_t enable)
+{
+ uint32_t reg;
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (pin >= GPIO_PINS_PER_REG) {
+ reg = GPIO_HI_DATA_IN_POLAR;
+ pin -= GPIO_PINS_PER_REG;
+ } else
+ reg = GPIO_DATA_IN_POLAR;
+
+ if (enable)
+ mv_gpio_reg_set(reg, pin);
+ else
+ mv_gpio_reg_clear(reg, pin);
+}
+
+static void
+mv_gpio_level(uint32_t pin, uint8_t enable)
+{
+ uint32_t reg;
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (pin >= GPIO_PINS_PER_REG) {
+ reg = GPIO_HI_INT_LEV_MASK;
+ pin -= GPIO_PINS_PER_REG;
+ } else
+ reg = GPIO_INT_LEV_MASK;
+
+ if (enable)
+ mv_gpio_reg_set(reg, pin);
+ else
+ mv_gpio_reg_clear(reg, pin);
+}
+
+static void
+mv_gpio_edge(uint32_t pin, uint8_t enable)
+{
+ uint32_t reg;
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (pin >= GPIO_PINS_PER_REG) {
+ reg = GPIO_HI_INT_EDGE_MASK;
+ pin -= GPIO_PINS_PER_REG;
+ } else
+ reg = GPIO_INT_EDGE_MASK;
+
+ if (enable)
+ mv_gpio_reg_set(reg, pin);
+ else
+ mv_gpio_reg_clear(reg, pin);
+}
+
+static void
+mv_gpio_int_ack(uint32_t pin)
+{
+ uint32_t reg;
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (pin >= GPIO_PINS_PER_REG) {
+ reg = GPIO_HI_INT_CAUSE;
+ pin -= GPIO_PINS_PER_REG;
+ } else
+ reg = GPIO_INT_CAUSE;
+
+ mv_gpio_reg_clear(reg, pin);
+}
+
+static uint32_t
+mv_gpio_value_get(uint32_t pin)
+{
+ uint32_t reg, reg_val;
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return (0);
+
+ if (pin >= GPIO_PINS_PER_REG) {
+ reg = GPIO_HI_DATA_IN;
+ pin -= GPIO_PINS_PER_REG;
+ } else
+ reg = GPIO_DATA_IN;
+
+ reg_val = mv_gpio_reg_read(reg);
+
+ return (reg_val & GPIO(pin));
+}
+
+static void
+mv_gpio_value_set(uint32_t pin, uint8_t val)
+{
+ uint32_t reg;
+
+ if (pin >= mv_gpio_softc->pin_num)
+ return;
+
+ if (pin >= GPIO_PINS_PER_REG) {
+ reg = GPIO_HI_DATA_OUT;
+ pin -= GPIO_PINS_PER_REG;
+ } else
+ reg = GPIO_DATA_OUT;
+
+ if (val)
+ mv_gpio_reg_set(reg, pin);
+ else
+ mv_gpio_reg_clear(reg, pin);
+}
+
+int
+mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len)
+{
+ pcell_t gpio_cells, pincnt;
+ int inc, t, tuples, tuple_size;
+ int dir, flags, pin;
+ u_long gpio_ctrl, size;
+ struct mv_gpio_softc sc;
+
+ pincnt = 0;
+ if (!OF_hasprop(ctrl, "gpio-controller"))
+ /* Node is not a GPIO controller. */
+ return (ENXIO);
+
+ if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0)
+ return (ENXIO);
+
+ gpio_cells = fdt32_to_cpu(gpio_cells);
+ if (gpio_cells != 3)
+ return (ENXIO);
+
+ tuple_size = gpio_cells * sizeof(pcell_t) + sizeof(phandle_t);
+ tuples = len / tuple_size;
+
+ if (fdt_regsize(ctrl, &gpio_ctrl, &size))
+ return (ENXIO);
+
+ if (OF_getprop(ctrl, "pin-count", &pincnt, sizeof(pcell_t)) < 0)
+ return (ENXIO);
+ sc.pin_num = fdt32_to_cpu(pincnt);
+
+ /*
+ * Skip controller reference, since controller's phandle is given
+ * explicitly (in a function argument).
+ */
+ inc = sizeof(ihandle_t) / sizeof(pcell_t);
+ gpios += inc;
+
+ for (t = 0; t < tuples; t++) {
+ pin = fdt32_to_cpu(gpios[0]);
+ dir = fdt32_to_cpu(gpios[1]);
+ flags = fdt32_to_cpu(gpios[2]);
+
+ mv_gpio_configure(pin, flags);
+
+ if (dir == 1)
+ /* Input. */
+ mv_gpio_out_en(pin, 0);
+ else {
+ /* Output. */
+ if (flags & MV_GPIO_OUT_OPEN_DRAIN)
+ mv_gpio_out(pin, 0, 1);
+
+ if (flags & MV_GPIO_OUT_OPEN_SRC)
+ mv_gpio_out(pin, 1, 1);
+ }
+ gpios += gpio_cells + inc;
+ }
+
+ return (0);
+}
+
+#define MAX_PINS_PER_NODE 5
+#define GPIOS_PROP_CELLS 4
+int
+platform_gpio_init(void)
+{
+ phandle_t child, parent, root, ctrl;
+ pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS];
+ struct gpio_ctrl_entry *e;
+ int len, rv;
+
+ root = OF_finddevice("/");
+ len = 0;
+ parent = root;
+
+ /* Traverse through entire tree to find nodes with 'gpios' prop */
+ for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
+
+ /* Find a 'leaf'. Start the search from this node. */
+ while (OF_child(child)) {
+ parent = child;
+ child = OF_child(child);
+ }
+ if ((len = OF_getproplen(child, "gpios")) > 0) {
+
+ if (len > sizeof(gpios))
+ return (ENXIO);
+
+ /* Get 'gpios' property. */
+ OF_getprop(child, "gpios", &gpios, len);
+
+ e = (struct gpio_ctrl_entry *)&gpio_controllers;
+
+ /* Find and call a handler. */
+ for (; e->compat; e++) {
+ /*
+ * First cell of 'gpios' property should
+ * contain a ref. to a node defining GPIO
+ * controller.
+ */
+ ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0]));
+
+ if (fdt_is_compatible(ctrl, e->compat))
+ /* Call a handler. */
+ if ((rv = e->handler(ctrl,
+ (pcell_t *)&gpios, len)))
+ return (rv);
+ }
+ }
+
+ if (OF_peer(child) == 0) {
+ /* No more siblings. */
+ child = parent;
+ parent = OF_parent(child);
+ }
+ }
+ return (0);
+}
Property changes on: trunk/sys/arm/mv/gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/ic.c
===================================================================
--- trunk/sys/arm/mv/ic.c (rev 0)
+++ trunk/sys/arm/mv/ic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,314 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice.
+ * Copyright (C) 2007-2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Adapted and extended to Marvell SoCs by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_icu.c, rev 1
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/ic.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+
+struct mv_ic_softc {
+ struct resource * ic_res[1];
+ bus_space_tag_t ic_bst;
+ bus_space_handle_t ic_bsh;
+ int ic_high_regs;
+ int ic_error_regs;
+};
+
+static struct resource_spec mv_ic_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct mv_ic_softc *mv_ic_sc = NULL;
+
+static int mv_ic_probe(device_t);
+static int mv_ic_attach(device_t);
+
+uint32_t mv_ic_get_cause(void);
+uint32_t mv_ic_get_mask(void);
+void mv_ic_set_mask(uint32_t);
+uint32_t mv_ic_get_cause_hi(void);
+uint32_t mv_ic_get_mask_hi(void);
+void mv_ic_set_mask_hi(uint32_t);
+uint32_t mv_ic_get_cause_error(void);
+uint32_t mv_ic_get_mask_error(void);
+void mv_ic_set_mask_error(uint32_t);
+static void arm_mask_irq_all(void);
+
+static int
+mv_ic_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "mrvl,pic"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell Integrated Interrupt Controller");
+ return (0);
+}
+
+static int
+mv_ic_attach(device_t dev)
+{
+ struct mv_ic_softc *sc;
+ uint32_t dev_id, rev_id;
+ int error;
+
+ sc = (struct mv_ic_softc *)device_get_softc(dev);
+
+ if (mv_ic_sc != NULL)
+ return (ENXIO);
+ mv_ic_sc = sc;
+
+ soc_id(&dev_id, &rev_id);
+
+ sc->ic_high_regs = 0;
+ sc->ic_error_regs = 0;
+
+ if (dev_id == MV_DEV_88F6281 ||
+ dev_id == MV_DEV_88F6282 ||
+ dev_id == MV_DEV_MV78100 ||
+ dev_id == MV_DEV_MV78100_Z0)
+ sc->ic_high_regs = 1;
+
+ if (dev_id == MV_DEV_MV78100 || dev_id == MV_DEV_MV78100_Z0)
+ sc->ic_error_regs = 1;
+
+ error = bus_alloc_resources(dev, mv_ic_spec, sc->ic_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->ic_bst = rman_get_bustag(sc->ic_res[0]);
+ sc->ic_bsh = rman_get_bushandle(sc->ic_res[0]);
+
+ /* Mask all interrupts */
+ arm_mask_irq_all();
+
+ return (0);
+}
+
+static device_method_t mv_ic_methods[] = {
+ DEVMETHOD(device_probe, mv_ic_probe),
+ DEVMETHOD(device_attach, mv_ic_attach),
+ { 0, 0 }
+};
+
+static driver_t mv_ic_driver = {
+ "ic",
+ mv_ic_methods,
+ sizeof(struct mv_ic_softc),
+};
+
+static devclass_t mv_ic_devclass;
+
+DRIVER_MODULE(ic, simplebus, mv_ic_driver, mv_ic_devclass, 0, 0);
+
+int
+arm_get_next_irq(int last)
+{
+ u_int filt, irq;
+ int next;
+
+ filt = ~((last >= 0) ? (2 << last) - 1 : 0);
+ irq = mv_ic_get_cause() & mv_ic_get_mask();
+ if (irq & filt) {
+ next = ffs(irq & filt) - 1;
+ goto out;
+ }
+ if (mv_ic_sc->ic_high_regs) {
+ filt = ~((last >= 32) ? (2 << (last - 32)) - 1 : 0);
+ irq = mv_ic_get_cause_hi() & mv_ic_get_mask_hi();
+ if (irq & filt) {
+ next = ffs(irq & filt) + 31;
+ goto out;
+ }
+ }
+ if (mv_ic_sc->ic_error_regs) {
+ filt = ~((last >= 64) ? (2 << (last - 64)) - 1 : 0);
+ irq = mv_ic_get_cause_error() & mv_ic_get_mask_error();
+ if (irq & filt) {
+ next = ffs(irq & filt) + 63;
+ goto out;
+ }
+ }
+ next = -1;
+
+ out:
+ CTR3(KTR_INTR, "%s: last=%d, next=%d", __func__, last, next);
+ return (next);
+}
+
+static void
+arm_mask_irq_all(void)
+{
+
+ mv_ic_set_mask(0);
+
+ if (mv_ic_sc->ic_high_regs)
+ mv_ic_set_mask_hi(0);
+
+ if (mv_ic_sc->ic_error_regs)
+ mv_ic_set_mask_error(0);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ uint32_t mr;
+
+ if (nb < 32) {
+ mr = mv_ic_get_mask();
+ mr &= ~(1 << nb);
+ mv_ic_set_mask(mr);
+
+ } else if ((nb < 64) && mv_ic_sc->ic_high_regs) {
+ mr = mv_ic_get_mask_hi();
+ mr &= ~(1 << (nb - 32));
+ mv_ic_set_mask_hi(mr);
+
+ } else if ((nb < 96) && mv_ic_sc->ic_error_regs) {
+ mr = mv_ic_get_mask_error();
+ mr &= ~(1 << (nb - 64));
+ mv_ic_set_mask_error(mr);
+ }
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ uint32_t mr;
+
+ if (nb < 32) {
+ mr = mv_ic_get_mask();
+ mr |= (1 << nb);
+ mv_ic_set_mask(mr);
+
+ } else if ((nb < 64) && mv_ic_sc->ic_high_regs) {
+ mr = mv_ic_get_mask_hi();
+ mr |= (1 << (nb - 32));
+ mv_ic_set_mask_hi(mr);
+
+ } else if ((nb < 96) && mv_ic_sc->ic_error_regs) {
+ mr = mv_ic_get_mask_error();
+ mr |= (1 << (nb - 64));
+ mv_ic_set_mask_error(mr);
+ }
+}
+
+void
+mv_ic_set_mask(uint32_t val)
+{
+
+ bus_space_write_4(mv_ic_sc->ic_bst, mv_ic_sc->ic_bsh,
+ IRQ_MASK, val);
+}
+
+uint32_t
+mv_ic_get_mask(void)
+{
+
+ return (bus_space_read_4(mv_ic_sc->ic_bst,
+ mv_ic_sc->ic_bsh, IRQ_MASK));
+}
+
+uint32_t
+mv_ic_get_cause(void)
+{
+
+ return (bus_space_read_4(mv_ic_sc->ic_bst,
+ mv_ic_sc->ic_bsh, IRQ_CAUSE));
+}
+
+void
+mv_ic_set_mask_hi(uint32_t val)
+{
+
+ bus_space_write_4(mv_ic_sc->ic_bst, mv_ic_sc->ic_bsh,
+ IRQ_MASK_HI, val);
+}
+
+uint32_t
+mv_ic_get_mask_hi(void)
+{
+
+ return (bus_space_read_4(mv_ic_sc->ic_bst,
+ mv_ic_sc->ic_bsh, IRQ_MASK_HI));
+}
+
+uint32_t
+mv_ic_get_cause_hi(void)
+{
+
+ return (bus_space_read_4(mv_ic_sc->ic_bst,
+ mv_ic_sc->ic_bsh, IRQ_CAUSE_HI));
+}
+
+void
+mv_ic_set_mask_error(uint32_t val)
+{
+
+ bus_space_write_4(mv_ic_sc->ic_bst, mv_ic_sc->ic_bsh,
+ IRQ_MASK_ERROR, val);
+}
+
+uint32_t
+mv_ic_get_mask_error(void)
+{
+
+ return (bus_space_read_4(mv_ic_sc->ic_bst,
+ mv_ic_sc->ic_bsh, IRQ_MASK_ERROR));
+}
+
+uint32_t
+mv_ic_get_cause_error(void)
+{
+
+ return (bus_space_read_4(mv_ic_sc->ic_bst,
+ mv_ic_sc->ic_bsh, IRQ_CAUSE_ERROR));
+}
Property changes on: trunk/sys/arm/mv/ic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/kirkwood/files.kirkwood
===================================================================
--- trunk/sys/arm/mv/kirkwood/files.kirkwood (rev 0)
+++ trunk/sys/arm/mv/kirkwood/files.kirkwood 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+# $FreeBSD: stable/10/sys/arm/mv/kirkwood/files.kirkwood 239277 2012-08-15 05:15:49Z gonzo $
+
+arm/mv/ic.c standard
+arm/mv/rtc.c standard
+arm/mv/kirkwood/kirkwood.c standard
Property changes on: trunk/sys/arm/mv/kirkwood/files.kirkwood
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/kirkwood/kirkwood.c
===================================================================
--- trunk/sys/arm/mv/kirkwood/kirkwood.c (rev 0)
+++ trunk/sys/arm/mv/kirkwood/kirkwood.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,82 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/kirkwood/kirkwood.c 238873 2012-07-28 21:56:24Z hrs $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+#include <arm/mv/mvwin.h>
+
+struct resource_spec mv_gpio_res[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { SYS_RES_IRQ, 4, RF_ACTIVE },
+ { SYS_RES_IRQ, 5, RF_ACTIVE },
+ { SYS_RES_IRQ, 6, RF_ACTIVE },
+ { -1, 0 }
+};
+
+const struct decode_win xor_win_tbl[] = {
+ { 0 },
+};
+const struct decode_win *xor_wins = xor_win_tbl;
+int xor_wins_no = 0;
+
+uint32_t
+get_tclk(void)
+{
+ uint32_t dev, rev;
+
+ /*
+ * On Kirkwood TCLK is not configurable and depends on silicon
+ * revision:
+ * - A0 and A1 have TCLK hardcoded to 200 MHz.
+ * - Z0 and others have TCLK hardcoded to 166 MHz.
+ */
+ soc_id(&dev, &rev);
+ if (dev == MV_DEV_88F6281 && (rev == 2 || rev == 3))
+ return (TCLK_200MHZ);
+ if (dev == MV_DEV_88F6282)
+ return (TCLK_200MHZ);
+
+ return (TCLK_166MHZ);
+}
Property changes on: trunk/sys/arm/mv/kirkwood/kirkwood.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/kirkwood/std.db88f6xxx
===================================================================
--- trunk/sys/arm/mv/kirkwood/std.db88f6xxx (rev 0)
+++ trunk/sys/arm/mv/kirkwood/std.db88f6xxx 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+# $FreeBSD: stable/10/sys/arm/mv/kirkwood/std.db88f6xxx 210249 2010-07-19 19:19:33Z raj $
+
+include "../mv/std.mv"
+include "../mv/kirkwood/std.kirkwood"
+files "../mv/kirkwood/files.kirkwood"
Property changes on: trunk/sys/arm/mv/kirkwood/std.db88f6xxx
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/kirkwood/std.kirkwood
===================================================================
--- trunk/sys/arm/mv/kirkwood/std.kirkwood (rev 0)
+++ trunk/sys/arm/mv/kirkwood/std.kirkwood 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,14 @@
+# $FreeBSD: stable/10/sys/arm/mv/kirkwood/std.kirkwood 266110 2014-05-15 02:41:23Z ian $
+
+# kernel gets loaded at 0x00900000 by the loader, but runs at virtual address
+# 0xc0900000. RAM starts at 0. We put the pagetable at a reasonable place
+# in memory, but may need to bounce it higher if there's a problem with this.
+# We could paper over this by loading the kernel at 0xc0000000 virtual, but
+# that leads to other complications, so we'll just reclaim the lower region of
+# ram after we're loaded. Put the page tables for startup at 1MB.
+makeoptions KERNPHYSADDR=0x00900000
+makeoptions KERNVIRTADDR=0xc0900000
+
+options KERNPHYSADDR=0x00900000
+options KERNVIRTADDR=0xc0900000
+options PHYSADDR=0x00000000
Property changes on: trunk/sys/arm/mv/kirkwood/std.kirkwood
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/mpic.c
===================================================================
--- trunk/sys/arm/mv/mpic.c (rev 0)
+++ trunk/sys/arm/mv/mpic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,399 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice.
+ * Copyright (C) 2007-2011 MARVELL INTERNATIONAL LTD.
+ * Copyright (c) 2012 Semihalf.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_icu.c, rev 1
+ * from: FreeBSD: src/sys/arm/mv/ic.c,v 1.5 2011/02/08 01:49:30
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/mpic.c 289184 2015-10-12 13:20:17Z andrew $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/cpuset.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/cpufunc.h>
+#include <machine/smp.h>
+
+#include <arm/mv/mvvar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/fdt/fdt_common.h>
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#define MPIC_INT_ERR 4
+#define MPIC_INT_MSI 96
+
+#define IRQ_MASK 0x3ff
+
+#define MPIC_CTRL 0x0
+#define MPIC_SOFT_INT 0x4
+#define MPIC_SOFT_INT_DRBL1 (1 << 5)
+#define MPIC_ERR_CAUSE 0x20
+#define MPIC_ISE 0x30
+#define MPIC_ICE 0x34
+
+
+#define MPIC_IN_DRBL 0x78
+#define MPIC_IN_DRBL_MASK 0x7c
+#define MPIC_CTP 0xb0
+#define MPIC_CTP 0xb0
+#define MPIC_IIACK 0xb4
+#define MPIC_ISM 0xb8
+#define MPIC_ICM 0xbc
+#define MPIC_ERR_MASK 0xec0
+
+struct mv_mpic_softc {
+ device_t sc_dev;
+ struct resource * mpic_res[3];
+ bus_space_tag_t mpic_bst;
+ bus_space_handle_t mpic_bsh;
+ bus_space_tag_t cpu_bst;
+ bus_space_handle_t cpu_bsh;
+ bus_space_tag_t drbl_bst;
+ bus_space_handle_t drbl_bsh;
+};
+
+static struct resource_spec mv_mpic_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct mv_mpic_softc *mv_mpic_sc = NULL;
+
+void mpic_send_ipi(int cpus, u_int ipi);
+
+static int mv_mpic_probe(device_t);
+static int mv_mpic_attach(device_t);
+uint32_t mv_mpic_get_cause(void);
+uint32_t mv_mpic_get_cause_err(void);
+uint32_t mv_mpic_get_msi(void);
+static void arm_mask_irq_err(uintptr_t);
+static void arm_unmask_irq_err(uintptr_t);
+static void arm_unmask_msi(void);
+
+#define MPIC_CPU_WRITE(softc, reg, val) \
+ bus_space_write_4((softc)->cpu_bst, (softc)->cpu_bsh, (reg), (val))
+#define MPIC_CPU_READ(softc, reg) \
+ bus_space_read_4((softc)->cpu_bst, (softc)->cpu_bsh, (reg))
+
+#define MPIC_DRBL_WRITE(softc, reg, val) \
+ bus_space_write_4((softc)->drbl_bst, (softc)->drbl_bsh, (reg), (val))
+#define MPIC_DRBL_READ(softc, reg) \
+ bus_space_read_4((softc)->drbl_bst, (softc)->drbl_bsh, (reg))
+
+static int
+mv_mpic_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "mrvl,mpic"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell Integrated Interrupt Controller");
+ return (0);
+}
+
+static int
+mv_mpic_attach(device_t dev)
+{
+ struct mv_mpic_softc *sc;
+ int error;
+
+ sc = (struct mv_mpic_softc *)device_get_softc(dev);
+
+ if (mv_mpic_sc != NULL)
+ return (ENXIO);
+ mv_mpic_sc = sc;
+
+ sc->sc_dev = dev;
+
+ error = bus_alloc_resources(dev, mv_mpic_spec, sc->mpic_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->mpic_bst = rman_get_bustag(sc->mpic_res[0]);
+ sc->mpic_bsh = rman_get_bushandle(sc->mpic_res[0]);
+
+ sc->cpu_bst = rman_get_bustag(sc->mpic_res[1]);
+ sc->cpu_bsh = rman_get_bushandle(sc->mpic_res[1]);
+
+ sc->drbl_bst = rman_get_bustag(sc->mpic_res[2]);
+ sc->drbl_bsh = rman_get_bushandle(sc->mpic_res[2]);
+
+ bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
+ MPIC_CTRL, 1);
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 0);
+
+ arm_unmask_msi();
+
+ return (0);
+}
+
+static device_method_t mv_mpic_methods[] = {
+ DEVMETHOD(device_probe, mv_mpic_probe),
+ DEVMETHOD(device_attach, mv_mpic_attach),
+ { 0, 0 }
+};
+
+static driver_t mv_mpic_driver = {
+ "mpic",
+ mv_mpic_methods,
+ sizeof(struct mv_mpic_softc),
+};
+
+static devclass_t mv_mpic_devclass;
+
+DRIVER_MODULE(mpic, simplebus, mv_mpic_driver, mv_mpic_devclass, 0, 0);
+
+int
+arm_get_next_irq(int last)
+{
+ u_int irq, next = -1;
+
+ irq = mv_mpic_get_cause() & IRQ_MASK;
+ CTR2(KTR_INTR, "%s: irq:%#x", __func__, irq);
+
+ if (irq != IRQ_MASK) {
+ if (irq == MPIC_INT_ERR)
+ irq = mv_mpic_get_cause_err();
+ if (irq == MPIC_INT_MSI)
+ irq = mv_mpic_get_msi();
+ next = irq;
+ }
+
+ CTR3(KTR_INTR, "%s: last=%d, next=%d", __func__, last, next);
+ return (next);
+}
+
+/*
+ * XXX We can make arm_enable_irq to operate on ICE and then mask/unmask only
+ * by ISM/ICM and remove access to ICE in masking operation
+ */
+void
+arm_mask_irq(uintptr_t nb)
+{
+
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 1);
+
+ if (nb < ERR_IRQ) {
+ bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
+ MPIC_ICE, nb);
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ISM, nb);
+ } else if (nb < MSI_IRQ)
+ arm_mask_irq_err(nb);
+}
+
+
+static void
+arm_mask_irq_err(uintptr_t nb)
+{
+ uint32_t mask;
+ uint8_t bit_off;
+
+ bit_off = nb - ERR_IRQ;
+ mask = MPIC_CPU_READ(mv_mpic_sc, MPIC_ERR_MASK);
+ mask &= ~(1 << bit_off);
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ERR_MASK, mask);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 0);
+
+ if (nb < ERR_IRQ) {
+ bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
+ MPIC_ISE, nb);
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ICM, nb);
+ } else if (nb < MSI_IRQ)
+ arm_unmask_irq_err(nb);
+
+ if (nb == 0)
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DRBL_MASK, 0xffffffff);
+}
+
+void
+arm_unmask_irq_err(uintptr_t nb)
+{
+ uint32_t mask;
+ uint8_t bit_off;
+
+ bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
+ MPIC_ISE, MPIC_INT_ERR);
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ICM, MPIC_INT_ERR);
+
+ bit_off = nb - ERR_IRQ;
+ mask = MPIC_CPU_READ(mv_mpic_sc, MPIC_ERR_MASK);
+ mask |= (1 << bit_off);
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ERR_MASK, mask);
+}
+
+static void
+arm_unmask_msi(void)
+{
+
+ arm_unmask_irq(MPIC_INT_MSI);
+}
+
+uint32_t
+mv_mpic_get_cause(void)
+{
+
+ return (MPIC_CPU_READ(mv_mpic_sc, MPIC_IIACK));
+}
+
+uint32_t
+mv_mpic_get_cause_err(void)
+{
+ uint32_t err_cause;
+ uint8_t bit_off;
+
+ err_cause = bus_space_read_4(mv_mpic_sc->mpic_bst,
+ mv_mpic_sc->mpic_bsh, MPIC_ERR_CAUSE);
+
+ if (err_cause)
+ bit_off = ffs(err_cause) - 1;
+ else
+ return (-1);
+
+ debugf("%s: irq:%x cause:%x\n", __func__, bit_off, err_cause);
+ return (ERR_IRQ + bit_off);
+}
+
+uint32_t
+mv_mpic_get_msi(void)
+{
+ uint32_t cause;
+ uint8_t bit_off;
+
+ cause = MPIC_DRBL_READ(mv_mpic_sc, 0);
+
+ if (cause)
+ bit_off = ffs(cause) - 1;
+ else
+ return (-1);
+
+ debugf("%s: irq:%x cause:%x\n", __func__, bit_off, cause);
+
+ cause &= ~(1 << bit_off);
+ MPIC_DRBL_WRITE(mv_mpic_sc, 0, cause);
+
+ return (MSI_IRQ + bit_off);
+}
+
+int
+mv_msi_data(int irq, uint64_t *addr, uint32_t *data)
+{
+ u_long phys, base, size;
+ phandle_t node;
+ int error;
+
+ node = ofw_bus_get_node(mv_mpic_sc->sc_dev);
+
+ /* Get physical addres of register space */
+ error = fdt_get_range(OF_parent(node), 0, &phys, &size);
+ if (error) {
+ printf("%s: Cannot get register physical address, err:%d",
+ __func__, error);
+ return (error);
+ }
+
+ /* Get offset of MPIC register space */
+ error = fdt_regsize(node, &base, &size);
+ if (error) {
+ printf("%s: Cannot get MPIC register offset, err:%d",
+ __func__, error);
+ return (error);
+ }
+
+ *addr = phys + base + MPIC_SOFT_INT;
+ *data = MPIC_SOFT_INT_DRBL1 | irq;
+
+ return (0);
+}
+
+#if defined(SMP)
+void
+pic_ipi_send(cpuset_t cpus, u_int ipi)
+{
+ uint32_t val, i;
+
+ val = 0x00000000;
+ for (i = 0; i < MAXCPU; i++)
+ if (CPU_ISSET(i, &cpus))
+ val |= (1 << (8 + i));
+ val |= ipi;
+ bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
+ MPIC_SOFT_INT, val);
+}
+
+int
+pic_ipi_get(int i __unused)
+{
+ uint32_t val;
+ int ipi;
+
+ val = MPIC_CPU_READ(mv_mpic_sc, MPIC_IN_DRBL);
+ if (val) {
+ ipi = ffs(val) - 1;
+ MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DRBL, ~(1 << ipi));
+ return (ipi);
+ }
+
+ return (0x3ff);
+}
+
+void
+pic_ipi_clear(int ipi)
+{
+}
+
+#endif
Property changes on: trunk/sys/arm/mv/mpic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/mv_common.c
===================================================================
--- trunk/sys/arm/mv/mv_common.c (rev 0)
+++ trunk/sys/arm/mv/mv_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,2211 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_global.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/mv_common.c 266277 2014-05-17 00:53:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kdb.h>
+#include <sys/reboot.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+#include <arm/mv/mvwin.h>
+
+
+MALLOC_DEFINE(M_IDMA, "idma", "idma dma test memory");
+
+#define IDMA_DEBUG
+#undef IDMA_DEBUG
+
+#define MAX_CPU_WIN 5
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#ifdef DEBUG
+#define MV_DUMP_WIN 1
+#else
+#define MV_DUMP_WIN 0
+#endif
+
+static int win_eth_can_remap(int i);
+
+#ifndef SOC_MV_FREY
+static int decode_win_cpu_valid(void);
+#endif
+static int decode_win_usb_valid(void);
+static int decode_win_eth_valid(void);
+static int decode_win_pcie_valid(void);
+static int decode_win_sata_valid(void);
+
+static int decode_win_idma_valid(void);
+static int decode_win_xor_valid(void);
+
+#ifndef SOC_MV_FREY
+static void decode_win_cpu_setup(void);
+#endif
+#ifdef SOC_MV_ARMADAXP
+static int decode_win_sdram_fixup(void);
+#endif
+static void decode_win_usb_setup(u_long);
+static void decode_win_eth_setup(u_long);
+static void decode_win_sata_setup(u_long);
+
+static void decode_win_idma_setup(u_long);
+static void decode_win_xor_setup(u_long);
+
+static void decode_win_usb_dump(u_long);
+static void decode_win_eth_dump(u_long base);
+static void decode_win_idma_dump(u_long base);
+static void decode_win_xor_dump(u_long base);
+
+static int fdt_get_ranges(const char *, void *, int, int *, int *);
+
+static int win_cpu_from_dt(void);
+static int fdt_win_setup(void);
+
+static uint32_t dev_mask = 0;
+static int cpu_wins_no = 0;
+static int eth_port = 0;
+static int usb_port = 0;
+
+static struct decode_win cpu_win_tbl[MAX_CPU_WIN];
+
+const struct decode_win *cpu_wins = cpu_win_tbl;
+
+typedef void (*decode_win_setup_t)(u_long);
+typedef void (*dump_win_t)(u_long);
+
+struct soc_node_spec {
+ const char *compat;
+ decode_win_setup_t decode_handler;
+ dump_win_t dump_handler;
+};
+
+static struct soc_node_spec soc_nodes[] = {
+ { "mrvl,ge", &decode_win_eth_setup, &decode_win_eth_dump },
+ { "mrvl,usb-ehci", &decode_win_usb_setup, &decode_win_usb_dump },
+ { "mrvl,sata", &decode_win_sata_setup, NULL },
+ { "mrvl,xor", &decode_win_xor_setup, &decode_win_xor_dump },
+ { "mrvl,idma", &decode_win_idma_setup, &decode_win_idma_dump },
+ { "mrvl,pcie", &decode_win_pcie_setup, NULL },
+ { NULL, NULL, NULL },
+};
+
+struct fdt_pm_mask_entry fdt_pm_mask_table[] = {
+ { "mrvl,ge", CPU_PM_CTRL_GE(0) },
+ { "mrvl,ge", CPU_PM_CTRL_GE(1) },
+ { "mrvl,usb-ehci", CPU_PM_CTRL_USB(0) },
+ { "mrvl,usb-ehci", CPU_PM_CTRL_USB(1) },
+ { "mrvl,usb-ehci", CPU_PM_CTRL_USB(2) },
+ { "mrvl,xor", CPU_PM_CTRL_XOR },
+ { "mrvl,sata", CPU_PM_CTRL_SATA },
+
+ { NULL, 0 }
+};
+
+static __inline int
+pm_is_disabled(uint32_t mask)
+{
+#if defined(SOC_MV_KIRKWOOD)
+ return (soc_power_ctrl_get(mask) == mask);
+#else
+ return (soc_power_ctrl_get(mask) == mask ? 0 : 1);
+#endif
+}
+
+/*
+ * Disable device using power management register.
+ * 1 - Device Power On
+ * 0 - Device Power Off
+ * Mask can be set in loader.
+ * EXAMPLE:
+ * loader> set hw.pm-disable-mask=0x2
+ *
+ * Common mask:
+ * |-------------------------------|
+ * | Device | Kirkwood | Discovery |
+ * |-------------------------------|
+ * | USB0 | 0x00008 | 0x020000 |
+ * |-------------------------------|
+ * | USB1 | - | 0x040000 |
+ * |-------------------------------|
+ * | USB2 | - | 0x080000 |
+ * |-------------------------------|
+ * | GE0 | 0x00001 | 0x000002 |
+ * |-------------------------------|
+ * | GE1 | - | 0x000004 |
+ * |-------------------------------|
+ * | IDMA | - | 0x100000 |
+ * |-------------------------------|
+ * | XOR | 0x10000 | 0x200000 |
+ * |-------------------------------|
+ * | CESA | 0x20000 | 0x400000 |
+ * |-------------------------------|
+ * | SATA | 0x04000 | 0x004000 |
+ * --------------------------------|
+ * This feature can be used only on Kirkwood and Discovery
+ * machines.
+ */
+static __inline void
+pm_disable_device(int mask)
+{
+#ifdef DIAGNOSTIC
+ uint32_t reg;
+
+ reg = soc_power_ctrl_get(CPU_PM_CTRL_ALL);
+ printf("Power Management Register: 0%x\n", reg);
+
+ reg &= ~mask;
+ soc_power_ctrl_set(reg);
+ printf("Device %x is disabled\n", mask);
+
+ reg = soc_power_ctrl_get(CPU_PM_CTRL_ALL);
+ printf("Power Management Register: 0%x\n", reg);
+#endif
+}
+
+int
+fdt_pm(phandle_t node)
+{
+ uint32_t cpu_pm_ctrl;
+ int i, ena, compat;
+
+ ena = 1;
+ cpu_pm_ctrl = read_cpu_ctrl(CPU_PM_CTRL);
+ for (i = 0; fdt_pm_mask_table[i].compat != NULL; i++) {
+ if (dev_mask & (1 << i))
+ continue;
+
+ compat = fdt_is_compatible(node, fdt_pm_mask_table[i].compat);
+#if defined(SOC_MV_KIRKWOOD)
+ if (compat && (cpu_pm_ctrl & fdt_pm_mask_table[i].mask)) {
+ dev_mask |= (1 << i);
+ ena = 0;
+ break;
+ } else if (compat) {
+ dev_mask |= (1 << i);
+ break;
+ }
+#else
+ if (compat && (~cpu_pm_ctrl & fdt_pm_mask_table[i].mask)) {
+ dev_mask |= (1 << i);
+ ena = 0;
+ break;
+ } else if (compat) {
+ dev_mask |= (1 << i);
+ break;
+ }
+#endif
+ }
+
+ return (ena);
+}
+
+uint32_t
+read_cpu_ctrl(uint32_t reg)
+{
+
+ return (bus_space_read_4(fdtbus_bs_tag, MV_CPU_CONTROL_BASE, reg));
+}
+
+void
+write_cpu_ctrl(uint32_t reg, uint32_t val)
+{
+
+ bus_space_write_4(fdtbus_bs_tag, MV_CPU_CONTROL_BASE, reg, val);
+}
+
+#if defined(SOC_MV_ARMADAXP)
+uint32_t
+read_cpu_mp_clocks(uint32_t reg)
+{
+
+ return (bus_space_read_4(fdtbus_bs_tag, MV_MP_CLOCKS_BASE, reg));
+}
+
+void
+write_cpu_mp_clocks(uint32_t reg, uint32_t val)
+{
+
+ bus_space_write_4(fdtbus_bs_tag, MV_MP_CLOCKS_BASE, reg, val);
+}
+
+uint32_t
+read_cpu_misc(uint32_t reg)
+{
+
+ return (bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE, reg));
+}
+
+void
+write_cpu_misc(uint32_t reg, uint32_t val)
+{
+
+ bus_space_write_4(fdtbus_bs_tag, MV_MISC_BASE, reg, val);
+}
+#endif
+
+void
+cpu_reset(void)
+{
+
+#if defined(SOC_MV_ARMADAXP)
+ write_cpu_misc(RSTOUTn_MASK, SOFT_RST_OUT_EN);
+ write_cpu_misc(SYSTEM_SOFT_RESET, SYS_SOFT_RST);
+#else
+ write_cpu_ctrl(RSTOUTn_MASK, SOFT_RST_OUT_EN);
+ write_cpu_ctrl(SYSTEM_SOFT_RESET, SYS_SOFT_RST);
+#endif
+ while (1);
+}
+
+uint32_t
+cpu_extra_feat(void)
+{
+ uint32_t dev, rev;
+ uint32_t ef = 0;
+
+ soc_id(&dev, &rev);
+
+ switch (dev) {
+ case MV_DEV_88F6281:
+ case MV_DEV_88F6282:
+ case MV_DEV_88RC8180:
+ case MV_DEV_MV78100_Z0:
+ case MV_DEV_MV78100:
+ __asm __volatile("mrc p15, 1, %0, c15, c1, 0" : "=r" (ef));
+ break;
+ case MV_DEV_88F5182:
+ case MV_DEV_88F5281:
+ __asm __volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (ef));
+ break;
+ default:
+ if (bootverbose)
+ printf("This ARM Core does not support any extra features\n");
+ }
+
+ return (ef);
+}
+
+/*
+ * Get the power status of device. This feature is only supported on
+ * Kirkwood and Discovery SoCs.
+ */
+uint32_t
+soc_power_ctrl_get(uint32_t mask)
+{
+
+#if !defined(SOC_MV_ORION) && !defined(SOC_MV_LOKIPLUS) && !defined(SOC_MV_FREY)
+ if (mask != CPU_PM_CTRL_NONE)
+ mask &= read_cpu_ctrl(CPU_PM_CTRL);
+
+ return (mask);
+#else
+ return (mask);
+#endif
+}
+
+/*
+ * Set the power status of device. This feature is only supported on
+ * Kirkwood and Discovery SoCs.
+ */
+void
+soc_power_ctrl_set(uint32_t mask)
+{
+
+#if !defined(SOC_MV_ORION) && !defined(SOC_MV_LOKIPLUS)
+ if (mask != CPU_PM_CTRL_NONE)
+ write_cpu_ctrl(CPU_PM_CTRL, mask);
+#endif
+}
+
+void
+soc_id(uint32_t *dev, uint32_t *rev)
+{
+
+ /*
+ * Notice: system identifiers are available in the registers range of
+ * PCIE controller, so using this function is only allowed (and
+ * possible) after the internal registers range has been mapped in via
+ * pmap_devmap_bootstrap().
+ */
+ *dev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 0) >> 16;
+ *rev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 8) & 0xff;
+}
+
+static void
+soc_identify(void)
+{
+ uint32_t d, r, size, mode;
+ const char *dev;
+ const char *rev;
+
+ soc_id(&d, &r);
+
+ printf("SOC: ");
+ if (bootverbose)
+ printf("(0x%4x:0x%02x) ", d, r);
+
+ rev = "";
+ switch (d) {
+ case MV_DEV_88F5181:
+ dev = "Marvell 88F5181";
+ if (r == 3)
+ rev = "B1";
+ break;
+ case MV_DEV_88F5182:
+ dev = "Marvell 88F5182";
+ if (r == 2)
+ rev = "A2";
+ break;
+ case MV_DEV_88F5281:
+ dev = "Marvell 88F5281";
+ if (r == 4)
+ rev = "D0";
+ else if (r == 5)
+ rev = "D1";
+ else if (r == 6)
+ rev = "D2";
+ break;
+ case MV_DEV_88F6281:
+ dev = "Marvell 88F6281";
+ if (r == 0)
+ rev = "Z0";
+ else if (r == 2)
+ rev = "A0";
+ else if (r == 3)
+ rev = "A1";
+ break;
+ case MV_DEV_88RC8180:
+ dev = "Marvell 88RC8180";
+ break;
+ case MV_DEV_88RC9480:
+ dev = "Marvell 88RC9480";
+ break;
+ case MV_DEV_88RC9580:
+ dev = "Marvell 88RC9580";
+ break;
+ case MV_DEV_88F6781:
+ dev = "Marvell 88F6781";
+ if (r == 2)
+ rev = "Y0";
+ break;
+ case MV_DEV_88F6282:
+ dev = "Marvell 88F6282";
+ if (r == 0)
+ rev = "A0";
+ else if (r == 1)
+ rev = "A1";
+ break;
+ case MV_DEV_MV78100_Z0:
+ dev = "Marvell MV78100 Z0";
+ break;
+ case MV_DEV_MV78100:
+ dev = "Marvell MV78100";
+ break;
+ case MV_DEV_MV78160:
+ dev = "Marvell MV78160";
+ break;
+ case MV_DEV_MV78260:
+ dev = "Marvell MV78260";
+ break;
+ case MV_DEV_MV78460:
+ dev = "Marvell MV78460";
+ break;
+ default:
+ dev = "UNKNOWN";
+ break;
+ }
+
+ printf("%s", dev);
+ if (*rev != '\0')
+ printf(" rev %s", rev);
+ printf(", TClock %dMHz\n", get_tclk() / 1000 / 1000);
+
+ mode = read_cpu_ctrl(CPU_CONFIG);
+ printf(" Instruction cache prefetch %s, data cache prefetch %s\n",
+ (mode & CPU_CONFIG_IC_PREF) ? "enabled" : "disabled",
+ (mode & CPU_CONFIG_DC_PREF) ? "enabled" : "disabled");
+
+ switch (d) {
+ case MV_DEV_88F6281:
+ case MV_DEV_88F6282:
+ mode = read_cpu_ctrl(CPU_L2_CONFIG) & CPU_L2_CONFIG_MODE;
+ printf(" 256KB 4-way set-associative %s unified L2 cache\n",
+ mode ? "write-through" : "write-back");
+ break;
+ case MV_DEV_MV78100:
+ mode = read_cpu_ctrl(CPU_CONTROL);
+ size = mode & CPU_CONTROL_L2_SIZE;
+ mode = mode & CPU_CONTROL_L2_MODE;
+ printf(" %s set-associative %s unified L2 cache\n",
+ size ? "256KB 4-way" : "512KB 8-way",
+ mode ? "write-through" : "write-back");
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+platform_identify(void *dummy)
+{
+
+ soc_identify();
+
+ /*
+ * XXX Board identification e.g. read out from FPGA or similar should
+ * go here
+ */
+}
+SYSINIT(platform_identify, SI_SUB_CPU, SI_ORDER_SECOND, platform_identify,
+ NULL);
+
+#ifdef KDB
+static void
+mv_enter_debugger(void *dummy)
+{
+
+ if (boothowto & RB_KDB)
+ kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
+}
+SYSINIT(mv_enter_debugger, SI_SUB_CPU, SI_ORDER_ANY, mv_enter_debugger, NULL);
+#endif
+
+int
+soc_decode_win(void)
+{
+ uint32_t dev, rev;
+ int mask, err;
+
+ mask = 0;
+ TUNABLE_INT_FETCH("hw.pm-disable-mask", &mask);
+
+ if (mask != 0)
+ pm_disable_device(mask);
+
+ /* Retrieve data about physical addresses from device tree. */
+ if ((err = win_cpu_from_dt()) != 0)
+ return (err);
+
+ /* Retrieve our ID: some windows facilities vary between SoC models */
+ soc_id(&dev, &rev);
+
+#ifdef SOC_MV_ARMADAXP
+ if ((err = decode_win_sdram_fixup()) != 0)
+ return(err);
+#endif
+
+#ifndef SOC_MV_FREY
+ if (!decode_win_cpu_valid() || !decode_win_usb_valid() ||
+ !decode_win_eth_valid() || !decode_win_idma_valid() ||
+ !decode_win_pcie_valid() || !decode_win_sata_valid() ||
+ !decode_win_xor_valid())
+ return (EINVAL);
+
+ decode_win_cpu_setup();
+#else
+ if (!decode_win_usb_valid() ||
+ !decode_win_eth_valid() || !decode_win_idma_valid() ||
+ !decode_win_pcie_valid() || !decode_win_sata_valid() ||
+ !decode_win_xor_valid())
+ return (EINVAL);
+#endif
+ if (MV_DUMP_WIN)
+ soc_dump_decode_win();
+
+ eth_port = 0;
+ usb_port = 0;
+ if ((err = fdt_win_setup()) != 0)
+ return (err);
+
+ return (0);
+}
+
+/**************************************************************************
+ * Decode windows registers accessors
+ **************************************************************************/
+#if !defined(SOC_MV_FREY)
+WIN_REG_IDX_RD(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_RD(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_RD(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_RD(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_WR(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_WR(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_WR(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_WR(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE)
+#endif
+
+WIN_REG_BASE_IDX_RD(win_usb, cr, MV_WIN_USB_CTRL)
+WIN_REG_BASE_IDX_RD(win_usb, br, MV_WIN_USB_BASE)
+WIN_REG_BASE_IDX_WR(win_usb, cr, MV_WIN_USB_CTRL)
+WIN_REG_BASE_IDX_WR(win_usb, br, MV_WIN_USB_BASE)
+
+WIN_REG_BASE_IDX_RD(win_eth, br, MV_WIN_ETH_BASE)
+WIN_REG_BASE_IDX_RD(win_eth, sz, MV_WIN_ETH_SIZE)
+WIN_REG_BASE_IDX_RD(win_eth, har, MV_WIN_ETH_REMAP)
+WIN_REG_BASE_IDX_WR(win_eth, br, MV_WIN_ETH_BASE)
+WIN_REG_BASE_IDX_WR(win_eth, sz, MV_WIN_ETH_SIZE)
+WIN_REG_BASE_IDX_WR(win_eth, har, MV_WIN_ETH_REMAP)
+
+WIN_REG_BASE_IDX_RD2(win_xor, br, MV_WIN_XOR_BASE)
+WIN_REG_BASE_IDX_RD2(win_xor, sz, MV_WIN_XOR_SIZE)
+WIN_REG_BASE_IDX_RD2(win_xor, har, MV_WIN_XOR_REMAP)
+WIN_REG_BASE_IDX_RD2(win_xor, ctrl, MV_WIN_XOR_CTRL)
+WIN_REG_BASE_IDX_WR2(win_xor, br, MV_WIN_XOR_BASE)
+WIN_REG_BASE_IDX_WR2(win_xor, sz, MV_WIN_XOR_SIZE)
+WIN_REG_BASE_IDX_WR2(win_xor, har, MV_WIN_XOR_REMAP)
+WIN_REG_BASE_IDX_WR2(win_xor, ctrl, MV_WIN_XOR_CTRL)
+
+WIN_REG_BASE_RD(win_eth, bare, 0x290)
+WIN_REG_BASE_RD(win_eth, epap, 0x294)
+WIN_REG_BASE_WR(win_eth, bare, 0x290)
+WIN_REG_BASE_WR(win_eth, epap, 0x294)
+
+WIN_REG_BASE_IDX_RD(win_pcie, cr, MV_WIN_PCIE_CTRL);
+WIN_REG_BASE_IDX_RD(win_pcie, br, MV_WIN_PCIE_BASE);
+WIN_REG_BASE_IDX_RD(win_pcie, remap, MV_WIN_PCIE_REMAP);
+WIN_REG_BASE_IDX_WR(win_pcie, cr, MV_WIN_PCIE_CTRL);
+WIN_REG_BASE_IDX_WR(win_pcie, br, MV_WIN_PCIE_BASE);
+WIN_REG_BASE_IDX_WR(win_pcie, remap, MV_WIN_PCIE_REMAP);
+WIN_REG_BASE_IDX_RD(pcie_bar, br, MV_PCIE_BAR_BASE);
+WIN_REG_BASE_IDX_WR(pcie_bar, br, MV_PCIE_BAR_BASE);
+WIN_REG_BASE_IDX_WR(pcie_bar, brh, MV_PCIE_BAR_BASE_H);
+WIN_REG_BASE_IDX_WR(pcie_bar, cr, MV_PCIE_BAR_CTRL);
+
+WIN_REG_BASE_IDX_RD(win_idma, br, MV_WIN_IDMA_BASE)
+WIN_REG_BASE_IDX_RD(win_idma, sz, MV_WIN_IDMA_SIZE)
+WIN_REG_BASE_IDX_RD(win_idma, har, MV_WIN_IDMA_REMAP)
+WIN_REG_BASE_IDX_RD(win_idma, cap, MV_WIN_IDMA_CAP)
+WIN_REG_BASE_IDX_WR(win_idma, br, MV_WIN_IDMA_BASE)
+WIN_REG_BASE_IDX_WR(win_idma, sz, MV_WIN_IDMA_SIZE)
+WIN_REG_BASE_IDX_WR(win_idma, har, MV_WIN_IDMA_REMAP)
+WIN_REG_BASE_IDX_WR(win_idma, cap, MV_WIN_IDMA_CAP)
+WIN_REG_BASE_RD(win_idma, bare, 0xa80)
+WIN_REG_BASE_WR(win_idma, bare, 0xa80)
+
+WIN_REG_BASE_IDX_RD(win_sata, cr, MV_WIN_SATA_CTRL);
+WIN_REG_BASE_IDX_RD(win_sata, br, MV_WIN_SATA_BASE);
+WIN_REG_BASE_IDX_WR(win_sata, cr, MV_WIN_SATA_CTRL);
+WIN_REG_BASE_IDX_WR(win_sata, br, MV_WIN_SATA_BASE);
+#ifndef SOC_MV_DOVE
+WIN_REG_IDX_RD(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE)
+WIN_REG_IDX_RD(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE)
+WIN_REG_IDX_WR(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE)
+WIN_REG_IDX_WR(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE)
+#else
+/*
+ * On 88F6781 (Dove) SoC DDR Controller is accessed through
+ * single MBUS <-> AXI bridge. In this case we provide emulated
+ * ddr_br_read() and ddr_sz_read() functions to keep compatibility
+ * with common decoding windows setup code.
+ */
+
+static inline uint32_t ddr_br_read(int i)
+{
+ uint32_t mmap;
+
+ /* Read Memory Address Map Register for CS i */
+ mmap = bus_space_read_4(fdtbus_bs_tag, MV_DDR_CADR_BASE + (i * 0x10), 0);
+
+ /* Return CS i base address */
+ return (mmap & 0xFF000000);
+}
+
+static inline uint32_t ddr_sz_read(int i)
+{
+ uint32_t mmap, size;
+
+ /* Read Memory Address Map Register for CS i */
+ mmap = bus_space_read_4(fdtbus_bs_tag, MV_DDR_CADR_BASE + (i * 0x10), 0);
+
+ /* Extract size of CS space in 64kB units */
+ size = (1 << ((mmap >> 16) & 0x0F));
+
+ /* Return CS size and enable/disable status */
+ return (((size - 1) << 16) | (mmap & 0x01));
+}
+#endif
+
+#if !defined(SOC_MV_FREY)
+/**************************************************************************
+ * Decode windows helper routines
+ **************************************************************************/
+void
+soc_dump_decode_win(void)
+{
+ uint32_t dev, rev;
+ int i;
+
+ soc_id(&dev, &rev);
+
+ for (i = 0; i < MV_WIN_CPU_MAX; i++) {
+ printf("CPU window#%d: c 0x%08x, b 0x%08x", i,
+ win_cpu_cr_read(i),
+ win_cpu_br_read(i));
+
+ if (win_cpu_can_remap(i))
+ printf(", rl 0x%08x, rh 0x%08x",
+ win_cpu_remap_l_read(i),
+ win_cpu_remap_h_read(i));
+
+ printf("\n");
+ }
+ printf("Internal regs base: 0x%08x\n",
+ bus_space_read_4(fdtbus_bs_tag, MV_INTREGS_BASE, 0));
+
+ for (i = 0; i < MV_WIN_DDR_MAX; i++)
+ printf("DDR CS#%d: b 0x%08x, s 0x%08x\n", i,
+ ddr_br_read(i), ddr_sz_read(i));
+}
+
+/**************************************************************************
+ * CPU windows routines
+ **************************************************************************/
+int
+win_cpu_can_remap(int i)
+{
+ uint32_t dev, rev;
+
+ soc_id(&dev, &rev);
+
+ /* Depending on the SoC certain windows have remap capability */
+ if ((dev == MV_DEV_88F5182 && i < 2) ||
+ (dev == MV_DEV_88F5281 && i < 4) ||
+ (dev == MV_DEV_88F6281 && i < 4) ||
+ (dev == MV_DEV_88F6282 && i < 4) ||
+ (dev == MV_DEV_88RC8180 && i < 2) ||
+ (dev == MV_DEV_88F6781 && i < 4) ||
+ (dev == MV_DEV_MV78100_Z0 && i < 8) ||
+ ((dev & MV_DEV_FAMILY_MASK) == MV_DEV_DISCOVERY && i < 8))
+ return (1);
+
+ return (0);
+}
+
+/* XXX This should check for overlapping remap fields too.. */
+int
+decode_win_overlap(int win, int win_no, const struct decode_win *wintab)
+{
+ const struct decode_win *tab;
+ int i;
+
+ tab = wintab;
+
+ for (i = 0; i < win_no; i++, tab++) {
+ if (i == win)
+ /* Skip self */
+ continue;
+
+ if ((tab->base + tab->size - 1) < (wintab + win)->base)
+ continue;
+
+ else if (((wintab + win)->base + (wintab + win)->size - 1) <
+ tab->base)
+ continue;
+ else
+ return (i);
+ }
+
+ return (-1);
+}
+
+static int
+decode_win_cpu_valid(void)
+{
+ int i, j, rv;
+ uint32_t b, e, s;
+
+ if (cpu_wins_no > MV_WIN_CPU_MAX) {
+ printf("CPU windows: too many entries: %d\n", cpu_wins_no);
+ return (0);
+ }
+
+ rv = 1;
+ for (i = 0; i < cpu_wins_no; i++) {
+
+ if (cpu_wins[i].target == 0) {
+ printf("CPU window#%d: DDR target window is not "
+ "supposed to be reprogrammed!\n", i);
+ rv = 0;
+ }
+
+ if (cpu_wins[i].remap != ~0 && win_cpu_can_remap(i) != 1) {
+ printf("CPU window#%d: not capable of remapping, but "
+ "val 0x%08x defined\n", i, cpu_wins[i].remap);
+ rv = 0;
+ }
+
+ s = cpu_wins[i].size;
+ b = cpu_wins[i].base;
+ e = b + s - 1;
+ if (s > (0xFFFFFFFF - b + 1)) {
+ /*
+ * XXX this boundary check should account for 64bit
+ * and remapping..
+ */
+ printf("CPU window#%d: no space for size 0x%08x at "
+ "0x%08x\n", i, s, b);
+ rv = 0;
+ continue;
+ }
+
+ if (b != (b & ~(s - 1))) {
+ printf("CPU window#%d: address 0x%08x is not aligned "
+ "to 0x%08x\n", i, b, s);
+ rv = 0;
+ continue;
+ }
+
+ j = decode_win_overlap(i, cpu_wins_no, &cpu_wins[0]);
+ if (j >= 0) {
+ printf("CPU window#%d: (0x%08x - 0x%08x) overlaps "
+ "with #%d (0x%08x - 0x%08x)\n", i, b, e, j,
+ cpu_wins[j].base,
+ cpu_wins[j].base + cpu_wins[j].size - 1);
+ rv = 0;
+ }
+ }
+
+ return (rv);
+}
+
+int
+decode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size,
+ vm_paddr_t remap)
+{
+ uint32_t br, cr;
+ int win, i;
+
+ if (remap == ~0) {
+ win = MV_WIN_CPU_MAX - 1;
+ i = -1;
+ } else {
+ win = 0;
+ i = 1;
+ }
+
+ while ((win >= 0) && (win < MV_WIN_CPU_MAX)) {
+ cr = win_cpu_cr_read(win);
+ if ((cr & MV_WIN_CPU_ENABLE_BIT) == 0)
+ break;
+ if ((cr & ((0xff << MV_WIN_CPU_ATTR_SHIFT) |
+ (0x1f << MV_WIN_CPU_TARGET_SHIFT))) ==
+ ((attr << MV_WIN_CPU_ATTR_SHIFT) |
+ (target << MV_WIN_CPU_TARGET_SHIFT)))
+ break;
+ win += i;
+ }
+ if ((win < 0) || (win >= MV_WIN_CPU_MAX) ||
+ ((remap != ~0) && (win_cpu_can_remap(win) == 0)))
+ return (-1);
+
+ br = base & 0xffff0000;
+ win_cpu_br_write(win, br);
+
+ if (win_cpu_can_remap(win)) {
+ if (remap != ~0) {
+ win_cpu_remap_l_write(win, remap & 0xffff0000);
+ win_cpu_remap_h_write(win, 0);
+ } else {
+ /*
+ * Remap function is not used for a given window
+ * (capable of remapping) - set remap field with the
+ * same value as base.
+ */
+ win_cpu_remap_l_write(win, base & 0xffff0000);
+ win_cpu_remap_h_write(win, 0);
+ }
+ }
+
+ cr = ((size - 1) & 0xffff0000) | (attr << MV_WIN_CPU_ATTR_SHIFT) |
+ (target << MV_WIN_CPU_TARGET_SHIFT) | MV_WIN_CPU_ENABLE_BIT;
+ win_cpu_cr_write(win, cr);
+
+ return (0);
+}
+
+static void
+decode_win_cpu_setup(void)
+{
+ int i;
+
+ /* Disable all CPU windows */
+ for (i = 0; i < MV_WIN_CPU_MAX; i++) {
+ win_cpu_cr_write(i, 0);
+ win_cpu_br_write(i, 0);
+ if (win_cpu_can_remap(i)) {
+ win_cpu_remap_l_write(i, 0);
+ win_cpu_remap_h_write(i, 0);
+ }
+ }
+
+ for (i = 0; i < cpu_wins_no; i++)
+ if (cpu_wins[i].target > 0)
+ decode_win_cpu_set(cpu_wins[i].target,
+ cpu_wins[i].attr, cpu_wins[i].base,
+ cpu_wins[i].size, cpu_wins[i].remap);
+
+}
+#endif
+
+#ifdef SOC_MV_ARMADAXP
+static int
+decode_win_sdram_fixup(void)
+{
+ struct mem_region mr[FDT_MEM_REGIONS];
+ uint8_t window_valid[MV_WIN_DDR_MAX];
+ int mr_cnt, memsize, err, i, j;
+ uint32_t valid_win_num = 0;
+
+ /* Grab physical memory regions information from device tree. */
+ err = fdt_get_mem_regions(mr, &mr_cnt, &memsize);
+ if (err != 0)
+ return (err);
+
+ for (i = 0; i < MV_WIN_DDR_MAX; i++)
+ window_valid[i] = 0;
+
+ /* Try to match entries from device tree with settings from u-boot */
+ for (i = 0; i < mr_cnt; i++) {
+ for (j = 0; j < MV_WIN_DDR_MAX; j++) {
+ if (ddr_is_active(j) &&
+ (ddr_base(j) == mr[i].mr_start) &&
+ (ddr_size(j) == mr[i].mr_size)) {
+ window_valid[j] = 1;
+ valid_win_num++;
+ }
+ }
+ }
+
+ if (mr_cnt != valid_win_num)
+ return (EINVAL);
+
+ /* Destroy windows without corresponding device tree entry */
+ for (j = 0; j < MV_WIN_DDR_MAX; j++) {
+ if (ddr_is_active(j) && (window_valid[j] != 1)) {
+ printf("Disabling SDRAM decoding window: %d\n", j);
+ ddr_disable(j);
+ }
+ }
+
+ return (0);
+}
+#endif
+/*
+ * Check if we're able to cover all active DDR banks.
+ */
+static int
+decode_win_can_cover_ddr(int max)
+{
+ int i, c;
+
+ c = 0;
+ for (i = 0; i < MV_WIN_DDR_MAX; i++)
+ if (ddr_is_active(i))
+ c++;
+
+ if (c > max) {
+ printf("Unable to cover all active DDR banks: "
+ "%d, available windows: %d\n", c, max);
+ return (0);
+ }
+
+ return (1);
+}
+
+/**************************************************************************
+ * DDR windows routines
+ **************************************************************************/
+int
+ddr_is_active(int i)
+{
+
+ if (ddr_sz_read(i) & 0x1)
+ return (1);
+
+ return (0);
+}
+
+void
+ddr_disable(int i)
+{
+
+ ddr_sz_write(i, 0);
+ ddr_br_write(i, 0);
+}
+
+uint32_t
+ddr_base(int i)
+{
+
+ return (ddr_br_read(i) & 0xff000000);
+}
+
+uint32_t
+ddr_size(int i)
+{
+
+ return ((ddr_sz_read(i) | 0x00ffffff) + 1);
+}
+
+uint32_t
+ddr_attr(int i)
+{
+ uint32_t dev, rev;
+
+ soc_id(&dev, &rev);
+ if (dev == MV_DEV_88RC8180)
+ return ((ddr_sz_read(i) & 0xf0) >> 4);
+ if (dev == MV_DEV_88F6781)
+ return (0);
+
+ return (i == 0 ? 0xe :
+ (i == 1 ? 0xd :
+ (i == 2 ? 0xb :
+ (i == 3 ? 0x7 : 0xff))));
+}
+
+uint32_t
+ddr_target(int i)
+{
+ uint32_t dev, rev;
+
+ soc_id(&dev, &rev);
+ if (dev == MV_DEV_88RC8180) {
+ i = (ddr_sz_read(i) & 0xf0) >> 4;
+ return (i == 0xe ? 0xc :
+ (i == 0xd ? 0xd :
+ (i == 0xb ? 0xe :
+ (i == 0x7 ? 0xf : 0xc))));
+ }
+
+ /*
+ * On SOCs other than 88RC8180 Mbus unit ID for
+ * DDR SDRAM controller is always 0x0.
+ */
+ return (0);
+}
+
+/**************************************************************************
+ * USB windows routines
+ **************************************************************************/
+static int
+decode_win_usb_valid(void)
+{
+
+ return (decode_win_can_cover_ddr(MV_WIN_USB_MAX));
+}
+
+static void
+decode_win_usb_dump(u_long base)
+{
+ int i;
+
+ if (pm_is_disabled(CPU_PM_CTRL_USB(usb_port - 1)))
+ return;
+
+ for (i = 0; i < MV_WIN_USB_MAX; i++)
+ printf("USB window#%d: c 0x%08x, b 0x%08x\n", i,
+ win_usb_cr_read(base, i), win_usb_br_read(base, i));
+}
+
+/*
+ * Set USB decode windows.
+ */
+static void
+decode_win_usb_setup(u_long base)
+{
+ uint32_t br, cr;
+ int i, j;
+
+
+ if (pm_is_disabled(CPU_PM_CTRL_USB(usb_port)))
+ return;
+
+ usb_port++;
+
+ for (i = 0; i < MV_WIN_USB_MAX; i++) {
+ win_usb_cr_write(base, i, 0);
+ win_usb_br_write(base, i, 0);
+ }
+
+ /* Only access to active DRAM banks is required */
+ for (i = 0; i < MV_WIN_DDR_MAX; i++) {
+ if (ddr_is_active(i)) {
+ br = ddr_base(i);
+ /*
+ * XXX for 6281 we should handle Mbus write
+ * burst limit field in the ctrl reg
+ */
+ cr = (((ddr_size(i) - 1) & 0xffff0000) |
+ (ddr_attr(i) << 8) |
+ (ddr_target(i) << 4) | 1);
+
+ /* Set the first free USB window */
+ for (j = 0; j < MV_WIN_USB_MAX; j++) {
+ if (win_usb_cr_read(base, j) & 0x1)
+ continue;
+
+ win_usb_br_write(base, j, br);
+ win_usb_cr_write(base, j, cr);
+ break;
+ }
+ }
+ }
+}
+
+/**************************************************************************
+ * ETH windows routines
+ **************************************************************************/
+
+static int
+win_eth_can_remap(int i)
+{
+
+ /* ETH encode windows 0-3 have remap capability */
+ if (i < 4)
+ return (1);
+
+ return (0);
+}
+
+static int
+eth_bare_read(uint32_t base, int i)
+{
+ uint32_t v;
+
+ v = win_eth_bare_read(base);
+ v &= (1 << i);
+
+ return (v >> i);
+}
+
+static void
+eth_bare_write(uint32_t base, int i, int val)
+{
+ uint32_t v;
+
+ v = win_eth_bare_read(base);
+ v &= ~(1 << i);
+ v |= (val << i);
+ win_eth_bare_write(base, v);
+}
+
+static void
+eth_epap_write(uint32_t base, int i, int val)
+{
+ uint32_t v;
+
+ v = win_eth_epap_read(base);
+ v &= ~(0x3 << (i * 2));
+ v |= (val << (i * 2));
+ win_eth_epap_write(base, v);
+}
+
+static void
+decode_win_eth_dump(u_long base)
+{
+ int i;
+
+ if (pm_is_disabled(CPU_PM_CTRL_GE(eth_port - 1)))
+ return;
+
+ for (i = 0; i < MV_WIN_ETH_MAX; i++) {
+ printf("ETH window#%d: b 0x%08x, s 0x%08x", i,
+ win_eth_br_read(base, i),
+ win_eth_sz_read(base, i));
+
+ if (win_eth_can_remap(i))
+ printf(", ha 0x%08x",
+ win_eth_har_read(base, i));
+
+ printf("\n");
+ }
+ printf("ETH windows: bare 0x%08x, epap 0x%08x\n",
+ win_eth_bare_read(base),
+ win_eth_epap_read(base));
+}
+
+#if defined(SOC_MV_LOKIPLUS)
+#define MV_WIN_ETH_DDR_TRGT(n) 0
+#else
+#define MV_WIN_ETH_DDR_TRGT(n) ddr_target(n)
+#endif
+
+static void
+decode_win_eth_setup(u_long base)
+{
+ uint32_t br, sz;
+ int i, j;
+
+ if (pm_is_disabled(CPU_PM_CTRL_GE(eth_port)))
+ return;
+
+ eth_port++;
+
+ /* Disable, clear and revoke protection for all ETH windows */
+ for (i = 0; i < MV_WIN_ETH_MAX; i++) {
+
+ eth_bare_write(base, i, 1);
+ eth_epap_write(base, i, 0);
+ win_eth_br_write(base, i, 0);
+ win_eth_sz_write(base, i, 0);
+ if (win_eth_can_remap(i))
+ win_eth_har_write(base, i, 0);
+ }
+
+ /* Only access to active DRAM banks is required */
+ for (i = 0; i < MV_WIN_DDR_MAX; i++)
+ if (ddr_is_active(i)) {
+
+ br = ddr_base(i) | (ddr_attr(i) << 8) | MV_WIN_ETH_DDR_TRGT(i);
+ sz = ((ddr_size(i) - 1) & 0xffff0000);
+
+ /* Set the first free ETH window */
+ for (j = 0; j < MV_WIN_ETH_MAX; j++) {
+ if (eth_bare_read(base, j) == 0)
+ continue;
+
+ win_eth_br_write(base, j, br);
+ win_eth_sz_write(base, j, sz);
+
+ /* XXX remapping ETH windows not supported */
+
+ /* Set protection RW */
+ eth_epap_write(base, j, 0x3);
+
+ /* Enable window */
+ eth_bare_write(base, j, 0);
+ break;
+ }
+ }
+}
+
+static int
+decode_win_eth_valid(void)
+{
+
+ return (decode_win_can_cover_ddr(MV_WIN_ETH_MAX));
+}
+
+/**************************************************************************
+ * PCIE windows routines
+ **************************************************************************/
+
+void
+decode_win_pcie_setup(u_long base)
+{
+ uint32_t size = 0, ddrbase = ~0;
+ uint32_t cr, br;
+ int i, j;
+
+ for (i = 0; i < MV_PCIE_BAR_MAX; i++) {
+ pcie_bar_br_write(base, i,
+ MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN);
+ if (i < 3)
+ pcie_bar_brh_write(base, i, 0);
+ if (i > 0)
+ pcie_bar_cr_write(base, i, 0);
+ }
+
+ for (i = 0; i < MV_WIN_PCIE_MAX; i++) {
+ win_pcie_cr_write(base, i, 0);
+ win_pcie_br_write(base, i, 0);
+ win_pcie_remap_write(base, i, 0);
+ }
+
+ /* On End-Point only set BAR size to 1MB regardless of DDR size */
+ if ((bus_space_read_4(fdtbus_bs_tag, base, MV_PCIE_CONTROL)
+ & MV_PCIE_ROOT_CMPLX) == 0) {
+ pcie_bar_cr_write(base, 1, 0xf0000 | 1);
+ return;
+ }
+
+ for (i = 0; i < MV_WIN_DDR_MAX; i++) {
+ if (ddr_is_active(i)) {
+ /* Map DDR to BAR 1 */
+ cr = (ddr_size(i) - 1) & 0xffff0000;
+ size += ddr_size(i) & 0xffff0000;
+ cr |= (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1;
+ br = ddr_base(i);
+ if (br < ddrbase)
+ ddrbase = br;
+
+ /* Use the first available PCIE window */
+ for (j = 0; j < MV_WIN_PCIE_MAX; j++) {
+ if (win_pcie_cr_read(base, j) != 0)
+ continue;
+
+ win_pcie_br_write(base, j, br);
+ win_pcie_cr_write(base, j, cr);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Upper 16 bits in BAR register is interpreted as BAR size
+ * (in 64 kB units) plus 64kB, so substract 0x10000
+ * form value passed to register to get correct value.
+ */
+ size -= 0x10000;
+ pcie_bar_cr_write(base, 1, size | 1);
+ pcie_bar_br_write(base, 1, ddrbase |
+ MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN);
+ pcie_bar_br_write(base, 0, fdt_immr_pa |
+ MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN);
+}
+
+static int
+decode_win_pcie_valid(void)
+{
+
+ return (decode_win_can_cover_ddr(MV_WIN_PCIE_MAX));
+}
+
+/**************************************************************************
+ * IDMA windows routines
+ **************************************************************************/
+#if defined(SOC_MV_ORION) || defined(SOC_MV_DISCOVERY)
+static int
+idma_bare_read(u_long base, int i)
+{
+ uint32_t v;
+
+ v = win_idma_bare_read(base);
+ v &= (1 << i);
+
+ return (v >> i);
+}
+
+static void
+idma_bare_write(u_long base, int i, int val)
+{
+ uint32_t v;
+
+ v = win_idma_bare_read(base);
+ v &= ~(1 << i);
+ v |= (val << i);
+ win_idma_bare_write(base, v);
+}
+
+/*
+ * Sets channel protection 'val' for window 'w' on channel 'c'
+ */
+static void
+idma_cap_write(u_long base, int c, int w, int val)
+{
+ uint32_t v;
+
+ v = win_idma_cap_read(base, c);
+ v &= ~(0x3 << (w * 2));
+ v |= (val << (w * 2));
+ win_idma_cap_write(base, c, v);
+}
+
+/*
+ * Set protection 'val' on all channels for window 'w'
+ */
+static void
+idma_set_prot(u_long base, int w, int val)
+{
+ int c;
+
+ for (c = 0; c < MV_IDMA_CHAN_MAX; c++)
+ idma_cap_write(base, c, w, val);
+}
+
+static int
+win_idma_can_remap(int i)
+{
+
+ /* IDMA decode windows 0-3 have remap capability */
+ if (i < 4)
+ return (1);
+
+ return (0);
+}
+
+void
+decode_win_idma_setup(u_long base)
+{
+ uint32_t br, sz;
+ int i, j;
+
+ if (pm_is_disabled(CPU_PM_CTRL_IDMA))
+ return;
+ /*
+ * Disable and clear all IDMA windows, revoke protection for all channels
+ */
+ for (i = 0; i < MV_WIN_IDMA_MAX; i++) {
+
+ idma_bare_write(base, i, 1);
+ win_idma_br_write(base, i, 0);
+ win_idma_sz_write(base, i, 0);
+ if (win_idma_can_remap(i) == 1)
+ win_idma_har_write(base, i, 0);
+ }
+ for (i = 0; i < MV_IDMA_CHAN_MAX; i++)
+ win_idma_cap_write(base, i, 0);
+
+ /*
+ * Set up access to all active DRAM banks
+ */
+ for (i = 0; i < MV_WIN_DDR_MAX; i++)
+ if (ddr_is_active(i)) {
+ br = ddr_base(i) | (ddr_attr(i) << 8) | ddr_target(i);
+ sz = ((ddr_size(i) - 1) & 0xffff0000);
+
+ /* Place DDR entries in non-remapped windows */
+ for (j = 0; j < MV_WIN_IDMA_MAX; j++)
+ if (win_idma_can_remap(j) != 1 &&
+ idma_bare_read(base, j) == 1) {
+
+ /* Configure window */
+ win_idma_br_write(base, j, br);
+ win_idma_sz_write(base, j, sz);
+
+ /* Set protection RW on all channels */
+ idma_set_prot(base, j, 0x3);
+
+ /* Enable window */
+ idma_bare_write(base, j, 0);
+ break;
+ }
+ }
+
+ /*
+ * Remaining targets -- from statically defined table
+ */
+ for (i = 0; i < idma_wins_no; i++)
+ if (idma_wins[i].target > 0) {
+ br = (idma_wins[i].base & 0xffff0000) |
+ (idma_wins[i].attr << 8) | idma_wins[i].target;
+ sz = ((idma_wins[i].size - 1) & 0xffff0000);
+
+ /* Set the first free IDMA window */
+ for (j = 0; j < MV_WIN_IDMA_MAX; j++) {
+ if (idma_bare_read(base, j) == 0)
+ continue;
+
+ /* Configure window */
+ win_idma_br_write(base, j, br);
+ win_idma_sz_write(base, j, sz);
+ if (win_idma_can_remap(j) &&
+ idma_wins[j].remap >= 0)
+ win_idma_har_write(base, j,
+ idma_wins[j].remap);
+
+ /* Set protection RW on all channels */
+ idma_set_prot(base, j, 0x3);
+
+ /* Enable window */
+ idma_bare_write(base, j, 0);
+ break;
+ }
+ }
+}
+
+int
+decode_win_idma_valid(void)
+{
+ const struct decode_win *wintab;
+ int c, i, j, rv;
+ uint32_t b, e, s;
+
+ if (idma_wins_no > MV_WIN_IDMA_MAX) {
+ printf("IDMA windows: too many entries: %d\n", idma_wins_no);
+ return (0);
+ }
+ for (i = 0, c = 0; i < MV_WIN_DDR_MAX; i++)
+ if (ddr_is_active(i))
+ c++;
+
+ if (idma_wins_no > (MV_WIN_IDMA_MAX - c)) {
+ printf("IDMA windows: too many entries: %d, available: %d\n",
+ idma_wins_no, MV_WIN_IDMA_MAX - c);
+ return (0);
+ }
+
+ wintab = idma_wins;
+ rv = 1;
+ for (i = 0; i < idma_wins_no; i++, wintab++) {
+
+ if (wintab->target == 0) {
+ printf("IDMA window#%d: DDR target window is not "
+ "supposed to be reprogrammed!\n", i);
+ rv = 0;
+ }
+
+ if (wintab->remap >= 0 && win_cpu_can_remap(i) != 1) {
+ printf("IDMA window#%d: not capable of remapping, but "
+ "val 0x%08x defined\n", i, wintab->remap);
+ rv = 0;
+ }
+
+ s = wintab->size;
+ b = wintab->base;
+ e = b + s - 1;
+ if (s > (0xFFFFFFFF - b + 1)) {
+ /* XXX this boundary check should account for 64bit and
+ * remapping.. */
+ printf("IDMA window#%d: no space for size 0x%08x at "
+ "0x%08x\n", i, s, b);
+ rv = 0;
+ continue;
+ }
+
+ j = decode_win_overlap(i, idma_wins_no, &idma_wins[0]);
+ if (j >= 0) {
+ printf("IDMA window#%d: (0x%08x - 0x%08x) overlaps "
+ "with #%d (0x%08x - 0x%08x)\n", i, b, e, j,
+ idma_wins[j].base,
+ idma_wins[j].base + idma_wins[j].size - 1);
+ rv = 0;
+ }
+ }
+
+ return (rv);
+}
+
+void
+decode_win_idma_dump(u_long base)
+{
+ int i;
+
+ if (pm_is_disabled(CPU_PM_CTRL_IDMA))
+ return;
+
+ for (i = 0; i < MV_WIN_IDMA_MAX; i++) {
+ printf("IDMA window#%d: b 0x%08x, s 0x%08x", i,
+ win_idma_br_read(base, i), win_idma_sz_read(base, i));
+
+ if (win_idma_can_remap(i))
+ printf(", ha 0x%08x", win_idma_har_read(base, i));
+
+ printf("\n");
+ }
+ for (i = 0; i < MV_IDMA_CHAN_MAX; i++)
+ printf("IDMA channel#%d: ap 0x%08x\n", i,
+ win_idma_cap_read(base, i));
+ printf("IDMA windows: bare 0x%08x\n", win_idma_bare_read(base));
+}
+#else
+
+/* Provide dummy functions to satisfy the build for SoCs not equipped with IDMA */
+int
+decode_win_idma_valid(void)
+{
+
+ return (1);
+}
+
+void
+decode_win_idma_setup(u_long base)
+{
+}
+
+void
+decode_win_idma_dump(u_long base)
+{
+}
+#endif
+
+/**************************************************************************
+ * XOR windows routines
+ **************************************************************************/
+#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
+static int
+xor_ctrl_read(u_long base, int i, int c, int e)
+{
+ uint32_t v;
+ v = win_xor_ctrl_read(base, c, e);
+ v &= (1 << i);
+
+ return (v >> i);
+}
+
+static void
+xor_ctrl_write(u_long base, int i, int c, int e, int val)
+{
+ uint32_t v;
+
+ v = win_xor_ctrl_read(base, c, e);
+ v &= ~(1 << i);
+ v |= (val << i);
+ win_xor_ctrl_write(base, c, e, v);
+}
+
+/*
+ * Set channel protection 'val' for window 'w' on channel 'c'
+ */
+static void
+xor_chan_write(u_long base, int c, int e, int w, int val)
+{
+ uint32_t v;
+
+ v = win_xor_ctrl_read(base, c, e);
+ v &= ~(0x3 << (w * 2 + 16));
+ v |= (val << (w * 2 + 16));
+ win_xor_ctrl_write(base, c, e, v);
+}
+
+/*
+ * Set protection 'val' on all channels for window 'w' on engine 'e'
+ */
+static void
+xor_set_prot(u_long base, int w, int e, int val)
+{
+ int c;
+
+ for (c = 0; c < MV_XOR_CHAN_MAX; c++)
+ xor_chan_write(base, c, e, w, val);
+}
+
+static int
+win_xor_can_remap(int i)
+{
+
+ /* XOR decode windows 0-3 have remap capability */
+ if (i < 4)
+ return (1);
+
+ return (0);
+}
+
+static int
+xor_max_eng(void)
+{
+ uint32_t dev, rev;
+
+ soc_id(&dev, &rev);
+ switch (dev) {
+ case MV_DEV_88F6281:
+ case MV_DEV_88F6282:
+ case MV_DEV_MV78130:
+ case MV_DEV_MV78160:
+ case MV_DEV_MV78230:
+ case MV_DEV_MV78260:
+ case MV_DEV_MV78460:
+ return (2);
+ case MV_DEV_MV78100:
+ case MV_DEV_MV78100_Z0:
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+static void
+xor_active_dram(u_long base, int c, int e, int *window)
+{
+ uint32_t br, sz;
+ int i, m, w;
+
+ /*
+ * Set up access to all active DRAM banks
+ */
+ m = xor_max_eng();
+ for (i = 0; i < m; i++)
+ if (ddr_is_active(i)) {
+ br = ddr_base(i) | (ddr_attr(i) << 8) |
+ ddr_target(i);
+ sz = ((ddr_size(i) - 1) & 0xffff0000);
+
+ /* Place DDR entries in non-remapped windows */
+ for (w = 0; w < MV_WIN_XOR_MAX; w++)
+ if (win_xor_can_remap(w) != 1 &&
+ (xor_ctrl_read(base, w, c, e) == 0) &&
+ w > *window) {
+ /* Configure window */
+ win_xor_br_write(base, w, e, br);
+ win_xor_sz_write(base, w, e, sz);
+
+ /* Set protection RW on all channels */
+ xor_set_prot(base, w, e, 0x3);
+
+ /* Enable window */
+ xor_ctrl_write(base, w, c, e, 1);
+ (*window)++;
+ break;
+ }
+ }
+}
+
+void
+decode_win_xor_setup(u_long base)
+{
+ uint32_t br, sz;
+ int i, j, z, e = 1, m, window;
+
+ if (pm_is_disabled(CPU_PM_CTRL_XOR))
+ return;
+
+ /*
+ * Disable and clear all XOR windows, revoke protection for all
+ * channels
+ */
+ m = xor_max_eng();
+ for (j = 0; j < m; j++, e--) {
+
+ /* Number of non-remaped windows */
+ window = MV_XOR_NON_REMAP - 1;
+
+ for (i = 0; i < MV_WIN_XOR_MAX; i++) {
+ win_xor_br_write(base, i, e, 0);
+ win_xor_sz_write(base, i, e, 0);
+ }
+
+ if (win_xor_can_remap(i) == 1)
+ win_xor_har_write(base, i, e, 0);
+
+ for (i = 0; i < MV_XOR_CHAN_MAX; i++) {
+ win_xor_ctrl_write(base, i, e, 0);
+ xor_active_dram(base, i, e, &window);
+ }
+
+ /*
+ * Remaining targets -- from a statically defined table
+ */
+ for (i = 0; i < xor_wins_no; i++)
+ if (xor_wins[i].target > 0) {
+ br = (xor_wins[i].base & 0xffff0000) |
+ (xor_wins[i].attr << 8) |
+ xor_wins[i].target;
+ sz = ((xor_wins[i].size - 1) & 0xffff0000);
+
+ /* Set the first free XOR window */
+ for (z = 0; z < MV_WIN_XOR_MAX; z++) {
+ if (xor_ctrl_read(base, z, 0, e) &&
+ xor_ctrl_read(base, z, 1, e))
+ continue;
+
+ /* Configure window */
+ win_xor_br_write(base, z, e, br);
+ win_xor_sz_write(base, z, e, sz);
+ if (win_xor_can_remap(z) &&
+ xor_wins[z].remap >= 0)
+ win_xor_har_write(base, z, e,
+ xor_wins[z].remap);
+
+ /* Set protection RW on all channels */
+ xor_set_prot(base, z, e, 0x3);
+
+ /* Enable window */
+ xor_ctrl_write(base, z, 0, e, 1);
+ xor_ctrl_write(base, z, 1, e, 1);
+ break;
+ }
+ }
+ }
+}
+
+int
+decode_win_xor_valid(void)
+{
+ const struct decode_win *wintab;
+ int c, i, j, rv;
+ uint32_t b, e, s;
+
+ if (xor_wins_no > MV_WIN_XOR_MAX) {
+ printf("XOR windows: too many entries: %d\n", xor_wins_no);
+ return (0);
+ }
+ for (i = 0, c = 0; i < MV_WIN_DDR_MAX; i++)
+ if (ddr_is_active(i))
+ c++;
+
+ if (xor_wins_no > (MV_WIN_XOR_MAX - c)) {
+ printf("XOR windows: too many entries: %d, available: %d\n",
+ xor_wins_no, MV_WIN_IDMA_MAX - c);
+ return (0);
+ }
+
+ wintab = xor_wins;
+ rv = 1;
+ for (i = 0; i < xor_wins_no; i++, wintab++) {
+
+ if (wintab->target == 0) {
+ printf("XOR window#%d: DDR target window is not "
+ "supposed to be reprogrammed!\n", i);
+ rv = 0;
+ }
+
+ if (wintab->remap >= 0 && win_cpu_can_remap(i) != 1) {
+ printf("XOR window#%d: not capable of remapping, but "
+ "val 0x%08x defined\n", i, wintab->remap);
+ rv = 0;
+ }
+
+ s = wintab->size;
+ b = wintab->base;
+ e = b + s - 1;
+ if (s > (0xFFFFFFFF - b + 1)) {
+ /*
+ * XXX this boundary check should account for 64bit
+ * and remapping..
+ */
+ printf("XOR window#%d: no space for size 0x%08x at "
+ "0x%08x\n", i, s, b);
+ rv = 0;
+ continue;
+ }
+
+ j = decode_win_overlap(i, xor_wins_no, &xor_wins[0]);
+ if (j >= 0) {
+ printf("XOR window#%d: (0x%08x - 0x%08x) overlaps "
+ "with #%d (0x%08x - 0x%08x)\n", i, b, e, j,
+ xor_wins[j].base,
+ xor_wins[j].base + xor_wins[j].size - 1);
+ rv = 0;
+ }
+ }
+
+ return (rv);
+}
+
+void
+decode_win_xor_dump(u_long base)
+{
+ int i, j;
+ int e = 1;
+
+ if (pm_is_disabled(CPU_PM_CTRL_XOR))
+ return;
+
+ for (j = 0; j < xor_max_eng(); j++, e--) {
+ for (i = 0; i < MV_WIN_XOR_MAX; i++) {
+ printf("XOR window#%d: b 0x%08x, s 0x%08x", i,
+ win_xor_br_read(base, i, e), win_xor_sz_read(base, i, e));
+
+ if (win_xor_can_remap(i))
+ printf(", ha 0x%08x", win_xor_har_read(base, i, e));
+
+ printf("\n");
+ }
+ for (i = 0; i < MV_XOR_CHAN_MAX; i++)
+ printf("XOR control#%d: 0x%08x\n", i,
+ win_xor_ctrl_read(base, i, e));
+ }
+}
+
+#else
+/* Provide dummy functions to satisfy the build for SoCs not equipped with XOR */
+static int
+decode_win_xor_valid(void)
+{
+
+ return (1);
+}
+
+static void
+decode_win_xor_setup(u_long base)
+{
+}
+
+static void
+decode_win_xor_dump(u_long base)
+{
+}
+#endif
+
+/**************************************************************************
+ * SATA windows routines
+ **************************************************************************/
+static void
+decode_win_sata_setup(u_long base)
+{
+ uint32_t cr, br;
+ int i, j;
+
+ if (pm_is_disabled(CPU_PM_CTRL_SATA))
+ return;
+
+ for (i = 0; i < MV_WIN_SATA_MAX; i++) {
+ win_sata_cr_write(base, i, 0);
+ win_sata_br_write(base, i, 0);
+ }
+
+ for (i = 0; i < MV_WIN_DDR_MAX; i++)
+ if (ddr_is_active(i)) {
+ cr = ((ddr_size(i) - 1) & 0xffff0000) |
+ (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1;
+ br = ddr_base(i);
+
+ /* Use the first available SATA window */
+ for (j = 0; j < MV_WIN_SATA_MAX; j++) {
+ if ((win_sata_cr_read(base, j) & 1) != 0)
+ continue;
+
+ win_sata_br_write(base, j, br);
+ win_sata_cr_write(base, j, cr);
+ break;
+ }
+ }
+}
+
+static int
+decode_win_sata_valid(void)
+{
+ uint32_t dev, rev;
+
+ soc_id(&dev, &rev);
+ if (dev == MV_DEV_88F5281)
+ return (1);
+
+ return (decode_win_can_cover_ddr(MV_WIN_SATA_MAX));
+}
+
+/**************************************************************************
+ * FDT parsing routines.
+ **************************************************************************/
+
+static int
+fdt_get_ranges(const char *nodename, void *buf, int size, int *tuples,
+ int *tuplesize)
+{
+ phandle_t node;
+ pcell_t addr_cells, par_addr_cells, size_cells;
+ int len, tuple_size, tuples_count;
+
+ node = OF_finddevice(nodename);
+ if (node == -1)
+ return (EINVAL);
+
+ if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
+ return (ENXIO);
+
+ par_addr_cells = fdt_parent_addr_cells(node);
+ if (par_addr_cells > 2)
+ return (ERANGE);
+
+ tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells +
+ size_cells);
+
+ /* Note the OF_getprop_alloc() cannot be used at this early stage. */
+ len = OF_getprop(node, "ranges", buf, size);
+
+ /*
+ * XXX this does not handle the empty 'ranges;' case, which is
+ * legitimate and should be allowed.
+ */
+ tuples_count = len / tuple_size;
+ if (tuples_count <= 0)
+ return (ERANGE);
+
+ if (fdt_ranges_verify(buf, tuples_count, par_addr_cells,
+ addr_cells, size_cells) != 0)
+ return (ERANGE);
+
+ *tuples = tuples_count;
+ *tuplesize = tuple_size;
+ return (0);
+}
+
+static int
+win_cpu_from_dt(void)
+{
+ pcell_t ranges[48];
+ phandle_t node;
+ int i, entry_size, err, t, tuple_size, tuples;
+ u_long sram_base, sram_size;
+
+ t = 0;
+ /* Retrieve 'ranges' property of '/localbus' node. */
+ if ((err = fdt_get_ranges("/localbus", ranges, sizeof(ranges),
+ &tuples, &tuple_size)) == 0) {
+ /*
+ * Fill CPU decode windows table.
+ */
+ bzero((void *)&cpu_win_tbl, sizeof(cpu_win_tbl));
+
+ entry_size = tuple_size / sizeof(pcell_t);
+ cpu_wins_no = tuples;
+
+ for (i = 0, t = 0; t < tuples; i += entry_size, t++) {
+ cpu_win_tbl[t].target = 1;
+ cpu_win_tbl[t].attr = fdt32_to_cpu(ranges[i + 1]);
+ cpu_win_tbl[t].base = fdt32_to_cpu(ranges[i + 2]);
+ cpu_win_tbl[t].size = fdt32_to_cpu(ranges[i + 3]);
+ cpu_win_tbl[t].remap = ~0;
+ debugf("target = 0x%0x attr = 0x%0x base = 0x%0x "
+ "size = 0x%0x remap = 0x%0x\n",
+ cpu_win_tbl[t].target,
+ cpu_win_tbl[t].attr, cpu_win_tbl[t].base,
+ cpu_win_tbl[t].size, cpu_win_tbl[t].remap);
+ }
+ }
+
+ /*
+ * Retrieve CESA SRAM data.
+ */
+ if ((node = OF_finddevice("sram")) != -1)
+ if (fdt_is_compatible(node, "mrvl,cesa-sram"))
+ goto moveon;
+
+ if ((node = OF_finddevice("/")) == 0)
+ return (ENXIO);
+
+ if ((node = fdt_find_compatible(node, "mrvl,cesa-sram", 0)) == 0)
+ /* SRAM block is not always present. */
+ return (0);
+moveon:
+ sram_base = sram_size = 0;
+ if (fdt_regsize(node, &sram_base, &sram_size) != 0)
+ return (EINVAL);
+
+ cpu_win_tbl[t].target = MV_WIN_CESA_TARGET;
+ cpu_win_tbl[t].attr = MV_WIN_CESA_ATTR(1);
+ cpu_win_tbl[t].base = sram_base;
+ cpu_win_tbl[t].size = sram_size;
+ cpu_win_tbl[t].remap = ~0;
+ cpu_wins_no++;
+ debugf("sram: base = 0x%0lx size = 0x%0lx\n", sram_base, sram_size);
+
+ return (0);
+}
+
+static int
+fdt_win_setup(void)
+{
+ phandle_t node, child;
+ struct soc_node_spec *soc_node;
+ u_long size, base;
+ int err, i;
+
+ node = OF_finddevice("/");
+ if (node == -1)
+ panic("fdt_win_setup: no root node");
+
+ /*
+ * Traverse through all children of root and simple-bus nodes.
+ * For each found device retrieve decode windows data (if applicable).
+ */
+ child = OF_child(node);
+ while (child != 0) {
+ for (i = 0; soc_nodes[i].compat != NULL; i++) {
+
+ soc_node = &soc_nodes[i];
+
+ if (!fdt_is_compatible(child, soc_node->compat))
+ continue;
+
+ err = fdt_regsize(child, &base, &size);
+ if (err != 0)
+ return (err);
+
+ base = (base & 0x000fffff) | fdt_immr_va;
+ if (soc_node->decode_handler != NULL)
+ soc_node->decode_handler(base);
+ else
+ return (ENXIO);
+
+ if (MV_DUMP_WIN && (soc_node->dump_handler != NULL))
+ soc_node->dump_handler(base);
+ }
+
+ /*
+ * Once done with root-level children let's move down to
+ * simple-bus and its children.
+ */
+ child = OF_peer(child);
+ if ((child == 0) && (node == OF_finddevice("/"))) {
+ node = fdt_find_compatible(node, "simple-bus", 1);
+ if (node == 0)
+ return (ENXIO);
+ child = OF_child(node);
+ }
+ }
+
+ return (0);
+}
+
+static void
+fdt_fixup_busfreq(phandle_t root)
+{
+ phandle_t sb;
+ pcell_t freq;
+
+ freq = cpu_to_fdt32(get_tclk());
+
+ /*
+ * Fix bus speed in cpu node
+ */
+ if ((sb = OF_finddevice("cpu")) != 0)
+ if (fdt_is_compatible_strict(sb, "ARM,88VS584"))
+ OF_setprop(sb, "bus-frequency", (void *)&freq,
+ sizeof(freq));
+
+ /*
+ * This fixup sets the simple-bus bus-frequency property.
+ */
+ if ((sb = fdt_find_compatible(root, "simple-bus", 1)) != 0)
+ OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq));
+}
+
+static void
+fdt_fixup_ranges(phandle_t root)
+{
+ phandle_t node;
+ pcell_t par_addr_cells, addr_cells, size_cells;
+ pcell_t ranges[3], reg[2], *rangesptr;
+ int len, tuple_size, tuples_count;
+ uint32_t base;
+
+ /* Fix-up SoC ranges according to real fdt_immr_pa */
+ if ((node = fdt_find_compatible(root, "simple-bus", 1)) != 0) {
+ if (fdt_addrsize_cells(node, &addr_cells, &size_cells) == 0 &&
+ (par_addr_cells = fdt_parent_addr_cells(node) <= 2)) {
+ tuple_size = sizeof(pcell_t) * (par_addr_cells +
+ addr_cells + size_cells);
+ len = OF_getprop(node, "ranges", ranges,
+ sizeof(ranges));
+ tuples_count = len / tuple_size;
+ /* Unexpected settings are not supported */
+ if (tuples_count != 1)
+ goto fixup_failed;
+
+ rangesptr = &ranges[0];
+ rangesptr += par_addr_cells;
+ base = fdt_data_get((void *)rangesptr, addr_cells);
+ *rangesptr = cpu_to_fdt32(fdt_immr_pa);
+ if (OF_setprop(node, "ranges", (void *)&ranges[0],
+ sizeof(ranges)) < 0)
+ goto fixup_failed;
+ }
+ }
+
+ /* Fix-up PCIe reg according to real PCIe registers' PA */
+ if ((node = fdt_find_compatible(root, "mrvl,pcie", 1)) != 0) {
+ if (fdt_addrsize_cells(OF_parent(node), &par_addr_cells,
+ &size_cells) == 0) {
+ tuple_size = sizeof(pcell_t) * (par_addr_cells +
+ size_cells);
+ len = OF_getprop(node, "reg", reg, sizeof(reg));
+ tuples_count = len / tuple_size;
+ /* Unexpected settings are not supported */
+ if (tuples_count != 1)
+ goto fixup_failed;
+
+ base = fdt_data_get((void *)®[0], par_addr_cells);
+ base &= ~0xFF000000;
+ base |= fdt_immr_pa;
+ reg[0] = cpu_to_fdt32(base);
+ if (OF_setprop(node, "reg", (void *)®[0],
+ sizeof(reg)) < 0)
+ goto fixup_failed;
+ }
+ }
+ /* Fix-up succeeded. May return and continue */
+ return;
+
+fixup_failed:
+ while (1) {
+ /*
+ * In case of any error while fixing ranges just hang.
+ * 1. No message can be displayed yet since console
+ * is not initialized.
+ * 2. Going further will cause failure on bus_space_map()
+ * relying on the wrong ranges or data abort when
+ * accessing PCIe registers.
+ */
+ }
+}
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { "mrvl,DB-88F6281", &fdt_fixup_busfreq },
+ { "mrvl,DB-78460", &fdt_fixup_busfreq },
+ { "mrvl,DB-78460", &fdt_fixup_ranges },
+ { NULL, NULL }
+};
+
+static int
+fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (!fdt_is_compatible(node, "mrvl,pic") &&
+ !fdt_is_compatible(node, "mrvl,mpic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_pic_decode_ic,
+ NULL
+};
+
+uint64_t
+get_sar_value(void)
+{
+ uint32_t sar_low, sar_high;
+
+#if defined(SOC_MV_ARMADAXP)
+ sar_high = bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE,
+ SAMPLE_AT_RESET_HI);
+ sar_low = bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE,
+ SAMPLE_AT_RESET_LO);
+#else
+ /*
+ * TODO: Add getting proper values for other SoC configurations
+ */
+ sar_high = 0;
+ sar_low = 0;
+#endif
+
+ return (((uint64_t)sar_high << 32) | sar_low);
+}
Property changes on: trunk/sys/arm/mv/mv_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/mv_localbus.c
===================================================================
--- trunk/sys/arm/mv/mv_localbus.c (rev 0)
+++ trunk/sys/arm/mv/mv_localbus.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,494 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/mv_localbus.c 266386 2014-05-18 00:32:35Z ian $");
+
+#include "opt_platform.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+
+#include <machine/devmap.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include "dev/fdt/fdt_common.h"
+#include "ofw_bus_if.h"
+
+#include <arm/mv/mvwin.h>
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#define MV_LOCALBUS_MAX_BANKS 8
+#define MV_LOCALBUS_MAX_BANK_CELLS 4
+
+static MALLOC_DEFINE(M_LOCALBUS, "localbus", "localbus devices information");
+
+struct localbus_bank {
+ vm_offset_t va; /* VA of the bank */
+ vm_paddr_t pa; /* physical address of the bank */
+ vm_size_t size; /* bank size */
+ uint8_t mapped; /* device memory has mapping */
+};
+
+struct localbus_softc {
+ device_t sc_dev;
+ bus_space_handle_t sc_bsh;
+ bus_space_tag_t sc_bst;
+ int sc_rid;
+
+ struct localbus_bank *sc_banks;
+};
+
+struct localbus_devinfo {
+ struct ofw_bus_devinfo di_ofw;
+ struct resource_list di_res;
+ int di_bank;
+};
+
+struct localbus_va_entry {
+ int8_t bank;
+ vm_offset_t va;
+ vm_size_t size;
+};
+
+/*
+ * Prototypes.
+ */
+static int localbus_probe(device_t);
+static int localbus_attach(device_t);
+static int localbus_print_child(device_t, device_t);
+
+static struct resource *localbus_alloc_resource(device_t, device_t, int,
+ int *, u_long, u_long, u_long, u_int);
+static struct resource_list *localbus_get_resource_list(device_t, device_t);
+
+static ofw_bus_get_devinfo_t localbus_get_devinfo;
+
+/*
+ * Bus interface definition.
+ */
+static device_method_t localbus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, localbus_probe),
+ DEVMETHOD(device_attach, localbus_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, localbus_print_child),
+ DEVMETHOD(bus_alloc_resource, localbus_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_get_resource_list, localbus_get_resource_list),
+
+ /* OFW bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, localbus_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ { 0, 0 }
+};
+
+static driver_t localbus_driver = {
+ "localbus",
+ localbus_methods,
+ sizeof(struct localbus_softc)
+};
+
+const struct localbus_va_entry localbus_virtmap[] = {
+ { 0, MV_DEV_BOOT_BASE, MV_DEV_BOOT_SIZE },
+ { 1, MV_DEV_CS0_BASE, MV_DEV_CS0_SIZE },
+ { 2, MV_DEV_CS1_BASE, MV_DEV_CS1_SIZE },
+ { 3, MV_DEV_CS2_BASE, MV_DEV_CS2_SIZE },
+
+ { -1, 0, 0 }
+};
+
+static struct localbus_bank localbus_banks[MV_LOCALBUS_MAX_BANKS];
+
+devclass_t localbus_devclass;
+
+DRIVER_MODULE(localbus, ofwbus, localbus_driver, localbus_devclass, 0, 0);
+
+static int
+fdt_localbus_reg_decode(phandle_t node, struct localbus_softc *sc,
+ struct localbus_devinfo *di)
+{
+ u_long start, end, count;
+ pcell_t *reg, *regptr;
+ pcell_t addr_cells, size_cells;
+ int tuple_size, tuples;
+ int i, rv, bank;
+
+ if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
+ return (ENXIO);
+
+ tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
+ tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)®);
+ debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
+ debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
+ if (tuples <= 0)
+ /* No 'reg' property in this node. */
+ return (0);
+
+ regptr = reg;
+ for (i = 0; i < tuples; i++) {
+
+ bank = fdt_data_get((void *)regptr, 1);
+
+ if (bank >= MV_LOCALBUS_MAX_BANKS) {
+ device_printf(sc->sc_dev, "bank number [%d] out of "
+ "range\n", bank);
+ continue;
+ }
+
+ /*
+ * If device doesn't have virtual to physical mapping don't add
+ * resources
+ */
+ if (!(sc->sc_banks[bank].mapped)) {
+ device_printf(sc->sc_dev, "device [%d]: missing memory "
+ "mapping\n", bank);
+ continue;
+ }
+
+ di->di_bank = bank;
+ regptr += 1;
+
+ /* Get address/size. */
+ rv = fdt_data_to_res(regptr, addr_cells - 1, size_cells, &start,
+ &count);
+ if (rv != 0) {
+ resource_list_free(&di->di_res);
+ goto out;
+ }
+
+ /* Check if enough amount of memory is mapped */
+ if (sc->sc_banks[bank].size < count) {
+ device_printf(sc->sc_dev, "device [%d]: not enough "
+ "memory reserved\n", bank);
+ continue;
+ }
+
+ regptr += addr_cells - 1 + size_cells;
+
+ /* Calculate address range relative to VA base. */
+ start = sc->sc_banks[bank].va + start;
+ end = start + count - 1;
+
+ debugf("reg addr bank = %d, start = %lx, end = %lx, "
+ "count = %lx\n", bank, start, end, count);
+
+ /* Use bank (CS) cell as rid. */
+ resource_list_add(&di->di_res, SYS_RES_MEMORY, di->di_bank,
+ start, end, count);
+ }
+ rv = 0;
+out:
+ free(reg, M_OFWPROP);
+ return (rv);
+}
+
+static int
+localbus_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible_strict(dev, "mrvl,lbc"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell device bus");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+localbus_attach(device_t dev)
+{
+ device_t dev_child;
+ struct localbus_softc *sc;
+ struct localbus_devinfo *di;
+ phandle_t dt_node, dt_child;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_banks = localbus_banks;
+
+ /*
+ * Walk localbus and add direct subordinates as our children.
+ */
+ dt_node = ofw_bus_get_node(dev);
+ for (dt_child = OF_child(dt_node); dt_child != 0;
+ dt_child = OF_peer(dt_child)) {
+
+ /* Check and process 'status' property. */
+ if (!(fdt_is_enabled(dt_child)))
+ continue;
+
+ if (!(fdt_pm_is_enabled(dt_child)))
+ continue;
+
+ di = malloc(sizeof(*di), M_LOCALBUS, M_WAITOK | M_ZERO);
+ if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) {
+ free(di, M_LOCALBUS);
+ device_printf(dev, "could not set up devinfo\n");
+ continue;
+ }
+
+ resource_list_init(&di->di_res);
+ if (fdt_localbus_reg_decode(dt_child, sc, di)) {
+ device_printf(dev, "could not process 'reg' "
+ "property\n");
+ ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+ free(di, M_LOCALBUS);
+ continue;
+ }
+
+ /* Add newbus device for this FDT node */
+ dev_child = device_add_child(dev, NULL, -1);
+ if (dev_child == NULL) {
+ device_printf(dev, "could not add child: %s\n",
+ di->di_ofw.obd_name);
+ resource_list_free(&di->di_res);
+ ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+ free(di, M_LOCALBUS);
+ continue;
+ }
+#ifdef DEBUG
+ device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name);
+#endif
+ device_set_ivars(dev_child, di);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+localbus_print_child(device_t dev, device_t child)
+{
+ struct localbus_devinfo *di;
+ struct resource_list *rl;
+ int rv;
+
+ di = device_get_ivars(child);
+ rl = &di->di_res;
+
+ rv = 0;
+ rv += bus_print_child_header(dev, child);
+ rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+ rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ rv += bus_print_child_footer(dev, child);
+
+ return (rv);
+}
+
+static struct resource *
+localbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct localbus_devinfo *di;
+ struct resource_list_entry *rle;
+
+ /*
+ * Request for the default allocation with a given rid: use resource
+ * list stored in the local device info.
+ */
+ if ((start == 0UL) && (end == ~0UL)) {
+ if ((di = device_get_ivars(child)) == NULL)
+ return (NULL);
+
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ rid = &di->di_bank;
+ rle = resource_list_find(&di->di_res, type, *rid);
+ if (rle == NULL) {
+ device_printf(bus, "no default resources for "
+ "rid = %d, type = %d\n", *rid, type);
+ return (NULL);
+ }
+ start = rle->start;
+ end = rle->end;
+ count = rle->count;
+ }
+
+ return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
+}
+
+
+static struct resource_list *
+localbus_get_resource_list(device_t bus, device_t child)
+{
+ struct localbus_devinfo *di;
+
+ di = device_get_ivars(child);
+ return (&di->di_res);
+}
+
+static const struct ofw_bus_devinfo *
+localbus_get_devinfo(device_t bus, device_t child)
+{
+ struct localbus_devinfo *di;
+
+ di = device_get_ivars(child);
+ return (&di->di_ofw);
+}
+
+int
+fdt_localbus_devmap(phandle_t dt_node, struct arm_devmap_entry *fdt_devmap,
+ int banks_max_num, int *banks_added)
+{
+ pcell_t ranges[MV_LOCALBUS_MAX_BANKS * MV_LOCALBUS_MAX_BANK_CELLS];
+ pcell_t *rangesptr;
+ uint32_t tuple_size, bank;
+ vm_paddr_t offset;
+ vm_size_t size;
+ int dev_num, addr_cells, size_cells, par_addr_cells, va_index, i, j, k;
+
+ if ((fdt_addrsize_cells(dt_node, &addr_cells, &size_cells)) != 0)
+ return (EINVAL);
+
+ par_addr_cells = fdt_parent_addr_cells(dt_node);
+ if (par_addr_cells > 2) {
+ /*
+ * Localbus devmap initialization error: unsupported parent
+ * #addr-cells
+ */
+ return (ERANGE);
+ }
+
+ tuple_size = (addr_cells + par_addr_cells + size_cells);
+ if (tuple_size > MV_LOCALBUS_MAX_BANK_CELLS)
+ return (ERANGE);
+
+ tuple_size *= sizeof(pcell_t);
+
+ dev_num = OF_getprop(dt_node, "ranges", ranges, sizeof(ranges));
+ if (dev_num <= 0)
+ return (EINVAL);
+
+ /* Calculate number of devices attached to bus */
+ dev_num = dev_num / tuple_size;
+
+ /*
+ * If number of ranges > max number of localbus devices,
+ * additional entries will not be processed
+ */
+ dev_num = MIN(dev_num, banks_max_num);
+
+ rangesptr = &ranges[0];
+ j = 0;
+
+ /* Process data from FDT */
+ for (i = 0; i < dev_num; i++) {
+
+ /* First field is bank number */
+ bank = fdt_data_get((void *)rangesptr, 1);
+ rangesptr += 1;
+
+ if (bank < 0 || bank > MV_LOCALBUS_MAX_BANKS) {
+ /* Bank out of range */
+ rangesptr += ((addr_cells - 1) + par_addr_cells +
+ size_cells);
+ continue;
+ }
+
+ /* Find virtmap entry for this bank */
+ va_index = -1;
+ for (k = 0; localbus_virtmap[k].bank >= 0; k++) {
+ if (localbus_virtmap[k].bank == bank) {
+ va_index = k;
+ break;
+ }
+ }
+
+ /* Check if virtmap entry was found */
+ if (va_index == -1) {
+ rangesptr += ((addr_cells - 1) + par_addr_cells +
+ size_cells);
+ continue;
+ }
+
+ /* Remaining child's address fields are unused */
+ rangesptr += (addr_cells - 1);
+
+ /* Parent address offset */
+ offset = fdt_data_get((void *)rangesptr, par_addr_cells);
+ rangesptr += par_addr_cells;
+
+ /* Last field is size */
+ size = fdt_data_get((void *)rangesptr, size_cells);
+ rangesptr += size_cells;
+
+ if (size > localbus_virtmap[va_index].size) {
+ /* Not enough space reserved in virtual memory map */
+ continue;
+ }
+
+ fdt_devmap[j].pd_va = localbus_virtmap[va_index].va;
+ fdt_devmap[j].pd_pa = offset;
+ fdt_devmap[j].pd_size = size;
+ fdt_devmap[j].pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ fdt_devmap[j].pd_cache = PTE_DEVICE;
+
+ /* Copy data to structure used by localbus driver */
+ localbus_banks[bank].va = fdt_devmap[j].pd_va;
+ localbus_banks[bank].pa = fdt_devmap[j].pd_pa;
+ localbus_banks[bank].size = fdt_devmap[j].pd_size;
+ localbus_banks[bank].mapped = 1;
+
+ j++;
+ }
+
+ *banks_added = j;
+ return (0);
+}
Property changes on: trunk/sys/arm/mv/mv_localbus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/mv_machdep.c
===================================================================
--- trunk/sys/arm/mv/mv_machdep.c (rev 0)
+++ trunk/sys/arm/mv/mv_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,486 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/at91/kb920x_machdep.c, rev 45
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/mv_machdep.c 266386 2014-05-18 00:32:35Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/fdt.h>
+#include <machine/machdep.h>
+
+#include <arm/mv/mvreg.h> /* XXX */
+#include <arm/mv/mvvar.h> /* XXX eventually this should be eliminated */
+#include <arm/mv/mvwin.h>
+
+#include <dev/fdt/fdt_common.h>
+
+static int platform_mpp_init(void);
+#if defined(SOC_MV_ARMADAXP)
+void armadaxp_init_coher_fabric(void);
+void armadaxp_l2_init(void);
+#endif
+
+#define MPP_PIN_MAX 68
+#define MPP_PIN_CELLS 2
+#define MPP_PINS_PER_REG 8
+#define MPP_SEL(pin,func) (((func) & 0xf) << \
+ (((pin) % MPP_PINS_PER_REG) * 4))
+
+static int
+platform_mpp_init(void)
+{
+ pcell_t pinmap[MPP_PIN_MAX * MPP_PIN_CELLS];
+ int mpp[MPP_PIN_MAX];
+ uint32_t ctrl_val, ctrl_offset;
+ pcell_t reg[4];
+ u_long start, size;
+ phandle_t node;
+ pcell_t pin_cells, *pinmap_ptr, pin_count;
+ ssize_t len;
+ int par_addr_cells, par_size_cells;
+ int tuple_size, tuples, rv, pins, i, j;
+ int mpp_pin, mpp_function;
+
+ /*
+ * Try to access the MPP node directly i.e. through /aliases/mpp.
+ */
+ if ((node = OF_finddevice("mpp")) != -1)
+ if (fdt_is_compatible(node, "mrvl,mpp"))
+ goto moveon;
+ /*
+ * Find the node the long way.
+ */
+ if ((node = OF_finddevice("/")) == -1)
+ return (ENXIO);
+
+ if ((node = fdt_find_compatible(node, "simple-bus", 0)) == 0)
+ return (ENXIO);
+
+ if ((node = fdt_find_compatible(node, "mrvl,mpp", 0)) == 0)
+ /*
+ * No MPP node. Fall back to how MPP got set by the
+ * first-stage loader and try to continue booting.
+ */
+ return (0);
+moveon:
+ /*
+ * Process 'reg' prop.
+ */
+ if ((rv = fdt_addrsize_cells(OF_parent(node), &par_addr_cells,
+ &par_size_cells)) != 0)
+ return(ENXIO);
+
+ tuple_size = sizeof(pcell_t) * (par_addr_cells + par_size_cells);
+ len = OF_getprop(node, "reg", reg, sizeof(reg));
+ tuples = len / tuple_size;
+ if (tuple_size <= 0)
+ return (EINVAL);
+
+ /*
+ * Get address/size. XXX we assume only the first 'reg' tuple is used.
+ */
+ rv = fdt_data_to_res(reg, par_addr_cells, par_size_cells,
+ &start, &size);
+ if (rv != 0)
+ return (rv);
+ start += fdt_immr_va;
+
+ /*
+ * Process 'pin-count' and 'pin-map' props.
+ */
+ if (OF_getprop(node, "pin-count", &pin_count, sizeof(pin_count)) <= 0)
+ return (ENXIO);
+ pin_count = fdt32_to_cpu(pin_count);
+ if (pin_count > MPP_PIN_MAX)
+ return (ERANGE);
+
+ if (OF_getprop(node, "#pin-cells", &pin_cells, sizeof(pin_cells)) <= 0)
+ pin_cells = MPP_PIN_CELLS;
+ pin_cells = fdt32_to_cpu(pin_cells);
+ if (pin_cells > MPP_PIN_CELLS)
+ return (ERANGE);
+ tuple_size = sizeof(pcell_t) * pin_cells;
+
+ bzero(pinmap, sizeof(pinmap));
+ len = OF_getprop(node, "pin-map", pinmap, sizeof(pinmap));
+ if (len <= 0)
+ return (ERANGE);
+ if (len % tuple_size)
+ return (ERANGE);
+ pins = len / tuple_size;
+ if (pins > pin_count)
+ return (ERANGE);
+ /*
+ * Fill out a "mpp[pin] => function" table. All pins unspecified in
+ * the 'pin-map' property are defaulted to 0 function i.e. GPIO.
+ */
+ bzero(mpp, sizeof(mpp));
+ pinmap_ptr = pinmap;
+ for (i = 0; i < pins; i++) {
+ mpp_pin = fdt32_to_cpu(*pinmap_ptr);
+ mpp_function = fdt32_to_cpu(*(pinmap_ptr + 1));
+ mpp[mpp_pin] = mpp_function;
+ pinmap_ptr += pin_cells;
+ }
+
+ /*
+ * Prepare and program MPP control register values.
+ */
+ ctrl_offset = 0;
+ for (i = 0; i < pin_count;) {
+ ctrl_val = 0;
+
+ for (j = 0; j < MPP_PINS_PER_REG; j++) {
+ if (i + j == pin_count - 1)
+ break;
+ ctrl_val |= MPP_SEL(i + j, mpp[i + j]);
+ }
+ i += MPP_PINS_PER_REG;
+ bus_space_write_4(fdtbus_bs_tag, start, ctrl_offset,
+ ctrl_val);
+
+#if defined(SOC_MV_ORION)
+ /*
+ * Third MPP reg on Orion SoC is placed
+ * non-linearly (with different offset).
+ */
+ if (i == (2 * MPP_PINS_PER_REG))
+ ctrl_offset = 0x50;
+ else
+#endif
+ ctrl_offset += 4;
+ }
+
+ return (0);
+}
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (fdt_immr_va);
+}
+
+void
+initarm_early_init(void)
+{
+
+ if (fdt_immr_addr(MV_BASE) != 0)
+ while (1);
+}
+
+void
+initarm_gpio_init(void)
+{
+
+ /*
+ * Re-initialise MPP. It is important to call this prior to using
+ * console as the physical connection can be routed via MPP.
+ */
+ if (platform_mpp_init() != 0)
+ while (1);
+}
+
+void
+initarm_late_init(void)
+{
+ /*
+ * Re-initialise decode windows
+ */
+#if !defined(SOC_MV_FREY)
+ if (soc_decode_win() != 0)
+ printf("WARNING: could not re-initialise decode windows! "
+ "Running with existing settings...\n");
+#else
+ /* Disable watchdog and timers */
+ write_cpu_ctrl(CPU_TIMERS_BASE + CPU_TIMER_CONTROL, 0);
+#endif
+#if defined(SOC_MV_ARMADAXP)
+#if !defined(SMP)
+ /* For SMP case it should be initialized after APs are booted */
+ armadaxp_init_coher_fabric();
+#endif
+ armadaxp_l2_init();
+#endif
+}
+
+#define FDT_DEVMAP_MAX (MV_WIN_CPU_MAX + 2)
+static struct arm_devmap_entry fdt_devmap[FDT_DEVMAP_MAX] = {
+ { 0, 0, 0, 0, 0, }
+};
+
+static int
+platform_sram_devmap(struct arm_devmap_entry *map)
+{
+#if !defined(SOC_MV_ARMADAXP)
+ phandle_t child, root;
+ u_long base, size;
+ /*
+ * SRAM range.
+ */
+ if ((child = OF_finddevice("/sram")) != 0)
+ if (fdt_is_compatible(child, "mrvl,cesa-sram") ||
+ fdt_is_compatible(child, "mrvl,scratchpad"))
+ goto moveon;
+
+ if ((root = OF_finddevice("/")) == 0)
+ return (ENXIO);
+
+ if ((child = fdt_find_compatible(root, "mrvl,cesa-sram", 0)) == 0 &&
+ (child = fdt_find_compatible(root, "mrvl,scratchpad", 0)) == 0)
+ goto out;
+
+moveon:
+ if (fdt_regsize(child, &base, &size) != 0)
+ return (EINVAL);
+
+ map->pd_va = MV_CESA_SRAM_BASE; /* XXX */
+ map->pd_pa = base;
+ map->pd_size = size;
+ map->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ map->pd_cache = PTE_DEVICE;
+
+ return (0);
+out:
+#endif
+ return (ENOENT);
+
+}
+
+/*
+ * Supply a default do-nothing implementation of mv_pci_devmap() via a weak
+ * alias. Many Marvell platforms don't support a PCI interface, but to support
+ * those that do, we end up with a reference to this function below, in
+ * platform_devmap_init(). If "device pci" appears in the kernel config, the
+ * real implementation of this function in arm/mv/mv_pci.c overrides the weak
+ * alias defined here.
+ */
+int mv_default_fdt_pci_devmap(phandle_t node, struct arm_devmap_entry *devmap,
+ vm_offset_t io_va, vm_offset_t mem_va);
+int
+mv_default_fdt_pci_devmap(phandle_t node, struct arm_devmap_entry *devmap,
+ vm_offset_t io_va, vm_offset_t mem_va)
+{
+
+ return (0);
+}
+__weak_reference(mv_default_fdt_pci_devmap, mv_pci_devmap);
+
+/*
+ * XXX: When device entry in devmap has pd_size smaller than section size,
+ * system will freeze during initialization
+ */
+
+/*
+ * Construct pmap_devmap[] with DT-derived config data.
+ */
+int
+initarm_devmap_init(void)
+{
+ phandle_t root, child;
+ pcell_t bank_count;
+ int i, num_mapped;
+
+ i = 0;
+ arm_devmap_register_table(&fdt_devmap[0]);
+
+#ifdef SOC_MV_ARMADAXP
+ vm_paddr_t cur_immr_pa;
+
+ /*
+ * Acquire SoC registers' base passed by u-boot and fill devmap
+ * accordingly. DTB is going to be modified basing on this data
+ * later.
+ */
+ __asm __volatile("mrc p15, 4, %0, c15, c0, 0" : "=r" (cur_immr_pa));
+ cur_immr_pa = (cur_immr_pa << 13) & 0xff000000;
+ if (cur_immr_pa != 0)
+ fdt_immr_pa = cur_immr_pa;
+#endif
+ /*
+ * IMMR range.
+ */
+ fdt_devmap[i].pd_va = fdt_immr_va;
+ fdt_devmap[i].pd_pa = fdt_immr_pa;
+ fdt_devmap[i].pd_size = fdt_immr_size;
+ fdt_devmap[i].pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ fdt_devmap[i].pd_cache = PTE_DEVICE;
+ i++;
+
+ /*
+ * SRAM range.
+ */
+ if (i < FDT_DEVMAP_MAX)
+ if (platform_sram_devmap(&fdt_devmap[i]) == 0)
+ i++;
+
+ /*
+ * PCI range(s).
+ * PCI range(s) and localbus.
+ */
+ if ((root = OF_finddevice("/")) == -1)
+ return (ENXIO);
+ for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+ if (fdt_is_type(child, "pci") || fdt_is_type(child, "pciep")) {
+ /*
+ * Check space: each PCI node will consume 2 devmap
+ * entries.
+ */
+ if (i + 1 >= FDT_DEVMAP_MAX)
+ return (ENOMEM);
+
+ /*
+ * XXX this should account for PCI and multiple ranges
+ * of a given kind.
+ */
+ if (mv_pci_devmap(child, &fdt_devmap[i], MV_PCI_VA_IO_BASE,
+ MV_PCI_VA_MEM_BASE) != 0)
+ return (ENXIO);
+ i += 2;
+ }
+
+ if (fdt_is_compatible(child, "mrvl,lbc")) {
+ /* Check available space */
+ if (OF_getprop(child, "bank-count", (void *)&bank_count,
+ sizeof(bank_count)) <= 0)
+ /* If no property, use default value */
+ bank_count = 1;
+ else
+ bank_count = fdt32_to_cpu(bank_count);
+
+ if ((i + bank_count) >= FDT_DEVMAP_MAX)
+ return (ENOMEM);
+
+ /* Add all localbus ranges to device map */
+ num_mapped = 0;
+
+ if (fdt_localbus_devmap(child, &fdt_devmap[i],
+ (int)bank_count, &num_mapped) != 0)
+ return (ENXIO);
+
+ i += num_mapped;
+ }
+ }
+
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+#if defined(CPU_MV_PJ4B)
+#ifdef DDB
+#include <ddb/ddb.h>
+
+DB_SHOW_COMMAND(cp15, db_show_cp15)
+{
+ u_int reg;
+
+ __asm __volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (reg));
+ db_printf("Cpu ID: 0x%08x\n", reg);
+ __asm __volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (reg));
+ db_printf("Current Cache Lvl ID: 0x%08x\n",reg);
+
+ __asm __volatile("mrc p15, 0, %0, c1, c0, 0" : "=r" (reg));
+ db_printf("Ctrl: 0x%08x\n",reg);
+ __asm __volatile("mrc p15, 0, %0, c1, c0, 1" : "=r" (reg));
+ db_printf("Aux Ctrl: 0x%08x\n",reg);
+
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 0" : "=r" (reg));
+ db_printf("Processor Feat 0: 0x%08x\n", reg);
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 1" : "=r" (reg));
+ db_printf("Processor Feat 1: 0x%08x\n", reg);
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 2" : "=r" (reg));
+ db_printf("Debug Feat 0: 0x%08x\n", reg);
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 3" : "=r" (reg));
+ db_printf("Auxiliary Feat 0: 0x%08x\n", reg);
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 4" : "=r" (reg));
+ db_printf("Memory Model Feat 0: 0x%08x\n", reg);
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 5" : "=r" (reg));
+ db_printf("Memory Model Feat 1: 0x%08x\n", reg);
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 6" : "=r" (reg));
+ db_printf("Memory Model Feat 2: 0x%08x\n", reg);
+ __asm __volatile("mrc p15, 0, %0, c0, c1, 7" : "=r" (reg));
+ db_printf("Memory Model Feat 3: 0x%08x\n", reg);
+
+ __asm __volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (reg));
+ db_printf("Aux Func Modes Ctrl 0: 0x%08x\n",reg);
+ __asm __volatile("mrc p15, 1, %0, c15, c2, 1" : "=r" (reg));
+ db_printf("Aux Func Modes Ctrl 1: 0x%08x\n",reg);
+
+ __asm __volatile("mrc p15, 1, %0, c15, c12, 0" : "=r" (reg));
+ db_printf("CPU ID code extension: 0x%08x\n",reg);
+}
+
+DB_SHOW_COMMAND(vtop, db_show_vtop)
+{
+ u_int reg;
+
+ if (have_addr) {
+ __asm __volatile("mcr p15, 0, %0, c7, c8, 0" : : "r" (addr));
+ __asm __volatile("mrc p15, 0, %0, c7, c4, 0" : "=r" (reg));
+ db_printf("Physical address reg: 0x%08x\n",reg);
+ } else
+ db_printf("show vtop <virt_addr>\n");
+}
+#endif /* DDB */
+#endif /* CPU_MV_PJ4B */
+
Property changes on: trunk/sys/arm/mv/mv_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/mv_pci.c
===================================================================
--- trunk/sys/arm/mv/mv_pci.c (rev 0)
+++ trunk/sys/arm/mv/mv_pci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1199 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 MARVELL INTERNATIONAL LTD.
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * Copyright (c) 2010-2012 Semihalf
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Portions of this software were developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Marvell integrated PCI/PCI-Express controller driver.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/mv_pci.c 283332 2015-05-23 22:33:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/endian.h>
+
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include "ofw_bus_if.h"
+#include "pcib_if.h"
+
+#include <machine/devmap.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+#include <arm/mv/mvwin.h>
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+/*
+ * Code and data related to fdt-based PCI configuration.
+ *
+ * This stuff used to be in dev/fdt/fdt_pci.c and fdt_common.h, but it was
+ * always Marvell-specific so that was deleted and the code now lives here.
+ */
+
+struct mv_pci_range {
+ u_long base_pci;
+ u_long base_parent;
+ u_long len;
+};
+
+#define FDT_RANGES_CELLS ((3 + 3 + 2) * 2)
+
+static void
+mv_pci_range_dump(struct mv_pci_range *range)
+{
+#ifdef DEBUG
+ printf("\n");
+ printf(" base_pci = 0x%08lx\n", range->base_pci);
+ printf(" base_par = 0x%08lx\n", range->base_parent);
+ printf(" len = 0x%08lx\n", range->len);
+#endif
+}
+
+static int
+mv_pci_ranges_decode(phandle_t node, struct mv_pci_range *io_space,
+ struct mv_pci_range *mem_space)
+{
+ pcell_t ranges[FDT_RANGES_CELLS];
+ struct mv_pci_range *pci_space;
+ pcell_t addr_cells, size_cells, par_addr_cells;
+ pcell_t *rangesptr;
+ pcell_t cell0, cell1, cell2;
+ int tuple_size, tuples, i, rv, offset_cells, len;
+
+ /*
+ * Retrieve 'ranges' property.
+ */
+ if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
+ return (EINVAL);
+ if (addr_cells != 3 || size_cells != 2)
+ return (ERANGE);
+
+ par_addr_cells = fdt_parent_addr_cells(node);
+ if (par_addr_cells > 3)
+ return (ERANGE);
+
+ len = OF_getproplen(node, "ranges");
+ if (len > sizeof(ranges))
+ return (ENOMEM);
+
+ if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
+ return (EINVAL);
+
+ tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells +
+ size_cells);
+ tuples = len / tuple_size;
+
+ /*
+ * Initialize the ranges so that we don't have to worry about
+ * having them all defined in the FDT. In particular, it is
+ * perfectly fine not to want I/O space on PCI busses.
+ */
+ bzero(io_space, sizeof(*io_space));
+ bzero(mem_space, sizeof(*mem_space));
+
+ rangesptr = &ranges[0];
+ offset_cells = 0;
+ for (i = 0; i < tuples; i++) {
+ cell0 = fdt_data_get((void *)rangesptr, 1);
+ rangesptr++;
+ cell1 = fdt_data_get((void *)rangesptr, 1);
+ rangesptr++;
+ cell2 = fdt_data_get((void *)rangesptr, 1);
+ rangesptr++;
+
+ if (cell0 & 0x02000000) {
+ pci_space = mem_space;
+ } else if (cell0 & 0x01000000) {
+ pci_space = io_space;
+ } else {
+ rv = ERANGE;
+ goto out;
+ }
+
+ if (par_addr_cells == 3) {
+ /*
+ * This is a PCI subnode 'ranges'. Skip cell0 and
+ * cell1 of this entry and only use cell2.
+ */
+ offset_cells = 2;
+ rangesptr += offset_cells;
+ }
+
+ if (fdt_data_verify((void *)rangesptr, par_addr_cells -
+ offset_cells)) {
+ rv = ERANGE;
+ goto out;
+ }
+ pci_space->base_parent = fdt_data_get((void *)rangesptr,
+ par_addr_cells - offset_cells);
+ rangesptr += par_addr_cells - offset_cells;
+
+ if (fdt_data_verify((void *)rangesptr, size_cells)) {
+ rv = ERANGE;
+ goto out;
+ }
+ pci_space->len = fdt_data_get((void *)rangesptr, size_cells);
+ rangesptr += size_cells;
+
+ pci_space->base_pci = cell2;
+ }
+ rv = 0;
+out:
+ return (rv);
+}
+
+static int
+mv_pci_ranges(phandle_t node, struct mv_pci_range *io_space,
+ struct mv_pci_range *mem_space)
+{
+ int err;
+
+ debugf("Processing PCI node: %x\n", node);
+ if ((err = mv_pci_ranges_decode(node, io_space, mem_space)) != 0) {
+ debugf("could not decode parent PCI node 'ranges'\n");
+ return (err);
+ }
+
+ debugf("Post fixup dump:\n");
+ mv_pci_range_dump(io_space);
+ mv_pci_range_dump(mem_space);
+ return (0);
+}
+
+int
+mv_pci_devmap(phandle_t node, struct arm_devmap_entry *devmap, vm_offset_t io_va,
+ vm_offset_t mem_va)
+{
+ struct mv_pci_range io_space, mem_space;
+ int error;
+
+ if ((error = mv_pci_ranges_decode(node, &io_space, &mem_space)) != 0)
+ return (error);
+
+ devmap->pd_va = (io_va ? io_va : io_space.base_parent);
+ devmap->pd_pa = io_space.base_parent;
+ devmap->pd_size = io_space.len;
+ devmap->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ devmap->pd_cache = PTE_DEVICE;
+ devmap++;
+
+ devmap->pd_va = (mem_va ? mem_va : mem_space.base_parent);
+ devmap->pd_pa = mem_space.base_parent;
+ devmap->pd_size = mem_space.len;
+ devmap->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ devmap->pd_cache = PTE_DEVICE;
+ return (0);
+}
+
+/*
+ * Code and data related to the Marvell pcib driver.
+ */
+
+#define PCI_CFG_ENA (1U << 31)
+#define PCI_CFG_BUS(bus) (((bus) & 0xff) << 16)
+#define PCI_CFG_DEV(dev) (((dev) & 0x1f) << 11)
+#define PCI_CFG_FUN(fun) (((fun) & 0x7) << 8)
+#define PCI_CFG_PCIE_REG(reg) ((reg) & 0xfc)
+
+#define PCI_REG_CFG_ADDR 0x0C78
+#define PCI_REG_CFG_DATA 0x0C7C
+
+#define PCIE_REG_CFG_ADDR 0x18F8
+#define PCIE_REG_CFG_DATA 0x18FC
+#define PCIE_REG_CONTROL 0x1A00
+#define PCIE_CTRL_LINK1X 0x00000001
+#define PCIE_REG_STATUS 0x1A04
+#define PCIE_REG_IRQ_MASK 0x1910
+
+#define PCIE_CONTROL_ROOT_CMPLX (1 << 1)
+#define PCIE_CONTROL_HOT_RESET (1 << 24)
+
+#define PCIE_LINK_TIMEOUT 1000000
+
+#define PCIE_STATUS_LINK_DOWN 1
+#define PCIE_STATUS_DEV_OFFS 16
+
+/* Minimum PCI Memory and I/O allocations taken from PCI spec (in bytes) */
+#define PCI_MIN_IO_ALLOC 4
+#define PCI_MIN_MEM_ALLOC 16
+
+#define BITS_PER_UINT32 (NBBY * sizeof(uint32_t))
+
+struct mv_pcib_softc {
+ device_t sc_dev;
+
+ struct rman sc_mem_rman;
+ bus_addr_t sc_mem_base;
+ bus_addr_t sc_mem_size;
+ uint32_t sc_mem_map[MV_PCI_MEM_SLICE_SIZE /
+ (PCI_MIN_MEM_ALLOC * BITS_PER_UINT32)];
+ int sc_win_target;
+ int sc_mem_win_attr;
+
+ struct rman sc_io_rman;
+ bus_addr_t sc_io_base;
+ bus_addr_t sc_io_size;
+ uint32_t sc_io_map[MV_PCI_IO_SLICE_SIZE /
+ (PCI_MIN_IO_ALLOC * BITS_PER_UINT32)];
+ int sc_io_win_attr;
+
+ struct resource *sc_res;
+ bus_space_handle_t sc_bsh;
+ bus_space_tag_t sc_bst;
+ int sc_rid;
+
+ struct mtx sc_msi_mtx;
+ uint32_t sc_msi_bitmap;
+
+ int sc_busnr; /* Host bridge bus number */
+ int sc_devnr; /* Host bridge device number */
+ int sc_type;
+ int sc_mode; /* Endpoint / Root Complex */
+
+ struct ofw_bus_iinfo sc_pci_iinfo;
+};
+
+/* Local forward prototypes */
+static int mv_pcib_decode_win(phandle_t, struct mv_pcib_softc *);
+static void mv_pcib_hw_cfginit(void);
+static uint32_t mv_pcib_hw_cfgread(struct mv_pcib_softc *, u_int, u_int,
+ u_int, u_int, int);
+static void mv_pcib_hw_cfgwrite(struct mv_pcib_softc *, u_int, u_int,
+ u_int, u_int, uint32_t, int);
+static int mv_pcib_init(struct mv_pcib_softc *, int, int);
+static int mv_pcib_init_all_bars(struct mv_pcib_softc *, int, int, int, int);
+static void mv_pcib_init_bridge(struct mv_pcib_softc *, int, int, int);
+static inline void pcib_write_irq_mask(struct mv_pcib_softc *, uint32_t);
+static void mv_pcib_enable(struct mv_pcib_softc *, uint32_t);
+static int mv_pcib_mem_init(struct mv_pcib_softc *);
+
+/* Forward prototypes */
+static int mv_pcib_probe(device_t);
+static int mv_pcib_attach(device_t);
+
+static struct resource *mv_pcib_alloc_resource(device_t, device_t, int, int *,
+ u_long, u_long, u_long, u_int);
+static int mv_pcib_release_resource(device_t, device_t, int, int,
+ struct resource *);
+static int mv_pcib_read_ivar(device_t, device_t, int, uintptr_t *);
+static int mv_pcib_write_ivar(device_t, device_t, int, uintptr_t);
+
+static int mv_pcib_maxslots(device_t);
+static uint32_t mv_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
+static void mv_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
+ uint32_t, int);
+static int mv_pcib_route_interrupt(device_t, device_t, int);
+#if defined(SOC_MV_ARMADAXP)
+static int mv_pcib_alloc_msi(device_t, device_t, int, int, int *);
+static int mv_pcib_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
+static int mv_pcib_release_msi(device_t, device_t, int, int *);
+#endif
+
+/*
+ * Bus interface definitions.
+ */
+static device_method_t mv_pcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mv_pcib_probe),
+ DEVMETHOD(device_attach, mv_pcib_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, mv_pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, mv_pcib_write_ivar),
+ DEVMETHOD(bus_alloc_resource, mv_pcib_alloc_resource),
+ DEVMETHOD(bus_release_resource, mv_pcib_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, mv_pcib_maxslots),
+ DEVMETHOD(pcib_read_config, mv_pcib_read_config),
+ DEVMETHOD(pcib_write_config, mv_pcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, mv_pcib_route_interrupt),
+
+#if defined(SOC_MV_ARMADAXP)
+ DEVMETHOD(pcib_alloc_msi, mv_pcib_alloc_msi),
+ DEVMETHOD(pcib_release_msi, mv_pcib_release_msi),
+ DEVMETHOD(pcib_map_msi, mv_pcib_map_msi),
+#endif
+
+ /* OFW bus interface */
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ DEVMETHOD_END
+};
+
+static driver_t mv_pcib_driver = {
+ "pcib",
+ mv_pcib_methods,
+ sizeof(struct mv_pcib_softc),
+};
+
+devclass_t pcib_devclass;
+
+DRIVER_MODULE(pcib, ofwbus, mv_pcib_driver, pcib_devclass, 0, 0);
+
+static struct mtx pcicfg_mtx;
+
+static int
+mv_pcib_probe(device_t self)
+{
+ phandle_t node;
+
+ node = ofw_bus_get_node(self);
+ if (!fdt_is_type(node, "pci"))
+ return (ENXIO);
+
+ if (!(ofw_bus_is_compatible(self, "mrvl,pcie") ||
+ ofw_bus_is_compatible(self, "mrvl,pci")))
+ return (ENXIO);
+
+ device_set_desc(self, "Marvell Integrated PCI/PCI-E Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+mv_pcib_attach(device_t self)
+{
+ struct mv_pcib_softc *sc;
+ phandle_t node, parnode;
+ uint32_t val, unit;
+ int err;
+
+ sc = device_get_softc(self);
+ sc->sc_dev = self;
+ unit = fdt_get_unit(self);
+
+
+ node = ofw_bus_get_node(self);
+ parnode = OF_parent(node);
+ if (fdt_is_compatible(node, "mrvl,pcie")) {
+ sc->sc_type = MV_TYPE_PCIE;
+ sc->sc_win_target = MV_WIN_PCIE_TARGET(unit);
+ sc->sc_mem_win_attr = MV_WIN_PCIE_MEM_ATTR(unit);
+ sc->sc_io_win_attr = MV_WIN_PCIE_IO_ATTR(unit);
+ } else if (fdt_is_compatible(node, "mrvl,pci")) {
+ sc->sc_type = MV_TYPE_PCI;
+ sc->sc_win_target = MV_WIN_PCI_TARGET;
+ sc->sc_mem_win_attr = MV_WIN_PCI_MEM_ATTR;
+ sc->sc_io_win_attr = MV_WIN_PCI_IO_ATTR;
+ } else
+ return (ENXIO);
+
+ /*
+ * Retrieve our mem-mapped registers range.
+ */
+ sc->sc_rid = 0;
+ sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid,
+ RF_ACTIVE);
+ if (sc->sc_res == NULL) {
+ device_printf(self, "could not map memory\n");
+ return (ENXIO);
+ }
+ sc->sc_bst = rman_get_bustag(sc->sc_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_res);
+
+ val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_CONTROL);
+ sc->sc_mode = (val & PCIE_CONTROL_ROOT_CMPLX ? MV_MODE_ROOT :
+ MV_MODE_ENDPOINT);
+
+ /*
+ * Get PCI interrupt info.
+ */
+ if (sc->sc_mode == MV_MODE_ROOT)
+ ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(pcell_t));
+
+ /*
+ * Configure decode windows for PCI(E) access.
+ */
+ if (mv_pcib_decode_win(node, sc) != 0)
+ return (ENXIO);
+
+ mv_pcib_hw_cfginit();
+
+ /*
+ * Enable PCIE device.
+ */
+ mv_pcib_enable(sc, unit);
+
+ /*
+ * Memory management.
+ */
+ err = mv_pcib_mem_init(sc);
+ if (err)
+ return (err);
+
+ if (sc->sc_mode == MV_MODE_ROOT) {
+ err = mv_pcib_init(sc, sc->sc_busnr,
+ mv_pcib_maxslots(sc->sc_dev));
+ if (err)
+ goto error;
+
+ device_add_child(self, "pci", -1);
+ } else {
+ sc->sc_devnr = 1;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+ PCIE_REG_STATUS, 1 << PCIE_STATUS_DEV_OFFS);
+ device_add_child(self, "pci_ep", -1);
+ }
+
+ mtx_init(&sc->sc_msi_mtx, "msi_mtx", NULL, MTX_DEF);
+ return (bus_generic_attach(self));
+
+error:
+ /* XXX SYS_RES_ should be released here */
+ rman_fini(&sc->sc_mem_rman);
+ rman_fini(&sc->sc_io_rman);
+
+ return (err);
+}
+
+static void
+mv_pcib_enable(struct mv_pcib_softc *sc, uint32_t unit)
+{
+ uint32_t val;
+#if !defined(SOC_MV_ARMADAXP)
+ int timeout;
+
+ /*
+ * Check if PCIE device is enabled.
+ */
+ if (read_cpu_ctrl(CPU_CONTROL) & CPU_CONTROL_PCIE_DISABLE(unit)) {
+ write_cpu_ctrl(CPU_CONTROL, read_cpu_ctrl(CPU_CONTROL) &
+ ~(CPU_CONTROL_PCIE_DISABLE(unit)));
+
+ timeout = PCIE_LINK_TIMEOUT;
+ val = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+ PCIE_REG_STATUS);
+ while (((val & PCIE_STATUS_LINK_DOWN) == 1) && (timeout > 0)) {
+ DELAY(1000);
+ timeout -= 1000;
+ val = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+ PCIE_REG_STATUS);
+ }
+ }
+#endif
+
+
+ if (sc->sc_mode == MV_MODE_ROOT) {
+ /*
+ * Enable PCI bridge.
+ */
+ val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIR_COMMAND);
+ val |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN |
+ PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, PCIR_COMMAND, val);
+ }
+}
+
+static int
+mv_pcib_mem_init(struct mv_pcib_softc *sc)
+{
+ int err;
+
+ /*
+ * Memory management.
+ */
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ err = rman_init(&sc->sc_mem_rman);
+ if (err)
+ return (err);
+
+ sc->sc_io_rman.rm_type = RMAN_ARRAY;
+ err = rman_init(&sc->sc_io_rman);
+ if (err) {
+ rman_fini(&sc->sc_mem_rman);
+ return (err);
+ }
+
+ err = rman_manage_region(&sc->sc_mem_rman, sc->sc_mem_base,
+ sc->sc_mem_base + sc->sc_mem_size - 1);
+ if (err)
+ goto error;
+
+ err = rman_manage_region(&sc->sc_io_rman, sc->sc_io_base,
+ sc->sc_io_base + sc->sc_io_size - 1);
+ if (err)
+ goto error;
+
+ return (0);
+
+error:
+ rman_fini(&sc->sc_mem_rman);
+ rman_fini(&sc->sc_io_rman);
+
+ return (err);
+}
+
+static inline uint32_t
+pcib_bit_get(uint32_t *map, uint32_t bit)
+{
+ uint32_t n = bit / BITS_PER_UINT32;
+
+ bit = bit % BITS_PER_UINT32;
+ return (map[n] & (1 << bit));
+}
+
+static inline void
+pcib_bit_set(uint32_t *map, uint32_t bit)
+{
+ uint32_t n = bit / BITS_PER_UINT32;
+
+ bit = bit % BITS_PER_UINT32;
+ map[n] |= (1 << bit);
+}
+
+static inline uint32_t
+pcib_map_check(uint32_t *map, uint32_t start, uint32_t bits)
+{
+ uint32_t i;
+
+ for (i = start; i < start + bits; i++)
+ if (pcib_bit_get(map, i))
+ return (0);
+
+ return (1);
+}
+
+static inline void
+pcib_map_set(uint32_t *map, uint32_t start, uint32_t bits)
+{
+ uint32_t i;
+
+ for (i = start; i < start + bits; i++)
+ pcib_bit_set(map, i);
+}
+
+/*
+ * The idea of this allocator is taken from ARM No-Cache memory
+ * management code (sys/arm/arm/vm_machdep.c).
+ */
+static bus_addr_t
+pcib_alloc(struct mv_pcib_softc *sc, uint32_t smask)
+{
+ uint32_t bits, bits_limit, i, *map, min_alloc, size;
+ bus_addr_t addr = 0;
+ bus_addr_t base;
+
+ if (smask & 1) {
+ base = sc->sc_io_base;
+ min_alloc = PCI_MIN_IO_ALLOC;
+ bits_limit = sc->sc_io_size / min_alloc;
+ map = sc->sc_io_map;
+ smask &= ~0x3;
+ } else {
+ base = sc->sc_mem_base;
+ min_alloc = PCI_MIN_MEM_ALLOC;
+ bits_limit = sc->sc_mem_size / min_alloc;
+ map = sc->sc_mem_map;
+ smask &= ~0xF;
+ }
+
+ size = ~smask + 1;
+ bits = size / min_alloc;
+
+ for (i = 0; i + bits <= bits_limit; i += bits)
+ if (pcib_map_check(map, i, bits)) {
+ pcib_map_set(map, i, bits);
+ addr = base + (i * min_alloc);
+ return (addr);
+ }
+
+ return (addr);
+}
+
+static int
+mv_pcib_init_bar(struct mv_pcib_softc *sc, int bus, int slot, int func,
+ int barno)
+{
+ uint32_t addr, bar;
+ int reg, width;
+
+ reg = PCIR_BAR(barno);
+
+ /*
+ * Need to init the BAR register with 0xffffffff before correct
+ * value can be read.
+ */
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
+ bar = mv_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4);
+ if (bar == 0)
+ return (1);
+
+ /* Calculate BAR size: 64 or 32 bit (in 32-bit units) */
+ width = ((bar & 7) == 4) ? 2 : 1;
+
+ addr = pcib_alloc(sc, bar);
+ if (!addr)
+ return (-1);
+
+ if (bootverbose)
+ printf("PCI %u:%u:%u: reg %x: smask=%08x: addr=%08x\n",
+ bus, slot, func, reg, bar, addr);
+
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
+ if (width == 2)
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4,
+ 0, 4);
+
+ return (width);
+}
+
+static void
+mv_pcib_init_bridge(struct mv_pcib_softc *sc, int bus, int slot, int func)
+{
+ bus_addr_t io_base, mem_base;
+ uint32_t io_limit, mem_limit;
+ int secbus;
+
+ io_base = sc->sc_io_base;
+ io_limit = io_base + sc->sc_io_size - 1;
+ mem_base = sc->sc_mem_base;
+ mem_limit = mem_base + sc->sc_mem_size - 1;
+
+ /* Configure I/O decode registers */
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEL_1,
+ io_base >> 8, 1);
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEH_1,
+ io_base >> 16, 2);
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITL_1,
+ io_limit >> 8, 1);
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITH_1,
+ io_limit >> 16, 2);
+
+ /* Configure memory decode registers */
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMBASE_1,
+ mem_base >> 16, 2);
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMLIMIT_1,
+ mem_limit >> 16, 2);
+
+ /* Disable memory prefetch decode */
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEL_1,
+ 0x10, 2);
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEH_1,
+ 0x0, 4);
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITL_1,
+ 0xF, 2);
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITH_1,
+ 0x0, 4);
+
+ secbus = mv_pcib_read_config(sc->sc_dev, bus, slot, func,
+ PCIR_SECBUS_1, 1);
+
+ /* Configure buses behind the bridge */
+ mv_pcib_init(sc, secbus, PCI_SLOTMAX);
+}
+
+static int
+mv_pcib_init(struct mv_pcib_softc *sc, int bus, int maxslot)
+{
+ int slot, func, maxfunc, error;
+ uint8_t hdrtype, command, class, subclass;
+
+ for (slot = 0; slot <= maxslot; slot++) {
+ maxfunc = 0;
+ for (func = 0; func <= maxfunc; func++) {
+ hdrtype = mv_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_HDRTYPE, 1);
+
+ if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
+ continue;
+
+ if (func == 0 && (hdrtype & PCIM_MFDEV))
+ maxfunc = PCI_FUNCMAX;
+
+ command = mv_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_COMMAND, 1);
+ command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_COMMAND, command, 1);
+
+ error = mv_pcib_init_all_bars(sc, bus, slot, func,
+ hdrtype);
+
+ if (error)
+ return (error);
+
+ command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
+ PCIM_CMD_PORTEN;
+ mv_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_COMMAND, command, 1);
+
+ /* Handle PCI-PCI bridges */
+ class = mv_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_CLASS, 1);
+ subclass = mv_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_SUBCLASS, 1);
+
+ if (class != PCIC_BRIDGE ||
+ subclass != PCIS_BRIDGE_PCI)
+ continue;
+
+ mv_pcib_init_bridge(sc, bus, slot, func);
+ }
+ }
+
+ /* Enable all ABCD interrupts */
+ pcib_write_irq_mask(sc, (0xF << 24));
+
+ return (0);
+}
+
+static int
+mv_pcib_init_all_bars(struct mv_pcib_softc *sc, int bus, int slot,
+ int func, int hdrtype)
+{
+ int maxbar, bar, i;
+
+ maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6;
+ bar = 0;
+
+ /* Program the base address registers */
+ while (bar < maxbar) {
+ i = mv_pcib_init_bar(sc, bus, slot, func, bar);
+ bar += i;
+ if (i < 0) {
+ device_printf(sc->sc_dev,
+ "PCI IO/Memory space exhausted\n");
+ return (ENOMEM);
+ }
+ }
+
+ return (0);
+}
+
+static struct resource *
+mv_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct mv_pcib_softc *sc = device_get_softc(dev);
+ struct rman *rm = NULL;
+ struct resource *res;
+
+ switch (type) {
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io_rman;
+ break;
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_mem_rman;
+ break;
+ default:
+ return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+ type, rid, start, end, count, flags));
+ };
+
+ if ((start == 0UL) && (end == ~0UL)) {
+ start = sc->sc_mem_base;
+ end = sc->sc_mem_base + sc->sc_mem_size - 1;
+ count = sc->sc_mem_size;
+ }
+
+ if ((start < sc->sc_mem_base) || (start + count - 1 != end) ||
+ (end > sc->sc_mem_base + sc->sc_mem_size - 1))
+ return (NULL);
+
+ res = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (res == NULL)
+ return (NULL);
+
+ rman_set_rid(res, *rid);
+ rman_set_bustag(res, fdtbus_bs_tag);
+ rman_set_bushandle(res, start);
+
+ if (flags & RF_ACTIVE)
+ if (bus_activate_resource(child, type, *rid, res)) {
+ rman_release_resource(res);
+ return (NULL);
+ }
+
+ return (res);
+}
+
+static int
+mv_pcib_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
+ return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
+ type, rid, res));
+
+ return (rman_release_resource(res));
+}
+
+static int
+mv_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct mv_pcib_softc *sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_busnr;
+ return (0);
+ case PCIB_IVAR_DOMAIN:
+ *result = device_get_unit(dev);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+mv_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct mv_pcib_softc *sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ sc->sc_busnr = value;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static inline void
+pcib_write_irq_mask(struct mv_pcib_softc *sc, uint32_t mask)
+{
+
+ if (!sc->sc_type != MV_TYPE_PCI)
+ return;
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_IRQ_MASK, mask);
+}
+
+static void
+mv_pcib_hw_cfginit(void)
+{
+ static int opened = 0;
+
+ if (opened)
+ return;
+
+ mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
+ opened = 1;
+}
+
+static uint32_t
+mv_pcib_hw_cfgread(struct mv_pcib_softc *sc, u_int bus, u_int slot,
+ u_int func, u_int reg, int bytes)
+{
+ uint32_t addr, data, ca, cd;
+
+ ca = (sc->sc_type != MV_TYPE_PCI) ?
+ PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
+ cd = (sc->sc_type != MV_TYPE_PCI) ?
+ PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
+ addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
+ PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
+
+ mtx_lock_spin(&pcicfg_mtx);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
+
+ data = ~0;
+ switch (bytes) {
+ case 1:
+ data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
+ cd + (reg & 3));
+ break;
+ case 2:
+ data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
+ cd + (reg & 2)));
+ break;
+ case 4:
+ data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+ cd));
+ break;
+ }
+ mtx_unlock_spin(&pcicfg_mtx);
+ return (data);
+}
+
+static void
+mv_pcib_hw_cfgwrite(struct mv_pcib_softc *sc, u_int bus, u_int slot,
+ u_int func, u_int reg, uint32_t data, int bytes)
+{
+ uint32_t addr, ca, cd;
+
+ ca = (sc->sc_type != MV_TYPE_PCI) ?
+ PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
+ cd = (sc->sc_type != MV_TYPE_PCI) ?
+ PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
+ addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
+ PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
+
+ mtx_lock_spin(&pcicfg_mtx);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
+
+ switch (bytes) {
+ case 1:
+ bus_space_write_1(sc->sc_bst, sc->sc_bsh,
+ cd + (reg & 3), data);
+ break;
+ case 2:
+ bus_space_write_2(sc->sc_bst, sc->sc_bsh,
+ cd + (reg & 2), htole16(data));
+ break;
+ case 4:
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+ cd, htole32(data));
+ break;
+ }
+ mtx_unlock_spin(&pcicfg_mtx);
+}
+
+static int
+mv_pcib_maxslots(device_t dev)
+{
+ struct mv_pcib_softc *sc = device_get_softc(dev);
+
+ return ((sc->sc_type != MV_TYPE_PCI) ? 1 : PCI_SLOTMAX);
+}
+
+static uint32_t
+mv_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, int bytes)
+{
+ struct mv_pcib_softc *sc = device_get_softc(dev);
+
+ /* Return ~0 if link is inactive or trying to read from Root */
+ if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS) &
+ PCIE_STATUS_LINK_DOWN) || (slot == 0))
+ return (~0U);
+
+ return (mv_pcib_hw_cfgread(sc, bus, slot, func, reg, bytes));
+}
+
+static void
+mv_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, uint32_t val, int bytes)
+{
+ struct mv_pcib_softc *sc = device_get_softc(dev);
+
+ /* Return if link is inactive or trying to write to Root */
+ if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS) &
+ PCIE_STATUS_LINK_DOWN) || (slot == 0))
+ return;
+
+ mv_pcib_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes);
+}
+
+static int
+mv_pcib_route_interrupt(device_t bus, device_t dev, int pin)
+{
+ struct mv_pcib_softc *sc;
+ struct ofw_pci_register reg;
+ uint32_t pintr, mintr[4];
+ int icells;
+ phandle_t iparent;
+
+ sc = device_get_softc(bus);
+ pintr = pin;
+
+ /* Fabricate imap information in case this isn't an OFW device */
+ bzero(®, sizeof(reg));
+ reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+ (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+ (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
+ icells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo,
+ ®, sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr),
+ &iparent);
+ if (icells > 0)
+ return (ofw_bus_map_intr(dev, iparent, icells, mintr));
+
+ /* Maybe it's a real interrupt, not an intpin */
+ if (pin > 4)
+ return (pin);
+
+ device_printf(bus, "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (PCI_INVALID_IRQ);
+}
+
+static int
+mv_pcib_decode_win(phandle_t node, struct mv_pcib_softc *sc)
+{
+ struct mv_pci_range io_space, mem_space;
+ device_t dev;
+ int error;
+
+ dev = sc->sc_dev;
+
+ if ((error = mv_pci_ranges(node, &io_space, &mem_space)) != 0) {
+ device_printf(dev, "could not retrieve 'ranges' data\n");
+ return (error);
+ }
+
+ /* Configure CPU decoding windows */
+ error = decode_win_cpu_set(sc->sc_win_target,
+ sc->sc_io_win_attr, io_space.base_parent, io_space.len, ~0);
+ if (error < 0) {
+ device_printf(dev, "could not set up CPU decode "
+ "window for PCI IO\n");
+ return (ENXIO);
+ }
+ error = decode_win_cpu_set(sc->sc_win_target,
+ sc->sc_mem_win_attr, mem_space.base_parent, mem_space.len,
+ mem_space.base_parent);
+ if (error < 0) {
+ device_printf(dev, "could not set up CPU decode "
+ "windows for PCI MEM\n");
+ return (ENXIO);
+ }
+
+ sc->sc_io_base = io_space.base_parent;
+ sc->sc_io_size = io_space.len;
+
+ sc->sc_mem_base = mem_space.base_parent;
+ sc->sc_mem_size = mem_space.len;
+
+ return (0);
+}
+
+#if defined(SOC_MV_ARMADAXP)
+static int
+mv_pcib_map_msi(device_t dev, device_t child, int irq, uint64_t *addr,
+ uint32_t *data)
+{
+ struct mv_pcib_softc *sc;
+
+ sc = device_get_softc(dev);
+ irq = irq - MSI_IRQ;
+
+ /* validate parameters */
+ if (isclr(&sc->sc_msi_bitmap, irq)) {
+ device_printf(dev, "invalid MSI 0x%x\n", irq);
+ return (EINVAL);
+ }
+
+ mv_msi_data(irq, addr, data);
+
+ debugf("%s: irq: %d addr: %jx data: %x\n",
+ __func__, irq, *addr, *data);
+
+ return (0);
+}
+
+static int
+mv_pcib_alloc_msi(device_t dev, device_t child, int count,
+ int maxcount __unused, int *irqs)
+{
+ struct mv_pcib_softc *sc;
+ u_int start = 0, i;
+
+ if (powerof2(count) == 0 || count > MSI_IRQ_NUM)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->sc_msi_mtx);
+
+ for (start = 0; (start + count) < MSI_IRQ_NUM; start++) {
+ for (i = start; i < start + count; i++) {
+ if (isset(&sc->sc_msi_bitmap, i))
+ break;
+ }
+ if (i == start + count)
+ break;
+ }
+
+ if ((start + count) == MSI_IRQ_NUM) {
+ mtx_unlock(&sc->sc_msi_mtx);
+ return (ENXIO);
+ }
+
+ for (i = start; i < start + count; i++) {
+ setbit(&sc->sc_msi_bitmap, i);
+ *irqs++ = MSI_IRQ + i;
+ }
+ debugf("%s: start: %x count: %x\n", __func__, start, count);
+
+ mtx_unlock(&sc->sc_msi_mtx);
+ return (0);
+}
+
+static int
+mv_pcib_release_msi(device_t dev, device_t child, int count, int *irqs)
+{
+ struct mv_pcib_softc *sc;
+ u_int i;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->sc_msi_mtx);
+
+ for (i = 0; i < count; i++)
+ clrbit(&sc->sc_msi_bitmap, irqs[i] - MSI_IRQ);
+
+ mtx_unlock(&sc->sc_msi_mtx);
+ return (0);
+}
+#endif
+
Property changes on: trunk/sys/arm/mv/mv_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/mv_ts.c
===================================================================
--- trunk/sys/arm/mv/mv_ts.c (rev 0)
+++ trunk/sys/arm/mv/mv_ts.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,182 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Hiroki Sato <hrs at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Driver for on-die thermal sensor in 88F6282 and 88F6283.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/mv_ts.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/sysctl.h>
+#include <machine/fdt.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+
+static struct resource_spec mvts_res[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+struct mvts_softc {
+ device_t sc_dev;
+ struct resource *sc_res[sizeof(mvts_res)];
+};
+
+static int
+ts_probe(device_t dev)
+{
+ uint32_t d, r;
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "mrvl,ts"))
+ return (ENXIO);
+ soc_id(&d, &r);
+ switch (d) {
+ case MV_DEV_88F6282:
+ break;
+ default:
+ device_printf(dev, "unsupported SoC (ID: 0x%08X)!\n", d);
+ return (ENXIO);
+ }
+ device_set_desc(dev, "Marvell Thermal Sensor");
+
+ return (0);
+}
+
+#define MV_TEMP_VALID_BIT (1 << 9)
+#define MV_TEMP_SENS_OFFS 10
+#define MV_TEMP_SENS_MASK 0x1ff
+#define MV_TEMP_SENS_READ_MAX 16
+#define TZ_ZEROC 2732
+#define MV_TEMP_CONVERT(x) ((((322 - x) * 100000) / 13625) + TZ_ZEROC)
+
+/*
+ * MSB LSB
+ * 0000 0000 0000 0000 0000 0000 0000 0000
+ * ^- valid bit
+ * |---------|
+ * ^--- temperature (9 bits)
+ */
+
+static int
+ts_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ struct mvts_softc *sc;
+ device_t dev;
+ uint32_t ret, ret0;
+ u_int val;
+ int i;
+
+ dev = (device_t)arg1;
+ sc = device_get_softc(dev);
+ val = TZ_ZEROC;
+
+ ret = bus_read_4(sc->sc_res[0], 0);
+ if ((ret & MV_TEMP_VALID_BIT) == 0) {
+ device_printf(dev, "temperature sensor is broken.\n");
+ goto ts_sysctl_handle_int;
+ }
+ ret0 = 0;
+ for (i = 0; i < MV_TEMP_SENS_READ_MAX; i++) {
+ ret = bus_read_4(sc->sc_res[0], 0);
+ ret = (ret >> MV_TEMP_SENS_OFFS) & MV_TEMP_SENS_MASK;
+
+ /*
+ * Successive reads should returns the same value except
+ * for the LSB when the sensor is normal.
+ */
+ if (((ret0 ^ ret) & 0x1fe) == 0)
+ break;
+ else
+ ret0 = ret;
+ }
+ if (i == MV_TEMP_SENS_READ_MAX) {
+ device_printf(dev, "temperature sensor is unstable.\n");
+ goto ts_sysctl_handle_int;
+ }
+ val = (u_int)MV_TEMP_CONVERT(ret);
+
+ts_sysctl_handle_int:
+ return (sysctl_handle_int(oidp, &val, 0, req));
+}
+
+static int
+ts_attach(device_t dev)
+{
+ struct mvts_softc *sc;
+ struct sysctl_ctx_list *ctx;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ error = bus_alloc_resources(dev, mvts_res, sc->sc_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+ ctx = device_get_sysctl_ctx(dev);
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, dev,
+ 0, ts_sysctl_handler, "IK", "Current Temperature");
+
+ return (0);
+}
+
+static int
+ts_detach(device_t dev)
+{
+
+ return (0);
+}
+
+static device_method_t ts_methods[] = {
+ DEVMETHOD(device_probe, ts_probe),
+ DEVMETHOD(device_attach, ts_attach),
+ DEVMETHOD(device_detach, ts_detach),
+ {0, 0},
+};
+
+static driver_t ts_driver = {
+ "mvts",
+ ts_methods,
+ sizeof(struct mvts_softc),
+};
+
+static devclass_t ts_devclass;
+DRIVER_MODULE(mvts, simplebus, ts_driver, ts_devclass, 0, 0);
+MODULE_VERSION(mvts, 1);
Property changes on: trunk/sys/arm/mv/mv_ts.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/mvreg.h
===================================================================
--- trunk/sys/arm/mv/mvreg.h (rev 0)
+++ trunk/sys/arm/mv/mvreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,448 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2007-2011 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/mv/mvreg.h 266277 2014-05-17 00:53:12Z ian $
+ */
+
+#ifndef _MVREG_H_
+#define _MVREG_H_
+
+#if defined(SOC_MV_DISCOVERY)
+#define IRQ_CAUSE_ERROR 0x0
+#define IRQ_CAUSE 0x4
+#define IRQ_CAUSE_HI 0x8
+#define IRQ_MASK_ERROR 0xC
+#define IRQ_MASK 0x10
+#define IRQ_MASK_HI 0x14
+#define IRQ_CAUSE_SELECT 0x18
+#define FIQ_MASK_ERROR 0x1C
+#define FIQ_MASK 0x20
+#define FIQ_MASK_HI 0x24
+#define FIQ_CAUSE_SELECT 0x28
+#define ENDPOINT_IRQ_MASK_ERROR(n) 0x2C
+#define ENDPOINT_IRQ_MASK(n) 0x30
+#define ENDPOINT_IRQ_MASK_HI(n) 0x34
+#define ENDPOINT_IRQ_CAUSE_SELECT 0x38
+#elif defined (SOC_MV_LOKIPLUS) || defined (SOC_MV_FREY)
+#define IRQ_CAUSE 0x0
+#define IRQ_MASK 0x4
+#define FIQ_MASK 0x8
+#define ENDPOINT_IRQ_MASK(n) (0xC + (n) * 4)
+#define IRQ_CAUSE_HI (-1) /* Fake defines for unified */
+#define IRQ_MASK_HI (-1) /* interrupt controller code */
+#define FIQ_MASK_HI (-1)
+#define ENDPOINT_IRQ_MASK_HI(n) (-1)
+#define ENDPOINT_IRQ_MASK_ERROR(n) (-1)
+#define IRQ_CAUSE_ERROR (-1)
+#define IRQ_MASK_ERROR (-1)
+#elif defined (SOC_MV_ARMADAXP)
+#define IRQ_CAUSE 0x18
+#define IRQ_MASK 0x30
+#else /* !SOC_MV_DISCOVERY && !SOC_MV_LOKIPLUS */
+#define IRQ_CAUSE 0x0
+#define IRQ_MASK 0x4
+#define FIQ_MASK 0x8
+#define ENDPOINT_IRQ_MASK(n) 0xC
+#define IRQ_CAUSE_HI 0x10
+#define IRQ_MASK_HI 0x14
+#define FIQ_MASK_HI 0x18
+#define ENDPOINT_IRQ_MASK_HI(n) 0x1C
+#define ENDPOINT_IRQ_MASK_ERROR(n) (-1)
+#define IRQ_CAUSE_ERROR (-1) /* Fake defines for unified */
+#define IRQ_MASK_ERROR (-1) /* interrupt controller code */
+#endif
+
+#if defined(SOC_MV_FREY)
+#define BRIDGE_IRQ_CAUSE 0x118
+#define IRQ_TIMER0 0x00000002
+#define IRQ_TIMER1 0x00000004
+#define IRQ_TIMER_WD 0x00000008
+
+#define BRIDGE_IRQ_MASK 0x11c
+#define IRQ_TIMER0_MASK 0x00000002
+#define IRQ_TIMER1_MASK 0x00000004
+#define IRQ_TIMER_WD_MASK 0x00000008
+#elif defined(SOC_MV_ARMADAXP)
+#define BRIDGE_IRQ_CAUSE 0x68
+#define IRQ_TIMER0 0x00000001
+#define IRQ_TIMER1 0x00000002
+#define IRQ_TIMER_WD 0x00000004
+#else
+#define BRIDGE_IRQ_CAUSE 0x10
+#define IRQ_CPU_SELF 0x00000001
+#define IRQ_TIMER0 0x00000002
+#define IRQ_TIMER1 0x00000004
+#define IRQ_TIMER_WD 0x00000008
+
+#define BRIDGE_IRQ_MASK 0x14
+#define IRQ_CPU_MASK 0x00000001
+#define IRQ_TIMER0_MASK 0x00000002
+#define IRQ_TIMER1_MASK 0x00000004
+#define IRQ_TIMER_WD_MASK 0x00000008
+#endif
+
+#if defined(SOC_MV_LOKIPLUS) || defined(SOC_MV_FREY)
+#define IRQ_CPU_SELF_CLR IRQ_CPU_SELF
+#define IRQ_TIMER0_CLR IRQ_TIMER0
+#define IRQ_TIMER1_CLR IRQ_TIMER1
+#define IRQ_TIMER_WD_CLR IRQ_TIMER_WD
+#else
+#define IRQ_CPU_SELF_CLR (~IRQ_CPU_SELF)
+#define IRQ_TIMER0_CLR (~IRQ_TIMER0)
+#define IRQ_TIMER1_CLR (~IRQ_TIMER1)
+#define IRQ_TIMER_WD_CLR (~IRQ_TIMER_WD)
+#endif
+
+/*
+ * System reset
+ */
+#if defined(SOC_MV_ARMADAXP)
+#define RSTOUTn_MASK 0x60
+#define SYSTEM_SOFT_RESET 0x64
+#define WD_RSTOUTn_MASK 0x4
+#define WD_GLOBAL_MASK 0x00000100
+#define WD_CPU0_MASK 0x00000001
+#define SOFT_RST_OUT_EN 0x00000001
+#define SYS_SOFT_RST 0x00000001
+#else
+#define RSTOUTn_MASK 0x8
+#define WD_RST_OUT_EN 0x00000002
+#define SOFT_RST_OUT_EN 0x00000004
+#define SYSTEM_SOFT_RESET 0xc
+#define SYS_SOFT_RST 0x00000001
+#endif
+
+/*
+ * Power Control
+ */
+#if defined(SOC_MV_KIRKWOOD)
+#define CPU_PM_CTRL 0x18
+#else
+#define CPU_PM_CTRL 0x1C
+#endif
+#define CPU_PM_CTRL_NONE 0
+#define CPU_PM_CTRL_ALL ~0x0
+
+#if defined(SOC_MV_KIRKWOOD)
+#define CPU_PM_CTRL_GE0 (1 << 0)
+#define CPU_PM_CTRL_PEX0_PHY (1 << 1)
+#define CPU_PM_CTRL_PEX0 (1 << 2)
+#define CPU_PM_CTRL_USB0 (1 << 3)
+#define CPU_PM_CTRL_SDIO (1 << 4)
+#define CPU_PM_CTRL_TSU (1 << 5)
+#define CPU_PM_CTRL_DUNIT (1 << 6)
+#define CPU_PM_CTRL_RUNIT (1 << 7)
+#define CPU_PM_CTRL_XOR0 (1 << 8)
+#define CPU_PM_CTRL_AUDIO (1 << 9)
+#define CPU_PM_CTRL_SATA0 (1 << 14)
+#define CPU_PM_CTRL_SATA1 (1 << 15)
+#define CPU_PM_CTRL_XOR1 (1 << 16)
+#define CPU_PM_CTRL_CRYPTO (1 << 17)
+#define CPU_PM_CTRL_GE1 (1 << 19)
+#define CPU_PM_CTRL_TDM (1 << 20)
+#define CPU_PM_CTRL_XOR (CPU_PM_CTRL_XOR0 | CPU_PM_CTRL_XOR1)
+#define CPU_PM_CTRL_USB(u) (CPU_PM_CTRL_USB0)
+#define CPU_PM_CTRL_SATA (CPU_PM_CTRL_SATA0 | CPU_PM_CTRL_SATA1)
+#define CPU_PM_CTRL_GE(u) (CPU_PM_CTRL_GE1 * (u) | CPU_PM_CTRL_GE0 * \
+ (1 - (u)))
+#define CPU_PM_CTRL_IDMA (CPU_PM_CTRL_NONE)
+#elif defined(SOC_MV_DISCOVERY)
+#define CPU_PM_CTRL_GE0 (1 << 1)
+#define CPU_PM_CTRL_GE1 (1 << 2)
+#define CPU_PM_CTRL_PEX00 (1 << 5)
+#define CPU_PM_CTRL_PEX01 (1 << 6)
+#define CPU_PM_CTRL_PEX02 (1 << 7)
+#define CPU_PM_CTRL_PEX03 (1 << 8)
+#define CPU_PM_CTRL_PEX10 (1 << 9)
+#define CPU_PM_CTRL_PEX11 (1 << 10)
+#define CPU_PM_CTRL_PEX12 (1 << 11)
+#define CPU_PM_CTRL_PEX13 (1 << 12)
+#define CPU_PM_CTRL_SATA0_PHY (1 << 13)
+#define CPU_PM_CTRL_SATA0 (1 << 14)
+#define CPU_PM_CTRL_SATA1_PHY (1 << 15)
+#define CPU_PM_CTRL_SATA1 (1 << 16)
+#define CPU_PM_CTRL_USB0 (1 << 17)
+#define CPU_PM_CTRL_USB1 (1 << 18)
+#define CPU_PM_CTRL_USB2 (1 << 19)
+#define CPU_PM_CTRL_IDMA (1 << 20)
+#define CPU_PM_CTRL_XOR (1 << 21)
+#define CPU_PM_CTRL_CRYPTO (1 << 22)
+#define CPU_PM_CTRL_DEVICE (1 << 23)
+#define CPU_PM_CTRL_USB(u) (1 << (17 + (u)))
+#define CPU_PM_CTRL_SATA (CPU_PM_CTRL_SATA0 | CPU_PM_CTRL_SATA1)
+#define CPU_PM_CTRL_GE(u) (CPU_PM_CTRL_GE1 * (u) | CPU_PM_CTRL_GE0 * \
+ (1 - (u)))
+#else
+#define CPU_PM_CTRL_CRYPTO (CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_IDMA (CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_XOR (CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_SATA (CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_USB(u) (CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_GE(u) (CPU_PM_CTRL_NONE)
+#endif
+
+/*
+ * Timers
+ */
+#define CPU_TIMERS_BASE 0x300
+#define CPU_TIMER_CONTROL 0x0
+#define CPU_TIMER0_EN 0x00000001
+#define CPU_TIMER0_AUTO 0x00000002
+#define CPU_TIMER1_EN 0x00000004
+#define CPU_TIMER1_AUTO 0x00000008
+#define CPU_TIMER_WD_EN 0x00000010
+#define CPU_TIMER_WD_AUTO 0x00000020
+/* 25MHz mode is Armada XP - specific */
+#define CPU_TIMER_WD_25MHZ_EN 0x00000400
+#define CPU_TIMER0_25MHZ_EN 0x00000800
+#define CPU_TIMER1_25MHZ_EN 0x00001000
+#define CPU_TIMER0_REL 0x10
+#define CPU_TIMER0 0x14
+
+/*
+ * SATA
+ */
+#define SATA_CHAN_NUM 2
+
+#define EDMA_REGISTERS_OFFSET 0x2000
+#define EDMA_REGISTERS_SIZE 0x2000
+#define SATA_EDMA_BASE(ch) (EDMA_REGISTERS_OFFSET + \
+ ((ch) * EDMA_REGISTERS_SIZE))
+
+/* SATAHC registers */
+#define SATA_CR 0x000 /* Configuration Reg. */
+#define SATA_CR_NODMABS (1 << 8)
+#define SATA_CR_NOEDMABS (1 << 9)
+#define SATA_CR_NOPRDPBS (1 << 10)
+#define SATA_CR_COALDIS(ch) (1 << (24 + ch))
+
+/* Interrupt Coalescing Threshold Reg. */
+#define SATA_ICTR 0x00C
+#define SATA_ICTR_MAX ((1 << 8) - 1)
+
+/* Interrupt Time Threshold Reg. */
+#define SATA_ITTR 0x010
+#define SATA_ITTR_MAX ((1 << 24) - 1)
+
+#define SATA_ICR 0x014 /* Interrupt Cause Reg. */
+#define SATA_ICR_DMADONE(ch) (1 << (ch))
+#define SATA_ICR_COAL (1 << 4)
+#define SATA_ICR_DEV(ch) (1 << (8 + ch))
+
+#define SATA_MICR 0x020 /* Main Interrupt Cause Reg. */
+#define SATA_MICR_ERR(ch) (1 << (2 * ch))
+#define SATA_MICR_DONE(ch) (1 << ((2 * ch) + 1))
+#define SATA_MICR_DMADONE(ch) (1 << (4 + ch))
+#define SATA_MICR_COAL (1 << 8)
+
+#define SATA_MIMR 0x024 /* Main Interrupt Mask Reg. */
+
+/* Shadow registers */
+#define SATA_SHADOWR_BASE(ch) (SATA_EDMA_BASE(ch) + 0x100)
+#define SATA_SHADOWR_CONTROL(ch) (SATA_EDMA_BASE(ch) + 0x120)
+
+/* SATA registers */
+#define SATA_SATA_SSTATUS(ch) (SATA_EDMA_BASE(ch) + 0x300)
+#define SATA_SATA_SERROR(ch) (SATA_EDMA_BASE(ch) + 0x304)
+#define SATA_SATA_SCONTROL(ch) (SATA_EDMA_BASE(ch) + 0x308)
+#define SATA_SATA_FISICR(ch) (SATA_EDMA_BASE(ch) + 0x364)
+
+/* EDMA registers */
+#define SATA_EDMA_CFG(ch) (SATA_EDMA_BASE(ch) + 0x000)
+#define SATA_EDMA_CFG_QL128 (1 << 19)
+#define SATA_EDMA_CFG_HQCACHE (1 << 22)
+
+#define SATA_EDMA_IECR(ch) (SATA_EDMA_BASE(ch) + 0x008)
+
+#define SATA_EDMA_IEMR(ch) (SATA_EDMA_BASE(ch) + 0x00C)
+#define SATA_EDMA_REQBAHR(ch) (SATA_EDMA_BASE(ch) + 0x010)
+#define SATA_EDMA_REQIPR(ch) (SATA_EDMA_BASE(ch) + 0x014)
+#define SATA_EDMA_REQOPR(ch) (SATA_EDMA_BASE(ch) + 0x018)
+#define SATA_EDMA_RESBAHR(ch) (SATA_EDMA_BASE(ch) + 0x01C)
+#define SATA_EDMA_RESIPR(ch) (SATA_EDMA_BASE(ch) + 0x020)
+#define SATA_EDMA_RESOPR(ch) (SATA_EDMA_BASE(ch) + 0x024)
+
+#define SATA_EDMA_CMD(ch) (SATA_EDMA_BASE(ch) + 0x028)
+#define SATA_EDMA_CMD_ENABLE (1 << 0)
+#define SATA_EDMA_CMD_DISABLE (1 << 1)
+#define SATA_EDMA_CMD_RESET (1 << 2)
+
+#define SATA_EDMA_STATUS(ch) (SATA_EDMA_BASE(ch) + 0x030)
+#define SATA_EDMA_STATUS_IDLE (1 << 7)
+
+/* Offset to extract input slot from REQIPR register */
+#define SATA_EDMA_REQIS_OFS 5
+
+/* Offset to extract input slot from RESOPR register */
+#define SATA_EDMA_RESOS_OFS 3
+
+/*
+ * GPIO
+ */
+#define GPIO_DATA_OUT 0x00
+#define GPIO_DATA_OUT_EN_CTRL 0x04
+#define GPIO_BLINK_EN 0x08
+#define GPIO_DATA_IN_POLAR 0x0c
+#define GPIO_DATA_IN 0x10
+#define GPIO_INT_CAUSE 0x14
+#define GPIO_INT_EDGE_MASK 0x18
+#define GPIO_INT_LEV_MASK 0x1c
+
+#define GPIO_HI_DATA_OUT 0x40
+#define GPIO_HI_DATA_OUT_EN_CTRL 0x44
+#define GPIO_HI_BLINK_EN 0x48
+#define GPIO_HI_DATA_IN_POLAR 0x4c
+#define GPIO_HI_DATA_IN 0x50
+#define GPIO_HI_INT_CAUSE 0x54
+#define GPIO_HI_INT_EDGE_MASK 0x58
+#define GPIO_HI_INT_LEV_MASK 0x5c
+
+#define GPIO(n) (1 << (n))
+#define MV_GPIO_MAX_NPINS 64
+
+#define MV_GPIO_IN_NONE 0x0
+#define MV_GPIO_IN_POL_LOW (1 << 16)
+#define MV_GPIO_IN_IRQ_EDGE (2 << 16)
+#define MV_GPIO_IN_IRQ_LEVEL (4 << 16)
+#define MV_GPIO_OUT_NONE 0x0
+#define MV_GPIO_OUT_BLINK 0x1
+#define MV_GPIO_OUT_OPEN_DRAIN 0x2
+#define MV_GPIO_OUT_OPEN_SRC 0x4
+
+#define IS_GPIO_IRQ(irq) ((irq) >= NIRQ && (irq) < NIRQ + MV_GPIO_MAX_NPINS)
+#define GPIO2IRQ(gpio) ((gpio) + NIRQ)
+#define IRQ2GPIO(irq) ((irq) - NIRQ)
+
+#if defined(SOC_MV_ORION) || defined(SOC_MV_LOKIPLUS)
+#define SAMPLE_AT_RESET 0x10
+#elif defined(SOC_MV_KIRKWOOD)
+#define SAMPLE_AT_RESET 0x30
+#elif defined(SOC_MV_FREY)
+#define SAMPLE_AT_RESET 0x100
+#endif
+#if defined(SOC_MV_DISCOVERY)
+#define SAMPLE_AT_RESET_LO 0x30
+#define SAMPLE_AT_RESET_HI 0x34
+#elif defined(SOC_MV_DOVE)
+#define SAMPLE_AT_RESET_LO 0x14
+#define SAMPLE_AT_RESET_HI 0x18
+#elif defined(SOC_MV_ARMADAXP)
+#define SAMPLE_AT_RESET_LO 0x30
+#define SAMPLE_AT_RESET_HI 0x34
+#endif
+
+/*
+ * Clocks
+ */
+#if defined(SOC_MV_ORION)
+#define TCLK_MASK 0x00000300
+#define TCLK_SHIFT 0x08
+#elif defined(SOC_MV_DISCOVERY)
+#define TCLK_MASK 0x00000180
+#define TCLK_SHIFT 0x07
+#elif defined(SOC_MV_LOKIPLUS)
+#define TCLK_MASK 0x0000F000
+#define TCLK_SHIFT 0x0C
+#endif
+
+#define TCLK_100MHZ 100000000
+#define TCLK_125MHZ 125000000
+#define TCLK_133MHZ 133333333
+#define TCLK_150MHZ 150000000
+#define TCLK_166MHZ 166666667
+#define TCLK_200MHZ 200000000
+#define TCLK_250MHZ 250000000
+#define TCLK_300MHZ 300000000
+#define TCLK_667MHZ 667000000
+
+/*
+ * CPU Cache Configuration
+ */
+
+#define CPU_CONFIG 0x00000000
+#define CPU_CONFIG_IC_PREF 0x00010000
+#define CPU_CONFIG_DC_PREF 0x00020000
+#define CPU_CONTROL 0x00000004
+#define CPU_CONTROL_L2_SIZE 0x00200000 /* Only on Discovery */
+#define CPU_CONTROL_L2_MODE 0x00020000 /* Only on Discovery */
+#define CPU_L2_CONFIG 0x00000028 /* Only on Kirkwood */
+#define CPU_L2_CONFIG_MODE 0x00000010 /* Only on Kirkwood */
+
+/*
+ * PCI Express port control (CPU Control registers)
+ */
+#define CPU_CONTROL_PCIE_DISABLE(n) (1 << (3 * (n)))
+
+/*
+ * Vendor ID
+ */
+#define PCI_VENDORID_MRVL 0x11AB
+#define PCI_VENDORID_MRVL2 0x1B4B
+
+/*
+ * Chip ID
+ */
+#define MV_DEV_88F5181 0x5181
+#define MV_DEV_88F5182 0x5182
+#define MV_DEV_88F5281 0x5281
+#define MV_DEV_88F6281 0x6281
+#define MV_DEV_88F6282 0x6282
+#define MV_DEV_88F6781 0x6781
+#define MV_DEV_MV78100_Z0 0x6381
+#define MV_DEV_MV78100 0x7810
+#define MV_DEV_MV78130 0x7813
+#define MV_DEV_MV78160 0x7816
+#define MV_DEV_MV78230 0x7823
+#define MV_DEV_MV78260 0x7826
+#define MV_DEV_MV78460 0x7846
+#define MV_DEV_88RC8180 0x8180
+#define MV_DEV_88RC9480 0x9480
+#define MV_DEV_88RC9580 0x9580
+
+#define MV_DEV_FAMILY_MASK 0xff00
+#define MV_DEV_DISCOVERY 0x7800
+
+/*
+ * Doorbell register control
+ */
+#define MV_DRBL_PCIE_TO_CPU 0
+#define MV_DRBL_CPU_TO_PCIE 1
+
+#if defined(SOC_MV_FREY)
+#define MV_DRBL_CAUSE(d,u) (0x60 + 0x20 * (d) + 0x8 * (u))
+#define MV_DRBL_MASK(d,u) (0x60 + 0x20 * (d) + 0x8 * (u) + 0x4)
+#define MV_DRBL_MSG(m,d,u) (0x8 * (u) + 0x20 * (d) + 0x4 * (m))
+#else
+#define MV_DRBL_CAUSE(d,u) (0x10 * (u) + 0x8 * (d))
+#define MV_DRBL_MASK(d,u) (0x10 * (u) + 0x8 * (d) + 0x4)
+#define MV_DRBL_MSG(m,d,u) (0x10 * (u) + 0x8 * (d) + 0x4 * (m) + 0x30)
+#endif
+#endif /* _MVREG_H_ */
Property changes on: trunk/sys/arm/mv/mvreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/mvvar.h
===================================================================
--- trunk/sys/arm/mv/mvvar.h (rev 0)
+++ trunk/sys/arm/mv/mvvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,146 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0var.h, rev 1
+ *
+ * $FreeBSD: stable/10/sys/arm/mv/mvvar.h 266084 2014-05-14 19:18:58Z ian $
+ */
+
+#ifndef _MVVAR_H_
+#define _MVVAR_H_
+
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/vm.h>
+
+#include <dev/ofw/openfirm.h>
+
+#define MV_TYPE_PCI 0
+#define MV_TYPE_PCIE 1
+
+#define MV_MODE_ENDPOINT 0
+#define MV_MODE_ROOT 1
+
+struct gpio_config {
+ int gc_gpio; /* GPIO number */
+ uint32_t gc_flags; /* GPIO flags */
+ int gc_output; /* GPIO output value */
+};
+
+struct decode_win {
+ int target; /* Mbus unit ID */
+ int attr; /* Attributes of the target interface */
+ vm_paddr_t base; /* Physical base addr */
+ uint32_t size;
+ vm_paddr_t remap;
+};
+
+extern const struct gpio_config mv_gpio_config[];
+extern const struct decode_win *cpu_wins;
+extern const struct decode_win *idma_wins;
+extern const struct decode_win *xor_wins;
+extern int idma_wins_no;
+extern int xor_wins_no;
+
+/* Function prototypes */
+int mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt,
+ void (*hand)(void *), void *arg, int pin, int flags, void **cookiep);
+void mv_gpio_intr_mask(int pin);
+void mv_gpio_intr_unmask(int pin);
+void mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable);
+uint8_t mv_gpio_in(uint32_t pin);
+int platform_gpio_init(void);
+
+int soc_decode_win(void);
+void soc_id(uint32_t *dev, uint32_t *rev);
+void soc_dump_decode_win(void);
+uint32_t soc_power_ctrl_get(uint32_t mask);
+void soc_power_ctrl_set(uint32_t mask);
+uint64_t get_sar_value(void);
+
+int decode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size,
+ vm_paddr_t remap);
+int decode_win_overlap(int, int, const struct decode_win *);
+int win_cpu_can_remap(int);
+void decode_win_pcie_setup(u_long);
+
+void ddr_disable(int i);
+int ddr_is_active(int i);
+uint32_t ddr_base(int i);
+uint32_t ddr_size(int i);
+uint32_t ddr_attr(int i);
+uint32_t ddr_target(int i);
+
+uint32_t cpu_extra_feat(void);
+uint32_t get_tclk(void);
+uint32_t get_l2clk(void);
+uint32_t read_cpu_ctrl(uint32_t);
+void write_cpu_ctrl(uint32_t, uint32_t);
+
+#if defined(SOC_MV_ARMADAXP)
+uint32_t read_cpu_mp_clocks(uint32_t reg);
+void write_cpu_mp_clocks(uint32_t reg, uint32_t val);
+uint32_t read_cpu_misc(uint32_t reg);
+void write_cpu_misc(uint32_t reg, uint32_t val);
+#endif
+
+int mv_pcib_bar_win_set(device_t dev, uint32_t base, uint32_t size,
+ uint32_t remap, int winno, int busno);
+int mv_pcib_cpu_win_remap(device_t dev, uint32_t remap, uint32_t size);
+
+void mv_mask_endpoint_irq(uintptr_t nb, int unit);
+void mv_unmask_endpoint_irq(uintptr_t nb, int unit);
+
+int mv_drbl_get_next_irq(int dir, int unit);
+void mv_drbl_mask_all(int unit);
+void mv_drbl_mask_irq(uint32_t irq, int dir, int unit);
+void mv_drbl_unmask_irq(uint32_t irq, int dir, int unit);
+void mv_drbl_set_mask(uint32_t val, int dir, int unit);
+uint32_t mv_drbl_get_mask(int dir, int unit);
+void mv_drbl_set_cause(uint32_t val, int dir, int unit);
+uint32_t mv_drbl_get_cause(int dir, int unit);
+void mv_drbl_set_msg(uint32_t val, int mnr, int dir, int unit);
+uint32_t mv_drbl_get_msg(int mnr, int dir, int unit);
+
+int mv_msi_data(int irq, uint64_t *addr, uint32_t *data);
+
+struct arm_devmap_entry;
+
+int mv_pci_devmap(phandle_t, struct arm_devmap_entry *, vm_offset_t,
+ vm_offset_t);
+
+#endif /* _MVVAR_H_ */
Property changes on: trunk/sys/arm/mv/mvvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/mvwin.h
===================================================================
--- trunk/sys/arm/mv/mvwin.h (rev 0)
+++ trunk/sys/arm/mv/mvwin.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,391 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2007-2011 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/mv/mvwin.h 250295 2013-05-06 14:54:17Z gber $
+ */
+
+#ifndef _MVWIN_H_
+#define _MVWIN_H_
+
+/*
+ * Decode windows addresses.
+ *
+ * All decoding windows must be aligned to their size, which has to be
+ * a power of 2.
+ */
+
+/*
+ * SoC Integrated devices: 0xF1000000, 16 MB (VA == PA)
+ */
+
+/* SoC Regs */
+#define MV_PHYS_BASE 0xF1000000
+#define MV_SIZE (1024 * 1024) /* 1 MB */
+
+/* SRAM */
+#define MV_CESA_SRAM_BASE 0xF1100000
+
+/* AXI Regs */
+#ifdef SOC_MV_DOVE
+#define MV_AXI_PHYS_BASE 0xF1800000
+#define MV_AXI_BASE MV_AXI_PHYS_BASE
+#define MV_AXI_SIZE (16 * 1024 * 1024) /* 16 MB */
+#endif
+
+/*
+ * External devices: 0x80000000, 1 GB (VA == PA)
+ * Includes Device Bus, PCI and PCIE.
+ */
+#if defined(SOC_MV_ORION)
+#define MV_PCI_PORTS 2 /* 1x PCI + 1x PCIE */
+#elif defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_FREY)
+#define MV_PCI_PORTS 1 /* 1x PCIE */
+#elif defined(SOC_MV_DISCOVERY)
+#define MV_PCI_PORTS 8 /* 8x PCIE */
+#elif defined(SOC_MV_DOVE) || defined(SOC_MV_LOKIPLUS)
+#define MV_PCI_PORTS 2 /* 2x PCIE */
+#elif defined(SOC_MV_ARMADAXP)
+#define MV_PCI_PORTS 3 /* 3x PCIE */
+#else
+#error "MV_PCI_PORTS not configured !"
+#endif
+
+/* PCI/PCIE Memory */
+#define MV_PCI_MEM_PHYS_BASE 0x80000000
+#define MV_PCI_MEM_SIZE (512 * 1024 * 1024) /* 512 MB */
+#define MV_PCI_MEM_BASE MV_PCI_MEM_PHYS_BASE
+#define MV_PCI_MEM_SLICE_SIZE (MV_PCI_MEM_SIZE / MV_PCI_PORTS)
+#define MV_PCI_MEM_SLICE(n) (MV_PCI_MEM_BASE + ((n) * \
+ MV_PCI_MEM_SLICE_SIZE))
+/* PCI/PCIE I/O */
+#define MV_PCI_IO_PHYS_BASE 0xBF000000
+#define MV_PCI_IO_SIZE (16 * 1024 * 1024) /* 16 MB */
+#define MV_PCI_IO_BASE MV_PCI_IO_PHYS_BASE
+#define MV_PCI_IO_SLICE_SIZE (MV_PCI_IO_SIZE / MV_PCI_PORTS)
+#define MV_PCI_IO_SLICE(n) (MV_PCI_IO_BASE + ((n) * MV_PCI_IO_SLICE_SIZE))
+
+#if defined(SOC_MV_FREY)
+#define MV_PCI_VA_MEM_BASE MV_PCI_MEM_BASE
+#else
+#define MV_PCI_VA_MEM_BASE 0
+#endif
+#define MV_PCI_VA_IO_BASE 0
+
+/*
+ * Device Bus (VA == PA)
+ */
+#define MV_DEV_BOOT_BASE 0xF9300000
+#define MV_DEV_BOOT_SIZE (1024 * 1024) /* 1 MB */
+
+#define MV_DEV_CS0_BASE 0xF9400000
+#define MV_DEV_CS0_SIZE (1024 * 1024) /* 1 MB */
+
+#define MV_DEV_CS1_BASE 0xF9500000
+#define MV_DEV_CS1_SIZE (32 * 1024 * 1024) /* 32 MB */
+
+#define MV_DEV_CS2_BASE 0xFB500000
+#define MV_DEV_CS2_SIZE (1024 * 1024) /* 1 MB */
+
+
+/*
+ * Integrated SoC peripherals addresses
+ */
+#define MV_BASE MV_PHYS_BASE /* VA == PA mapping */
+#if defined(SOC_MV_DOVE)
+#define MV_DDR_CADR_BASE (MV_AXI_BASE + 0x100)
+#elif defined(SOC_MV_LOKIPLUS)
+#define MV_DDR_CADR_BASE (MV_BASE + 0xF1500)
+#elif defined(SOC_MV_ARMADAXP)
+#define MV_DDR_CADR_BASE (MV_BASE + 0x20180)
+#else
+#define MV_DDR_CADR_BASE (MV_BASE + 0x1500)
+#endif
+#define MV_MPP_BASE (MV_BASE + 0x10000)
+
+#if defined(SOC_MV_ARMADAXP)
+#define MV_MISC_BASE (MV_BASE + 0x18200)
+#define MV_MBUS_BRIDGE_BASE (MV_BASE + 0x20000)
+#define MV_INTREGS_BASE (MV_MBUS_BRIDGE_BASE + 0x80)
+#define MV_MP_CLOCKS_BASE (MV_MBUS_BRIDGE_BASE + 0x700)
+#define MV_CPU_CONTROL_BASE (MV_MBUS_BRIDGE_BASE + 0x1800)
+#elif !defined(SOC_MV_FREY)
+#define MV_MBUS_BRIDGE_BASE (MV_BASE + 0x20000)
+#define MV_INTREGS_BASE (MV_MBUS_BRIDGE_BASE + 0x80)
+#define MV_CPU_CONTROL_BASE (MV_MBUS_BRIDGE_BASE + 0x100)
+#else
+#define MV_CPU_CONTROL_BASE (MV_BASE + 0x10000)
+#endif
+
+#define MV_PCI_BASE (MV_BASE + 0x30000)
+#define MV_PCI_SIZE 0x2000
+
+#if defined(SOC_MV_FREY)
+#define MV_PCIE_BASE (MV_BASE + 0x8000)
+#else
+#define MV_PCIE_BASE (MV_BASE + 0x40000)
+#endif
+#define MV_PCIE_SIZE 0x2000
+
+#define MV_PCIE00_BASE (MV_PCIE_BASE + 0x00000)
+#define MV_PCIE01_BASE (MV_PCIE_BASE + 0x04000)
+#define MV_PCIE02_BASE (MV_PCIE_BASE + 0x08000)
+#define MV_PCIE03_BASE (MV_PCIE_BASE + 0x0C000)
+#define MV_PCIE10_BASE (MV_PCIE_BASE + 0x40000)
+#define MV_PCIE11_BASE (MV_PCIE_BASE + 0x44000)
+#define MV_PCIE12_BASE (MV_PCIE_BASE + 0x48000)
+#define MV_PCIE13_BASE (MV_PCIE_BASE + 0x4C000)
+
+#define MV_SDIO_BASE (MV_BASE + 0x90000)
+#define MV_SDIO_SIZE 0x10000
+
+/*
+ * Decode windows definitions and macros
+ */
+#if defined(SOC_MV_ARMADAXP)
+#define MV_WIN_CPU_CTRL(n) (((n) < 8) ? 0x10 * (n) : 0x90 + (0x8 * ((n) - 8)))
+#define MV_WIN_CPU_BASE(n) ((((n) < 8) ? 0x10 * (n) : 0x90 + (0x8 * ((n) - 8))) + 0x4)
+#define MV_WIN_CPU_REMAP_LO(n) (0x10 * (n) + 0x008)
+#define MV_WIN_CPU_REMAP_HI(n) (0x10 * (n) + 0x00C)
+#else
+#define MV_WIN_CPU_CTRL(n) (0x10 * (n) + (((n) < 8) ? 0x000 : 0x880))
+#define MV_WIN_CPU_BASE(n) (0x10 * (n) + (((n) < 8) ? 0x004 : 0x884))
+#define MV_WIN_CPU_REMAP_LO(n) (0x10 * (n) + (((n) < 8) ? 0x008 : 0x888))
+#define MV_WIN_CPU_REMAP_HI(n) (0x10 * (n) + (((n) < 8) ? 0x00C : 0x88C))
+#endif
+
+#if defined(SOC_MV_DISCOVERY)
+#define MV_WIN_CPU_MAX 14
+#elif defined(SOC_MV_ARMADAXP)
+#define MV_WIN_CPU_MAX 20
+#else
+#define MV_WIN_CPU_MAX 8
+#endif
+
+#define MV_WIN_CPU_ATTR_SHIFT 8
+#if defined(SOC_MV_LOKIPLUS)
+#define MV_WIN_CPU_TARGET_SHIFT 0
+#define MV_WIN_CPU_ENABLE_BIT (1 << 5)
+#else
+#define MV_WIN_CPU_TARGET_SHIFT 4
+#define MV_WIN_CPU_ENABLE_BIT 1
+#endif
+
+#if defined(SOC_MV_DOVE)
+#define MV_WIN_DDR_MAX 2
+#else /* SOC_MV_DOVE */
+#if defined(SOC_MV_LOKIPLUS)
+#define MV_WIN_DDR_BASE(n) (0xc * (n) + 0x4)
+#define MV_WIN_DDR_SIZE(n) (0xc * (n) + 0x0)
+#else /* SOC_MV_LOKIPLUS */
+#define MV_WIN_DDR_BASE(n) (0x8 * (n) + 0x0)
+#define MV_WIN_DDR_SIZE(n) (0x8 * (n) + 0x4)
+#endif /* SOC_MV_LOKIPLUS */
+#define MV_WIN_DDR_MAX 4
+#endif /* SOC_MV_DOVE */
+
+/*
+ * These values are valid only for peripherals decoding windows
+ * Bit in ATTR is zeroed according to CS bank number
+ */
+#define MV_WIN_DDR_ATTR(cs) (0x0F & ~(0x01 << (cs)))
+#define MV_WIN_DDR_TARGET 0x0
+
+#if defined(SOC_MV_DISCOVERY)
+#define MV_WIN_CESA_TARGET 9
+#define MV_WIN_CESA_ATTR(eng_sel) 1
+#elif defined(SOC_MV_ARMADAXP)
+#define MV_WIN_CESA_TARGET 9
+/*
+ * Bits [2:3] of cesa attribute select engine:
+ * eng_sel:
+ * 1: engine1
+ * 2: engine0
+ */
+#define MV_WIN_CESA_ATTR(eng_sel) (1 | ((eng_sel) << 2))
+#else
+#define MV_WIN_CESA_TARGET 3
+#define MV_WIN_CESA_ATTR(eng_sel) 0
+#endif
+
+#define MV_WIN_USB_CTRL(n) (0x10 * (n) + 0x320)
+#define MV_WIN_USB_BASE(n) (0x10 * (n) + 0x324)
+#define MV_WIN_USB_MAX 4
+
+#define MV_WIN_ETH_BASE(n) (0x8 * (n) + 0x200)
+#define MV_WIN_ETH_SIZE(n) (0x8 * (n) + 0x204)
+#define MV_WIN_ETH_REMAP(n) (0x4 * (n) + 0x280)
+#define MV_WIN_ETH_MAX 6
+
+#define MV_WIN_IDMA_BASE(n) (0x8 * (n) + 0xa00)
+#define MV_WIN_IDMA_SIZE(n) (0x8 * (n) + 0xa04)
+#define MV_WIN_IDMA_REMAP(n) (0x4 * (n) + 0xa60)
+#define MV_WIN_IDMA_CAP(n) (0x4 * (n) + 0xa70)
+#define MV_WIN_IDMA_MAX 8
+#define MV_IDMA_CHAN_MAX 4
+
+#define MV_WIN_XOR_BASE(n, m) (0x4 * (n) + 0xa50 + (m) * 0x100)
+#define MV_WIN_XOR_SIZE(n, m) (0x4 * (n) + 0xa70 + (m) * 0x100)
+#define MV_WIN_XOR_REMAP(n, m) (0x4 * (n) + 0xa90 + (m) * 0x100)
+#define MV_WIN_XOR_CTRL(n, m) (0x4 * (n) + 0xa40 + (m) * 0x100)
+#define MV_WIN_XOR_OVERR(n, m) (0x4 * (n) + 0xaa0 + (m) * 0x100)
+#define MV_WIN_XOR_MAX 8
+#define MV_XOR_CHAN_MAX 2
+#define MV_XOR_NON_REMAP 4
+
+#if defined(SOC_MV_DISCOVERY) || defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DOVE)
+#define MV_WIN_PCIE_TARGET(n) 4
+#define MV_WIN_PCIE_MEM_ATTR(n) 0xE8
+#define MV_WIN_PCIE_IO_ATTR(n) 0xE0
+#elif defined(SOC_MV_ARMADAXP)
+#define MV_WIN_PCIE_TARGET(n) (4 + (4 * ((n) % 2)))
+#define MV_WIN_PCIE_MEM_ATTR(n) (0xE8 + (0x10 * ((n) / 2)))
+#define MV_WIN_PCIE_IO_ATTR(n) (0xE0 + (0x10 * ((n) / 2)))
+#elif defined(SOC_MV_ORION)
+#define MV_WIN_PCIE_TARGET(n) 4
+#define MV_WIN_PCIE_MEM_ATTR(n) 0x59
+#define MV_WIN_PCIE_IO_ATTR(n) 0x51
+#elif defined(SOC_MV_LOKIPLUS)
+#define MV_WIN_PCIE_TARGET(n) (3 + (n))
+#define MV_WIN_PCIE_MEM_ATTR(n) 0x59
+#define MV_WIN_PCIE_IO_ATTR(n) 0x51
+#endif
+
+#define MV_WIN_PCI_TARGET 3
+#define MV_WIN_PCI_MEM_ATTR 0x59
+#define MV_WIN_PCI_IO_ATTR 0x51
+
+#define MV_WIN_PCIE_CTRL(n) (0x10 * (((n) < 5) ? (n) : \
+ (n) + 1) + 0x1820)
+#define MV_WIN_PCIE_BASE(n) (0x10 * (((n) < 5) ? (n) : \
+ (n) + 1) + 0x1824)
+#define MV_WIN_PCIE_REMAP(n) (0x10 * (((n) < 5) ? (n) : \
+ (n) + 1) + 0x182C)
+#define MV_WIN_PCIE_MAX 6
+
+#define MV_PCIE_BAR_CTRL(n) (0x04 * (n) + 0x1800)
+#define MV_PCIE_BAR_BASE(n) (0x08 * ((n) < 3 ? (n) : 4) + 0x0010)
+#define MV_PCIE_BAR_BASE_H(n) (0x08 * (n) + 0x0014)
+#define MV_PCIE_BAR_MAX 4
+#define MV_PCIE_BAR_64BIT (0x4)
+#define MV_PCIE_BAR_PREFETCH_EN (0x8)
+
+#define MV_PCIE_CONTROL (0x1a00)
+#define MV_PCIE_ROOT_CMPLX (1 << 1)
+
+#define MV_WIN_SATA_CTRL(n) (0x10 * (n) + 0x30)
+#define MV_WIN_SATA_BASE(n) (0x10 * (n) + 0x34)
+#define MV_WIN_SATA_MAX 4
+
+#define WIN_REG_IDX_RD(pre,reg,off,base) \
+ static __inline uint32_t \
+ pre ## _ ## reg ## _read(int i) \
+ { \
+ return (bus_space_read_4(fdtbus_bs_tag, base, off(i))); \
+ }
+
+#define WIN_REG_IDX_RD2(pre,reg,off,base) \
+ static __inline uint32_t \
+ pre ## _ ## reg ## _read(int i, int j) \
+ { \
+ return (bus_space_read_4(fdtbus_bs_tag, base, off(i, j))); \
+ } \
+
+#define WIN_REG_BASE_IDX_RD(pre,reg,off) \
+ static __inline uint32_t \
+ pre ## _ ## reg ## _read(uint32_t base, int i) \
+ { \
+ return (bus_space_read_4(fdtbus_bs_tag, base, off(i))); \
+ }
+
+#define WIN_REG_BASE_IDX_RD2(pre,reg,off) \
+ static __inline uint32_t \
+ pre ## _ ## reg ## _read(uint32_t base, int i, int j) \
+ { \
+ return (bus_space_read_4(fdtbus_bs_tag, base, off(i, j))); \
+ }
+
+#define WIN_REG_IDX_WR(pre,reg,off,base) \
+ static __inline void \
+ pre ## _ ## reg ## _write(int i, uint32_t val) \
+ { \
+ bus_space_write_4(fdtbus_bs_tag, base, off(i), val); \
+ }
+
+#define WIN_REG_IDX_WR2(pre,reg,off,base) \
+ static __inline void \
+ pre ## _ ## reg ## _write(int i, int j, uint32_t val) \
+ { \
+ bus_space_write_4(fdtbus_bs_tag, base, off(i, j), val); \
+ }
+
+#define WIN_REG_BASE_IDX_WR(pre,reg,off) \
+ static __inline void \
+ pre ## _ ## reg ## _write(uint32_t base, int i, uint32_t val) \
+ { \
+ bus_space_write_4(fdtbus_bs_tag, base, off(i), val); \
+ }
+
+#define WIN_REG_BASE_IDX_WR2(pre,reg,off) \
+ static __inline void \
+ pre ## _ ## reg ## _write(uint32_t base, int i, int j, uint32_t val) \
+ { \
+ bus_space_write_4(fdtbus_bs_tag, base, off(i, j), val); \
+ }
+
+#define WIN_REG_RD(pre,reg,off,base) \
+ static __inline uint32_t \
+ pre ## _ ## reg ## _read(void) \
+ { \
+ return (bus_space_read_4(fdtbus_bs_tag, base, off)); \
+ }
+
+#define WIN_REG_BASE_RD(pre,reg,off) \
+ static __inline uint32_t \
+ pre ## _ ## reg ## _read(uint32_t base) \
+ { \
+ return (bus_space_read_4(fdtbus_bs_tag, base, off)); \
+ }
+
+#define WIN_REG_WR(pre,reg,off,base) \
+ static __inline void \
+ pre ## _ ## reg ## _write(uint32_t val) \
+ { \
+ bus_space_write_4(fdtbus_bs_tag, base, off, val); \
+ }
+
+#define WIN_REG_BASE_WR(pre,reg,off) \
+ static __inline void \
+ pre ## _ ## reg ## _write(uint32_t base, uint32_t val) \
+ { \
+ bus_space_write_4(fdtbus_bs_tag, base, off, val); \
+ }
+
+#endif /* _MVWIN_H_ */
Property changes on: trunk/sys/arm/mv/mvwin.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/orion/db88f5xxx.c
===================================================================
--- trunk/sys/arm/mv/orion/db88f5xxx.c (rev 0)
+++ trunk/sys/arm/mv/orion/db88f5xxx.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,187 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/orion/db88f5xxx.c 266386 2014-05-18 00:32:35Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/pte.h>
+#include <machine/vmparam.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+#include <arm/mv/mvwin.h>
+
+/*
+ * Virtual address space layout:
+ * -----------------------------
+ * 0x0000_0000 - 0xbfff_ffff : user process
+ *
+ * 0xc040_0000 - virtual_avail : kernel reserved (text, data, page tables
+ * : structures, ARM stacks etc.)
+ * virtual_avail - 0xefff_ffff : KVA (virtual_avail is typically < 0xc0a0_0000)
+ * 0xf000_0000 - 0xf0ff_ffff : no-cache allocation area (16MB)
+ * 0xf100_0000 - 0xf10f_ffff : SoC integrated devices registers range (1MB)
+ * 0xf110_0000 - 0xf11f_ffff : PCI-Express I/O space (1MB)
+ * 0xf120_0000 - 0xf12f_ffff : PCI I/O space (1MB)
+ * 0xf130_0000 - 0xf52f_ffff : PCI-Express memory space (64MB)
+ * 0xf530_0000 - 0xf92f_ffff : PCI memory space (64MB)
+ * 0xf930_0000 - 0xfffe_ffff : unused (~108MB)
+ * 0xffff_0000 - 0xffff_0fff : 'high' vectors page (4KB)
+ * 0xffff_1000 - 0xffff_1fff : ARM_TP_ADDRESS/RAS page (4KB)
+ * 0xffff_2000 - 0xffff_ffff : unused (~55KB)
+ */
+
+
+#if 0
+int platform_pci_get_irq(u_int bus, u_int slot, u_int func, u_int pin);
+
+/* Static device mappings. */
+const struct pmap_devmap pmap_devmap[] = {
+ /*
+ * Map the on-board devices VA == PA so that we can access them
+ * with the MMU on or off.
+ */
+ { /* SoC integrated peripherals registers range */
+ MV_BASE,
+ MV_PHYS_BASE,
+ MV_SIZE,
+ VM_PROT_READ | VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ { /* PCIE I/O */
+ MV_PCIE_IO_BASE,
+ MV_PCIE_IO_PHYS_BASE,
+ MV_PCIE_IO_SIZE,
+ VM_PROT_READ | VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ { /* PCIE Memory */
+ MV_PCIE_MEM_BASE,
+ MV_PCIE_MEM_PHYS_BASE,
+ MV_PCIE_MEM_SIZE,
+ VM_PROT_READ | VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ { /* PCI I/O */
+ MV_PCI_IO_BASE,
+ MV_PCI_IO_PHYS_BASE,
+ MV_PCI_IO_SIZE,
+ VM_PROT_READ | VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ { /* PCI Memory */
+ MV_PCI_MEM_BASE,
+ MV_PCI_MEM_PHYS_BASE,
+ MV_PCI_MEM_SIZE,
+ VM_PROT_READ | VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ { /* 7-seg LED */
+ MV_DEV_CS0_BASE,
+ MV_DEV_CS0_PHYS_BASE,
+ MV_DEV_CS0_SIZE,
+ VM_PROT_READ | VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ { 0, 0, 0, 0, 0, }
+};
+
+/*
+ * The pci_irq_map table consists of 3 columns:
+ * - PCI slot number (less than zero means ANY).
+ * - PCI IRQ pin (less than zero means ANY).
+ * - PCI IRQ (less than zero marks end of table).
+ *
+ * IRQ number from the first matching entry is used to configure PCI device
+ */
+
+/* PCI IRQ Map for DB-88F5281 */
+const struct obio_pci_irq_map pci_irq_map[] = {
+ { 7, -1, GPIO2IRQ(12) },
+ { 8, -1, GPIO2IRQ(13) },
+ { 9, -1, GPIO2IRQ(13) },
+ { -1, -1, -1 }
+};
+
+/* PCI IRQ Map for DB-88F5182 */
+const struct obio_pci_irq_map pci_irq_map[] = {
+ { 7, -1, GPIO2IRQ(0) },
+ { 8, -1, GPIO2IRQ(1) },
+ { 9, -1, GPIO2IRQ(1) },
+ { -1, -1, -1 }
+};
+#endif
+
+#if 0
+/*
+ * mv_gpio_config row structure:
+ * <GPIO number>, <GPIO flags>, <GPIO mode>
+ *
+ * - GPIO pin number (less than zero marks end of table)
+ * - GPIO flags:
+ * MV_GPIO_BLINK
+ * MV_GPIO_POLAR_LOW
+ * MV_GPIO_EDGE
+ * MV_GPIO_LEVEL
+ * - GPIO mode:
+ * 1 - Output, set to HIGH.
+ * 0 - Output, set to LOW.
+ * -1 - Input.
+ */
+
+/* GPIO Configuration for DB-88F5281 */
+const struct gpio_config mv_gpio_config[] = {
+ { 12, MV_GPIO_POLAR_LOW | MV_GPIO_LEVEL, -1 },
+ { 13, MV_GPIO_POLAR_LOW | MV_GPIO_LEVEL, -1 },
+ { -1, -1, -1 }
+};
+
+#if 0
+/* GPIO Configuration for DB-88F5182 */
+const struct gpio_config mv_gpio_config[] = {
+ { 0, MV_GPIO_POLAR_LOW | MV_GPIO_LEVEL, -1 },
+ { 1, MV_GPIO_POLAR_LOW | MV_GPIO_LEVEL, -1 },
+ { -1, -1, -1 }
+};
+#endif
+
+#endif
Property changes on: trunk/sys/arm/mv/orion/db88f5xxx.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/orion/files.db88f5xxx
===================================================================
--- trunk/sys/arm/mv/orion/files.db88f5xxx (rev 0)
+++ trunk/sys/arm/mv/orion/files.db88f5xxx 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+# $FreeBSD: stable/10/sys/arm/mv/orion/files.db88f5xxx 239277 2012-08-15 05:15:49Z gonzo $
+
+arm/mv/ic.c standard
+arm/mv/orion/orion.c standard
+arm/mv/orion/db88f5xxx.c standard
Property changes on: trunk/sys/arm/mv/orion/files.db88f5xxx
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/orion/files.ts7800
===================================================================
--- trunk/sys/arm/mv/orion/files.ts7800 (rev 0)
+++ trunk/sys/arm/mv/orion/files.ts7800 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+# $FreeBSD: stable/10/sys/arm/mv/orion/files.ts7800 239277 2012-08-15 05:15:49Z gonzo $
+
+arm/mv/ic.c standard
+arm/mv/orion/orion.c standard
+
Property changes on: trunk/sys/arm/mv/orion/files.ts7800
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/orion/orion.c
===================================================================
--- trunk/sys/arm/mv/orion/orion.c (rev 0)
+++ trunk/sys/arm/mv/orion/orion.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,103 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/orion/orion.c 209131 2010-06-13 13:28:53Z raj $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+#include <arm/mv/mvwin.h>
+
+#if 0
+extern const struct obio_pci_irq_map pci_irq_map[];
+const struct obio_pci mv_pci_info[] = {
+ { MV_TYPE_PCIE,
+ MV_PCIE_BASE, MV_PCIE_SIZE,
+ MV_PCIE_IO_BASE, MV_PCIE_IO_SIZE, 4, 0x51,
+ MV_PCIE_MEM_BASE, MV_PCIE_MEM_SIZE, 4, 0x59,
+ NULL, MV_INT_PEX0
+ },
+
+ { MV_TYPE_PCI,
+ MV_PCI_BASE, MV_PCI_SIZE,
+ MV_PCI_IO_BASE, MV_PCI_IO_SIZE, 3, 0x51,
+ MV_PCI_MEM_BASE, MV_PCI_MEM_SIZE, 3, 0x59,
+ pci_irq_map, -1
+ },
+
+ { 0, 0, 0 }
+};
+#endif
+
+struct resource_spec mv_gpio_res[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { -1, 0 }
+};
+
+const struct decode_win idma_win_tbl[] = {
+ { 0 },
+};
+const struct decode_win *idma_wins = idma_win_tbl;
+int idma_wins_no = 0;
+
+uint32_t
+get_tclk(void)
+{
+ uint32_t sar;
+
+ /*
+ * On Orion TCLK is can be configured to 150 MHz or 166 MHz.
+ * Current setting is read from Sample At Reset register.
+ */
+ /* XXX MPP addr should be retrieved from the DT */
+ sar = bus_space_read_4(fdtbus_bs_tag, MV_MPP_BASE, SAMPLE_AT_RESET);
+ sar = (sar & TCLK_MASK) >> TCLK_SHIFT;
+ switch (sar) {
+ case 1:
+ return (TCLK_150MHZ);
+ case 2:
+ return (TCLK_166MHZ);
+ default:
+ panic("Unknown TCLK settings!");
+ }
+}
Property changes on: trunk/sys/arm/mv/orion/orion.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/orion/std.db88f5xxx
===================================================================
--- trunk/sys/arm/mv/orion/std.db88f5xxx (rev 0)
+++ trunk/sys/arm/mv/orion/std.db88f5xxx 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,11 @@
+# $FreeBSD: stable/10/sys/arm/mv/orion/std.db88f5xxx 266110 2014-05-15 02:41:23Z ian $
+
+include "../mv/std.mv"
+files "../mv/orion/files.db88f5xxx"
+
+makeoptions KERNPHYSADDR=0x00900000
+makeoptions KERNVIRTADDR=0xc0900000
+
+options KERNPHYSADDR=0x00900000
+options KERNVIRTADDR=0xc0900000
+options PHYSADDR=0x00000000
Property changes on: trunk/sys/arm/mv/orion/std.db88f5xxx
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/orion/std.ts7800
===================================================================
--- trunk/sys/arm/mv/orion/std.ts7800 (rev 0)
+++ trunk/sys/arm/mv/orion/std.ts7800 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,14 @@
+# $FreeBSD: stable/10/sys/arm/mv/orion/std.ts7800 266110 2014-05-15 02:41:23Z ian $
+
+include "../mv/std.mv"
+files "../mv/orion/files.ts7800"
+
+makeoptions KERNPHYSADDR=0x00900000
+makeoptions KERNVIRTADDR=0xc0900000
+
+options KERNPHYSADDR=0x00900000
+options KERNVIRTADDR=0xc0900000
+options PHYSADDR=0x00000000
+options LOADERRAMADDR=0x00000000
+options FLASHADDR=0x00008000
+
Property changes on: trunk/sys/arm/mv/orion/std.ts7800
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/rtc.c
===================================================================
--- trunk/sys/arm/mv/rtc.c (rev 0)
+++ trunk/sys/arm/mv/rtc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,194 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/rtc.c 266152 2014-05-15 16:11:06Z ian $");
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/time.h>
+#include <sys/clock.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clock_if.h"
+
+#define MV_RTC_TIME_REG 0x00
+#define MV_RTC_DATE_REG 0x04
+#define YEAR_BASE 2000
+
+struct mv_rtc_softc {
+ device_t dev;
+ struct resource *res[1];
+};
+
+static struct resource_spec res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int mv_rtc_probe(device_t dev);
+static int mv_rtc_attach(device_t dev);
+
+static int mv_rtc_gettime(device_t dev, struct timespec *ts);
+static int mv_rtc_settime(device_t dev, struct timespec *ts);
+
+static uint32_t mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off);
+static int mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off,
+ uint32_t val);
+
+static device_method_t mv_rtc_methods[] = {
+ DEVMETHOD(device_probe, mv_rtc_probe),
+ DEVMETHOD(device_attach, mv_rtc_attach),
+
+ DEVMETHOD(clock_gettime, mv_rtc_gettime),
+ DEVMETHOD(clock_settime, mv_rtc_settime),
+
+ { 0, 0 },
+};
+
+static driver_t mv_rtc_driver = {
+ "rtc",
+ mv_rtc_methods,
+ sizeof(struct mv_rtc_softc),
+};
+static devclass_t mv_rtc_devclass;
+
+DRIVER_MODULE(mv_rtc, simplebus, mv_rtc_driver, mv_rtc_devclass, 0, 0);
+
+static int
+mv_rtc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "mrvl,rtc"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell Integrated RTC");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+mv_rtc_attach(device_t dev)
+{
+ struct mv_rtc_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ clock_register(dev, 1000000);
+
+ if (bus_alloc_resources(dev, res_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+mv_rtc_gettime(device_t dev, struct timespec *ts)
+{
+ struct clocktime ct;
+ struct mv_rtc_softc *sc;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
+
+ val = mv_rtc_reg_read(sc, MV_RTC_TIME_REG);
+
+ ct.nsec = 0;
+ ct.sec = FROMBCD(val & 0x7f);
+ ct.min = FROMBCD((val & 0x7f00) >> 8);
+ ct.hour = FROMBCD((val & 0x3f0000) >> 16);
+ ct.dow = FROMBCD((val & 0x7000000) >> 24) - 1;
+
+ val = mv_rtc_reg_read(sc, MV_RTC_DATE_REG);
+
+ ct.day = FROMBCD(val & 0x7f);
+ ct.mon = FROMBCD((val & 0x1f00) >> 8);
+ ct.year = YEAR_BASE + FROMBCD((val & 0xff0000) >> 16);
+
+ return (clock_ct_to_ts(&ct, ts));
+}
+
+static int
+mv_rtc_settime(device_t dev, struct timespec *ts)
+{
+ struct clocktime ct;
+ struct mv_rtc_softc *sc;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
+
+ /* Resolution: 1 sec */
+ if (ts->tv_nsec >= 500000000)
+ ts->tv_sec++;
+ ts->tv_nsec = 0;
+ clock_ts_to_ct(ts, &ct);
+
+ val = TOBCD(ct.sec) | (TOBCD(ct.min) << 8) |
+ (TOBCD(ct.hour) << 16) | (TOBCD( ct.dow + 1) << 24);
+ mv_rtc_reg_write(sc, MV_RTC_TIME_REG, val);
+
+ val = TOBCD(ct.day) | (TOBCD(ct.mon) << 8) |
+ (TOBCD(ct.year - YEAR_BASE) << 16);
+ mv_rtc_reg_write(sc, MV_RTC_DATE_REG, val);
+
+ return (0);
+}
+
+static uint32_t
+mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->res[0], off));
+}
+
+static int
+mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->res[0], off, val);
+ return (0);
+}
Property changes on: trunk/sys/arm/mv/rtc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/std-pj4b.mv
===================================================================
--- trunk/sys/arm/mv/std-pj4b.mv (rev 0)
+++ trunk/sys/arm/mv/std-pj4b.mv 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,12 @@
+# $FreeBSD: stable/10/sys/arm/mv/std-pj4b.mv 294690 2016-01-24 22:17:05Z ian $
+
+files "../mv/files.mv"
+cpu CPU_MV_PJ4B
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+
+# This was originally defined as "(KERNBASE-(1024*1024*1024))" but that
+# (in opt_global.h) clashed with the value emitted by genassym which
+# reduces the original macro text to its numeric value. The only way
+# to avoid that is to define it here as the numeric value genassym emits.
+options VM_MAXUSER_ADDRESS="0x80000000"
Property changes on: trunk/sys/arm/mv/std-pj4b.mv
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/std.mv
===================================================================
--- trunk/sys/arm/mv/std.mv (rev 0)
+++ trunk/sys/arm/mv/std.mv 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,7 @@
+# $FreeBSD: stable/10/sys/arm/mv/std.mv 239362 2012-08-18 05:48:19Z andrew $
+
+files "../mv/files.mv"
+cpu CPU_ARM9E
+machine arm
+makeoptions CONF_CFLAGS="-march=armv5te"
+options FREEBSD_BOOT_LOADER
Property changes on: trunk/sys/arm/mv/std.mv
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/mv/timer.c
===================================================================
--- trunk/sys/arm/mv/timer.c (rev 0)
+++ trunk/sys/arm/mv/timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,448 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice.
+ * Copyright (C) 2007-2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Adapted to Marvell SoC by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_timer.c, rev 1
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/timer.c 266207 2014-05-16 02:21:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#define INITIAL_TIMECOUNTER (0xffffffff)
+#define MAX_WATCHDOG_TICKS (0xffffffff)
+
+#if defined(SOC_MV_ARMADAXP)
+#define MV_CLOCK_SRC 25000000 /* Timers' 25MHz mode */
+#else
+#define MV_CLOCK_SRC get_tclk()
+#endif
+
+struct mv_timer_softc {
+ struct resource * timer_res[2];
+ bus_space_tag_t timer_bst;
+ bus_space_handle_t timer_bsh;
+ struct mtx timer_mtx;
+ struct eventtimer et;
+};
+
+static struct resource_spec mv_timer_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct mv_timer_softc *timer_softc = NULL;
+static int timers_initialized = 0;
+
+static int mv_timer_probe(device_t);
+static int mv_timer_attach(device_t);
+
+static int mv_hardclock(void *);
+static unsigned mv_timer_get_timecount(struct timecounter *);
+
+static uint32_t mv_get_timer_control(void);
+static void mv_set_timer_control(uint32_t);
+static uint32_t mv_get_timer(uint32_t);
+static void mv_set_timer(uint32_t, uint32_t);
+static void mv_set_timer_rel(uint32_t, uint32_t);
+static void mv_watchdog_enable(void);
+static void mv_watchdog_disable(void);
+static void mv_watchdog_event(void *, unsigned int, int *);
+static int mv_timer_start(struct eventtimer *et,
+ sbintime_t first, sbintime_t period);
+static int mv_timer_stop(struct eventtimer *et);
+static void mv_setup_timers(void);
+
+static struct timecounter mv_timer_timecounter = {
+ .tc_get_timecount = mv_timer_get_timecount,
+ .tc_name = "CPUTimer1",
+ .tc_frequency = 0, /* This is assigned on the fly in the init sequence */
+ .tc_counter_mask = ~0u,
+ .tc_quality = 1000,
+};
+
+static int
+mv_timer_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "mrvl,timer"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell CPU Timer");
+ return (0);
+}
+
+static int
+mv_timer_attach(device_t dev)
+{
+ int error;
+ void *ihl;
+ struct mv_timer_softc *sc;
+#if !defined(SOC_MV_ARMADAXP)
+ uint32_t irq_cause, irq_mask;
+#endif
+
+ if (timer_softc != NULL)
+ return (ENXIO);
+
+ sc = (struct mv_timer_softc *)device_get_softc(dev);
+ timer_softc = sc;
+
+ error = bus_alloc_resources(dev, mv_timer_spec, sc->timer_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->timer_bst = rman_get_bustag(sc->timer_res[0]);
+ sc->timer_bsh = rman_get_bushandle(sc->timer_res[0]);
+
+ mtx_init(&timer_softc->timer_mtx, "watchdog", NULL, MTX_DEF);
+ mv_watchdog_disable();
+ EVENTHANDLER_REGISTER(watchdog_list, mv_watchdog_event, sc, 0);
+
+ if (bus_setup_intr(dev, sc->timer_res[1], INTR_TYPE_CLK,
+ mv_hardclock, NULL, sc, &ihl) != 0) {
+ bus_release_resources(dev, mv_timer_spec, sc->timer_res);
+ device_printf(dev, "Could not setup interrupt.\n");
+ return (ENXIO);
+ }
+
+ mv_setup_timers();
+#if !defined(SOC_MV_ARMADAXP)
+ irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
+ irq_cause &= IRQ_TIMER0_CLR;
+
+ write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
+ irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
+ irq_mask |= IRQ_TIMER0_MASK;
+ irq_mask &= ~IRQ_TIMER1_MASK;
+ write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
+#endif
+ sc->et.et_name = "CPUTimer0";
+ sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
+ sc->et.et_quality = 1000;
+
+ sc->et.et_frequency = MV_CLOCK_SRC;
+ sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
+ sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
+ sc->et.et_start = mv_timer_start;
+ sc->et.et_stop = mv_timer_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+ mv_timer_timecounter.tc_frequency = MV_CLOCK_SRC;
+ tc_init(&mv_timer_timecounter);
+
+ return (0);
+}
+
+static int
+mv_hardclock(void *arg)
+{
+ struct mv_timer_softc *sc;
+ uint32_t irq_cause;
+
+ irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
+ irq_cause &= IRQ_TIMER0_CLR;
+ write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
+
+ sc = (struct mv_timer_softc *)arg;
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+
+ return (FILTER_HANDLED);
+}
+
+static device_method_t mv_timer_methods[] = {
+ DEVMETHOD(device_probe, mv_timer_probe),
+ DEVMETHOD(device_attach, mv_timer_attach),
+
+ { 0, 0 }
+};
+
+static driver_t mv_timer_driver = {
+ "timer",
+ mv_timer_methods,
+ sizeof(struct mv_timer_softc),
+};
+
+static devclass_t mv_timer_devclass;
+
+DRIVER_MODULE(timer, simplebus, mv_timer_driver, mv_timer_devclass, 0, 0);
+
+static unsigned
+mv_timer_get_timecount(struct timecounter *tc)
+{
+
+ return (INITIAL_TIMECOUNTER - mv_get_timer(1));
+}
+
+void
+DELAY(int usec)
+{
+ uint32_t val, val_temp;
+ int32_t nticks;
+
+ if (!timers_initialized) {
+ for (; usec > 0; usec--)
+ for (val = 100; val > 0; val--)
+ __asm __volatile("nop" ::: "memory");
+ return;
+ }
+
+ val = mv_get_timer(1);
+ nticks = ((MV_CLOCK_SRC / 1000000 + 1) * usec);
+
+ while (nticks > 0) {
+ val_temp = mv_get_timer(1);
+ if (val > val_temp)
+ nticks -= (val - val_temp);
+ else
+ nticks -= (val + (INITIAL_TIMECOUNTER - val_temp));
+
+ val = val_temp;
+ }
+}
+
+static uint32_t
+mv_get_timer_control(void)
+{
+
+ return (bus_space_read_4(timer_softc->timer_bst,
+ timer_softc->timer_bsh, CPU_TIMER_CONTROL));
+}
+
+static void
+mv_set_timer_control(uint32_t val)
+{
+
+ bus_space_write_4(timer_softc->timer_bst,
+ timer_softc->timer_bsh, CPU_TIMER_CONTROL, val);
+}
+
+static uint32_t
+mv_get_timer(uint32_t timer)
+{
+
+ return (bus_space_read_4(timer_softc->timer_bst,
+ timer_softc->timer_bsh, CPU_TIMER0 + timer * 0x8));
+}
+
+static void
+mv_set_timer(uint32_t timer, uint32_t val)
+{
+
+ bus_space_write_4(timer_softc->timer_bst,
+ timer_softc->timer_bsh, CPU_TIMER0 + timer * 0x8, val);
+}
+
+static void
+mv_set_timer_rel(uint32_t timer, uint32_t val)
+{
+
+ bus_space_write_4(timer_softc->timer_bst,
+ timer_softc->timer_bsh, CPU_TIMER0_REL + timer * 0x8, val);
+}
+
+static void
+mv_watchdog_enable(void)
+{
+ uint32_t val, irq_cause;
+#if !defined(SOC_MV_ARMADAXP)
+ uint32_t irq_mask;
+#endif
+
+ irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
+ irq_cause &= IRQ_TIMER_WD_CLR;
+ write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
+
+#if defined(SOC_MV_ARMADAXP)
+ val = read_cpu_mp_clocks(WD_RSTOUTn_MASK);
+ val |= (WD_GLOBAL_MASK | WD_CPU0_MASK);
+ write_cpu_mp_clocks(WD_RSTOUTn_MASK, val);
+#else
+ irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
+ irq_mask |= IRQ_TIMER_WD_MASK;
+ write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
+
+ val = read_cpu_ctrl(RSTOUTn_MASK);
+ val |= WD_RST_OUT_EN;
+ write_cpu_ctrl(RSTOUTn_MASK, val);
+#endif
+
+ val = mv_get_timer_control();
+ val |= CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO;
+#if defined(SOC_MV_ARMADAXP)
+ val |= CPU_TIMER_WD_25MHZ_EN;
+#endif
+ mv_set_timer_control(val);
+}
+
+static void
+mv_watchdog_disable(void)
+{
+ uint32_t val, irq_cause;
+#if !defined(SOC_MV_ARMADAXP)
+ uint32_t irq_mask;
+#endif
+
+ val = mv_get_timer_control();
+ val &= ~(CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO);
+ mv_set_timer_control(val);
+
+#if defined(SOC_MV_ARMADAXP)
+ val = read_cpu_mp_clocks(WD_RSTOUTn_MASK);
+ val &= ~(WD_GLOBAL_MASK | WD_CPU0_MASK);
+ write_cpu_mp_clocks(WD_RSTOUTn_MASK, val);
+#else
+ val = read_cpu_ctrl(RSTOUTn_MASK);
+ val &= ~WD_RST_OUT_EN;
+ write_cpu_ctrl(RSTOUTn_MASK, val);
+
+ irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
+ irq_mask &= ~(IRQ_TIMER_WD_MASK);
+ write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
+#endif
+
+ irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
+ irq_cause &= IRQ_TIMER_WD_CLR;
+ write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
+}
+
+
+/*
+ * Watchdog event handler.
+ */
+static void
+mv_watchdog_event(void *arg, unsigned int cmd, int *error)
+{
+ uint64_t ns;
+ uint64_t ticks;
+
+ mtx_lock(&timer_softc->timer_mtx);
+ if (cmd == 0)
+ mv_watchdog_disable();
+ else {
+ /*
+ * Watchdog timeout is in nanosecs, calculation according to
+ * watchdog(9)
+ */
+ ns = (uint64_t)1 << (cmd & WD_INTERVAL);
+ ticks = (uint64_t)(ns * MV_CLOCK_SRC) / 1000000000;
+ if (ticks > MAX_WATCHDOG_TICKS)
+ mv_watchdog_disable();
+ else {
+ /* Timer 2 is the watchdog */
+ mv_set_timer(2, ticks);
+ mv_watchdog_enable();
+ *error = 0;
+ }
+ }
+ mtx_unlock(&timer_softc->timer_mtx);
+}
+
+static int
+mv_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct mv_timer_softc *sc;
+ uint32_t val, val1;
+
+ /* Calculate dividers. */
+ sc = (struct mv_timer_softc *)et->et_priv;
+ if (period != 0)
+ val = ((uint32_t)sc->et.et_frequency * period) >> 32;
+ else
+ val = 0;
+ if (first != 0)
+ val1 = ((uint32_t)sc->et.et_frequency * first) >> 32;
+ else
+ val1 = val;
+
+ /* Apply configuration. */
+ mv_set_timer_rel(0, val);
+ mv_set_timer(0, val1);
+ val = mv_get_timer_control();
+ val |= CPU_TIMER0_EN;
+ if (period != 0)
+ val |= CPU_TIMER0_AUTO;
+ else
+ val &= ~CPU_TIMER0_AUTO;
+ mv_set_timer_control(val);
+ return (0);
+}
+
+static int
+mv_timer_stop(struct eventtimer *et)
+{
+ uint32_t val;
+
+ val = mv_get_timer_control();
+ val &= ~(CPU_TIMER0_EN | CPU_TIMER0_AUTO);
+ mv_set_timer_control(val);
+ return (0);
+}
+
+static void
+mv_setup_timers(void)
+{
+ uint32_t val;
+
+ mv_set_timer_rel(1, INITIAL_TIMECOUNTER);
+ mv_set_timer(1, INITIAL_TIMECOUNTER);
+ val = mv_get_timer_control();
+ val &= ~(CPU_TIMER0_EN | CPU_TIMER0_AUTO);
+ val |= CPU_TIMER1_EN | CPU_TIMER1_AUTO;
+#if defined(SOC_MV_ARMADAXP)
+ /* Enable 25MHz mode */
+ val |= CPU_TIMER0_25MHZ_EN | CPU_TIMER1_25MHZ_EN;
+#endif
+ mv_set_timer_control(val);
+ timers_initialized = 1;
+}
Property changes on: trunk/sys/arm/mv/timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/mv/twsi.c
===================================================================
--- trunk/sys/arm/mv/twsi.c (rev 0)
+++ trunk/sys/arm/mv/twsi.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,642 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell
+ * SoCs. Supports master operation only, and works in polling mode.
+ *
+ * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software
+ * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices".
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/mv/twsi.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/_inttypes.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+
+#include "iicbus_if.h"
+
+#define MV_TWSI_NAME "twsi"
+#define IICBUS_DEVNAME "iicbus"
+
+#define TWSI_SLAVE_ADDR 0x00
+#define TWSI_EXT_SLAVE_ADDR 0x10
+#define TWSI_DATA 0x04
+
+#define TWSI_CONTROL 0x08
+#define TWSI_CONTROL_ACK (1 << 2)
+#define TWSI_CONTROL_IFLG (1 << 3)
+#define TWSI_CONTROL_STOP (1 << 4)
+#define TWSI_CONTROL_START (1 << 5)
+#define TWSI_CONTROL_TWSIEN (1 << 6)
+#define TWSI_CONTROL_INTEN (1 << 7)
+
+#define TWSI_STATUS 0x0c
+#define TWSI_STATUS_START 0x08
+#define TWSI_STATUS_RPTD_START 0x10
+#define TWSI_STATUS_ADDR_W_ACK 0x18
+#define TWSI_STATUS_DATA_WR_ACK 0x28
+#define TWSI_STATUS_ADDR_R_ACK 0x40
+#define TWSI_STATUS_DATA_RD_ACK 0x50
+#define TWSI_STATUS_DATA_RD_NOACK 0x58
+
+#define TWSI_BAUD_RATE 0x0c
+#define TWSI_BAUD_RATE_PARAM(M,N) ((((M) << 3) | ((N) & 0x7)) & 0x7f)
+#define TWSI_BAUD_RATE_RAW(C,M,N) ((C)/((10*(M+1))<<(N+1)))
+#define TWSI_BAUD_RATE_SLOW 50000 /* 50kHz */
+#define TWSI_BAUD_RATE_FAST 100000 /* 100kHz */
+
+#define TWSI_SOFT_RESET 0x1c
+
+#define TWSI_DEBUG
+#undef TWSI_DEBUG
+
+#ifdef TWSI_DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+struct mv_twsi_softc {
+ device_t dev;
+ struct resource *res[1]; /* SYS_RES_MEMORY */
+ struct mtx mutex;
+ device_t iicbus;
+};
+
+static struct mv_twsi_baud_rate {
+ uint32_t raw;
+ int param;
+ int m;
+ int n;
+} baud_rate[IIC_FASTEST + 1];
+
+static int mv_twsi_probe(device_t);
+static int mv_twsi_attach(device_t);
+static int mv_twsi_detach(device_t);
+
+static int mv_twsi_reset(device_t dev, u_char speed, u_char addr,
+ u_char *oldaddr);
+static int mv_twsi_repeated_start(device_t dev, u_char slave, int timeout);
+static int mv_twsi_start(device_t dev, u_char slave, int timeout);
+static int mv_twsi_stop(device_t dev);
+static int mv_twsi_read(device_t dev, char *buf, int len, int *read, int last,
+ int delay);
+static int mv_twsi_write(device_t dev, const char *buf, int len, int *sent,
+ int timeout);
+
+static struct resource_spec res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static device_method_t mv_twsi_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, mv_twsi_probe),
+ DEVMETHOD(device_attach, mv_twsi_attach),
+ DEVMETHOD(device_detach, mv_twsi_detach),
+
+ /* iicbus interface */
+ DEVMETHOD(iicbus_callback, iicbus_null_callback),
+ DEVMETHOD(iicbus_repeated_start, mv_twsi_repeated_start),
+ DEVMETHOD(iicbus_start, mv_twsi_start),
+ DEVMETHOD(iicbus_stop, mv_twsi_stop),
+ DEVMETHOD(iicbus_write, mv_twsi_write),
+ DEVMETHOD(iicbus_read, mv_twsi_read),
+ DEVMETHOD(iicbus_reset, mv_twsi_reset),
+ DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
+ { 0, 0 }
+};
+
+static devclass_t mv_twsi_devclass;
+
+static driver_t mv_twsi_driver = {
+ MV_TWSI_NAME,
+ mv_twsi_methods,
+ sizeof(struct mv_twsi_softc),
+};
+
+DRIVER_MODULE(twsi, simplebus, mv_twsi_driver, mv_twsi_devclass, 0, 0);
+DRIVER_MODULE(iicbus, twsi, iicbus_driver, iicbus_devclass, 0, 0);
+MODULE_DEPEND(twsi, iicbus, 1, 1, 1);
+
+static __inline uint32_t
+TWSI_READ(struct mv_twsi_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->res[0], off));
+}
+
+static __inline void
+TWSI_WRITE(struct mv_twsi_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->res[0], off, val);
+}
+
+static __inline void
+twsi_control_clear(struct mv_twsi_softc *sc, uint32_t mask)
+{
+ uint32_t val;
+
+ val = TWSI_READ(sc, TWSI_CONTROL);
+ val &= ~mask;
+ TWSI_WRITE(sc, TWSI_CONTROL, val);
+}
+
+static __inline void
+twsi_control_set(struct mv_twsi_softc *sc, uint32_t mask)
+{
+ uint32_t val;
+
+ val = TWSI_READ(sc, TWSI_CONTROL);
+ val |= mask;
+ TWSI_WRITE(sc, TWSI_CONTROL, val);
+}
+
+static __inline void
+twsi_clear_iflg(struct mv_twsi_softc *sc)
+{
+
+ DELAY(1000);
+ twsi_control_clear(sc, TWSI_CONTROL_IFLG);
+ DELAY(1000);
+}
+
+
+/*
+ * timeout given in us
+ * returns
+ * 0 on sucessfull mask change
+ * non-zero on timeout
+ */
+static int
+twsi_poll_ctrl(struct mv_twsi_softc *sc, int timeout, uint32_t mask)
+{
+
+ timeout /= 10;
+ while (!(TWSI_READ(sc, TWSI_CONTROL) & mask)) {
+ DELAY(10);
+ if (--timeout < 0)
+ return (timeout);
+ }
+ return (0);
+}
+
+
+/*
+ * 'timeout' is given in us. Note also that timeout handling is not exact --
+ * twsi_locked_start() total wait can be more than 2 x timeout
+ * (twsi_poll_ctrl() is called twice). 'mask' can be either TWSI_STATUS_START
+ * or TWSI_STATUS_RPTD_START
+ */
+static int
+twsi_locked_start(device_t dev, struct mv_twsi_softc *sc, int32_t mask,
+ u_char slave, int timeout)
+{
+ int read_access, iflg_set = 0;
+ uint32_t status;
+
+ mtx_assert(&sc->mutex, MA_OWNED);
+
+ if (mask == TWSI_STATUS_RPTD_START)
+ /* read IFLG to know if it should be cleared later; from NBSD */
+ iflg_set = TWSI_READ(sc, TWSI_CONTROL) & TWSI_CONTROL_IFLG;
+
+ twsi_control_set(sc, TWSI_CONTROL_START);
+
+ if (mask == TWSI_STATUS_RPTD_START && iflg_set) {
+ debugf("IFLG set, clearing\n");
+ twsi_clear_iflg(sc);
+ }
+
+ /*
+ * Without this delay we timeout checking IFLG if the timeout is 0.
+ * NBSD driver always waits here too.
+ */
+ DELAY(1000);
+
+ if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
+ debugf("timeout sending %sSTART condition\n",
+ mask == TWSI_STATUS_START ? "" : "repeated ");
+ return (IIC_ETIMEOUT);
+ }
+
+ status = TWSI_READ(sc, TWSI_STATUS);
+ if (status != mask) {
+ debugf("wrong status (%02x) after sending %sSTART condition\n",
+ status, mask == TWSI_STATUS_START ? "" : "repeated ");
+ return (IIC_ESTATUS);
+ }
+
+ TWSI_WRITE(sc, TWSI_DATA, slave);
+ DELAY(1000);
+ twsi_clear_iflg(sc);
+
+ if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
+ debugf("timeout sending slave address\n");
+ return (IIC_ETIMEOUT);
+ }
+
+ read_access = (slave & 0x1) ? 1 : 0;
+ status = TWSI_READ(sc, TWSI_STATUS);
+ if (status != (read_access ?
+ TWSI_STATUS_ADDR_R_ACK : TWSI_STATUS_ADDR_W_ACK)) {
+ debugf("no ACK (status: %02x) after sending slave address\n",
+ status);
+ return (IIC_ENOACK);
+ }
+
+ return (IIC_NOERR);
+}
+
+static int
+mv_twsi_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "mrvl,twsi"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell Integrated I2C Bus Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+#define ABSSUB(a,b) (((a) > (b)) ? (a) - (b) : (b) - (a))
+static void
+mv_twsi_cal_baud_rate(const uint32_t target, struct mv_twsi_baud_rate *rate)
+{
+ uint32_t clk, cur, diff, diff0;
+ int m, n, m0, n0;
+
+ /* Calculate baud rate. */
+ m0 = n0 = 4; /* Default values on reset */
+ diff0 = 0xffffffff;
+ clk = get_tclk();
+
+ for (n = 0; n < 8; n++) {
+ for (m = 0; m < 16; m++) {
+ cur = TWSI_BAUD_RATE_RAW(clk,m,n);
+ diff = ABSSUB(target, cur);
+ if (diff < diff0) {
+ m0 = m;
+ n0 = n;
+ diff0 = diff;
+ }
+ }
+ }
+ rate->raw = TWSI_BAUD_RATE_RAW(clk, m0, n0);
+ rate->param = TWSI_BAUD_RATE_PARAM(m0, n0);
+ rate->m = m0;
+ rate->n = n0;
+}
+
+static int
+mv_twsi_attach(device_t dev)
+{
+ struct mv_twsi_softc *sc;
+ phandle_t child, iicbusnode;
+ device_t childdev;
+ struct iicbus_ivar *devi;
+ char dname[32]; /* 32 is taken from struct u_device */
+ uint32_t paddr;
+ int len, error;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ bzero(baud_rate, sizeof(baud_rate));
+
+ mtx_init(&sc->mutex, device_get_nameunit(dev), MV_TWSI_NAME, MTX_DEF);
+
+ /* Allocate IO resources */
+ if (bus_alloc_resources(dev, res_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ mv_twsi_detach(dev);
+ return (ENXIO);
+ }
+
+ mv_twsi_cal_baud_rate(TWSI_BAUD_RATE_SLOW, &baud_rate[IIC_SLOW]);
+ mv_twsi_cal_baud_rate(TWSI_BAUD_RATE_FAST, &baud_rate[IIC_FAST]);
+ if (bootverbose)
+ device_printf(dev, "calculated baud rates are:\n"
+ " %" PRIu32 " kHz (M=%d, N=%d) for slow,\n"
+ " %" PRIu32 " kHz (M=%d, N=%d) for fast.\n",
+ baud_rate[IIC_SLOW].raw / 1000,
+ baud_rate[IIC_SLOW].m,
+ baud_rate[IIC_SLOW].n,
+ baud_rate[IIC_FAST].raw / 1000,
+ baud_rate[IIC_FAST].m,
+ baud_rate[IIC_FAST].n);
+
+ sc->iicbus = device_add_child(dev, IICBUS_DEVNAME, -1);
+ if (sc->iicbus == NULL) {
+ device_printf(dev, "could not add iicbus child\n");
+ mv_twsi_detach(dev);
+ return (ENXIO);
+ }
+ /* Attach iicbus. */
+ bus_generic_attach(dev);
+
+ iicbusnode = 0;
+ /* Find iicbus as the child devices in the device tree. */
+ for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
+ child = OF_peer(child)) {
+ len = OF_getproplen(child, "model");
+ if (len <= 0 || len > sizeof(dname) - 1)
+ continue;
+ error = OF_getprop(child, "model", &dname, len);
+ dname[len + 1] = '\0';
+ if (error == -1)
+ continue;
+ len = strlen(dname);
+ if (len == strlen(IICBUS_DEVNAME) &&
+ strncasecmp(dname, IICBUS_DEVNAME, len) == 0) {
+ iicbusnode = child;
+ break;
+ }
+ }
+ if (iicbusnode == 0)
+ goto attach_end;
+
+ /* Attach child devices onto iicbus. */
+ for (child = OF_child(iicbusnode); child != 0; child = OF_peer(child)) {
+ /* Get slave address. */
+ error = OF_getprop(child, "i2c-address", &paddr, sizeof(paddr));
+ if (error == -1)
+ error = OF_getprop(child, "reg", &paddr, sizeof(paddr));
+ if (error == -1)
+ continue;
+
+ /* Get device driver name. */
+ len = OF_getproplen(child, "model");
+ if (len <= 0 || len > sizeof(dname) - 1)
+ continue;
+ OF_getprop(child, "model", &dname, len);
+ dname[len + 1] = '\0';
+
+ if (bootverbose)
+ device_printf(dev, "adding a device %s at %d.\n",
+ dname, fdt32_to_cpu(paddr));
+ childdev = BUS_ADD_CHILD(sc->iicbus, 0, dname, -1);
+ devi = IICBUS_IVAR(childdev);
+ devi->addr = fdt32_to_cpu(paddr);
+ }
+
+attach_end:
+ bus_generic_attach(sc->iicbus);
+
+ return (0);
+}
+
+static int
+mv_twsi_detach(device_t dev)
+{
+ struct mv_twsi_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ if ((rv = bus_generic_detach(dev)) != 0)
+ return (rv);
+
+ if (sc->iicbus != NULL)
+ if ((rv = device_delete_child(dev, sc->iicbus)) != 0)
+ return (rv);
+
+ bus_release_resources(dev, res_spec, sc->res);
+
+ mtx_destroy(&sc->mutex);
+ return (0);
+}
+
+/*
+ * Only slave mode supported, disregard [old]addr
+ */
+static int
+mv_twsi_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+ struct mv_twsi_softc *sc;
+ uint32_t param;
+
+ sc = device_get_softc(dev);
+
+ switch (speed) {
+ case IIC_SLOW:
+ case IIC_FAST:
+ param = baud_rate[speed].param;
+ break;
+ case IIC_FASTEST:
+ case IIC_UNKNOWN:
+ default:
+ param = baud_rate[IIC_FAST].param;
+ break;
+ }
+
+ mtx_lock(&sc->mutex);
+ TWSI_WRITE(sc, TWSI_SOFT_RESET, 0x0);
+ DELAY(2000);
+ TWSI_WRITE(sc, TWSI_BAUD_RATE, param);
+ TWSI_WRITE(sc, TWSI_CONTROL, TWSI_CONTROL_TWSIEN | TWSI_CONTROL_ACK);
+ DELAY(1000);
+ mtx_unlock(&sc->mutex);
+
+ return (0);
+}
+
+/*
+ * timeout is given in us
+ */
+static int
+mv_twsi_repeated_start(device_t dev, u_char slave, int timeout)
+{
+ struct mv_twsi_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ rv = twsi_locked_start(dev, sc, TWSI_STATUS_RPTD_START, slave,
+ timeout);
+ mtx_unlock(&sc->mutex);
+
+ if (rv) {
+ mv_twsi_stop(dev);
+ return (rv);
+ } else
+ return (IIC_NOERR);
+}
+
+/*
+ * timeout is given in us
+ */
+static int
+mv_twsi_start(device_t dev, u_char slave, int timeout)
+{
+ struct mv_twsi_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ rv = twsi_locked_start(dev, sc, TWSI_STATUS_START, slave, timeout);
+ mtx_unlock(&sc->mutex);
+
+ if (rv) {
+ mv_twsi_stop(dev);
+ return (rv);
+ } else
+ return (IIC_NOERR);
+}
+
+static int
+mv_twsi_stop(device_t dev)
+{
+ struct mv_twsi_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ twsi_control_set(sc, TWSI_CONTROL_STOP);
+ DELAY(1000);
+ twsi_clear_iflg(sc);
+ mtx_unlock(&sc->mutex);
+
+ return (IIC_NOERR);
+}
+
+static int
+mv_twsi_read(device_t dev, char *buf, int len, int *read, int last, int delay)
+{
+ struct mv_twsi_softc *sc;
+ uint32_t status;
+ int last_byte, rv;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ *read = 0;
+ while (*read < len) {
+ /*
+ * Check if we are reading last byte of the last buffer,
+ * do not send ACK then, per I2C specs
+ */
+ last_byte = ((*read == len - 1) && last) ? 1 : 0;
+ if (last_byte)
+ twsi_control_clear(sc, TWSI_CONTROL_ACK);
+ else
+ twsi_control_set(sc, TWSI_CONTROL_ACK);
+
+ DELAY (1000);
+ twsi_clear_iflg(sc);
+
+ if (twsi_poll_ctrl(sc, delay, TWSI_CONTROL_IFLG)) {
+ debugf("timeout reading data\n");
+ rv = IIC_ETIMEOUT;
+ goto out;
+ }
+
+ status = TWSI_READ(sc, TWSI_STATUS);
+ if (status != (last_byte ?
+ TWSI_STATUS_DATA_RD_NOACK : TWSI_STATUS_DATA_RD_ACK)) {
+ debugf("wrong status (%02x) while reading\n", status);
+ rv = IIC_ESTATUS;
+ goto out;
+ }
+
+ *buf++ = TWSI_READ(sc, TWSI_DATA);
+ (*read)++;
+ }
+ rv = IIC_NOERR;
+out:
+ mtx_unlock(&sc->mutex);
+ return (rv);
+}
+
+static int
+mv_twsi_write(device_t dev, const char *buf, int len, int *sent, int timeout)
+{
+ struct mv_twsi_softc *sc;
+ uint32_t status;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ *sent = 0;
+ while (*sent < len) {
+ TWSI_WRITE(sc, TWSI_DATA, *buf++);
+
+ twsi_clear_iflg(sc);
+ if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
+ debugf("timeout writing data\n");
+ rv = IIC_ETIMEOUT;
+ goto out;
+ }
+
+ status = TWSI_READ(sc, TWSI_STATUS);
+ if (status != TWSI_STATUS_DATA_WR_ACK) {
+ debugf("wrong status (%02x) while writing\n", status);
+ rv = IIC_ESTATUS;
+ goto out;
+ }
+ (*sent)++;
+ }
+ rv = IIC_NOERR;
+out:
+ mtx_unlock(&sc->mutex);
+ return (rv);
+}
Property changes on: trunk/sys/arm/mv/twsi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/files.rk30xx
===================================================================
--- trunk/sys/arm/rockchip/files.rk30xx (rev 0)
+++ trunk/sys/arm/rockchip/files.rk30xx 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,22 @@
+# $FreeBSD: stable/10/sys/arm/rockchip/files.rk30xx 278727 2015-02-13 22:32:02Z ian $
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+
+arm/arm/gic.c standard
+arm/arm/mpcore_timer.c standard
+
+arm/arm/bus_space_base.c standard
+arm/rockchip/rk30xx_common.c standard
+arm/rockchip/rk30xx_machdep.c standard
+arm/rockchip/rk30xx_pmu.c standard
+arm/rockchip/rk30xx_grf.c standard
+arm/rockchip/rk30xx_wdog.c standard
+arm/rockchip/rk30xx_gpio.c optional gpio
+dev/usb/controller/dwc_otg_fdt.c optional dwcotg
+arm/rockchip/rk30xx_mp.c optional smp
Property changes on: trunk/sys/arm/rockchip/files.rk30xx
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_common.c
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_common.c (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,65 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/rockchip/rk30xx_common.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (!fdt_is_compatible(node, "arm,gic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_aintc_decode_ic,
+ NULL
+};
Property changes on: trunk/sys/arm/rockchip/rk30xx_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_gpio.c
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_gpio.c (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,663 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012 Luiz Otavio O Souza.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/rockchip/rk30xx_gpio.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "gpio_if.h"
+
+#include "rk30xx_grf.h"
+#include "rk30xx_pmu.h"
+
+/*
+ * RK3188 has 4 banks of gpio.
+ * 32 pins per bank
+ * PA0 - PA7 | PB0 - PB7
+ * PC0 - PC7 | PD0 - PD7
+ */
+
+#define RK30_GPIO_PINS 128
+#define RK30_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+ GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
+
+#define RK30_GPIO_NONE 0
+#define RK30_GPIO_PULLUP 1
+#define RK30_GPIO_PULLDOWN 2
+
+#define RK30_GPIO_INPUT 0
+#define RK30_GPIO_OUTPUT 1
+
+struct rk30_gpio_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ struct resource * sc_mem_res;
+ struct resource * sc_irq_res;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ void * sc_intrhand;
+ int sc_gpio_npins;
+ struct gpio_pin sc_gpio_pins[RK30_GPIO_PINS];
+};
+
+static struct rk30_gpio_softc *rk30_gpio_sc = NULL;
+
+typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int);
+
+struct gpio_ctrl_entry {
+ const char *compat;
+ gpios_phandler_t handler;
+};
+
+int rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len);
+static int rk30_gpio_init(void);
+
+struct gpio_ctrl_entry gpio_controllers[] = {
+ { "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle },
+ { "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle },
+ { "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle },
+ { "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle },
+ { NULL, NULL }
+};
+
+#define RK30_GPIO_LOCK(_sc) mtx_lock(&_sc->sc_mtx)
+#define RK30_GPIO_UNLOCK(_sc) mtx_unlock(&_sc->sc_mtx)
+#define RK30_GPIO_LOCK_ASSERT(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
+
+#define RK30_GPIO_SWPORT_DR 0x00
+#define RK30_GPIO_SWPORT_DDR 0x04
+#define RK30_GPIO_INTEN 0x30
+#define RK30_GPIO_INTMASK 0x34
+#define RK30_GPIO_INTTYPE_LEVEL 0x38
+#define RK30_GPIO_INT_POLARITY 0x3c
+#define RK30_GPIO_INT_STATUS 0x40
+#define RK30_GPIO_INT_RAWSTATUS 0x44
+#define RK30_GPIO_DEBOUNCE 0x48
+#define RK30_GPIO_PORTS_EOI 0x4c
+#define RK30_GPIO_EXT_PORT 0x50
+#define RK30_GPIO_LS_SYNC 0x60
+
+#define RK30_GPIO_WRITE(_sc, _off, _val) \
+ bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
+#define RK30_GPIO_READ(_sc, _off) \
+ bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
+
+static uint32_t
+rk30_gpio_get_function(struct rk30_gpio_softc *sc, uint32_t pin)
+{
+ uint32_t bank, func, offset;
+
+ bank = pin / 32;
+ pin = pin % 32;
+ offset = 1 << pin;
+
+ func = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DDR);
+ func &= offset;
+
+ return (func);
+}
+
+static uint32_t
+rk30_gpio_func_flag(uint32_t nfunc)
+{
+
+ switch (nfunc) {
+ case RK30_GPIO_INPUT:
+ return (GPIO_PIN_INPUT);
+ case RK30_GPIO_OUTPUT:
+ return (GPIO_PIN_OUTPUT);
+ }
+ return (0);
+}
+
+static void
+rk30_gpio_set_function(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t f)
+{
+ uint32_t bank, data, offset;
+
+ /* Must be called with lock held. */
+ RK30_GPIO_LOCK_ASSERT(sc);
+
+ bank = pin / 32;
+ pin = pin % 32;
+ offset = 1 << pin;
+
+ data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DDR);
+ if (f)
+ data |= offset;
+ else
+ data &= ~offset;
+ RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DDR, data);
+}
+
+static void
+rk30_gpio_set_pud(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t state)
+{
+ uint32_t bank;
+
+ bank = pin / 32;
+
+ /* Must be called with lock held. */
+ RK30_GPIO_LOCK_ASSERT(sc);
+
+ if (bank == 0 && pin < 12)
+ rk30_pmu_gpio_pud(pin, state);
+ else
+ rk30_grf_gpio_pud(bank, pin, state);
+}
+
+static void
+rk30_gpio_pin_configure(struct rk30_gpio_softc *sc, struct gpio_pin *pin,
+ unsigned int flags)
+{
+
+ RK30_GPIO_LOCK(sc);
+
+ /*
+ * Manage input/output.
+ */
+ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
+ pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
+ if (flags & GPIO_PIN_OUTPUT) {
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+ rk30_gpio_set_function(sc, pin->gp_pin,
+ RK30_GPIO_OUTPUT);
+ } else {
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ rk30_gpio_set_function(sc, pin->gp_pin,
+ RK30_GPIO_INPUT);
+ }
+ }
+
+ /* Manage Pull-up/pull-down. */
+ pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
+ if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
+ if (flags & GPIO_PIN_PULLUP) {
+ pin->gp_flags |= GPIO_PIN_PULLUP;
+ rk30_gpio_set_pud(sc, pin->gp_pin,
+ RK30_GPIO_PULLUP);
+ } else {
+ pin->gp_flags |= GPIO_PIN_PULLDOWN;
+ rk30_gpio_set_pud(sc, pin->gp_pin,
+ RK30_GPIO_PULLDOWN);
+ }
+ } else
+ rk30_gpio_set_pud(sc, pin->gp_pin, RK30_GPIO_NONE);
+
+ RK30_GPIO_UNLOCK(sc);
+}
+
+static int
+rk30_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = RK30_GPIO_PINS - 1;
+ return (0);
+}
+
+static int
+rk30_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct rk30_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ RK30_GPIO_LOCK(sc);
+ *caps = sc->sc_gpio_pins[i].gp_caps;
+ RK30_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+rk30_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct rk30_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ RK30_GPIO_LOCK(sc);
+ *flags = sc->sc_gpio_pins[i].gp_flags;
+ RK30_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+rk30_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct rk30_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ RK30_GPIO_LOCK(sc);
+ memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME);
+ RK30_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+rk30_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct rk30_gpio_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ rk30_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
+
+ return (0);
+}
+
+static int
+rk30_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct rk30_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, offset, data;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ bank = pin / 32;
+ pin = pin % 32;
+ offset = 1 << pin;
+
+ RK30_GPIO_LOCK(sc);
+ data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DDR);
+ data |= offset;
+ RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DDR, data);
+
+ data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DR);
+ if (value)
+ data |= offset;
+ else
+ data &= ~offset;
+ RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DR, data);
+ RK30_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+rk30_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct rk30_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, offset, reg_data;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ bank = pin / 32;
+ pin = pin % 32;
+ offset = 1 << pin;
+
+ RK30_GPIO_LOCK(sc);
+ reg_data = RK30_GPIO_READ(sc, RK30_GPIO_EXT_PORT);
+ RK30_GPIO_UNLOCK(sc);
+ *val = (reg_data & offset) ? 1 : 0;
+
+ return (0);
+}
+
+static int
+rk30_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct rk30_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank, data, offset;
+ int i;
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ bank = pin / 32;
+ pin = pin % 32;
+ offset = 1 << pin;
+
+ RK30_GPIO_LOCK(sc);
+ data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DDR);
+ if (data & offset)
+ data &= ~offset;
+ else
+ data |= offset;
+ RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DDR, data);
+
+ data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DR);
+ if (data & offset)
+ data &= ~offset;
+ else
+ data |= offset;
+ RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DR, data);
+ RK30_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+rk30_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "rockchip,rk30xx-gpio"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Rockchip RK30XX GPIO controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+rk30_gpio_attach(device_t dev)
+{
+ struct rk30_gpio_softc *sc = device_get_softc(dev);
+ uint32_t func;
+ int i, rid;
+ phandle_t gpio;
+
+ if (rk30_gpio_sc)
+ return (ENXIO);
+
+ sc->sc_dev = dev;
+
+ mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ /* Find our node. */
+ gpio = ofw_bus_get_node(sc->sc_dev);
+
+ if (!OF_hasprop(gpio, "gpio-controller"))
+ /* Node is not a GPIO controller. */
+ goto fail;
+
+ /* Initialize the software controlled pins. */
+ for (i = 0; i < RK30_GPIO_PINS; i++) {
+ snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
+ "pin %d", i);
+ func = rk30_gpio_get_function(sc, i);
+ sc->sc_gpio_pins[i].gp_pin = i;
+ sc->sc_gpio_pins[i].gp_caps = RK30_GPIO_DEFAULT_CAPS;
+ sc->sc_gpio_pins[i].gp_flags = rk30_gpio_func_flag(func);
+ }
+ sc->sc_gpio_npins = i;
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ rk30_gpio_sc = sc;
+
+ rk30_gpio_init();
+
+ return (bus_generic_attach(dev));
+
+fail:
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ return (ENXIO);
+}
+
+static int
+rk30_gpio_detach(device_t dev)
+{
+
+ return (EBUSY);
+}
+
+static device_method_t rk30_gpio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, rk30_gpio_probe),
+ DEVMETHOD(device_attach, rk30_gpio_attach),
+ DEVMETHOD(device_detach, rk30_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, rk30_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, rk30_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, rk30_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, rk30_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, rk30_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, rk30_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, rk30_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, rk30_gpio_pin_toggle),
+
+ DEVMETHOD_END
+};
+
+static devclass_t rk30_gpio_devclass;
+
+static driver_t rk30_gpio_driver = {
+ "gpio",
+ rk30_gpio_methods,
+ sizeof(struct rk30_gpio_softc),
+};
+
+DRIVER_MODULE(rk30_gpio, simplebus, rk30_gpio_driver, rk30_gpio_devclass, 0, 0);
+
+int
+rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len)
+{
+ struct rk30_gpio_softc *sc;
+ pcell_t gpio_cells;
+ int inc, t, tuples, tuple_size;
+ int dir, flags, pin, i;
+ u_long gpio_ctrl, size;
+
+ sc = rk30_gpio_sc;
+ if (sc == NULL)
+ return ENXIO;
+
+ if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0)
+ return (ENXIO);
+
+ gpio_cells = fdt32_to_cpu(gpio_cells);
+ if (gpio_cells != 2)
+ return (ENXIO);
+
+ tuple_size = gpio_cells * sizeof(pcell_t) + sizeof(phandle_t);
+ tuples = len / tuple_size;
+
+ if (fdt_regsize(ctrl, &gpio_ctrl, &size))
+ return (ENXIO);
+
+ /*
+ * Skip controller reference, since controller's phandle is given
+ * explicitly (in a function argument).
+ */
+ inc = sizeof(ihandle_t) / sizeof(pcell_t);
+ gpios += inc;
+ for (t = 0; t < tuples; t++) {
+ pin = fdt32_to_cpu(gpios[0]);
+ dir = fdt32_to_cpu(gpios[1]);
+ flags = fdt32_to_cpu(gpios[2]);
+
+ for (i = 0; i < sc->sc_gpio_npins; i++) {
+ if (sc->sc_gpio_pins[i].gp_pin == pin)
+ break;
+ }
+ if (i >= sc->sc_gpio_npins)
+ return (EINVAL);
+
+ rk30_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
+
+ if (dir == 1) {
+ /* Input. */
+ rk30_gpio_pin_set(sc->sc_dev, pin, RK30_GPIO_INPUT);
+ } else {
+ /* Output. */
+ rk30_gpio_pin_set(sc->sc_dev, pin, RK30_GPIO_OUTPUT);
+ }
+ gpios += gpio_cells + inc;
+ }
+
+ return (0);
+}
+
+#define MAX_PINS_PER_NODE 5
+#define GPIOS_PROP_CELLS 4
+
+static int
+rk30_gpio_init(void)
+{
+ phandle_t child, parent, root, ctrl;
+ pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS];
+ struct gpio_ctrl_entry *e;
+ int len, rv;
+
+ root = OF_finddevice("/");
+ len = 0;
+ parent = root;
+
+ /* Traverse through entire tree to find nodes with 'gpios' prop */
+ for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
+
+ /* Find a 'leaf'. Start the search from this node. */
+ while (OF_child(child)) {
+ parent = child;
+ child = OF_child(child);
+ }
+ if ((len = OF_getproplen(child, "gpios")) > 0) {
+
+ if (len > sizeof(gpios))
+ return (ENXIO);
+
+ /* Get 'gpios' property. */
+ OF_getprop(child, "gpios", &gpios, len);
+
+ e = (struct gpio_ctrl_entry *)&gpio_controllers;
+
+ /* Find and call a handler. */
+ for (; e->compat; e++) {
+ /*
+ * First cell of 'gpios' property should
+ * contain a ref. to a node defining GPIO
+ * controller.
+ */
+ ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0]));
+
+ if (fdt_is_compatible(ctrl, e->compat))
+ /* Call a handler. */
+ if ((rv = e->handler(ctrl,
+ (pcell_t *)&gpios, len)))
+ return (rv);
+ }
+ }
+
+ if (OF_peer(child) == 0) {
+ /* No more siblings. */
+ child = parent;
+ parent = OF_parent(child);
+ }
+ }
+ return (0);
+}
Property changes on: trunk/sys/arm/rockchip/rk30xx_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_grf.c
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_grf.c (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_grf.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,133 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* General Register File for Rockchip RK30xx */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/rockchip/rk30xx_grf.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include "rk30xx_grf.h"
+
+struct rk30_grf_softc {
+ struct resource *res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct rk30_grf_softc *rk30_grf_sc = NULL;
+
+#define grf_read_4(sc, reg) \
+ bus_space_read_4((sc)->bst, (sc)->bsh, (reg))
+#define grf_write_4(sc, reg, val) \
+ bus_space_write_4((sc)->bst, (sc)->bsh, (reg), (val))
+
+static int
+rk30_grf_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "rockchip,rk30xx-grf")) {
+ device_set_desc(dev, "RK30XX General Register File");
+ return(BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+rk30_grf_attach(device_t dev)
+{
+ struct rk30_grf_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ if (rk30_grf_sc)
+ return (ENXIO);
+
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res);
+ sc->bsh = rman_get_bushandle(sc->res);
+
+ rk30_grf_sc = sc;
+
+ return (0);
+}
+
+static device_method_t rk30_grf_methods[] = {
+ DEVMETHOD(device_probe, rk30_grf_probe),
+ DEVMETHOD(device_attach, rk30_grf_attach),
+ { 0, 0 }
+};
+
+static driver_t rk30_grf_driver = {
+ "rk30_grf",
+ rk30_grf_methods,
+ sizeof(struct rk30_grf_softc),
+};
+
+static devclass_t rk30_grf_devclass;
+
+DRIVER_MODULE(rk30_grf, simplebus, rk30_grf_driver, rk30_grf_devclass, 0, 0);
+
+void
+rk30_grf_gpio_pud(uint32_t bank, uint32_t pin, uint32_t state)
+{
+ uint32_t offset;
+
+ offset = GRF_GPIO0B_PULL - 4 + (bank * 16) + ((pin / 8) * 4);
+ pin = (7 - (pin % 8)) * 2;
+ grf_write_4(rk30_grf_sc, offset, (0x3 << (16 + pin)) | (state << pin));
+}
+
Property changes on: trunk/sys/arm/rockchip/rk30xx_grf.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_grf.h
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_grf.h (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_grf.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,142 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/rockchip/rk30xx_grf.h 266337 2014-05-17 18:53:36Z ian $
+ */
+
+#ifndef _RK30_GRF_H_
+#define _RK30_GRF_H_
+
+#define RK30_GRF_BASE 0xF0008000
+
+#define GRF_GPIO0L_DIR 0x0000
+#define GRF_GPIO0H_DIR 0x0004
+#define GRF_GPIO1L_DIR 0x0008
+#define GRF_GPIO1H_DIR 0x000c
+#define GRF_GPIO2L_DIR 0x0010
+#define GRF_GPIO2H_DIR 0x0014
+#define GRF_GPIO3L_DIR 0x0018
+#define GRF_GPIO3H_DIR 0x001c
+#define GRF_GPIO0L_DO 0x0020
+#define GRF_GPIO0H_DO 0x0024
+#define GRF_GPIO1L_DO 0x0028
+#define GRF_GPIO1H_DO 0x002c
+#define GRF_GPIO2L_DO 0x0030
+#define GRF_GPIO2H_DO 0x0034
+#define GRF_GPIO3L_DO 0x0038
+#define GRF_GPIO3H_DO 0x003c
+#define GRF_GPIO0L_EN 0x0040
+#define GRF_GPIO0H_EN 0x0044
+#define GRF_GPIO1L_EN 0x0048
+#define GRF_GPIO1H_EN 0x004c
+#define GRF_GPIO2L_EN 0x0050
+#define GRF_GPIO2H_EN 0x0054
+#define GRF_GPIO3L_EN 0x0058
+#define GRF_GPIO3H_EN 0x005c
+
+#define GRF_GPIO0C_IOMUX 0x0068
+#define GRF_GPIO0D_IOMUX 0x006c
+#define GRF_GPIO1A_IOMUX 0x0070
+#define GRF_GPIO1B_IOMUX 0x0074
+#define GRF_GPIO1C_IOMUX 0x0078
+#define GRF_GPIO1D_IOMUX 0x007c
+#define GRF_GPIO2A_IOMUX 0x0080
+#define GRF_GPIO2B_IOMUX 0x0084
+#define GRF_GPIO2C_IOMUX 0x0088
+#define GRF_GPIO2D_IOMUX 0x008c
+#define GRF_GPIO3A_IOMUX 0x0090
+#define GRF_GPIO3B_IOMUX 0x0094
+#define GRF_GPIO3C_IOMUX 0x0098
+#define GRF_GPIO3D_IOMUX 0x009c
+#define GRF_SOC_CON0 0x00a0
+#define GRF_SOC_CON1 0x00a4
+#define GRF_SOC_CON2 0x00a8
+#define GRF_SOC_STATUS0 0x00ac
+#define GRF_DMAC1_CON0 0x00b0
+#define GRF_DMAC1_CON1 0x00b4
+#define GRF_DMAC1_CON2 0x00b8
+#define GRF_DMAC2_CON0 0x00bc
+#define GRF_DMAC2_CON1 0x00c0
+#define GRF_DMAC2_CON2 0x00c4
+#define GRF_DMAC2_CON3 0x00c8
+#define GRF_CPU_CON0 0x00cc
+#define GRF_CPU_CON1 0x00d0
+#define GRF_CPU_CON2 0x00d4
+#define GRF_CPU_CON3 0x00d8
+#define GRF_CPU_CON4 0x00dc
+#define GRF_CPU_CON5 0x00e0
+
+#define GRF_DDRC_CON0 0x00ec
+#define GRF_DDRC_STAT 0x00f0
+#define GRF_IO_CON0 0x00f4
+#define GRF_IO_CON1 0x00f8
+#define GRF_IO_CON2 0x00fc
+#define GRF_IO_CON3 0x0100
+#define GRF_IO_CON4 0x0104
+#define GRF_SOC_STATUS1 0x0108
+#define GRF_UOC0_CON0 0x010c
+#define GRF_UOC0_CON1 0x0110
+#define GRF_UOC0_CON2 0x0114
+#define GRF_UOC0_CON3 0x0118
+#define GRF_UOC1_CON0 0x011c
+#define GRF_UOC1_CON1 0x0120
+#define GRF_UOC1_CON2 0x0124
+#define GRF_UOC1_CON3 0x0128
+#define GRF_UOC2_CON0 0x012c
+#define GRF_UOC2_CON1 0x0130
+
+#define GRF_UOC3_CON0 0x0138
+#define GRF_UOC3_CON1 0x013c
+#define GRF_HSIC_STAT 0x0140
+#define GRF_OS_REG0 0x0144
+#define GRF_OS_REG1 0x0148
+#define GRF_OS_REG2 0x014c
+#define GRF_OS_REG3 0x0150
+#define GRF_OS_REG4 0x0154
+#define GRF_OS_REG5 0x0158
+#define GRF_OS_REG6 0x015c
+#define GRF_OS_REG7 0x0160
+#define GRF_GPIO0B_PULL 0x0164
+#define GRF_GPIO0C_PULL 0x0168
+#define GRF_GPIO0D_PULL 0x016c
+#define GRF_GPIO1A_PULL 0x0170
+#define GRF_GPIO1B_PULL 0x0174
+#define GRF_GPIO1C_PULL 0x0178
+#define GRF_GPIO1D_PULL 0x017c
+#define GRF_GPIO2A_PULL 0x0180
+#define GRF_GPIO2B_PULL 0x0184
+#define GRF_GPIO2C_PULL 0x0188
+#define GRF_GPIO2D_PULL 0x018c
+#define GRF_GPIO3A_PULL 0x0190
+#define GRF_GPIO3B_PULL 0x0194
+#define GRF_GPIO3C_PULL 0x0198
+#define GRF_GPIO3D_PULL 0x019c
+#define GRF_FLASH_DATA_PULL 0x01a0
+#define GRF_FLASH_CMD_PULL 0x01a4
+
+void rk30_grf_gpio_pud(uint32_t bank, uint32_t pin, uint32_t state);
+
+#endif /* _RK30_GRF_H_ */
Property changes on: trunk/sys/arm/rockchip/rk30xx_grf.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_machdep.c
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_machdep.c (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,113 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/ti/ti_machdep.c
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/rockchip/rk30xx_machdep.c 266397 2014-05-18 13:05:07Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <dev/fdt/fdt_common.h>
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+
+}
+
+void
+initarm_gpio_init(void)
+{
+}
+
+void
+initarm_late_init(void)
+{
+
+ /* Enable cache */
+ cpufunc_control(CPU_CONTROL_DC_ENABLE|CPU_CONTROL_IC_ENABLE,
+ CPU_CONTROL_DC_ENABLE|CPU_CONTROL_IC_ENABLE);
+}
+
+/*
+ * Set up static device mappings.
+ */
+int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(0x10000000, 0x00200000);
+ arm_devmap_add_entry(0x20000000, 0x00100000);
+
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+void
+cpu_reset()
+{
+
+ printf("No cpu_reset implementation!\n");
+ while (1);
+}
Property changes on: trunk/sys/arm/rockchip/rk30xx_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_mp.c
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_mp.c (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_mp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,193 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/rockchip/rk30xx_mp.c 266397 2014-05-18 13:05:07Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#define SCU_PHYSBASE 0x1013c000
+#define SCU_SIZE 0x100
+
+#define SCU_CONTROL_REG 0x00
+#define SCU_CONTROL_ENABLE (1 << 0)
+#define SCU_STANDBY_EN (1 << 5)
+#define SCU_CONFIG_REG 0x04
+#define SCU_CONFIG_REG_NCPU_MASK 0x03
+#define SCU_CPUPOWER_REG 0x08
+#define SCU_INV_TAGS_REG 0x0c
+
+#define SCU_FILTER_START_REG 0x10
+#define SCU_FILTER_END_REG 0x14
+#define SCU_SECURE_ACCESS_REG 0x18
+#define SCU_NONSECURE_ACCESS_REG 0x1c
+
+#define IMEM_PHYSBASE 0x10080000
+#define IMEM_SIZE 0x20
+
+#define PMU_PHYSBASE 0x20004000
+#define PMU_SIZE 0x100
+#define PMU_PWRDN_CON 0x08
+#define PMU_PWRDN_SCU (1 << 4)
+
+extern char *mpentry_addr;
+static void rk30xx_boot2(void);
+
+static void
+rk30xx_boot2(void)
+{
+
+ __asm __volatile(
+ "ldr pc, 1f\n"
+ ".globl mpentry_addr\n"
+ "mpentry_addr:\n"
+ "1: .space 4\n");
+}
+
+void
+platform_mp_init_secondary(void)
+{
+
+ gic_init_secondary();
+}
+
+void
+platform_mp_setmaxid(void)
+{
+ bus_space_handle_t scu;
+ int ncpu;
+ uint32_t val;
+
+ if (mp_ncpus != 0)
+ return;
+
+ if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
+ panic("Could not map the SCU");
+
+ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONFIG_REG);
+ ncpu = (val & SCU_CONFIG_REG_NCPU_MASK) + 1;
+ bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
+
+ mp_ncpus = ncpu;
+ mp_maxid = ncpu - 1;
+}
+
+int
+platform_mp_probe(void)
+{
+
+ if (mp_ncpus == 0)
+ platform_mp_setmaxid();
+
+ return (mp_ncpus > 1);
+}
+
+void
+platform_mp_start_ap(void)
+{
+ bus_space_handle_t scu;
+ bus_space_handle_t imem;
+ bus_space_handle_t pmu;
+ uint32_t val;
+ int i;
+
+ if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
+ panic("Could not map the SCU");
+ if (bus_space_map(fdtbus_bs_tag, IMEM_PHYSBASE,
+ IMEM_SIZE, 0, &imem) != 0)
+ panic("Could not map the IMEM");
+ if (bus_space_map(fdtbus_bs_tag, PMU_PHYSBASE, PMU_SIZE, 0, &pmu) != 0)
+ panic("Could not map the PMU");
+
+ /*
+ * Invalidate SCU cache tags. The 0x0000ffff constant invalidates all
+ * ways on all cores 0-3. Per the ARM docs, it's harmless to write to
+ * the bits for cores that are not present.
+ */
+ bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff);
+
+ /* Make sure all cores except the first are off */
+ val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON);
+ for (i = 1; i < mp_ncpus; i++)
+ val |= 1 << i;
+ bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val);
+
+ /* Enable SCU power domain */
+ val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON);
+ val &= ~PMU_PWRDN_SCU;
+ bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val);
+
+ /* Enable SCU */
+ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG);
+ bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG,
+ val | SCU_CONTROL_ENABLE);
+
+ /*
+ * Cores will execute the code which resides at the start of
+ * the on-chip bootram/sram after power-on. This sram region
+ * should be reserved and the trampoline code that directs
+ * the core to the real startup code in ram should be copied
+ * into this sram region.
+ *
+ * First set boot function for the sram code.
+ */
+ mpentry_addr = (char *)pmap_kextract((vm_offset_t)mpentry);
+
+ /* Copy trampoline to sram, that runs during startup of the core */
+ bus_space_write_region_4(fdtbus_bs_tag, imem, 0,
+ (uint32_t *)&rk30xx_boot2, 8);
+
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+
+ /* Start all cores */
+ val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON);
+ for (i = 1; i < mp_ncpus; i++)
+ val &= ~(1 << i);
+ bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val);
+
+ armv7_sev();
+
+ bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
+ bus_space_unmap(fdtbus_bs_tag, imem, IMEM_SIZE);
+ bus_space_unmap(fdtbus_bs_tag, pmu, PMU_SIZE);
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+
+ pic_ipi_send(cpus, ipi);
+}
Property changes on: trunk/sys/arm/rockchip/rk30xx_mp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_pmu.c
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_pmu.c (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_pmu.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,133 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* PMU for Rockchip RK30xx */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/rockchip/rk30xx_pmu.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include "rk30xx_pmu.h"
+
+struct rk30_pmu_softc {
+ struct resource *res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct rk30_pmu_softc *rk30_pmu_sc = NULL;
+
+#define pmu_read_4(sc, reg) \
+ bus_space_read_4((sc)->bst, (sc)->bsh, (reg))
+#define pmu_write_4(sc, reg, val) \
+ bus_space_write_4((sc)->bst, (sc)->bsh, (reg), (val))
+
+static int
+rk30_pmu_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "rockchip,rk30xx-pmu")) {
+ device_set_desc(dev, "RK30XX PMU");
+ return(BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+rk30_pmu_attach(device_t dev)
+{
+ struct rk30_pmu_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ if (rk30_pmu_sc)
+ return (ENXIO);
+
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res);
+ sc->bsh = rman_get_bushandle(sc->res);
+
+ rk30_pmu_sc = sc;
+
+ return (0);
+}
+
+static device_method_t rk30_pmu_methods[] = {
+ DEVMETHOD(device_probe, rk30_pmu_probe),
+ DEVMETHOD(device_attach, rk30_pmu_attach),
+ { 0, 0 }
+};
+
+static driver_t rk30_pmu_driver = {
+ "rk30_pmu",
+ rk30_pmu_methods,
+ sizeof(struct rk30_pmu_softc),
+};
+
+static devclass_t rk30_pmu_devclass;
+
+DRIVER_MODULE(rk30_pmu, simplebus, rk30_pmu_driver, rk30_pmu_devclass, 0, 0);
+
+void
+rk30_pmu_gpio_pud(uint32_t pin, uint32_t state)
+{
+ uint32_t offset;
+
+ offset = PMU_GPIO0A_PULL + ((pin / 8) * 4);
+ pin = (pin % 8) * 2;
+ pmu_write_4(rk30_pmu_sc, offset, (0x3 << (16 + pin)) | (state << pin));
+}
+
Property changes on: trunk/sys/arm/rockchip/rk30xx_pmu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_pmu.h
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_pmu.h (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_pmu.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,61 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/rockchip/rk30xx_pmu.h 266337 2014-05-17 18:53:36Z ian $
+ */
+
+#ifndef _RK30_PMU_H_
+#define _RK30_PMU_H_
+
+#define RK30_PMU_BASE 0xF0004000
+
+#define PMU_WAKEUP_CFG0 0x00
+#define PMU_WAKEUP_CFG1 0x04
+#define PMU_PWRDN_CON 0x08
+#define PMU_PWRDN_ST 0x0c
+#define PMU_INT_CON 0x10
+#define PMU_INT_ST 0x14
+#define PMU_MISC_CON 0x18
+#define PMU_OSC_CNT 0x1c
+#define PMU_PLL_CNT 0x20
+#define PMU_PMU_CNT 0x24
+#define PMU_DDRIO_PWRON_CNT 0x28
+#define PMU_WAKEUP_RST_CLR_CNT 0x2c
+#define PMU_SCU_PWRDWN_CNT 0x30
+#define PMU_SCU_PWRUP_CNT 0x34
+#define PMU_MISC_CON1 0x38
+#define PMU_GPIO0_CON 0x3c
+#define PMU_SYS_REG0 0x40
+#define PMU_SYS_REG1 0x44
+#define PMU_SYS_REG2 0x48
+#define PMU_SYS_REG3 0x4c
+#define PMU_STOP_INT_DLY 0x60
+#define PMU_GPIO0A_PULL 0x64
+#define PMU_GPIO0B_PULL 0x68
+
+void rk30_pmu_gpio_pud(uint32_t pin, uint32_t state);
+
+#endif /* _RK30_PMU_H_ */
Property changes on: trunk/sys/arm/rockchip/rk30xx_pmu.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_wdog.c
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_wdog.c (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_wdog.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,202 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/rockchip/rk30xx_wdog.c 266337 2014-05-17 18:53:36Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/watchdog.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <machine/machdep.h>
+#include <machine/fdt.h>
+
+#include <arm/rockchip/rk30xx_wdog.h>
+
+#ifndef RK30_WDT_BASE
+#define RK30_WDT_BASE 0x2004c000
+#define RK30_WDT_PSIZE 0x100
+#endif
+
+#define RK30_WDT_READ(_sc, _r) bus_read_4((_sc)->res, (_r))
+#define RK30_WDT_WRITE(_sc, _r, _v) bus_write_4((_sc)->res, (_r), (_v))
+
+#define WDOG_CTRL 0x00
+#define WDOG_CTRL_EN (1 << 0)
+#define WDOG_CTRL_RSP_MODE (1 << 1)
+#define WDOG_CTRL_RST_PULSE (4 << 2)
+#define WDOG_CTRL_RST 0xa
+#define WDOG_TORR 0x04
+#define WDOG_TORR_INTVL_SHIFT 0
+#define WDOG_CCVR 0x08
+#define WDOG_CRR 0x0c
+#define WDOG_CRR_PWD 0x76
+#define WDOG_STAT 0x10
+#define WDOG_EOI 0x14
+
+static struct rk30_wd_softc *rk30_wd_sc = NULL;
+
+struct rk30_wd_softc {
+ device_t dev;
+ struct resource *res;
+ struct mtx mtx;
+ int freq;
+};
+
+static void rk30_wd_watchdog_fn(void *private, u_int cmd, int *error);
+
+static int
+rk30_wd_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "rockchip,rk30xx-wdt")) {
+ device_set_desc(dev, "Rockchip RK30XX Watchdog");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+rk30_wd_attach(device_t dev)
+{
+ struct rk30_wd_softc *sc;
+ int rid;
+ phandle_t node;
+ pcell_t cell;
+
+ if (rk30_wd_sc != NULL)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ node = ofw_bus_get_node(sc->dev);
+ if (OF_getencprop(node, "clock-frequency", &cell, sizeof(cell)) > 0)
+ sc->freq = cell / 1000000;
+ else
+ return (ENXIO);
+
+ rid = 0;
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ rk30_wd_sc = sc;
+ mtx_init(&sc->mtx, "RK30XX Watchdog", "rk30_wd", MTX_DEF);
+ EVENTHANDLER_REGISTER(watchdog_list, rk30_wd_watchdog_fn, sc, 0);
+
+ return (0);
+}
+
+static void
+rk30_wd_watchdog_fn(void *private, u_int cmd, int *error)
+{
+ struct rk30_wd_softc *sc;
+ uint64_t ms, m, max;
+ int i;
+
+ sc = private;
+ mtx_lock(&sc->mtx);
+
+ cmd &= WD_INTERVAL;
+
+ if (cmd > 0) {
+ ms = ((uint64_t)1 << (cmd & WD_INTERVAL)) / 1000000;
+ m = 0xffff / sc->freq;
+ max = 0x7fffffff / sc->freq + 1;
+ i = 0;
+ while (m < max && m < ms) {
+ m <<= 1;
+ i++;
+ }
+ if (m < max) {
+ RK30_WDT_WRITE(sc, WDOG_TORR,
+ i << WDOG_TORR_INTVL_SHIFT);
+ RK30_WDT_WRITE(sc, WDOG_CTRL,
+ WDOG_CTRL_EN | WDOG_CTRL_RSP_MODE |
+ WDOG_CTRL_RST_PULSE);
+ RK30_WDT_WRITE(sc, WDOG_CRR, WDOG_CRR_PWD);
+ *error = 0;
+ } else {
+ device_printf(sc->dev, "Can not be disabled\n");
+ mtx_unlock(&sc->mtx);
+ RK30_WDT_WRITE(sc, WDOG_CTRL, WDOG_CTRL_RST);
+ return;
+ }
+ }
+ else
+ RK30_WDT_WRITE(sc, WDOG_CTRL, WDOG_CTRL_RST);
+
+ mtx_unlock(&sc->mtx);
+}
+
+void
+rk30_wd_watchdog_reset()
+{
+ bus_space_handle_t bsh;
+
+ bus_space_map(fdtbus_bs_tag, RK30_WDT_BASE, RK30_WDT_PSIZE, 0, &bsh);
+ bus_space_write_4(fdtbus_bs_tag, bsh, WDOG_TORR, 0);
+ bus_space_write_4(fdtbus_bs_tag, bsh, WDOG_CTRL,
+ WDOG_CTRL_EN | WDOG_CTRL_RSP_MODE | WDOG_CTRL_RST_PULSE);
+
+ while (1);
+}
+
+static device_method_t rk30_wd_methods[] = {
+ DEVMETHOD(device_probe, rk30_wd_probe),
+ DEVMETHOD(device_attach, rk30_wd_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t rk30_wd_driver = {
+ "rk30_wd",
+ rk30_wd_methods,
+ sizeof(struct rk30_wd_softc),
+};
+static devclass_t rk30_wd_devclass;
+
+DRIVER_MODULE(rk30_wd, simplebus, rk30_wd_driver, rk30_wd_devclass, 0, 0);
Property changes on: trunk/sys/arm/rockchip/rk30xx_wdog.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/rk30xx_wdog.h
===================================================================
--- trunk/sys/arm/rockchip/rk30xx_wdog.h (rev 0)
+++ trunk/sys/arm/rockchip/rk30xx_wdog.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,36 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/rockchip/rk30xx_wdog.h 266337 2014-05-17 18:53:36Z ian $
+ *
+ */
+#ifndef __RK30XX_WDOG_H__
+#define __RK30XX_WDOG_H__
+
+void rk30_wd_watchdog_reset(void);
+
+#endif /*__RK30XX_WDOG_H__*/
+
Property changes on: trunk/sys/arm/rockchip/rk30xx_wdog.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/rockchip/std.rk30xx
===================================================================
--- trunk/sys/arm/rockchip/std.rk30xx (rev 0)
+++ trunk/sys/arm/rockchip/std.rk30xx 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,26 @@
+# Rockchip rk30xx common options
+#$FreeBSD: stable/10/sys/arm/rockchip/std.rk30xx 278601 2015-02-11 22:47:48Z ian $
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+makeoption ARM_LITTLE_ENDIAN
+
+# Physical memory starts at 0x60400000. We assume images are loaded at
+# 0x60400000.
+#
+#
+options PHYSADDR=0x60000000
+
+makeoptions KERNPHYSADDR=0x60400000
+options KERNPHYSADDR=0x60400000
+
+makeoptions KERNVIRTADDR=0xc0400000
+options KERNVIRTADDR=0xc0400000
+
+options ARM_L2_PIPT
+
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
+
+files "../rockchip/files.rk30xx"
Property changes on: trunk/sys/arm/rockchip/std.rk30xx
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/chrome_ec.c
===================================================================
--- trunk/sys/arm/samsung/exynos/chrome_ec.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/chrome_ec.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,267 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPREC OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNEC FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINEC INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Samsung Chromebook Embedded Controller
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/chrome_ec.c 266341 2014-05-17 19:37:04Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <sys/gpio.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/iicbus/iiconf.h>
+
+#include "iicbus_if.h"
+#include "gpio_if.h"
+
+#include <arm/samsung/exynos/chrome_ec.h>
+
+/* TODO: export to DTS */
+#define OUR_GPIO 177
+#define EC_GPIO 168
+
+struct ec_softc {
+ device_t dev;
+};
+
+struct ec_softc *ec_sc;
+
+/*
+ * bus_claim, bus_release
+ * both functions used for bus arbitration
+ * in multi-master mode
+ */
+
+static int
+bus_claim(struct ec_softc *sc)
+{
+ device_t gpio_dev;
+ int status;
+
+ gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (gpio_dev == NULL) {
+ device_printf(sc->dev, "cant find gpio_dev\n");
+ return (1);
+ }
+
+ /* Say we want the bus */
+ GPIO_PIN_SET(gpio_dev, OUR_GPIO, GPIO_PIN_LOW);
+
+ /* Check EC decision */
+ GPIO_PIN_GET(gpio_dev, EC_GPIO, &status);
+
+ if (status == 1) {
+ /* Okay. We have bus */
+ return (0);
+ }
+
+ /* EC is master */
+ return (-1);
+}
+
+static int
+bus_release(struct ec_softc *sc)
+{
+ device_t gpio_dev;
+
+ gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (gpio_dev == NULL) {
+ device_printf(sc->dev, "cant find gpio_dev\n");
+ return (1);
+ }
+
+ GPIO_PIN_SET(gpio_dev, OUR_GPIO, GPIO_PIN_HIGH);
+
+ return (0);
+}
+
+static int
+ec_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Chromebook Embedded Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+fill_checksum(uint8_t *data_out, int len)
+{
+ int res;
+ int i;
+
+ res = 0;
+ for (i = 0; i < len; i++) {
+ res += data_out[i];
+ }
+
+ data_out[len] = (res & 0xff);
+
+ return (0);
+}
+
+int
+ec_command(uint8_t cmd, uint8_t *dout, uint8_t dout_len,
+ uint8_t *dinp, uint8_t dinp_len)
+{
+ struct ec_softc *sc;
+ uint8_t *msg_dout;
+ uint8_t *msg_dinp;
+ int ret;
+ int i;
+
+ msg_dout = malloc(dout_len + 4, M_DEVBUF, M_NOWAIT);
+ msg_dinp = malloc(dinp_len + 4, M_DEVBUF, M_NOWAIT);
+
+ if (ec_sc == NULL)
+ return (-1);
+
+ sc = ec_sc;
+
+ msg_dout[0] = EC_CMD_VERSION0;
+ msg_dout[1] = cmd;
+ msg_dout[2] = dout_len;
+
+ for (i = 0; i < dout_len; i++) {
+ msg_dout[i + 3] = dout[i];
+ };
+
+ fill_checksum(msg_dout, dout_len + 3);
+
+ struct iic_msg msgs[] = {
+ { 0x1e, IIC_M_WR, dout_len + 4, msg_dout, },
+ { 0x1e, IIC_M_RD, dinp_len + 4, msg_dinp, },
+ };
+
+ ret = iicbus_transfer(sc->dev, msgs, 2);
+ if (ret != 0) {
+ device_printf(sc->dev, "i2c transfer returned %d\n", ret);
+ free(msg_dout, M_DEVBUF);
+ free(msg_dinp, M_DEVBUF);
+ return (-1);
+ }
+
+ for (i = 0; i < dinp_len; i++) {
+ dinp[i] = msg_dinp[i + 3];
+ };
+
+ free(msg_dout, M_DEVBUF);
+ free(msg_dinp, M_DEVBUF);
+ return (0);
+}
+
+int ec_hello(void)
+{
+ uint8_t data_in[4];
+ uint8_t data_out[4];
+
+ data_in[0] = 0x40;
+ data_in[1] = 0x30;
+ data_in[2] = 0x20;
+ data_in[3] = 0x10;
+
+ ec_command(EC_CMD_MKBP_STATE, data_in, 4,
+ data_out, 4);
+
+ return (0);
+}
+
+static int
+ec_attach(device_t dev)
+{
+ struct ec_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ ec_sc = sc;
+
+ /*
+ * Claim the bus.
+ *
+ * We don't know cases when EC is master,
+ * so hold the bus forever for us.
+ *
+ */
+
+ if (bus_claim(sc) != 0) {
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+ec_detach(device_t dev)
+{
+ struct ec_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ bus_release(sc);
+
+ return (0);
+}
+
+static device_method_t ec_methods[] = {
+ DEVMETHOD(device_probe, ec_probe),
+ DEVMETHOD(device_attach, ec_attach),
+ DEVMETHOD(device_detach, ec_detach),
+ { 0, 0 }
+};
+
+static driver_t ec_driver = {
+ "chrome_ec",
+ ec_methods,
+ sizeof(struct ec_softc),
+};
+
+static devclass_t ec_devclass;
+
+DRIVER_MODULE(chrome_ec, iicbus, ec_driver, ec_devclass, 0, 0);
+MODULE_VERSION(chrome_ec, 1);
+MODULE_DEPEND(chrome_ec, iicbus, 1, 1, 1);
Property changes on: trunk/sys/arm/samsung/exynos/chrome_ec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/chrome_ec.h
===================================================================
--- trunk/sys/arm/samsung/exynos/chrome_ec.h (rev 0)
+++ trunk/sys/arm/samsung/exynos/chrome_ec.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/exynos/chrome_ec.h 266341 2014-05-17 19:37:04Z ian $
+ */
+
+#define EC_CMD_HELLO 0x01
+#define EC_CMD_GET_VERSION 0x02
+#define EC_CMD_MKBP_STATE 0x60
+#define EC_CMD_VERSION0 0xdc
+
+int ec_command(uint8_t cmd, uint8_t *dout, uint8_t dout_len,
+ uint8_t *dinp, uint8_t dinp_len);
+int ec_hello(void);
Property changes on: trunk/sys/arm/samsung/exynos/chrome_ec.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/chrome_kb.c
===================================================================
--- trunk/sys/arm/samsung/exynos/chrome_kb.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/chrome_kb.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,792 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Samsung Chromebook Keyboard
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/chrome_kb.c 266352 2014-05-17 20:52:10Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/kdb.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <sys/ioccom.h>
+#include <sys/filio.h>
+#include <sys/tty.h>
+#include <sys/kbio.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include "gpio_if.h"
+
+#include <arm/samsung/exynos/chrome_ec.h>
+#include <arm/samsung/exynos/chrome_kb.h>
+
+#include <arm/samsung/exynos/exynos5_combiner.h>
+#include <arm/samsung/exynos/exynos5_pad.h>
+
+#define CKB_LOCK() mtx_lock(&Giant)
+#define CKB_UNLOCK() mtx_unlock(&Giant)
+
+#ifdef INVARIANTS
+/*
+ * Assert that the lock is held in all contexts
+ * where the code can be executed.
+ */
+#define CKB_LOCK_ASSERT() mtx_assert(&Giant, MA_OWNED)
+/*
+ * Assert that the lock is held in the contexts
+ * where it really has to be so.
+ */
+#define CKB_CTX_LOCK_ASSERT() \
+ do { \
+ if (!kdb_active && panicstr == NULL) \
+ mtx_assert(&Giant, MA_OWNED); \
+ } while (0)
+#else
+#define CKB_LOCK_ASSERT() (void)0
+#define CKB_CTX_LOCK_ASSERT() (void)0
+#endif
+
+/*
+ * Define a stub keyboard driver in case one hasn't been
+ * compiled into the kernel
+ */
+#include <sys/kbio.h>
+#include <dev/kbd/kbdreg.h>
+#include <dev/kbd/kbdtables.h>
+
+#define CKB_NFKEY 12
+#define CKB_FLAG_COMPOSE 0x1
+#define CKB_FLAG_POLLING 0x2
+#define KBD_DRIVER_NAME "ckbd"
+
+/* TODO: take interrupt from DTS */
+#define KB_GPIO_INT 146
+
+struct ckb_softc {
+ keyboard_t sc_kbd;
+ keymap_t sc_keymap;
+ accentmap_t sc_accmap;
+ fkeytab_t sc_fkeymap[CKB_NFKEY];
+
+ struct resource* sc_mem_res;
+ struct resource* sc_irq_res;
+ void* sc_intr_hl;
+
+ int sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
+ int sc_state; /* shift/lock key state */
+ int sc_accents; /* accent key index (> 0) */
+ int sc_flags; /* flags */
+
+ struct callout sc_repeat_callout;
+ int sc_repeat_key;
+ int sc_repeating;
+
+ int flag;
+ int rows;
+ int cols;
+ device_t dev;
+ struct thread *sc_poll_thread;
+
+ uint8_t *scan_local;
+ uint8_t *scan;
+};
+
+/* prototypes */
+static int ckb_set_typematic(keyboard_t *, int);
+static uint32_t ckb_read_char(keyboard_t *, int);
+static void ckb_clear_state(keyboard_t *);
+static int ckb_ioctl(keyboard_t *, u_long, caddr_t);
+static int ckb_enable(keyboard_t *);
+static int ckb_disable(keyboard_t *);
+
+static void
+ckb_repeat(void *arg)
+{
+ struct ckb_softc *sc;
+
+ sc = arg;
+
+ if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
+ if (sc->sc_repeat_key != -1) {
+ sc->sc_repeating = 1;
+ sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
+ KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
+ }
+ }
+}
+
+/* detect a keyboard, not used */
+static int
+ckb__probe(int unit, void *arg, int flags)
+{
+
+ return (ENXIO);
+}
+
+/* reset and initialize the device, not used */
+static int
+ckb_init(int unit, keyboard_t **kbdp, void *arg, int flags)
+{
+
+ return (ENXIO);
+}
+
+/* test the interface to the device, not used */
+static int
+ckb_test_if(keyboard_t *kbd)
+{
+
+ return (0);
+}
+
+/* finish using this keyboard, not used */
+static int
+ckb_term(keyboard_t *kbd)
+{
+
+ return (ENXIO);
+}
+
+/* keyboard interrupt routine, not used */
+static int
+ckb_intr(keyboard_t *kbd, void *arg)
+{
+
+ return (0);
+}
+
+/* lock the access to the keyboard, not used */
+static int
+ckb_lock(keyboard_t *kbd, int lock)
+{
+
+ return (1);
+}
+
+/* clear the internal state of the keyboard */
+static void
+ckb_clear_state(keyboard_t *kbd)
+{
+ struct ckb_softc *sc;
+
+ sc = kbd->kb_data;
+
+ CKB_CTX_LOCK_ASSERT();
+
+ sc->sc_flags &= ~(CKB_FLAG_COMPOSE | CKB_FLAG_POLLING);
+ sc->sc_state &= LOCK_MASK; /* preserve locking key state */
+ sc->sc_accents = 0;
+}
+
+/* save the internal state, not used */
+static int
+ckb_get_state(keyboard_t *kbd, void *buf, size_t len)
+{
+
+ return (len == 0) ? 1 : -1;
+}
+
+/* set the internal state, not used */
+static int
+ckb_set_state(keyboard_t *kbd, void *buf, size_t len)
+{
+
+ return (EINVAL);
+}
+
+
+/* check if data is waiting */
+static int
+ckb_check(keyboard_t *kbd)
+{
+ struct ckb_softc *sc;
+ int i;
+
+ sc = kbd->kb_data;
+
+ CKB_CTX_LOCK_ASSERT();
+
+ if (!KBD_IS_ACTIVE(kbd))
+ return (0);
+
+ if (sc->sc_flags & CKB_FLAG_POLLING) {
+ return (1);
+ };
+
+ for (i = 0; i < sc->cols; i++)
+ if (sc->scan_local[i] != sc->scan[i]) {
+ return (1);
+ };
+
+ if (sc->sc_repeating)
+ return (1);
+
+ return (0);
+}
+
+/* check if char is waiting */
+static int
+ckb_check_char_locked(keyboard_t *kbd)
+{
+ CKB_CTX_LOCK_ASSERT();
+
+ if (!KBD_IS_ACTIVE(kbd))
+ return (0);
+
+ return (ckb_check(kbd));
+}
+
+static int
+ckb_check_char(keyboard_t *kbd)
+{
+ int result;
+
+ CKB_LOCK();
+ result = ckb_check_char_locked(kbd);
+ CKB_UNLOCK();
+
+ return (result);
+}
+
+/* read one byte from the keyboard if it's allowed */
+/* Currently unused. */
+static int
+ckb_read(keyboard_t *kbd, int wait)
+{
+ CKB_CTX_LOCK_ASSERT();
+
+ if (!KBD_IS_ACTIVE(kbd))
+ return (-1);
+
+ printf("Implement ME: %s\n", __func__);
+ return (0);
+}
+
+int scantokey(int i, int j);
+
+int
+scantokey(int i, int j)
+{
+ int k;
+
+ for (k = 0; k < KEYMAP_LEN; k++)
+ if ((keymap[k].col == i) && (keymap[k].row == j))
+ return (keymap[k].key);
+
+ return (0);
+}
+
+/* read char from the keyboard */
+static uint32_t
+ckb_read_char_locked(keyboard_t *kbd, int wait)
+{
+ struct ckb_softc *sc;
+ int i,j;
+ uint16_t key;
+ int oldbit;
+ int newbit;
+
+ sc = kbd->kb_data;
+
+ CKB_CTX_LOCK_ASSERT();
+
+ if (!KBD_IS_ACTIVE(kbd))
+ return (NOKEY);
+
+ if (sc->sc_repeating) {
+ sc->sc_repeating = 0;
+ callout_reset(&sc->sc_repeat_callout, hz / 10,
+ ckb_repeat, sc);
+ return (sc->sc_repeat_key);
+ };
+
+ if (sc->sc_flags & CKB_FLAG_POLLING) {
+ /* TODO */
+ };
+
+ for (i = 0; i < sc->cols; i++) {
+ for (j = 0; j < sc->rows; j++) {
+ oldbit = (sc->scan_local[i] & (1 << j));
+ newbit = (sc->scan[i] & (1 << j));
+
+ if (oldbit == newbit)
+ continue;
+
+ key = scantokey(i,j);
+ if (key == 0) {
+ continue;
+ };
+
+ if (newbit > 0) {
+ /* key pressed */
+ sc->scan_local[i] |= (1 << j);
+
+ /* setup repeating */
+ sc->sc_repeat_key = key;
+ callout_reset(&sc->sc_repeat_callout,
+ hz / 2, ckb_repeat, sc);
+
+ } else {
+ /* key released */
+ sc->scan_local[i] &= ~(1 << j);
+
+ /* release flag */
+ key |= 0x80;
+
+ /* unsetup repeating */
+ sc->sc_repeat_key = -1;
+ callout_stop(&sc->sc_repeat_callout);
+ }
+
+ return (key);
+ }
+ }
+
+ return (NOKEY);
+}
+
+/* Currently wait is always false. */
+static uint32_t
+ckb_read_char(keyboard_t *kbd, int wait)
+{
+ uint32_t keycode;
+
+ CKB_LOCK();
+ keycode = ckb_read_char_locked(kbd, wait);
+ CKB_UNLOCK();
+
+ return (keycode);
+}
+
+
+/* some useful control functions */
+static int
+ckb_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg)
+{
+ struct ckb_softc *sc;
+ int i;
+
+ sc = kbd->kb_data;
+
+ CKB_LOCK_ASSERT();
+
+ switch (cmd) {
+ case KDGKBMODE: /* get keyboard mode */
+ *(int *)arg = sc->sc_mode;
+ break;
+
+ case KDSKBMODE: /* set keyboard mode */
+ switch (*(int *)arg) {
+ case K_XLATE:
+ if (sc->sc_mode != K_XLATE) {
+ /* make lock key state and LED state match */
+ sc->sc_state &= ~LOCK_MASK;
+ sc->sc_state |= KBD_LED_VAL(kbd);
+ }
+ /* FALLTHROUGH */
+ case K_RAW:
+ case K_CODE:
+ if (sc->sc_mode != *(int *)arg) {
+ if ((sc->sc_flags & CKB_FLAG_POLLING) == 0)
+ ckb_clear_state(kbd);
+ sc->sc_mode = *(int *)arg;
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+
+ case KDGETLED: /* get keyboard LED */
+ *(int *)arg = KBD_LED_VAL(kbd);
+ break;
+
+ case KDSETLED: /* set keyboard LED */
+ /* NOTE: lock key state in "sc_state" won't be changed */
+ if (*(int *)arg & ~LOCK_MASK)
+ return (EINVAL);
+
+ i = *(int *)arg;
+
+ /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
+ if (sc->sc_mode == K_XLATE &&
+ kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
+ if (i & ALKED)
+ i |= CLKED;
+ else
+ i &= ~CLKED;
+ }
+ if (KBD_HAS_DEVICE(kbd)) {
+ /* Configure LED */
+ }
+
+ KBD_LED_VAL(kbd) = *(int *)arg;
+ break;
+ case KDGKBSTATE: /* get lock key state */
+ *(int *)arg = sc->sc_state & LOCK_MASK;
+ break;
+
+ case KDSKBSTATE: /* set lock key state */
+ if (*(int *)arg & ~LOCK_MASK) {
+ return (EINVAL);
+ }
+ sc->sc_state &= ~LOCK_MASK;
+ sc->sc_state |= *(int *)arg;
+
+ /* set LEDs and quit */
+ return (ckb_ioctl(kbd, KDSETLED, arg));
+
+ case KDSETREPEAT: /* set keyboard repeat rate (new
+ * interface) */
+
+ if (!KBD_HAS_DEVICE(kbd)) {
+ return (0);
+ }
+ if (((int *)arg)[1] < 0) {
+ return (EINVAL);
+ }
+ if (((int *)arg)[0] < 0) {
+ return (EINVAL);
+ }
+ if (((int *)arg)[0] < 200) /* fastest possible value */
+ kbd->kb_delay1 = 200;
+ else
+ kbd->kb_delay1 = ((int *)arg)[0];
+ kbd->kb_delay2 = ((int *)arg)[1];
+ return (0);
+
+ case KDSETRAD: /* set keyboard repeat rate (old
+ * interface) */
+ return (ckb_set_typematic(kbd, *(int *)arg));
+
+ case PIO_KEYMAP: /* set keyboard translation table */
+ case OPIO_KEYMAP: /* set keyboard translation table
+ * (compat) */
+ case PIO_KEYMAPENT: /* set keyboard translation table
+ * entry */
+ case PIO_DEADKEYMAP: /* set accent key translation table */
+ sc->sc_accents = 0;
+ /* FALLTHROUGH */
+ default:
+ return (genkbd_commonioctl(kbd, cmd, arg));
+ }
+
+ return (0);
+}
+
+static int
+ckb_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
+{
+ int result;
+
+ /*
+ * XXX KDGKBSTATE, KDSKBSTATE and KDSETLED can be called from any
+ * context where printf(9) can be called, which among other things
+ * includes interrupt filters and threads with any kinds of locks
+ * already held. For this reason it would be dangerous to acquire
+ * the Giant here unconditionally. On the other hand we have to
+ * have it to handle the ioctl.
+ * So we make our best effort to auto-detect whether we can grab
+ * the Giant or not. Blame syscons(4) for this.
+ */
+ switch (cmd) {
+ case KDGKBSTATE:
+ case KDSKBSTATE:
+ case KDSETLED:
+ if (!mtx_owned(&Giant) && !SCHEDULER_STOPPED())
+ return (EDEADLK); /* best I could come up with */
+ /* FALLTHROUGH */
+ default:
+ CKB_LOCK();
+ result = ckb_ioctl_locked(kbd, cmd, arg);
+ CKB_UNLOCK();
+ return (result);
+ }
+}
+
+
+/*
+ * Enable the access to the device; until this function is called,
+ * the client cannot read from the keyboard.
+ */
+static int
+ckb_enable(keyboard_t *kbd)
+{
+
+ CKB_LOCK();
+ KBD_ACTIVATE(kbd);
+ CKB_UNLOCK();
+
+ return (0);
+}
+
+/* disallow the access to the device */
+static int
+ckb_disable(keyboard_t *kbd)
+{
+
+ CKB_LOCK();
+ KBD_DEACTIVATE(kbd);
+ CKB_UNLOCK();
+
+ return (0);
+}
+
+/* local functions */
+
+static int
+ckb_set_typematic(keyboard_t *kbd, int code)
+{
+ static const int delays[] = {250, 500, 750, 1000};
+ static const int rates[] = {34, 38, 42, 46, 50, 55, 59, 63,
+ 68, 76, 84, 92, 100, 110, 118, 126,
+ 136, 152, 168, 184, 200, 220, 236, 252,
+ 272, 304, 336, 368, 400, 440, 472, 504};
+
+ if (code & ~0x7f) {
+ return (EINVAL);
+ }
+ kbd->kb_delay1 = delays[(code >> 5) & 3];
+ kbd->kb_delay2 = rates[code & 0x1f];
+ return (0);
+}
+
+static int
+ckb_poll(keyboard_t *kbd, int on)
+{
+ struct ckb_softc *sc;
+
+ sc = kbd->kb_data;
+
+ CKB_LOCK();
+ if (on) {
+ sc->sc_flags |= CKB_FLAG_POLLING;
+ sc->sc_poll_thread = curthread;
+ } else {
+ sc->sc_flags &= ~CKB_FLAG_POLLING;
+ }
+ CKB_UNLOCK();
+
+ return (0);
+}
+
+/* local functions */
+
+static int dummy_kbd_configure(int flags);
+
+keyboard_switch_t ckbdsw = {
+ .probe = &ckb__probe,
+ .init = &ckb_init,
+ .term = &ckb_term,
+ .intr = &ckb_intr,
+ .test_if = &ckb_test_if,
+ .enable = &ckb_enable,
+ .disable = &ckb_disable,
+ .read = &ckb_read,
+ .check = &ckb_check,
+ .read_char = &ckb_read_char,
+ .check_char = &ckb_check_char,
+ .ioctl = &ckb_ioctl,
+ .lock = &ckb_lock,
+ .clear_state = &ckb_clear_state,
+ .get_state = &ckb_get_state,
+ .set_state = &ckb_set_state,
+ .get_fkeystr = &genkbd_get_fkeystr,
+ .poll = &ckb_poll,
+ .diag = &genkbd_diag,
+};
+
+static int
+dummy_kbd_configure(int flags)
+{
+
+ return (0);
+}
+
+KEYBOARD_DRIVER(ckbd, ckbdsw, dummy_kbd_configure);
+
+static int
+parse_dts(struct ckb_softc *sc)
+{
+ phandle_t node;
+ pcell_t dts_value;
+ int len;
+
+ if ((node = ofw_bus_get_node(sc->dev)) == -1)
+ return (ENXIO);
+
+ if ((len = OF_getproplen(node, "keypad,num-rows")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "keypad,num-rows", &dts_value, len);
+ sc->rows = fdt32_to_cpu(dts_value);
+
+ if ((len = OF_getproplen(node, "keypad,num-columns")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "keypad,num-columns", &dts_value, len);
+ sc->cols = fdt32_to_cpu(dts_value);
+
+ if ((sc->rows == 0) || (sc->cols == 0))
+ return (ENXIO);
+
+ return (0);
+}
+
+void
+ckb_ec_intr(void *arg)
+{
+ struct ckb_softc *sc;
+
+ sc = arg;
+
+ if (sc->sc_flags & CKB_FLAG_POLLING)
+ return;
+
+ ec_command(EC_CMD_MKBP_STATE, sc->scan, sc->cols,
+ sc->scan, sc->cols);
+
+ (sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
+ sc->sc_kbd.kb_callback.kc_arg);
+};
+
+static int
+chrome_kb_attach(device_t dev)
+{
+ struct ckb_softc *sc;
+ keyboard_t *kbd;
+ int error;
+ int rid;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ sc->dev = dev;
+
+ if ((error = parse_dts(sc)) != 0)
+ return error;
+
+#if 0
+ device_printf(sc->dev, "Keyboard matrix [%dx%d]\n",
+ sc->cols, sc->rows);
+#endif
+
+ /* TODO: take interrupt from DTS */
+ pad_setup_intr(KB_GPIO_INT, ckb_ec_intr, sc);
+
+ kbd = &sc->sc_kbd;
+ rid = 0;
+
+ sc->scan_local = malloc(sc->cols, M_DEVBUF, M_NOWAIT);
+ sc->scan = malloc(sc->cols, M_DEVBUF, M_NOWAIT);
+
+ for (i = 0; i < sc->cols; i++) {
+ sc->scan_local[i] = 0;
+ sc->scan[i] = 0;
+ };
+
+ kbd_init_struct(kbd, KBD_DRIVER_NAME, KB_OTHER,
+ device_get_unit(dev), 0, 0, 0);
+ kbd->kb_data = (void *)sc;
+
+ sc->sc_keymap = key_map;
+ sc->sc_accmap = accent_map;
+ for (i = 0; i < CKB_NFKEY; i++) {
+ sc->sc_fkeymap[i] = fkey_tab[i];
+ }
+
+ kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap,
+ sc->sc_fkeymap, CKB_NFKEY);
+
+ KBD_FOUND_DEVICE(kbd);
+ ckb_clear_state(kbd);
+ KBD_PROBE_DONE(kbd);
+
+ callout_init(&sc->sc_repeat_callout, 0);
+
+ KBD_INIT_DONE(kbd);
+
+ if (kbd_register(kbd) < 0) {
+ return (ENXIO);
+ };
+ KBD_CONFIG_DONE(kbd);
+
+ return (0);
+}
+
+static int
+chrome_kb_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "google,cros-ec-keyb")) {
+ device_set_desc(dev, "Chrome EC Keyboard");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static device_method_t chrome_kb_methods[] = {
+ DEVMETHOD(device_probe, chrome_kb_probe),
+ DEVMETHOD(device_attach, chrome_kb_attach),
+ { 0, 0 }
+};
+
+static driver_t chrome_kb_driver = {
+ "chrome_kb",
+ chrome_kb_methods,
+ sizeof(struct ckb_softc),
+};
+
+static devclass_t chrome_kb_devclass;
+
+DRIVER_MODULE(chrome_kb, simplebus, chrome_kb_driver,
+ chrome_kb_devclass, 0, 0);
Property changes on: trunk/sys/arm/samsung/exynos/chrome_kb.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/chrome_kb.h
===================================================================
--- trunk/sys/arm/samsung/exynos/chrome_kb.h (rev 0)
+++ trunk/sys/arm/samsung/exynos/chrome_kb.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,123 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/exynos/chrome_kb.h 266341 2014-05-17 19:37:04Z ian $
+ */
+
+void ckb_ec_intr(void *);
+
+struct key {
+ uint8_t row;
+ uint8_t col;
+ uint8_t key;
+};
+
+#define KEYMAP_LEN 75
+
+struct key keymap[KEYMAP_LEN] = {
+ { 0x00, 0x01, 0x7d }, /* lmeta */
+ { 0x00, 0x02, 0x3b }, /* F1 */
+ { 0x00, 0x03, 0x30 }, /* B */
+ { 0x00, 0x04, 0x44 }, /* F10 */
+ { 0x00, 0x06, 0x31 }, /* N */
+ { 0x00, 0x08, 0x0d }, /* = */
+ { 0x00, 0x0a, 0x64 }, /* ralt */
+
+ { 0x01, 0x01, 0x01 }, /* escape */
+ { 0x01, 0x02, 0x3e }, /* F4 */
+ { 0x01, 0x03, 0x22 }, /* G */
+ { 0x01, 0x04, 0x41 }, /* F7 */
+ { 0x01, 0x06, 0x23 }, /* H */
+ { 0x01, 0x08, 0x28 }, /* ' */
+ { 0x01, 0x09, 0x43 }, /* F9 */
+ { 0x01, 0x0b, 0x0e }, /* backspace */
+
+ { 0x02, 0x00, 0x1d }, /* lctrl */
+ { 0x02, 0x01, 0x0f }, /* tab */
+ { 0x02, 0x02, 0x3d }, /* F3 */
+ { 0x02, 0x03, 0x14 }, /* t */
+ { 0x02, 0x04, 0x40 }, /* F6 */
+ { 0x02, 0x05, 0x1b }, /* ] */
+ { 0x02, 0x06, 0x15 }, /* y */
+ { 0x02, 0x07, 0x56 }, /* 102nd */
+ { 0x02, 0x08, 0x1a }, /* [ */
+ { 0x02, 0x09, 0x42 }, /* F8 */
+
+ { 0x03, 0x01, 0x29 }, /* grave */
+ { 0x03, 0x02, 0x3c }, /* F2 */
+ { 0x03, 0x03, 0x06 }, /* 5 */
+ { 0x03, 0x04, 0x3f }, /* F5 */
+ { 0x03, 0x06, 0x07 }, /* 6 */
+ { 0x03, 0x08, 0x0c }, /* - */
+ { 0x03, 0x0b, 0x2b }, /* \ */
+
+ { 0x04, 0x00, 0x61 }, /* rctrl */
+ { 0x04, 0x01, 0x1e }, /* a */
+ { 0x04, 0x02, 0x20 }, /* d */
+ { 0x04, 0x03, 0x21 }, /* f */
+ { 0x04, 0x04, 0x1f }, /* s */
+ { 0x04, 0x05, 0x25 }, /* k */
+ { 0x04, 0x06, 0x24 }, /* j */
+ { 0x04, 0x08, 0x27 }, /* ; */
+ { 0x04, 0x09, 0x26 }, /* l */
+ { 0x04, 0x0a, 0x2b }, /* \ */
+ { 0x04, 0x0b, 0x1c }, /* enter */
+
+ { 0x05, 0x01, 0x2c }, /* z */
+ { 0x05, 0x02, 0x2e }, /* c */
+ { 0x05, 0x03, 0x2f }, /* v */
+ { 0x05, 0x04, 0x2d }, /* x */
+ { 0x05, 0x05, 0x33 }, /* , */
+ { 0x05, 0x06, 0x32 }, /* m */
+ { 0x05, 0x07, 0x2a }, /* lsh */
+ { 0x05, 0x08, 0x35 }, /* / */
+ { 0x05, 0x09, 0x34 }, /* . */
+ { 0x05, 0x0B, 0x39 }, /* space */
+
+ { 0x06, 0x01, 0x02 }, /* 1 */
+ { 0x06, 0x02, 0x04 }, /* 3 */
+ { 0x06, 0x03, 0x05 }, /* 4 */
+ { 0x06, 0x04, 0x03 }, /* 2 */
+ { 0x06, 0x05, 0x09 }, /* 8 */
+ { 0x06, 0x06, 0x08 }, /* 7 */
+ { 0x06, 0x08, 0x0b }, /* 0 */
+ { 0x06, 0x09, 0x0a }, /* 9 */
+ { 0x06, 0x0a, 0x38 }, /* lalt */
+ { 0x06, 0x0b, 0x64 }, /* down */
+ { 0x06, 0x0c, 0x62 }, /* right */
+
+ { 0x07, 0x01, 0x10 }, /* q */
+ { 0x07, 0x02, 0x12 }, /* e */
+ { 0x07, 0x03, 0x13 }, /* r */
+ { 0x07, 0x04, 0x11 }, /* w */
+ { 0x07, 0x05, 0x17 }, /* i */
+ { 0x07, 0x06, 0x16 }, /* u */
+ { 0x07, 0x07, 0x36 }, /* rsh */
+ { 0x07, 0x08, 0x19 }, /* p */
+ { 0x07, 0x09, 0x18 }, /* o */
+ { 0x07, 0x0b, 0x5F }, /* up */
+ { 0x07, 0x0c, 0x61 }, /* left */
+};
Property changes on: trunk/sys/arm/samsung/exynos/chrome_kb.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_combiner.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_combiner.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_combiner.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,305 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Samsung Exynos 5 Interrupt Combiner
+ * Chapter 7, Exynos 5 Dual User's Manual Public Rev 1.00
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_combiner.c 266341 2014-05-17 19:37:04Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/samsung/exynos/exynos5_common.h>
+#include <arm/samsung/exynos/exynos5_combiner.h>
+
+#define NGRP 32
+#define ITABLE_LEN 24
+
+#define IESR(n) (0x10 * n + 0x0) /* Interrupt enable set */
+#define IECR(n) (0x10 * n + 0x4) /* Interrupt enable clear */
+#define ISTR(n) (0x10 * n + 0x8) /* Interrupt status */
+#define IMSR(n) (0x10 * n + 0xC) /* Interrupt masked status */
+#define CIPSR 0x100 /* Combined interrupt pending */
+
+struct combiner_softc {
+ struct resource *res[1 + NGRP];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ void *ih[NGRP];
+ device_t dev;
+};
+
+struct combiner_softc *combiner_sc;
+
+static struct resource_spec combiner_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { SYS_RES_IRQ, 4, RF_ACTIVE },
+ { SYS_RES_IRQ, 5, RF_ACTIVE },
+ { SYS_RES_IRQ, 6, RF_ACTIVE },
+ { SYS_RES_IRQ, 7, RF_ACTIVE },
+ { SYS_RES_IRQ, 8, RF_ACTIVE },
+ { SYS_RES_IRQ, 9, RF_ACTIVE },
+ { SYS_RES_IRQ, 10, RF_ACTIVE },
+ { SYS_RES_IRQ, 11, RF_ACTIVE },
+ { SYS_RES_IRQ, 12, RF_ACTIVE },
+ { SYS_RES_IRQ, 13, RF_ACTIVE },
+ { SYS_RES_IRQ, 14, RF_ACTIVE },
+ { SYS_RES_IRQ, 15, RF_ACTIVE },
+ { SYS_RES_IRQ, 16, RF_ACTIVE },
+ { SYS_RES_IRQ, 17, RF_ACTIVE },
+ { SYS_RES_IRQ, 18, RF_ACTIVE },
+ { SYS_RES_IRQ, 19, RF_ACTIVE },
+ { SYS_RES_IRQ, 20, RF_ACTIVE },
+ { SYS_RES_IRQ, 21, RF_ACTIVE },
+ { SYS_RES_IRQ, 22, RF_ACTIVE },
+ { SYS_RES_IRQ, 23, RF_ACTIVE },
+ { SYS_RES_IRQ, 24, RF_ACTIVE },
+ { SYS_RES_IRQ, 25, RF_ACTIVE },
+ { SYS_RES_IRQ, 26, RF_ACTIVE },
+ { SYS_RES_IRQ, 27, RF_ACTIVE },
+ { SYS_RES_IRQ, 28, RF_ACTIVE },
+ { SYS_RES_IRQ, 29, RF_ACTIVE },
+ { SYS_RES_IRQ, 30, RF_ACTIVE },
+ { SYS_RES_IRQ, 31, RF_ACTIVE },
+ { -1, 0 }
+};
+
+struct combiner_entry {
+ int combiner_id;
+ int bit;
+ char *source_name;
+};
+
+static struct combiner_entry interrupt_table[ITABLE_LEN] = {
+ { 63, 1, "EINT[15]" },
+ { 63, 0, "EINT[14]" },
+ { 62, 1, "EINT[13]" },
+ { 62, 0, "EINT[12]" },
+ { 61, 1, "EINT[11]" },
+ { 61, 0, "EINT[10]" },
+ { 60, 1, "EINT[9]" },
+ { 60, 0, "EINT[8]" },
+ { 59, 1, "EINT[7]" },
+ { 59, 0, "EINT[6]" },
+ { 58, 1, "EINT[5]" },
+ { 58, 0, "EINT[4]" },
+ { 57, 3, "MCT_G3" },
+ { 57, 2, "MCT_G2" },
+ { 57, 1, "EINT[3]" },
+ { 57, 0, "EINT[2]" },
+ { 56, 6, "SYSMMU_G2D[1]" },
+ { 56, 5, "SYSMMU_G2D[0]" },
+ { 56, 2, "SYSMMU_FIMC_LITE1[1]" },
+ { 56, 1, "SYSMMU_FIMC_LITE1[0]" },
+ { 56, 0, "EINT[1]" },
+ { 55, 4, "MCT_G1" },
+ { 55, 3, "MCT_G0" },
+ { 55, 0, "EINT[0]" },
+
+ /* TODO: add groups 54-32 */
+};
+
+struct combined_intr {
+ uint32_t enabled;
+ void (*ih) (void *);
+ void *ih_user;
+};
+
+static struct combined_intr intr_map[32][8];
+
+static void
+combiner_intr(void *arg)
+{
+ struct combiner_softc *sc;
+ void (*ih) (void *);
+ void *ih_user;
+ int enabled;
+ int intrs;
+ int shift;
+ int cirq;
+ int grp;
+ int i,n;
+
+ sc = arg;
+
+ intrs = READ4(sc, CIPSR);
+ for (grp = 0; grp < 32; grp++) {
+ if (intrs & (1 << grp)) {
+ n = (grp / 4);
+ shift = (grp % 4) * 8;
+
+ cirq = READ4(sc, ISTR(n));
+ for (i = 0; i < 8; i++) {
+ if (cirq & (1 << (i + shift))) {
+ ih = intr_map[grp][i].ih;
+ ih_user = intr_map[grp][i].ih_user;
+ enabled = intr_map[grp][i].enabled;
+ if (enabled && (ih != NULL)) {
+ ih(ih_user);
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+combiner_setup_intr(char *source_name, void (*ih)(void *), void *ih_user)
+{
+ struct combiner_entry *entry;
+ struct combined_intr *cirq;
+ struct combiner_softc *sc;
+ int shift;
+ int reg;
+ int grp;
+ int n;
+ int i;
+
+ sc = combiner_sc;
+
+ if (sc == NULL) {
+ device_printf(sc->dev, "Error: combiner is not attached\n");
+ return;
+ }
+
+ entry = NULL;
+
+ for (i = 0; i < ITABLE_LEN; i++) {
+ if (strcmp(interrupt_table[i].source_name, source_name) == 0) {
+ entry = &interrupt_table[i];
+ }
+ }
+
+ if (entry == NULL) {
+ device_printf(sc->dev, "Can't find interrupt name %s\n",
+ source_name);
+ return;
+ }
+
+#if 0
+ device_printf(sc->dev, "Setting up interrupt %s\n", source_name);
+#endif
+
+ grp = entry->combiner_id - 32;
+
+ cirq = &intr_map[grp][entry->bit];
+ cirq->enabled = 1;
+ cirq->ih = ih;
+ cirq->ih_user = ih_user;
+
+ n = grp / 4;
+ shift = (grp % 4) * 8 + entry->bit;
+
+ reg = (1 << shift);
+ WRITE4(sc, IESR(n), reg);
+}
+
+static int
+combiner_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "exynos,combiner"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Samsung Exynos 5 Interrupt Combiner");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+combiner_attach(device_t dev)
+{
+ struct combiner_softc *sc;
+ int err;
+ int i;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, combiner_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ combiner_sc = sc;
+
+ /* Setup interrupt handler */
+ for (i = 0; i < NGRP; i++) {
+ err = bus_setup_intr(dev, sc->res[1+i], INTR_TYPE_BIO | \
+ INTR_MPSAFE, NULL, combiner_intr, sc, &sc->ih[i]);
+ if (err) {
+ device_printf(dev, "Unable to alloc int resource.\n");
+ return (ENXIO);
+ }
+ }
+
+ return (0);
+}
+
+static device_method_t combiner_methods[] = {
+ DEVMETHOD(device_probe, combiner_probe),
+ DEVMETHOD(device_attach, combiner_attach),
+ { 0, 0 }
+};
+
+static driver_t combiner_driver = {
+ "combiner",
+ combiner_methods,
+ sizeof(struct combiner_softc),
+};
+
+static devclass_t combiner_devclass;
+
+DRIVER_MODULE(combiner, simplebus, combiner_driver, combiner_devclass, 0, 0);
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_combiner.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_combiner.h
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_combiner.h (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_combiner.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,30 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_combiner.h 266341 2014-05-17 19:37:04Z ian $
+ */
+
+void combiner_setup_intr(char *source_name, void (*ih)(void *), void *ih_user);
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_combiner.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_common.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_common.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,74 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_common.c 266277 2014-05-17 00:53:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+void
+cpu_reset(void)
+{
+ bus_space_handle_t bsh;
+
+ bus_space_map(fdtbus_bs_tag, 0x10040400, 0x1000, 0, &bsh);
+ bus_space_write_4(fdtbus_bs_tag, bsh, 0, 1);
+
+ while (1);
+}
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (!fdt_is_compatible(node, "arm,gic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_pic_decode_ic,
+ NULL
+};
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_common.h
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_common.h (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_common.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,41 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_common.h 266332 2014-05-17 17:54:38Z ian $
+ */
+
+#define READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst, _sc->bsh, _reg)
+#define WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
+#define READ2(_sc, _reg) \
+ bus_space_read_2(_sc->bst, _sc->bsh, _reg)
+#define WRITE2(_sc, _reg, _val) \
+ bus_space_write_2(_sc->bst, _sc->bsh, _reg, _val)
+#define READ1(_sc, _reg) \
+ bus_space_read_1(_sc->bst, _sc->bsh, _reg)
+#define WRITE1(_sc, _reg, _val) \
+ bus_space_write_1(_sc->bst, _sc->bsh, _reg, _val)
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_common.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_ehci.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_ehci.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_ehci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,371 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_ehci.c 278278 2015-02-05 20:03:02Z hselasky $");
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/rman.h>
+#include <sys/gpio.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include "gpio_if.h"
+
+#include "opt_platform.h"
+
+/* GPIO control */
+#define GPIO_OUTPUT 1
+#define GPIO_INPUT 0
+#define PIN_USB 161
+
+/* PWR control */
+#define EXYNOS5_PWR_USBHOST_PHY 0x708
+#define PHY_POWER_ON 1
+#define PHY_POWER_OFF 0
+
+/* SYSREG */
+#define EXYNOS5_SYSREG_USB2_PHY 0x0
+#define USB2_MODE_HOST 0x1
+
+/* USB HOST */
+#define HOST_CTRL_CLK_24MHZ (5 << 16)
+#define HOST_CTRL_CLK_MASK (7 << 16)
+#define HOST_CTRL_SIDDQ (1 << 6)
+#define HOST_CTRL_SLEEP (1 << 5)
+#define HOST_CTRL_SUSPEND (1 << 4)
+#define HOST_CTRL_RESET_LINK (1 << 1)
+#define HOST_CTRL_RESET_PHY (1 << 0)
+#define HOST_CTRL_RESET_PHY_ALL (1U << 31)
+
+/* Forward declarations */
+static int exynos_ehci_attach(device_t dev);
+static int exynos_ehci_detach(device_t dev);
+static int exynos_ehci_probe(device_t dev);
+
+struct exynos_ehci_softc {
+ device_t dev;
+ ehci_softc_t base;
+ struct resource *res[5];
+ bus_space_tag_t host_bst;
+ bus_space_tag_t pwr_bst;
+ bus_space_tag_t sysreg_bst;
+ bus_space_handle_t host_bsh;
+ bus_space_handle_t pwr_bsh;
+ bus_space_handle_t sysreg_bsh;
+
+};
+
+static struct resource_spec exynos_ehci_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, exynos_ehci_probe),
+ DEVMETHOD(device_attach, exynos_ehci_attach),
+ DEVMETHOD(device_detach, exynos_ehci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+ { 0, 0 }
+};
+
+/* kobj_class definition */
+static driver_t ehci_driver = {
+ "ehci",
+ ehci_methods,
+ sizeof(ehci_softc_t)
+};
+
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
+MODULE_DEPEND(ehci, usb, 1, 1, 1);
+
+/*
+ * Public methods
+ */
+static int
+exynos_ehci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "exynos,usb-ehci") == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Exynos integrated USB controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+gpio_ctrl(struct exynos_ehci_softc *esc, int dir, int power)
+{
+ device_t gpio_dev;
+
+ /* Get the GPIO device, we need this to give power to USB */
+ gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (gpio_dev == NULL) {
+ device_printf(esc->dev, "cant find gpio_dev\n");
+ return (1);
+ }
+
+ if (power)
+ GPIO_PIN_SET(gpio_dev, PIN_USB, GPIO_PIN_HIGH);
+ else
+ GPIO_PIN_SET(gpio_dev, PIN_USB, GPIO_PIN_LOW);
+
+ if (dir)
+ GPIO_PIN_SETFLAGS(gpio_dev, PIN_USB, GPIO_PIN_OUTPUT);
+ else
+ GPIO_PIN_SETFLAGS(gpio_dev, PIN_USB, GPIO_PIN_INPUT);
+
+ return (0);
+}
+
+static int
+phy_init(struct exynos_ehci_softc *esc)
+{
+ int reg;
+
+ gpio_ctrl(esc, GPIO_INPUT, 1);
+
+ /* set USB HOST mode */
+ bus_space_write_4(esc->sysreg_bst, esc->sysreg_bsh,
+ EXYNOS5_SYSREG_USB2_PHY, USB2_MODE_HOST);
+
+ /* Power ON phy */
+ bus_space_write_4(esc->pwr_bst, esc->pwr_bsh,
+ EXYNOS5_PWR_USBHOST_PHY, PHY_POWER_ON);
+
+ reg = bus_space_read_4(esc->host_bst, esc->host_bsh, 0x0);
+ reg &= ~(HOST_CTRL_CLK_MASK |
+ HOST_CTRL_RESET_PHY |
+ HOST_CTRL_RESET_PHY_ALL |
+ HOST_CTRL_SIDDQ |
+ HOST_CTRL_SUSPEND |
+ HOST_CTRL_SLEEP);
+
+ reg |= (HOST_CTRL_CLK_24MHZ |
+ HOST_CTRL_RESET_LINK);
+ bus_space_write_4(esc->host_bst, esc->host_bsh, 0x0, reg);
+
+ DELAY(10);
+
+ reg = bus_space_read_4(esc->host_bst, esc->host_bsh, 0x0);
+ reg &= ~(HOST_CTRL_RESET_LINK);
+ bus_space_write_4(esc->host_bst, esc->host_bsh, 0x0, reg);
+
+ gpio_ctrl(esc, GPIO_OUTPUT, 1);
+
+ return (0);
+}
+
+static int
+exynos_ehci_attach(device_t dev)
+{
+ struct exynos_ehci_softc *esc;
+ ehci_softc_t *sc;
+ bus_space_handle_t bsh;
+ int err;
+
+ esc = device_get_softc(dev);
+ esc->dev = dev;
+ sc = &esc->base;
+ sc->sc_bus.parent = dev;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
+
+ if (bus_alloc_resources(dev, exynos_ehci_spec, esc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* EHCI registers */
+ sc->sc_io_tag = rman_get_bustag(esc->res[0]);
+ bsh = rman_get_bushandle(esc->res[0]);
+ sc->sc_io_size = rman_get_size(esc->res[0]);
+
+ /* EHCI HOST ctrl registers */
+ esc->host_bst = rman_get_bustag(esc->res[1]);
+ esc->host_bsh = rman_get_bushandle(esc->res[1]);
+
+ /* PWR registers */
+ esc->pwr_bst = rman_get_bustag(esc->res[2]);
+ esc->pwr_bsh = rman_get_bushandle(esc->res[2]);
+
+ /* SYSREG */
+ esc->sysreg_bst = rman_get_bustag(esc->res[3]);
+ esc->sysreg_bsh = rman_get_bushandle(esc->res[3]);
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev),
+ &ehci_iterate_hw_softc))
+ return (ENXIO);
+
+ /*
+ * Set handle to USB related registers subregion used by
+ * generic EHCI driver.
+ */
+ err = bus_space_subregion(sc->sc_io_tag, bsh, 0x0,
+ sc->sc_io_size, &sc->sc_io_hdl);
+ if (err != 0)
+ return (ENXIO);
+
+ phy_init(esc);
+
+ /* Setup interrupt handler */
+ err = bus_setup_intr(dev, esc->res[4], INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)ehci_interrupt, sc,
+ &sc->sc_intr_hdl);
+ if (err) {
+ device_printf(dev, "Could not setup irq, "
+ "%d\n", err);
+ return (1);
+ }
+
+ /* Add USB device */
+ sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(dev, "Could not add USB device\n");
+ err = bus_teardown_intr(dev, esc->res[4],
+ sc->sc_intr_hdl);
+ if (err)
+ device_printf(dev, "Could not tear down irq,"
+ " %d\n", err);
+ return (1);
+ }
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+
+ strlcpy(sc->sc_vendor, "Samsung", sizeof(sc->sc_vendor));
+
+ err = ehci_init(sc);
+ if (!err) {
+ sc->sc_flags |= EHCI_SCFLG_DONEINIT;
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ } else {
+ device_printf(dev, "USB init failed err=%d\n", err);
+
+ device_delete_child(dev, sc->sc_bus.bdev);
+ sc->sc_bus.bdev = NULL;
+
+ err = bus_teardown_intr(dev, esc->res[4],
+ sc->sc_intr_hdl);
+ if (err)
+ device_printf(dev, "Could not tear down irq,"
+ " %d\n", err);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+exynos_ehci_detach(device_t dev)
+{
+ struct exynos_ehci_softc *esc;
+ ehci_softc_t *sc;
+ int err;
+
+ esc = device_get_softc(dev);
+ sc = &esc->base;
+
+ if (sc->sc_flags & EHCI_SCFLG_DONEINIT)
+ return (0);
+
+ /*
+ * only call ehci_detach() after ehci_init()
+ */
+ if (sc->sc_flags & EHCI_SCFLG_DONEINIT) {
+ ehci_detach(sc);
+ sc->sc_flags &= ~EHCI_SCFLG_DONEINIT;
+ }
+
+ /*
+ * Disable interrupts that might have been switched on in
+ * ehci_init.
+ */
+ if (sc->sc_io_tag && sc->sc_io_hdl)
+ bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl,
+ EHCI_USBINTR, 0);
+
+ if (esc->res[4] && sc->sc_intr_hdl) {
+ err = bus_teardown_intr(dev, esc->res[4],
+ sc->sc_intr_hdl);
+ if (err) {
+ device_printf(dev, "Could not tear down irq,"
+ " %d\n", err);
+ return (err);
+ }
+ sc->sc_intr_hdl = NULL;
+ }
+
+ if (sc->sc_bus.bdev) {
+ device_delete_child(dev, sc->sc_bus.bdev);
+ sc->sc_bus.bdev = NULL;
+ }
+
+ /* During module unload there are lots of children leftover */
+ device_delete_children(dev);
+
+ bus_release_resources(dev, exynos_ehci_spec, esc->res);
+
+ return (0);
+}
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_ehci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_fimd.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_fimd.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_fimd.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,414 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Samsung Exynos 5 Display Controller
+ * Chapter 15, Exynos 5 Dual User's Manual Public Rev 1.00
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_fimd.c 266358 2014-05-17 21:26:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+#include <sys/eventhandler.h>
+#include <sys/gpio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/vt/vt.h>
+#include <dev/vt/colors/vt_termcolors.h>
+
+#include <arm/samsung/exynos/exynos5_common.h>
+
+#include "gpio_if.h"
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include "fb_if.h"
+
+#define FIMDBYPASS_DISP1 (1 << 15)
+
+#define VIDCON0 (0x0)
+#define VIDCON0_ENVID (1 << 1)
+#define VIDCON0_ENVID_F (1 << 0)
+#define CLKVAL_F 0xb
+#define CLKVAL_F_OFFSET 6
+
+#define WINCON0 0x0020
+#define WINCON1 0x0024
+#define WINCON2 0x0028
+#define WINCON3 0x002C
+#define WINCON4 0x0030
+
+#define ENLOCAL_F (1 << 22)
+#define BPPMODE_F_RGB_16BIT_565 0x5
+#define BPPMODE_F_OFFSET 2
+#define ENWIN_F_ENABLE (1 << 0)
+#define HALF_WORD_SWAP_EN (1 << 16)
+
+#define SHADOWCON 0x0034
+#define CHANNEL0_EN (1 << 0)
+
+#define VIDOSD0A 0x0040
+#define VIDOSD0B 0x0044
+#define VIDOSD0C 0x0048
+
+#define VIDW00ADD0B0 0x00A0
+#define VIDW00ADD0B1 0x00A4
+#define VIDW00ADD0B2 0x20A0
+#define VIDW00ADD1B0 0x00D0
+#define VIDW00ADD1B1 0x00D4
+#define VIDW00ADD1B2 0x20D0
+
+#define VIDW00ADD2 0x0100
+#define VIDW01ADD2 0x0104
+#define VIDW02ADD2 0x0108
+#define VIDW03ADD2 0x010C
+#define VIDW04ADD2 0x0110
+
+#define VIDCON1 (0x04)
+#define VIDTCON0 0x0010
+#define VIDTCON1 0x0014
+#define VIDTCON2 0x0018
+#define VIDTCON3 0x001C
+
+#define VIDINTCON0 0x0130
+#define VIDINTCON1 0x0134
+
+#define VSYNC_PULSE_WIDTH_VAL 0x3
+#define VSYNC_PULSE_WIDTH_OFFSET 0
+#define V_FRONT_PORCH_VAL 0x3
+#define V_FRONT_PORCH_OFFSET 8
+#define V_BACK_PORCH_VAL 0x3
+#define V_BACK_PORCH_OFFSET 16
+
+#define HSYNC_PULSE_WIDTH_VAL 0x3
+#define HSYNC_PULSE_WIDTH_OFFSET 0
+#define H_FRONT_PORCH_VAL 0x3
+#define H_FRONT_PORCH_OFFSET 8
+#define H_BACK_PORCH_VAL 0x3
+#define H_BACK_PORCH_OFFSET 16
+
+#define HOZVAL_OFFSET 0
+#define LINEVAL_OFFSET 11
+
+#define OSD_RIGHTBOTX_F_OFFSET 11
+#define OSD_RIGHTBOTY_F_OFFSET 0
+
+#define DPCLKCON 0x27c
+#define DPCLKCON_EN (1 << 1)
+
+#define DREAD4(_sc, _reg) \
+ bus_space_read_4(_sc->bst_disp, _sc->bsh_disp, _reg)
+#define DWRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst_disp, _sc->bsh_disp, _reg, _val)
+
+struct panel_info {
+ uint32_t width;
+ uint32_t height;
+ uint32_t h_back_porch;
+ uint32_t h_pulse_width;
+ uint32_t h_front_porch;
+ uint32_t v_back_porch;
+ uint32_t v_pulse_width;
+ uint32_t v_front_porch;
+ uint32_t clk_div;
+ uint32_t backlight_pin;
+ uint32_t fixvclk;
+ uint32_t ivclk;
+ uint32_t clkval_f;
+};
+
+struct fimd_softc {
+ struct resource *res[3];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ bus_space_tag_t bst_disp;
+ bus_space_handle_t bsh_disp;
+ bus_space_tag_t bst_sysreg;
+ bus_space_handle_t bsh_sysreg;
+
+ void *ih;
+ device_t dev;
+ device_t sc_fbd; /* fbd child */
+ struct fb_info sc_info;
+ struct panel_info *panel;
+};
+
+static struct resource_spec fimd_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Timer registers */
+ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* FIMD */
+ { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* DISP */
+ { -1, 0 }
+};
+
+static int
+fimd_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "exynos,fimd"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Samsung Exynos 5 Display Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+get_panel_info(struct fimd_softc *sc, struct panel_info *panel)
+{
+ phandle_t node;
+ pcell_t dts_value[3];
+ int len;
+
+ if ((node = ofw_bus_get_node(sc->dev)) == -1)
+ return (ENXIO);
+
+ /* panel size */
+ if ((len = OF_getproplen(node, "panel-size")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-size", &dts_value, len);
+ panel->width = fdt32_to_cpu(dts_value[0]);
+ panel->height = fdt32_to_cpu(dts_value[1]);
+
+ /* hsync */
+ if ((len = OF_getproplen(node, "panel-hsync")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-hsync", &dts_value, len);
+ panel->h_back_porch = fdt32_to_cpu(dts_value[0]);
+ panel->h_pulse_width = fdt32_to_cpu(dts_value[1]);
+ panel->h_front_porch = fdt32_to_cpu(dts_value[2]);
+
+ /* vsync */
+ if ((len = OF_getproplen(node, "panel-vsync")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-vsync", &dts_value, len);
+ panel->v_back_porch = fdt32_to_cpu(dts_value[0]);
+ panel->v_pulse_width = fdt32_to_cpu(dts_value[1]);
+ panel->v_front_porch = fdt32_to_cpu(dts_value[2]);
+
+ /* clk divider */
+ if ((len = OF_getproplen(node, "panel-clk-div")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-clk-div", &dts_value, len);
+ panel->clk_div = fdt32_to_cpu(dts_value[0]);
+
+ /* backlight pin */
+ if ((len = OF_getproplen(node, "panel-backlight-pin")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "panel-backlight-pin", &dts_value, len);
+ panel->backlight_pin = fdt32_to_cpu(dts_value[0]);
+
+ return (0);
+}
+
+static int
+fimd_init(struct fimd_softc *sc)
+{
+ struct panel_info *panel;
+ int reg;
+
+ panel = sc->panel;
+
+ /* fb_init */
+ reg = panel->ivclk | panel->fixvclk;
+ DWRITE4(sc,VIDCON1,reg);
+
+ reg = (VIDCON0_ENVID | VIDCON0_ENVID_F);
+ reg |= (panel->clkval_f << CLKVAL_F_OFFSET);
+ WRITE4(sc,VIDCON0,reg);
+
+ reg = (panel->v_pulse_width << VSYNC_PULSE_WIDTH_OFFSET);
+ reg |= (panel->v_front_porch << V_FRONT_PORCH_OFFSET);
+ reg |= (panel->v_back_porch << V_BACK_PORCH_OFFSET);
+ DWRITE4(sc,VIDTCON0,reg);
+
+ reg = (panel->h_pulse_width << HSYNC_PULSE_WIDTH_OFFSET);
+ reg |= (panel->h_front_porch << H_FRONT_PORCH_OFFSET);
+ reg |= (panel->h_back_porch << H_BACK_PORCH_OFFSET);
+ DWRITE4(sc,VIDTCON1,reg);
+
+ reg = ((panel->width - 1) << HOZVAL_OFFSET);
+ reg |= ((panel->height - 1) << LINEVAL_OFFSET);
+ DWRITE4(sc,VIDTCON2,reg);
+
+ reg = sc->sc_info.fb_pbase;
+ WRITE4(sc, VIDW00ADD0B0, reg);
+ reg += (sc->sc_info.fb_stride * (sc->sc_info.fb_height + 1));
+ WRITE4(sc, VIDW00ADD1B0, reg);
+ WRITE4(sc, VIDW00ADD2, sc->sc_info.fb_stride);
+
+ reg = ((panel->width - 1) << OSD_RIGHTBOTX_F_OFFSET);
+ reg |= ((panel->height - 1) << OSD_RIGHTBOTY_F_OFFSET);
+ WRITE4(sc,VIDOSD0B,reg);
+
+ reg = panel->width * panel->height;
+ WRITE4(sc,VIDOSD0C,reg);
+
+ reg = READ4(sc, SHADOWCON);
+ reg |= CHANNEL0_EN;
+ reg &= ~(1 << 5); /* disable local path for channel0 */
+ WRITE4(sc,SHADOWCON,reg);
+
+ reg = BPPMODE_F_RGB_16BIT_565 << BPPMODE_F_OFFSET;
+ reg |= ENWIN_F_ENABLE | HALF_WORD_SWAP_EN; /* Note: swap=0 when ENLOCAL==1 */
+ reg &= ~ENLOCAL_F; /* use DMA */
+ WRITE4(sc,WINCON0,reg);
+
+ /* Enable DisplayPort Clk */
+ WRITE4(sc, DPCLKCON, DPCLKCON_EN);
+
+ return (0);
+}
+
+static int
+fimd_attach(device_t dev)
+{
+ struct panel_info panel;
+ struct fimd_softc *sc;
+ device_t gpio_dev;
+ int reg;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, fimd_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+ sc->bst_disp = rman_get_bustag(sc->res[1]);
+ sc->bsh_disp = rman_get_bushandle(sc->res[1]);
+ sc->bst_sysreg = rman_get_bustag(sc->res[2]);
+ sc->bsh_sysreg = rman_get_bushandle(sc->res[2]);
+
+ if (get_panel_info(sc, &panel)) {
+ device_printf(dev, "Can't get panel info\n");
+ return (ENXIO);
+ }
+
+ panel.fixvclk = 0;
+ panel.ivclk = 0;
+ panel.clkval_f = 2;
+
+ sc->panel = &panel;
+
+ /* Get the GPIO device, we need this to give power to USB */
+ gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (gpio_dev == NULL) {
+ /* TODO */
+ }
+
+ reg = bus_space_read_4(sc->bst_sysreg, sc->bsh_sysreg, 0x214);
+ reg |= FIMDBYPASS_DISP1;
+ bus_space_write_4(sc->bst_sysreg, sc->bsh_sysreg, 0x214, reg);
+
+ sc->sc_info.fb_width = panel.width;
+ sc->sc_info.fb_height = panel.height;
+ sc->sc_info.fb_stride = sc->sc_info.fb_width * 2;
+ sc->sc_info.fb_bpp = sc->sc_info.fb_depth = 16;
+ sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride;
+ sc->sc_info.fb_vbase = (intptr_t)kmem_alloc_contig(kernel_arena,
+ sc->sc_info.fb_size, M_ZERO, 0, ~0, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE);
+ sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase);
+
+#if 0
+ printf("%dx%d [%d]\n", sc->sc_info.fb_width, sc->sc_info.fb_height,
+ sc->sc_info.fb_stride);
+ printf("pbase == 0x%08x\n", sc->sc_info.fb_pbase);
+#endif
+
+ memset((int8_t *)sc->sc_info.fb_vbase, 0x0, sc->sc_info.fb_size);
+
+ fimd_init(sc);
+
+ sc->sc_info.fb_name = device_get_nameunit(dev);
+
+ /* Ask newbus to attach framebuffer device to me. */
+ sc->sc_fbd = device_add_child(dev, "fbd", device_get_unit(dev));
+ if (sc->sc_fbd == NULL)
+ device_printf(dev, "Can't attach fbd device\n");
+
+ if (device_probe_and_attach(sc->sc_fbd) != 0) {
+ device_printf(sc->dev, "Failed to attach fbd device\n");
+ }
+
+ return (0);
+}
+
+static struct fb_info *
+fimd_fb_getinfo(device_t dev)
+{
+ struct fimd_softc *sc = device_get_softc(dev);
+
+ return (&sc->sc_info);
+}
+
+static device_method_t fimd_methods[] = {
+ DEVMETHOD(device_probe, fimd_probe),
+ DEVMETHOD(device_attach, fimd_attach),
+
+ /* Framebuffer service methods */
+ DEVMETHOD(fb_getinfo, fimd_fb_getinfo),
+ { 0, 0 }
+};
+
+static driver_t fimd_driver = {
+ "fb",
+ fimd_methods,
+ sizeof(struct fimd_softc),
+};
+
+static devclass_t fimd_devclass;
+
+DRIVER_MODULE(fb, simplebus, fimd_driver, fimd_devclass, 0, 0);
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_fimd.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_i2c.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_i2c.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_i2c.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,477 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Samsung Exynos 5 Inter-Integrated Circuit (I2C)
+ * Chapter 13, Exynos 5 Dual User's Manual Public Rev 1.00
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_i2c.c 289666 2015-10-20 21:20:34Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include "iicbus_if.h"
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/samsung/exynos/exynos5_common.h>
+
+#define I2CCON 0x00 /* Control register */
+#define ACKGEN (1 << 7) /* Acknowledge Enable */
+/*
+ * Source Clock of I2C-bus Transmit Clock Prescaler
+ *
+ * 0 = I2CCLK = fPCLK/16
+ * 1 = I2CCLK = fPCLK/512
+ */
+#define I2CCLK (1 << 6)
+#define IRQ_EN (1 << 5) /* Tx/Rx Interrupt Enable/Disable */
+#define IPEND (1 << 4) /* Tx/Rx Interrupt Pending Flag */
+#define CLKVAL_M 0xf /* Transmit Clock Prescaler Mask */
+#define CLKVAL_S 0
+#define I2CSTAT 0x04 /* Control/status register */
+#define I2CMODE_M 0x3 /* Master/Slave Tx/Rx Mode Select */
+#define I2CMODE_S 6
+#define I2CMODE_SR 0x0 /* Slave Receive Mode */
+#define I2CMODE_ST 0x1 /* Slave Transmit Mode */
+#define I2CMODE_MR 0x2 /* Master Receive Mode */
+#define I2CMODE_MT 0x3 /* Master Transmit Mode */
+#define I2CSTAT_BSY (1 << 5) /* Busy Signal Status bit */
+#define I2C_START_STOP (1 << 5) /* Busy Signal Status bit */
+#define RXTX_EN (1 << 4) /* Data Output Enable/Disable */
+#define ARBST (1 << 3) /* Arbitration status flag */
+#define ADDAS (1 << 2) /* Address-as-slave Status Flag */
+#define ADDZERO (1 << 1) /* Address Zero Status Flag */
+#define ACKRECVD (1 << 0) /* Last-received Bit Status Flag */
+#define I2CADD 0x08 /* Address register */
+#define I2CDS 0x0C /* Transmit/receive data shift */
+#define I2CLC 0x10 /* Multi-master line control */
+#define FILTER_EN (1 << 2) /* Filter Enable bit */
+#define SDAOUT_DELAY_M 0x3 /* SDA Line Delay Length */
+#define SDAOUT_DELAY_S 0
+
+#ifdef DEBUG
+#define DPRINTF(fmt, args...) \
+ printf(fmt, ##args)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+static int i2c_start(device_t, u_char, int);
+static int i2c_stop(device_t);
+static int i2c_reset(device_t, u_char, u_char, u_char *);
+static int i2c_read(device_t, char *, int, int *, int, int);
+static int i2c_write(device_t, const char *, int, int *, int);
+
+struct i2c_softc {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ device_t iicbus;
+ struct mtx mutex;
+ void *ih;
+ int intr;
+};
+
+static struct resource_spec i2c_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int
+i2c_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "exynos,i2c"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Samsung Exynos 5 I2C controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+clear_ipend(struct i2c_softc *sc)
+{
+ int reg;
+
+ reg = READ1(sc, I2CCON);
+ reg &= ~(IPEND);
+ WRITE1(sc, I2CCON, reg);
+
+ return (0);
+}
+
+static int
+i2c_attach(device_t dev)
+{
+ struct i2c_softc *sc;
+ int reg;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF);
+
+ if (bus_alloc_resources(dev, i2c_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ sc->iicbus = device_add_child(dev, "iicbus", -1);
+ if (sc->iicbus == NULL) {
+ device_printf(dev, "could not add iicbus child");
+ mtx_destroy(&sc->mutex);
+ return (ENXIO);
+ }
+
+ WRITE1(sc, I2CSTAT, 0);
+ WRITE1(sc, I2CADD, 0x00);
+
+ /* Mode */
+ reg = (RXTX_EN);
+ reg |= (I2CMODE_MT << I2CMODE_S);
+ WRITE1(sc, I2CSTAT, reg);
+
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static int
+wait_for_iif(struct i2c_softc *sc)
+{
+ int retry;
+ int reg;
+
+ retry = 1000;
+ while (retry --) {
+ reg = READ1(sc, I2CCON);
+ if (reg & IPEND) {
+ return (IIC_NOERR);
+ }
+ DELAY(50);
+ }
+
+ return (IIC_ETIMEOUT);
+}
+
+static int
+wait_for_nibb(struct i2c_softc *sc)
+{
+ int retry;
+
+ retry = 1000;
+ while (retry --) {
+ if ((READ1(sc, I2CSTAT) & I2CSTAT_BSY) == 0)
+ return (IIC_NOERR);
+ DELAY(10);
+ }
+
+ return (IIC_ETIMEOUT);
+}
+
+static int
+is_ack(struct i2c_softc *sc)
+{
+ int stat;
+
+ stat = READ1(sc, I2CSTAT);
+ if (!(stat & 1)) {
+ /* ACK received */
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+i2c_start(device_t dev, u_char slave, int timeout)
+{
+ struct i2c_softc *sc;
+ int error;
+ int reg;
+
+ sc = device_get_softc(dev);
+
+ DPRINTF("i2c start\n");
+
+ mtx_lock(&sc->mutex);
+
+#if 0
+ DPRINTF("I2CCON == 0x%08x\n", READ1(sc, I2CCON));
+ DPRINTF("I2CSTAT == 0x%08x\n", READ1(sc, I2CSTAT));
+#endif
+
+ if (slave & 1) {
+ slave &= ~(1);
+ slave <<= 1;
+ slave |= 1;
+ } else {
+ slave <<= 1;
+ }
+
+ error = wait_for_nibb(sc);
+ if (error) {
+ mtx_unlock(&sc->mutex);
+ DPRINTF("cant i2c start: IIC_EBUSERR\n");
+ return (IIC_EBUSERR);
+ }
+
+ reg = READ1(sc, I2CCON);
+ reg |= (IRQ_EN | ACKGEN);
+ WRITE1(sc, I2CCON, reg);
+
+ WRITE1(sc, I2CDS, slave);
+ DELAY(50);
+
+ reg = (RXTX_EN);
+ reg |= I2C_START_STOP;
+ reg |= (I2CMODE_MT << I2CMODE_S);
+ WRITE1(sc, I2CSTAT, reg);
+
+ error = wait_for_iif(sc);
+ if (error) {
+ DPRINTF("cant i2c start: iif error\n");
+
+ mtx_unlock(&sc->mutex);
+ return (error);
+ }
+
+ if (!is_ack(sc)) {
+ DPRINTF("cant i2c start: no ack\n");
+
+ mtx_unlock(&sc->mutex);
+ return (IIC_ENOACK);
+ };
+
+ mtx_unlock(&sc->mutex);
+ return (IIC_NOERR);
+}
+
+static int
+i2c_stop(device_t dev)
+{
+ struct i2c_softc *sc;
+ int reg;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ DPRINTF("i2c stop\n");
+
+ mtx_lock(&sc->mutex);
+
+ reg = READ1(sc, I2CSTAT);
+ int mode = (reg >> I2CMODE_S) & I2CMODE_M;
+
+ reg = (RXTX_EN);
+ reg |= (mode << I2CMODE_S);
+ WRITE1(sc, I2CSTAT, reg);
+
+ clear_ipend(sc);
+
+ error = wait_for_nibb(sc);
+ if (error) {
+ DPRINTF("cant i2c stop: nibb error\n");
+ return (error);
+ }
+
+ mtx_unlock(&sc->mutex);
+ return (IIC_NOERR);
+}
+
+static int
+i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
+{
+ struct i2c_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ DPRINTF("i2c reset\n");
+
+ mtx_lock(&sc->mutex);
+
+ /* TODO */
+
+ mtx_unlock(&sc->mutex);
+
+ return (IIC_NOERR);
+}
+
+static int
+i2c_read(device_t dev, char *buf, int len,
+ int *read, int last, int delay)
+{
+ struct i2c_softc *sc;
+ int error;
+ int reg;
+ uint8_t d;
+
+ sc = device_get_softc(dev);
+
+ DPRINTF("i2c read\n");
+
+ reg = (RXTX_EN);
+ reg |= (I2CMODE_MR << I2CMODE_S);
+ reg |= I2C_START_STOP;
+ WRITE1(sc, I2CSTAT, reg);
+
+ *read = 0;
+ mtx_lock(&sc->mutex);
+
+ /* dummy read */
+ READ1(sc, I2CDS);
+
+ DPRINTF("Read ");
+ while (*read < len) {
+
+ /* Do not ack last read */
+ if (*read == (len - 1)) {
+ reg = READ1(sc, I2CCON);
+ reg &= ~(ACKGEN);
+ WRITE1(sc, I2CCON, reg);
+ };
+
+ clear_ipend(sc);
+
+ error = wait_for_iif(sc);
+ if (error) {
+ DPRINTF("cant i2c read: iif error\n");
+ mtx_unlock(&sc->mutex);
+ return (error);
+ }
+
+ d = READ1(sc, I2CDS);
+ DPRINTF("0x%02x ", d);
+ *buf++ = d;
+ (*read)++;
+ }
+ DPRINTF("\n");
+
+ mtx_unlock(&sc->mutex);
+ return (IIC_NOERR);
+}
+
+static int
+i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout)
+{
+ struct i2c_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ DPRINTF("i2c write\n");
+
+ *sent = 0;
+
+ mtx_lock(&sc->mutex);
+
+ DPRINTF("writing ");
+ while (*sent < len) {
+ uint8_t d = *buf++;
+ DPRINTF("0x%02x ", d);
+
+ WRITE1(sc, I2CDS, d);
+ DELAY(50);
+
+ clear_ipend(sc);
+
+ error = wait_for_iif(sc);
+ if (error) {
+ DPRINTF("cant i2c write: iif error\n");
+ mtx_unlock(&sc->mutex);
+ return (error);
+ }
+
+ if (!is_ack(sc)) {
+ DPRINTF("cant i2c write: no ack\n");
+ mtx_unlock(&sc->mutex);
+ return (IIC_ENOACK);
+ };
+
+ (*sent)++;
+ }
+ DPRINTF("\n");
+
+ mtx_unlock(&sc->mutex);
+ return (IIC_NOERR);
+}
+
+static device_method_t i2c_methods[] = {
+ DEVMETHOD(device_probe, i2c_probe),
+ DEVMETHOD(device_attach, i2c_attach),
+
+ DEVMETHOD(iicbus_callback, iicbus_null_callback),
+ DEVMETHOD(iicbus_start, i2c_start),
+ DEVMETHOD(iicbus_stop, i2c_stop),
+ DEVMETHOD(iicbus_reset, i2c_reset),
+ DEVMETHOD(iicbus_read, i2c_read),
+ DEVMETHOD(iicbus_write, i2c_write),
+ DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
+
+ { 0, 0 }
+};
+
+static driver_t i2c_driver = {
+ "i2c",
+ i2c_methods,
+ sizeof(struct i2c_softc),
+};
+
+static devclass_t i2c_devclass;
+
+DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0);
+DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_i2c.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_machdep.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_machdep.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,95 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_machdep.c 266275 2014-05-16 23:49:40Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <dev/fdt/fdt_common.h>
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+
+}
+
+void
+initarm_gpio_init(void)
+{
+
+}
+
+void
+initarm_late_init(void)
+{
+
+}
+
+int
+initarm_devmap_init(void)
+{
+
+ /* UART */
+ arm_devmap_add_entry(0x12C00000, 0x100000);
+
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_mct.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_mct.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_mct.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,140 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This module just enables Exynos MCT, so ARMv7 Generic Timer will works
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_mct.c 266332 2014-05-17 17:54:38Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#define MCT_CTRL_START (1 << 8)
+#define MCT_CTRL (0x240)
+#define MCT_WRITE_STAT (0x24C)
+
+struct arm_tmr_softc {
+ struct resource *tmr_res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct resource_spec arm_tmr_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Timer registers */
+ { -1, 0 }
+};
+
+static int
+arm_tmr_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "exynos,mct"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Exynos MPCore Timer");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+arm_tmr_attach(device_t dev)
+{
+ struct arm_tmr_softc *sc;
+ int reg, i;
+ int mask;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, arm_tmr_spec, sc->tmr_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Timer interface */
+ sc->bst = rman_get_bustag(sc->tmr_res[0]);
+ sc->bsh = rman_get_bushandle(sc->tmr_res[0]);
+
+ reg = bus_space_read_4(sc->bst, sc->bsh, MCT_CTRL);
+ reg |= MCT_CTRL_START;
+ bus_space_write_4(sc->bst, sc->bsh, MCT_CTRL, reg);
+
+ mask = (1 << 16);
+
+ /* Wait 10 times until written value is applied */
+ for (i = 0; i < 10; i++) {
+ reg = bus_space_read_4(sc->bst, sc->bsh, MCT_WRITE_STAT);
+ if (reg & mask) {
+ bus_space_write_4(sc->bst, sc->bsh,
+ MCT_WRITE_STAT, mask);
+ return (0);
+ }
+ cpufunc_nullop();
+ }
+
+ /* NOTREACHED */
+
+ panic("Can't enable timer\n");
+}
+
+static device_method_t arm_tmr_methods[] = {
+ DEVMETHOD(device_probe, arm_tmr_probe),
+ DEVMETHOD(device_attach, arm_tmr_attach),
+ { 0, 0 }
+};
+
+static driver_t arm_tmr_driver = {
+ "mct",
+ arm_tmr_methods,
+ sizeof(struct arm_tmr_softc),
+};
+
+static devclass_t arm_tmr_devclass;
+
+DRIVER_MODULE(mct, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0);
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_mct.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_mp.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_mp.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_mp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,90 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_mp.c 266203 2014-05-16 00:14:50Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#define EXYNOS_SYSRAM 0x02020000
+
+void
+platform_mp_init_secondary(void)
+{
+
+ gic_init_secondary();
+}
+
+void
+platform_mp_setmaxid(void)
+{
+
+ mp_maxid = 1;
+}
+
+int
+platform_mp_probe(void)
+{
+
+ mp_ncpus = 2;
+ return (1);
+}
+
+void
+platform_mp_start_ap(void)
+{
+ bus_addr_t sysram;
+ int err;
+
+ err = bus_space_map(fdtbus_bs_tag, EXYNOS_SYSRAM, 0x100, 0, &sysram);
+ if (err != 0)
+ panic("Couldn't map sysram\n");
+
+ bus_space_write_4(fdtbus_bs_tag, sysram, 0x0,
+ pmap_kextract((vm_offset_t)mpentry));
+
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+
+ armv7_sev();
+ bus_space_unmap(fdtbus_bs_tag, sysram, 0x100);
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+
+ pic_ipi_send(cpus, ipi);
+}
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_mp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_pad.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_pad.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_pad.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,708 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Samsung Exynos 5 Pad Control
+ * Chapter 4, Exynos 5 Dual User's Manual Public Rev 1.00
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_pad.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include "gpio_if.h"
+
+#include <arm/samsung/exynos/exynos5_combiner.h>
+#include <arm/samsung/exynos/exynos5_pad.h>
+
+#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+
+#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
+
+#define NPORTS 4
+#define NGRP 40
+#define NGPIO 253
+#define NINTS 16
+
+#define PIN_IN 0
+#define PIN_OUT 1
+
+#define READ4(_sc, _port, _reg) \
+ bus_space_read_4(_sc->bst[_port], _sc->bsh[_port], _reg)
+#define WRITE4(_sc, _port, _reg, _val) \
+ bus_space_write_4(_sc->bst[_port], _sc->bsh[_port], _reg, _val)
+
+/*
+ * GPIO interface
+ */
+static int pad_pin_max(device_t, int *);
+static int pad_pin_getcaps(device_t, uint32_t, uint32_t *);
+static int pad_pin_getname(device_t, uint32_t, char *);
+static int pad_pin_getflags(device_t, uint32_t, uint32_t *);
+static int pad_pin_setflags(device_t, uint32_t, uint32_t);
+static int pad_pin_set(device_t, uint32_t, unsigned int);
+static int pad_pin_get(device_t, uint32_t, unsigned int *);
+static int pad_pin_toggle(device_t, uint32_t pin);
+
+struct pad_softc {
+ struct resource *res[NPORTS+4];
+ bus_space_tag_t bst[NPORTS];
+ bus_space_handle_t bsh[NPORTS];
+ struct mtx sc_mtx;
+ int gpio_npins;
+ struct gpio_pin gpio_pins[NGPIO];
+ void *gpio_ih[NPORTS+4];
+ device_t dev;
+};
+
+struct pad_softc *gpio_sc;
+
+static struct resource_spec pad_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { -1, 0 }
+};
+
+struct pad_intr {
+ uint32_t enabled;
+ void (*ih) (void *);
+ void *ih_user;
+};
+
+static struct pad_intr intr_map[NGPIO];
+
+struct interrupt_entry {
+ int gpio_number;
+ char *combiner_source_name;
+};
+
+struct interrupt_entry interrupt_table[NINTS] = {
+ { 147, "EINT[15]" },
+ { 146, "EINT[14]" },
+ { 145, "EINT[13]" },
+ { 144, "EINT[12]" },
+ { 143, "EINT[11]" },
+ { 142, "EINT[10]" },
+ { 141, "EINT[9]" },
+ { 140, "EINT[8]" },
+ { 139, "EINT[7]" },
+ { 138, "EINT[6]" },
+ { 137, "EINT[5]" },
+ { 136, "EINT[4]" },
+ { 135, "EINT[3]" },
+ { 134, "EINT[2]" },
+ { 133, "EINT[1]" },
+ { 132, "EINT[0]" },
+};
+
+struct gpio_bank {
+ char *name;
+ uint32_t port;
+ uint32_t con;
+ uint32_t ngpio;
+ uint32_t ext_int_grp;
+ uint32_t ext_con;
+ uint32_t ext_flt_con;
+ uint32_t mask;
+ uint32_t pend;
+};
+
+/*
+ * 253 multi-functional input/output ports
+ */
+
+static struct gpio_bank gpio_map[] = {
+ /* first 132 gpio */
+ { "gpa0", 0, 0x000, 8, 1, 0x700, 0x800, 0x900, 0xA00 },
+ { "gpa1", 0, 0x020, 6, 2, 0x704, 0x808, 0x904, 0xA04 },
+ { "gpa2", 0, 0x040, 8, 3, 0x708, 0x810, 0x908, 0xA08 },
+ { "gpb0", 0, 0x060, 5, 4, 0x70C, 0x818, 0x90C, 0xA0C },
+ { "gpb1", 0, 0x080, 5, 5, 0x710, 0x820, 0x910, 0xA10 },
+ { "gpb2", 0, 0x0A0, 4, 6, 0x714, 0x828, 0x914, 0xA14 },
+ { "gpb3", 0, 0x0C0, 4, 7, 0x718, 0x830, 0x918, 0xA18 },
+ { "gpc0", 0, 0x0E0, 7, 8, 0x71C, 0x838, 0x91C, 0xA1C },
+ { "gpc1", 0, 0x100, 4, 9, 0x720, 0x840, 0x920, 0xA20 },
+ { "gpc2", 0, 0x120, 7, 10, 0x724, 0x848, 0x924, 0xA24 },
+ { "gpc3", 0, 0x140, 7, 11, 0x728, 0x850, 0x928, 0xA28 },
+ { "gpd0", 0, 0x160, 4, 12, 0x72C, 0x858, 0x92C, 0xA2C },
+ { "gpd1", 0, 0x180, 8, 13, 0x730, 0x860, 0x930, 0xA30 },
+ { "gpy0", 0, 0x1A0, 6, 0, 0, 0, 0, 0 },
+ { "gpy1", 0, 0x1C0, 4, 0, 0, 0, 0, 0 },
+ { "gpy2", 0, 0x1E0, 6, 0, 0, 0, 0, 0 },
+ { "gpy3", 0, 0x200, 8, 0, 0, 0, 0, 0 },
+ { "gpy4", 0, 0x220, 8, 0, 0, 0, 0, 0 },
+ { "gpy5", 0, 0x240, 8, 0, 0, 0, 0, 0 },
+ { "gpy6", 0, 0x260, 8, 0, 0, 0, 0, 0 },
+ { "gpc4", 0, 0x2E0, 7, 30, 0x734, 0x868, 0x934, 0xA34 },
+
+ /* next 32 */
+ { "gpx0", 0, 0xC00, 8, 40, 0xE00, 0xE80, 0xF00, 0xF40 },
+ { "gpx1", 0, 0xC20, 8, 41, 0xE04, 0xE88, 0xF04, 0xF44 },
+ { "gpx2", 0, 0xC40, 8, 42, 0xE08, 0xE90, 0xF08, 0xF48 },
+ { "gpx3", 0, 0xC60, 8, 43, 0xE0C, 0xE98, 0xF0C, 0xF4C },
+
+ { "gpe0", 1, 0x000, 8, 14, 0x700, 0x800, 0x900, 0xA00 },
+ { "gpe1", 1, 0x020, 2, 15, 0x704, 0x808, 0x904, 0xA04 },
+ { "gpf0", 1, 0x040, 4, 16, 0x708, 0x810, 0x908, 0xA08 },
+ { "gpf1", 1, 0x060, 4, 17, 0x70C, 0x818, 0x90C, 0xA0C },
+ { "gpg0", 1, 0x080, 8, 18, 0x710, 0x820, 0x910, 0xA10 },
+ { "gpg1", 1, 0x0A0, 8, 19, 0x714, 0x828, 0x914, 0xA14 },
+ { "gpg2", 1, 0x0C0, 2, 20, 0x718, 0x830, 0x918, 0xA18 },
+ { "gph0", 1, 0x0E0, 4, 21, 0x71C, 0x838, 0x91C, 0xA1C },
+ { "gph1", 1, 0x100, 8, 22, 0x720, 0x840, 0x920, 0xA20 },
+
+ { "gpv0", 2, 0x000, 8, 60, 0x700, 0x800, 0x900, 0xA00 },
+ { "gpv1", 2, 0x020, 8, 61, 0x704, 0x808, 0x904, 0xA04 },
+ { "gpv2", 2, 0x060, 8, 62, 0x708, 0x810, 0x908, 0xA08 },
+ { "gpv3", 2, 0x080, 8, 63, 0x70C, 0x818, 0x90C, 0xA0C },
+ { "gpv4", 2, 0x0C0, 2, 64, 0x710, 0x820, 0x910, 0xA10 },
+
+ { "gpz", 3, 0x000, 7, 50, 0x700, 0x800, 0x900, 0xA00 },
+};
+
+static int
+get_bank(int gpio_number, struct gpio_bank *bank, int *pin_shift)
+{
+ int ngpio;
+ int i;
+ int n;
+
+ n = 0;
+ for (i = 0; i < NGRP; i++) {
+ ngpio = gpio_map[i].ngpio;
+
+ if ((n + ngpio) >= gpio_number) {
+ *bank = gpio_map[i];
+ *pin_shift = (gpio_number - n);
+ return (0);
+ };
+
+ n += ngpio;
+ };
+
+ return (-1);
+}
+
+static int
+port_intr(void *arg)
+{
+ struct port_softc *sc;
+
+ sc = arg;
+
+ return (FILTER_HANDLED);
+}
+
+static void
+ext_intr(void *arg)
+{
+ struct pad_softc *sc;
+ void (*ih) (void *);
+ void *ih_user;
+ int ngpio;
+ int found;
+ int reg;
+ int i,j;
+ int n,k;
+
+ sc = arg;
+
+ n = 0;
+ for (i = 0; i < NGRP; i++) {
+ found = 0;
+ ngpio = gpio_map[i].ngpio;
+
+ if (gpio_map[i].pend == 0) {
+ n += ngpio;
+ continue;
+ }
+
+ reg = READ4(sc, gpio_map[i].port, gpio_map[i].pend);
+
+ for (j = 0; j < ngpio; j++) {
+ if (reg & (1 << j)) {
+ found = 1;
+
+ k = (n + j);
+ if (intr_map[k].enabled == 1) {
+ ih = intr_map[k].ih;
+ ih_user = intr_map[k].ih_user;
+ ih(ih_user);
+ }
+ }
+ }
+
+ if (found) {
+ /* ACK */
+ WRITE4(sc, gpio_map[i].port, gpio_map[i].pend, reg);
+ }
+
+ n += ngpio;
+ }
+}
+
+int
+pad_setup_intr(int gpio_number, void (*ih)(void *), void *ih_user)
+{
+ struct interrupt_entry *entry;
+ struct pad_intr *pad_irq;
+ struct gpio_bank bank;
+ struct pad_softc *sc;
+ int pin_shift;
+ int reg;
+ int i;
+
+ sc = gpio_sc;
+
+ if (sc == NULL) {
+ device_printf(sc->dev, "Error: pad is not attached\n");
+ return (-1);
+ }
+
+ if (get_bank(gpio_number, &bank, &pin_shift) != 0)
+ return (-1);
+
+ entry = NULL;
+ for (i = 0; i < NINTS; i++)
+ if (interrupt_table[i].gpio_number == gpio_number)
+ entry = &interrupt_table[i];
+
+ if (entry == NULL) {
+ device_printf(sc->dev, "Cant find interrupt source for %d\n",
+ gpio_number);
+ return (-1);
+ }
+
+#if 0
+ printf("Request interrupt name %s\n", entry->combiner_source_name);
+#endif
+
+ pad_irq = &intr_map[gpio_number];
+ pad_irq->enabled = 1;
+ pad_irq->ih = ih;
+ pad_irq->ih_user = ih_user;
+
+ /* Setup port as external interrupt source */
+ reg = READ4(sc, bank.port, bank.con);
+ reg |= (0xf << (pin_shift * 4));
+#if 0
+ printf("writing 0x%08x to 0x%08x\n", reg, bank.con);
+#endif
+ WRITE4(sc, bank.port, bank.con, reg);
+
+ /*
+ * Configure interrupt pin
+ *
+ * 0x0 = Sets Low level
+ * 0x1 = Sets High level
+ * 0x2 = Triggers Falling edge
+ * 0x3 = Triggers Rising edge
+ * 0x4 = Triggers Both edge
+ *
+ * TODO: add parameter. For now configure as 0x0
+ */
+ reg = READ4(sc, bank.port, bank.ext_con);
+ reg &= ~(0x7 << (pin_shift * 4));
+ WRITE4(sc, bank.port, bank.ext_con, reg);
+
+ /* Unmask */
+ reg = READ4(sc, bank.port, bank.mask);
+ reg &= ~(1 << pin_shift);
+ WRITE4(sc, bank.port, bank.mask, reg);
+
+ combiner_setup_intr(entry->combiner_source_name, ext_intr, sc);
+
+ return (0);
+}
+
+static int
+pad_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "exynos,pad"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Exynos Pad Control");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+pad_attach(device_t dev)
+{
+ struct gpio_bank bank;
+ struct pad_softc *sc;
+ int pin_shift;
+ int reg;
+ int i;
+
+ sc = device_get_softc(dev);
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ if (bus_alloc_resources(dev, pad_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+
+ for (i = 0; i < NPORTS; i++) {
+ sc->bst[i] = rman_get_bustag(sc->res[i]);
+ sc->bsh[i] = rman_get_bushandle(sc->res[i]);
+ };
+
+ sc->dev = dev;
+ sc->gpio_npins = NGPIO;
+
+ gpio_sc = sc;
+
+ for (i = 0; i < NPORTS; i++) {
+ if ((bus_setup_intr(dev, sc->res[NPORTS + i],
+ INTR_TYPE_BIO | INTR_MPSAFE, port_intr,
+ NULL, sc, &sc->gpio_ih[i]))) {
+ device_printf(dev,
+ "ERROR: Unable to register interrupt handler\n");
+ return (ENXIO);
+ }
+ };
+
+ for (i = 0; i < sc->gpio_npins; i++) {
+ sc->gpio_pins[i].gp_pin = i;
+ sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
+
+ if (get_bank(i, &bank, &pin_shift) != 0)
+ continue;
+
+ pin_shift *= 4;
+
+ reg = READ4(sc, bank.port, bank.con);
+ if (reg & (PIN_OUT << pin_shift))
+ sc->gpio_pins[i].gp_flags = GPIO_PIN_OUTPUT;
+ else
+ sc->gpio_pins[i].gp_flags = GPIO_PIN_INPUT;
+
+ /* TODO: add other pin statuses */
+
+ snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
+ "pad%d.%d", device_get_unit(dev), i);
+ }
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+pad_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = NGPIO - 1;
+ return (0);
+}
+
+static int
+pad_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct pad_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+pad_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct pad_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *caps = sc->gpio_pins[i].gp_caps;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+pad_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct pad_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *flags = sc->gpio_pins[i].gp_flags;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+pad_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct gpio_bank bank;
+ struct pad_softc *sc;
+ int pin_shift;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ if (get_bank(pin, &bank, &pin_shift) != 0)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ if (READ4(sc, bank.port, bank.con + 0x4) & (1 << pin_shift))
+ *val = 1;
+ else
+ *val = 0;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+pad_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct gpio_bank bank;
+ struct pad_softc *sc;
+ int pin_shift;
+ int reg;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ if (get_bank(pin, &bank, &pin_shift) != 0)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ reg = READ4(sc, bank.port, bank.con + 0x4);
+ if (reg & (1 << pin_shift))
+ reg &= ~(1 << pin_shift);
+ else
+ reg |= (1 << pin_shift);
+ WRITE4(sc, bank.port, bank.con + 0x4, reg);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+
+static void
+pad_pin_configure(struct pad_softc *sc, struct gpio_pin *pin,
+ unsigned int flags)
+{
+ struct gpio_bank bank;
+ int pin_shift;
+ int reg;
+
+ GPIO_LOCK(sc);
+
+ /*
+ * Manage input/output
+ */
+ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
+ pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
+
+ if (get_bank(pin->gp_pin, &bank, &pin_shift) != 0)
+ return;
+
+ pin_shift *= 4;
+
+#if 0
+ printf("bank is 0x%08x pin_shift %d\n", bank.con, pin_shift);
+#endif
+
+ if (flags & GPIO_PIN_OUTPUT) {
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+ reg = READ4(sc, bank.port, bank.con);
+ reg &= ~(0xf << pin_shift);
+ reg |= (PIN_OUT << pin_shift);
+ WRITE4(sc, bank.port, bank.con, reg);
+ } else {
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ reg = READ4(sc, bank.port, bank.con);
+ reg &= ~(0xf << pin_shift);
+ WRITE4(sc, bank.port, bank.con, reg);
+ }
+ }
+
+ GPIO_UNLOCK(sc);
+}
+
+
+static int
+pad_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct pad_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ pad_pin_configure(sc, &sc->gpio_pins[i], flags);
+
+ return (0);
+}
+
+static int
+pad_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct pad_softc *sc;
+ struct gpio_bank bank;
+ int pin_shift;
+ int reg;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ if (sc->gpio_pins[i].gp_pin == pin)
+ break;
+ }
+
+ if (i >= sc->gpio_npins)
+ return (EINVAL);
+
+ if (get_bank(pin, &bank, &pin_shift) != 0)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ reg = READ4(sc, bank.port, bank.con + 0x4);
+ reg &= ~(PIN_OUT << pin_shift);
+ if (value)
+ reg |= (PIN_OUT << pin_shift);
+ WRITE4(sc, bank.port, bank.con + 0x4, reg);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static device_method_t pad_methods[] = {
+ DEVMETHOD(device_probe, pad_probe),
+ DEVMETHOD(device_attach, pad_attach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, pad_pin_max),
+ DEVMETHOD(gpio_pin_getname, pad_pin_getname),
+ DEVMETHOD(gpio_pin_getcaps, pad_pin_getcaps),
+ DEVMETHOD(gpio_pin_getflags, pad_pin_getflags),
+ DEVMETHOD(gpio_pin_get, pad_pin_get),
+ DEVMETHOD(gpio_pin_toggle, pad_pin_toggle),
+ DEVMETHOD(gpio_pin_setflags, pad_pin_setflags),
+ DEVMETHOD(gpio_pin_set, pad_pin_set),
+ { 0, 0 }
+};
+
+static driver_t pad_driver = {
+ "gpio",
+ pad_methods,
+ sizeof(struct pad_softc),
+};
+
+static devclass_t pad_devclass;
+
+DRIVER_MODULE(pad, simplebus, pad_driver, pad_devclass, 0, 0);
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_pad.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos5_pad.h
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos5_pad.h (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos5_pad.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,30 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/exynos/exynos5_pad.h 266341 2014-05-17 19:37:04Z ian $
+ */
+
+int pad_setup_intr(int gpio_number, void (*ih)(void *), void *ih_user);
Property changes on: trunk/sys/arm/samsung/exynos/exynos5_pad.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos_uart.c
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos_uart.c (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos_uart.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,390 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * Copyright (c) 2007-2009 Andrew Turner
+ * Copyright (c) 2013 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/exynos/exynos_uart.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/tty.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+
+#include <arm/samsung/exynos/exynos_uart.h>
+
+#include "uart_if.h"
+
+#define DEF_CLK 100000000
+
+static int sscomspeed(long, long);
+static int exynos4210_uart_param(struct uart_bas *, int, int, int, int);
+
+/*
+ * Low-level UART interface.
+ */
+static int exynos4210_probe(struct uart_bas *bas);
+static void exynos4210_init(struct uart_bas *bas, int, int, int, int);
+static void exynos4210_term(struct uart_bas *bas);
+static void exynos4210_putc(struct uart_bas *bas, int);
+static int exynos4210_rxready(struct uart_bas *bas);
+static int exynos4210_getc(struct uart_bas *bas, struct mtx *mtx);
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+
+static int
+sscomspeed(long speed, long frequency)
+{
+ int x;
+
+ if (speed <= 0 || frequency <= 0)
+ return (-1);
+ x = (frequency / 16) / speed;
+ return (x-1);
+}
+
+static int
+exynos4210_uart_param(struct uart_bas *bas, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ int brd, ulcon;
+
+ ulcon = 0;
+
+ switch(databits) {
+ case 5:
+ ulcon |= ULCON_LENGTH_5;
+ break;
+ case 6:
+ ulcon |= ULCON_LENGTH_6;
+ break;
+ case 7:
+ ulcon |= ULCON_LENGTH_7;
+ break;
+ case 8:
+ ulcon |= ULCON_LENGTH_8;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ switch (parity) {
+ case UART_PARITY_NONE:
+ ulcon |= ULCON_PARITY_NONE;
+ break;
+ case UART_PARITY_ODD:
+ ulcon |= ULCON_PARITY_ODD;
+ break;
+ case UART_PARITY_EVEN:
+ ulcon |= ULCON_PARITY_EVEN;
+ break;
+ case UART_PARITY_MARK:
+ case UART_PARITY_SPACE:
+ default:
+ return (EINVAL);
+ }
+
+ if (stopbits == 2)
+ ulcon |= ULCON_STOP;
+
+ uart_setreg(bas, SSCOM_ULCON, ulcon);
+
+ brd = sscomspeed(baudrate, bas->rclk);
+ uart_setreg(bas, SSCOM_UBRDIV, brd);
+
+ return (0);
+}
+
+struct uart_ops uart_exynos4210_ops = {
+ .probe = exynos4210_probe,
+ .init = exynos4210_init,
+ .term = exynos4210_term,
+ .putc = exynos4210_putc,
+ .rxready = exynos4210_rxready,
+ .getc = exynos4210_getc,
+};
+
+static int
+exynos4210_probe(struct uart_bas *bas)
+{
+
+ return (0);
+}
+
+static void
+exynos4210_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+
+ if (bas->rclk == 0)
+ bas->rclk = DEF_CLK;
+
+ KASSERT(bas->rclk != 0, ("exynos4210_init: Invalid rclk"));
+
+ uart_setreg(bas, SSCOM_UCON, 0);
+ uart_setreg(bas, SSCOM_UFCON,
+ UFCON_TXTRIGGER_8 | UFCON_RXTRIGGER_8 |
+ UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET |
+ UFCON_FIFO_ENABLE);
+ exynos4210_uart_param(bas, baudrate, databits, stopbits, parity);
+
+ /* Enable UART. */
+ uart_setreg(bas, SSCOM_UCON, UCON_TXMODE_INT | UCON_RXMODE_INT |
+ UCON_TOINT);
+ uart_setreg(bas, SSCOM_UMCON, UMCON_RTS);
+}
+
+static void
+exynos4210_term(struct uart_bas *bas)
+{
+ /* XXX */
+}
+
+static void
+exynos4210_putc(struct uart_bas *bas, int c)
+{
+
+ while ((bus_space_read_4(bas->bst, bas->bsh, SSCOM_UFSTAT) &
+ UFSTAT_TXFULL) == UFSTAT_TXFULL)
+ continue;
+
+ uart_setreg(bas, SSCOM_UTXH, c);
+}
+
+static int
+exynos4210_rxready(struct uart_bas *bas)
+{
+
+ return ((uart_getreg(bas, SSCOM_UTRSTAT) & UTRSTAT_RXREADY) ==
+ UTRSTAT_RXREADY);
+}
+
+static int
+exynos4210_getc(struct uart_bas *bas, struct mtx *mtx)
+{
+ int utrstat;
+
+ utrstat = bus_space_read_1(bas->bst, bas->bsh, SSCOM_UTRSTAT);
+ while (!(utrstat & UTRSTAT_RXREADY)) {
+ utrstat = bus_space_read_1(bas->bst, bas->bsh, SSCOM_UTRSTAT);
+ continue;
+ }
+
+ return (bus_space_read_1(bas->bst, bas->bsh, SSCOM_URXH));
+}
+
+static int exynos4210_bus_probe(struct uart_softc *sc);
+static int exynos4210_bus_attach(struct uart_softc *sc);
+static int exynos4210_bus_flush(struct uart_softc *, int);
+static int exynos4210_bus_getsig(struct uart_softc *);
+static int exynos4210_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int exynos4210_bus_ipend(struct uart_softc *);
+static int exynos4210_bus_param(struct uart_softc *, int, int, int, int);
+static int exynos4210_bus_receive(struct uart_softc *);
+static int exynos4210_bus_setsig(struct uart_softc *, int);
+static int exynos4210_bus_transmit(struct uart_softc *);
+
+static kobj_method_t exynos4210_methods[] = {
+ KOBJMETHOD(uart_probe, exynos4210_bus_probe),
+ KOBJMETHOD(uart_attach, exynos4210_bus_attach),
+ KOBJMETHOD(uart_flush, exynos4210_bus_flush),
+ KOBJMETHOD(uart_getsig, exynos4210_bus_getsig),
+ KOBJMETHOD(uart_ioctl, exynos4210_bus_ioctl),
+ KOBJMETHOD(uart_ipend, exynos4210_bus_ipend),
+ KOBJMETHOD(uart_param, exynos4210_bus_param),
+ KOBJMETHOD(uart_receive, exynos4210_bus_receive),
+ KOBJMETHOD(uart_setsig, exynos4210_bus_setsig),
+ KOBJMETHOD(uart_transmit, exynos4210_bus_transmit),
+
+ {0, 0 }
+};
+
+int
+exynos4210_bus_probe(struct uart_softc *sc)
+{
+
+ sc->sc_txfifosz = 16;
+ sc->sc_rxfifosz = 16;
+
+ return (0);
+}
+
+static int
+exynos4210_bus_attach(struct uart_softc *sc)
+{
+
+ sc->sc_hwiflow = 0;
+ sc->sc_hwoflow = 0;
+
+ return (0);
+}
+
+static int
+exynos4210_bus_transmit(struct uart_softc *sc)
+{
+ int i;
+ int reg;
+
+ uart_lock(sc->sc_hwmtx);
+
+ for (i = 0; i < sc->sc_txdatasz; i++) {
+ exynos4210_putc(&sc->sc_bas, sc->sc_txbuf[i]);
+ uart_barrier(&sc->sc_bas);
+ }
+
+ sc->sc_txbusy = 1;
+
+ uart_unlock(sc->sc_hwmtx);
+
+ /* unmask TX interrupt */
+ reg = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UINTM);
+ reg &= ~(1 << 2);
+ bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UINTM, reg);
+
+ return (0);
+}
+
+static int
+exynos4210_bus_setsig(struct uart_softc *sc, int sig)
+{
+
+ return (0);
+}
+
+static int
+exynos4210_bus_receive(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ while (bus_space_read_4(bas->bst, bas->bsh,
+ SSCOM_UFSTAT) & UFSTAT_RXCOUNT)
+ uart_rx_put(sc, uart_getreg(&sc->sc_bas, SSCOM_URXH));
+
+ return (0);
+}
+
+static int
+exynos4210_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ int error;
+
+ if (sc->sc_bas.rclk == 0)
+ sc->sc_bas.rclk = DEF_CLK;
+
+ KASSERT(sc->sc_bas.rclk != 0, ("exynos4210_init: Invalid rclk"));
+
+ uart_lock(sc->sc_hwmtx);
+ error = exynos4210_uart_param(&sc->sc_bas, baudrate, databits, stopbits,
+ parity);
+ uart_unlock(sc->sc_hwmtx);
+
+ return (error);
+}
+
+static int
+exynos4210_bus_ipend(struct uart_softc *sc)
+{
+ uint32_t ints;
+ uint32_t txempty, rxready;
+ int reg;
+ int ipend;
+
+ uart_lock(sc->sc_hwmtx);
+ ints = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UINTP);
+ bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UINTP, ints);
+
+ txempty = (1 << 2);
+ rxready = (1 << 0);
+
+ ipend = 0;
+ if ((ints & txempty) > 0) {
+ if (sc->sc_txbusy != 0)
+ ipend |= SER_INT_TXIDLE;
+
+ /* mask TX interrupt */
+ reg = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh,
+ SSCOM_UINTM);
+ reg |= (1 << 2);
+ bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh,
+ SSCOM_UINTM, reg);
+ }
+
+ if ((ints & rxready) > 0) {
+ ipend |= SER_INT_RXREADY;
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+ return (ipend);
+}
+
+static int
+exynos4210_bus_flush(struct uart_softc *sc, int what)
+{
+
+ return (0);
+}
+
+static int
+exynos4210_bus_getsig(struct uart_softc *sc)
+{
+
+ return (0);
+}
+
+static int
+exynos4210_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+
+ return (EINVAL);
+}
+
+static struct uart_class uart_exynos4210_class = {
+ "exynos4210 class",
+ exynos4210_methods,
+ 1,
+ .uc_ops = &uart_exynos4210_ops,
+ .uc_range = 8,
+ .uc_rclk = 0,
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"exynos", (uintptr_t)&uart_exynos4210_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
Property changes on: trunk/sys/arm/samsung/exynos/exynos_uart.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/exynos_uart.h
===================================================================
--- trunk/sys/arm/samsung/exynos/exynos_uart.h (rev 0)
+++ trunk/sys/arm/samsung/exynos/exynos_uart.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,127 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c2xx0reg.h,v 1.4 2004/02/12 03:47:29 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 Fujitsu Component Limited
+ * Copyright (c) 2002, 2003 Genetec Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of The Fujitsu Component Limited nor the name of
+ * Genetec corporation may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
+ * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
+ * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/exynos/exynos_uart.h 283322 2015-05-23 19:50:14Z ian $
+ */
+
+/* s3c2410-specific registers */
+#define UMCON_AFC (1 << 4) /* auto flow control */
+#define UMSTAT_DCTS (1 << 2) /* CTS change */
+#define ULCON_IR (1 << 6)
+#define ULCON_PARITY_SHIFT 3
+
+/*
+ * Exynos-specific
+ *
+ * UFSTAT_TXFULL register differs between Exynos and others.
+ * Others have UFSTAT_TXFULL (1 << 9)
+ */
+#define UFSTAT_TXFULL (1 << 24)
+
+#define SSCOM_UINTM 0x038
+#define SSCOM_UINTP 0x030
+
+/* common for s3c2800 and s3c24x0 */
+#define SSCOM_ULCON 0x00 /* UART line control */
+#define ULCON_PARITY_NONE (0 << ULCON_PARITY_SHIFT)
+#define ULCON_PARITY_ODD (4 << ULCON_PARITY_SHIFT)
+#define ULCON_PARITY_EVEN (5 << ULCON_PARITY_SHIFT)
+#define ULCON_PARITY_ONE (6 << ULCON_PARITY_SHIFT)
+#define ULCON_PARITY_ZERO (7 << ULCON_PARITY_SHIFT)
+#define ULCON_STOP (1 << 2)
+#define ULCON_LENGTH_5 0
+#define ULCON_LENGTH_6 1
+#define ULCON_LENGTH_7 2
+#define ULCON_LENGTH_8 3
+#define SSCOM_UCON 0x04 /* UART control */
+#define UCON_TXINT_TYPE (1 << 9) /* Tx interrupt. 0=pulse,1=level */
+#define UCON_TXINT_TYPE_LEVEL UCON_TXINT_TYPE
+#define UCON_TXINT_TYPE_PULSE 0
+#define UCON_RXINT_TYPE (1 << 8) /* Rx interrupt */
+#define UCON_RXINT_TYPE_LEVEL UCON_RXINT_TYPE
+#define UCON_RXINT_TYPE_PULSE 0
+#define UCON_TOINT (1 << 7) /* Rx timeout interrupt */
+#define UCON_ERRINT (1 << 6) /* receive error interrupt */
+#define UCON_LOOP (1 << 5) /* loopback */
+#define UCON_SBREAK (1 << 4) /* send break */
+#define UCON_TXMODE_DISABLE (0 << 2)
+#define UCON_TXMODE_INT (1 << 2)
+#define UCON_TXMODE_DMA (2 << 2)
+#define UCON_TXMODE_MASK (3 << 2)
+#define UCON_RXMODE_DISABLE (0 << 0)
+#define UCON_RXMODE_INT (1 << 0)
+#define UCON_RXMODE_DMA (2 << 0)
+#define UCON_RXMODE_MASK (3 << 0)
+#define SSCOM_UFCON 0x08 /* FIFO control */
+#define UFCON_TXTRIGGER_0 (0 << 6)
+#define UFCON_TXTRIGGER_4 (1 << 6)
+#define UFCON_TXTRIGGER_8 (2 << 6)
+#define UFCON_TXTRIGGER_16 (3 << 6)
+#define UFCON_RXTRIGGER_4 (0 << 4)
+#define UFCON_RXTRIGGER_8 (1 << 4)
+#define UFCON_RXTRIGGER_12 (2 << 4)
+#define UFCON_RXTRIGGER_16 (3 << 4)
+#define UFCON_TXFIFO_RESET (1 << 2)
+#define UFCON_RXFIFO_RESET (1 << 1)
+#define UFCON_FIFO_ENABLE (1 << 0)
+#define SSCOM_UMCON 0x0c /* MODEM control */
+#define UMCON_RTS (1 << 0) /* Request to send */
+#define SSCOM_UTRSTAT 0x10 /* Status register */
+#define UTRSTAT_TXSHIFTER_EMPTY ( 1<< 2)
+#define UTRSTAT_TXEMPTY (1 << 1) /* TX fifo or buffer empty */
+#define UTRSTAT_RXREADY (1 << 0) /* RX fifo or buffer is not empty */
+#define SSCOM_UERSTAT 0x14 /* Error status register */
+#define UERSTAT_BREAK (1 << 3) /* Break signal, not 2410 */
+#define UERSTAT_FRAME (1 << 2) /* Frame error */
+#define UERSTAT_PARITY (1 << 1) /* Parity error, not 2410 */
+#define UERSTAT_OVERRUN (1 << 0) /* Overrun */
+#define UERSTAT_ALL_ERRORS \
+ (UERSTAT_OVERRUN|UERSTAT_BREAK|UERSTAT_FRAME|UERSTAT_PARITY)
+#define SSCOM_UFSTAT 0x18 /* Fifo status register */
+#define UFSTAT_RXFULL (1 <<8) /* Rx fifo full */
+#define UFSTAT_TXCOUNT_SHIFT 4 /* TX FIFO count */
+#define UFSTAT_TXCOUNT (0x0f << UFSTAT_TXCOUNT_SHIFT)
+#define UFSTAT_RXCOUNT_SHIFT 0 /* RX FIFO count */
+#define UFSTAT_RXCOUNT (0x0f << UFSTAT_RXCOUNT_SHIFT)
+#define SSCOM_UMSTAT 0x1c /* Modem status register */
+#define UMSTAT_CTS (1 << 0) /* Clear to send */
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#define SSCOM_UTXH 0x20 /* Transmit data register */
+#define SSCOM_URXH 0x24 /* Receive data register */
+#else
+#define SSCOM_UTXH 0x23 /* Transmit data register */
+#define SSCOM_URXH 0x27 /* Receive data register */
+#endif
+#define SSCOM_UBRDIV 0x28 /* baud-reate divisor */
+#define SSCOM_SIZE 0x2c
Property changes on: trunk/sys/arm/samsung/exynos/exynos_uart.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/files.exynos5
===================================================================
--- trunk/sys/arm/samsung/exynos/files.exynos5 (rev 0)
+++ trunk/sys/arm/samsung/exynos/files.exynos5 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,31 @@
+# $FreeBSD: stable/10/sys/arm/samsung/exynos/files.exynos5 283322 2015-05-23 19:50:14Z ian $
+
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_generic.c standard
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+
+arm/arm/bus_space_base.c standard
+arm/arm/gic.c standard
+arm/arm/generic_timer.c standard
+
+arm/samsung/exynos/exynos5_mct.c standard
+arm/samsung/exynos/exynos5_mp.c optional smp
+arm/samsung/exynos/exynos5_common.c standard
+arm/samsung/exynos/exynos5_machdep.c standard
+arm/samsung/exynos/exynos5_combiner.c standard
+arm/samsung/exynos/exynos5_pad.c optional gpio
+arm/samsung/exynos/exynos_uart.c optional uart
+arm/samsung/exynos/exynos5_ehci.c optional ehci
+arm/samsung/exynos/exynos5_fimd.c optional vt
+arm/samsung/exynos/exynos5_i2c.c optional iicbus
+
+# chromebook drivers
+arm/samsung/exynos/chrome_ec.c optional chrome_ec
+arm/samsung/exynos/chrome_kb.c optional chrome_kb
+
+#dev/sdhci/sdhci_fdt.c optional sdhci
Property changes on: trunk/sys/arm/samsung/exynos/files.exynos5
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/std.exynos5250
===================================================================
--- trunk/sys/arm/samsung/exynos/std.exynos5250 (rev 0)
+++ trunk/sys/arm/samsung/exynos/std.exynos5250 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,22 @@
+# $FreeBSD: stable/10/sys/arm/samsung/exynos/std.exynos5250 278601 2015-02-11 22:47:48Z ian $
+
+makeoption ARM_LITTLE_ENDIAN
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+
+options PHYSADDR=0x40000000
+
+makeoptions KERNPHYSADDR=0x40f00000
+options KERNPHYSADDR=0x40f00000
+
+makeoptions KERNVIRTADDR=0xc0f00000
+options KERNVIRTADDR=0xc0f00000
+
+options ARM_L2_PIPT
+
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
+
+files "../samsung/exynos/files.exynos5"
Property changes on: trunk/sys/arm/samsung/exynos/std.exynos5250
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/samsung/exynos/std.exynos5420
===================================================================
--- trunk/sys/arm/samsung/exynos/std.exynos5420 (rev 0)
+++ trunk/sys/arm/samsung/exynos/std.exynos5420 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,22 @@
+# $FreeBSD: stable/10/sys/arm/samsung/exynos/std.exynos5420 278601 2015-02-11 22:47:48Z ian $
+
+makeoption ARM_LITTLE_ENDIAN
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+
+options PHYSADDR=0x20000000
+
+makeoptions KERNPHYSADDR=0x20f00000
+options KERNPHYSADDR=0x20f00000
+
+makeoptions KERNVIRTADDR=0xc0f00000
+options KERNVIRTADDR=0xc0f00000
+
+options ARM_L2_PIPT
+
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
+
+files "../samsung/exynos/files.exynos5"
Property changes on: trunk/sys/arm/samsung/exynos/std.exynos5420
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/board_ln2410sbc.c
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/board_ln2410sbc.c (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/board_ln2410sbc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,46 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (C) 2009 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/board_ln2410sbc.c 272103 2014-09-25 11:38:26Z gavin $");
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <arm/samsung/s3c2xx0/s3c2410reg.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0board.h>
+
+extern vm_offset_t s3c2410_uart_vaddr;
+
+long
+board_init(void)
+{
+ s3c2410_uart_vaddr = S3C24X0_UART_BASE(0);
+
+ return (64 * 1024 * 1024);
+}
+
Property changes on: trunk/sys/arm/samsung/s3c2xx0/board_ln2410sbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/files.s3c2xx0
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/files.s3c2xx0 (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/files.s3c2xx0 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,15 @@
+# $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/files.s3c2xx0 278727 2015-02-13 22:32:02Z ian $
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_arm9.S standard
+arm/samsung/s3c2xx0/board_ln2410sbc.c optional board_ln2410sbc
+arm/samsung/s3c2xx0/s3c24x0_rtc.c standard
+arm/samsung/s3c2xx0/s3c24x0_machdep.c standard
+arm/samsung/s3c2xx0/s3c24x0.c standard
+arm/samsung/s3c2xx0/s3c24x0_clk.c standard
+arm/samsung/s3c2xx0/uart_bus_s3c2410.c optional uart
+arm/samsung/s3c2xx0/uart_cpu_s3c2410.c optional uart
+arm/samsung/s3c2xx0/uart_dev_s3c2410.c optional uart
+
+dev/usb/controller/ohci_s3c24x0.c optional ohci
Property changes on: trunk/sys/arm/samsung/s3c2xx0/files.s3c2xx0
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c2410reg.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c2410reg.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c2410reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,97 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c2410reg.h,v 1.6 2004/02/12 03:52:46 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2003, 2004 Genetec corporation. All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of Genetec corporation may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c2410reg.h 272103 2014-09-25 11:38:26Z gavin $
+ */
+
+
+/*
+ * Samsung S3C2410X processor is ARM920T based integrated CPU
+ *
+ * Reference:
+ * S3C2410X User's Manual
+ */
+#ifndef _ARM_S3C2XX0_S3C2410REG_H_
+#define _ARM_S3C2XX0_S3C2410REG_H_
+
+/* common definitions for S3C2410 and S3C2440 */
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
+
+/*
+ * Memory Map
+ */
+#define S3C2410_BANK_SIZE 0x08000000
+#define S3C2410_BANK_START(n) (S3C2410_BANK_SIZE*(n))
+#define S3C2410_SDRAM_START S3C2410_BANK_START(6)
+
+
+/* interrupt control */
+#define S3C2410_SUBIRQ_MAX (S3C24X0_SUBIRQ_MIN+10)
+
+/* Clock control */
+/* CLKMAN_CLKCON */
+#define S3C2410_CLKCON_SM (1<<0) /* 1=transition to SPECIAL mode */
+/* CLKMAN_CLKDIVN */
+#define S3C2410_CLKDIVN_HDIVN (1<<1) /* hclk=fclk/2 */
+
+/* NAND Flash controller */
+#define S3C2410_NANDFC_SIZE 0x18
+/* NANDFC_NFCONF */
+#define S3C2410_NFCONF_ENABLE (1<<15) /* NAND controller enabled */
+#define S3C2410_NFCONF_ECC (1<<12) /* Initialize ECC decoder/encoder */
+#define S3C2410_NFCONF_FCE (1<<11) /* Flash chip enabled */
+#define S3C2410_NFCONF_TACLS (7<<8) /* CLE and ALE duration */
+#define S3C2410_NFCONF_TWRPH0 (7<<4) /* TWRPH0 duration */
+#define S3C2410_NFCONF_TWRPH1 (7<<0) /* TWRPH1 duration */
+#define S3C2410_NANDFC_NFCMD 0x04 /* command */
+#define S3C2410_NANDFC_NFADDR 0x08 /* address */
+#define S3C2410_NANDFC_NFDATA 0x0c /* data */
+#define S3C2410_NANDFC_NFSTAT 0x10 /* operation status */
+#define S3C2410_NANDFC_NFECC 0x14 /* ecc */
+
+/* MMC/SD */
+/* SDI_CON */
+#define S3C2410_CON_FIFO_RESET (1<<1)
+
+/* GPIO */
+#define S3C2410_GPIO_SIZE 0xb4
+
+/* SD interface */
+#define S3C2410_SDI_SIZE 0x44
+#define DCON_STOP (1<<14) /* Force the transfer to stop */
+#define S3C2410_SDI_DAT 0x3c
+#define S3C2410_SDI_IMSK 0x40 /* Interrupt mask */
+#define S3C2410_SDI_IMASK_ALL 0x3ffdf
+
+/* ADC */
+#define S3C2410_ADC_SIZE 0x14
+
+#endif /* _ARM_S3C2XX0_S3C2410REG_H_ */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c2410reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c2410var.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c2410var.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c2410var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,50 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c2410var.h,v 1.2 2003/08/29 12:57:50 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2003 Genetec corporation. All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of Genetec corporation may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c2410var.h 272103 2014-09-25 11:38:26Z gavin $
+ */
+
+#ifndef _ARM_S3C2410VAR_H_
+#define _ARM_S3C2410VAR_H_
+
+#include <arm/samsung/s3c2xx0/s3c24x0var.h>
+
+int s3c2410_sscom_cnattach(bus_space_tag_t, int, int, int, tcflag_t);
+int s3c2410_sscom_kgdb_attach(bus_space_tag_t, int, int, int, tcflag_t);
+void s3c2410_intr_init(struct s3c24x0_softc *);
+void s3c2410_softreset(void);
+
+void s3c2410_mask_subinterrupts(int);
+void s3c2410_unmask_subinterrupts(int);
+
+void *s3c2410_extint_establish(int, int, int, int (*)(void *), void *);
+void s3c2410_setup_extint(int, int);
+#endif /* _ARM_S3C2410VAR_H_ */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c2410var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c2440reg.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c2440reg.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c2440reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,110 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2009 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c2440reg.h 272103 2014-09-25 11:38:26Z gavin $
+ */
+
+/*
+ * Samsung S3C2440X processor is ARM920T based integrated CPU
+ *
+ * Reference:
+ * S3C2440A/S3C2442B User's Manual
+ */
+#ifndef _ARM_S3C2XX0_S3C2440REG_H_
+#define _ARM_S3C2XX0_S3C2440REG_H_
+
+/* common definitions for S3C2410 and S3C2440 */
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
+
+/*
+ * Memory Map
+ */
+#define S3C2440_BANK_SIZE 0x08000000
+#define S3C2440_BANK_START(n) (S3C2410_BANK_SIZE*(n))
+#define S3C2440_SDRAM_START S3C2410_BANK_START(6)
+
+
+/* interrupt control */
+#define S3C2440_SUBIRQ_MAX (S3C24X0_SUBIRQ_MIN+10)
+
+/* Clock control */
+/* CLKMAN_CLKCON */
+#define S3C2440_CLKCON_STOP (1<<0) /* 1=transition to STOP mode */
+/* CLKMAN_CLKDIVN */
+#define S3C2440_CLKDIVN_HDIVN (3<<1) /* hclk */
+#define S3C2440_CLKMAN_CAMDIVN 0x18
+#define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)
+#define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)
+
+/* NAND Flash controller */
+#define S3C2440_NANDFC_SIZE 0x40
+
+#define S3C2440_NANDFC_NFCONT 0x04
+#define S3C2440_NFCONT_LOCK_TIGHT (1<<13) /* Lock part of the NAND */
+#define S3C2440_NFCONT_SOFT_LOCK (1<<12) /* Soft lock part of the NAND */
+#define S3C2440_NFCONT_ILLEGAL_ACC_INT (1<<10) /* Illegal access interrupt */
+#define S3C2440_NFCONT_RNB_INT (1<<9) /* RnB transition interrupt */
+#define S3C2440_NFCONT_RNB_TRANS_MODE (1<<8) /* RnB transition mode */
+#define S3C2440_NFCONT_SPARE_ECC_LOCK (1<<6) /* Lock spare ECC generation */
+#define S3C2440_NFCONT_MAIN_ECC_LOCK (1<<5) /* Lock main ECC generation */
+#define S3C2440_NFCONT_INIT_ECC (1<<4) /* Init ECC encoder/decoder */
+#define S3C2440_NFCONT_NCE (1<<1) /* NAND Chip select */
+#define S3C2440_NFCONT_ENABLE (1<<0) /* Enable the controller */
+#define S3C2440_NANDFC_NFCMMD 0x08
+#define S3C2440_NANDFC_NFADDR 0x0c
+#define S3C2440_NANDFC_NFDATA 0x10
+#define S3C2440_NANDFC_NFSTAT 0x20
+
+/* MMC/SD */
+/* SDI_CON */
+#define S3C2440_CON_RESET (1<<8)
+#define S3C2440_CON_CLOCK_TYPE (1<<5)
+/* SDI_FSTA */
+#define S3c2440_FSTA_RESET (1<<16)
+#define S3C2440_FSTA_FAIL_ERROR_MSK (3<<14)
+#define S3C2440_FSTA_FAIL_NONE (0<<14)
+#define S3C2440_FSTA_FAIL_FIFO (1<<14)
+#define S3C2440_FSTA_FAIL_LAST_TRANS (2<<14)
+
+/* GPIO */
+#define S3C2440_GPIO_SIZE 0xd0
+
+/* SD interface */
+#define S3C2410_SDI_SIZE 0x44
+#define DCON_START (1<<14) /* Start the data transfer */
+#define S3C2440_SDI_IMSK 0x3c /* Interrupt mask */
+#define S3C2440_SDI_IMASK_ALL 0x3C7C0
+#define S3C2440_SDI_DAT 0x40
+
+/* ADC */
+#define ADCTSC_UD_SEN (1<<8)
+#define S3C2440_ADC_SIZE 0x18
+
+/* UART */
+#define S3C2440_UFSTAT_TXCOUNT (0x3f << 8)
+#define S3C2440_UFSTAT_RXCOUNT (0x3f << 0)
+
+#endif /* _ARM_S3C2XX0_S3C2440REG_H_ */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c2440reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c24x0.c
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c24x0.c (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c24x0.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,803 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c2410.c,v 1.4 2003/08/27 03:46:05 bsh Exp $ */
+
+/*
+ * Copyright (c) 2003 Genetec corporation. All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of Genetec corporation may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c24x0.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/armreg.h>
+#include <machine/cpu.h>
+#include <machine/bus.h>
+
+#include <machine/cpufunc.h>
+#include <machine/intr.h>
+#include <arm/samsung/s3c2xx0/s3c2410reg.h>
+#include <arm/samsung/s3c2xx0/s3c2440reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0var.h>
+#include <sys/rman.h>
+
+#define S3C2XX0_XTAL_CLK 12000000
+
+bus_space_tag_t s3c2xx0_bs_tag;
+
+#define IPL_LEVELS 13
+u_int irqmasks[IPL_LEVELS];
+
+static struct {
+ uint32_t idcode;
+ const char *name;
+ s3c2xx0_cpu cpu;
+} s3c2x0_cpu_id[] = {
+ { CHIPID_S3C2410A, "S3C2410A", CPU_S3C2410 },
+ { CHIPID_S3C2440A, "S3C2440A", CPU_S3C2440 },
+ { CHIPID_S3C2442B, "S3C2442B", CPU_S3C2440 },
+
+ { 0, NULL }
+};
+
+static struct {
+ const char *name;
+ int prio;
+ int unit;
+ struct {
+ int type;
+ u_long start;
+ u_long count;
+ } res[2];
+} s3c24x0_children[] = {
+ { "rtc", 0, -1, {
+ { SYS_RES_IOPORT, S3C24X0_RTC_PA_BASE, S3C24X0_RTC_SIZE },
+ { 0 },
+ } },
+ { "timer", 0, -1, { { 0 }, } },
+ { "uart", 1, 0, {
+ { SYS_RES_IRQ, S3C24X0_INT_UART0, 1 },
+ { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(0),
+ S3C24X0_UART_BASE(1) - S3C24X0_UART_BASE(0) },
+ } },
+ { "uart", 1, 1, {
+ { SYS_RES_IRQ, S3C24X0_INT_UART1, 1 },
+ { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(1),
+ S3C24X0_UART_BASE(2) - S3C24X0_UART_BASE(1) },
+ } },
+ { "uart", 1, 2, {
+ { SYS_RES_IRQ, S3C24X0_INT_UART2, 1 },
+ { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(2),
+ S3C24X0_UART_BASE(3) - S3C24X0_UART_BASE(2) },
+ } },
+ { "ohci", 0, -1, {
+ { SYS_RES_IRQ, S3C24X0_INT_USBH, 0 },
+ { SYS_RES_IOPORT, S3C24X0_USBHC_PA_BASE, S3C24X0_USBHC_SIZE },
+ } },
+ { NULL },
+};
+
+
+/* prototypes */
+static device_t s3c24x0_add_child(device_t, int, const char *, int);
+
+static int s3c24x0_probe(device_t);
+static int s3c24x0_attach(device_t);
+static void s3c24x0_identify(driver_t *, device_t);
+static int s3c24x0_setup_intr(device_t, device_t, struct resource *, int,
+ driver_filter_t *, driver_intr_t *, void *, void **);
+static int s3c24x0_teardown_intr(device_t, device_t, struct resource *,
+ void *);
+static int s3c24x0_config_intr(device_t, int, enum intr_trigger,
+ enum intr_polarity);
+static struct resource *s3c24x0_alloc_resource(device_t, device_t, int, int *,
+ u_long, u_long, u_long, u_int);
+static int s3c24x0_activate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int s3c24x0_release_resource(device_t, device_t, int, int,
+ struct resource *);
+static struct resource_list *s3c24x0_get_resource_list(device_t, device_t);
+
+static void s3c24x0_identify_cpu(device_t);
+
+static device_method_t s3c24x0_methods[] = {
+ DEVMETHOD(device_probe, s3c24x0_probe),
+ DEVMETHOD(device_attach, s3c24x0_attach),
+ DEVMETHOD(device_identify, s3c24x0_identify),
+ DEVMETHOD(bus_setup_intr, s3c24x0_setup_intr),
+ DEVMETHOD(bus_teardown_intr, s3c24x0_teardown_intr),
+ DEVMETHOD(bus_config_intr, s3c24x0_config_intr),
+ DEVMETHOD(bus_alloc_resource, s3c24x0_alloc_resource),
+ DEVMETHOD(bus_activate_resource, s3c24x0_activate_resource),
+ DEVMETHOD(bus_release_resource, s3c24x0_release_resource),
+ DEVMETHOD(bus_get_resource_list,s3c24x0_get_resource_list),
+ DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ {0, 0},
+};
+
+static driver_t s3c24x0_driver = {
+ "s3c24x0",
+ s3c24x0_methods,
+ sizeof(struct s3c24x0_softc),
+};
+static devclass_t s3c24x0_devclass;
+
+DRIVER_MODULE(s3c24x0, nexus, s3c24x0_driver, s3c24x0_devclass, 0, 0);
+
+struct s3c2xx0_softc *s3c2xx0_softc = NULL;
+
+static device_t
+s3c24x0_add_child(device_t bus, int prio, const char *name, int unit)
+{
+ device_t child;
+ struct s3c2xx0_ivar *ivar;
+
+ child = device_add_child_ordered(bus, prio, name, unit);
+ if (child == NULL)
+ return (NULL);
+
+ ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (ivar == NULL) {
+ device_delete_child(bus, child);
+ printf("Can't add alloc ivar\n");
+ return (NULL);
+ }
+ device_set_ivars(child, ivar);
+ resource_list_init(&ivar->resources);
+
+ return (child);
+}
+
+static void
+s3c24x0_enable_ext_intr(unsigned int irq)
+{
+ uint32_t reg, value;
+ int offset;
+
+ if (irq <= 7) {
+ reg = GPIO_PFCON;
+ offset = irq * 2;
+ } else if (irq <= 23) {
+ reg = GPIO_PGCON;
+ offset = (irq - 8) * 2;
+ } else
+ return;
+
+ /* Make the pin an interrupt source */
+ value = bus_space_read_4(s3c2xx0_softc->sc_iot,
+ s3c2xx0_softc->sc_gpio_ioh, reg);
+ value &= ~(3 << offset);
+ value |= 2 << offset;
+ bus_space_write_4(s3c2xx0_softc->sc_iot, s3c2xx0_softc->sc_gpio_ioh,
+ reg, value);
+}
+
+static int
+s3c24x0_setup_intr(device_t dev, device_t child,
+ struct resource *ires, int flags, driver_filter_t *filt,
+ driver_intr_t *intr, void *arg, void **cookiep)
+{
+ int error, irq;
+
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt,
+ intr, arg, cookiep);
+ if (error != 0)
+ return (error);
+
+ for (irq = rman_get_start(ires); irq <= rman_get_end(ires); irq++) {
+ if (irq >= S3C24X0_EXTIRQ_MIN && irq <= S3C24X0_EXTIRQ_MAX) {
+ /* Enable the external interrupt pin */
+ s3c24x0_enable_ext_intr(irq - S3C24X0_EXTIRQ_MIN);
+ }
+ }
+ return (0);
+}
+
+static int
+s3c24x0_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
+static int
+s3c24x0_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+ uint32_t mask, reg, value;
+ int offset;
+
+ /* Only external interrupts can be configured */
+ if (irq < S3C24X0_EXTIRQ_MIN || irq > S3C24X0_EXTIRQ_MAX)
+ return (EINVAL);
+
+ /* There is no standard trigger or polarity for the bus */
+ if (trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM)
+ return (EINVAL);
+
+ irq -= S3C24X0_EXTIRQ_MIN;
+
+ /* Get the bits to set */
+ mask = 0;
+ if (pol == INTR_POLARITY_LOW) {
+ mask = 2;
+ } else if (pol == INTR_POLARITY_HIGH) {
+ mask = 4;
+ }
+ if (trig == INTR_TRIGGER_LEVEL) {
+ mask >>= 2;
+ }
+
+ /* Get the register to set */
+ if (irq <= 7) {
+ reg = GPIO_EXTINT(0);
+ offset = irq * 4;
+ } else if (irq <= 15) {
+ reg = GPIO_EXTINT(1);
+ offset = (irq - 8) * 4;
+ } else if (irq <= 23) {
+ reg = GPIO_EXTINT(2);
+ offset = (irq - 16) * 4;
+ } else {
+ return (EINVAL);
+ }
+
+ /* Set the new signaling method */
+ value = bus_space_read_4(s3c2xx0_softc->sc_iot,
+ s3c2xx0_softc->sc_gpio_ioh, reg);
+ value &= ~(7 << offset);
+ value |= mask << offset;
+ bus_space_write_4(s3c2xx0_softc->sc_iot,
+ s3c2xx0_softc->sc_gpio_ioh, reg, value);
+
+ return (0);
+}
+
+static struct resource *
+s3c24x0_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct resource_list_entry *rle;
+ struct s3c2xx0_ivar *ivar = device_get_ivars(child);
+ struct resource_list *rl = &ivar->resources;
+ struct resource *res = NULL;
+
+ if (device_get_parent(child) != bus)
+ return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
+ type, rid, start, end, count, flags));
+
+ rle = resource_list_find(rl, type, *rid);
+ if (rle != NULL) {
+ /* There is a resource list. Use it */
+ if (rle->res)
+ panic("Resource rid %d type %d already in use", *rid,
+ type);
+ if (start == 0UL && end == ~0UL) {
+ start = rle->start;
+ count = ulmax(count, rle->count);
+ end = ulmax(rle->end, start + count - 1);
+ }
+ /*
+ * When allocating an irq with children irq's really
+ * allocate the children as it is those we are interested
+ * in receiving, not the parent.
+ */
+ if (type == SYS_RES_IRQ && start == end) {
+ switch (start) {
+ case S3C24X0_INT_ADCTC:
+ start = S3C24X0_INT_TC;
+ end = S3C24X0_INT_ADC;
+ break;
+#ifdef S3C2440_INT_CAM
+ case S3C2440_INT_CAM:
+ start = S3C2440_INT_CAM_C;
+ end = S3C2440_INT_CAM_P;
+ break;
+#endif
+ default:
+ break;
+ }
+ count = end - start + 1;
+ }
+ }
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ res = rman_reserve_resource(
+ &s3c2xx0_softc->s3c2xx0_irq_rman, start, end,
+ count, flags, child);
+ break;
+
+ case SYS_RES_IOPORT:
+ case SYS_RES_MEMORY:
+ res = rman_reserve_resource(
+ &s3c2xx0_softc->s3c2xx0_mem_rman,
+ start, end, count, flags, child);
+ if (res == NULL)
+ panic("Unable to map address space %#lX-%#lX", start,
+ end);
+
+ rman_set_bustag(res, s3c2xx0_bs_tag);
+ rman_set_bushandle(res, start);
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, res)) {
+ rman_release_resource(res);
+ return (NULL);
+ }
+ }
+ break;
+ }
+
+ if (res != NULL) {
+ rman_set_rid(res, *rid);
+ if (rle != NULL) {
+ rle->res = res;
+ rle->start = rman_get_start(res);
+ rle->end = rman_get_end(res);
+ rle->count = count;
+ }
+ }
+
+ return (res);
+}
+
+static int
+s3c24x0_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ bus_space_handle_t p;
+ int error;
+
+ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+ error = bus_space_map(rman_get_bustag(r),
+ rman_get_bushandle(r), rman_get_size(r), 0, &p);
+ if (error)
+ return (error);
+ rman_set_bushandle(r, p);
+ }
+ return (rman_activate_resource(r));
+}
+
+static int
+s3c24x0_release_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct s3c2xx0_ivar *ivar = device_get_ivars(child);
+ struct resource_list *rl = &ivar->resources;
+ struct resource_list_entry *rle;
+
+ if (rl == NULL)
+ return (EINVAL);
+
+ rle = resource_list_find(rl, type, rid);
+ if (rle == NULL)
+ return (EINVAL);
+
+ rman_release_resource(r);
+ rle->res = NULL;
+
+ return 0;
+}
+
+static struct resource_list *
+s3c24x0_get_resource_list(device_t dev, device_t child)
+{
+ struct s3c2xx0_ivar *ivar;
+
+ ivar = device_get_ivars(child);
+ return (&(ivar->resources));
+}
+
+void
+s3c24x0_identify(driver_t *driver, device_t parent)
+{
+
+ BUS_ADD_CHILD(parent, 0, "s3c24x0", 0);
+}
+
+int
+s3c24x0_probe(device_t dev)
+{
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+int
+s3c24x0_attach(device_t dev)
+{
+ struct s3c24x0_softc *sc = device_get_softc(dev);
+ bus_space_tag_t iot;
+ device_t child;
+ unsigned int i, j;
+ u_long irqmax;
+
+ s3c2xx0_bs_tag = arm_base_bs_tag;
+ s3c2xx0_softc = &(sc->sc_sx);
+ sc->sc_sx.sc_iot = iot = s3c2xx0_bs_tag;
+ s3c2xx0_softc->s3c2xx0_irq_rman.rm_type = RMAN_ARRAY;
+ s3c2xx0_softc->s3c2xx0_irq_rman.rm_descr = "S3C24X0 IRQs";
+ s3c2xx0_softc->s3c2xx0_mem_rman.rm_type = RMAN_ARRAY;
+ s3c2xx0_softc->s3c2xx0_mem_rman.rm_descr = "S3C24X0 Device Registers";
+ /* Manage the registor memory space */
+ if ((rman_init(&s3c2xx0_softc->s3c2xx0_mem_rman) != 0) ||
+ (rman_manage_region(&s3c2xx0_softc->s3c2xx0_mem_rman,
+ S3C24X0_DEV_VA_OFFSET,
+ S3C24X0_DEV_VA_OFFSET + S3C24X0_DEV_VA_SIZE) != 0) ||
+ (rman_manage_region(&s3c2xx0_softc->s3c2xx0_mem_rman,
+ S3C24X0_DEV_START, S3C24X0_DEV_STOP) != 0))
+ panic("s3c24x0_attach: failed to set up register rman");
+
+ /* These are needed for things without a proper device to attach to */
+ sc->sc_sx.sc_intctl_ioh = S3C24X0_INTCTL_BASE;
+ sc->sc_sx.sc_gpio_ioh = S3C24X0_GPIO_BASE;
+ sc->sc_sx.sc_clkman_ioh = S3C24X0_CLKMAN_BASE;
+ sc->sc_sx.sc_wdt_ioh = S3C24X0_WDT_BASE;
+ sc->sc_timer_ioh = S3C24X0_TIMER_BASE;
+
+ /*
+ * Identify the CPU
+ */
+ s3c24x0_identify_cpu(dev);
+
+ /*
+ * Manage the interrupt space.
+ * We need to put this after s3c24x0_identify_cpu as the avaliable
+ * interrupts change depending on which CPU we have.
+ */
+ if (sc->sc_sx.sc_cpu == CPU_S3C2410)
+ irqmax = S3C2410_SUBIRQ_MAX;
+ else
+ irqmax = S3C2440_SUBIRQ_MAX;
+ if (rman_init(&s3c2xx0_softc->s3c2xx0_irq_rman) != 0 ||
+ rman_manage_region(&s3c2xx0_softc->s3c2xx0_irq_rman, 0,
+ irqmax) != 0 ||
+ rman_manage_region(&s3c2xx0_softc->s3c2xx0_irq_rman,
+ S3C24X0_EXTIRQ_MIN, S3C24X0_EXTIRQ_MAX))
+ panic("s3c24x0_attach: failed to set up IRQ rman");
+
+ /* calculate current clock frequency */
+ s3c24x0_clock_freq(&sc->sc_sx);
+ device_printf(dev, "fclk %d MHz hclk %d MHz pclk %d MHz\n",
+ sc->sc_sx.sc_fclk / 1000000, sc->sc_sx.sc_hclk / 1000000,
+ sc->sc_sx.sc_pclk / 1000000);
+
+ /*
+ * Attach children devices
+ */
+
+ for (i = 0; s3c24x0_children[i].name != NULL; i++) {
+ child = s3c24x0_add_child(dev, s3c24x0_children[i].prio,
+ s3c24x0_children[i].name, s3c24x0_children[i].unit);
+ for (j = 0; j < sizeof(s3c24x0_children[i].res) /
+ sizeof(s3c24x0_children[i].res[0]) &&
+ s3c24x0_children[i].res[j].type != 0; j++) {
+ bus_set_resource(child,
+ s3c24x0_children[i].res[j].type, 0,
+ s3c24x0_children[i].res[j].start,
+ s3c24x0_children[i].res[j].count);
+ }
+ }
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static void
+s3c24x0_identify_cpu(device_t dev)
+{
+ struct s3c24x0_softc *sc = device_get_softc(dev);
+ uint32_t idcode;
+ int i;
+
+ idcode = bus_space_read_4(sc->sc_sx.sc_iot, sc->sc_sx.sc_gpio_ioh,
+ GPIO_GSTATUS1);
+
+ for (i = 0; s3c2x0_cpu_id[i].name != NULL; i++) {
+ if (s3c2x0_cpu_id[i].idcode == idcode)
+ break;
+ }
+ if (s3c2x0_cpu_id[i].name == NULL)
+ panic("Unknown CPU detected ((Chip ID: %#X)", idcode);
+ device_printf(dev, "Found %s CPU (Chip ID: %#X)\n",
+ s3c2x0_cpu_id[i].name, idcode);
+ sc->sc_sx.sc_cpu = s3c2x0_cpu_id[i].cpu;
+}
+
+/*
+ * fill sc_pclk, sc_hclk, sc_fclk from values of clock controller register.
+ *
+ * s3c24{1,4}0_clock_freq2() is meant to be called from kernel startup routines.
+ * s3c24x0_clock_freq() is for after kernel initialization is done.
+ *
+ * Because they can be called before bus_space is available we need to use
+ * volatile pointers rather than bus_space_read.
+ */
+void
+s3c2410_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
+{
+ uint32_t pllcon, divn;
+ unsigned int mdiv, pdiv, sdiv;
+ unsigned int f, h, p;
+
+ pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
+ divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
+
+ mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
+ pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
+ sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
+
+ f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
+ h = f;
+ if (divn & S3C2410_CLKDIVN_HDIVN)
+ h /= 2;
+ p = h;
+ if (divn & CLKDIVN_PDIVN)
+ p /= 2;
+
+ if (fclk) *fclk = f;
+ if (hclk) *hclk = h;
+ if (pclk) *pclk = p;
+}
+
+void
+s3c2440_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
+{
+ uint32_t pllcon, divn, camdivn;
+ unsigned int mdiv, pdiv, sdiv;
+ unsigned int f, h, p;
+
+ pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
+ divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
+ camdivn = *(volatile uint32_t *)(clkman_base + S3C2440_CLKMAN_CAMDIVN);
+
+ mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
+ pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
+ sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
+
+ f = (2 * (mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
+ h = f;
+ switch((divn >> 1) & 3) {
+ case 0:
+ break;
+ case 1:
+ h /= 2;
+ break;
+ case 2:
+ if ((camdivn & S3C2440_CAMDIVN_HCLK4_HALF) ==
+ S3C2440_CAMDIVN_HCLK4_HALF)
+ h /= 8;
+ else
+ h /= 4;
+ break;
+ case 3:
+ if ((camdivn & S3C2440_CAMDIVN_HCLK3_HALF) ==
+ S3C2440_CAMDIVN_HCLK3_HALF)
+ h /= 6;
+ else
+ h /= 3;
+ break;
+ }
+ p = h;
+ if (divn & CLKDIVN_PDIVN)
+ p /= 2;
+
+ if (fclk) *fclk = f;
+ if (hclk) *hclk = h;
+ if (pclk) *pclk = p;
+}
+
+void
+s3c24x0_clock_freq(struct s3c2xx0_softc *sc)
+{
+ vm_offset_t va;
+
+ va = sc->sc_clkman_ioh;
+ switch(sc->sc_cpu) {
+ case CPU_S3C2410:
+ s3c2410_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk,
+ &sc->sc_pclk);
+ break;
+ case CPU_S3C2440:
+ s3c2440_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk,
+ &sc->sc_pclk);
+ break;
+ }
+}
+
+void
+cpu_reset(void)
+{
+ (void) disable_interrupts(PSR_I|PSR_F);
+
+ bus_space_write_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_wdt_ioh, WDT_WTCON,
+ WTCON_ENABLE | WTCON_CLKSEL_16 | WTCON_ENRST);
+ for(;;);
+}
+
+void
+s3c24x0_sleep(int mode __unused)
+{
+ int reg;
+
+ reg = bus_space_read_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_clkman_ioh,
+ CLKMAN_CLKCON);
+ bus_space_write_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_clkman_ioh,
+ CLKMAN_CLKCON, reg | CLKCON_IDLE);
+}
+
+
+int
+arm_get_next_irq(int last __unused)
+{
+ uint32_t intpnd;
+ int irq, subirq;
+
+ if ((irq = bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTOFFSET)) != 0) {
+
+ /* Clear the pending bit */
+ intpnd = bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTPND);
+ bus_space_write_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
+ INTCTL_SRCPND, intpnd);
+ bus_space_write_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
+ INTCTL_INTPND, intpnd);
+
+ switch (irq) {
+ case S3C24X0_INT_ADCTC:
+ case S3C24X0_INT_UART0:
+ case S3C24X0_INT_UART1:
+ case S3C24X0_INT_UART2:
+ /* Find the sub IRQ */
+ subirq = 0x7ff;
+ subirq &= bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND);
+ subirq &= ~(bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK));
+ if (subirq == 0)
+ return (irq);
+
+ subirq = ffs(subirq) - 1;
+
+ /* Clear the sub irq pending bit */
+ bus_space_write_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND,
+ (1 << subirq));
+
+ /*
+ * Return the parent IRQ for UART
+ * as it is all we ever need
+ */
+ if (subirq <= 8)
+ return (irq);
+
+ return (S3C24X0_SUBIRQ_MIN + subirq);
+
+ case S3C24X0_INT_0:
+ case S3C24X0_INT_1:
+ case S3C24X0_INT_2:
+ case S3C24X0_INT_3:
+ /* There is a 1:1 mapping to the IRQ we are handling */
+ return S3C24X0_INT_EXT(irq);
+
+ case S3C24X0_INT_4_7:
+ case S3C24X0_INT_8_23:
+ /* Find the external interrupt being called */
+ subirq = 0x7fffff;
+ subirq &= bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTPEND);
+ subirq &= ~bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
+ if (subirq == 0)
+ return (irq);
+
+ subirq = ffs(subirq) - 1;
+
+ /* Clear the external irq pending bit */
+ bus_space_write_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTPEND,
+ (1 << subirq));
+
+ return S3C24X0_INT_EXT(subirq);
+ }
+
+ return (irq);
+ }
+ return (-1);
+}
+
+void
+arm_mask_irq(uintptr_t irq)
+{
+ u_int32_t mask;
+
+ if (irq >= S3C24X0_INT_EXT(0) && irq <= S3C24X0_INT_EXT(3)) {
+ /* External interrupt 0..3 are directly mapped to irq 0..3 */
+ irq -= S3C24X0_EXTIRQ_MIN;
+ }
+ if (irq < S3C24X0_SUBIRQ_MIN) {
+ mask = bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK);
+ mask |= (1 << irq);
+ bus_space_write_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK, mask);
+ } else if (irq < S3C24X0_EXTIRQ_MIN) {
+ mask = bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK);
+ mask |= (1 << (irq - S3C24X0_SUBIRQ_MIN));
+ bus_space_write_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask);
+ } else {
+ mask = bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
+ mask |= (1 << (irq - S3C24X0_EXTIRQ_MIN));
+ bus_space_write_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, GPIO_EINTMASK, mask);
+ }
+}
+
+void
+arm_unmask_irq(uintptr_t irq)
+{
+ u_int32_t mask;
+
+ if (irq >= S3C24X0_INT_EXT(0) && irq <= S3C24X0_INT_EXT(3)) {
+ /* External interrupt 0..3 are directly mapped to irq 0..3 */
+ irq -= S3C24X0_EXTIRQ_MIN;
+ }
+ if (irq < S3C24X0_SUBIRQ_MIN) {
+ mask = bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK);
+ mask &= ~(1 << irq);
+ bus_space_write_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK, mask);
+ } else if (irq < S3C24X0_EXTIRQ_MIN) {
+ mask = bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK);
+ mask &= ~(1 << (irq - S3C24X0_SUBIRQ_MIN));
+ bus_space_write_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask);
+ } else {
+ mask = bus_space_read_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
+ mask &= ~(1 << (irq - S3C24X0_EXTIRQ_MIN));
+ bus_space_write_4(s3c2xx0_bs_tag,
+ s3c2xx0_softc->sc_intctl_ioh, GPIO_EINTMASK, mask);
+ }
+}
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c24x0.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c24x0_clk.c
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c24x0_clk.c (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c24x0_clk.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,288 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c24x0_clk.c,v 1.6 2005/12/24 20:06:52 perry Exp $ */
+
+/*
+ * Copyright (c) 2003 Genetec corporation. All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of Genetec corporation may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c24x0_clk.c 272103 2014-09-25 11:38:26Z gavin $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0var.h>
+
+struct s3c24x0_timer_softc {
+ device_t dev;
+} timer_softc;
+
+static unsigned s3c24x0_timer_get_timecount(struct timecounter *tc);
+
+static struct timecounter s3c24x0_timer_timecounter = {
+ s3c24x0_timer_get_timecount, /* get_timecount */
+ NULL, /* no poll_pps */
+ ~0u, /* counter_mask */
+ 3686400, /* frequency */
+ "s3c24x0 timer", /* name */
+ 1000 /* quality */
+};
+
+static int
+s3c24x0_timer_probe(device_t dev)
+{
+
+ device_set_desc(dev, "s3c24x0 timer");
+ return (0);
+}
+
+static int
+s3c24x0_timer_attach(device_t dev)
+{
+ timer_softc.dev = dev;
+
+ /* We need to do this here for devices that expect DELAY to work */
+ return (0);
+}
+
+static device_method_t s3c24x0_timer_methods[] = {
+ DEVMETHOD(device_probe, s3c24x0_timer_probe),
+ DEVMETHOD(device_attach, s3c24x0_timer_attach),
+ {0, 0},
+};
+
+static driver_t s3c24x0_timer_driver = {
+ "timer",
+ s3c24x0_timer_methods,
+ sizeof(struct s3c24x0_timer_softc),
+};
+static devclass_t s3c24x0_timer_devclass;
+
+DRIVER_MODULE(s3c24x0timer, s3c24x0, s3c24x0_timer_driver,
+ s3c24x0_timer_devclass, 0, 0);
+
+#define TIMER_FREQUENCY(pclk) ((pclk)/16) /* divider=1/16 */
+
+static unsigned int timer4_reload_value;
+static unsigned int timer4_prescaler;
+static unsigned int timer4_mseccount;
+static volatile uint32_t s3c24x0_base;
+
+#define usec_to_counter(t) \
+ ((timer4_mseccount*(t))/1000)
+
+#define counter_to_usec(c,pclk) \
+ (((c)*timer4_prescaler*1000)/(TIMER_FREQUENCY(pclk)/1000))
+
+static inline int
+read_timer(struct s3c24x0_softc *sc)
+{
+ int count;
+
+ do {
+ count = bus_space_read_2(sc->sc_sx.sc_iot, sc->sc_timer_ioh,
+ TIMER_TCNTO(4));
+ } while ( __predict_false(count > timer4_reload_value) );
+
+ return count;
+}
+
+static unsigned
+s3c24x0_timer_get_timecount(struct timecounter *tc)
+{
+ struct s3c24x0_softc *sc = (struct s3c24x0_softc *)s3c2xx0_softc;
+ int value;
+
+ value = bus_space_read_2(sc->sc_sx.sc_iot, sc->sc_timer_ioh,
+ TIMER_TCNTO(4));
+ return (s3c24x0_base - value);
+}
+
+static int
+clock_intr(void *arg)
+{
+ struct trapframe *fp = arg;
+
+ atomic_add_32(&s3c24x0_base, timer4_reload_value);
+
+ hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp));
+ return (FILTER_HANDLED);
+}
+
+void
+cpu_initclocks(void)
+{
+ struct s3c24x0_softc *sc = (struct s3c24x0_softc *)s3c2xx0_softc;
+ long tc;
+ struct resource *irq;
+ int rid = 0;
+ void *ihl;
+ int err, prescaler;
+ int pclk = s3c2xx0_softc->sc_pclk;
+ bus_space_tag_t iot = sc->sc_sx.sc_iot;
+ bus_space_handle_t ioh = sc->sc_timer_ioh;
+ uint32_t reg;
+ device_t dev = timer_softc.dev;
+
+ /* We have already been initialized */
+ if (timer4_reload_value != 0)
+ return;
+
+#define time_constant(hz) (TIMER_FREQUENCY(pclk) /(hz)/ prescaler)
+#define calc_time_constant(hz) \
+ do { \
+ prescaler = 1; \
+ do { \
+ ++prescaler; \
+ tc = time_constant(hz); \
+ } while( tc > 65536 ); \
+ } while(0)
+
+
+ /* Use the channels 4 and 3 for hardclock and statclock, respectively */
+
+ /* stop all timers */
+ bus_space_write_4(iot, ioh, TIMER_TCON, 0);
+
+ /* calc suitable prescaler value */
+ calc_time_constant(hz);
+
+ timer4_prescaler = prescaler;
+ timer4_reload_value = TIMER_FREQUENCY(pclk) / hz / prescaler;
+ timer4_mseccount = TIMER_FREQUENCY(pclk)/timer4_prescaler/1000 ;
+
+ bus_space_write_4(iot, ioh, TIMER_TCNTB(4),
+ ((prescaler - 1) << 16) | (timer4_reload_value - 1));
+
+ printf("clock: hz=%d PCLK=%d prescaler=%d tc=%ld\n",
+ hz, pclk, prescaler, tc);
+
+ irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, S3C24X0_INT_TIMER4,
+ S3C24X0_INT_TIMER4, 1, RF_ACTIVE);
+ if (!irq)
+ panic("Unable to allocate the clock irq handler.\n");
+
+ err = bus_setup_intr(dev, irq, INTR_TYPE_CLK,
+ clock_intr, NULL, NULL, &ihl);
+ if (err != 0)
+ panic("Unable to setup the clock irq handler.\n");
+
+ /* set prescaler1 */
+ reg = bus_space_read_4(iot, ioh, TIMER_TCFG0);
+ bus_space_write_4(iot, ioh, TIMER_TCFG0,
+ (reg & ~0xff00) | ((prescaler-1) << 8));
+
+ /* divider 1/16 for ch #4 */
+ reg = bus_space_read_4(iot, ioh, TIMER_TCFG1);
+ bus_space_write_4(iot, ioh, TIMER_TCFG1,
+ (reg & ~(TCFG1_MUX_MASK(4))) |
+ (TCFG1_MUX_DIV16 << TCFG1_MUX_SHIFT(4)) );
+
+
+ /* start timers */
+ reg = bus_space_read_4(iot, ioh, TIMER_TCON);
+ reg &= ~(TCON_MASK(4));
+
+ /* load the time constant */
+ bus_space_write_4(iot, ioh, TIMER_TCON, reg | TCON_MANUALUPDATE(4));
+ /* set auto reload and start */
+ bus_space_write_4(iot, ioh, TIMER_TCON, reg |
+ TCON_AUTORELOAD(4) | TCON_START(4) );
+
+ s3c24x0_timer_timecounter.tc_frequency = TIMER_FREQUENCY(pclk) /
+ timer4_prescaler;
+ tc_init(&s3c24x0_timer_timecounter);
+}
+
+/*
+ * DELAY:
+ *
+ * Delay for at least N microseconds.
+ */
+void
+DELAY(int n)
+{
+ struct s3c24x0_softc *sc = (struct s3c24x0_softc *) s3c2xx0_softc;
+ int v0, v1, delta;
+ u_int ucnt;
+
+ if (timer4_reload_value == 0) {
+ /* not initialized yet */
+ while ( n-- > 0 ){
+ int m;
+
+ for (m = 0; m < 100; ++m )
+ ;
+ }
+ return;
+ }
+
+ /* read down counter */
+ v0 = read_timer(sc);
+
+ ucnt = usec_to_counter(n);
+
+ while( ucnt > 0 ) {
+ v1 = read_timer(sc);
+ delta = v0 - v1;
+ if ( delta < 0 )
+ delta += timer4_reload_value;
+
+ if((u_int)delta < ucnt){
+ ucnt -= (u_int)delta;
+ v0 = v1;
+ }
+ else {
+ ucnt = 0;
+ }
+ }
+}
+
+void
+cpu_startprofclock(void)
+{
+}
+
+void
+cpu_stopprofclock(void)
+{
+}
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c24x0_clk.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,405 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work.
+ *
+ * Created : 17/09/94
+ */
+
+#include "opt_ddb.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c 272103 2014-09-25 11:38:26Z gavin $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/cons.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/kdb.h>
+#include <sys/msgbuf.h>
+#include <machine/physmem.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <machine/devmap.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <sys/reboot.h>
+
+#include <arm/samsung/s3c2xx0/s3c24x0var.h>
+#include <arm/samsung/s3c2xx0/s3c2410reg.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0board.h>
+
+/* Page table for mapping proc0 zero page */
+#define KERNEL_PT_SYS 0
+#define KERNEL_PT_KERN 1
+#define KERNEL_PT_KERN_NUM 44
+/* L2 table for mapping after kernel */
+#define KERNEL_PT_AFKERNEL KERNEL_PT_KERN + KERNEL_PT_KERN_NUM
+#define KERNEL_PT_AFKERNEL_NUM 5
+
+/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
+#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
+
+extern int s3c2410_pclk;
+
+struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
+
+/* Physical and virtual addresses for some global pages */
+
+struct pv_addr systempage;
+struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+struct pv_addr kernelstack;
+
+#define _A(a) ((a) & ~L1_S_OFFSET)
+#define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
+
+/* Static device mappings. */
+static const struct arm_devmap_entry s3c24x0_devmap[] = {
+ /*
+ * Map the devices we need early on.
+ */
+ {
+ _A(S3C24X0_CLKMAN_BASE),
+ _A(S3C24X0_CLKMAN_PA_BASE),
+ _S(S3C24X0_CLKMAN_SIZE),
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ _A(S3C24X0_GPIO_BASE),
+ _A(S3C24X0_GPIO_PA_BASE),
+ _S(S3C2410_GPIO_SIZE),
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ _A(S3C24X0_INTCTL_BASE),
+ _A(S3C24X0_INTCTL_PA_BASE),
+ _S(S3C24X0_INTCTL_SIZE),
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ _A(S3C24X0_TIMER_BASE),
+ _A(S3C24X0_TIMER_PA_BASE),
+ _S(S3C24X0_TIMER_SIZE),
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ _A(S3C24X0_UART0_BASE),
+ _A(S3C24X0_UART0_PA_BASE),
+ _S(S3C24X0_UART_PA_BASE(3) - S3C24X0_UART0_PA_BASE),
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ _A(S3C24X0_WDT_BASE),
+ _A(S3C24X0_WDT_PA_BASE),
+ _S(S3C24X0_WDT_SIZE),
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ }
+};
+
+#undef _A
+#undef _S
+
+#define ioreg_read32(a) (*(volatile uint32_t *)(a))
+#define ioreg_write32(a,v) (*(volatile uint32_t *)(a)=(v))
+
+struct arm32_dma_range s3c24x0_range = {
+ .dr_sysbase = 0,
+ .dr_busbase = 0,
+ .dr_len = 0,
+};
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ if (s3c24x0_range.dr_len == 0) {
+ s3c24x0_range.dr_sysbase = dump_avail[0];
+ s3c24x0_range.dr_busbase = dump_avail[0];
+ s3c24x0_range.dr_len = dump_avail[1] - dump_avail[0];
+ }
+ return (&s3c24x0_range);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+ return (1);
+}
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+ struct pv_addr kernel_l1pt;
+ int loop;
+ u_int l1pagetable;
+ vm_offset_t freemempos;
+ vm_offset_t afterkern;
+ vm_offset_t lastaddr;
+
+ int i;
+ uint32_t memsize;
+
+ boothowto = 0; /* Likely not needed */
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+ i = 0;
+ set_cpufuncs();
+ cpufuncs.cf_sleep = s3c24x0_sleep;
+
+ pcpu0_init();
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+#define KERNEL_TEXT_BASE (KERNBASE)
+ freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK;
+ /* Define a macro to simplify memory allocation */
+#define valloc_pages(var, np) \
+ alloc_pages((var).pv_va, (np)); \
+ (var).pv_pa = (var).pv_va + (abp->abp_physaddr - KERNVIRTADDR);
+
+#define alloc_pages(var, np) \
+ (var) = freemempos; \
+ freemempos += (np * PAGE_SIZE); \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos += PAGE_SIZE;
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[loop],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ } else {
+ kernel_pt_table[loop].pv_va = freemempos -
+ (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
+ L2_TABLE_SIZE_REAL;
+ kernel_pt_table[loop].pv_pa =
+ kernel_pt_table[loop].pv_va - KERNVIRTADDR +
+ abp->abp_physaddr;
+ }
+ }
+ /*
+ * Allocate a page for the system page mapped to V0x00000000
+ * This page will just contain the system vectors and can be
+ * shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE);
+ valloc_pages(abtstack, ABT_STACK_SIZE);
+ valloc_pages(undstack, UND_STACK_SIZE);
+ valloc_pages(kernelstack, KSTACK_PAGES);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+ /*
+ * Now we start construction of the L1 page table
+ * We start by mapping the L2 page tables into the L1.
+ * This means that we can replace L1 mappings later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /* Map the L2 pages tables in the L1 page table */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH,
+ &kernel_pt_table[KERNEL_PT_SYS]);
+ for (i = 0; i < KERNEL_PT_KERN_NUM; i++)
+ pmap_link_l2pt(l1pagetable, KERNBASE + i * L1_S_SIZE,
+ &kernel_pt_table[KERNEL_PT_KERN + i]);
+ pmap_map_chunk(l1pagetable, KERNBASE, PHYSADDR,
+ (((uint32_t)(lastaddr) - KERNBASE) + PAGE_SIZE) & ~(PAGE_SIZE - 1),
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ afterkern = round_page((lastaddr + L1_S_SIZE) & ~(L1_S_SIZE
+ - 1));
+ for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
+ pmap_link_l2pt(l1pagetable, afterkern + i * L1_S_SIZE,
+ &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
+ }
+
+ /* Map the vector page. */
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ /* Map the stack pages */
+ pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa,
+ IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa,
+ ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa,
+ UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa,
+ KSTACK_PAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
+ L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ pmap_map_chunk(l1pagetable, msgbufpv.pv_va, msgbufpv.pv_pa,
+ msgbufsize, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va,
+ kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ }
+
+ arm_devmap_bootstrap(l1pagetable, s3c24x0_devmap);
+
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
+
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+
+ cpu_control(CPU_CONTROL_MMU_ENABLE, CPU_CONTROL_MMU_ENABLE);
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+ cpu_setup("");
+
+ /* Disable all peripheral interrupts */
+ ioreg_write32(S3C24X0_INTCTL_BASE + INTCTL_INTMSK, ~0);
+ memsize = board_init();
+ /* Find pclk for uart */
+ switch(ioreg_read32(S3C24X0_GPIO_BASE + GPIO_GSTATUS1) >> 16) {
+ case 0x3241:
+ s3c2410_clock_freq2(S3C24X0_CLKMAN_BASE, NULL, NULL,
+ &s3c2410_pclk);
+ break;
+ case 0x3244:
+ s3c2440_clock_freq2(S3C24X0_CLKMAN_BASE, NULL, NULL,
+ &s3c2410_pclk);
+ break;
+ }
+ cninit();
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+
+ pmap_curmaxkvaddr = afterkern + 0x100000 * (KERNEL_PT_KERN_NUM - 1);
+ vm_max_kernel_address = KERNVIRTADDR + 3 * memsize;
+ pmap_bootstrap(freemempos, &kernel_l1pt);
+ msgbufp = (void*)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+
+ /*
+ * Add the physical ram we have available.
+ *
+ * Exclude the kernel, and all the things we allocated which immediately
+ * follow the kernel, from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ arm_physmem_hardware_region(PHYSADDR, memsize);
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+}
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,163 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (C) 2010 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c 272103 2014-09-25 11:38:26Z gavin $");
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/time.h>
+#include <sys/clock.h>
+#include <sys/resource.h>
+#include <sys/systm.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
+
+#include "clock_if.h"
+
+#define YEAR_BASE 2000
+
+struct s3c2xx0_rtc_softc {
+ struct resource *mem_res;
+};
+
+static int
+s3c2xx0_rtc_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Samsung Integrated RTC");
+ return (0);
+}
+
+static int
+s3c2xx0_rtc_attach(device_t dev)
+{
+ struct s3c2xx0_rtc_softc *sc;
+ int error, rid;
+
+ sc = device_get_softc(dev);
+ error = 0;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ bus_write_1(sc->mem_res, RTC_RTCCON, RTCCON_RTCEN);
+ clock_register(dev, 1000000);
+
+out:
+ return (error);
+}
+
+static int
+s3c2xx0_rtc_gettime(device_t dev, struct timespec *ts)
+{
+ struct s3c2xx0_rtc_softc *sc;
+ struct clocktime ct;
+
+#define READ_TIME() do { \
+ ct.year = YEAR_BASE + FROMBCD(bus_read_1(sc->mem_res, RTC_BCDYEAR)); \
+ ct.mon = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDMON)); \
+ ct.dow = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDDAY)); \
+ ct.day = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDDATE)); \
+ ct.hour = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDHOUR)); \
+ ct.min = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDMIN)); \
+ ct.sec = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDSEC)); \
+} while (0)
+
+ sc = device_get_softc(dev);
+
+ ct.nsec = 0;
+ READ_TIME();
+ /*
+ * Check if we could have read incorrect values
+ * as the values could have changed.
+ */
+ if (ct.sec == 0) {
+ READ_TIME();
+ }
+
+ ct.dow = -1;
+
+#undef READ_TIME
+ return (clock_ct_to_ts(&ct, ts));
+}
+
+static int
+s3c2xx0_rtc_settime(device_t dev, struct timespec *ts)
+{
+ struct s3c2xx0_rtc_softc *sc;
+ struct clocktime ct;
+
+ sc = device_get_softc(dev);
+
+ /* Resolution: 1 sec */
+ if (ts->tv_nsec >= 500000000)
+ ts->tv_sec++;
+ ts->tv_nsec = 0;
+ clock_ts_to_ct(ts, &ct);
+
+ bus_write_1(sc->mem_res, RTC_BCDSEC, TOBCD(ct.sec));
+ bus_write_1(sc->mem_res, RTC_BCDMIN, TOBCD(ct.min));
+ bus_write_1(sc->mem_res, RTC_BCDHOUR, TOBCD(ct.hour));
+ bus_write_1(sc->mem_res, RTC_BCDDATE, TOBCD(ct.day));
+ bus_write_1(sc->mem_res, RTC_BCDDAY, TOBCD(ct.dow));
+ bus_write_1(sc->mem_res, RTC_BCDMON, TOBCD(ct.mon));
+ bus_write_1(sc->mem_res, RTC_BCDYEAR, TOBCD(ct.year - YEAR_BASE));
+
+ return (0);
+}
+
+static device_method_t s3c2xx0_rtc_methods[] = {
+ DEVMETHOD(device_probe, s3c2xx0_rtc_probe),
+ DEVMETHOD(device_attach, s3c2xx0_rtc_attach),
+
+ DEVMETHOD(clock_gettime, s3c2xx0_rtc_gettime),
+ DEVMETHOD(clock_settime, s3c2xx0_rtc_settime),
+
+ { 0, 0 },
+};
+
+static driver_t s3c2xx0_rtc_driver = {
+ "rtc",
+ s3c2xx0_rtc_methods,
+ sizeof(struct s3c2xx0_rtc_softc),
+};
+static devclass_t s3c2xx0_rtc_devclass;
+
+DRIVER_MODULE(s3c2xx0_rtc, s3c24x0, s3c2xx0_rtc_driver, s3c2xx0_rtc_devclass,
+ 0, 0);
+
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c24x0reg.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c24x0reg.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c24x0reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,719 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c24x0reg.h,v 1.7 2004/02/12 03:52:46 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2003 Genetec corporation All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of Genetec corporation may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c24x0reg.h 272103 2014-09-25 11:38:26Z gavin $
+ */
+
+
+/*
+ * Samsung S3C2410X/2400 processor is ARM920T based integrated CPU
+ *
+ * Reference:
+ * S3C2410X User's Manual
+ * S3C2400 User's Manual
+ */
+#ifndef _ARM_S3C2XX0_S3C24X0REG_H_
+#define _ARM_S3C2XX0_S3C24X0REG_H_
+
+/* common definitions for S3C2800, S3C2410 and S3C2440 */
+#include <arm/samsung/s3c2xx0/s3c2xx0reg.h>
+
+/*
+ * Map the device registers into kernel space.
+ *
+ * As most devices use less than 1 page of memory reduce
+ * the distance between allocations by right shifting
+ * S3C24X0_DEV_SHIFT bits. Because the UART takes 3*0x4000
+ * bytes the upper limit on S3C24X0_DEV_SHIFT is 4.
+ * TODO: Fix the UART code so we can increase this value.
+ */
+#define S3C24X0_DEV_START 0x48000000
+#define S3C24X0_DEV_STOP 0x60000000
+#define S3C24X0_DEV_VA_OFFSET 0xD8000000
+#define S3C24X0_DEV_SHIFT 4
+#define S3C24X0_DEV_PA_SIZE (S3C24X0_DEV_STOP - S3C24X0_DEV_START)
+#define S3C24X0_DEV_VA_SIZE (S3C24X0_DEV_PA_SIZE >> S3C24X0_DEV_SHIFT)
+#define S3C24X0_DEV_PA_TO_VA(x) ((x >> S3C24X0_DEV_SHIFT) - S3C24X0_DEV_START + S3C24X0_DEV_VA_OFFSET)
+
+/*
+ * Physical address of integrated peripherals
+ */
+#define S3C24X0_MEMCTL_PA_BASE 0x48000000 /* memory controller */
+#define S3C24X0_MEMCTL_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_MEMCTL_PA_BASE)
+#define S3C24X0_USBHC_PA_BASE 0x49000000 /* USB Host controller */
+#define S3C24X0_USBHC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_USBHC_PA_BASE)
+#define S3C24X0_INTCTL_PA_BASE 0x4a000000 /* Interrupt controller */
+#define S3C24X0_INTCTL_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_INTCTL_PA_BASE)
+#define S3C24X0_INTCTL_SIZE 0x20
+#define S3C24X0_DMAC_PA_BASE 0x4b000000
+#define S3C24X0_DMAC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_DMAC_PA_BASE)
+#define S3C24X0_DMAC_SIZE 0xe4
+#define S3C24X0_CLKMAN_PA_BASE 0x4c000000 /* clock & power management */
+#define S3C24X0_CLKMAN_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_CLKMAN_PA_BASE)
+#define S3C24X0_LCDC_PA_BASE 0x4d000000 /* LCD controller */
+#define S3C24X0_LCDC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_LCDC_PA_BASE)
+#define S3C24X0_LCDC_SIZE 0x64
+#define S3C24X0_NANDFC_PA_BASE 0x4e000000 /* NAND Flash controller */
+#define S3C24X0_NANDFC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_NANDFC_PA_BASE)
+#define S3C24X0_UART0_PA_BASE 0x50000000
+#define S3C24X0_UART0_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_UART0_PA_BASE)
+#define S3C24X0_UART_PA_BASE(n) (S3C24X0_UART0_PA_BASE+0x4000*(n))
+#define S3C24X0_UART_BASE(n) (S3C24X0_UART0_BASE+0x4000*(n))
+#define S3C24X0_TIMER_PA_BASE 0x51000000
+#define S3C24X0_TIMER_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_TIMER_PA_BASE)
+#define S3C24X0_USBDC_PA_BASE 0x5200140
+#define S3C24X0_USBDC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_USBDC_PA_BASE)
+#define S3C24X0_USBDC_SIZE 0x130
+#define S3C24X0_WDT_PA_BASE 0x53000000
+#define S3C24X0_WDT_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_WDT_PA_BASE)
+#define S3C24X0_IIC_PA_BASE 0x54000000
+#define S3C24X0_IIC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_IIC_PA_BASE)
+#define S3C24X0_IIS_PA_BASE 0x55000000
+#define S3C24X0_IIS_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_IIS_PA_BASE)
+#define S3C24X0_GPIO_PA_BASE 0x56000000
+#define S3C24X0_GPIO_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_GPIO_PA_BASE)
+#define S3C24X0_RTC_PA_BASE 0x57000000
+#define S3C24X0_RTC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_RTC_PA_BASE)
+#define S3C24X0_RTC_SIZE 0x8C
+#define S3C24X0_ADC_PA_BASE 0x58000000
+#define S3C24X0_ADC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_ADC_PA_BASE)
+#define S3C24X0_SPI0_PA_BASE 0x59000000
+#define S3C24X0_SPI0_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_SPI0_PA_BASE)
+#define S3C24X0_SPI1_PA_BASE 0x59000020
+#define S3C24X0_SPI1_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_SPI1_PA_BASE)
+#define S3C24X0_SDI_PA_BASE 0x5a000000 /* SD Interface */
+#define S3C24X0_SDI_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_SDI_PA_BASE)
+
+#define S3C24X0_REG_BASE 0x48000000
+#define S3C24X0_REG_SIZE 0x13000000
+
+/* Memory controller */
+#define MEMCTL_BWSCON 0x00 /* Bus width and wait status */
+#define BWSCON_DW0_SHIFT 1 /* bank0 is odd */
+#define BWSCON_BANK_SHIFT(n) (4*(n)) /* for bank 1..7 */
+#define BWSCON_DW_MASK 0x03
+#define BWSCON_DW_8 0
+#define BWSCON_DW_16 1
+#define BWSCON_DW_32 2
+#define BWSCON_WS 0x04 /* WAIT enable for the bank */
+#define BWSCON_ST 0x08 /* SRAM use UB/LB for the bank */
+
+#define MEMCTL_BANKCON0 0x04 /* Boot ROM control */
+#define MEMCTL_BANKCON(n) (0x04+4*(n)) /* BANKn control */
+#define BANKCON_MT_SHIFT 15
+#define BANKCON_MT_ROM (0<<BANKCON_MT_SHIFT)
+#define BANKCON_MT_DRAM (3<<BANKCON_MT_SHIFT)
+#define BANKCON_TACS_SHIFT 13 /* address set-up time to nGCS */
+#define BANKCON_TCOS_SHIFT 11 /* CS set-up to nOE */
+#define BANKCON_TACC_SHIFT 8 /* CS set-up to nOE */
+#define BANKCON_TOCH_SHIFT 6 /* CS hold time from OE */
+#define BANKCON_TCAH_SHIFT 4 /* address hold time from OE */
+#define BANKCON_TACP_SHIFT 2 /* page mode access cycle */
+#define BANKCON_TACP_2 (0<<BANKCON_TACP_SHIFT)
+#define BANKCON_TACP_3 (1<<BANKCON_TACP_SHIFT)
+#define BANKCON_TACP_4 (2<<BANKCON_TACP_SHIFT)
+#define BANKCON_TACP_6 (3<<BANKCON_TACP_SHIFT)
+#define BANKCON_PMC_4 (1<<0)
+#define BANKCON_PMC_8 (2<<0)
+#define BANKCON_PMC_16 (3<<0)
+#define BANKCON_TRCD_SHIFT 2 /* RAS to CAS delay */
+#define BANKCON_TRCD_2 (0<<2)
+#define BANKCON_TRCD_3 (1<<2)
+#define BANKCON_TRCD_4 (2<<2)
+#define BANKCON_SCAN_8 (0<<0) /* Column address number */
+#define BANKCON_SCAN_9 (1<<0)
+#define BANKCON_SCAN_10 (2<<0)
+#define MEMCTL_REFRESH 0x24 /* DRAM?SDRAM Refresh */
+#define REFRESH_REFEN (1<<23)
+#define REFRESH_TREFMD (1<<22) /* 1=self refresh */
+#define REFRESH_TRP_2 (0<<20)
+#define REFRESH_TRP_3 (1<<20)
+#define REFRESH_TRP_4 (2<<20)
+#define REFRESH_TRC_4 (0<<18)
+#define REFRESH_TRC_5 (1<<18)
+#define REFRESH_TRC_6 (2<<18)
+#define REFRESH_TRC_7 (3<<18)
+#define REFRESH_COUNTER_MASK 0x3ff
+#define MEMCTL_BANKSIZE 0x28 /* Flexible Bank size */
+#define MEMCTL_MRSRB6 0x2c /* SDRAM Mode register */
+#define MEMCTL_MRSRB7 0x30
+#define MRSR_CL_SHIFT 4 /* CAS Latency */
+
+#define S3C24X0_MEMCTL_SIZE 0x34
+
+/* USB Host controller */
+#define S3C24X0_USBHC_SIZE 0x5c
+
+/* Interrupt controller */
+#define INTCTL_PRIORITY 0x0c /* IRQ Priority control */
+#define INTCTL_INTPND 0x10 /* Interrupt request status */
+#define INTCTL_INTOFFSET 0x14 /* Interrupt request source */
+#define INTCTL_SUBSRCPND 0x18 /* sub source pending */
+#define INTCTL_INTSUBMSK 0x1c /* sub mask */
+
+/* Interrupt source */
+#define S3C24X0_INT_ADCTC 31 /* ADC (and TC for 2410) */
+#define S3C24X0_INT_RTC 30 /* RTC alarm */
+#define S3C24X0_INT_SPI1 29 /* SPI 1 */
+#define S3C24X0_INT_UART0 28 /* UART0 */
+#define S3C24X0_INT_IIC 27
+#define S3C24X0_INT_USBH 26 /* USB Host */
+#define S3C24X0_INT_USBD 25 /* USB Device */
+#define S3C24X0_INT_UART1 23 /* UART0 (2410 only) */
+#define S3C24X0_INT_SPI0 22 /* SPI 0 */
+#define S3C24X0_INT_SDI 21
+#define S3C24X0_INT_DMA3 20
+#define S3C24X0_INT_DMA2 19
+#define S3C24X0_INT_DMA1 18
+#define S3C24X0_INT_DMA0 17
+#define S3C24X0_INT_LCD 16
+
+#define S3C24X0_INT_UART2 15 /* UART2 int (2410) */
+#define S3C24X0_INT_TIMER4 14
+#define S3C24X0_INT_TIMER3 13
+#define S3C24X0_INT_TIMER2 12
+#define S3C24X0_INT_TIMER1 11
+#define S3C24X0_INT_TIMER0 10
+#define S3C24X0_INT_TIMER(n) (10+(n)) /* timer interrupt [4:0] */
+#define S3C24X0_INT_WDT 9 /* Watch dog timer */
+#define S3C24X0_INT_TICK 8
+#define S3C24X0_INT_BFLT 7 /* Battery fault */
+#define S3C24X0_INT_8_23 5 /* Ext int 8..23 */
+#define S3C24X0_INT_4_7 4 /* Ext int 4..7 */
+#define S3C24X0_INT_3 3
+#define S3C24X0_INT_2 2
+#define S3C24X0_INT_1 1
+#define S3C24X0_INT_0 0
+
+/* 24{1,4}0 has more than 32 interrupt sources. These are sub-sources
+ * that are OR-ed into main interrupt sources, and controlled via
+ * SUBSRCPND and SUBSRCMSK registers */
+#define S3C24X0_SUBIRQ_MIN 32
+
+/* cascaded to INT_ADCTC */
+#define S3C24X0_INT_ADC (S3C24X0_SUBIRQ_MIN+10) /* AD converter */
+#define S3C24X0_INT_TC (S3C24X0_SUBIRQ_MIN+9) /* Touch screen */
+/* cascaded to INT_UART2 */
+#define S3C24X0_INT_ERR2 (S3C24X0_SUBIRQ_MIN+8) /* UART2 Error */
+#define S3C24X0_INT_TXD2 (S3C24X0_SUBIRQ_MIN+7) /* UART2 Tx */
+#define S3C24X0_INT_RXD2 (S3C24X0_SUBIRQ_MIN+6) /* UART2 Rx */
+/* cascaded to INT_UART1 */
+#define S3C24X0_INT_ERR1 (S3C24X0_SUBIRQ_MIN+5) /* UART1 Error */
+#define S3C24X0_INT_TXD1 (S3C24X0_SUBIRQ_MIN+4) /* UART1 Tx */
+#define S3C24X0_INT_RXD1 (S3C24X0_SUBIRQ_MIN+3) /* UART1 Rx */
+/* cascaded to INT_UART0 */
+#define S3C24X0_INT_ERR0 (S3C24X0_SUBIRQ_MIN+2) /* UART0 Error */
+#define S3C24X0_INT_TXD0 (S3C24X0_SUBIRQ_MIN+1) /* UART0 Tx */
+#define S3C24X0_INT_RXD0 (S3C24X0_SUBIRQ_MIN+0) /* UART0 Rx */
+
+/*
+ * Support for external interrupts. We use values from 48
+ * to allow new CPU's to allocate new subirq's.
+ */
+#define S3C24X0_EXTIRQ_MIN 48
+#define S3C24X0_EXTIRQ_COUNT 24
+#define S3C24X0_EXTIRQ_MAX (S3C24X0_EXTIRQ_MIN + S3C24X0_EXTIRQ_COUNT - 1)
+#define S3C24X0_INT_EXT(n) (S3C24X0_EXTIRQ_MIN + (n))
+
+/* DMA controller */
+/* XXX */
+
+/* Clock & power manager */
+#define CLKMAN_LOCKTIME 0x00 /* PLL lock time */
+#define CLKMAN_MPLLCON 0x04 /* MPLL control */
+#define CLKMAN_UPLLCON 0x08 /* UPLL control */
+#define PLLCON_MDIV_SHIFT 12
+#define PLLCON_MDIV_MASK (0xff<<PLLCON_MDIV_SHIFT)
+#define PLLCON_PDIV_SHIFT 4
+#define PLLCON_PDIV_MASK (0x3f<<PLLCON_PDIV_SHIFT)
+#define PLLCON_SDIV_SHIFT 0
+#define PLLCON_SDIV_MASK (0x03<<PLLCON_SDIV_SHIFT)
+#define CLKMAN_CLKCON 0x0c
+#define CLKCON_SPI (1<<18)
+#define CLKCON_IIS (1<<17)
+#define CLKCON_IIC (1<<16)
+#define CLKCON_ADC (1<<15)
+#define CLKCON_RTC (1<<14)
+#define CLKCON_GPIO (1<<13)
+#define CLKCON_UART2 (1<<12)
+#define CLKCON_UART1 (1<<11)
+#define CLKCON_UART0 (1<<10) /* PCLK to UART0 */
+#define CLKCON_SDI (1<<9)
+#define CLKCON_TIMER (1<<8) /* PCLK to TIMER */
+#define CLKCON_USBD (1<<7) /* PCLK to USB device controller */
+#define CLKCON_USBH (1<<6) /* PCLK to USB host controller */
+#define CLKCON_LCDC (1<<5) /* PCLK to LCD controller */
+#define CLKCON_NANDFC (1<<4) /* PCLK to NAND Flash controller */
+#define CLKCON_IDLE (1<<2) /* 1=transition to IDLE mode */
+#define CLKMAN_CLKSLOW 0x10
+#define CLKMAN_CLKDIVN 0x14
+#define CLKDIVN_PDIVN (1<<0) /* pclk=hclk/2 */
+
+#define CLKMAN_CLKSLOW 0x10 /* slow clock controll */
+#define CLKSLOW_UCLK (1<<7) /* 1=UPLL off */
+#define CLKSLOW_MPLL (1<<5) /* 1=PLL off */
+#define CLKSLOW_SLOW (1<<4) /* 1: Enable SLOW mode */
+#define CLKSLOW_VAL_MASK 0x0f /* divider value for slow clock */
+
+#define CLKMAN_CLKDIVN 0x14 /* Software reset control */
+#define CLKDIVN_PDIVN (1<<0)
+
+#define S3C24X0_CLKMAN_SIZE 0x18
+
+/* LCD controller */
+#define LCDC_LCDCON1 0x00 /* control 1 */
+#define LCDCON1_ENVID (1<<0) /* enable video */
+#define LCDCON1_BPPMODE_SHIFT 1
+#define LCDCON1_BPPMODE_MASK (0x0f<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_STN1 (0x0<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_STN2 (0x1<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_STN4 (0x2<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_STN8 (0x3<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_STN12 (0x4<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_TFT1 (0x8<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_TFT2 (0x9<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_TFT4 (0xa<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_TFT8 (0xb<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_TFT16 (0xc<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_TFT24 (0xd<<LCDCON1_BPPMODE_SHIFT)
+#define LCDCON1_BPPMODE_TFTX (0x8<<LCDCON1_BPPMODE_SHIFT)
+
+#define LCDCON1_PNRMODE_SHIFT 5
+#define LCDCON1_PNRMODE_MASK (0x3<<LCDCON1_PNRMODE_SHIFT)
+#define LCDCON1_PNRMODE_DUALSTN4 (0x0<<LCDCON1_PNRMODE_SHIFT)
+#define LCDCON1_PNRMODE_SINGLESTN4 (0x1<<LCDCON1_PNRMODE_SHIFT)
+#define LCDCON1_PNRMODE_SINGLESTN8 (0x2<<LCDCON1_PNRMODE_SHIFT)
+#define LCDCON1_PNRMODE_TFT (0x3<<LCDCON1_PNRMODE_SHIFT)
+
+#define LCDCON1_MMODE (1<<7) /* VM toggle rate */
+#define LCDCON1_CLKVAL_SHIFT 8
+#define LCDCON1_CLKVAL_MASK (0x3ff<<LCDCON1_CLKVAL_SHIFT)
+#define LCDCON1_LINCNT_SHIFT 18
+#define LCDCON1_LINCNT_MASK (0x3ff<<LCDCON1_LINCNT_SHIFT)
+
+#define LCDC_LCDCON2 0x04 /* control 2 */
+#define LCDCON2_VPSW_SHIFT 0 /* TFT Vsync pulse width */
+#define LCDCON2_VPSW_MASK (0x3f<<LCDCON2_VPSW_SHIFT)
+#define LCDCON2_VFPD_SHIFT 6 /* TFT V front porch */
+#define LCDCON2_VFPD_MASK (0xff<<LCDCON2_VFPD_SHIFT)
+#define LCDCON2_LINEVAL_SHIFT 14 /* Vertical size */
+#define LCDCON2_LINEVAL_MASK (0x3ff<<LCDCON2_LINEVAL_SHIFT)
+#define LCDCON2_VBPD_SHIFT 24 /* TFT V back porch */
+#define LCDCON2_VBPD_MASK (0xff<<LCDCON2_VBPD_SHIFT)
+
+#define LCDC_LCDCON3 0x08 /* control 2 */
+#define LCDCON3_HFPD_SHIFT 0 /* TFT H front porch */
+#define LCDCON3_HFPD_MASK (0xff<<LCDCON3_VPFD_SHIFT)
+#define LCDCON3_LINEBLANK_SHIFT 0 /* STN H blank time */
+#define LCDCON3_LINEBLANK_MASK (0xff<<LCDCON3_LINEBLANK_SHIFT)
+#define LCDCON3_HOZVAL_SHIFT 8 /* Horizontal size */
+#define LCDCON3_HOZVAL_MASK (0x7ff<<LCDCON3_HOZVAL_SHIFT)
+#define LCDCON3_HBPD_SHIFT 19 /* TFT H back porch */
+#define LCDCON3_HBPD_MASK (0x7f<<LCDCON3_HPBD_SHIFT)
+#define LCDCON3_WDLY_SHIFT 19 /* STN vline delay */
+#define LCDCON3_WDLY_MASK (0x03<<LCDCON3_WDLY_SHIFT)
+#define LCDCON3_WDLY_16 (0x00<<LCDCON3_WDLY_SHIFT)
+#define LCDCON3_WDLY_32 (0x01<<LCDCON3_WDLY_SHIFT)
+#define LCDCON3_WDLY_64 (0x02<<LCDCON3_WDLY_SHIFT)
+#define LCDCON3_WDLY_128 (0x03<<LCDCON3_WDLY_SHIFT)
+
+#define LCDC_LCDCON4 0x0c /* control 4 */
+#define LCDCON4_HPSW_SHIFT 0 /* TFT Hsync pulse width */
+#define LCDCON4_HPSW_MASK (0xff<<LCDCON4_HPSW_SHIFT)
+#define LCDCON4_WLH_SHIFT 0 /* STN VLINE high width */
+#define LCDCON4_WLH_MASK (0x03<<LCDCON4_WLH_SHIFT)
+#define LCDCON4_WLH_16 (0x00<<LCDCON4_WLH_SHIFT)
+#define LCDCON4_WLH_32 (0x01<<LCDCON4_WLH_SHIFT)
+#define LCDCON4_WLH_64 (0x02<<LCDCON4_WLH_SHIFT)
+#define LCDCON4_WLH_128 (0x03<<LCDCON4_WLH_SHIFT)
+
+#define LCDCON4_MVAL_SHIFT 8 /* STN VM toggle rate */
+#define LCDCON4_MVAL_MASK (0xff<<LCDCON4_MVAL_SHIFT)
+
+#define LCDC_LCDCON5 0x10 /* control 5 */
+#define LCDCON5_HWSWP (1<<0) /* half-word swap */
+#define LCDCON5_BSWP (1<<1) /* byte swap */
+#define LCDCON5_ENLEND (1<<2) /* TFT: enable LEND signal */
+#define LCDCON5_PWREN (1<<3) /* enable PWREN signale */
+#define LCDCON5_INVLEND (1<<4) /* TFT: LEND signal polarity */
+#define LCDCON5_INVPWREN (1<<5) /* PWREN signal polarity */
+#define LCDCON5_INVVDEN (1<<6) /* VDEN signal polarity */
+#define LCDCON5_INVVD (1<<7) /* video data signal polarity */
+#define LCDCON5_INVVFRAME (1<<8) /* VFRAME/VSYNC signal polarity */
+#define LCDCON5_INVVLINE (1<<9) /* VLINE/HSYNC signal polarity */
+#define LCDCON5_INVVCLK (1<<10) /* VCLK signal polarity */
+#define LCDCON5_INVVCLK_RISING LCDCON5_INVVCLK
+#define LCDCON5_INVVCLK_FALLING 0
+#define LCDCON5_FRM565 (1<<11) /* RGB:565 format*/
+#define LCDCON5_FRM555I 0 /* RGBI:5551 format */
+#define LCDCON5_BPP24BL (1<<12) /* bit order for bpp24 */
+
+#define LCDCON5_HSTATUS_SHIFT 17 /* TFT: horizontal status */
+#define LCDCON5_HSTATUS_MASK (0x03<<LCDCON5_HSTATUS_SHIFT)
+#define LCDCON5_HSTATUS_HSYNC (0x00<<LCDCON5_HSTATUS_SHIFT)
+#define LCDCON5_HSTATUS_BACKP (0x01<<LCDCON5_HSTATUS_SHIFT)
+#define LCDCON5_HSTATUS_ACTIVE (0x02<<LCDCON5_HSTATUS_SHIFT)
+#define LCDCON5_HSTATUS_FRONTP (0x03<<LCDCON5_HSTATUS_SHIFT)
+
+#define LCDCON5_VSTATUS_SHIFT 19 /* TFT: vertical status */
+#define LCDCON5_VSTATUS_MASK (0x03<<LCDCON5_VSTATUS_SHIFT)
+#define LCDCON5_VSTATUS_HSYNC (0x00<<LCDCON5_VSTATUS_SHIFT)
+#define LCDCON5_VSTATUS_BACKP (0x01<<LCDCON5_VSTATUS_SHIFT)
+#define LCDCON5_VSTATUS_ACTIVE (0x02<<LCDCON5_VSTATUS_SHIFT)
+#define LCDCON5_VSTATUS_FRONTP (0x03<<LCDCON5_VSTATUS_SHIFT)
+
+#define LCDC_LCDSADDR1 0x14 /* frame buffer start address */
+#define LCDC_LCDSADDR2 0x18
+#define LCDC_LCDSADDR3 0x1c
+#define LCDSADDR3_OFFSIZE_SHIFT 11
+#define LCDSADDR3_PAGEWIDTH_SHIFT 0
+
+#define LCDC_REDLUT 0x20 /* STN: red lookup table */
+#define LCDC_GREENLUT 0x24 /* STN: green lookup table */
+#define LCDC_BLUELUT 0x28 /* STN: blue lookup table */
+#define LCDC_DITHMODE 0x4c /* STN: dithering mode */
+
+#define LCDC_TPAL 0x50 /* TFT: temporary palette */
+#define TPAL_TPALEN (1<<24)
+#define TPAL_RED_SHIFT 16
+#define TPAL_GREEN_SHIFT 8
+#define TPAL_BLUE_SHIFT 0
+
+#define LCDC_LCDINTPND 0x54
+#define LCDC_LCDSRCPND 0x58
+#define LCDC_LCDINTMSK 0x5c
+#define LCDINT_FICNT (1<<0) /* FIFO trigger interrupt pending */
+#define LCDINT_FRSYN (1<<1) /* frame sync interrupt pending */
+#define LCDINT_FIWSEL (1<<2) /* FIFO trigger level: 1=8 words, 0=4 words*/
+
+#define LCDC_LPCSEL 0x60 /* LPC3600 mode */
+#define LPCSEL_LPC_EN (1<<0) /* enable LPC3600 mode */
+#define LPCSEL_RES_SEL (1<<1) /* 1=240x320 0=320x240 */
+#define LPCSEL_MODE_SEL (1<<2)
+#define LPCSEL_CPV_SEL (1<<3)
+
+
+#define LCDC_PALETTE 0x0400
+#define LCDC_PALETTE_SIZE 0x0400
+
+/* NAND Flash controller */
+#define NANDFC_NFCONF 0x00 /* Configuration */
+/* NANDFC_NFSTAT */
+#define NFSTAT_READY (1<<0) /* NAND flash memory ready/busy status */
+
+
+/* MMC/SD */
+#define SDI_CON 0x00
+#define CON_BYTEORDER (1<<4)
+#define CON_SDIO_INTR (1<<3)
+#define CON_READWAIT_EN (1<<2)
+#define CON_CLOCK_EN (1<<0)
+#define SDI_PRE 0x04
+#define SDI_CARG 0x08
+#define SDI_CCON 0x0c
+#define CCON_ABORDCMD (1<<12) /* Abort SDIO CMD12/52 */
+#define CCON_WITHDATA (1<<11) /* CMD with data */
+#define CCON_LONGRSP (1<<10) /* 136 bit response */
+#define CCON_WAITRSP (1<<9) /* Host waits for response */
+#define CCON_CMD_START (1<<8)
+#define CCON_CMDINDEX_MASK (0x7F) /* Command number index */
+#define SDI_CSTA 0x10
+#define CSTA_RSPCRCFAIL (1<<12)
+#define CSTA_CMDSENT (1<<11)
+#define CSTA_CMDTOUT (1<<10)
+#define CSTA_RSPFIN (1<<9)
+/* All the bits to be cleared */
+#define CSTA_ALL_CLEAR (CSTA_RSPCRCFAIL | CSTA_CMDSENT | \
+ CSTA_CMDTOUT | CSTA_RSPFIN)
+#define CSTA_ERROR (CSTA_RSPCRCFAIL | CSTA_CMDTOUT)
+#define CSTA_CMDON (1<<8)
+#define SDI_RSP0 0x14
+#define SDI_RSP1 0x18
+#define SDI_RSP2 0x1c
+#define SDI_RSP3 0x20
+#define SDI_DTIMER 0x24
+#define SDI_BSIZE 0x28
+#define SDI_DCON 0x2c
+#define DCON_PRDTYPE (1<<21)
+#define DCON_TARSP (1<<20) /* Transmit after response */
+#define DCON_RACMD (1<<19) /* Receive after command */
+#define DCON_BACMD (1<<18) /* Busy after command */
+#define DCON_BLKMODE (1<<17) /* Stream/Block mode */
+#define DCON_WIDEBUS (1<<16) /* Standard/Wide bus */
+#define DCON_ENDMA (1<<15) /* DMA Enable */
+/* Determine the direction of the data transfer */
+#define DCON_DATA_READY (0<<12) /* No transfer */
+#define DCON_ONLYBUST (1<<12) /* Check if busy */
+#define DCON_DATA_RECEIVE (2<<12) /* Receive data from SD */
+#define DCON_DATA_TRANSMIT (3<<12) /* Send data to SD */
+#define DCON_BLKNUM_MASK (0x7FF) /* Block number */
+#define SDI_DCNT 0x30
+#define SDI_DSTA 0x34
+#define SDI_FSTA 0x38
+#define FSTA_TX_AVAIL (1<<13)
+#define FSTA_RX_AVAIL (1<<12)
+#define FSTA_TX_FIFO_HALF_FULL (1<<11)
+#define FSTA_TX_FIFO_EMPTY (1<<10)
+#define FSTA_RX_FIFO_LAST_DATA (1<<9)
+#define FSTA_RX_FIFO_FULL (1<<8)
+#define FSTA_RX_FIFO_HALF_FULL (1<<7)
+#define FSTA_FIFO_COUNT_MSK (0x7F)
+
+/* Timer */
+#define TIMER_TCFG0 0x00 /* Timer configuration */
+#define TIMER_TCFG1 0x04
+#define TCFG1_MUX_SHIFT(n) (4*(n))
+#define TCFG1_MUX_MASK(n) (0x0f << TCFG1_MUX_SHIFT(n))
+#define TCFG1_MUX_DIV2 0
+#define TCFG1_MUX_DIV4 1
+#define TCFG1_MUX_DIV8 2
+#define TCFG1_MUX_DIV16 3
+#define TCFG1_MUX_EXT 4
+#define TIMER_TCON 0x08 /* control */
+#define TCON_SHIFT(n) (4 * ((n)==0 ? 0 : (n)+1))
+#define TCON_START(n) (1 << TCON_SHIFT(n))
+#define TCON_MANUALUPDATE(n) (1 << (TCON_SHIFT(n) + 1))
+#define TCON_INVERTER(n) (1 << (TCON_SHIFT(n) + 2))
+#define __TCON_AUTORELOAD(n) (1 << (TCON_SHIFT(n) + 3)) /* n=0..3 */
+#define TCON_AUTORELOAD4 (1<<22) /* stupid hardware design */
+#define TCON_AUTORELOAD(n) \
+ ((n)==4 ? TCON_AUTORELOAD4 : __TCON_AUTORELOAD(n))
+#define TCON_MASK(n) (0x0f << TCON_SHIFT(n))
+#define TIMER_TCNTB(n) (0x0c+0x0c*(n)) /* count buffer */
+#define TIMER_TCMPB(n) (0x10+0x0c*(n)) /* compare buffer */
+#define __TIMER_TCNTO(n) (0x14+0x0c*(n)) /* count observation */
+#define TIMER_TCNTO4 0x40
+#define TIMER_TCNTO(n) ((n)==4 ? TIMER_TCNTO4 : __TIMER_TCNTO(n))
+
+#define S3C24X0_TIMER_SIZE 0x44
+
+/* UART */
+/* diffs to s3c2800 */
+/* SSCOM_UMCON */
+#define UMCON_AFC (1<<4) /* auto flow control */
+/* SSCOM_UMSTAT */
+#define UMSTAT_DCTS (1<<2) /* CTS change */
+/* SSCOM_UMSTAT */
+#define ULCON_IR (1<<6)
+#define ULCON_PARITY_SHIFT 3
+
+#define S3C24X0_UART_SIZE 0x2c
+
+/* USB device */
+/* XXX */
+
+/* Watch dog timer */
+#define WDT_WTCON 0x00 /* WDT mode */
+#define WTCON_PRESCALE_SHIFT 8
+#define WTCON_PRESCALE (0xff<<WTCON_PRESCALE_SHIFT)
+#define WTCON_ENABLE (1<<5)
+#define WTCON_CLKSEL (3<<3)
+#define WTCON_CLKSEL_16 (0<<3)
+#define WTCON_CLKSEL_32 (1<<3)
+#define WTCON_CLKSEL_64 (2<<3)
+#define WTCON_CLKSEL_128 (3<<3)
+#define WTCON_ENINT (1<<2)
+#define WTCON_ENRST (1<<0)
+
+#define WTCON_WDTSTOP 0
+
+#define WDT_WTDAT 0x04 /* timer data */
+#define WDT_WTCNT 0x08 /* timer count */
+
+#define S3C24X0_WDT_SIZE 0x0c
+
+/* IIC */
+#define S3C24X0_IIC_SIZE 0x0c
+
+
+/* IIS */
+#define S3C24X0_IIS_SIZE 0x14
+
+/* GPIO */
+#define GPIO_PACON 0x00 /* port A configuration */
+#define GPIO_PADAT 0x04 /* port A data */
+
+#define GPIO_PBCON 0x10
+/* These are only used on port B-H on 2410 & B-H,J on 2440 */
+#define PCON_INPUT 0 /* Input port */
+#define PCON_OUTPUT 1 /* Output port */
+#define PCON_ALTFUN 2 /* Alternate function */
+#define PCON_ALTFUN2 3 /* Alternate function */
+#define GPIO_PBDAT 0x14
+/* This is different between 2440 and 2442 (pull up vs pull down): */
+#define GPIO_PBUP 0x18 /* 2410 & 2440 */
+#define GPIO_PBDOWN 0x18 /* 2442 */
+
+#define GPIO_PCCON 0x20
+#define GPIO_PCDAT 0x24
+#define GPIO_PCUP 0x28 /* 2410 & 2440 */
+#define GPIO_PCDOWN 0x28 /* 2442 */
+
+#define GPIO_PDCON 0x30
+#define GPIO_PDDAT 0x34
+#define GPIO_PDUP 0x38 /* 2410 & 2440 */
+#define GPIO_PDDOWN 0x38 /* 2442 */
+
+#define GPIO_PECON 0x40
+#define PECON_INPUT(x) (0<<((x)*2)) /* Pin is used for input */
+#define PECON_OUTPUT(x) (1<<((x)*2)) /* Pin is used for output */
+#define PECON_FUNC_A(x) (2<<((x)*2)) /* Pin is used for function 'A' */
+#define PECON_FUNC_B(x) (3<<((x)*2)) /* Pin is used for function 'B' */
+#define PECON_MASK(x) (3<<((x)*2))
+#define GPIO_PEDAT 0x44
+#define GPIO_PEUP 0x48 /* 2410 & 2440 */
+#define GPIO_PEDOWN 0x48 /* 2442 */
+#define PEUD_ENABLE(x) (~(1<<(x))) /* Enable the pull Up/Down */
+#define PEUD_DISABLE(x) (1<<(x)) /* Disable the pull Up/Down */
+
+#define GPIO_PFCON 0x50
+#define GPIO_PFDAT 0x54
+#define GPIO_PFUP 0x58 /* 2410 & 2440 */
+#define GPIO_PFDOWN 0x58 /* 2442 */
+
+#define GPIO_PGCON 0x60
+#define GPIO_PGDAT 0x64
+#define GPIO_PGUP 0x68 /* 2410 & 2440 */
+#define GPIO_PGDOWN 0x68 /* 2442 */
+
+#define GPIO_PHCON 0x70
+#define GPIO_PHDAT 0x74
+#define GPIO_PHUP 0x78 /* 2410 & 2440 */
+#define GPIO_PHDOWN 0x78 /* 2442 */
+
+#define GPIO_MISCCR 0x80 /* miscellaneous control */
+#define GPIO_DCLKCON 0x84 /* DCLK 0/1 */
+#define GPIO_EXTINT(n) (0x88+4*(n)) /* external int control 0/1/2 */
+#define GPIO_EINTFLT(n) (0x94+4*(n)) /* external int filter control 0..3 */
+#define EXTINTR_LOW 0x00
+#define EXTINTR_HIGH 0x01
+#define EXTINTR_FALLING 0x02
+#define EXTINTR_RISING 0x04
+#define EXTINTR_BOTH 0x06
+#define GPIO_EINTMASK 0xa4
+#define GPIO_EINTPEND 0xa8
+#define GPIO_GSTATUS0 0xac /* external pin status */
+#define GPIO_GSTATUS1 0xb0 /* Chip ID */
+#define CHIPID_S3C2410A 0x32410002
+#define CHIPID_S3C2440A 0x32440001
+#define CHIPID_S3C2442B 0x32440AAB
+#define GPIO_GSTATUS2 0xb4 /* Reset status */
+#define GPIO_GSTATUS3 0xb8
+#define GPIO_GSTATUS4 0xbc
+
+#define GPIO_SET_FUNC(v,port,func) \
+ (((v) & ~(3<<(2*(port))))|((func)<<(2*(port))))
+
+/* ADC */
+#define ADC_ADCCON 0x00
+#define ADCCON_ENABLE_START (1<<0)
+#define ADCCON_READ_START (1<<1)
+#define ADCCON_STDBM (1<<2)
+#define ADCCON_SEL_MUX_SHIFT 3
+#define ADCCON_SEL_MUX_MASK (0x7<<ADCCON_SEL_MUX_SHIFT)
+#define ADCCON_PRSCVL_SHIFT 6
+#define ADCCON_PRSCVL_MASK (0xff<<ADCCON_PRSCVL_SHIFT)
+#define ADCCON_PRSCEN (1<<14)
+#define ADCCON_ECFLG (1<<15)
+
+#define ADC_ADCTSC 0x04
+#define ADCTSC_XY_PST 0x03
+#define ADCTSC_AUTO_PST (1<<2)
+#define ADCTSC_PULL_UP (1<<3)
+#define ADCTSC_XP_SEN (1<<4)
+#define ADCTSC_XM_SEN (1<<5)
+#define ADCTSC_YP_SEN (1<<6)
+#define ADCTSC_YM_SEN (1<<7)
+#define ADC_ADCDLY 0x08
+#define ADC_ADCDAT0 0x0c
+#define ADC_ADCDAT1 0x10
+
+#define ADCDAT_DATAMASK 0x3ff
+
+/* RTC */
+#define RTC_RTCCON 0x40
+#define RTCCON_RTCEN (1<<0)
+#define RTCCON_CLKSEL (1<<1)
+#define RTCCON_CNTSEL (1<<2)
+#define RTCCON_CLKRST (1<<3)
+#define RTC_TICNT0 0x44
+/* TICNT1 on 2440 */
+#define RTC_RTCALM 0x50
+#define RTC_ALMSEC 0x54
+#define RTC_ALMMIN 0x58
+#define RTC_ALMHOUR 0x5C
+#define RTC_ALMDATE 0x60
+#define RTC_ALMMON 0x64
+#define RTC_ALMYEAR 0x68
+/* RTCRST on 2410 */
+#define RTC_BCDSEC 0x70
+#define RTC_BCDMIN 0x74
+#define RTC_BCDHOUR 0x78
+#define RTC_BCDDATE 0x7C
+#define RTC_BCDDAY 0x80
+#define RTC_BCDMON 0x84
+#define RTC_BCDYEAR 0x88
+
+
+/* SPI */
+#define S3C24X0_SPI_SIZE 0x20
+
+#define SPI_SPCON 0x00
+#define SPCON_TAGD (1<<0) /* Tx auto garbage */
+#define SPCON_CPHA (1<<1)
+#define SPCON_CPOL (1<<2)
+#define SPCON_IDLELOW_RISING (0|0)
+#define SPCON_IDLELOW_FALLING (0|SPCON_CPHA)
+#define SPCON_IDLEHIGH_FALLING (SPCON_CPOL|0)
+#define SPCON_IDLEHIGH_RISING (SPCON_CPOL|SPCON_CPHA)
+#define SPCON_MSTR (1<<3)
+#define SPCON_ENSCK (1<<4)
+#define SPCON_SMOD_SHIFT 5
+#define SPCON_SMOD_MASK (0x03<<SPCON_SMOD_SHIFT)
+#define SPCON_SMOD_POLL (0x00<<SPCON_SMOD_SHIFT)
+#define SPCON_SMOD_INT (0x01<<SPCON_SMOD_SHIFT)
+#define SPCON_SMOD_DMA (0x02<<SPCON_SMOD_SHIFT)
+
+#define SPI_SPSTA 0x04 /* status register */
+#define SPSTA_REDY (1<<0) /* ready */
+#define SPSTA_MULF (1<<1) /* multi master error */
+#define SPSTA_DCOL (1<<2) /* Data collision error */
+
+#define SPI_SPPIN 0x08
+#define SPPIN_KEEP (1<<0)
+#define SPPIN_ENMUL (1<<2) /* multi master error detect */
+
+#define SPI_SPPRE 0x0c /* prescaler */
+#define SPI_SPTDAT 0x10 /* tx data */
+#define SPI_SPRDAT 0x14 /* rx data */
+
+
+#endif /* _ARM_S3C2XX0_S3C24X0REG_H_ */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c24x0reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c24x0var.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c24x0var.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c24x0var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c24x0var.h,v 1.1 2003/07/31 19:49:44 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2003 Genetec corporation. All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of Genetec corporation may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c24x0var.h 272103 2014-09-25 11:38:26Z gavin $
+ */
+
+#ifndef _ARM_S3C24X0VAR_H_
+#define _ARM_S3C24X0VAR_H_
+
+#include <arm/samsung/s3c2xx0/s3c2xx0var.h>
+
+struct s3c24x0_softc {
+ struct s3c2xx0_softc sc_sx;
+
+ bus_space_handle_t sc_timer_ioh; /* Timer control registers */
+};
+
+void s3c24x0_clock_freq(struct s3c2xx0_softc *);
+void s3c2410_clock_freq2(vm_offset_t, int *, int *, int *);
+void s3c2440_clock_freq2(vm_offset_t, int *, int *, int *);
+
+void s3c24x0_sleep(int);
+
+#endif /* _ARM_S3C24X0VAR_H_ */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c24x0var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c2xx0board.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c2xx0board.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c2xx0board.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c2xx0board.h 205354 2010-03-20 03:39:35Z imp $ */
+
+#ifndef _ARM_S3C2XX0_S3C2XX0BOARD_H_
+#define _ARM_S3C2XX0_S3C2XX0BOARD_H_
+
+/*
+ * These routines are expected to be provided by the board files.
+ */
+long board_init(void);
+
+#endif /* _ARM_S3C2XX0_S3C2XX0BOARD_H_ */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c2xx0board.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c2xx0reg.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c2xx0reg.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c2xx0reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,140 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c2xx0reg.h,v 1.4 2004/02/12 03:47:29 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 Fujitsu Component Limited
+ * Copyright (c) 2002, 2003 Genetec Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of The Fujitsu Component Limited nor the name of
+ * Genetec corporation may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
+ * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
+ * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c2xx0reg.h 205354 2010-03-20 03:39:35Z imp $
+ */
+
+
+/*
+ * Register definitions common to S3C2800 and S3C24[01]0
+ */
+#ifndef _ARM_S3C2XX0_S3C2XX0REG_H_
+#define _ARM_S3C2XX0_S3C2XX0REG_H_
+
+/* UART */
+/*
+ * S3C2800, 2410 and 2400 have a common built-in UART block. However,
+ * there are small diffs in bit position of some registers.
+ * Following definitions can be foune in s3c{2800,24x0}reg.h for
+ * that reason.
+ *
+ * ULCON_IR (Infra-red mode)
+ * ULCON_PARITY_SHIFT (Parity mode bit position)
+ * UMCON_AFC (Auto flow control)
+ * UMSTAT_DCTS (CTS change)
+ */
+
+#define SSCOM_ULCON 0x00 /* UART line control */
+/* ULCON_PARITY_SHIFT and ULCON_IR is defined in s3c{2800,24x0}reg.h */
+#define ULCON_PARITY_NONE (0<<ULCON_PARITY_SHIFT)
+#define ULCON_PARITY_ODD (4<<ULCON_PARITY_SHIFT)
+#define ULCON_PARITY_EVEN (5<<ULCON_PARITY_SHIFT)
+#define ULCON_PARITY_ONE (6<<ULCON_PARITY_SHIFT)
+#define ULCON_PARITY_ZERO (7<<ULCON_PARITY_SHIFT)
+#define ULCON_STOP (1<<2)
+#define ULCON_LENGTH_5 0
+#define ULCON_LENGTH_6 1
+#define ULCON_LENGTH_7 2
+#define ULCON_LENGTH_8 3
+#define SSCOM_UCON 0x04 /* UART control */
+#define UCON_TXINT_TYPE (1<<9) /* Tx interrupt. 0=pulse,1=level */
+#define UCON_TXINT_TYPE_LEVEL UCON_TXINT_TYPE
+#define UCON_TXINT_TYPE_PULSE 0
+#define UCON_RXINT_TYPE (1<<8) /* Rx interrupt */
+#define UCON_RXINT_TYPE_LEVEL UCON_RXINT_TYPE
+#define UCON_RXINT_TYPE_PULSE 0
+#define UCON_TOINT (1<<7) /* Rx timeout interrupt */
+#define UCON_ERRINT (1<<6) /* receive error interrupt */
+#define UCON_LOOP (1<<5) /* loopback */
+#define UCON_SBREAK (1<<4) /* send break */
+#define UCON_TXMODE_DISABLE (0<<2)
+#define UCON_TXMODE_INT (1<<2)
+#define UCON_TXMODE_DMA (2<<2)
+#define UCON_TXMODE_MASK (3<<2)
+#define UCON_RXMODE_DISABLE (0<<0)
+#define UCON_RXMODE_INT (1<<0)
+#define UCON_RXMODE_DMA (2<<0)
+#define UCON_RXMODE_MASK (3<<0)
+#define SSCOM_UFCON 0x08 /* FIFO control */
+#define UFCON_TXTRIGGER_0 (0<<6)
+#define UFCON_TXTRIGGER_4 (1<<6)
+#define UFCON_TXTRIGGER_8 (2<<6)
+#define UFCON_TXTRIGGER_16 (3<<6)
+#define UFCON_RXTRIGGER_4 (0<<4)
+#define UFCON_RXTRIGGER_8 (1<<4)
+#define UFCON_RXTRIGGER_12 (2<<4)
+#define UFCON_RXTRIGGER_16 (3<<4)
+#define UFCON_TXFIFO_RESET (1<<2)
+#define UFCON_RXFIFO_RESET (1<<1)
+#define UFCON_FIFO_ENABLE (1<<0)
+#define SSCOM_UMCON 0x0c /* MODEM control */
+/* UMCON_AFC is defined in s3c{2800,24x0}reg.h */
+#define UMCON_RTS (1<<0) /* Request to send */
+#define SSCOM_UTRSTAT 0x10 /* Status register */
+#define UTRSTAT_TXSHIFTER_EMPTY (1<<2)
+#define UTRSTAT_TXEMPTY (1<<1) /* TX fifo or buffer empty */
+#define UTRSTAT_RXREADY (1<<0) /* RX fifo or buffer is not empty */
+#define SSCOM_UERSTAT 0x14 /* Error status register */
+#define UERSTAT_BREAK (1<<3) /* Break signal, not 2410 */
+#define UERSTAT_FRAME (1<<2) /* Frame error */
+#define UERSTAT_PARITY (1<<1) /* Parity error, not 2410 */
+#define UERSTAT_OVERRUN (1<<0) /* Overrun */
+#define UERSTAT_ALL_ERRORS \
+ (UERSTAT_OVERRUN|UERSTAT_BREAK|UERSTAT_FRAME|UERSTAT_PARITY)
+#define SSCOM_UFSTAT 0x18 /* Fifo status register */
+#define UFSTAT_TXFULL (1<<9) /* Tx fifo full */
+#define UFSTAT_RXFULL (1<<8) /* Rx fifo full */
+#define UFSTAT_TXCOUNT_SHIFT 4 /* TX FIFO count */
+#define UFSTAT_TXCOUNT (0x0f<<UFSTAT_TXCOUNT_SHIFT)
+#define UFSTAT_RXCOUNT_SHIFT 0 /* RX FIFO count */
+#define UFSTAT_RXCOUNT (0x0f<<UFSTAT_RXCOUNT_SHIFT)
+#define SSCOM_UMSTAT 0x1c /* Modem status register */
+/* UMSTAT_DCTS is defined in s3c{2800,24x0}reg.h */
+#define UMSTAT_CTS (1<<0) /* Clear to send */
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#define SSCOM_UTXH 0x20 /* Transmit data register */
+#define SSCOM_URXH 0x24 /* Receive data register */
+#else
+#define SSCOM_UTXH 0x23 /* Transmit data register */
+#define SSCOM_URXH 0x27 /* Receive data register */
+#endif
+#define SSCOM_UBRDIV 0x28 /* baud-reate divisor */
+#define SSCOM_SIZE 0x2c
+
+/* Interrupt controller (Common to S3c2800/2400X/2410X) */
+#define INTCTL_SRCPND 0x00 /* Interrupt request status */
+#define INTCTL_INTMOD 0x04 /* Interrupt mode (FIQ/IRQ) */
+#define INTCTL_INTMSK 0x08 /* Interrupt mask */
+
+#endif /* _ARM_S3C2XX0_S3C2XX0REG_H_ */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c2xx0reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/s3c2xx0var.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/s3c2xx0var.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/s3c2xx0var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,85 @@
+/* $MidnightBSD$ */
+/* $NetBSD: s3c2xx0var.h,v 1.3 2003/08/05 11:26:54 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2002 Fujitsu Component Limited
+ * Copyright (c) 2002 Genetec Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of The Fujitsu Component Limited nor the name of
+ * Genetec corporation may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
+ * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
+ * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/s3c2xx0var.h 278727 2015-02-13 22:32:02Z ian $
+ */
+
+#ifndef _ARM_S3C2XX0VAR_H_
+#define _ARM_S3C2XX0VAR_H_
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+
+typedef enum {
+ CPU_S3C2410,
+ CPU_S3C2440,
+} s3c2xx0_cpu;
+
+struct s3c2xx0_softc {
+ device_t sc_dev;
+
+ s3c2xx0_cpu sc_cpu;
+
+ bus_space_tag_t sc_iot;
+
+ bus_space_handle_t sc_intctl_ioh;
+ bus_space_handle_t sc_gpio_ioh; /* GPIO */
+ bus_space_handle_t sc_clkman_ioh; /* Clock manager */
+ bus_space_handle_t sc_wdt_ioh; /* Watchdog Timer */
+
+ bus_dma_tag_t sc_dmat;
+
+ /* clock frequency */
+ int sc_fclk; /* CPU clock */
+ int sc_hclk; /* AHB bus clock */
+ int sc_pclk; /* peripheral clock */
+
+ struct rman s3c2xx0_irq_rman;
+ struct rman s3c2xx0_mem_rman;
+};
+
+struct s3c2xx0_ivar {
+ struct resource_list resources;
+};
+
+typedef void *s3c2xx0_chipset_tag_t;
+
+extern bus_space_tag_t s3c2xx0_bs_tag;
+extern struct s3c2xx0_softc *s3c2xx0_softc;
+extern struct arm32_bus_dma_tag s3c2xx0_bus_dma;
+
+/* Platform needs to provide this */
+bus_dma_tag_t s3c2xx0_bus_dma_init(struct arm32_bus_dma_tag *);
+
+#endif /* _ARM_S3C2XX0VAR_H_ */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/s3c2xx0var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/std.ln2410sbc
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/std.ln2410sbc (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/std.ln2410sbc 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+#$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/std.ln2410sbc 272103 2014-09-25 11:38:26Z gavin $
+include "../samsung/s3c2xx0/std.s3c2410"
+
+makeoptions KERNPHYSADDR=0x30000000
+makeoptions KERNVIRTADDR=0xc0000000
+options KERNPHYSADDR=0x30000000
+options KERNVIRTADDR=0xc0000000
+options PHYSADDR=0x30000000
+options NO_EVENTTIMERS
+
Property changes on: trunk/sys/arm/samsung/s3c2xx0/std.ln2410sbc
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/std.s3c2410
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/std.s3c2410 (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/std.s3c2410 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,8 @@
+# $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/std.s3c2410 272103 2014-09-25 11:38:26Z gavin $
+
+files "../samsung/s3c2xx0/files.s3c2xx0"
+cpu CPU_ARM9
+machine arm
+
+makeoptions CONF_CFLAGS=-mcpu=arm920t
+options NO_EVENTTIMERS
Property changes on: trunk/sys/arm/samsung/s3c2xx0/std.s3c2410
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,61 @@
+/* $MidnightBSD$ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
+
+#include "uart_if.h"
+
+extern struct uart_class uart_s3c2410_class;
+
+static int uart_s3c2410_probe(device_t dev);
+
+static device_method_t uart_s3c2410_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uart_s3c2410_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, uart_bus_detach),
+ { 0, 0 }
+};
+
+static driver_t uart_s3c2410_driver = {
+ uart_driver_name,
+ uart_s3c2410_methods,
+ sizeof(struct uart_softc),
+};
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+static int
+uart_s3c2410_probe(device_t dev)
+{
+ struct uart_devinfo *sysdev;
+ struct uart_softc *sc;
+ int unit;
+
+ sc = device_get_softc(dev);
+ sc->sc_class = &uart_s3c2410_class;
+
+ unit = device_get_unit(dev);
+ sysdev = SLIST_FIRST(&uart_sysdevs);
+ if (S3C24X0_UART_BASE(unit) == sysdev->bas.bsh) {
+ sc->sc_sysdev = sysdev;
+ bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
+ }
+ return(uart_bus_probe(dev, 0, 0, 0, unit));
+}
+
+DRIVER_MODULE(uart, s3c24x0, uart_s3c2410_driver, uart_devclass, 0, 0);
Property changes on: trunk/sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,77 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * Copyright (c) 2007 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/samsung/s3c2xx0/s3c2xx0var.h>
+
+extern struct uart_class uart_s3c2410_class;
+
+bus_space_tag_t uart_bus_space_io;
+bus_space_tag_t uart_bus_space_mem;
+
+vm_offset_t s3c2410_uart_vaddr;
+unsigned int s3c2410_pclk;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+ return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+ if (devtype != UART_DEV_CONSOLE)
+ return (ENXIO);
+
+ di->ops = uart_getops(&uart_s3c2410_class);
+ di->bas.chan = 0;
+ di->bas.bst = s3c2xx0_bs_tag;
+ di->bas.bsh = s3c2410_uart_vaddr;
+ di->bas.regshft = 0;
+ di->bas.rclk = s3c2410_pclk;
+ di->baudrate = 115200;
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ uart_bus_space_io = s3c2xx0_bs_tag;
+ uart_bus_space_mem = NULL;
+
+ return (0);
+}
Property changes on: trunk/sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,406 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * Copyright (c) 2007-2009 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c 272103 2014-09-25 11:38:26Z gavin $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/tty.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_bus.h>
+#include <arm/samsung/s3c2xx0/s3c2440reg.h>
+#include <arm/samsung/s3c2xx0/uart_dev_s3c2410.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0reg.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0var.h>
+#include "uart_if.h"
+
+/* Finds the subirq from the parent */
+#define get_sub_irq(parent, offset) \
+ ((parent == S3C24X0_INT_UART0) ? S3C24X0_SUBIRQ_MIN + offset : \
+ ((parent == S3C24X0_INT_UART1) ? S3C24X0_SUBIRQ_MIN + 3 + offset : \
+ S3C24X0_SUBIRQ_MIN + 6 + offset))
+#define RX_OFF 0
+#define TX_OFF 1
+#define ERR_OFF 2
+
+extern unsigned int s3c2410_pclk;
+
+static int sscomspeed(long, long);
+static int s3c24x0_uart_param(struct uart_bas *, int, int, int, int);
+
+/*
+ * Low-level UART interface.
+ */
+static int s3c2410_probe(struct uart_bas *bas);
+static void s3c2410_init(struct uart_bas *bas, int, int, int, int);
+static void s3c2410_term(struct uart_bas *bas);
+static void s3c2410_putc(struct uart_bas *bas, int);
+static int s3c2410_rxready(struct uart_bas *bas);
+static int s3c2410_getc(struct uart_bas *bas, struct mtx *mtx);
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+
+static int
+sscomspeed(long speed, long frequency)
+{
+ int x;
+
+ if (speed <= 0 || frequency <= 0)
+ return -1;
+ x = (frequency / 16) / speed;
+ return x-1;
+}
+
+static int
+s3c24x0_uart_param(struct uart_bas *bas, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ int brd, ulcon;
+
+ ulcon = 0;
+
+ switch(databits) {
+ case 5:
+ ulcon |= ULCON_LENGTH_5;
+ break;
+ case 6:
+ ulcon |= ULCON_LENGTH_6;
+ break;
+ case 7:
+ ulcon |= ULCON_LENGTH_7;
+ break;
+ case 8:
+ ulcon |= ULCON_LENGTH_8;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ switch (parity) {
+ case UART_PARITY_NONE:
+ ulcon |= ULCON_PARITY_NONE;
+ break;
+ case UART_PARITY_ODD:
+ ulcon |= ULCON_PARITY_ODD;
+ break;
+ case UART_PARITY_EVEN:
+ ulcon |= ULCON_PARITY_EVEN;
+ break;
+ case UART_PARITY_MARK:
+ case UART_PARITY_SPACE:
+ default:
+ return (EINVAL);
+ }
+
+ if (stopbits == 2)
+ ulcon |= ULCON_STOP;
+
+ uart_setreg(bas, SSCOM_ULCON, ulcon);
+
+ brd = sscomspeed(baudrate, bas->rclk);
+ uart_setreg(bas, SSCOM_UBRDIV, brd);
+
+ return (0);
+}
+
+struct uart_ops uart_s3c2410_ops = {
+ .probe = s3c2410_probe,
+ .init = s3c2410_init,
+ .term = s3c2410_term,
+ .putc = s3c2410_putc,
+ .rxready = s3c2410_rxready,
+ .getc = s3c2410_getc,
+};
+
+static int
+s3c2410_probe(struct uart_bas *bas)
+{
+ return (0);
+}
+
+static void
+s3c2410_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+ if (bas->rclk == 0)
+ bas->rclk = s3c2410_pclk;
+ KASSERT(bas->rclk != 0, ("s3c2410_init: Invalid rclk"));
+
+ uart_setreg(bas, SSCOM_UCON, 0);
+ uart_setreg(bas, SSCOM_UFCON,
+ UFCON_TXTRIGGER_8 | UFCON_RXTRIGGER_8 |
+ UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET |
+ UFCON_FIFO_ENABLE);
+ s3c24x0_uart_param(bas, baudrate, databits, stopbits, parity);
+
+ /* Enable UART. */
+ uart_setreg(bas, SSCOM_UCON, UCON_TXMODE_INT | UCON_RXMODE_INT |
+ UCON_TOINT);
+ uart_setreg(bas, SSCOM_UMCON, UMCON_RTS);
+}
+
+static void
+s3c2410_term(struct uart_bas *bas)
+{
+ /* XXX */
+}
+
+static void
+s3c2410_putc(struct uart_bas *bas, int c)
+{
+ while ((bus_space_read_4(bas->bst, bas->bsh, SSCOM_UFSTAT) &
+ UFSTAT_TXFULL) == UFSTAT_TXFULL)
+ continue;
+
+ uart_setreg(bas, SSCOM_UTXH, c);
+}
+
+static int
+s3c2410_rxready(struct uart_bas *bas)
+{
+ return ((uart_getreg(bas, SSCOM_UTRSTAT) & UTRSTAT_RXREADY) ==
+ UTRSTAT_RXREADY);
+}
+
+static int
+s3c2410_getc(struct uart_bas *bas, struct mtx *mtx)
+{
+ while (!sscom_rxrdy(bas->bst, bas->bsh))
+ continue;
+
+ return sscom_getc(bas->bst, bas->bsh);
+}
+static int s3c2410_bus_probe(struct uart_softc *sc);
+static int s3c2410_bus_attach(struct uart_softc *sc);
+static int s3c2410_bus_flush(struct uart_softc *, int);
+static int s3c2410_bus_getsig(struct uart_softc *);
+static int s3c2410_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int s3c2410_bus_ipend(struct uart_softc *);
+static int s3c2410_bus_param(struct uart_softc *, int, int, int, int);
+static int s3c2410_bus_receive(struct uart_softc *);
+static int s3c2410_bus_setsig(struct uart_softc *, int);
+static int s3c2410_bus_transmit(struct uart_softc *);
+static void s3c2410_bus_grab(struct uart_softc *);
+static void s3c2410_bus_ungrab(struct uart_softc *);
+
+static kobj_method_t s3c2410_methods[] = {
+ KOBJMETHOD(uart_probe, s3c2410_bus_probe),
+ KOBJMETHOD(uart_attach, s3c2410_bus_attach),
+ KOBJMETHOD(uart_flush, s3c2410_bus_flush),
+ KOBJMETHOD(uart_getsig, s3c2410_bus_getsig),
+ KOBJMETHOD(uart_ioctl, s3c2410_bus_ioctl),
+ KOBJMETHOD(uart_ipend, s3c2410_bus_ipend),
+ KOBJMETHOD(uart_param, s3c2410_bus_param),
+ KOBJMETHOD(uart_receive, s3c2410_bus_receive),
+ KOBJMETHOD(uart_setsig, s3c2410_bus_setsig),
+ KOBJMETHOD(uart_transmit, s3c2410_bus_transmit),
+ KOBJMETHOD(uart_grab, s3c2410_bus_grab),
+ KOBJMETHOD(uart_ungrab, s3c2410_bus_ungrab),
+
+ {0, 0 }
+};
+
+int
+s3c2410_bus_probe(struct uart_softc *sc)
+{
+ switch(s3c2xx0_softc->sc_cpu) {
+ case CPU_S3C2410:
+ sc->sc_txfifosz = 16;
+ sc->sc_rxfifosz = 16;
+ break;
+ case CPU_S3C2440:
+ sc->sc_txfifosz = 64;
+ sc->sc_rxfifosz = 64;
+ break;
+ default:
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+s3c2410_bus_attach(struct uart_softc *sc)
+{
+ uintptr_t irq;
+
+ sc->sc_hwiflow = 0;
+ sc->sc_hwoflow = 0;
+
+ irq = rman_get_start(sc->sc_ires);
+ arm_unmask_irq(irq);
+ arm_unmask_irq(get_sub_irq(irq, RX_OFF));
+ arm_unmask_irq(get_sub_irq(irq, TX_OFF));
+ arm_unmask_irq(get_sub_irq(irq, ERR_OFF));
+
+ return (0);
+}
+
+static int
+s3c2410_bus_transmit(struct uart_softc *sc)
+{
+ uintptr_t irq;
+
+ uart_lock(sc->sc_hwmtx);
+
+ for (int i = 0; i < sc->sc_txdatasz; i++) {
+ s3c2410_putc(&sc->sc_bas, sc->sc_txbuf[i]);
+ uart_barrier(&sc->sc_bas);
+ }
+
+ sc->sc_txbusy = 1;
+
+ uart_unlock(sc->sc_hwmtx);
+
+ irq = rman_get_start(sc->sc_ires);
+ arm_unmask_irq(get_sub_irq(irq, TX_OFF));
+
+ return (0);
+}
+
+static int
+s3c2410_bus_setsig(struct uart_softc *sc, int sig)
+{
+ return (0);
+}
+
+static int
+s3c2410_bus_receive(struct uart_softc *sc)
+{
+
+ uart_rx_put(sc, uart_getreg(&sc->sc_bas, SSCOM_URXH));
+ return (0);
+}
+
+static int
+s3c2410_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ int error;
+
+ if (sc->sc_bas.rclk == 0)
+ sc->sc_bas.rclk = s3c2410_pclk;
+ KASSERT(sc->sc_bas.rclk != 0, ("s3c2410_init: Invalid rclk"));
+
+ uart_lock(sc->sc_hwmtx);
+ error = s3c24x0_uart_param(&sc->sc_bas, baudrate, databits, stopbits,
+ parity);
+ uart_unlock(sc->sc_hwmtx);
+
+ return (error);
+}
+
+static int
+s3c2410_bus_ipend(struct uart_softc *sc)
+{
+ uint32_t ufstat, txmask, rxmask;
+ uintptr_t irq;
+ int ipend = 0;
+
+ uart_lock(sc->sc_hwmtx);
+ ufstat = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UFSTAT);
+ uart_unlock(sc->sc_hwmtx);
+
+ txmask = rxmask = 0;
+ switch (s3c2xx0_softc->sc_cpu) {
+ case CPU_S3C2410:
+ txmask = UFSTAT_TXCOUNT;
+ rxmask = UFSTAT_RXCOUNT;
+ break;
+ case CPU_S3C2440:
+ txmask = S3C2440_UFSTAT_TXCOUNT;
+ rxmask = S3C2440_UFSTAT_RXCOUNT;
+ break;
+ }
+ if ((ufstat & txmask) == 0) {
+ if (sc->sc_txbusy != 0)
+ ipend |= SER_INT_TXIDLE;
+ irq = rman_get_start(sc->sc_ires);
+ arm_mask_irq(get_sub_irq(irq, TX_OFF));
+ }
+ if ((ufstat & rxmask) > 0) {
+ ipend |= SER_INT_RXREADY;
+ }
+
+ return (ipend);
+}
+
+static int
+s3c2410_bus_flush(struct uart_softc *sc, int what)
+{
+ return (0);
+}
+
+static int
+s3c2410_bus_getsig(struct uart_softc *sc)
+{
+ return (0);
+}
+
+static int
+s3c2410_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+ return (EINVAL);
+}
+
+
+static void
+s3c2410_bus_grab(struct uart_softc *sc)
+{
+ uintptr_t irq;
+
+ irq = rman_get_start(sc->sc_ires);
+ arm_mask_irq(get_sub_irq(irq, RX_OFF));
+}
+
+static void
+s3c2410_bus_ungrab(struct uart_softc *sc)
+{
+ uintptr_t irq;
+
+ irq = rman_get_start(sc->sc_ires);
+ arm_unmask_irq(get_sub_irq(irq, RX_OFF));
+}
+
+struct uart_class uart_s3c2410_class = {
+ "s3c2410 class",
+ s3c2410_methods,
+ 1,
+ .uc_ops = &uart_s3c2410_ops,
+ .uc_range = 8,
+ .uc_rclk = 0,
+};
Property changes on: trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h
===================================================================
--- trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h (rev 0)
+++ trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,89 @@
+/* $MidnightBSD$ */
+/* $NetBSD: sscom_var.h,v 1.5 2003/08/04 12:28:49 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 Fujitsu Component Limited
+ * Copyright (c) 2002, 2003 Genetec Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of The Fujitsu Component Limited nor the name of
+ * Genetec corporation may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
+ * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
+ * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* derived from sys/dev/ic/comvar.h */
+
+/*-
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h 205354 2010-03-20 03:39:35Z imp $
+ */
+
+#ifndef _ARM_S3C2XX0_SSCOM_VAR_H
+#define _ARM_S3C2XX0_SSCOM_VAR_H
+
+
+/* Hardware flag masks */
+#define SSCOM_HW_FLOW 0x02
+#define SSCOM_HW_DEV_OK 0x04
+#define SSCOM_HW_CONSOLE 0x08
+#define SSCOM_HW_KGDB 0x10
+#define SSCOM_HW_TXINT 0x20
+#define SSCOM_HW_RXINT 0x40
+
+/* Buffer size for character buffer */
+#define SSCOM_RING_SIZE 2048
+
+#define sscom_rxrdy(iot,ioh) \
+ (bus_space_read_1((iot), (ioh), SSCOM_UTRSTAT) & UTRSTAT_RXREADY)
+#define sscom_getc(iot,ioh) bus_space_read_1((iot), (ioh), SSCOM_URXH)
+#define sscom_geterr(iot,ioh) bus_space_read_1((iot), (ioh), SSCOM_UERSTAT)
+
+#endif /* _ARM_S3C2XX0_SSCOM_VAR_H */
Property changes on: trunk/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/aintc.c
===================================================================
--- trunk/sys/arm/ti/aintc.c (rev 0)
+++ trunk/sys/arm/ti/aintc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,196 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Based on OMAP3 INTC code by Ben Gray
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/aintc.c 283329 2015-05-23 21:12:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#define INTC_REVISION 0x00
+#define INTC_SYSCONFIG 0x10
+#define INTC_SYSSTATUS 0x14
+#define INTC_SIR_IRQ 0x40
+#define INTC_CONTROL 0x48
+#define INTC_THRESHOLD 0x68
+#define INTC_MIR_CLEAR(x) (0x88 + ((x) * 0x20))
+#define INTC_MIR_SET(x) (0x8C + ((x) * 0x20))
+#define INTC_ISR_SET(x) (0x90 + ((x) * 0x20))
+#define INTC_ISR_CLEAR(x) (0x94 + ((x) * 0x20))
+
+struct ti_aintc_softc {
+ device_t sc_dev;
+ struct resource * aintc_res[3];
+ bus_space_tag_t aintc_bst;
+ bus_space_handle_t aintc_bsh;
+ uint8_t ver;
+};
+
+static struct resource_spec ti_aintc_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+
+static struct ti_aintc_softc *ti_aintc_sc = NULL;
+
+#define aintc_read_4(_sc, reg) \
+ bus_space_read_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg))
+#define aintc_write_4(_sc, reg, val) \
+ bus_space_write_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg), (val))
+
+
+static void
+aintc_post_filter(void *arg)
+{
+
+ arm_irq_memory_barrier(0);
+ aintc_write_4(ti_aintc_sc, INTC_CONTROL, 1); /* EOI */
+}
+
+static int
+ti_aintc_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+
+ if (!ofw_bus_is_compatible(dev, "ti,aintc"))
+ return (ENXIO);
+ device_set_desc(dev, "TI AINTC Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_aintc_attach(device_t dev)
+{
+ struct ti_aintc_softc *sc = device_get_softc(dev);
+ uint32_t x;
+
+ sc->sc_dev = dev;
+
+ if (ti_aintc_sc)
+ return (ENXIO);
+
+ if (bus_alloc_resources(dev, ti_aintc_spec, sc->aintc_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->aintc_bst = rman_get_bustag(sc->aintc_res[0]);
+ sc->aintc_bsh = rman_get_bushandle(sc->aintc_res[0]);
+
+ ti_aintc_sc = sc;
+
+ x = aintc_read_4(sc, INTC_REVISION);
+ device_printf(dev, "Revision %u.%u\n",(x >> 4) & 0xF, x & 0xF);
+
+ /* SoftReset */
+ aintc_write_4(sc, INTC_SYSCONFIG, 2);
+
+ /* Wait for reset to complete */
+ while(!(aintc_read_4(sc, INTC_SYSSTATUS) & 1));
+
+ /*Set Priority Threshold */
+ aintc_write_4(sc, INTC_THRESHOLD, 0xFF);
+
+ arm_post_filter = aintc_post_filter;
+
+ return (0);
+}
+
+static device_method_t ti_aintc_methods[] = {
+ DEVMETHOD(device_probe, ti_aintc_probe),
+ DEVMETHOD(device_attach, ti_aintc_attach),
+ { 0, 0 }
+};
+
+static driver_t ti_aintc_driver = {
+ "aintc",
+ ti_aintc_methods,
+ sizeof(struct ti_aintc_softc),
+};
+
+static devclass_t ti_aintc_devclass;
+
+DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass, 0, 0);
+
+int
+arm_get_next_irq(int last_irq)
+{
+ struct ti_aintc_softc *sc = ti_aintc_sc;
+ uint32_t active_irq;
+
+ /* Get the next active interrupt */
+ active_irq = aintc_read_4(sc, INTC_SIR_IRQ);
+
+ /* Check for spurious interrupt */
+ if ((active_irq & 0xffffff80)) {
+ device_printf(sc->sc_dev,
+ "Spurious interrupt detected (0x%08x)\n", active_irq);
+ aintc_write_4(sc, INTC_SIR_IRQ, 0);
+ return -1;
+ }
+
+ if (active_irq != last_irq)
+ return active_irq;
+ else
+ return -1;
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ struct ti_aintc_softc *sc = ti_aintc_sc;
+
+ aintc_write_4(sc, INTC_MIR_SET(nb >> 5), (1UL << (nb & 0x1F)));
+ aintc_write_4(sc, INTC_CONTROL, 1); /* EOI */
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ struct ti_aintc_softc *sc = ti_aintc_sc;
+
+ arm_irq_memory_barrier(nb);
+ aintc_write_4(sc, INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F)));
+}
Property changes on: trunk/sys/arm/ti/aintc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_dmtimer.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_dmtimer.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_dmtimer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,680 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_dmtimer.c 287040 2015-08-23 17:54:48Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/taskqueue.h>
+#include <sys/timeet.h>
+#include <sys/timepps.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_scm.h>
+
+#define AM335X_NUM_TIMERS 8
+
+#define DMT_TIDR 0x00 /* Identification Register */
+#define DMT_TIOCP_CFG 0x10 /* OCP Configuration Reg */
+#define DMT_TIOCP_RESET (1 << 0) /* TIOCP perform soft reset */
+#define DMT_IQR_EOI 0x20 /* IRQ End-Of-Interrupt Reg */
+#define DMT_IRQSTATUS_RAW 0x24 /* IRQSTATUS Raw Reg */
+#define DMT_IRQSTATUS 0x28 /* IRQSTATUS Reg */
+#define DMT_IRQENABLE_SET 0x2c /* IRQSTATUS Set Reg */
+#define DMT_IRQENABLE_CLR 0x30 /* IRQSTATUS Clear Reg */
+#define DMT_IRQWAKEEN 0x34 /* IRQ Wakeup Enable Reg */
+#define DMT_IRQ_MAT (1 << 0) /* IRQ: Match */
+#define DMT_IRQ_OVF (1 << 1) /* IRQ: Overflow */
+#define DMT_IRQ_TCAR (1 << 2) /* IRQ: Capture */
+#define DMT_IRQ_MASK (DMT_IRQ_TCAR | DMT_IRQ_OVF | DMT_IRQ_MAT)
+#define DMT_TCLR 0x38 /* Control Register */
+#define DMT_TCLR_START (1 << 0) /* Start timer */
+#define DMT_TCLR_AUTOLOAD (1 << 1) /* Auto-reload on overflow */
+#define DMT_TCLR_PRES_MASK (7 << 2) /* Prescaler mask */
+#define DMT_TCLR_PRES_ENABLE (1 << 5) /* Prescaler enable */
+#define DMT_TCLR_COMP_ENABLE (1 << 6) /* Compare enable */
+#define DMT_TCLR_PWM_HIGH (1 << 7) /* PWM default output high */
+#define DMT_TCLR_CAPTRAN_MASK (3 << 8) /* Capture transition mask */
+#define DMT_TCLR_CAPTRAN_NONE (0 << 8) /* Capture: none */
+#define DMT_TCLR_CAPTRAN_LOHI (1 << 8) /* Capture lo->hi transition */
+#define DMT_TCLR_CAPTRAN_HILO (2 << 8) /* Capture hi->lo transition */
+#define DMT_TCLR_CAPTRAN_BOTH (3 << 8) /* Capture both transitions */
+#define DMT_TCLR_TRGMODE_MASK (3 << 10) /* Trigger output mode mask */
+#define DMT_TCLR_TRGMODE_NONE (0 << 10) /* Trigger off */
+#define DMT_TCLR_TRGMODE_OVFL (1 << 10) /* Trigger on overflow */
+#define DMT_TCLR_TRGMODE_BOTH (2 << 10) /* Trigger on match + ovflow */
+#define DMT_TCLR_PWM_PTOGGLE (1 << 12) /* PWM toggles */
+#define DMT_TCLR_CAP_MODE_2ND (1 << 13) /* Capture second event mode */
+#define DMT_TCLR_GPO_CFG (1 << 14) /* (no descr in datasheet) */
+#define DMT_TCRR 0x3C /* Counter Register */
+#define DMT_TLDR 0x40 /* Load Reg */
+#define DMT_TTGR 0x44 /* Trigger Reg */
+#define DMT_TWPS 0x48 /* Write Posted Status Reg */
+#define DMT_TMAR 0x4C /* Match Reg */
+#define DMT_TCAR1 0x50 /* Capture Reg */
+#define DMT_TSICR 0x54 /* Synchr. Interface Ctrl Reg */
+#define DMT_TSICR_RESET (1 << 1) /* TSICR perform soft reset */
+#define DMT_TCAR2 0x48 /* Capture Reg */
+
+/*
+ * Use timer 2 for the eventtimer. When PPS support is not compiled in, there's
+ * no need to use a timer that has an associated capture-input pin, so use timer
+ * 3 for timecounter. When PPS is compiled in we ignore the default and use
+ * whichever of timers 4-7 have the capture pin configured.
+ */
+#define DEFAULT_ET_TIMER 2
+#define DEFAULT_TC_TIMER 3
+
+struct am335x_dmtimer_softc {
+ struct resource * tmr_mem_res[AM335X_NUM_TIMERS];
+ struct resource * tmr_irq_res[AM335X_NUM_TIMERS];
+ uint32_t sysclk_freq;
+ uint32_t tc_num; /* Which timer number is tc. */
+ uint32_t tc_tclr; /* Cached tc TCLR register. */
+ struct resource * tc_memres; /* Resources for tc timer. */
+ uint32_t et_num; /* Which timer number is et. */
+ uint32_t et_tclr; /* Cached et TCLR register. */
+ struct resource * et_memres; /* Resources for et timer. */
+ int pps_curmode; /* Edge mode now set in hw. */
+ struct task pps_task; /* For pps_event handling. */
+ struct cdev * pps_cdev;
+ struct pps_state pps;
+ struct timecounter tc;
+ struct eventtimer et;
+};
+
+static struct am335x_dmtimer_softc *am335x_dmtimer_sc;
+
+static struct resource_spec am335x_dmtimer_mem_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE },
+ { SYS_RES_MEMORY, 4, RF_ACTIVE },
+ { SYS_RES_MEMORY, 5, RF_ACTIVE },
+ { SYS_RES_MEMORY, 6, RF_ACTIVE },
+ { SYS_RES_MEMORY, 7, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+static struct resource_spec am335x_dmtimer_irq_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { SYS_RES_IRQ, 4, RF_ACTIVE },
+ { SYS_RES_IRQ, 5, RF_ACTIVE },
+ { SYS_RES_IRQ, 6, RF_ACTIVE },
+ { SYS_RES_IRQ, 7, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+static inline uint32_t
+am335x_dmtimer_tc_read_4(struct am335x_dmtimer_softc *sc, uint32_t reg)
+{
+
+ return (bus_read_4(sc->tc_memres, reg));
+}
+
+static inline void
+am335x_dmtimer_tc_write_4(struct am335x_dmtimer_softc *sc, uint32_t reg,
+ uint32_t val)
+{
+
+ bus_write_4(sc->tc_memres, reg, val);
+}
+
+static inline uint32_t
+am335x_dmtimer_et_read_4(struct am335x_dmtimer_softc *sc, uint32_t reg)
+{
+
+ return (bus_read_4(sc->et_memres, reg));
+}
+
+static inline void
+am335x_dmtimer_et_write_4(struct am335x_dmtimer_softc *sc, uint32_t reg,
+ uint32_t val)
+{
+
+ bus_write_4(sc->et_memres, reg, val);
+}
+
+/*
+ * PPS driver routines, included when the kernel is built with option PPS_SYNC.
+ *
+ * Note that this PPS driver does not use an interrupt. Instead it uses the
+ * hardware's ability to latch the timer's count register in response to a
+ * signal on an IO pin. Each of timers 4-7 have an associated pin, and this
+ * code allows any one of those to be used.
+ *
+ * The timecounter routines in kern_tc.c call the pps poll routine periodically
+ * to see if a new counter value has been latched. When a new value has been
+ * latched, the only processing done in the poll routine is to capture the
+ * current set of timecounter timehands (done with pps_capture()) and the
+ * latched value from the timer. The remaining work (done by pps_event()) is
+ * scheduled to be done later in a non-interrupt context.
+ */
+
+#define PPS_CDEV_NAME "dmtpps"
+
+static void
+am335x_dmtimer_set_capture_mode(struct am335x_dmtimer_softc *sc, bool force_off)
+{
+ int newmode;
+
+ if (force_off)
+ newmode = 0;
+ else
+ newmode = sc->pps.ppsparam.mode & PPS_CAPTUREBOTH;
+
+ if (newmode == sc->pps_curmode)
+ return;
+
+ sc->pps_curmode = newmode;
+ sc->tc_tclr &= ~DMT_TCLR_CAPTRAN_MASK;
+ switch (newmode) {
+ case PPS_CAPTUREASSERT:
+ sc->tc_tclr |= DMT_TCLR_CAPTRAN_LOHI;
+ break;
+ case PPS_CAPTURECLEAR:
+ sc->tc_tclr |= DMT_TCLR_CAPTRAN_HILO;
+ break;
+ default:
+ /* It can't be BOTH, so it's disabled. */
+ break;
+ }
+ am335x_dmtimer_tc_write_4(sc, DMT_TCLR, sc->tc_tclr);
+}
+
+static void
+am335x_dmtimer_tc_poll_pps(struct timecounter *tc)
+{
+ struct am335x_dmtimer_softc *sc;
+
+ sc = tc->tc_priv;
+
+ /*
+ * Note that we don't have the TCAR interrupt enabled, but the hardware
+ * still provides the status bits in the "RAW" status register even when
+ * they're masked from generating an irq. However, when clearing the
+ * TCAR status to re-arm the capture for the next second, we have to
+ * write to the IRQ status register, not the RAW register. Quirky.
+ */
+ if (am335x_dmtimer_tc_read_4(sc, DMT_IRQSTATUS_RAW) & DMT_IRQ_TCAR) {
+ pps_capture(&sc->pps);
+ sc->pps.capcount = am335x_dmtimer_tc_read_4(sc, DMT_TCAR1);
+ am335x_dmtimer_tc_write_4(sc, DMT_IRQSTATUS, DMT_IRQ_TCAR);
+ taskqueue_enqueue_fast(taskqueue_fast, &sc->pps_task);
+ }
+}
+
+static void
+am335x_dmtimer_process_pps_event(void *arg, int pending)
+{
+ struct am335x_dmtimer_softc *sc;
+
+ sc = arg;
+
+ /* This is the task function that gets enqueued by poll_pps. Once the
+ * time has been captured in the hw interrupt context, the remaining
+ * (more expensive) work to process the event is done later in a
+ * non-fast-interrupt context.
+ *
+ * We only support capture of the rising or falling edge, not both at
+ * once; tell the kernel to process whichever mode is currently active.
+ */
+ pps_event(&sc->pps, sc->pps.ppsparam.mode & PPS_CAPTUREBOTH);
+}
+
+static int
+am335x_dmtimer_pps_open(struct cdev *dev, int flags, int fmt,
+ struct thread *td)
+{
+ struct am335x_dmtimer_softc *sc;
+
+ sc = dev->si_drv1;
+
+ /* Enable capture on open. Harmless if already open. */
+ am335x_dmtimer_set_capture_mode(sc, 0);
+
+ return 0;
+}
+
+static int
+am335x_dmtimer_pps_close(struct cdev *dev, int flags, int fmt,
+ struct thread *td)
+{
+ struct am335x_dmtimer_softc *sc;
+
+ sc = dev->si_drv1;
+
+ /*
+ * Disable capture on last close. Use the force-off flag to override
+ * the configured mode and turn off the hardware capture.
+ */
+ am335x_dmtimer_set_capture_mode(sc, 1);
+
+ return 0;
+}
+
+static int
+am335x_dmtimer_pps_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
+ int flags, struct thread *td)
+{
+ struct am335x_dmtimer_softc *sc;
+ int err;
+
+ sc = dev->si_drv1;
+
+ /*
+ * The hardware has a "capture both edges" mode, but we can't do
+ * anything useful with it in terms of PPS capture, so don't even try.
+ */
+ if ((sc->pps.ppsparam.mode & PPS_CAPTUREBOTH) == PPS_CAPTUREBOTH)
+ return (EINVAL);
+
+ /* Let the kernel do the heavy lifting for ioctl. */
+ err = pps_ioctl(cmd, data, &sc->pps);
+ if (err != 0)
+ return (err);
+
+ /*
+ * The capture mode could have changed, set the hardware to whatever
+ * mode is now current. Effectively a no-op if nothing changed.
+ */
+ am335x_dmtimer_set_capture_mode(sc, 0);
+
+ return (err);
+}
+
+static struct cdevsw am335x_dmtimer_pps_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = am335x_dmtimer_pps_open,
+ .d_close = am335x_dmtimer_pps_close,
+ .d_ioctl = am335x_dmtimer_pps_ioctl,
+ .d_name = PPS_CDEV_NAME,
+};
+
+/*
+ * Set up the PPS cdev and the the kernel timepps stuff.
+ *
+ * Note that this routine cannot touch the hardware, because bus space resources
+ * are not fully set up yet when this is called.
+ */
+static int
+am335x_dmtimer_pps_init(device_t dev, struct am335x_dmtimer_softc *sc)
+{
+ int i, timer_num, unit;
+ unsigned int padstate;
+ const char * padmux;
+ struct padinfo {
+ char * ballname;
+ char * muxname;
+ int timer_num;
+ } padinfo[] = {
+ {"GPMC_ADVn_ALE", "timer4", 4},
+ {"GPMC_BEn0_CLE", "timer5", 5},
+ {"GPMC_WEn", "timer6", 6},
+ {"GPMC_OEn_REn", "timer7", 7},
+ };
+
+ /*
+ * Figure out which pin the user has set up for pps. We'll use the
+ * first timer that has an external caputure pin configured as input.
+ *
+ * XXX The hieroglyphic "(padstate & (0x01 << 5)))" checks that the pin
+ * is configured for input. The right symbolic values aren't exported
+ * yet from ti_scm.h.
+ */
+ timer_num = 0;
+ for (i = 0; i < nitems(padinfo) && timer_num == 0; ++i) {
+ if (ti_scm_padconf_get(padinfo[i].ballname, &padmux,
+ &padstate) == 0) {
+ if (strcasecmp(padinfo[i].muxname, padmux) == 0 &&
+ (padstate & (0x01 << 5)))
+ timer_num = padinfo[i].timer_num;
+ }
+ }
+
+ if (timer_num == 0) {
+ device_printf(dev, "No DMTimer found with capture pin "
+ "configured as input; PPS driver disabled.\n");
+ return (DEFAULT_TC_TIMER);
+ }
+
+ /*
+ * Indicate our capabilities (pretty much just capture of either edge).
+ * Have the kernel init its part of the pps_state struct and add its
+ * capabilities.
+ */
+ sc->pps.ppscap = PPS_CAPTUREBOTH;
+ pps_init(&sc->pps);
+
+ /*
+ * Set up to capture the PPS via timecounter polling, and init the task
+ * that does deferred pps_event() processing after capture.
+ */
+ sc->tc.tc_poll_pps = am335x_dmtimer_tc_poll_pps;
+ TASK_INIT(&sc->pps_task, 0, am335x_dmtimer_process_pps_event, sc);
+
+ /* Create the PPS cdev. */
+ unit = device_get_unit(dev);
+ sc->pps_cdev = make_dev(&am335x_dmtimer_pps_cdevsw, unit,
+ UID_ROOT, GID_WHEEL, 0600, PPS_CDEV_NAME);
+ sc->pps_cdev->si_drv1 = sc;
+
+ device_printf(dev, "Using DMTimer%d for PPS device /dev/%s%d\n",
+ timer_num, PPS_CDEV_NAME, unit);
+
+ return (timer_num);
+}
+
+/*
+ * End of PPS driver code.
+ */
+
+static unsigned
+am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
+{
+ struct am335x_dmtimer_softc *sc;
+
+ sc = tc->tc_priv;
+
+ return (am335x_dmtimer_tc_read_4(sc, DMT_TCRR));
+}
+
+static int
+am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct am335x_dmtimer_softc *sc;
+ uint32_t initial_count, reload_count;
+
+ sc = et->et_priv;
+
+ /*
+ * Stop the timer before changing it. This routine will often be called
+ * while the timer is still running, to either lengthen or shorten the
+ * current event time. We need to ensure the timer doesn't expire while
+ * we're working with it.
+ *
+ * Also clear any pending interrupt status, because it's at least
+ * theoretically possible that we're running in a primary interrupt
+ * context now, and a timer interrupt could be pending even before we
+ * stopped the timer. The more likely case is that we're being called
+ * from the et_event_cb() routine dispatched from our own handler, but
+ * it's not clear to me that that's the only case possible.
+ */
+ sc->et_tclr &= ~(DMT_TCLR_START | DMT_TCLR_AUTOLOAD);
+ am335x_dmtimer_et_write_4(sc, DMT_TCLR, sc->et_tclr);
+ am335x_dmtimer_et_write_4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
+
+ if (period != 0) {
+ reload_count = ((uint32_t)et->et_frequency * period) >> 32;
+ sc->et_tclr |= DMT_TCLR_AUTOLOAD;
+ } else {
+ reload_count = 0;
+ }
+
+ if (first != 0)
+ initial_count = ((uint32_t)et->et_frequency * first) >> 32;
+ else
+ initial_count = reload_count;
+
+ /*
+ * Set auto-reload and current-count values. This timer hardware counts
+ * up from the initial/reload value and interrupts on the zero rollover.
+ */
+ am335x_dmtimer_et_write_4(sc, DMT_TLDR, 0xFFFFFFFF - reload_count);
+ am335x_dmtimer_et_write_4(sc, DMT_TCRR, 0xFFFFFFFF - initial_count);
+
+ /* Enable overflow interrupt, and start the timer. */
+ am335x_dmtimer_et_write_4(sc, DMT_IRQENABLE_SET, DMT_IRQ_OVF);
+ sc->et_tclr |= DMT_TCLR_START;
+ am335x_dmtimer_et_write_4(sc, DMT_TCLR, sc->et_tclr);
+
+ return (0);
+}
+
+static int
+am335x_dmtimer_stop(struct eventtimer *et)
+{
+ struct am335x_dmtimer_softc *sc;
+
+ sc = et->et_priv;
+
+ /* Stop timer, disable and clear interrupt. */
+ sc->et_tclr &= ~(DMT_TCLR_START | DMT_TCLR_AUTOLOAD);
+ am335x_dmtimer_et_write_4(sc, DMT_TCLR, sc->et_tclr);
+ am335x_dmtimer_et_write_4(sc, DMT_IRQENABLE_CLR, DMT_IRQ_OVF);
+ am335x_dmtimer_et_write_4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
+ return (0);
+}
+
+static int
+am335x_dmtimer_intr(void *arg)
+{
+ struct am335x_dmtimer_softc *sc;
+
+ sc = arg;
+
+ /* Ack the interrupt, and invoke the callback if it's still enabled. */
+ am335x_dmtimer_et_write_4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+
+ return (FILTER_HANDLED);
+}
+
+static int
+am335x_dmtimer_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "ti,am335x-dmtimer")) {
+ device_set_desc(dev, "AM335x DMTimer");
+ return(BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+am335x_dmtimer_attach(device_t dev)
+{
+ struct am335x_dmtimer_softc *sc;
+ void *ihl;
+ int err;
+
+ /*
+ * Note that if this routine returns an error status rather than running
+ * to completion it makes no attempt to clean up allocated resources;
+ * the system is essentially dead anyway without functional timers.
+ */
+
+ sc = device_get_softc(dev);
+
+ if (am335x_dmtimer_sc != NULL)
+ return (EINVAL);
+
+ /* Get the base clock frequency. */
+ err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq);
+ if (err) {
+ device_printf(dev, "Error: could not get sysclk frequency\n");
+ return (ENXIO);
+ }
+
+ /* Request the memory resources. */
+ err = bus_alloc_resources(dev, am335x_dmtimer_mem_spec,
+ sc->tmr_mem_res);
+ if (err) {
+ device_printf(dev, "Error: could not allocate mem resources\n");
+ return (ENXIO);
+ }
+
+ /* Request the IRQ resources. */
+ err = bus_alloc_resources(dev, am335x_dmtimer_irq_spec,
+ sc->tmr_irq_res);
+ if (err) {
+ device_printf(dev, "Error: could not allocate irq resources\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Use the default eventtimer. Let the PPS init routine decide which
+ * timer to use for the timecounter.
+ */
+ sc->et_num = DEFAULT_ET_TIMER;
+ sc->tc_num = am335x_dmtimer_pps_init(dev, sc);
+
+ sc->et_memres = sc->tmr_mem_res[sc->et_num];
+ sc->tc_memres = sc->tmr_mem_res[sc->tc_num];
+
+ /* Enable clocks and power on the chosen devices. */
+ err = ti_prcm_clk_set_source(DMTIMER0_CLK + sc->et_num, SYSCLK_CLK);
+ err |= ti_prcm_clk_enable(DMTIMER0_CLK + sc->et_num);
+ err |= ti_prcm_clk_set_source(DMTIMER0_CLK + sc->tc_num, SYSCLK_CLK);
+ err |= ti_prcm_clk_enable(DMTIMER0_CLK + sc->tc_num);
+ if (err) {
+ device_printf(dev, "Error: could not enable timer clock\n");
+ return (ENXIO);
+ }
+
+ /* Setup eventtimer interrupt handler. */
+ if (bus_setup_intr(dev, sc->tmr_irq_res[sc->et_num], INTR_TYPE_CLK,
+ am335x_dmtimer_intr, NULL, sc, &ihl) != 0) {
+ device_printf(dev, "Unable to setup the clock irq handler.\n");
+ return (ENXIO);
+ }
+
+ /* Set up timecounter, start it, register it. */
+ am335x_dmtimer_tc_write_4(sc, DMT_TSICR, DMT_TSICR_RESET);
+ while (am335x_dmtimer_tc_read_4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)
+ continue;
+
+ sc->tc_tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD;
+ am335x_dmtimer_tc_write_4(sc, DMT_TLDR, 0);
+ am335x_dmtimer_tc_write_4(sc, DMT_TCRR, 0);
+ am335x_dmtimer_tc_write_4(sc, DMT_TCLR, sc->tc_tclr);
+
+ sc->tc.tc_name = "AM335x Timecounter";
+ sc->tc.tc_get_timecount = am335x_dmtimer_tc_get_timecount;
+ sc->tc.tc_counter_mask = ~0u;
+ sc->tc.tc_frequency = sc->sysclk_freq;
+ sc->tc.tc_quality = 1000;
+ sc->tc.tc_priv = sc;
+ tc_init(&sc->tc);
+
+ sc->et.et_name = "AM335x Eventtimer";
+ sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
+ sc->et.et_quality = 1000;
+ sc->et.et_frequency = sc->sysclk_freq;
+ sc->et.et_min_period =
+ ((0x00000005LLU << 32) / sc->et.et_frequency);
+ sc->et.et_max_period =
+ (0xfffffffeLLU << 32) / sc->et.et_frequency;
+ sc->et.et_start = am335x_dmtimer_start;
+ sc->et.et_stop = am335x_dmtimer_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ /* Store a pointer to the softc for use in DELAY(). */
+ am335x_dmtimer_sc = sc;
+
+ return (0);
+}
+
+static device_method_t am335x_dmtimer_methods[] = {
+ DEVMETHOD(device_probe, am335x_dmtimer_probe),
+ DEVMETHOD(device_attach, am335x_dmtimer_attach),
+ { 0, 0 }
+};
+
+static driver_t am335x_dmtimer_driver = {
+ "am335x_dmtimer",
+ am335x_dmtimer_methods,
+ sizeof(struct am335x_dmtimer_softc),
+};
+
+static devclass_t am335x_dmtimer_devclass;
+
+DRIVER_MODULE(am335x_dmtimer, simplebus, am335x_dmtimer_driver, am335x_dmtimer_devclass, 0, 0);
+MODULE_DEPEND(am335x_dmtimer, am335x_prcm, 1, 1, 1);
+
+void
+DELAY(int usec)
+{
+ struct am335x_dmtimer_softc *sc;
+ int32_t counts;
+ uint32_t first, last;
+
+ sc = am335x_dmtimer_sc;
+
+ if (sc == NULL) {
+ for (; usec > 0; usec--)
+ for (counts = 200; counts > 0; counts--)
+ /* Prevent gcc from optimizing out the loop */
+ cpufunc_nullop();
+ return;
+ }
+
+ /* Get the number of times to count */
+ counts = (usec + 1) * (sc->sysclk_freq / 1000000);
+
+ first = am335x_dmtimer_tc_read_4(sc, DMT_TCRR);
+
+ while (counts > 0) {
+ last = am335x_dmtimer_tc_read_4(sc, DMT_TCRR);
+ if (last > first) {
+ counts -= (int32_t)(last - first);
+ } else {
+ counts -= (int32_t)((0xFFFFFFFF - first) + last);
+ }
+ first = last;
+ }
+}
+
Property changes on: trunk/sys/arm/ti/am335x/am335x_dmtimer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_lcd.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_lcd.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_lcd.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,693 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2013 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_lcd.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/clock.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+/* syscons bits */
+#include <sys/fbio.h>
+#include <sys/consio.h>
+
+#include <machine/bus.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_scm.h>
+
+#include "am335x_lcd.h"
+#include "am335x_pwm.h"
+
+#define LCD_PID 0x00
+#define LCD_CTRL 0x04
+#define CTRL_DIV_MASK 0xff
+#define CTRL_DIV_SHIFT 8
+#define CTRL_AUTO_UFLOW_RESTART (1 << 1)
+#define CTRL_RASTER_MODE 1
+#define CTRL_LIDD_MODE 0
+#define LCD_LIDD_CTRL 0x0C
+#define LCD_LIDD_CS0_CONF 0x10
+#define LCD_LIDD_CS0_ADDR 0x14
+#define LCD_LIDD_CS0_DATA 0x18
+#define LCD_LIDD_CS1_CONF 0x1C
+#define LCD_LIDD_CS1_ADDR 0x20
+#define LCD_LIDD_CS1_DATA 0x24
+#define LCD_RASTER_CTRL 0x28
+#define RASTER_CTRL_TFT24_UNPACKED (1 << 26)
+#define RASTER_CTRL_TFT24 (1 << 25)
+#define RASTER_CTRL_STN565 (1 << 24)
+#define RASTER_CTRL_TFTPMAP (1 << 23)
+#define RASTER_CTRL_NIBMODE (1 << 22)
+#define RASTER_CTRL_PALMODE_SHIFT 20
+#define PALETTE_PALETTE_AND_DATA 0x00
+#define PALETTE_PALETTE_ONLY 0x01
+#define PALETTE_DATA_ONLY 0x02
+#define RASTER_CTRL_REQDLY_SHIFT 12
+#define RASTER_CTRL_MONO8B (1 << 9)
+#define RASTER_CTRL_RBORDER (1 << 8)
+#define RASTER_CTRL_LCDTFT (1 << 7)
+#define RASTER_CTRL_LCDBW (1 << 1)
+#define RASTER_CTRL_LCDEN (1 << 0)
+#define LCD_RASTER_TIMING_0 0x2C
+#define RASTER_TIMING_0_HBP_SHIFT 24
+#define RASTER_TIMING_0_HFP_SHIFT 16
+#define RASTER_TIMING_0_HSW_SHIFT 10
+#define RASTER_TIMING_0_PPLLSB_SHIFT 4
+#define RASTER_TIMING_0_PPLMSB_SHIFT 3
+#define LCD_RASTER_TIMING_1 0x30
+#define RASTER_TIMING_1_VBP_SHIFT 24
+#define RASTER_TIMING_1_VFP_SHIFT 16
+#define RASTER_TIMING_1_VSW_SHIFT 10
+#define RASTER_TIMING_1_LPP_SHIFT 0
+#define LCD_RASTER_TIMING_2 0x34
+#define RASTER_TIMING_2_HSWHI_SHIFT 27
+#define RASTER_TIMING_2_LPP_B10_SHIFT 26
+#define RASTER_TIMING_2_PHSVS (1 << 25)
+#define RASTER_TIMING_2_PHSVS_RISE (1 << 24)
+#define RASTER_TIMING_2_PHSVS_FALL (0 << 24)
+#define RASTER_TIMING_2_IOE (1 << 23)
+#define RASTER_TIMING_2_IPC (1 << 22)
+#define RASTER_TIMING_2_IHS (1 << 21)
+#define RASTER_TIMING_2_IVS (1 << 20)
+#define RASTER_TIMING_2_ACBI_SHIFT 16
+#define RASTER_TIMING_2_ACB_SHIFT 8
+#define RASTER_TIMING_2_HBPHI_SHIFT 4
+#define RASTER_TIMING_2_HFPHI_SHIFT 0
+#define LCD_RASTER_SUBPANEL 0x38
+#define LCD_RASTER_SUBPANEL2 0x3C
+#define LCD_LCDDMA_CTRL 0x40
+#define LCDDMA_CTRL_DMA_MASTER_PRIO_SHIFT 16
+#define LCDDMA_CTRL_TH_FIFO_RDY_SHIFT 8
+#define LCDDMA_CTRL_BURST_SIZE_SHIFT 4
+#define LCDDMA_CTRL_BYTES_SWAP (1 << 3)
+#define LCDDMA_CTRL_BE (1 << 1)
+#define LCDDMA_CTRL_FB0_ONLY 0
+#define LCDDMA_CTRL_FB0_FB1 (1 << 0)
+#define LCD_LCDDMA_FB0_BASE 0x44
+#define LCD_LCDDMA_FB0_CEILING 0x48
+#define LCD_LCDDMA_FB1_BASE 0x4C
+#define LCD_LCDDMA_FB1_CEILING 0x50
+#define LCD_SYSCONFIG 0x54
+#define SYSCONFIG_STANDBY_FORCE (0 << 4)
+#define SYSCONFIG_STANDBY_NONE (1 << 4)
+#define SYSCONFIG_STANDBY_SMART (2 << 4)
+#define SYSCONFIG_IDLE_FORCE (0 << 2)
+#define SYSCONFIG_IDLE_NONE (1 << 2)
+#define SYSCONFIG_IDLE_SMART (2 << 2)
+#define LCD_IRQSTATUS_RAW 0x58
+#define LCD_IRQSTATUS 0x5C
+#define LCD_IRQENABLE_SET 0x60
+#define LCD_IRQENABLE_CLEAR 0x64
+#define IRQ_EOF1 (1 << 9)
+#define IRQ_EOF0 (1 << 8)
+#define IRQ_PL (1 << 6)
+#define IRQ_FUF (1 << 5)
+#define IRQ_ACB (1 << 3)
+#define IRQ_SYNC_LOST (1 << 2)
+#define IRQ_RASTER_DONE (1 << 1)
+#define IRQ_FRAME_DONE (1 << 0)
+#define LCD_CLKC_ENABLE 0x6C
+#define CLKC_ENABLE_DMA (1 << 2)
+#define CLKC_ENABLE_LDID (1 << 1)
+#define CLKC_ENABLE_CORE (1 << 0)
+#define LCD_CLKC_RESET 0x70
+#define CLKC_RESET_MAIN (1 << 3)
+#define CLKC_RESET_DMA (1 << 2)
+#define CLKC_RESET_LDID (1 << 1)
+#define CLKC_RESET_CORE (1 << 0)
+
+#define LCD_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define LCD_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define LCD_LOCK_INIT(_sc) mtx_init(&(_sc)->sc_mtx, \
+ device_get_nameunit(_sc->sc_dev), "am335x_lcd", MTX_DEF)
+#define LCD_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx);
+
+#define LCD_READ4(_sc, reg) bus_read_4((_sc)->sc_mem_res, reg);
+#define LCD_WRITE4(_sc, reg, value) \
+ bus_write_4((_sc)->sc_mem_res, reg, value);
+
+
+/* Backlight is controlled by eCAS interface on PWM unit 0 */
+#define PWM_UNIT 0
+#define PWM_PERIOD 100
+
+struct am335x_lcd_softc {
+ device_t sc_dev;
+ struct resource *sc_mem_res;
+ struct resource *sc_irq_res;
+ void *sc_intr_hl;
+ struct mtx sc_mtx;
+ int sc_backlight;
+ struct sysctl_oid *sc_oid;
+
+ /* Framebuffer */
+ bus_dma_tag_t sc_dma_tag;
+ bus_dmamap_t sc_dma_map;
+ size_t sc_fb_size;
+ bus_addr_t sc_fb_phys;
+ uint8_t *sc_fb_base;
+};
+
+static void
+am335x_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+
+ addr = (bus_addr_t*)arg;
+ *addr = segs[0].ds_addr;
+}
+
+static uint32_t
+am335x_lcd_calc_divisor(uint32_t reference, uint32_t freq)
+{
+ uint32_t div;
+ /* Raster mode case: divisors are in range from 2 to 255 */
+ for (div = 2; div < 255; div++)
+ if (reference/div <= freq)
+ return (div);
+
+ return (255);
+}
+
+static int
+am335x_lcd_sysctl_backlight(SYSCTL_HANDLER_ARGS)
+{
+ struct am335x_lcd_softc *sc = (struct am335x_lcd_softc*)arg1;
+ int error;
+ int backlight;
+
+ backlight = sc->sc_backlight;;
+ error = sysctl_handle_int(oidp, &backlight, 0, req);
+
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (backlight < 0)
+ backlight = 0;
+ if (backlight > 100)
+ backlight = 100;
+
+ LCD_LOCK(sc);
+ error = am335x_pwm_config_ecas(PWM_UNIT, PWM_PERIOD,
+ backlight*PWM_PERIOD/100);
+ if (error == 0)
+ sc->sc_backlight = backlight;
+ LCD_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+am335x_read_panel_property(device_t dev, const char *name, uint32_t *val)
+{
+ phandle_t node;
+ pcell_t cell;
+
+ node = ofw_bus_get_node(dev);
+ if ((OF_getprop(node, name, &cell, sizeof(cell))) <= 0) {
+ device_printf(dev, "missing '%s' attribute in LCD panel info\n",
+ name);
+ return (ENXIO);
+ }
+
+ *val = fdt32_to_cpu(cell);
+
+ return (0);
+}
+
+static int
+am335x_read_panel_info(device_t dev, struct panel_info *panel)
+{
+ int error;
+
+ error = 0;
+ if ((error = am335x_read_panel_property(dev,
+ "panel_width", &panel->panel_width)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_height", &panel->panel_height)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_hfp", &panel->panel_hfp)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_hbp", &panel->panel_hbp)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_hsw", &panel->panel_hsw)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_vfp", &panel->panel_vfp)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_vbp", &panel->panel_vbp)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_vsw", &panel->panel_vsw)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_pxl_clk", &panel->panel_pxl_clk)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "panel_invert_pxl_clk", &panel->panel_invert_pxl_clk)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "ac_bias", &panel->ac_bias)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "ac_bias_intrpt", &panel->ac_bias_intrpt)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "dma_burst_sz", &panel->dma_burst_sz)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "bpp", &panel->bpp)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "fdd", &panel->fdd)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "invert_line_clock", &panel->invert_line_clock)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "invert_frm_clock", &panel->invert_frm_clock)))
+ goto out;
+
+ if ((error = am335x_read_panel_property(dev,
+ "sync_edge", &panel->sync_edge)))
+ goto out;
+
+ error = am335x_read_panel_property(dev,
+ "sync_ctrl", &panel->sync_ctrl);
+
+out:
+ return (error);
+}
+
+static void
+am335x_lcd_intr(void *arg)
+{
+ struct am335x_lcd_softc *sc = arg;
+ uint32_t reg;
+
+ reg = LCD_READ4(sc, LCD_IRQSTATUS);
+ LCD_WRITE4(sc, LCD_IRQSTATUS, reg);
+
+ if (reg & IRQ_SYNC_LOST) {
+ reg = LCD_READ4(sc, LCD_RASTER_CTRL);
+ reg &= ~RASTER_CTRL_LCDEN;
+ LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
+
+ reg = LCD_READ4(sc, LCD_RASTER_CTRL);
+ reg |= RASTER_CTRL_LCDEN;
+ LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
+ return;
+ }
+
+ if (reg & IRQ_PL) {
+ reg = LCD_READ4(sc, LCD_RASTER_CTRL);
+ reg &= ~RASTER_CTRL_LCDEN;
+ LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
+
+ reg = LCD_READ4(sc, LCD_RASTER_CTRL);
+ reg |= RASTER_CTRL_LCDEN;
+ LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
+ return;
+ }
+
+ if (reg & IRQ_EOF0) {
+ LCD_WRITE4(sc, LCD_LCDDMA_FB0_BASE, sc->sc_fb_phys);
+ LCD_WRITE4(sc, LCD_LCDDMA_FB0_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
+ reg &= ~IRQ_EOF0;
+ }
+
+ if (reg & IRQ_EOF1) {
+ LCD_WRITE4(sc, LCD_LCDDMA_FB1_BASE, sc->sc_fb_phys);
+ LCD_WRITE4(sc, LCD_LCDDMA_FB1_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
+ reg &= ~IRQ_EOF1;
+ }
+
+ if (reg & IRQ_FUF) {
+ /* TODO: Handle FUF */
+ }
+
+ if (reg & IRQ_ACB) {
+ /* TODO: Handle ACB */
+ }
+}
+
+static int
+am335x_lcd_probe(device_t dev)
+{
+ int err;
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,am335x-lcd"))
+ return (ENXIO);
+
+ device_set_desc(dev, "AM335x LCD controller");
+
+ err = sc_probe_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD);
+ if (err != 0)
+ return (err);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+am335x_lcd_attach(device_t dev)
+{
+ struct am335x_lcd_softc *sc;
+ int rid;
+ int div;
+ struct panel_info panel;
+ uint32_t reg, timing0, timing1, timing2;
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree;
+ uint32_t burst_log;
+ int err;
+ size_t dma_size;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ if (am335x_read_panel_info(dev, &panel))
+ return (ENXIO);
+
+ int ref_freq = 0;
+ ti_prcm_clk_enable(LCDC_CLK);
+ if (ti_prcm_clk_get_source_freq(LCDC_CLK, &ref_freq)) {
+ device_printf(dev, "Can't get reference frequency\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, am335x_lcd_intr, sc,
+ &sc->sc_intr_hl) != 0) {
+ bus_release_resource(dev, SYS_RES_IRQ, rid,
+ sc->sc_irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, rid,
+ sc->sc_mem_res);
+ device_printf(dev, "Unable to setup the irq handler.\n");
+ return (ENXIO);
+ }
+
+ LCD_LOCK_INIT(sc);
+
+ /* Panle initialization */
+ dma_size = round_page(panel.panel_width*panel.panel_height*panel.bpp/8);
+
+ /*
+ * Now allocate framebuffer memory
+ */
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(dev),
+ 4, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ dma_size, 1, /* maxsize, nsegments */
+ dma_size, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->sc_dma_tag);
+ if (err)
+ goto fail;
+
+ err = bus_dmamem_alloc(sc->sc_dma_tag, (void **)&sc->sc_fb_base,
+ BUS_DMA_COHERENT, &sc->sc_dma_map);
+
+ if (err) {
+ device_printf(dev, "cannot allocate framebuffer\n");
+ goto fail;
+ }
+
+ err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, sc->sc_fb_base,
+ dma_size, am335x_fb_dmamap_cb, &sc->sc_fb_phys, BUS_DMA_NOWAIT);
+
+ if (err) {
+ device_printf(dev, "cannot load DMA map\n");
+ goto fail;
+ }
+
+ /* Make sure it's blank */
+ memset(sc->sc_fb_base, 0x00, dma_size);
+
+ /* Calculate actual FB Size */
+ sc->sc_fb_size = panel.panel_width*panel.panel_height*panel.bpp/8;
+
+ /* Only raster mode is supported */
+ reg = CTRL_RASTER_MODE;
+ div = am335x_lcd_calc_divisor(ref_freq, panel.panel_pxl_clk);
+ reg |= (div << CTRL_DIV_SHIFT);
+ LCD_WRITE4(sc, LCD_CTRL, reg);
+
+ /* Set timing */
+ timing0 = timing1 = timing2 = 0;
+
+ /* Horizontal back porch */
+ timing0 |= (panel.panel_hbp & 0xff) << RASTER_TIMING_0_HBP_SHIFT;
+ timing2 |= ((panel.panel_hbp >> 8) & 3) << RASTER_TIMING_2_HBPHI_SHIFT;
+ /* Horizontal front porch */
+ timing0 |= (panel.panel_hfp & 0xff) << RASTER_TIMING_0_HFP_SHIFT;
+ timing2 |= ((panel.panel_hfp >> 8) & 3) << RASTER_TIMING_2_HFPHI_SHIFT;
+ /* Horizontal sync width */
+ timing0 |= (panel.panel_hsw & 0x3f) << RASTER_TIMING_0_HSW_SHIFT;
+ timing2 |= ((panel.panel_hsw >> 6) & 0xf) << RASTER_TIMING_2_HSWHI_SHIFT;
+
+ /* Vertical back porch, front porch, sync width */
+ timing1 |= (panel.panel_vbp & 0xff) << RASTER_TIMING_1_VBP_SHIFT;
+ timing1 |= (panel.panel_vfp & 0xff) << RASTER_TIMING_1_VFP_SHIFT;
+ timing1 |= (panel.panel_vsw & 0x3f) << RASTER_TIMING_1_VSW_SHIFT;
+
+ /* Pixels per line */
+ timing0 |= (((panel.panel_width - 1) >> 10) & 1)
+ << RASTER_TIMING_0_PPLMSB_SHIFT;
+ timing0 |= (((panel.panel_width - 1) >> 4) & 0x3f)
+ << RASTER_TIMING_0_PPLLSB_SHIFT;
+
+ /* Lines per panel */
+ timing1 |= ((panel.panel_height - 1) & 0x3ff)
+ << RASTER_TIMING_1_LPP_SHIFT;
+ timing2 |= (((panel.panel_height - 1) >> 10 ) & 1)
+ << RASTER_TIMING_2_LPP_B10_SHIFT;
+
+ /* clock signal settings */
+ if (panel.sync_ctrl)
+ timing2 |= RASTER_TIMING_2_PHSVS;
+ if (panel.sync_edge)
+ timing2 |= RASTER_TIMING_2_PHSVS_RISE;
+ else
+ timing2 |= RASTER_TIMING_2_PHSVS_FALL;
+ if (panel.invert_line_clock)
+ timing2 |= RASTER_TIMING_2_IHS;
+ if (panel.invert_frm_clock)
+ timing2 |= RASTER_TIMING_2_IVS;
+ if (panel.panel_invert_pxl_clk)
+ timing2 |= RASTER_TIMING_2_IPC;
+
+ /* AC bias */
+ timing2 |= (panel.ac_bias << RASTER_TIMING_2_ACB_SHIFT);
+ timing2 |= (panel.ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT);
+
+ LCD_WRITE4(sc, LCD_RASTER_TIMING_0, timing0);
+ LCD_WRITE4(sc, LCD_RASTER_TIMING_1, timing1);
+ LCD_WRITE4(sc, LCD_RASTER_TIMING_2, timing2);
+
+ /* DMA settings */
+ reg = LCDDMA_CTRL_FB0_FB1;
+ /* Find power of 2 for current burst size */
+ switch (panel.dma_burst_sz) {
+ case 1:
+ burst_log = 0;
+ break;
+ case 2:
+ burst_log = 1;
+ break;
+ case 4:
+ burst_log = 2;
+ break;
+ case 8:
+ burst_log = 3;
+ break;
+ case 16:
+ default:
+ burst_log = 4;
+ break;
+ }
+ reg |= (burst_log << LCDDMA_CTRL_BURST_SIZE_SHIFT);
+ /* XXX: FIFO TH */
+ reg |= (0 << LCDDMA_CTRL_TH_FIFO_RDY_SHIFT);
+ LCD_WRITE4(sc, LCD_LCDDMA_CTRL, reg);
+
+ LCD_WRITE4(sc, LCD_LCDDMA_FB0_BASE, sc->sc_fb_phys);
+ LCD_WRITE4(sc, LCD_LCDDMA_FB0_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
+ LCD_WRITE4(sc, LCD_LCDDMA_FB1_BASE, sc->sc_fb_phys);
+ LCD_WRITE4(sc, LCD_LCDDMA_FB1_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
+
+ /* Enable LCD */
+ reg = RASTER_CTRL_LCDTFT;
+ reg |= (panel.fdd << RASTER_CTRL_REQDLY_SHIFT);
+ reg |= (PALETTE_DATA_ONLY << RASTER_CTRL_PALMODE_SHIFT);
+ if (panel.bpp >= 24)
+ reg |= RASTER_CTRL_TFT24;
+ if (panel.bpp == 32)
+ reg |= RASTER_CTRL_TFT24_UNPACKED;
+ LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
+
+ LCD_WRITE4(sc, LCD_CLKC_ENABLE,
+ CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE);
+
+ LCD_WRITE4(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN);
+ DELAY(100);
+ LCD_WRITE4(sc, LCD_CLKC_RESET, 0);
+
+ reg = IRQ_EOF1 | IRQ_EOF0 | IRQ_FUF | IRQ_PL |
+ IRQ_ACB | IRQ_SYNC_LOST | IRQ_RASTER_DONE |
+ IRQ_FRAME_DONE;
+ LCD_WRITE4(sc, LCD_IRQENABLE_SET, reg);
+
+ reg = LCD_READ4(sc, LCD_RASTER_CTRL);
+ reg |= RASTER_CTRL_LCDEN;
+ LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
+
+ LCD_WRITE4(sc, LCD_SYSCONFIG,
+ SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART);
+
+ /* Init backlight interface */
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ tree = device_get_sysctl_tree(sc->sc_dev);
+ sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ am335x_lcd_sysctl_backlight, "I", "LCD backlight");
+ sc->sc_backlight = 0;
+ /* Check if eCAS interface is available at this point */
+ if (am335x_pwm_config_ecas(PWM_UNIT,
+ PWM_PERIOD, PWM_PERIOD) == 0)
+ sc->sc_backlight = 100;
+
+ err = (sc_attach_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD));
+
+ if (err) {
+ device_printf(dev, "failed to attach syscons\n");
+ goto fail;
+ }
+
+ am335x_lcd_syscons_setup((vm_offset_t)sc->sc_fb_base, sc->sc_fb_phys, &panel);
+
+ return (0);
+
+fail:
+ return (err);
+}
+
+static int
+am335x_lcd_detach(device_t dev)
+{
+ /* Do not let unload driver */
+ return (EBUSY);
+}
+
+static device_method_t am335x_lcd_methods[] = {
+ DEVMETHOD(device_probe, am335x_lcd_probe),
+ DEVMETHOD(device_attach, am335x_lcd_attach),
+ DEVMETHOD(device_detach, am335x_lcd_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t am335x_lcd_driver = {
+ "am335x_lcd",
+ am335x_lcd_methods,
+ sizeof(struct am335x_lcd_softc),
+};
+
+static devclass_t am335x_lcd_devclass;
+
+DRIVER_MODULE(am335x_lcd, simplebus, am335x_lcd_driver, am335x_lcd_devclass, 0, 0);
+MODULE_VERSION(am335x_lcd, 1);
+MODULE_DEPEND(am335x_lcd, simplebus, 1, 1, 1);
Property changes on: trunk/sys/arm/ti/am335x/am335x_lcd.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_lcd.h
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_lcd.h (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_lcd.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,57 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/am335x/am335x_lcd.h 251018 2013-05-27 00:23:01Z gonzo $
+ */
+#ifndef __AM335X_LCD_H__
+#define __AM335X_LCD_H__
+
+struct panel_info {
+ uint32_t panel_width;
+ uint32_t panel_height;
+ uint32_t panel_hfp;
+ uint32_t panel_hbp;
+ uint32_t panel_hsw;
+ uint32_t panel_vfp;
+ uint32_t panel_vbp;
+ uint32_t panel_vsw;
+ uint32_t ac_bias;
+ uint32_t ac_bias_intrpt;
+ uint32_t dma_burst_sz;
+ uint32_t bpp;
+ uint32_t fdd;
+ uint32_t invert_line_clock;
+ uint32_t invert_frm_clock;
+ uint32_t sync_edge;
+ uint32_t sync_ctrl;
+ uint32_t panel_pxl_clk;
+ uint32_t panel_invert_pxl_clk;
+};
+
+int am335x_lcd_syscons_setup(vm_offset_t vaddr, vm_paddr_t paddr,
+ struct panel_info *panel);
+
+#endif /* __AM335X_LCD_H__ */
Property changes on: trunk/sys/arm/ti/am335x/am335x_lcd.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_lcd_syscons.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_lcd_syscons.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_lcd_syscons.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,793 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_lcd_syscons.c 259329 2013-12-13 20:43:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#include "am335x_lcd.h"
+
+struct video_adapter_softc {
+ /* Videoadpater part */
+ video_adapter_t va;
+ int console;
+
+ intptr_t fb_addr;
+ intptr_t fb_paddr;
+ unsigned int fb_size;
+
+ unsigned int height;
+ unsigned int width;
+ unsigned int depth;
+ unsigned int stride;
+
+ unsigned int xmargin;
+ unsigned int ymargin;
+
+ unsigned char *font;
+ int initialized;
+};
+
+struct argb {
+ uint8_t a;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+};
+
+static struct argb am335x_syscons_palette[16] = {
+ {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0xaa},
+ {0x00, 0x00, 0xaa, 0x00},
+ {0x00, 0x00, 0xaa, 0xaa},
+ {0x00, 0xaa, 0x00, 0x00},
+ {0x00, 0xaa, 0x00, 0xaa},
+ {0x00, 0xaa, 0x55, 0x00},
+ {0x00, 0xaa, 0xaa, 0xaa},
+ {0x00, 0x55, 0x55, 0x55},
+ {0x00, 0x55, 0x55, 0xff},
+ {0x00, 0x55, 0xff, 0x55},
+ {0x00, 0x55, 0xff, 0xff},
+ {0x00, 0xff, 0x55, 0x55},
+ {0x00, 0xff, 0x55, 0xff},
+ {0x00, 0xff, 0xff, 0x55},
+ {0x00, 0xff, 0xff, 0xff}
+};
+
+/* mouse pointer from dev/syscons/scgfbrndr.c */
+static u_char mouse_pointer[16] = {
+ 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
+ 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
+};
+
+#define AM335X_FONT_HEIGHT 16
+
+#define FB_WIDTH 640
+#define FB_HEIGHT 480
+#define FB_DEPTH 24
+
+static struct video_adapter_softc va_softc;
+
+static int am335x_syscons_configure(int flags);
+
+/*
+ * Video driver routines and glue.
+ */
+static vi_probe_t am335x_syscons_probe;
+static vi_init_t am335x_syscons_init;
+static vi_get_info_t am335x_syscons_get_info;
+static vi_query_mode_t am335x_syscons_query_mode;
+static vi_set_mode_t am335x_syscons_set_mode;
+static vi_save_font_t am335x_syscons_save_font;
+static vi_load_font_t am335x_syscons_load_font;
+static vi_show_font_t am335x_syscons_show_font;
+static vi_save_palette_t am335x_syscons_save_palette;
+static vi_load_palette_t am335x_syscons_load_palette;
+static vi_set_border_t am335x_syscons_set_border;
+static vi_save_state_t am335x_syscons_save_state;
+static vi_load_state_t am335x_syscons_load_state;
+static vi_set_win_org_t am335x_syscons_set_win_org;
+static vi_read_hw_cursor_t am335x_syscons_read_hw_cursor;
+static vi_set_hw_cursor_t am335x_syscons_set_hw_cursor;
+static vi_set_hw_cursor_shape_t am335x_syscons_set_hw_cursor_shape;
+static vi_blank_display_t am335x_syscons_blank_display;
+static vi_mmap_t am335x_syscons_mmap;
+static vi_ioctl_t am335x_syscons_ioctl;
+static vi_clear_t am335x_syscons_clear;
+static vi_fill_rect_t am335x_syscons_fill_rect;
+static vi_bitblt_t am335x_syscons_bitblt;
+static vi_diag_t am335x_syscons_diag;
+static vi_save_cursor_palette_t am335x_syscons_save_cursor_palette;
+static vi_load_cursor_palette_t am335x_syscons_load_cursor_palette;
+static vi_copy_t am335x_syscons_copy;
+static vi_putp_t am335x_syscons_putp;
+static vi_putc_t am335x_syscons_putc;
+static vi_puts_t am335x_syscons_puts;
+static vi_putm_t am335x_syscons_putm;
+
+static video_switch_t am335x_sysconsvidsw = {
+ .probe = am335x_syscons_probe,
+ .init = am335x_syscons_init,
+ .get_info = am335x_syscons_get_info,
+ .query_mode = am335x_syscons_query_mode,
+ .set_mode = am335x_syscons_set_mode,
+ .save_font = am335x_syscons_save_font,
+ .load_font = am335x_syscons_load_font,
+ .show_font = am335x_syscons_show_font,
+ .save_palette = am335x_syscons_save_palette,
+ .load_palette = am335x_syscons_load_palette,
+ .set_border = am335x_syscons_set_border,
+ .save_state = am335x_syscons_save_state,
+ .load_state = am335x_syscons_load_state,
+ .set_win_org = am335x_syscons_set_win_org,
+ .read_hw_cursor = am335x_syscons_read_hw_cursor,
+ .set_hw_cursor = am335x_syscons_set_hw_cursor,
+ .set_hw_cursor_shape = am335x_syscons_set_hw_cursor_shape,
+ .blank_display = am335x_syscons_blank_display,
+ .mmap = am335x_syscons_mmap,
+ .ioctl = am335x_syscons_ioctl,
+ .clear = am335x_syscons_clear,
+ .fill_rect = am335x_syscons_fill_rect,
+ .bitblt = am335x_syscons_bitblt,
+ .diag = am335x_syscons_diag,
+ .save_cursor_palette = am335x_syscons_save_cursor_palette,
+ .load_cursor_palette = am335x_syscons_load_cursor_palette,
+ .copy = am335x_syscons_copy,
+ .putp = am335x_syscons_putp,
+ .putc = am335x_syscons_putc,
+ .puts = am335x_syscons_puts,
+ .putm = am335x_syscons_putm,
+};
+
+VIDEO_DRIVER(am335x_syscons, am335x_sysconsvidsw, am335x_syscons_configure);
+
+static vr_init_t am335x_rend_init;
+static vr_clear_t am335x_rend_clear;
+static vr_draw_border_t am335x_rend_draw_border;
+static vr_draw_t am335x_rend_draw;
+static vr_set_cursor_t am335x_rend_set_cursor;
+static vr_draw_cursor_t am335x_rend_draw_cursor;
+static vr_blink_cursor_t am335x_rend_blink_cursor;
+static vr_set_mouse_t am335x_rend_set_mouse;
+static vr_draw_mouse_t am335x_rend_draw_mouse;
+
+/*
+ * We use our own renderer; this is because we must emulate a hardware
+ * cursor.
+ */
+static sc_rndr_sw_t am335x_rend = {
+ am335x_rend_init,
+ am335x_rend_clear,
+ am335x_rend_draw_border,
+ am335x_rend_draw,
+ am335x_rend_set_cursor,
+ am335x_rend_draw_cursor,
+ am335x_rend_blink_cursor,
+ am335x_rend_set_mouse,
+ am335x_rend_draw_mouse
+};
+
+RENDERER(am335x_syscons, 0, am335x_rend, gfb_set);
+RENDERER_MODULE(am335x_syscons, gfb_set);
+
+static void
+am335x_rend_init(scr_stat* scp)
+{
+}
+
+static void
+am335x_rend_clear(scr_stat* scp, int c, int attr)
+{
+}
+
+static void
+am335x_rend_draw_border(scr_stat* scp, int color)
+{
+}
+
+static void
+am335x_rend_draw(scr_stat* scp, int from, int count, int flip)
+{
+ video_adapter_t* adp = scp->sc->adp;
+ int i, c, a;
+
+ if (!flip) {
+ /* Normal printing */
+ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count);
+ } else {
+ /* This is for selections and such: invert the color attribute */
+ for (i = count; i-- > 0; ++from) {
+ c = sc_vtb_getc(&scp->vtb, from);
+ a = sc_vtb_geta(&scp->vtb, from) >> 8;
+ vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4));
+ }
+ }
+}
+
+static void
+am335x_rend_set_cursor(scr_stat* scp, int base, int height, int blink)
+{
+}
+
+static void
+am335x_rend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip)
+{
+ video_adapter_t* adp = scp->sc->adp;
+ struct video_adapter_softc *sc;
+ int row, col;
+ uint8_t *addr;
+ int i, j, bytes;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ if (scp->curs_attr.height <= 0)
+ return;
+
+ if (sc->fb_addr == 0)
+ return;
+
+ if (off >= adp->va_info.vi_width * adp->va_info.vi_height)
+ return;
+
+ /* calculate the coordinates in the video buffer */
+ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+ col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+
+ addr = (uint8_t *)sc->fb_addr
+ + (row + sc->ymargin)*(sc->stride)
+ + (sc->depth/8) * (col + sc->xmargin);
+
+ bytes = sc->depth/8;
+
+ /* our cursor consists of simply inverting the char under it */
+ for (i = 0; i < adp->va_info.vi_cheight; i++) {
+ for (j = 0; j < adp->va_info.vi_cwidth; j++) {
+ switch (sc->depth) {
+ case 32:
+ case 24:
+ addr[bytes*j + 2] ^= 0xff;
+ /* FALLTHROUGH */
+ case 16:
+ addr[bytes*j + 1] ^= 0xff;
+ addr[bytes*j] ^= 0xff;
+ break;
+ default:
+ break;
+ }
+ }
+
+ addr += sc->stride;
+ }
+}
+
+static void
+am335x_rend_blink_cursor(scr_stat* scp, int at, int flip)
+{
+}
+
+static void
+am335x_rend_set_mouse(scr_stat* scp)
+{
+}
+
+static void
+am335x_rend_draw_mouse(scr_stat* scp, int x, int y, int on)
+{
+ vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8);
+}
+
+static uint16_t am335x_syscons_static_window[ROW*COL];
+extern u_char dflt_font_16[];
+
+/*
+ * Update videoadapter settings after changing resolution
+ */
+static void
+am335x_syscons_update_margins(video_adapter_t *adp)
+{
+ struct video_adapter_softc *sc;
+ video_info_t *vi;
+
+ sc = (struct video_adapter_softc *)adp;
+ vi = &adp->va_info;
+
+ sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
+}
+
+static phandle_t
+am335x_syscons_find_panel_node(phandle_t start)
+{
+ phandle_t child;
+ phandle_t result;
+
+ for (child = OF_child(start); child != 0; child = OF_peer(child)) {
+ if (fdt_is_compatible(child, "ti,am335x-lcd"))
+ return (child);
+ if ((result = am335x_syscons_find_panel_node(child)))
+ return (result);
+ }
+
+ return (0);
+}
+
+static int
+am335x_syscons_configure(int flags)
+{
+ struct video_adapter_softc *va_sc;
+
+ va_sc = &va_softc;
+ phandle_t display, root;
+ pcell_t cell;
+
+ if (va_sc->initialized)
+ return (0);
+
+ va_sc->width = 0;
+ va_sc->height = 0;
+
+ /*
+ * It seems there is no way to let syscons framework know
+ * that framebuffer resolution has changed. So just try
+ * to fetch data from FDT and go with defaults if failed
+ */
+ root = OF_finddevice("/");
+ if ((root != 0) &&
+ (display = am335x_syscons_find_panel_node(root))) {
+ if ((OF_getprop(display, "panel_width",
+ &cell, sizeof(cell))) > 0)
+ va_sc->width = (int)fdt32_to_cpu(cell);
+
+ if ((OF_getprop(display, "panel_height",
+ &cell, sizeof(cell))) > 0)
+ va_sc->height = (int)fdt32_to_cpu(cell);
+ }
+
+ if (va_sc->width == 0)
+ va_sc->width = FB_WIDTH;
+ if (va_sc->height == 0)
+ va_sc->height = FB_HEIGHT;
+
+ am335x_syscons_init(0, &va_sc->va, 0);
+
+ va_sc->initialized = 1;
+
+ return (0);
+}
+
+static int
+am335x_syscons_probe(int unit, video_adapter_t **adp, void *arg, int flags)
+{
+
+ return (0);
+}
+
+static int
+am335x_syscons_init(int unit, video_adapter_t *adp, int flags)
+{
+ struct video_adapter_softc *sc;
+ video_info_t *vi;
+
+ sc = (struct video_adapter_softc *)adp;
+ vi = &adp->va_info;
+
+ vid_init_struct(adp, "am335x_syscons", -1, unit);
+
+ sc->font = dflt_font_16;
+ vi->vi_cheight = AM335X_FONT_HEIGHT;
+ vi->vi_cwidth = 8;
+
+ vi->vi_width = sc->width/8;
+ vi->vi_height = sc->height/vi->vi_cheight;
+
+ /*
+ * Clamp width/height to syscons maximums
+ */
+ if (vi->vi_width > COL)
+ vi->vi_width = COL;
+ if (vi->vi_height > ROW)
+ vi->vi_height = ROW;
+
+ sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
+
+
+ adp->va_window = (vm_offset_t) am335x_syscons_static_window;
+ adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
+
+ vid_register(&sc->va);
+
+ return (0);
+}
+
+static int
+am335x_syscons_get_info(video_adapter_t *adp, int mode, video_info_t *info)
+{
+ bcopy(&adp->va_info, info, sizeof(*info));
+ return (0);
+}
+
+static int
+am335x_syscons_query_mode(video_adapter_t *adp, video_info_t *info)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_set_mode(video_adapter_t *adp, int mode)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_save_font(video_adapter_t *adp, int page, int size, int width,
+ u_char *data, int c, int count)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_load_font(video_adapter_t *adp, int page, int size, int width,
+ u_char *data, int c, int count)
+{
+ struct video_adapter_softc *sc = (struct video_adapter_softc *)adp;
+
+ sc->font = data;
+
+ return (0);
+}
+
+static int
+am335x_syscons_show_font(video_adapter_t *adp, int page)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_save_palette(video_adapter_t *adp, u_char *palette)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_load_palette(video_adapter_t *adp, u_char *palette)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_set_border(video_adapter_t *adp, int border)
+{
+ return (am335x_syscons_blank_display(adp, border));
+}
+
+static int
+am335x_syscons_save_state(video_adapter_t *adp, void *p, size_t size)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_load_state(video_adapter_t *adp, void *p)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_set_win_org(video_adapter_t *adp, off_t offset)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
+{
+ *col = *row = 0;
+
+ return (0);
+}
+
+static int
+am335x_syscons_set_hw_cursor(video_adapter_t *adp, int col, int row)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
+ int celsize, int blink)
+{
+ return (0);
+}
+
+static int
+am335x_syscons_blank_display(video_adapter_t *adp, int mode)
+{
+
+ struct video_adapter_softc *sc;
+
+ sc = (struct video_adapter_softc *)adp;
+ if (sc && sc->fb_addr)
+ memset((void*)sc->fb_addr, 0, sc->fb_size);
+
+ return (0);
+}
+
+static int
+am335x_syscons_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int prot, vm_memattr_t *memattr)
+{
+ struct video_adapter_softc *sc;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ /*
+ * This might be a legacy VGA mem request: if so, just point it at the
+ * framebuffer, since it shouldn't be touched
+ */
+ if (offset < sc->stride*sc->height) {
+ *paddr = sc->fb_paddr + offset;
+ return (0);
+ }
+
+ return (EINVAL);
+}
+
+static int
+am335x_syscons_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
+{
+ struct video_adapter_softc *sc;
+ struct fbtype *fb;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ switch (cmd) {
+ case FBIOGTYPE:
+ fb = (struct fbtype *)data;
+ fb->fb_type = FBTYPE_PCIMISC;
+ fb->fb_height = sc->height;
+ fb->fb_width = sc->width;
+ fb->fb_depth = sc->depth;
+ if (sc->depth <= 1 || sc->depth > 8)
+ fb->fb_cmsize = 0;
+ else
+ fb->fb_cmsize = 1 << sc->depth;
+ fb->fb_size = sc->fb_size;
+ break;
+ default:
+ return (fb_commonioctl(adp, cmd, data));
+ }
+
+ return (0);
+}
+
+static int
+am335x_syscons_clear(video_adapter_t *adp)
+{
+
+ return (am335x_syscons_blank_display(adp, 0));
+}
+
+static int
+am335x_syscons_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+
+ return (0);
+}
+
+static int
+am335x_syscons_bitblt(video_adapter_t *adp, ...)
+{
+
+ return (0);
+}
+
+static int
+am335x_syscons_diag(video_adapter_t *adp, int level)
+{
+
+ return (0);
+}
+
+static int
+am335x_syscons_save_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+am335x_syscons_load_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+am335x_syscons_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
+{
+
+ return (0);
+}
+
+static int
+am335x_syscons_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
+ int size, int bpp, int bit_ltor, int byte_ltor)
+{
+
+ return (0);
+}
+
+static int
+am335x_syscons_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+{
+ struct video_adapter_softc *sc;
+ int row;
+ int col;
+ int i, j, k;
+ uint8_t *addr;
+ u_char *p;
+ uint8_t fg, bg, color;
+ uint16_t rgb;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ if (sc->fb_addr == 0)
+ return (0);
+
+ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+ col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+ p = sc->font + c*AM335X_FONT_HEIGHT;
+ addr = (uint8_t *)sc->fb_addr
+ + (row + sc->ymargin)*(sc->stride)
+ + (sc->depth/8) * (col + sc->xmargin);
+
+ fg = a & 0xf ;
+ bg = (a >> 4) & 0xf;
+
+ for (i = 0; i < AM335X_FONT_HEIGHT; i++) {
+ for (j = 0, k = 7; j < 8; j++, k--) {
+ if ((p[i] & (1 << k)) == 0)
+ color = bg;
+ else
+ color = fg;
+
+ switch (sc->depth) {
+ case 32:
+ addr[4*j+0] = am335x_syscons_palette[color].r;
+ addr[4*j+1] = am335x_syscons_palette[color].g;
+ addr[4*j+2] = am335x_syscons_palette[color].b;
+ addr[4*j+3] = am335x_syscons_palette[color].a;
+ break;
+ case 24:
+ addr[3*j] = am335x_syscons_palette[color].r;
+ addr[3*j+1] = am335x_syscons_palette[color].g;
+ addr[3*j+2] = am335x_syscons_palette[color].b;
+ break;
+ case 16:
+ rgb = (am335x_syscons_palette[color].r >> 3) << 11;
+ rgb |= (am335x_syscons_palette[color].g >> 2) << 5;
+ rgb |= (am335x_syscons_palette[color].b >> 3);
+ addr[2*j] = rgb & 0xff;
+ addr[2*j + 1] = (rgb >> 8) & 0xff;
+ default:
+ /* Not supported yet */
+ break;
+ }
+ }
+
+ addr += (sc->stride);
+ }
+
+ return (0);
+}
+
+static int
+am335x_syscons_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ am335x_syscons_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
+
+ return (0);
+}
+
+static int
+am335x_syscons_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+ uint32_t pixel_mask, int size, int width)
+{
+
+ return (0);
+}
+
+/* Initialization function */
+int am335x_lcd_syscons_setup(vm_offset_t vaddr, vm_paddr_t paddr,
+ struct panel_info *panel)
+{
+ struct video_adapter_softc *va_sc = &va_softc;
+
+ va_sc->fb_addr = vaddr;
+ va_sc->fb_paddr = paddr;
+ va_sc->depth = panel->bpp;
+ va_sc->stride = panel->bpp*panel->panel_width/8;
+
+ va_sc->width = panel->panel_width;
+ va_sc->height = panel->panel_height;
+ va_sc->fb_size = va_sc->width * va_sc->height
+ * va_sc->depth/8;
+ am335x_syscons_update_margins(&va_sc->va);
+
+ return (0);
+}
+
+/*
+ * Define a stub keyboard driver in case one hasn't been
+ * compiled into the kernel
+ */
+#include <sys/kbio.h>
+#include <dev/kbd/kbdreg.h>
+
+static int dummy_kbd_configure(int flags);
+
+keyboard_switch_t am335x_dummysw;
+
+static int
+dummy_kbd_configure(int flags)
+{
+
+ return (0);
+}
+KEYBOARD_DRIVER(am335x_dummy, am335x_dummysw, dummy_kbd_configure);
Property changes on: trunk/sys/arm/ti/am335x/am335x_lcd_syscons.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_pmic.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_pmic.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_pmic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,212 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_pmic.c 278079 2015-02-02 12:48:13Z loos $");
+/*
+* TPS65217 PMIC companion chip for AM335x SoC sitting on I2C bus
+*/
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/clock.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/reboot.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/am335x/am335x_rtcvar.h>
+
+#include "iicbus_if.h"
+
+#define TPS65217A 0x7
+#define TPS65217B 0xF
+#define TPS65217C 0xE
+#define TPS65217D 0x6
+
+/* TPS65217 Reisters */
+#define TPS65217_CHIPID_REG 0x00
+#define TPS65217_STATUS_REG 0x0A
+#define TPS65217_STATUS_OFF (1U << 7)
+#define TPS65217_STATUS_ACPWR (1U << 3)
+#define TPS65217_STATUS_USBPWR (1U << 2)
+#define TPS65217_STATUS_BT (1U << 0)
+
+#define MAX_IIC_DATA_SIZE 2
+
+
+struct am335x_pmic_softc {
+ device_t sc_dev;
+ uint32_t sc_addr;
+ struct intr_config_hook enum_hook;
+};
+
+static void am335x_pmic_shutdown(void *, int);
+
+static int
+am335x_pmic_read(device_t dev, uint8_t addr, uint8_t *data, uint8_t size)
+{
+ struct am335x_pmic_softc *sc = device_get_softc(dev);
+ struct iic_msg msg[] = {
+ { sc->sc_addr, IIC_M_WR, 1, &addr },
+ { sc->sc_addr, IIC_M_RD, size, data },
+ };
+ return (iicbus_transfer(dev, msg, 2));
+}
+
+static int
+am335x_pmic_write(device_t dev, uint8_t address, uint8_t *data, uint8_t size)
+{
+ uint8_t buffer[MAX_IIC_DATA_SIZE + 1];
+ struct am335x_pmic_softc *sc = device_get_softc(dev);
+ struct iic_msg msg[] = {
+ { sc->sc_addr, IIC_M_WR, size + 1, buffer },
+ };
+
+ if (size > MAX_IIC_DATA_SIZE)
+ return (ENOMEM);
+
+ buffer[0] = address;
+ memcpy(buffer + 1, data, size);
+
+ return (iicbus_transfer(dev, msg, 1));
+}
+
+static int
+am335x_pmic_probe(device_t dev)
+{
+ struct am335x_pmic_softc *sc;
+
+ if (!ofw_bus_is_compatible(dev, "ti,am335x-pmic"))
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_addr = iicbus_get_addr(dev);
+
+ device_set_desc(dev, "TI TPS65217 Power Management IC");
+
+ return (0);
+}
+
+static void
+am335x_pmic_start(void *xdev)
+{
+ struct am335x_pmic_softc *sc;
+ device_t dev = (device_t)xdev;
+ uint8_t reg;
+ char name[20];
+ char pwr[4][11] = {"Unknown", "USB", "AC", "USB and AC"};
+
+ sc = device_get_softc(dev);
+
+ am335x_pmic_read(dev, TPS65217_CHIPID_REG, ®, 1);
+ switch (reg>>4) {
+ case TPS65217A:
+ sprintf(name, "TPS65217A ver 1.%u", reg & 0xF);
+ break;
+ case TPS65217B:
+ sprintf(name, "TPS65217B ver 1.%u", reg & 0xF);
+ break;
+ case TPS65217C:
+ sprintf(name, "TPS65217C ver 1.%u", reg & 0xF);
+ break;
+ case TPS65217D:
+ sprintf(name, "TPS65217D ver 1.%u", reg & 0xF);
+ break;
+ default:
+ sprintf(name, "Unknown PMIC");
+ }
+
+ am335x_pmic_read(dev, TPS65217_STATUS_REG, ®, 1);
+ device_printf(dev, "%s powered by %s\n", name, pwr[(reg>>2)&0x03]);
+
+ EVENTHANDLER_REGISTER(shutdown_final, am335x_pmic_shutdown, dev,
+ SHUTDOWN_PRI_LAST);
+
+ config_intrhook_disestablish(&sc->enum_hook);
+}
+
+static int
+am335x_pmic_attach(device_t dev)
+{
+ struct am335x_pmic_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ sc->enum_hook.ich_func = am335x_pmic_start;
+ sc->enum_hook.ich_arg = dev;
+
+ if (config_intrhook_establish(&sc->enum_hook) != 0)
+ return (ENOMEM);
+
+ return (0);
+}
+
+static void
+am335x_pmic_shutdown(void *xdev, int howto)
+{
+ device_t dev;
+ uint8_t reg;
+
+ if (!(howto & RB_POWEROFF))
+ return;
+ dev = (device_t)xdev;
+ /* Set the OFF bit on status register to start the shutdown sequence. */
+ reg = TPS65217_STATUS_OFF;
+ am335x_pmic_write(dev, TPS65217_STATUS_REG, ®, 1);
+ /* Toggle pmic_pwr_enable to shutdown the PMIC. */
+ am335x_rtc_pmic_pwr_toggle();
+}
+
+static device_method_t am335x_pmic_methods[] = {
+ DEVMETHOD(device_probe, am335x_pmic_probe),
+ DEVMETHOD(device_attach, am335x_pmic_attach),
+ {0, 0},
+};
+
+static driver_t am335x_pmic_driver = {
+ "am335x_pmic",
+ am335x_pmic_methods,
+ sizeof(struct am335x_pmic_softc),
+};
+
+static devclass_t am335x_pmic_devclass;
+
+DRIVER_MODULE(am335x_pmic, iicbus, am335x_pmic_driver, am335x_pmic_devclass, 0, 0);
+MODULE_VERSION(am335x_pmic, 1);
+MODULE_DEPEND(am335x_pmic, iicbus, 1, 1, 1);
Property changes on: trunk/sys/arm/ti/am335x/am335x_pmic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_prcm.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_prcm.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_prcm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,799 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_prcm.c 278432 2015-02-09 02:49:10Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/ti/tivar.h>
+#include <arm/ti/ti_scm.h>
+#include <arm/ti/ti_prcm.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#define CM_PER 0
+#define CM_PER_L4LS_CLKSTCTRL (CM_PER + 0x000)
+#define CM_PER_L3S_CLKSTCTRL (CM_PER + 0x004)
+#define CM_PER_L3_CLKSTCTRL (CM_PER + 0x00C)
+#define CM_PER_CPGMAC0_CLKCTRL (CM_PER + 0x014)
+#define CM_PER_LCDC_CLKCTRL (CM_PER + 0x018)
+#define CM_PER_USB0_CLKCTRL (CM_PER + 0x01C)
+#define CM_PER_TPTC0_CLKCTRL (CM_PER + 0x024)
+#define CM_PER_UART5_CLKCTRL (CM_PER + 0x038)
+#define CM_PER_MMC0_CLKCTRL (CM_PER + 0x03C)
+#define CM_PER_I2C2_CLKCTRL (CM_PER + 0x044)
+#define CM_PER_I2C1_CLKCTRL (CM_PER + 0x048)
+#define CM_PER_UART1_CLKCTRL (CM_PER + 0x06C)
+#define CM_PER_UART2_CLKCTRL (CM_PER + 0x070)
+#define CM_PER_UART3_CLKCTRL (CM_PER + 0x074)
+#define CM_PER_UART4_CLKCTRL (CM_PER + 0x078)
+#define CM_PER_TIMER7_CLKCTRL (CM_PER + 0x07C)
+#define CM_PER_TIMER2_CLKCTRL (CM_PER + 0x080)
+#define CM_PER_TIMER3_CLKCTRL (CM_PER + 0x084)
+#define CM_PER_TIMER4_CLKCTRL (CM_PER + 0x088)
+#define CM_PER_GPIO1_CLKCTRL (CM_PER + 0x0AC)
+#define CM_PER_GPIO2_CLKCTRL (CM_PER + 0x0B0)
+#define CM_PER_GPIO3_CLKCTRL (CM_PER + 0x0B4)
+#define CM_PER_TPCC_CLKCTRL (CM_PER + 0x0BC)
+#define CM_PER_EPWMSS1_CLKCTRL (CM_PER + 0x0CC)
+#define CM_PER_EPWMSS0_CLKCTRL (CM_PER + 0x0D4)
+#define CM_PER_EPWMSS2_CLKCTRL (CM_PER + 0x0D8)
+#define CM_PER_L3_INSTR_CLKCTRL (CM_PER + 0x0DC)
+#define CM_PER_L3_CLKCTRL (CM_PER + 0x0E0)
+#define CM_PER_PRUSS_CLKCTRL (CM_PER + 0x0E8)
+#define CM_PER_TIMER5_CLKCTRL (CM_PER + 0x0EC)
+#define CM_PER_TIMER6_CLKCTRL (CM_PER + 0x0F0)
+#define CM_PER_MMC1_CLKCTRL (CM_PER + 0x0F4)
+#define CM_PER_MMC2_CLKCTRL (CM_PER + 0x0F8)
+#define CM_PER_TPTC1_CLKCTRL (CM_PER + 0x0FC)
+#define CM_PER_TPTC2_CLKCTRL (CM_PER + 0x100)
+#define CM_PER_SPINLOCK0_CLKCTRL (CM_PER + 0x10C)
+#define CM_PER_MAILBOX0_CLKCTRL (CM_PER + 0x110)
+#define CM_PER_OCPWP_L3_CLKSTCTRL (CM_PER + 0x12C)
+#define CM_PER_OCPWP_CLKCTRL (CM_PER + 0x130)
+#define CM_PER_CPSW_CLKSTCTRL (CM_PER + 0x144)
+#define CM_PER_PRUSS_CLKSTCTRL (CM_PER + 0x140)
+
+#define CM_WKUP 0x400
+#define CM_WKUP_CLKSTCTRL (CM_WKUP + 0x000)
+#define CM_WKUP_CONTROL_CLKCTRL (CM_WKUP + 0x004)
+#define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x008)
+#define CM_WKUP_CM_L3_AON_CLKSTCTRL (CM_WKUP + 0x01C)
+#define CM_WKUP_CM_CLKSEL_DPLL_MPU (CM_WKUP + 0x02C)
+#define CM_WKUP_CM_IDLEST_DPLL_DISP (CM_WKUP + 0x048)
+#define CM_WKUP_CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x054)
+#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x07C)
+#define CM_WKUP_CM_CLKMODE_DPLL_DISP (CM_WKUP + 0x098)
+#define CM_WKUP_I2C0_CLKCTRL (CM_WKUP + 0x0B8)
+#define CM_WKUP_ADC_TSC_CLKCTRL (CM_WKUP + 0x0BC)
+
+#define CM_DPLL 0x500
+#define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004)
+#define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008)
+#define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C)
+#define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010)
+#define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018)
+#define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C)
+#define CLKSEL_PRUSS_OCP_CLK (CM_DPLL + 0x030)
+
+#define CM_RTC 0x800
+#define CM_RTC_RTC_CLKCTRL (CM_RTC + 0x000)
+#define CM_RTC_CLKSTCTRL (CM_RTC + 0x004)
+
+#define PRM_PER 0xC00
+#define PRM_PER_RSTCTRL (PRM_PER + 0x00)
+
+#define PRM_DEVICE_OFFSET 0xF00
+#define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00)
+
+struct am335x_prcm_softc {
+ struct resource * res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct resource_spec am335x_prcm_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
+
+static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
+static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
+static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
+static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
+static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
+static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
+static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
+static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+static void am335x_prcm_reset(void);
+static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
+static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
+static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
+static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
+
+#define AM335X_NOOP_CLOCK_DEV(i) \
+ { .id = (i), \
+ .clk_activate = am335x_clk_noop_activate, \
+ .clk_deactivate = am335x_clk_noop_deactivate, \
+ .clk_set_source = am335x_clk_noop_set_source, \
+ .clk_accessible = NULL, \
+ .clk_get_source_freq = NULL \
+ }
+
+#define AM335X_GENERIC_CLOCK_DEV(i) \
+ { .id = (i), \
+ .clk_activate = am335x_clk_generic_activate, \
+ .clk_deactivate = am335x_clk_generic_deactivate, \
+ .clk_set_source = am335x_clk_generic_set_source, \
+ .clk_accessible = NULL, \
+ .clk_get_source_freq = NULL \
+ }
+
+#define AM335X_GPIO_CLOCK_DEV(i) \
+ { .id = (i), \
+ .clk_activate = am335x_clk_gpio_activate, \
+ .clk_deactivate = am335x_clk_generic_deactivate, \
+ .clk_set_source = am335x_clk_generic_set_source, \
+ .clk_accessible = NULL, \
+ .clk_get_source_freq = NULL \
+ }
+
+#define AM335X_MMCHS_CLOCK_DEV(i) \
+ { .id = (i), \
+ .clk_activate = am335x_clk_generic_activate, \
+ .clk_deactivate = am335x_clk_generic_deactivate, \
+ .clk_set_source = am335x_clk_generic_set_source, \
+ .clk_accessible = NULL, \
+ .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq \
+ }
+
+struct ti_clock_dev ti_clk_devmap[] = {
+ /* System clocks */
+ { .id = SYS_CLK,
+ .clk_activate = NULL,
+ .clk_deactivate = NULL,
+ .clk_set_source = NULL,
+ .clk_accessible = NULL,
+ .clk_get_source_freq = am335x_clk_get_sysclk_freq,
+ },
+ /* MPU (ARM) core clocks */
+ { .id = MPU_CLK,
+ .clk_activate = NULL,
+ .clk_deactivate = NULL,
+ .clk_set_source = NULL,
+ .clk_accessible = NULL,
+ .clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
+ },
+ /* CPSW Ethernet Switch core clocks */
+ { .id = CPSW_CLK,
+ .clk_activate = am335x_clk_cpsw_activate,
+ .clk_deactivate = NULL,
+ .clk_set_source = NULL,
+ .clk_accessible = NULL,
+ .clk_get_source_freq = NULL,
+ },
+
+ /* Mentor USB HS controller core clocks */
+ { .id = MUSB0_CLK,
+ .clk_activate = am335x_clk_musb0_activate,
+ .clk_deactivate = NULL,
+ .clk_set_source = NULL,
+ .clk_accessible = NULL,
+ .clk_get_source_freq = NULL,
+ },
+
+ /* LCD controller clocks */
+ { .id = LCDC_CLK,
+ .clk_activate = am335x_clk_lcdc_activate,
+ .clk_deactivate = NULL,
+ .clk_set_source = NULL,
+ .clk_accessible = NULL,
+ .clk_get_source_freq = am335x_clk_get_arm_disp_freq,
+ },
+
+ /* UART. Uart0 clock cannot be controlled. */
+ AM335X_NOOP_CLOCK_DEV(UART0_CLK),
+ AM335X_GENERIC_CLOCK_DEV(UART1_CLK),
+ AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
+ AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
+ AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
+ AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
+
+ /* DMTimer */
+ AM335X_GENERIC_CLOCK_DEV(DMTIMER2_CLK),
+ AM335X_GENERIC_CLOCK_DEV(DMTIMER3_CLK),
+ AM335X_GENERIC_CLOCK_DEV(DMTIMER4_CLK),
+ AM335X_GENERIC_CLOCK_DEV(DMTIMER5_CLK),
+ AM335X_GENERIC_CLOCK_DEV(DMTIMER6_CLK),
+ AM335X_GENERIC_CLOCK_DEV(DMTIMER7_CLK),
+
+ /* GPIO */
+ AM335X_GPIO_CLOCK_DEV(GPIO0_CLK),
+ AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
+ AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
+ AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
+
+ /* I2C */
+ AM335X_GENERIC_CLOCK_DEV(I2C0_CLK),
+ AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
+ AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
+
+ /* TSC_ADC */
+ AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK),
+
+ /* EDMA */
+ AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
+ AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
+ AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
+ AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
+
+ /* MMCHS */
+ AM335X_MMCHS_CLOCK_DEV(MMC0_CLK),
+ AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
+ AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
+
+ /* PWMSS */
+ AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
+ AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
+ AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
+
+ /* System Mailbox clock */
+ AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
+
+ /* SPINLOCK */
+ AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
+
+ /* PRU-ICSS */
+ { .id = PRUSS_CLK,
+ .clk_activate = am335x_clk_pruss_activate,
+ .clk_deactivate = NULL,
+ .clk_set_source = NULL,
+ .clk_accessible = NULL,
+ .clk_get_source_freq = NULL,
+ },
+
+ /* RTC */
+ AM335X_GENERIC_CLOCK_DEV(RTC_CLK),
+
+ { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
+};
+
+struct am335x_clk_details {
+ clk_ident_t id;
+ uint32_t clkctrl_reg;
+ uint32_t clksel_reg;
+};
+
+#define _CLK_DETAIL(i, c, s) \
+ { .id = (i), \
+ .clkctrl_reg = (c), \
+ .clksel_reg = (s), \
+ }
+
+static struct am335x_clk_details g_am335x_clk_details[] = {
+
+ /* UART. UART0 clock not controllable. */
+ _CLK_DETAIL(UART0_CLK, 0, 0),
+ _CLK_DETAIL(UART1_CLK, CM_PER_UART1_CLKCTRL, 0),
+ _CLK_DETAIL(UART2_CLK, CM_PER_UART2_CLKCTRL, 0),
+ _CLK_DETAIL(UART3_CLK, CM_PER_UART3_CLKCTRL, 0),
+ _CLK_DETAIL(UART4_CLK, CM_PER_UART4_CLKCTRL, 0),
+ _CLK_DETAIL(UART5_CLK, CM_PER_UART5_CLKCTRL, 0),
+
+ /* DMTimer modules */
+ _CLK_DETAIL(DMTIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
+ _CLK_DETAIL(DMTIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
+ _CLK_DETAIL(DMTIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
+ _CLK_DETAIL(DMTIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
+ _CLK_DETAIL(DMTIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
+ _CLK_DETAIL(DMTIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
+
+ /* GPIO modules */
+ _CLK_DETAIL(GPIO0_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
+ _CLK_DETAIL(GPIO1_CLK, CM_PER_GPIO1_CLKCTRL, 0),
+ _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO2_CLKCTRL, 0),
+ _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO3_CLKCTRL, 0),
+
+ /* I2C modules */
+ _CLK_DETAIL(I2C0_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
+ _CLK_DETAIL(I2C1_CLK, CM_PER_I2C1_CLKCTRL, 0),
+ _CLK_DETAIL(I2C2_CLK, CM_PER_I2C2_CLKCTRL, 0),
+
+ /* TSC_ADC module */
+ _CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0),
+
+ /* EDMA modules */
+ _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
+ _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
+ _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
+ _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
+
+ /* MMCHS modules*/
+ _CLK_DETAIL(MMC0_CLK, CM_PER_MMC0_CLKCTRL, 0),
+ _CLK_DETAIL(MMC1_CLK, CM_PER_MMC1_CLKCTRL, 0),
+ _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
+
+ /* PWMSS modules */
+ _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
+ _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
+ _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
+
+ _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
+ _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
+
+ /* RTC module */
+ _CLK_DETAIL(RTC_CLK, CM_RTC_RTC_CLKCTRL, 0),
+
+ { INVALID_CLK_IDENT, 0},
+};
+
+/* Read/Write macros */
+#define prcm_read_4(reg) \
+ bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
+#define prcm_write_4(reg, val) \
+ bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
+
+void am335x_prcm_setup_dmtimer(int);
+
+static int
+am335x_prcm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "am335x,prcm")) {
+ device_set_desc(dev, "AM335x Power and Clock Management");
+ return(BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+am335x_prcm_attach(device_t dev)
+{
+ struct am335x_prcm_softc *sc = device_get_softc(dev);
+ unsigned int sysclk, fclk;
+
+ if (am335x_prcm_sc)
+ return (ENXIO);
+
+ if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ am335x_prcm_sc = sc;
+ ti_cpu_reset = am335x_prcm_reset;
+
+ am335x_clk_get_sysclk_freq(NULL, &sysclk);
+ am335x_clk_get_arm_fclk_freq(NULL, &fclk);
+ device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
+ sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
+
+ return (0);
+}
+
+static device_method_t am335x_prcm_methods[] = {
+ DEVMETHOD(device_probe, am335x_prcm_probe),
+ DEVMETHOD(device_attach, am335x_prcm_attach),
+ { 0, 0 }
+};
+
+static driver_t am335x_prcm_driver = {
+ "am335x_prcm",
+ am335x_prcm_methods,
+ sizeof(struct am335x_prcm_softc),
+};
+
+static devclass_t am335x_prcm_devclass;
+
+DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
+ am335x_prcm_devclass, 0, 0);
+MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
+
+static struct am335x_clk_details*
+am335x_clk_details(clk_ident_t id)
+{
+ struct am335x_clk_details *walker;
+
+ for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
+ if (id == walker->id)
+ return (walker);
+ }
+
+ return NULL;
+}
+
+static int
+am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
+{
+
+ return (0);
+}
+
+static int
+am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
+{
+ struct am335x_prcm_softc *sc = am335x_prcm_sc;
+ struct am335x_clk_details* clk_details;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = am335x_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
+ prcm_write_4(clk_details->clkctrl_reg, 2);
+ while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
+ DELAY(10);
+
+ return (0);
+}
+
+static int
+am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
+{
+ struct am335x_prcm_softc *sc = am335x_prcm_sc;
+ struct am335x_clk_details* clk_details;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = am335x_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
+ /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
+ prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
+ while ((prcm_read_4(clk_details->clkctrl_reg) &
+ (3 | (1 << 18) )) != (2 | (1 << 18)))
+ DELAY(10);
+
+ return (0);
+}
+
+static int
+am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
+{
+
+ return(0);
+}
+
+static int
+am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
+{
+ struct am335x_prcm_softc *sc = am335x_prcm_sc;
+ struct am335x_clk_details* clk_details;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = am335x_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
+ prcm_write_4(clk_details->clkctrl_reg, 0);
+ while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
+ DELAY(10);
+
+ return (0);
+}
+
+static int
+am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
+{
+
+ return (0);
+}
+
+static int
+am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
+{
+ struct am335x_prcm_softc *sc = am335x_prcm_sc;
+ struct am335x_clk_details* clk_details;
+ uint32_t reg;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = am335x_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ switch (clksrc) {
+ case EXT_CLK:
+ reg = 0; /* SEL2: TCLKIN clock */
+ break;
+ case SYSCLK_CLK:
+ reg = 1; /* SEL1: CLK_M_OSC clock */
+ break;
+ case F32KHZ_CLK:
+ reg = 2; /* SEL3: CLK_32KHZ clock */
+ break;
+ default:
+ return (ENXIO);
+ }
+
+ prcm_write_4(clk_details->clksel_reg, reg);
+ while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
+ DELAY(10);
+
+ return (0);
+}
+
+static int
+am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
+{
+ *freq = 96000000;
+ return (0);
+}
+
+static int
+am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
+{
+ uint32_t ctrl_status;
+
+ /* Read the input clock freq from the control module */
+ /* control_status reg (0x40) */
+ if (ti_scm_reg_read_4(0x40, &ctrl_status))
+ return ENXIO;
+
+ switch ((ctrl_status>>22) & 0x3) {
+ case 0x0:
+ /* 19.2Mhz */
+ *freq = 19200000;
+ break;
+ case 0x1:
+ /* 24Mhz */
+ *freq = 24000000;
+ break;
+ case 0x2:
+ /* 25Mhz */
+ *freq = 25000000;
+ break;
+ case 0x3:
+ /* 26Mhz */
+ *freq = 26000000;
+ break;
+ }
+
+ return (0);
+}
+
+#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1)
+#define DPLL_DIV(reg) ((reg & 0x7f)+1)
+#define DPLL_MULT(reg) ((reg>>8) & 0x7FF)
+
+static int
+am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
+{
+ uint32_t reg;
+ uint32_t sysclk;
+
+ reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
+
+ /*Check if we are running in bypass */
+ if (DPLL_BYP_CLKSEL(reg))
+ return ENXIO;
+
+ am335x_clk_get_sysclk_freq(NULL, &sysclk);
+ *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
+ return(0);
+}
+
+static int
+am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
+{
+ uint32_t reg;
+ uint32_t sysclk;
+
+ reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
+
+ /*Check if we are running in bypass */
+ if (DPLL_BYP_CLKSEL(reg))
+ return ENXIO;
+
+ am335x_clk_get_sysclk_freq(NULL, &sysclk);
+ *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
+ return(0);
+}
+
+static void
+am335x_prcm_reset(void)
+{
+ prcm_write_4(PRM_RSTCTRL, (1<<1));
+}
+
+static int
+am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
+{
+ struct am335x_prcm_softc *sc = am335x_prcm_sc;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ /* set MODULENAME to ENABLE */
+ prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
+
+ /* wait for IDLEST to become Func(0) */
+ while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
+
+ /*set CLKTRCTRL to SW_WKUP(2) */
+ prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
+
+ /* wait for 125 MHz OCP clock to become active */
+ while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
+ return(0);
+}
+
+static int
+am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
+{
+ struct am335x_prcm_softc *sc = am335x_prcm_sc;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
+ /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
+ prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
+
+ /*set MODULEMODE to ENABLE(2) */
+ prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
+
+ /* wait for MODULEMODE to become ENABLE(2) */
+ while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
+ DELAY(10);
+
+ /* wait for IDLEST to become Func(0) */
+ while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
+ DELAY(10);
+
+ return(0);
+}
+
+static int
+am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
+{
+ struct am335x_prcm_softc *sc = am335x_prcm_sc;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ /* Bypass mode */
+ prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
+
+ /* Make sure it's in bypass mode */
+ while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
+ & (1 << 8)))
+ DELAY(10);
+
+ /*
+ * For now set frequency to 5xSYSFREQ
+ * More flexible control might be required
+ */
+ prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (5 << 8) | 0);
+
+ /* Locked mode */
+ prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
+
+ int timeout = 10000;
+ while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
+ & (1 << 0))) && timeout--)
+ DELAY(10);
+
+ /*set MODULEMODE to ENABLE(2) */
+ prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
+
+ /* wait for MODULEMODE to become ENABLE(2) */
+ while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
+ DELAY(10);
+
+ /* wait for IDLEST to become Func(0) */
+ while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
+ DELAY(10);
+
+ return (0);
+}
+
+static int
+am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
+{
+ struct am335x_prcm_softc *sc = am335x_prcm_sc;
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ /* Set MODULEMODE to ENABLE(2) */
+ prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
+
+ /* Wait for MODULEMODE to become ENABLE(2) */
+ while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
+ DELAY(10);
+
+ /* Set CLKTRCTRL to SW_WKUP(2) */
+ prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
+
+ /* Wait for the 200 MHz OCP clock to become active */
+ while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
+ DELAY(10);
+
+ /* Wait for the 200 MHz IEP clock to become active */
+ while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
+ DELAY(10);
+
+ /* Wait for the 192 MHz UART clock to become active */
+ while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
+ DELAY(10);
+
+ /* Select L3F as OCP clock */
+ prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 0);
+ while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 0)
+ DELAY(10);
+
+ /* Clear the RESET bit */
+ prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
+
+ return (0);
+}
Property changes on: trunk/sys/arm/ti/am335x/am335x_prcm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_pwm.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_pwm.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_pwm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,543 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_pwm.c 270237 2014-08-20 17:57:23Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_scm.h>
+
+#include "am335x_pwm.h"
+#include "am335x_scm.h"
+
+/* In ticks */
+#define DEFAULT_PWM_PERIOD 1000
+#define PWM_CLOCK 100000000UL
+
+#define PWM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define PWM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define PWM_LOCK_INIT(_sc) mtx_init(&(_sc)->sc_mtx, \
+ device_get_nameunit(_sc->sc_dev), "am335x_pwm softc", MTX_DEF)
+#define PWM_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
+
+static struct resource_spec am335x_pwm_mem_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* PWMSS */
+ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* eCAP */
+ { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* eQEP */
+ { SYS_RES_MEMORY, 3, RF_ACTIVE }, /*ePWM */
+ { -1, 0, 0 }
+};
+
+#define PWMSS_READ4(_sc, reg) bus_read_4((_sc)->sc_mem_res[0], reg);
+#define PWMSS_WRITE4(_sc, reg, value) \
+ bus_write_4((_sc)->sc_mem_res[0], reg, value);
+
+#define ECAP_READ2(_sc, reg) bus_read_2((_sc)->sc_mem_res[1], reg);
+#define ECAP_WRITE2(_sc, reg, value) \
+ bus_write_2((_sc)->sc_mem_res[1], reg, value);
+#define ECAP_READ4(_sc, reg) bus_read_4((_sc)->sc_mem_res[1], reg);
+#define ECAP_WRITE4(_sc, reg, value) \
+ bus_write_4((_sc)->sc_mem_res[1], reg, value);
+
+#define EPWM_READ2(_sc, reg) bus_read_2((_sc)->sc_mem_res[3], reg);
+#define EPWM_WRITE2(_sc, reg, value) \
+ bus_write_2((_sc)->sc_mem_res[3], reg, value);
+
+#define PWMSS_IDVER 0x00
+#define PWMSS_SYSCONFIG 0x04
+#define PWMSS_CLKCONFIG 0x08
+#define CLKCONFIG_EPWMCLK_EN (1 << 8)
+#define PWMSS_CLKSTATUS 0x0C
+
+#define ECAP_TSCTR 0x00
+#define ECAP_CAP1 0x08
+#define ECAP_CAP2 0x0C
+#define ECAP_CAP3 0x10
+#define ECAP_CAP4 0x14
+#define ECAP_ECCTL2 0x2A
+#define ECCTL2_MODE_APWM (1 << 9)
+#define ECCTL2_SYNCO_SEL (3 << 6)
+#define ECCTL2_TSCTRSTOP_FREERUN (1 << 4)
+
+#define EPWM_TBCTL 0x00
+#define TBCTL_FREERUN (2 << 14)
+#define TBCTL_PHDIR_UP (1 << 13)
+#define TBCTL_PHDIR_DOWN (0 << 13)
+#define TBCTL_CLKDIV(x) ((x) << 10)
+#define TBCTL_CLKDIV_MASK (3 << 10)
+#define TBCTL_HSPCLKDIV(x) ((x) << 7)
+#define TBCTL_HSPCLKDIV_MASK (3 << 7)
+#define TBCTL_SYNCOSEL_DISABLED (3 << 4)
+#define TBCTL_PRDLD_SHADOW (0 << 3)
+#define TBCTL_PRDLD_IMMEDIATE (0 << 3)
+#define TBCTL_PHSEN_ENABLED (1 << 2)
+#define TBCTL_PHSEN_DISABLED (0 << 2)
+#define TBCTL_CTRMODE_MASK (3)
+#define TBCTL_CTRMODE_UP (0 << 0)
+#define TBCTL_CTRMODE_DOWN (1 << 0)
+#define TBCTL_CTRMODE_UPDOWN (2 << 0)
+#define TBCTL_CTRMODE_FREEZE (3 << 0)
+
+#define EPWM_TBSTS 0x02
+#define EPWM_TBPHSHR 0x04
+#define EPWM_TBPHS 0x06
+#define EPWM_TBCNT 0x08
+#define EPWM_TBPRD 0x0a
+/* Counter-compare */
+#define EPWM_CMPCTL 0x0e
+#define CMPCTL_SHDWBMODE_SHADOW (1 << 6)
+#define CMPCTL_SHDWBMODE_IMMEDIATE (0 << 6)
+#define CMPCTL_SHDWAMODE_SHADOW (1 << 4)
+#define CMPCTL_SHDWAMODE_IMMEDIATE (0 << 4)
+#define CMPCTL_LOADBMODE_ZERO (0 << 2)
+#define CMPCTL_LOADBMODE_PRD (1 << 2)
+#define CMPCTL_LOADBMODE_EITHER (2 << 2)
+#define CMPCTL_LOADBMODE_FREEZE (3 << 2)
+#define CMPCTL_LOADAMODE_ZERO (0 << 0)
+#define CMPCTL_LOADAMODE_PRD (1 << 0)
+#define CMPCTL_LOADAMODE_EITHER (2 << 0)
+#define CMPCTL_LOADAMODE_FREEZE (3 << 0)
+#define EPWM_CMPAHR 0x10
+#define EPWM_CMPA 0x12
+#define EPWM_CMPB 0x14
+/* CMPCTL_LOADAMODE_ZERO */
+#define EPWM_AQCTLA 0x16
+#define EPWM_AQCTLB 0x18
+#define AQCTL_CBU_NONE (0 << 8)
+#define AQCTL_CBU_CLEAR (1 << 8)
+#define AQCTL_CBU_SET (2 << 8)
+#define AQCTL_CBU_TOGGLE (3 << 8)
+#define AQCTL_CAU_NONE (0 << 4)
+#define AQCTL_CAU_CLEAR (1 << 4)
+#define AQCTL_CAU_SET (2 << 4)
+#define AQCTL_CAU_TOGGLE (3 << 4)
+#define AQCTL_ZRO_NONE (0 << 0)
+#define AQCTL_ZRO_CLEAR (1 << 0)
+#define AQCTL_ZRO_SET (2 << 0)
+#define AQCTL_ZRO_TOGGLE (3 << 0)
+#define EPWM_AQSFRC 0x1a
+#define EPWM_AQCSFRC 0x1c
+
+/* Trip-Zone module */
+#define EPWM_TZCTL 0x28
+#define EPWM_TZFLG 0x2C
+/* High-Resolution PWM */
+#define EPWM_HRCTL 0x40
+#define HRCTL_DELMODE_BOTH 3
+#define HRCTL_DELMODE_FALL 2
+#define HRCTL_DELMODE_RISE 1
+
+static device_probe_t am335x_pwm_probe;
+static device_attach_t am335x_pwm_attach;
+static device_detach_t am335x_pwm_detach;
+
+static int am335x_pwm_clkdiv[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+struct am335x_pwm_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ struct resource *sc_mem_res[4];
+ int sc_id;
+ /* sysctl for configuration */
+ int sc_pwm_clkdiv;
+ int sc_pwm_freq;
+ struct sysctl_oid *sc_clkdiv_oid;
+ struct sysctl_oid *sc_freq_oid;
+ struct sysctl_oid *sc_period_oid;
+ struct sysctl_oid *sc_chanA_oid;
+ struct sysctl_oid *sc_chanB_oid;
+ uint32_t sc_pwm_period;
+ uint32_t sc_pwm_dutyA;
+ uint32_t sc_pwm_dutyB;
+};
+
+static device_method_t am335x_pwm_methods[] = {
+ DEVMETHOD(device_probe, am335x_pwm_probe),
+ DEVMETHOD(device_attach, am335x_pwm_attach),
+ DEVMETHOD(device_detach, am335x_pwm_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t am335x_pwm_driver = {
+ "am335x_pwm",
+ am335x_pwm_methods,
+ sizeof(struct am335x_pwm_softc),
+};
+
+static devclass_t am335x_pwm_devclass;
+
+/*
+ * API function to set period/duty cycles for ECASx
+ */
+int
+am335x_pwm_config_ecas(int unit, int period, int duty)
+{
+ device_t dev;
+ struct am335x_pwm_softc *sc;
+ uint16_t reg;
+
+ dev = devclass_get_device(am335x_pwm_devclass, unit);
+ if (dev == NULL)
+ return (ENXIO);
+
+ if (duty > period)
+ return (EINVAL);
+
+ if (period == 0)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ PWM_LOCK(sc);
+
+ reg = ECAP_READ2(sc, ECAP_ECCTL2);
+ reg |= ECCTL2_MODE_APWM | ECCTL2_TSCTRSTOP_FREERUN | ECCTL2_SYNCO_SEL;
+ ECAP_WRITE2(sc, ECAP_ECCTL2, reg);
+
+ /* CAP3 in APWM mode is APRD shadow register */
+ ECAP_WRITE4(sc, ECAP_CAP3, period - 1);
+
+ /* CAP4 in APWM mode is ACMP shadow register */
+ ECAP_WRITE4(sc, ECAP_CAP4, duty);
+ /* Restart counter */
+ ECAP_WRITE4(sc, ECAP_TSCTR, 0);
+
+ PWM_UNLOCK(sc);
+
+ return (0);
+}
+
+static void
+am335x_pwm_freq(struct am335x_pwm_softc *sc)
+{
+ int clkdiv;
+
+ clkdiv = am335x_pwm_clkdiv[sc->sc_pwm_clkdiv];
+ sc->sc_pwm_freq = PWM_CLOCK / (1 * clkdiv) / sc->sc_pwm_period;
+}
+
+static int
+am335x_pwm_sysctl_freq(SYSCTL_HANDLER_ARGS)
+{
+ int clkdiv, error, freq, i, period;
+ struct am335x_pwm_softc *sc;
+ uint32_t reg;
+
+ sc = (struct am335x_pwm_softc *)arg1;
+
+ PWM_LOCK(sc);
+ freq = sc->sc_pwm_freq;
+ PWM_UNLOCK(sc);
+
+ error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (freq > PWM_CLOCK)
+ freq = PWM_CLOCK;
+
+ PWM_LOCK(sc);
+ if (freq != sc->sc_pwm_freq) {
+ for (i = nitems(am335x_pwm_clkdiv) - 1; i >= 0; i--) {
+ clkdiv = am335x_pwm_clkdiv[i];
+ period = PWM_CLOCK / clkdiv / freq;
+ if (period > USHRT_MAX)
+ break;
+ sc->sc_pwm_clkdiv = i;
+ sc->sc_pwm_period = period;
+ }
+ /* Reset the duty cycle settings. */
+ sc->sc_pwm_dutyA = 0;
+ sc->sc_pwm_dutyB = 0;
+ EPWM_WRITE2(sc, EPWM_CMPA, sc->sc_pwm_dutyA);
+ EPWM_WRITE2(sc, EPWM_CMPB, sc->sc_pwm_dutyB);
+ /* Update the clkdiv settings. */
+ reg = EPWM_READ2(sc, EPWM_TBCTL);
+ reg &= ~TBCTL_CLKDIV_MASK;
+ reg |= TBCTL_CLKDIV(sc->sc_pwm_clkdiv);
+ EPWM_WRITE2(sc, EPWM_TBCTL, reg);
+ /* Update the period settings. */
+ EPWM_WRITE2(sc, EPWM_TBPRD, sc->sc_pwm_period - 1);
+ am335x_pwm_freq(sc);
+ }
+ PWM_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+am335x_pwm_sysctl_clkdiv(SYSCTL_HANDLER_ARGS)
+{
+ int error, i, clkdiv;
+ struct am335x_pwm_softc *sc;
+ uint32_t reg;
+
+ sc = (struct am335x_pwm_softc *)arg1;
+
+ PWM_LOCK(sc);
+ clkdiv = am335x_pwm_clkdiv[sc->sc_pwm_clkdiv];
+ PWM_UNLOCK(sc);
+
+ error = sysctl_handle_int(oidp, &clkdiv, sizeof(clkdiv), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ PWM_LOCK(sc);
+ if (clkdiv != am335x_pwm_clkdiv[sc->sc_pwm_clkdiv]) {
+ for (i = 0; i < nitems(am335x_pwm_clkdiv); i++)
+ if (clkdiv >= am335x_pwm_clkdiv[i])
+ sc->sc_pwm_clkdiv = i;
+
+ reg = EPWM_READ2(sc, EPWM_TBCTL);
+ reg &= ~TBCTL_CLKDIV_MASK;
+ reg |= TBCTL_CLKDIV(sc->sc_pwm_clkdiv);
+ EPWM_WRITE2(sc, EPWM_TBCTL, reg);
+ am335x_pwm_freq(sc);
+ }
+ PWM_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+am335x_pwm_sysctl_duty(SYSCTL_HANDLER_ARGS)
+{
+ struct am335x_pwm_softc *sc = (struct am335x_pwm_softc*)arg1;
+ int error;
+ uint32_t duty;
+
+ if (oidp == sc->sc_chanA_oid)
+ duty = sc->sc_pwm_dutyA;
+ else
+ duty = sc->sc_pwm_dutyB;
+ error = sysctl_handle_int(oidp, &duty, 0, req);
+
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (duty > sc->sc_pwm_period) {
+ device_printf(sc->sc_dev, "Duty cycle can't be greater then period\n");
+ return (EINVAL);
+ }
+
+ PWM_LOCK(sc);
+ if (oidp == sc->sc_chanA_oid) {
+ sc->sc_pwm_dutyA = duty;
+ EPWM_WRITE2(sc, EPWM_CMPA, sc->sc_pwm_dutyA);
+ }
+ else {
+ sc->sc_pwm_dutyB = duty;
+ EPWM_WRITE2(sc, EPWM_CMPB, sc->sc_pwm_dutyB);
+ }
+ PWM_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+am335x_pwm_sysctl_period(SYSCTL_HANDLER_ARGS)
+{
+ struct am335x_pwm_softc *sc = (struct am335x_pwm_softc*)arg1;
+ int error;
+ uint32_t period;
+
+ period = sc->sc_pwm_period;
+ error = sysctl_handle_int(oidp, &period, 0, req);
+
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (period < 1)
+ return (EINVAL);
+
+ if (period > USHRT_MAX)
+ period = USHRT_MAX;
+
+ PWM_LOCK(sc);
+ /* Reset the duty cycle settings. */
+ sc->sc_pwm_dutyA = 0;
+ sc->sc_pwm_dutyB = 0;
+ EPWM_WRITE2(sc, EPWM_CMPA, sc->sc_pwm_dutyA);
+ EPWM_WRITE2(sc, EPWM_CMPB, sc->sc_pwm_dutyB);
+ /* Update the period settings. */
+ sc->sc_pwm_period = period;
+ EPWM_WRITE2(sc, EPWM_TBPRD, period - 1);
+ am335x_pwm_freq(sc);
+ PWM_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+am335x_pwm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,am335x-pwm"))
+ return (ENXIO);
+
+ device_set_desc(dev, "AM335x PWM");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+am335x_pwm_attach(device_t dev)
+{
+ struct am335x_pwm_softc *sc;
+ int err;
+ uint32_t reg;
+ phandle_t node;
+ pcell_t did;
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ /* Get the PWM module id */
+ node = ofw_bus_get_node(dev);
+ if ((OF_getprop(node, "pwm-device-id", &did, sizeof(did))) <= 0) {
+ device_printf(dev, "missing pwm-device-id attribute in FDT\n");
+ return (ENXIO);
+ }
+ sc->sc_id = fdt32_to_cpu(did);
+
+ PWM_LOCK_INIT(sc);
+
+ err = bus_alloc_resources(dev, am335x_pwm_mem_spec,
+ sc->sc_mem_res);
+ if (err) {
+ device_printf(dev, "cannot allocate memory resources\n");
+ goto fail;
+ }
+
+ ti_prcm_clk_enable(PWMSS0_CLK + sc->sc_id);
+ ti_scm_reg_read_4(SCM_PWMSS_CTRL, ®);
+ reg |= (1 << sc->sc_id);
+ ti_scm_reg_write_4(SCM_PWMSS_CTRL, reg);
+
+ /* Init backlight interface */
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ tree = device_get_sysctl_tree(sc->sc_dev);
+
+ sc->sc_clkdiv_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "clkdiv", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ am335x_pwm_sysctl_clkdiv, "I", "PWM clock prescaler");
+
+ sc->sc_freq_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ am335x_pwm_sysctl_freq, "I", "PWM frequency");
+
+ sc->sc_period_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "period", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ am335x_pwm_sysctl_period, "I", "PWM period");
+
+ sc->sc_chanA_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "dutyA", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ am335x_pwm_sysctl_duty, "I", "Channel A duty cycles");
+
+ sc->sc_chanB_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "dutyB", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ am335x_pwm_sysctl_duty, "I", "Channel B duty cycles");
+
+ /* CONFIGURE EPWM1 */
+ reg = EPWM_READ2(sc, EPWM_TBCTL);
+ reg &= ~(TBCTL_CLKDIV_MASK | TBCTL_HSPCLKDIV_MASK);
+ EPWM_WRITE2(sc, EPWM_TBCTL, reg);
+
+ sc->sc_pwm_period = DEFAULT_PWM_PERIOD;
+ sc->sc_pwm_dutyA = 0;
+ sc->sc_pwm_dutyB = 0;
+ am335x_pwm_freq(sc);
+
+ EPWM_WRITE2(sc, EPWM_TBPRD, sc->sc_pwm_period - 1);
+ EPWM_WRITE2(sc, EPWM_CMPA, sc->sc_pwm_dutyA);
+ EPWM_WRITE2(sc, EPWM_CMPB, sc->sc_pwm_dutyB);
+
+ EPWM_WRITE2(sc, EPWM_AQCTLA, (AQCTL_ZRO_SET | AQCTL_CAU_CLEAR));
+ EPWM_WRITE2(sc, EPWM_AQCTLB, (AQCTL_ZRO_SET | AQCTL_CBU_CLEAR));
+
+ /* START EPWM */
+ reg &= ~TBCTL_CTRMODE_MASK;
+ reg |= TBCTL_CTRMODE_UP | TBCTL_FREERUN;
+ EPWM_WRITE2(sc, EPWM_TBCTL, reg);
+
+ EPWM_WRITE2(sc, EPWM_TZCTL, 0xf);
+ reg = EPWM_READ2(sc, EPWM_TZFLG);
+
+ return (0);
+fail:
+ PWM_LOCK_DESTROY(sc);
+ if (sc->sc_mem_res[0])
+ bus_release_resources(dev, am335x_pwm_mem_spec,
+ sc->sc_mem_res);
+
+ return(ENXIO);
+}
+
+static int
+am335x_pwm_detach(device_t dev)
+{
+ struct am335x_pwm_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ PWM_LOCK(sc);
+ if (sc->sc_mem_res[0])
+ bus_release_resources(dev, am335x_pwm_mem_spec,
+ sc->sc_mem_res);
+ PWM_UNLOCK(sc);
+
+ PWM_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+DRIVER_MODULE(am335x_pwm, simplebus, am335x_pwm_driver, am335x_pwm_devclass, 0, 0);
+MODULE_VERSION(am335x_pwm, 1);
+MODULE_DEPEND(am335x_pwm, simplebus, 1, 1, 1);
Property changes on: trunk/sys/arm/ti/am335x/am335x_pwm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_pwm.h
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_pwm.h (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_pwm.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,34 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/am335x/am335x_pwm.h 251017 2013-05-27 00:13:27Z gonzo $
+ */
+#ifndef __AM335X_PWM_H__
+#define __AM335X_PWM_H__
+
+int am335x_pwm_config_ecas(int unit, int period, int duty);
+
+#endif /* __AM335X_PWM_H__ */
Property changes on: trunk/sys/arm/ti/am335x/am335x_pwm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_reg.h
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_reg.h (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,42 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/am335x/am335x_reg.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+#ifndef _AM335X_REG_H_
+#define _AM335X_REG_H_
+
+#define AM335X_L4_WKUP_BASE 0x44C00000
+#define AM335X_L4_WKUP_SIZE 0x400000
+
+#define AM335X_CONTROL_BASE AM335X_L4_WKUP_BASE + 0x210000
+#define AM335X_CONTROL_SIZE 0x2000
+#define AM335X_CONTROL_DEVICE_ID 0x0600
+#define AM335X_CONTROL_DEV_FEATURE 0x0604
+
+#endif
+
Property changes on: trunk/sys/arm/ti/am335x/am335x_reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_rtc.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_rtc.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_rtc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,212 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2015 Luiz Otavio O Souza <loos at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_rtc.c 279462 2015-03-01 00:57:01Z dim $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus_subr.h>
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/am335x/am335x_rtcvar.h>
+#include <arm/ti/am335x/am335x_rtcreg.h>
+
+#define RTC_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define RTC_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define RTC_LOCK_INIT(_sc) mtx_init(&(_sc)->sc_mtx, \
+ device_get_nameunit(_sc->sc_dev), "am335x_rtc", MTX_DEF)
+#define RTC_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
+
+#define RTC_READ4(_sc, reg) \
+ bus_read_4((_sc)->sc_mem_res, reg)
+#define RTC_WRITE4(_sc, reg, value) \
+ bus_write_4((_sc)->sc_mem_res, reg, value)
+
+#define RTC_MAXIRQS 2
+
+struct am335x_rtc_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ struct resource *sc_irq_res[RTC_MAXIRQS];
+ struct resource *sc_mem_res;
+};
+
+static struct am335x_rtc_softc *rtc_sc = NULL;
+static struct resource_spec am335x_rtc_irq_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+static int
+am335x_rtc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (!ofw_bus_is_compatible(dev, "ti,da830-rtc"))
+ return (ENXIO);
+ device_set_desc(dev, "AM335x RTC (power management mode)");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+am335x_rtc_attach(device_t dev)
+{
+ int rid;
+ struct am335x_rtc_softc *sc;
+ uint32_t rev;
+
+ if (rtc_sc != NULL)
+ return (ENXIO);
+ rtc_sc = sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+ if (bus_alloc_resources(dev, am335x_rtc_irq_spec, sc->sc_irq_res) != 0) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate irq resources\n");
+ return (ENXIO);
+ }
+ RTC_LOCK_INIT(sc);
+
+ /* Enable the RTC module. */
+ ti_prcm_clk_enable(RTC_CLK);
+ rev = RTC_READ4(sc, RTC_REVISION);
+ device_printf(dev, "AM335X RTC v%d.%d.%d\n",
+ (rev >> 8) & 0x7, (rev >> 6) & 0x3, rev & 0x3f);
+ /* Unlock the RTC. */
+ RTC_WRITE4(sc, RTC_KICK0R, RTC_KICK0R_PASS);
+ RTC_WRITE4(sc, RTC_KICK1R, RTC_KICK1R_PASS);
+ /* Stop the RTC, we don't need it right now. */
+ RTC_WRITE4(sc, RTC_CTRL, 0);
+ /* Disable interrupts. */
+ RTC_WRITE4(sc, RTC_INTR, 0);
+ /* Ack any pending interrupt. */
+ RTC_WRITE4(sc, RTC_STATUS, RTC_STATUS_ALARM2 | RTC_STATUS_ALARM);
+ /* Enable external clock (xtal) and 32 kHz clock. */
+ RTC_WRITE4(sc, RTC_OSC, RTC_OSC_32KCLK_EN | RTC_OSC_32KCLK_SEL);
+ /* Enable pmic_pwr_enable. */
+ RTC_WRITE4(sc, RTC_PMIC, PMIC_PWR_ENABLE);
+
+ return (0);
+}
+
+static int
+am335x_rtc_detach(device_t dev)
+{
+ struct am335x_rtc_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->sc_irq_res[0] != NULL)
+ bus_release_resources(dev, am335x_rtc_irq_spec, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ RTC_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+void
+am335x_rtc_pmic_pwr_toggle(void)
+{
+ int timeout;
+ struct clocktime ct;
+ struct timespec ts;
+
+ /*
+ * We stop the RTC so we don't need to check the STATUS.BUSY bit
+ * before update ALARM2 registers.
+ */
+ timeout = 10;
+ RTC_WRITE4(rtc_sc, RTC_CTRL, 0);
+ while (--timeout && RTC_READ4(rtc_sc, RTC_STATUS) & RTC_STATUS_RUN)
+ DELAY(100);
+ if (timeout == 0) {
+ device_printf(rtc_sc->sc_dev, "RTC does not stop.\n");
+ return;
+ }
+ /* Program the ALARM2 to fire in 2 seconds. */
+ ct.dow = 0;
+ ct.nsec = 0;
+ ct.sec = FROMBCD(RTC_READ4(rtc_sc, RTC_SECONDS) & 0x7f);
+ ct.min = FROMBCD(RTC_READ4(rtc_sc, RTC_MINUTES) & 0x7f);
+ ct.hour = FROMBCD(RTC_READ4(rtc_sc, RTC_HOURS) & 0x3f);
+ ct.day = FROMBCD(RTC_READ4(rtc_sc, RTC_DAYS) & 0x3f);
+ ct.mon = FROMBCD(RTC_READ4(rtc_sc, RTC_MONTHS) & 0x1f);
+ ct.year = FROMBCD(RTC_READ4(rtc_sc, RTC_YEARS) & 0xff);
+ ct.year += POSIX_BASE_YEAR;
+ clock_ct_to_ts(&ct, &ts);
+ ts.tv_sec += 2;
+ clock_ts_to_ct(&ts, &ct);
+ RTC_WRITE4(rtc_sc, RTC_ALARM2_SECONDS, TOBCD(ct.sec));
+ RTC_WRITE4(rtc_sc, RTC_ALARM2_MINUTES, TOBCD(ct.min));
+ RTC_WRITE4(rtc_sc, RTC_ALARM2_HOURS, TOBCD(ct.hour));
+ RTC_WRITE4(rtc_sc, RTC_ALARM2_DAYS, TOBCD(ct.day));
+ RTC_WRITE4(rtc_sc, RTC_ALARM2_MONTHS, TOBCD(ct.mon));
+ RTC_WRITE4(rtc_sc, RTC_ALARM2_YEARS, TOBCD(ct.year - POSIX_BASE_YEAR));
+ /* Enable ALARM2 interrupt. */
+ RTC_WRITE4(rtc_sc, RTC_INTR, RTC_INTR_ALARM2);
+ /* Start count. */
+ RTC_WRITE4(rtc_sc, RTC_CTRL, RTC_CTRL_RUN);
+}
+
+static device_method_t am335x_rtc_methods[] = {
+ DEVMETHOD(device_probe, am335x_rtc_probe),
+ DEVMETHOD(device_attach, am335x_rtc_attach),
+ DEVMETHOD(device_detach, am335x_rtc_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t am335x_rtc_driver = {
+ "am335x_rtc",
+ am335x_rtc_methods,
+ sizeof(struct am335x_rtc_softc),
+};
+
+static devclass_t am335x_rtc_devclass;
+
+DRIVER_MODULE(am335x_rtc, simplebus, am335x_rtc_driver, am335x_rtc_devclass, 0, 0);
+MODULE_VERSION(am335x_rtc, 1);
+MODULE_DEPEND(am335x_rtc, simplebus, 1, 1, 1);
Property changes on: trunk/sys/arm/ti/am335x/am335x_rtc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_rtcreg.h
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_rtcreg.h (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_rtcreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,77 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2015 Luiz Otavio O Souza <loos at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/am335x/am335x_rtcreg.h 278079 2015-02-02 12:48:13Z loos $
+ */
+
+#ifndef _AM335X_RTCREG_H_
+#define _AM335X_RTCREG_H_
+
+#define RTC_SECONDS 0x00
+#define RTC_MINUTES 0x04
+#define RTC_HOURS 0x08
+#define RTC_DAYS 0x0c
+#define RTC_MONTHS 0x10
+#define RTC_YEARS 0x14
+#define RTC_WEEK 0x18
+#define RTC_CTRL 0x40
+#define RTC_CTRL_DISABLE (1U << 6)
+#define RTC_CTRL_RUN (1U << 0)
+#define RTC_STATUS 0x44
+#define RTC_STATUS_ALARM2 (1U << 7)
+#define RTC_STATUS_ALARM (1U << 6)
+#define RTC_STATUS_1D_EVENT (1U << 5)
+#define RTC_STATUS_1H_EVENT (1U << 4)
+#define RTC_STATUS_1M_EVENT (1U << 3)
+#define RTC_STATUS_1S_EVENT (1U << 2)
+#define RTC_STATUS_RUN (1U << 1)
+#define RTC_STATUS_BUSY (1U << 0)
+#define RTC_INTR 0x48
+#define RTC_INTR_ALARM2 (1U << 4)
+#define RTC_INTR_ALARM (1U << 3)
+#define RTC_INTR_TIMER (1U << 2)
+#define RTC_OSC 0x54
+#define RTC_OSC_32KCLK_EN (1U << 6)
+#define RTC_OSC_OSC32K_GZ (1U << 4)
+#define RTC_OSC_32KCLK_SEL (1U << 3)
+#define RTC_OSC_RES_SELECT (1U << 2)
+#define RTC_OSC_SW2 (1U << 1)
+#define RTC_OSC_SW1 (1U << 0)
+#define RTC_KICK0R 0x6c
+#define RTC_KICK0R_PASS 0x83e70b13
+#define RTC_KICK1R 0x70
+#define RTC_KICK1R_PASS 0x95a4f1e0
+#define RTC_REVISION 0x74
+#define RTC_ALARM2_SECONDS 0x80
+#define RTC_ALARM2_MINUTES 0x84
+#define RTC_ALARM2_HOURS 0x88
+#define RTC_ALARM2_DAYS 0x8c
+#define RTC_ALARM2_MONTHS 0x90
+#define RTC_ALARM2_YEARS 0x94
+#define RTC_PMIC 0x98
+#define PMIC_PWR_ENABLE (1U << 16)
+
+#endif /* _AM335X_RTCREG_H_ */
Property changes on: trunk/sys/arm/ti/am335x/am335x_rtcreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_rtcvar.h
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_rtcvar.h (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_rtcvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,35 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2015 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/am335x/am335x_rtcvar.h 278079 2015-02-02 12:48:13Z loos $
+ */
+
+#ifndef _AM335X_RTCVAR_H_
+#define _AM335X_RTCVAR_H_
+
+void am335x_rtc_pmic_pwr_toggle(void);
+
+#endif /* _AM335X_RTCVAR_H_ */
Property changes on: trunk/sys/arm/ti/am335x/am335x_rtcvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_scm.h
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_scm.h (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_scm.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,39 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/am335x/am335x_scm.h 251016 2013-05-27 00:09:04Z gonzo $
+ */
+#ifndef __AM335X_SCM_H__
+#define __AM335X_SCM_H__
+
+/* AM335x-specific registers for control module (scm) */
+#define SCM_USB_CTRL0 0x620
+#define SCM_USB_STS0 0x624
+#define SCM_USB_CTRL1 0x628
+#define SCM_USB_STS1 0x62C
+#define SCM_PWMSS_CTRL 0x664
+
+#endif /* __AM335X_SCM_H__ */
Property changes on: trunk/sys/arm/ti/am335x/am335x_scm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_scm_padconf.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_scm_padconf.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_scm_padconf.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,365 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_scm_padconf.c 279467 2015-03-01 01:08:14Z dim $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <sys/gpio.h>
+
+#include <arm/ti/tivar.h>
+#include <arm/ti/ti_scm.h>
+
+#define _PIN(r, b, gp, gm, m0, m1, m2, m3, m4, m5, m6, m7) \
+ { .reg_off = r, \
+ .gpio_pin = gp, \
+ .gpio_mode = gm, \
+ .ballname = b, \
+ .muxmodes[0] = m0, \
+ .muxmodes[1] = m1, \
+ .muxmodes[2] = m2, \
+ .muxmodes[3] = m3, \
+ .muxmodes[4] = m4, \
+ .muxmodes[5] = m5, \
+ .muxmodes[6] = m6, \
+ .muxmodes[7] = m7, \
+ }
+
+#define SLEWCTRL (0x01 << 6) /* faster(0) or slower(1) slew rate. */
+#define RXACTIVE (0x01 << 5) /* Input enable value for the Pad */
+#define PULLTYPESEL (0x01 << 4) /* Pad pullup/pulldown type selection */
+#define PULLUDEN (0x01 << 3) /* Pullup/pulldown disabled */
+
+#define PADCONF_OUTPUT (0)
+#define PADCONF_OUTPUT_PULLUP (PULLTYPESEL)
+#define PADCONF_INPUT (RXACTIVE | PULLUDEN)
+#define PADCONF_INPUT_PULLUP (RXACTIVE | PULLTYPESEL)
+#define PADCONF_INPUT_PULLDOWN (RXACTIVE)
+#define PADCONF_INPUT_PULLUP_SLOW (PADCONF_INPUT_PULLUP | SLEWCTRL)
+
+const struct ti_scm_padstate ti_padstate_devmap[] = {
+ {"output", PADCONF_OUTPUT },
+ {"output_pullup", PADCONF_OUTPUT_PULLUP },
+ {"input", PADCONF_INPUT },
+ {"input_pulldown", PADCONF_INPUT_PULLDOWN },
+ {"input_pullup", PADCONF_INPUT_PULLUP },
+ {"i2c", PADCONF_INPUT_PULLUP_SLOW },
+ { .state = NULL }
+};
+
+const struct ti_scm_padconf ti_padconf_devmap[] = {
+ _PIN(0x800, "GPMC_AD0", 32, 7,"gpmc_ad0", "mmc1_dat0", NULL, NULL, NULL, NULL, NULL, "gpio1_0"),
+ _PIN(0x804, "GPMC_AD1", 33, 7,"gpmc_ad1", "mmc1_dat1", NULL, NULL, NULL, NULL, NULL, "gpio1_1"),
+ _PIN(0x808, "GPMC_AD2", 34, 7,"gpmc_ad2", "mmc1_dat2", NULL, NULL, NULL, NULL, NULL, "gpio1_2"),
+ _PIN(0x80C, "GPMC_AD3", 35, 7,"gpmc_ad3", "mmc1_dat3", NULL, NULL, NULL, NULL, NULL, "gpio1_3"),
+ _PIN(0x810, "GPMC_AD4", 36, 7,"gpmc_ad4", "mmc1_dat4", NULL, NULL, NULL, NULL, NULL, "gpio1_4"),
+ _PIN(0x814, "GPMC_AD5", 37, 7,"gpmc_ad5", "mmc1_dat5", NULL, NULL, NULL, NULL, NULL, "gpio1_5"),
+ _PIN(0x818, "GPMC_AD6", 38, 7,"gpmc_ad6", "mmc1_dat6", NULL, NULL, NULL, NULL, NULL, "gpio1_6"),
+ _PIN(0x81C, "GPMC_AD7", 39, 7,"gpmc_ad7", "mmc1_dat7", NULL, NULL, NULL, NULL, NULL, "gpio1_7"),
+ _PIN(0x820, "GPMC_AD8", 22, 7, "gpmc_ad8", "lcd_data23", "mmc1_dat0", "mmc2_dat4", "ehrpwm2A", NULL, NULL, "gpio0_22"),
+ _PIN(0x824, "GPMC_AD9", 23, 7, "gpmc_ad9", "lcd_data22", "mmc1_dat1", "mmc2_dat5", "ehrpwm2B", NULL, NULL, "gpio0_23"),
+ _PIN(0x828, "GPMC_AD10", 26, 7, "gpmc_ad10", "lcd_data21", "mmc1_dat2", "mmc2_dat6", "ehrpwm2_tripzone_in", NULL, NULL, "gpio0_26"),
+ _PIN(0x82C, "GPMC_AD11", 27, 7, "gpmc_ad11", "lcd_data20", "mmc1_dat3", "mmc2_dat7", "ehrpwm0_synco", NULL, NULL, "gpio0_27"),
+ _PIN(0x830, "GPMC_AD12", 44, 7, "gpmc_ad12", "lcd_data19", "mmc1_dat4", "mmc2_dat0", "eQEP2A_in", "pr1_mii0_txd2", "pr1_pru0_pru_r30_14", "gpio1_12"),
+ _PIN(0x834, "GPMC_AD13", 45, 7, "gpmc_ad13", "lcd_data18", "mmc1_dat5", "mmc2_dat1", "eQEP2B_in", "pr1_mii0_txd1", "pr1_pru0_pru_r30_15", "gpio1_13"),
+ _PIN(0x838, "GPMC_AD14", 46, 7, "gpmc_ad14", "lcd_data17", "mmc1_dat6", "mmc2_dat2", "eQEP2_index", "pr1_mii0_txd0", "pr1_pru0_pru_r31_14", "gpio1_14"),
+ _PIN(0x83C, "GPMC_AD15", 47, 7, "gpmc_ad15", "lcd_data16", "mmc1_dat7", "mmc2_dat3", "eQEP2_strobe", "pr1_ecap0_ecap_capin_apwm_o", "pr1_pru0_pru_r31_15", "gpio1_15"),
+ _PIN(0x840, "GPMC_A0", 48, 7, "gpmc_a0", "gmii2_txen", "rgmii2_tctl", "rmii2_txen", "gpmc_a16", "pr1_mii_mt1_clk", "ehrpwm1_tripzone_input", "gpio1_16"),
+ _PIN(0x844, "GPMC_A1", 49, 7, "gpmc_a1", "gmii2_rxdv", "rgmii2_rctl", "mmc2_dat0", "gpmc_a17", "pr1_mii1_txd3", "ehrpwm0_synco", "gpio1_17"),
+ _PIN(0x848, "GPMC_A2", 50, 7, "gpmc_a2", "gmii2_txd3", "rgmii2_td3", "mmc2_dat1", "gpmc_a18", "pr1_mii1_txd2", "ehrpwm1A", "gpio1_18"),
+ _PIN(0x84C, "GPMC_A3", 51, 7, "gpmc_a3", "gmii2_txd2", "rgmii2_td2", "mmc2_dat2", "gpmc_a19", "pr1_mii1_txd1", "ehrpwm1B", "gpio1_19"),
+ _PIN(0x850, "GPMC_A4", 52, 7, "gpmc_a4", "gmii2_txd1", "rgmii2_td1", "rmii2_tdx1", "gpmc_a20", "pr1_mii1_txd0", "eQEP1A_in", "gpio1_20"),
+ _PIN(0x854, "GPMC_A5", 53, 7, "gpmc_a5", "gmii2_txd0", "rgmii2_td0", "rmii2_txd0", "gpmc_a21", "pr1_mii1_rxd3", "eQEP1B_in", "gpio1_21"),
+ _PIN(0x858, "GPMC_A6", 54, 7, "gpmc_a6", "gmii2_txclk", "rgmii2_tclk", "mmc2_dat4", "gpmc_a22", "pr1_mii1_rxd2", "eQEP1_index", "gpio1_22"),
+ _PIN(0x85C, "GPMC_A7", 55, 7, "gpmc_a7", "gmii2_rxclk", "rgmii2_rclk", "mmc2_dat5", "gpmc_a23", "pr1_mii1_rxd1", "eQEP1_strobe", "gpio1_23"),
+ _PIN(0x860, "GPMC_A8", 56, 7, "gpmc_a8", "gmii2_rxd3", "rgmii2_rd3", "mmc2_dat6", "gpmc_a24", "pr1_mii1_rxd0", "mcasp0_aclkx", "gpio1_24"),
+ _PIN(0x864, "GPMC_A9", 57, 7, "gmpc_a9", "gmii2_rxd2", "rgmii2_rd2", "mmc2_dat7 / rmii2_crs_dv", "gpmc_a25", "pr1_mii_mr1_clk", "mcasp0_fsx", "gpio1_25"),
+ _PIN(0x868, "GPMC_A10", 58, 7, "gmpc_a10", "gmii2_rxd1", "rgmii2_rd1", "rmii2_rxd1", "gpmc_a26", "pr1_mii1_rxdv", "mcasp0_arx0", "gpio1_26"),
+ _PIN(0x86C, "GPMC_A11", 59, 7, "gmpc_a11", "gmii2_rxd0", "rgmii2_rd0", "rmii2_rxd0", "gpmc_a27", "pr1_mii1_rxer", "mcasp0_axr1", "gpio1_27"),
+ _PIN(0x870, "GPMC_WAIT0", 30, 7, "gpmc_wait0", "gmii2_crs", "gpmc_csn4", "rmii2_crs_dv", "mmc1_sdcd", "pr1_mii1_col", "uart4_rxd", "gpio0_30"),
+ _PIN(0x874, "GPMC_WPn", 31, 7, "gpmc_wpn", "gmii2_rxerr", "gpmc_csn5", "rmii2_rxerr", "mmc2_sdcd", "pr1_mii1_txen", "uart4_txd", "gpio0_31"),
+ _PIN(0x878, "GPMC_BEn1", 60, 7, "gpmc_be1n", "gmii2_col", "gmpc_csn6","mmc2_dat3", "gpmc_dir", "pr1_mii1_rxlink", "mcasp0_aclkr", "gpio1_28"),
+ _PIN(0x87c, "GPMC_CSn0", 61, 7, "gpmc_csn0", NULL, NULL, NULL, NULL, NULL, NULL, "gpio1_29"),
+ _PIN(0x880, "GPMC_CSn1", 62, 7, "gpmc_csn1", "gpmc_clk", "mmc1_clk", "pr1_edio_data_in6", "pr1_edio_data_out6", "pr1_pru1_pru_r30_12", "pr1_pru1_pru_r31_12", "gpio1_30"),
+ _PIN(0x884, "GPMC_CSn2", 63, 7, "gpmc_csn2", "gpmc_be1n", "mmc1_cmd", "pr1_edio_data_in7", "pr1_edio_data_out7", "pr1_pru1_pru_r30_13", "pr1_pru1_pru_r31_13", "gpio1_31"),
+ _PIN(0x888, "GPMC_CSn3", 64, 7, "gpmc_csn3", "gpmc_a3", "rmii2_crs_dv", "mmc2_cmd", "pr1_mii0_crs", "pr1_mdio_data", "EMU4", "gpio2_0"),
+ _PIN(0x88c, "GPMC_CLK", 65, 7, "gpmc_clk", "lcd_memory_clk", "gpmc_wait1", "mmc2_clk", "pr1_mii1_crs", "pr1_mdio_mdclk", "mcasp0_fsr", "gpio2_1"),
+ _PIN(0x890, "GPMC_ADVn_ALE", 66, 7, "gpmc_advn_ale", NULL, "timer4", NULL, NULL, NULL, NULL, "gpio2_2"),
+ _PIN(0x894, "GPMC_OEn_REn", 67, 7, "gpmc_oen_ren", NULL, "timer7", NULL, NULL, NULL, NULL, "gpio2_3"),
+ _PIN(0x898, "GPMC_WEn", 68, 7, "gpmc_wen", NULL, "timer6", NULL, NULL, NULL, NULL, "gpio2_4"),
+ _PIN(0x89c, "GPMC_BEn0_CLE", 67, 7, "gpmc_ben0_cle", NULL, "timer5", NULL, NULL, NULL, NULL, "gpio2_5"),
+ _PIN(0x8a0, "LCD_DATA0", 68, 7, "lcd_data0", "gpmc_a0", "pr1_mii_mt0_clk", "ehrpwm2A", NULL, "pr1_pru1_pru_r30_0", "pr1_pru1_pru_r31_0", "gpio2_6"),
+ _PIN(0x8a4, "LCD_DATA1", 69, 7, "lcd_data1", "gpmc_a1", "pr1_mii0_txen", "ehrpwm2B", NULL, "pr1_pru1_pru_r30_1", "pr1_pru1_pru_r31_1", "gpio2_7"),
+ _PIN(0x8a8, "LCD_DATA2", 70, 7, "lcd_data2", "gpmc_a2", "pr1_mii0_txd3", "ehrpwm2_tripzone_input", NULL, "pr1_pru1_pru_r30_2", "pr1_pru1_pru_r31_2", "gpio2_8"),
+ _PIN(0x8ac, "LCD_DATA3", 71, 7, "lcd_data3", "gpmc_a3", "pr1_mii0_txd2", "ehrpwm0_synco", NULL, "pr1_pru1_pru_r30_3", "pr1_pru1_pru_r31_3", "gpio2_9"),
+ _PIN(0x8b0, "LCD_DATA4", 72, 7, "lcd_data4", "gpmc_a4", "pr1_mii0_txd1", "eQEP2A_in", NULL, "pr1_pru1_pru_r30_4", "pr1_pru1_pru_r31_4", "gpio2_10"),
+ _PIN(0x8b4, "LCD_DATA5", 73, 7, "lcd_data5", "gpmc_a5", "pr1_mii0_txd0", "eQEP2B_in", NULL, "pr1_pru1_pru_r30_5", "pr1_pru1_pru_r31_5", "gpio2_11"),
+ _PIN(0x8b8, "LCD_DATA6", 74, 7, "lcd_data6", "gpmc_a6", "pr1_edio_data_in6", "eQEP2_index", "pr1_edio_data_out6", "pr1_pru1_pru_r30_6", "pr1_pru1_pru_r31_6", "gpio2_12"),
+ _PIN(0x8bc, "LCD_DATA7", 75, 7, "lcd_data7", "gpmc_a7", "pr1_edio_data_in7", "eQEP2_strobe", "pr1_edio_data_out7", "pr1_pru1_pru_r30_7", "pr1_pru1_pru_r31_7", "gpio2_13"),
+ _PIN(0x8c0, "LCD_DATA8", 76, 7, "lcd_data8", "gpmc_a12", "ehrpwm1_tripzone_input", "mcasp0_aclkx", "uart5_txd", "pr1_mii0_rxd3", "uart2_ctsn", "gpio2_14"),
+ _PIN(0x8c4, "LCD_DATA9", 76, 7, "lcd_data9", "gpmc_a13", "ehrpwm0_synco", "mcasp0_fsx", "uart5_rxd", "pr1_mii0_rxd2", "uart2_rtsn", "gpio2_15"),
+ _PIN(0x8c8, "LCD_DATA10", 77, 7, "lcd_data10", "gpmc_a14", "ehrpwm1A", "mcasp0_axr0", NULL, "pr1_mii0_rxd1", "uart3_ctsn", "gpio2_16"),
+ _PIN(0x8cc, "LCD_DATA11", 78, 7, "lcd_data11", "gpmc_a15", "ehrpwm1B", "mcasp0_ahclkr", "mcasp0_axr2", "pr1_mii0_rxd0", "uart3_rtsn", "gpio2_17"),
+ _PIN(0x8d0, "LCD_DATA12", 8, 7, "lcd_data12", "gpmc_a16", "eQEP1A_in", "mcasp0_aclkr", "mcasp0_axr2", "pr1_mii0_rxlink", "uart4_ctsn", "gpio0_8"),
+ _PIN(0x8d4, "LCD_DATA13", 9, 7, "lcd_data13", "gpmc_a17", "eQEP1B_in", "mcasp0_fsr", "mcasp0_axr3", "pr1_mii0_rxer", "uart4_rtsn", "gpio0_9"),
+ _PIN(0x8d8, "LCD_DATA14", 10, 7, "lcd_data14", "gpmc_a18", "eQEP1_index", "mcasp0_axr1", "uart5_rxd", "pr1_mii_mr0_clk", "uart5_ctsn", "gpio0_10"),
+ _PIN(0x8dc, "LCD_DATA15", 11, 7, "lcd_data15", "gpmc_a19", "eQEP1_strobe", "mcasp0_ahclkx", "mcasp0_axr3", "pr1_mii0_rxdv", "uart5_rtsn", "gpio0_11"),
+ _PIN(0x8e0, "LCD_VSYNC", 86, 7, "lcd_vsync", "gpmc_a8", "gpmc_a1", "pr1_edio_data_in2", "pr1_edio_data_out2", "pr1_pru1_pru_r30_8", "pr1_pru1_pru_r31_8", "gpio2_22"),
+ _PIN(0x8e4, "LCD_HSYNC", 87, 7, "lcd_hsync", "gmpc_a9", "gpmc_a2", "pr1_edio_data_in3", "pr1_edio_data_out3", "pr1_pru1_pru_r30_9", "pr1_pru1_pru_r31_9", "gpio2_23"),
+ _PIN(0x8e8, "LCD_PCLK", 88, 7, "lcd_pclk", "gpmc_a10", "pr1_mii0_crs", "pr1_edio_data_in4", "pr1_edio_data_out4", "pr1_pru1_pru_r30_10", "pr1_pru1_pru_r31_10", "gpio2_24"),
+ _PIN(0x8ec, "LCD_AC_BIAS_EN", 89, 7, "lcd_ac_bias_en", "gpmc_a11", "pr1_mii1_crs", "pr1_edio_data_in5", "pr1_edio_data_out5", "pr1_pru1_pru_r30_11", "pr1_pru1_pru_r31_11", "gpio2_25"),
+ _PIN(0x8f0, "MMC0_DAT3", 90, 7, "mmc0_dat3", "gpmc_a20", "uart4_ctsn", "timer5", "uart1_dcdn", "pr1_pru0_pru_r30_8", "pr1_pru0_pru_r31_8", "gpio2_26"),
+ _PIN(0x8f4, "MMC0_DAT2", 91, 7, "mmc0_dat2", "gpmc_a21", "uart4_rtsn", "timer6", "uart1_dsrn", "pr1_pru0_pru_r30_9", "pr1_pru0_pru_r31_9", "gpio2_27"),
+ _PIN(0x8f8, "MMC0_DAT1", 92, 7, "mmc0_dat1", "gpmc_a22", "uart5_ctsn", "uart3_rxd", "uart1_dtrn", "pr1_pru0_pru_r30_10", "pr1_pru0_pru_r31_10", "gpio2_28"),
+ _PIN(0x8fc, "MMC0_DAT0", 93, 7, "mmc0_dat0", "gpmc_a23", "uart5_rtsn", "uart3_txd", "uart1_rin", "pr1_pru0_pru_r30_11", "pr1_pru0_pru_r31_11", "gpio2_29"),
+ _PIN(0x900, "MMC0_CLK", 94, 7, "mmc0_clk", "gpmc_a24", "uart3_ctsn", "uart2_rxd", "dcan1_tx", "pr1_pru0_pru_r30_12", "pr1_pru0_pru_r31_12", "gpio2_30"),
+ _PIN(0x904, "MMC0_CMD", 95, 7, "mmc0_cmd", "gpmc_a25", "uart3_rtsn", "uart2_txd", "dcan1_rx", "pr1_pru0_pru_r30_13", "pr1_pru0_pru_r31_13", "gpio2_31"),
+ _PIN(0x908, "MII1_COL", 96, 7, "gmii1_col", "rmii2_refclk", "spi1_sclk", "uart5_rxd", "mcasp1_axr2", "mmc2_dat3", "mcasp0_axr2", "gpio3_0"),
+ _PIN(0x90c, "MII1_CRS", 97, 7, "gmii1_crs", "rmii1_crs_dv", "spi1_d0", "I2C1_SDA", "mcasp1_aclkx", "uart5_ctsn", "uart2_rxd", "gpio3_1"),
+ _PIN(0x910, "MII1_RX_ER", 98, 7, "gmii1_rxerr", "rmii1_rxerr", "spi1_d1", "I2C1_SCL", "mcasp1_fsx", "uart5_rtsn", "uart2_txd", "gpio3_2"),
+ _PIN(0x914, "MII1_TX_EN", 99, 7, "gmii1_txen", "rmii1_txen", "rgmii1_tctl", "timer4", "mcasp1_axr0", "eQEP0_index", "mmc2_cmd", "gpio3_3"),
+ _PIN(0x918, "MII1_RX_DV", 100, 7, "gmii1_rxdv", "cd_memory_clk", "rgmii1_rctl", "uart5_txd", "mcasp1_aclkx", "mmc2_dat0", "mcasp0_aclkr", "gpio3_4"),
+ _PIN(0x91c, "MII1_TXD3", 16, 7, "gmii1_txd3", "dcan0_tx", "rgmii1_td3", "uart4_rxd", "mcasp1_fsx", "mmc2_dat1", "mcasp0_fsr", "gpio0_16"),
+ _PIN(0x920, "MII1_TXD2", 17, 7, "gmii1_txd2", "dcan0_rx", "rgmii1_td2", "uart4_txd", "mcasp1_axr0", "mmc2_dat2", "mcasp0_ahclkx", "gpio0_17"),
+ _PIN(0x924, "MII1_TXD1", 21, 7, "gmii1_txd1", "rmii1_txd1", "rgmii1_td1", "mcasp1_fsr", "mcasp1_axr1", "eQEP0A_in", "mmc1_cmd", "gpio0_21"),
+ _PIN(0x928, "MII1_TXD0", 28, 7, "gmii1_txd0", "rmii1_txd0", "rgmii1_td0", "mcasp1_axr2", "mcasp1_aclkr", "eQEP0B_in", "mmc1_clk", "gpio0_28"),
+ _PIN(0x92c, "MII1_TX_CLK", 105, 7, "gmii1_txclk", "uart2_rxd", "rgmii1_tclk", "mmc0_dat7", "mmc1_dat0", "uart1_dcdn", "mcasp0_aclkx", "gpio3_9"),
+ _PIN(0x930, "MII1_RX_CLK", 106, 7, "gmii1_rxclk", "uart2_txd", "rgmii1_rclk", "mmc0_dat6", "mmc1_dat1", "uart1_dsrn", "mcasp0_fsx", "gpio3_10"),
+ _PIN(0x934, "MII1_RXD3", 82, 7, "gmii1_rxd3", "uart3_rxd", "rgmii1_rd3", "mmc0_dat5", "mmc1_dat2", "uart1_dtrn", "mcasp0_axr0", "gpio2_18"),
+ _PIN(0x938, "MII1_RXD2", 83, 7, "gmii1_rxd2", "uart3_txd", "rgmii1_rd2", "mmc0_dat4", "mmc1_dat3", "uart1_rin", "mcasp0_axr1", "gpio2_19"),
+ _PIN(0x93c, "MII1_RXD1", 84, 7, "gmii1_rxd1", "rmii1_rxd1", "rgmii1_rd1", "mcasp1_axr3", "mcasp1_fsr", "eQEP0_strobe", "mmc2_clk", "gpio2_20"),
+ _PIN(0x940, "MII1_RXD0", 85, 7, "gmii1_rxd0", "rmii1_rxd0", "rgmii1_rd0", "mcasp1_ahclkx", "mcasp1_ahclkr", "mcasp1_aclkr", "mcasp0_axr3", "gpio2_21"),
+ _PIN(0x944, "RMII1_REF_CLK", 29, 7, "rmii1_refclk", "xdma_event_intr2", "spi1_cs0", "uart5_txd", "mcasp1_axr3", "mmc0_pow", "mcasp1_ahclkx", "gpio0_29"),
+ _PIN(0x948, "MDIO", 0, 7, "mdio_data", "timer6", "uart5_rxd", "uart3_ctsn", "mmc0_sdcd","mmc1_cmd", "mmc2_cmd","gpio0_0"),
+ _PIN(0x94c, "MDC", 1, 7, "mdio_clk", "timer5", "uart5_txd", "uart3_rtsn", "mmc0_sdwp", "mmc1_clk", "mmc2_clk", "gpio0_1"),
+ _PIN(0x950, "SPI0_SCLK", 2, 7, "spi0_sclk", "uart2_rxd", "I2C2_SDA", "ehrpwm0A", "pr1_uart0_cts_n", "pr1_edio_sof", "EMU2", "gpio0_2"),
+ _PIN(0x954, "SPI0_D0", 3, 7, "spi0_d0", "uart2_txd", "I2C2_SCL", "ehrpwm0B", "pr1_uart0_rts_n", "pr1_edio_latch_in", "EMU3", "gpio0_3"),
+ _PIN(0x958, "SPI0_D1", 4, 7, "spi0_d1", "mmc1_sdwp", "I2C1_SDA", "ehrpwm0_tripzone_input", "pr1_uart0_rxd", "pr1_edio_data_in0", "pr1_edio_data_out0", "gpio0_4"),
+ _PIN(0x95c, "SPI0_CS0", 5, 7, "spi0_cs0", "mmc2_sdwp", "I2C1_SCL", "ehrpwm0_synci", "pr1_uart0_txd", "pr1_edio_data_in1", "pr1_edio_data_out1", "gpio0_5"),
+ _PIN(0x960, "SPI0_CS1", 6, 7, "spi0_cs1", "uart3_rxd", "eCAP1_in_PWM1_out", "mcc0_pow", "xdm_event_intr2", "mmc0_sdcd", "EMU4", "gpio0_6"),
+ _PIN(0x964, "ECAP0_IN_PWM0_OUT",7, 7, "eCAP0_in_PWM0_out", "uart3_txd", "spi1_cs1", "pr1_ecap0_ecap_capin_apwm_o", "spi1_sclk", "mmc0_sdwp", "xdma_event_intr2", "gpio0_7"),
+ _PIN(0x968, "UART0_CTSn", 40, 7, "uart0_ctsn", "uart4_rxd", "dcan1_tx", "I2C1_SDA", "spi1_d0", "timer7", "pr1_edc_sync0_out", "gpio1_8"),
+ _PIN(0x96c, "UART0_RTSn", 41, 7, "uart0_rtsn", "uart4_txd", "dcan1_rx", "I2C1_SCL", "spi1_d1", "spi1_cs0", "pr1_edc_sync1_out", "gpio1_9"),
+ _PIN(0x970, "UART0_rxd", 42, 7, "uart0_rxd", "spi1_cs0", "dcan0_tx", "I2C2_SDA", "eCAP2_in_PWM2_out", "pr1_pru1_pru_r30_14", "pr1_pru1_pru_r31_14", "gpio1_10"),
+ _PIN(0x974, "UART0_txd", 43, 7, "uart0_txd", "spi1_cs1", "dcan0_rx", "I2C2_SCL", "eCAP1_in_PWM1_out", "pr1_pru1_pru_r30_15", "pr1_pru1_pru_r31_15", "gpio1_11"),
+ _PIN(0x978, "UART1_CTSn", 12, 7, "uart1_ctsn", "timer6_mux1", "dcan0_tx", "I2C2_SDA", "spi1_cs0", "pr1_uart0_cts_n", "pr1_edc_latch0_in", "gpio0_12"),
+ _PIN(0x97c, "UART1_RTSn", 13, 7, "uart1_rtsn", "timer5_mux1", "dcan0_rx", "I2C2_SCL", "spi1_cs1", "pr1_uart0_rts_n", "pr1_edc_latch1_in", "gpio0_13"),
+ _PIN(0x980, "UART1_RXD", 14, 7, "uart1_rxd", "mmc1_sdwp", "dcan1_tx", "I2C1_SDA", NULL, "pr1_uart0_rxd", "pr1_pru1_pru_r31_16", "gpio0_14"),
+ _PIN(0x984, "UART1_TXD", 15, 7, "uart1_txd", "mmc2_sdwp", "dcan1_rx", "I2C1_SCL", NULL, "pr1_uart0_txd", "pr1_pru0_pru_r31_16", "gpio0_15"),
+ _PIN(0x988, "I2C0_SDA", 101, 7, "I2C0_SDA", "timer4", "uart2_ctsn", "eCAP2_in_PWM2_out", NULL, NULL, NULL, "gpio3_5"),
+ _PIN(0x98c, "I2C0_SCL", 102, 7, "I2C0_SCL", "timer7", "uart2_rtsn", "eCAP1_in_PWM1_out", NULL, NULL, NULL, "gpio3_6"),
+ _PIN(0x990, "MCASP0_ACLKX", 110, 7, "mcasp0_aclkx", "ehrpwm0A", NULL, "spi1_sclk", "mmc0_sdcd", "pr1_pru0_pru_r30_0", "pr1_pru0_pru_r31_0", "gpio3_14"),
+ _PIN(0x994, "MCASP0_FSX", 111, 7, "mcasp0_fsx", "ehrpwm0B", NULL, "spi1_d0", "mmc1_sdcd", "pr1_pru0_pru_r30_1", "pr1_pru0_pru_r31_1", "gpio3_15"),
+ _PIN(0x998, "MCASP0_AXR0", 112, 7, "mcasp0_axr0", "ehrpwm0_tripzone_input", NULL, "spi1_d1", "mmc2_sdcd", "pr1_pru0_pru_r30_2", "pr1_pru0_pru_r31_2", "gpio3_16"),
+ _PIN(0x99c, "MCASP0_AHCLKR", 113, 7, "mcasp0_ahclkr", "ehrpwm0_synci", "mcasp0_axr2", "spi1_cs0", "eCAP2_in_PWM2_out", "pr1_pru0_pru_r30_3", "pr1_pru0_pru_r31_3", "gpio3_17"),
+ _PIN(0x9a0, "MCASP0_ACLKR", 114, 7, "mcasp0_aclkr", "eQEP0A_in", "mcasp0_axr2", "mcasp1_aclkx", "mmc0_sdwp", "pr1_pru0_pru_r30_4", "pr1_pru0_pru_r31_4", "gpio3_18"),
+ _PIN(0x9a4, "MCASP0_FSR", 115, 7, "mcasp0_fsr", "eQEP0B_in", "mcasp0_axr3", "mcasp1_fsx", "EMU2", "pr1_pru0_pru_r30_5", "pr1_pru0_pru_r31_5", "gpio3_19"),
+ _PIN(0x9a8, "MCASP0_AXR1", 116, 7, "mcasp0_axr1", "eQEP0_index", NULL, "mcasp1_axr0", "EMU3", "pr1_pru0_pru_r30_6", "pr1_pru0_pru_r31_6", "gpio3_20"),
+ _PIN(0x9ac, "MCASP0_AHCLKX", 117, 7, "mcasp0_ahclkx", "eQEP0_strobe", "mcasp0_axr3", "mcasp1_axr1", "EMU4", "pr1_pru0_pru_r30_7", "pr1_pru0_pru_r31_7", "gpio3_21"),
+ _PIN(0x9b0, "XDMA_EVENT_INTR0", 19, 7, "xdma_event_intr0", NULL, "timer4", "clkout1", "spi1_cs1", "pr1_pru1_pru_r31_16", "EMU2", "gpio0_19"),
+ _PIN(0x9b4, "XDMA_EVENT_INTR1", 20, 7, "xdma_event_intr1", NULL, "tclkin", "clkout2", "timer7", "pr1_pru0_pru_r31_16", "EMU3", "gpio0_20"),
+#if 0
+ _PIN(0x9b8, "nresetin_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9bc, "porz", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9c0, "nnmi", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9c4, "osc0_in", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9c8, "osc0_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9cc, "osc0_vss", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9d0, "tms", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9d4, "tdi", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9d8, "tdo", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9dc, "tck", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9e0, "ntrst", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+#endif
+ _PIN(0x9e4, "EMU0", 103, 7, "EMU0", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_7"),
+ _PIN(0x9e8, "EMU1", 104, 0, "EMU1", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_8"),
+#if 0
+ _PIN(0x9ec, "osc1_in", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9f0, "osc1_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9f4, "osc1_vss", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9f8, "rtc_porz", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9fc, "pmic_power_en", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa00, "ext_wakeup", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa04, "enz_kaldo_1p8v", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+#endif
+ _PIN(0xa08, "USB0_DM", 0, 0, "USB0_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa0c, "USB0_DP", 0, 0, "USB0_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa10, "USB0_CE", 0, 0, "USB0_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa14, "USB0_ID", 0, 0, "USB0_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa18, "USB0_VBUS", 0, 0, "USB0_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa1c, "USB0_DRVVBUS", 18, 7, "USB0_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio0_18"),
+ _PIN(0xa20, "USB1_DM", 0, 0, "USB1_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa24, "USB1_DP", 0, 0, "USB1_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa28, "USB1_CE", 0, 0, "USB1_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa2c, "USB1_ID", 0, 0, "USB1_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa30, "USB1_VBUS", 0, 0, "USB1_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa34, "USB1_DRVVBUS", 109, 7, "USB1_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_13"),
+#if 0
+ _PIN(0xa38, "ddr_resetn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa3c, "ddr_csn0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa40, "ddr_cke", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa44, "ddr_ck", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa48, "ddr_nck", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa4c, "ddr_casn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa50, "ddr_rasn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa54, "ddr_wen", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa58, "ddr_ba0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa5c, "ddr_ba1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa60, "ddr_ba2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa64, "ddr_a0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa68, "ddr_a1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa6c, "ddr_a2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa70, "ddr_a3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa74, "ddr_a4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa78, "ddr_a5", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa7c, "ddr_a6", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa80, "ddr_a7", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa84, "ddr_a8", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa88, "ddr_a9", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa8c, "ddr_a10", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa90, "ddr_a11", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa94, "ddr_a12", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa98, "ddr_a13", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa9c, "ddr_a14", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaa0, "ddr_a15", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaa4, "ddr_odt", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaa8, "ddr_d0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaac, "ddr_d1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xab0, "ddr_d2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xab4, "ddr_d3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xab8, "ddr_d4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xabc, "ddr_d5", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xac0, "ddr_d6", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xac4, "ddr_d7", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xac8, "ddr_d8", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xacc, "ddr_d9", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xad0, "ddr_d10", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xad4, "ddr_d11", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xad8, "ddr_d12", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xadc, "ddr_d13", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xae0, "ddr_d14", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xae4, "ddr_d15", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xae8, "ddr_dqm0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaec, "ddr_dqm1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaf0, "ddr_dqs0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaf4, "ddr_dqsn0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaf8, "ddr_dqs1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xafc, "ddr_dqsn1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb00, "ddr_vref", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb04, "ddr_vtp", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb08, "ddr_strben0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb0c, "ddr_strben1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb2c, "ain0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb28, "ain1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb24, "ain2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb20, "ain3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb1c, "ain4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb18, "ain5", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb14, "ain6", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb10, "ain7", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb30, "vrefp", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb34, "vrefn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb38, "avdd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb3c, "avss", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb40, "iforce", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb44, "vsense", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb48, "testout", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+#endif
+ { .ballname = NULL },
+};
+
+const struct ti_scm_device ti_scm_dev = {
+ .padconf_muxmode_mask = 0x7,
+ .padconf_sate_mask = 0x78,
+ .padstate = ti_padstate_devmap,
+ .padconf = ti_padconf_devmap,
+};
+
+int
+ti_scm_padconf_set_gpioflags(uint32_t gpio, uint32_t flags)
+{
+ unsigned int state = 0;
+ if (flags & GPIO_PIN_OUTPUT) {
+ if (flags & GPIO_PIN_PULLUP)
+ state = PADCONF_OUTPUT_PULLUP;
+ else
+ state = PADCONF_OUTPUT;
+ } else if (flags & GPIO_PIN_INPUT) {
+ if (flags & GPIO_PIN_PULLUP)
+ state = PADCONF_INPUT_PULLUP;
+ else if (flags & GPIO_PIN_PULLDOWN)
+ state = PADCONF_INPUT_PULLDOWN;
+ else
+ state = PADCONF_INPUT;
+ }
+ return ti_scm_padconf_set_gpiomode(gpio, state);
+}
+
+void
+ti_scm_padconf_get_gpioflags(uint32_t gpio, uint32_t *flags)
+{
+ unsigned int state;
+ if (ti_scm_padconf_get_gpiomode(gpio, &state) != 0)
+ *flags = 0;
+ else {
+ switch (state) {
+ case PADCONF_OUTPUT:
+ *flags = GPIO_PIN_OUTPUT;
+ break;
+ case PADCONF_OUTPUT_PULLUP:
+ *flags = GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP;
+ break;
+ case PADCONF_INPUT:
+ *flags = GPIO_PIN_INPUT;
+ break;
+ case PADCONF_INPUT_PULLUP:
+ *flags = GPIO_PIN_INPUT | GPIO_PIN_PULLUP;
+ break;
+ case PADCONF_INPUT_PULLDOWN:
+ *flags = GPIO_PIN_INPUT | GPIO_PIN_PULLDOWN;
+ break;
+ default:
+ *flags = 0;
+ break;
+ }
+ }
+}
+
Property changes on: trunk/sys/arm/ti/am335x/am335x_scm_padconf.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/am335x_usbss.c
===================================================================
--- trunk/sys/arm/ti/am335x/am335x_usbss.c (rev 0)
+++ trunk/sys/arm/ti/am335x/am335x_usbss.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,496 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_usbss.c 278278 2015-02-05 20:03:02Z hselasky $");
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#define USB_DEBUG_VAR usbssdebug
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/musb_otg.h>
+#include <dev/usb/usb_debug.h>
+
+#include <sys/rman.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_scm.h>
+#include <arm/ti/am335x/am335x_scm.h>
+
+#define AM335X_USB_PORTS 2
+
+#define USBSS_REVREG 0x00
+#define USBSS_SYSCONFIG 0x10
+#define USBSS_SYSCONFIG_SRESET 1
+
+#define USBCTRL_REV 0x00
+#define USBCTRL_CTRL 0x14
+#define USBCTRL_STAT 0x18
+#define USBCTRL_IRQ_STAT0 0x30
+#define IRQ_STAT0_RXSHIFT 16
+#define IRQ_STAT0_TXSHIFT 0
+#define USBCTRL_IRQ_STAT1 0x34
+#define IRQ_STAT1_DRVVBUS (1 << 8)
+#define USBCTRL_INTEN_SET0 0x38
+#define USBCTRL_INTEN_SET1 0x3C
+#define USBCTRL_INTEN_USB_ALL 0x1ff
+#define USBCTRL_INTEN_USB_SOF (1 << 3)
+#define USBCTRL_INTEN_CLR0 0x40
+#define USBCTRL_INTEN_CLR1 0x44
+#define USBCTRL_UTMI 0xE0
+#define USBCTRL_UTMI_FSDATAEXT (1 << 1)
+#define USBCTRL_MODE 0xE8
+#define USBCTRL_MODE_IDDIG (1 << 8)
+#define USBCTRL_MODE_IDDIGMUX (1 << 7)
+
+/* USBSS resource + 2 MUSB ports */
+
+#define RES_USBSS 0
+#define RES_USBCTRL(i) (3*i+1)
+#define RES_USBPHY(i) (3*i+2)
+#define RES_USBCORE(i) (3*i+3)
+
+#define USB_WRITE4(sc, idx, reg, val) do { \
+ bus_write_4((sc)->sc_mem_res[idx], (reg), (val)); \
+} while (0)
+
+#define USB_READ4(sc, idx, reg) bus_read_4((sc)->sc_mem_res[idx], (reg))
+
+#define USBSS_WRITE4(sc, reg, val) \
+ USB_WRITE4((sc), RES_USBSS, (reg), (val))
+#define USBSS_READ4(sc, reg) \
+ USB_READ4((sc), RES_USBSS, (reg))
+#define USBCTRL_WRITE4(sc, unit, reg, val) \
+ USB_WRITE4((sc), RES_USBCTRL(unit), (reg), (val))
+#define USBCTRL_READ4(sc, unit, reg) \
+ USB_READ4((sc), RES_USBCTRL(unit), (reg))
+#define USBPHY_WRITE4(sc, unit, reg, val) \
+ USB_WRITE4((sc), RES_USBPHY(unit), (reg), (val))
+#define USBPHY_READ4(sc, unit, reg) \
+ USB_READ4((sc), RES_USBPHY(unit), (reg))
+
+static struct resource_spec am335x_musbotg_mem_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE },
+ { SYS_RES_MEMORY, 4, RF_ACTIVE },
+ { SYS_RES_MEMORY, 5, RF_ACTIVE },
+ { SYS_RES_MEMORY, 6, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+static struct resource_spec am335x_musbotg_irq_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+#ifdef USB_DEBUG
+static int usbssdebug = 0;
+
+static SYSCTL_NODE(_hw_usb, OID_AUTO, am335x_usbss, CTLFLAG_RW, 0, "AM335x USBSS");
+SYSCTL_INT(_hw_usb_am335x_usbss, OID_AUTO, debug, CTLFLAG_RW,
+ &usbssdebug, 0, "Debug level");
+#endif
+
+static device_probe_t musbotg_probe;
+static device_attach_t musbotg_attach;
+static device_detach_t musbotg_detach;
+
+struct musbotg_super_softc {
+ struct musbotg_softc sc_otg[AM335X_USB_PORTS];
+ struct resource *sc_mem_res[AM335X_USB_PORTS*3+1];
+ struct resource *sc_irq_res[AM335X_USB_PORTS+1];
+ void *sc_intr_hdl;
+};
+
+static void
+musbotg_vbus_poll(struct musbotg_super_softc *sc, int port)
+{
+ uint32_t stat;
+
+ if (sc->sc_otg[port].sc_mode == MUSB2_DEVICE_MODE)
+ musbotg_vbus_interrupt(&sc->sc_otg[port], 1);
+ else {
+ stat = USBCTRL_READ4(sc, port, USBCTRL_STAT);
+ musbotg_vbus_interrupt(&sc->sc_otg[port], stat & 1);
+ }
+}
+
+/*
+ * Arg to musbotg_clocks_on and musbot_clocks_off is
+ * a uint32_t * pointing to the SCM register offset.
+ */
+static uint32_t USB_CTRL[] = {SCM_USB_CTRL0, SCM_USB_CTRL1};
+
+static void
+musbotg_clocks_on(void *arg)
+{
+ uint32_t c, reg = *(uint32_t *)arg;
+
+ ti_scm_reg_read_4(reg, &c);
+ c &= ~3; /* Enable power */
+ c |= 1 << 19; /* VBUS detect enable */
+ c |= 1 << 20; /* Session end enable */
+ ti_scm_reg_write_4(reg, c);
+}
+
+static void
+musbotg_clocks_off(void *arg)
+{
+ uint32_t c, reg = *(uint32_t *)arg;
+
+ /* Disable power to PHY */
+ ti_scm_reg_read_4(reg, &c);
+ ti_scm_reg_write_4(reg, c | 3);
+}
+
+static void
+musbotg_ep_int_set(struct musbotg_softc *sc, int ep, int on)
+{
+ struct musbotg_super_softc *ssc = sc->sc_platform_data;
+ uint32_t epmask;
+
+ epmask = ((1 << ep) << IRQ_STAT0_RXSHIFT);
+ epmask |= ((1 << ep) << IRQ_STAT0_TXSHIFT);
+ if (on)
+ USBCTRL_WRITE4(ssc, sc->sc_id,
+ USBCTRL_INTEN_SET0, epmask);
+ else
+ USBCTRL_WRITE4(ssc, sc->sc_id,
+ USBCTRL_INTEN_CLR0, epmask);
+}
+
+static void
+musbotg_usbss_interrupt(void *arg)
+{
+ panic("USBSS real interrupt");
+}
+
+static void
+musbotg_wrapper_interrupt(void *arg)
+{
+ struct musbotg_softc *sc = arg;
+ struct musbotg_super_softc *ssc = sc->sc_platform_data;
+ uint32_t stat, stat0, stat1;
+ stat = USBCTRL_READ4(ssc, sc->sc_id, USBCTRL_STAT);
+ stat0 = USBCTRL_READ4(ssc, sc->sc_id, USBCTRL_IRQ_STAT0);
+ stat1 = USBCTRL_READ4(ssc, sc->sc_id, USBCTRL_IRQ_STAT1);
+ if (stat0)
+ USBCTRL_WRITE4(ssc, sc->sc_id, USBCTRL_IRQ_STAT0, stat0);
+ if (stat1)
+ USBCTRL_WRITE4(ssc, sc->sc_id, USBCTRL_IRQ_STAT1, stat1);
+
+ DPRINTFN(4, "port%d: stat0=%08x stat1=%08x, stat=%08x\n",
+ sc->sc_id, stat0, stat1, stat);
+
+ if (stat1 & IRQ_STAT1_DRVVBUS)
+ musbotg_vbus_interrupt(sc, stat & 1);
+
+ musbotg_interrupt(arg, ((stat0 >> 16) & 0xffff),
+ stat0 & 0xffff, stat1 & 0xff);
+}
+
+static int
+musbotg_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,musb-am33xx"))
+ return (ENXIO);
+
+ device_set_desc(dev, "TI AM33xx integrated USB OTG controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+musbotg_attach(device_t dev)
+{
+ struct musbotg_super_softc *sc = device_get_softc(dev);
+ int err;
+ int i;
+ uint32_t rev, reg;
+
+ /* Request the memory resources */
+ err = bus_alloc_resources(dev, am335x_musbotg_mem_spec,
+ sc->sc_mem_res);
+ if (err) {
+ device_printf(dev,
+ "Error: could not allocate mem resources\n");
+ return (ENXIO);
+ }
+
+ /* Request the IRQ resources */
+ err = bus_alloc_resources(dev, am335x_musbotg_irq_spec,
+ sc->sc_irq_res);
+ if (err) {
+ device_printf(dev,
+ "Error: could not allocate irq resources\n");
+ return (ENXIO);
+ }
+
+ /* Enable device clocks. */
+ ti_prcm_clk_enable(MUSB0_CLK);
+
+ /*
+ * Reset USBSS, USB0 and USB1.
+ * The registers of USB subsystem must not be accessed while the
+ * reset pulse is active (200ns).
+ */
+ USBSS_WRITE4(sc, USBSS_SYSCONFIG, USBSS_SYSCONFIG_SRESET);
+ DELAY(100);
+ i = 10;
+ while (USBSS_READ4(sc, USBSS_SYSCONFIG) & USBSS_SYSCONFIG_SRESET) {
+ DELAY(100);
+ if (i-- == 0) {
+ device_printf(dev, "reset timeout.\n");
+ return (ENXIO);
+ }
+ }
+
+ /* Read the module revision. */
+ rev = USBSS_READ4(sc, USBSS_REVREG);
+ device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n",
+ (rev >> 8) & 7, (rev >> 6) & 3, rev & 63);
+
+ err = bus_setup_intr(dev, sc->sc_irq_res[0],
+ INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)musbotg_usbss_interrupt, sc,
+ &sc->sc_intr_hdl);
+
+ if (err) {
+ sc->sc_intr_hdl = NULL;
+ device_printf(dev, "Failed to setup USBSS interrupt\n");
+ goto error;
+ }
+
+ for (i = 0; i < AM335X_USB_PORTS; i++) {
+ /* setup MUSB OTG USB controller interface softc */
+ sc->sc_otg[i].sc_clocks_on = &musbotg_clocks_on;
+ sc->sc_otg[i].sc_clocks_off = &musbotg_clocks_off;
+ sc->sc_otg[i].sc_clocks_arg = &USB_CTRL[i];
+
+ sc->sc_otg[i].sc_ep_int_set = musbotg_ep_int_set;
+
+ /* initialise some bus fields */
+ sc->sc_otg[i].sc_bus.parent = dev;
+ sc->sc_otg[i].sc_bus.devices = sc->sc_otg[i].sc_devices;
+ sc->sc_otg[i].sc_bus.devices_max = MUSB2_MAX_DEVICES;
+ sc->sc_otg[i].sc_bus.dma_bits = 32;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_otg[i].sc_bus,
+ USB_GET_DMA_TAG(dev), NULL)) {
+ device_printf(dev,
+ "Failed allocate bus mem for musb%d\n", i);
+ return (ENOMEM);
+ }
+ sc->sc_otg[i].sc_io_res = sc->sc_mem_res[RES_USBCORE(i)];
+ sc->sc_otg[i].sc_io_tag =
+ rman_get_bustag(sc->sc_otg[i].sc_io_res);
+ sc->sc_otg[i].sc_io_hdl =
+ rman_get_bushandle(sc->sc_otg[i].sc_io_res);
+ sc->sc_otg[i].sc_io_size =
+ rman_get_size(sc->sc_otg[i].sc_io_res);
+
+ sc->sc_otg[i].sc_irq_res = sc->sc_irq_res[i+1];
+
+ sc->sc_otg[i].sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (!(sc->sc_otg[i].sc_bus.bdev)) {
+ device_printf(dev, "No busdev for musb%d\n", i);
+ goto error;
+ }
+ device_set_ivars(sc->sc_otg[i].sc_bus.bdev,
+ &sc->sc_otg[i].sc_bus);
+
+ err = bus_setup_intr(dev, sc->sc_otg[i].sc_irq_res,
+ INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)musbotg_wrapper_interrupt,
+ &sc->sc_otg[i], &sc->sc_otg[i].sc_intr_hdl);
+ if (err) {
+ sc->sc_otg[i].sc_intr_hdl = NULL;
+ device_printf(dev,
+ "Failed to setup interrupt for musb%d\n", i);
+ goto error;
+ }
+
+ sc->sc_otg[i].sc_id = i;
+ sc->sc_otg[i].sc_platform_data = sc;
+ if (i == 0)
+ sc->sc_otg[i].sc_mode = MUSB2_DEVICE_MODE;
+ else
+ sc->sc_otg[i].sc_mode = MUSB2_HOST_MODE;
+
+ /*
+ * software-controlled function
+ */
+
+ if (sc->sc_otg[i].sc_mode == MUSB2_HOST_MODE) {
+ reg = USBCTRL_READ4(sc, i, USBCTRL_MODE);
+ reg |= USBCTRL_MODE_IDDIGMUX;
+ reg &= ~USBCTRL_MODE_IDDIG;
+ USBCTRL_WRITE4(sc, i, USBCTRL_MODE, reg);
+ USBCTRL_WRITE4(sc, i, USBCTRL_UTMI,
+ USBCTRL_UTMI_FSDATAEXT);
+ } else {
+ reg = USBCTRL_READ4(sc, i, USBCTRL_MODE);
+ reg |= USBCTRL_MODE_IDDIGMUX;
+ reg |= USBCTRL_MODE_IDDIG;
+ USBCTRL_WRITE4(sc, i, USBCTRL_MODE, reg);
+ }
+
+ reg = USBCTRL_INTEN_USB_ALL & ~USBCTRL_INTEN_USB_SOF;
+ USBCTRL_WRITE4(sc, i, USBCTRL_INTEN_SET1, reg);
+ USBCTRL_WRITE4(sc, i, USBCTRL_INTEN_CLR0, 0xffffffff);
+
+ err = musbotg_init(&sc->sc_otg[i]);
+ if (!err)
+ err = device_probe_and_attach(sc->sc_otg[i].sc_bus.bdev);
+
+ if (err)
+ goto error;
+
+ /* poll VBUS one time */
+ musbotg_vbus_poll(sc, i);
+ }
+
+ return (0);
+
+error:
+ musbotg_detach(dev);
+ return (ENXIO);
+}
+
+static int
+musbotg_detach(device_t dev)
+{
+ struct musbotg_super_softc *sc = device_get_softc(dev);
+ device_t bdev;
+ int err;
+ int i;
+
+ for (i = 0; i < AM335X_USB_PORTS; i++) {
+ if (sc->sc_otg[i].sc_bus.bdev) {
+ bdev = sc->sc_otg[i].sc_bus.bdev;
+ device_detach(bdev);
+ device_delete_child(dev, bdev);
+ }
+
+ if (sc->sc_otg[i].sc_irq_res && sc->sc_otg[i].sc_intr_hdl) {
+ /*
+ * only call musbotg_uninit() after musbotg_init()
+ */
+ musbotg_uninit(&sc->sc_otg[i]);
+
+ err = bus_teardown_intr(dev, sc->sc_otg[i].sc_irq_res,
+ sc->sc_otg[i].sc_intr_hdl);
+ sc->sc_otg[i].sc_intr_hdl = NULL;
+ }
+
+ usb_bus_mem_free_all(&sc->sc_otg[i].sc_bus, NULL);
+ }
+
+ if (sc->sc_intr_hdl) {
+ bus_teardown_intr(dev, sc->sc_irq_res[0],
+ sc->sc_intr_hdl);
+ sc->sc_intr_hdl = NULL;
+ }
+
+
+ /* Free resources if any */
+ if (sc->sc_mem_res[0])
+ bus_release_resources(dev, am335x_musbotg_mem_spec,
+ sc->sc_mem_res);
+
+ if (sc->sc_irq_res[0])
+ bus_release_resources(dev, am335x_musbotg_irq_spec,
+ sc->sc_irq_res);
+
+ /* during module unload there are lots of children leftover */
+ device_delete_children(dev);
+
+ return (0);
+}
+
+static device_method_t musbotg_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, musbotg_probe),
+ DEVMETHOD(device_attach, musbotg_attach),
+ DEVMETHOD(device_detach, musbotg_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD_END
+};
+
+static driver_t musbotg_driver = {
+ .name = "musbotg",
+ .methods = musbotg_methods,
+ .size = sizeof(struct musbotg_super_softc),
+};
+
+static devclass_t musbotg_devclass;
+
+DRIVER_MODULE(musbotg, simplebus, musbotg_driver, musbotg_devclass, 0, 0);
+MODULE_DEPEND(musbotg, usb, 1, 1, 1);
Property changes on: trunk/sys/arm/ti/am335x/am335x_usbss.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/files.am335x
===================================================================
--- trunk/sys/arm/ti/am335x/files.am335x (rev 0)
+++ trunk/sys/arm/ti/am335x/files.am335x 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,18 @@
+#$FreeBSD: stable/10/sys/arm/ti/am335x/files.am335x 278079 2015-02-02 12:48:13Z loos $
+
+arm/ti/aintc.c standard
+
+arm/ti/am335x/am335x_dmtimer.c standard
+arm/ti/am335x/am335x_lcd.c optional sc
+arm/ti/am335x/am335x_lcd_syscons.c optional sc
+arm/ti/am335x/am335x_pmic.c optional am335x_pmic
+arm/ti/am335x/am335x_prcm.c standard
+arm/ti/am335x/am335x_pwm.c standard
+arm/ti/am335x/am335x_rtc.c optional am335x_rtc
+arm/ti/am335x/am335x_scm_padconf.c standard
+arm/ti/am335x/am335x_usbss.c optional musb fdt
+
+arm/ti/ti_edma3.c standard
+arm/ti/ti_sdhci.c optional sdhci
+#arm/ti/ti_mmchs.c optional mmc
+arm/ti/cpsw/if_cpsw.c optional cpsw
Property changes on: trunk/sys/arm/ti/am335x/files.am335x
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/ti/am335x/std.am335x
===================================================================
--- trunk/sys/arm/ti/am335x/std.am335x (rev 0)
+++ trunk/sys/arm/ti/am335x/std.am335x 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,19 @@
+# AM335x generic configuration
+#$FreeBSD: stable/10/sys/arm/ti/am335x/std.am335x 266110 2014-05-15 02:41:23Z ian $
+files "../ti/am335x/files.am335x"
+include "../ti/std.ti"
+makeoption ARM_LITTLE_ENDIAN
+
+# Physical memory starts at 0x80000000. We assume images are loaded at
+# 0x80200000, e.g. from u-boot with 'fatload mmc 0 0x80200000 kernel.bin'
+#
+#
+options PHYSADDR=0x80000000
+options KERNPHYSADDR=0x80200000
+makeoptions KERNPHYSADDR=0x80200000
+options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+makeoptions KERNVIRTADDR=0xc0200000
+
+options SOC_TI_AM335X
+
+options ARM_L2_PIPT
Property changes on: trunk/sys/arm/ti/am335x/std.am335x
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/ti/cpsw/if_cpsw.c
===================================================================
--- trunk/sys/arm/ti/cpsw/if_cpsw.c (rev 0)
+++ trunk/sys/arm/ti/cpsw/if_cpsw.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,2198 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * TI Common Platform Ethernet Switch (CPSW) Driver
+ * Found in TI8148 "DaVinci" and AM335x "Sitara" SoCs.
+ *
+ * This controller is documented in the AM335x Technical Reference
+ * Manual, in the TMS320DM814x DaVinci Digital Video Processors TRM
+ * and in the TMS320C6452 3 Port Switch Ethernet Subsystem TRM.
+ *
+ * It is basically a single Ethernet port (port 0) wired internally to
+ * a 3-port store-and-forward switch connected to two independent
+ * "sliver" controllers (port 1 and port 2). You can operate the
+ * controller in a variety of different ways by suitably configuring
+ * the slivers and the Address Lookup Engine (ALE) that routes packets
+ * between the ports.
+ *
+ * This code was developed and tested on a BeagleBone with
+ * an AM335x SoC.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/cpsw/if_cpsw.c 276875 2015-01-09 02:51:06Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/endian.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/ethernet.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+#include <net/if_vlan_var.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+#include <sys/sockio.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "if_cpswreg.h"
+#include "if_cpswvar.h"
+
+#include <arm/ti/ti_scm.h>
+
+#include "miibus_if.h"
+
+/* Device probe/attach/detach. */
+static int cpsw_probe(device_t);
+static void cpsw_init_slots(struct cpsw_softc *);
+static int cpsw_attach(device_t);
+static void cpsw_free_slot(struct cpsw_softc *, struct cpsw_slot *);
+static int cpsw_detach(device_t);
+
+/* Device Init/shutdown. */
+static void cpsw_init(void *);
+static void cpsw_init_locked(void *);
+static int cpsw_shutdown(device_t);
+static void cpsw_shutdown_locked(struct cpsw_softc *);
+
+/* Device Suspend/Resume. */
+static int cpsw_suspend(device_t);
+static int cpsw_resume(device_t);
+
+/* Ioctl. */
+static int cpsw_ioctl(struct ifnet *, u_long command, caddr_t data);
+
+static int cpsw_miibus_readreg(device_t, int phy, int reg);
+static int cpsw_miibus_writereg(device_t, int phy, int reg, int value);
+
+/* Send/Receive packets. */
+static void cpsw_intr_rx(void *arg);
+static struct mbuf *cpsw_rx_dequeue(struct cpsw_softc *);
+static void cpsw_rx_enqueue(struct cpsw_softc *);
+static void cpsw_start(struct ifnet *);
+static void cpsw_tx_enqueue(struct cpsw_softc *);
+static int cpsw_tx_dequeue(struct cpsw_softc *);
+
+/* Misc interrupts and watchdog. */
+static void cpsw_intr_rx_thresh(void *);
+static void cpsw_intr_misc(void *);
+static void cpsw_tick(void *);
+static void cpsw_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int cpsw_ifmedia_upd(struct ifnet *);
+static void cpsw_tx_watchdog(struct cpsw_softc *);
+
+/* ALE support */
+static void cpsw_ale_read_entry(struct cpsw_softc *, uint16_t idx, uint32_t *ale_entry);
+static void cpsw_ale_write_entry(struct cpsw_softc *, uint16_t idx, uint32_t *ale_entry);
+static int cpsw_ale_mc_entry_set(struct cpsw_softc *, uint8_t portmap, uint8_t *mac);
+static int cpsw_ale_update_addresses(struct cpsw_softc *, int purge);
+static void cpsw_ale_dump_table(struct cpsw_softc *);
+
+/* Statistics and sysctls. */
+static void cpsw_add_sysctls(struct cpsw_softc *);
+static void cpsw_stats_collect(struct cpsw_softc *);
+static int cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS);
+
+/*
+ * Arbitrary limit on number of segments in an mbuf to be transmitted.
+ * Packets with more segments than this will be defragmented before
+ * they are queued.
+ */
+#define CPSW_TXFRAGS 8
+
+
+/*
+ * TODO: The CPSW subsystem (CPSW_SS) can drive two independent PHYs
+ * as separate Ethernet ports. To properly support this, we should
+ * break this into two separate devices: a CPSW_SS device that owns
+ * the interrupts and actually talks to the CPSW hardware, and a
+ * separate CPSW Ethernet child device for each Ethernet port. The RX
+ * interrupt, for example, would be part of CPSW_SS; it would receive
+ * a packet, note the input port, and then dispatch it to the child
+ * device's interface queue. Similarly for transmit.
+ *
+ * It's not clear to me whether the device tree should be restructured
+ * with a cpsw_ss node and two child nodes. That would allow specifying
+ * MAC addresses for each port, for example, but might be overkill.
+ *
+ * Unfortunately, I don't have hardware right now that supports two
+ * Ethernet ports via CPSW.
+ */
+
+static device_method_t cpsw_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, cpsw_probe),
+ DEVMETHOD(device_attach, cpsw_attach),
+ DEVMETHOD(device_detach, cpsw_detach),
+ DEVMETHOD(device_shutdown, cpsw_shutdown),
+ DEVMETHOD(device_suspend, cpsw_suspend),
+ DEVMETHOD(device_resume, cpsw_resume),
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, cpsw_miibus_readreg),
+ DEVMETHOD(miibus_writereg, cpsw_miibus_writereg),
+ { 0, 0 }
+};
+
+static driver_t cpsw_driver = {
+ "cpsw",
+ cpsw_methods,
+ sizeof(struct cpsw_softc),
+};
+
+static devclass_t cpsw_devclass;
+
+DRIVER_MODULE(cpsw, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
+DRIVER_MODULE(miibus, cpsw, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(cpsw, ether, 1, 1, 1);
+MODULE_DEPEND(cpsw, miibus, 1, 1, 1);
+
+static struct resource_spec res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE | RF_SHAREABLE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE | RF_SHAREABLE },
+ { -1, 0 }
+};
+
+/* Number of entries here must match size of stats
+ * array in struct cpsw_softc. */
+static struct cpsw_stat {
+ int reg;
+ char *oid;
+} cpsw_stat_sysctls[CPSW_SYSCTL_COUNT] = {
+ {0x00, "GoodRxFrames"},
+ {0x04, "BroadcastRxFrames"},
+ {0x08, "MulticastRxFrames"},
+ {0x0C, "PauseRxFrames"},
+ {0x10, "RxCrcErrors"},
+ {0x14, "RxAlignErrors"},
+ {0x18, "OversizeRxFrames"},
+ {0x1c, "RxJabbers"},
+ {0x20, "ShortRxFrames"},
+ {0x24, "RxFragments"},
+ {0x30, "RxOctets"},
+ {0x34, "GoodTxFrames"},
+ {0x38, "BroadcastTxFrames"},
+ {0x3c, "MulticastTxFrames"},
+ {0x40, "PauseTxFrames"},
+ {0x44, "DeferredTxFrames"},
+ {0x48, "CollisionsTxFrames"},
+ {0x4c, "SingleCollisionTxFrames"},
+ {0x50, "MultipleCollisionTxFrames"},
+ {0x54, "ExcessiveCollisions"},
+ {0x58, "LateCollisions"},
+ {0x5c, "TxUnderrun"},
+ {0x60, "CarrierSenseErrors"},
+ {0x64, "TxOctets"},
+ {0x68, "RxTx64OctetFrames"},
+ {0x6c, "RxTx65to127OctetFrames"},
+ {0x70, "RxTx128to255OctetFrames"},
+ {0x74, "RxTx256to511OctetFrames"},
+ {0x78, "RxTx512to1024OctetFrames"},
+ {0x7c, "RxTx1024upOctetFrames"},
+ {0x80, "NetOctets"},
+ {0x84, "RxStartOfFrameOverruns"},
+ {0x88, "RxMiddleOfFrameOverruns"},
+ {0x8c, "RxDmaOverruns"}
+};
+
+/*
+ * Basic debug support.
+ */
+
+#define IF_DEBUG(sc) if (sc->cpsw_if_flags & IFF_DEBUG)
+
+static void
+cpsw_debugf_head(const char *funcname)
+{
+ int t = (int)(time_second % (24 * 60 * 60));
+
+ printf("%02d:%02d:%02d %s ", t / (60 * 60), (t / 60) % 60, t % 60, funcname);
+}
+
+#include <machine/stdarg.h>
+static void
+cpsw_debugf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ printf("\n");
+
+}
+
+#define CPSW_DEBUGF(a) do { \
+ IF_DEBUG(sc) { \
+ cpsw_debugf_head(__func__); \
+ cpsw_debugf a; \
+ } \
+} while (0)
+
+
+/*
+ * Locking macros
+ */
+#define CPSW_TX_LOCK(sc) do { \
+ mtx_assert(&(sc)->rx.lock, MA_NOTOWNED); \
+ mtx_lock(&(sc)->tx.lock); \
+} while (0)
+
+#define CPSW_TX_UNLOCK(sc) mtx_unlock(&(sc)->tx.lock)
+#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx.lock, MA_OWNED)
+
+#define CPSW_RX_LOCK(sc) do { \
+ mtx_assert(&(sc)->tx.lock, MA_NOTOWNED); \
+ mtx_lock(&(sc)->rx.lock); \
+} while (0)
+
+#define CPSW_RX_UNLOCK(sc) mtx_unlock(&(sc)->rx.lock)
+#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx.lock, MA_OWNED)
+
+#define CPSW_GLOBAL_LOCK(sc) do { \
+ if ((mtx_owned(&(sc)->tx.lock) ? 1 : 0) != \
+ (mtx_owned(&(sc)->rx.lock) ? 1 : 0)) { \
+ panic("cpsw deadlock possibility detection!"); \
+ } \
+ mtx_lock(&(sc)->tx.lock); \
+ mtx_lock(&(sc)->rx.lock); \
+} while (0)
+
+#define CPSW_GLOBAL_UNLOCK(sc) do { \
+ CPSW_RX_UNLOCK(sc); \
+ CPSW_TX_UNLOCK(sc); \
+} while (0)
+
+#define CPSW_GLOBAL_LOCK_ASSERT(sc) do { \
+ CPSW_TX_LOCK_ASSERT(sc); \
+ CPSW_RX_LOCK_ASSERT(sc); \
+} while (0)
+
+/*
+ * Read/Write macros
+ */
+#define cpsw_read_4(sc, reg) bus_read_4(sc->res[0], reg)
+#define cpsw_write_4(sc, reg, val) bus_write_4(sc->res[0], reg, val)
+
+#define cpsw_cpdma_bd_offset(i) (CPSW_CPPI_RAM_OFFSET + ((i)*16))
+
+#define cpsw_cpdma_bd_paddr(sc, slot) \
+ BUS_SPACE_PHYSADDR(sc->res[0], slot->bd_offset)
+#define cpsw_cpdma_read_bd(sc, slot, val) \
+ bus_read_region_4(sc->res[0], slot->bd_offset, (uint32_t *) val, 4)
+#define cpsw_cpdma_write_bd(sc, slot, val) \
+ bus_write_region_4(sc->res[0], slot->bd_offset, (uint32_t *) val, 4)
+#define cpsw_cpdma_write_bd_next(sc, slot, next_slot) \
+ cpsw_write_4(sc, slot->bd_offset, cpsw_cpdma_bd_paddr(sc, next_slot))
+#define cpsw_cpdma_read_bd_flags(sc, slot) \
+ bus_read_2(sc->res[0], slot->bd_offset + 14)
+#define cpsw_write_hdp_slot(sc, queue, slot) \
+ cpsw_write_4(sc, (queue)->hdp_offset, cpsw_cpdma_bd_paddr(sc, slot))
+#define CP_OFFSET (CPSW_CPDMA_TX_CP(0) - CPSW_CPDMA_TX_HDP(0))
+#define cpsw_read_cp(sc, queue) \
+ cpsw_read_4(sc, (queue)->hdp_offset + CP_OFFSET)
+#define cpsw_write_cp(sc, queue, val) \
+ cpsw_write_4(sc, (queue)->hdp_offset + CP_OFFSET, (val))
+#define cpsw_write_cp_slot(sc, queue, slot) \
+ cpsw_write_cp(sc, queue, cpsw_cpdma_bd_paddr(sc, slot))
+
+#if 0
+/* XXX temporary function versions for debugging. */
+static void
+cpsw_write_hdp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
+{
+ uint32_t reg = queue->hdp_offset;
+ uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
+ CPSW_DEBUGF(("HDP <=== 0x%08x (was 0x%08x)", v, cpsw_read_4(sc, reg)));
+ cpsw_write_4(sc, reg, v);
+}
+
+static void
+cpsw_write_cp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
+{
+ uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
+ CPSW_DEBUGF(("CP <=== 0x%08x (expecting 0x%08x)", v, cpsw_read_cp(sc, queue)));
+ cpsw_write_cp(sc, queue, v);
+}
+#endif
+
+/*
+ * Expanded dump routines for verbose debugging.
+ */
+static void
+cpsw_dump_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
+{
+ static const char *flags[] = {"SOP", "EOP", "Owner", "EOQ",
+ "TDownCmplt", "PassCRC", "Long", "Short", "MacCtl", "Overrun",
+ "PktErr1", "PortEn/PktErr0", "RxVlanEncap", "Port2", "Port1",
+ "Port0"};
+ struct cpsw_cpdma_bd bd;
+ const char *sep;
+ int i;
+
+ cpsw_cpdma_read_bd(sc, slot, &bd);
+ printf("BD Addr: 0x%08x Next: 0x%08x\n", cpsw_cpdma_bd_paddr(sc, slot), bd.next);
+ printf(" BufPtr: 0x%08x BufLen: 0x%08x\n", bd.bufptr, bd.buflen);
+ printf(" BufOff: 0x%08x PktLen: 0x%08x\n", bd.bufoff, bd.pktlen);
+ printf(" Flags: ");
+ sep = "";
+ for (i = 0; i < 16; ++i) {
+ if (bd.flags & (1 << (15 - i))) {
+ printf("%s%s", sep, flags[i]);
+ sep = ",";
+ }
+ }
+ printf("\n");
+ if (slot->mbuf) {
+ printf(" Ether: %14D\n",
+ (char *)(slot->mbuf->m_hdr.mh_data), " ");
+ printf(" Packet: %16D\n",
+ (char *)(slot->mbuf->m_hdr.mh_data) + 14, " ");
+ }
+}
+
+#define CPSW_DUMP_SLOT(cs, slot) do { \
+ IF_DEBUG(sc) { \
+ cpsw_dump_slot(sc, slot); \
+ } \
+} while (0)
+
+
+static void
+cpsw_dump_queue(struct cpsw_softc *sc, struct cpsw_slots *q)
+{
+ struct cpsw_slot *slot;
+ int i = 0;
+ int others = 0;
+
+ STAILQ_FOREACH(slot, q, next) {
+ if (i > 4)
+ ++others;
+ else
+ cpsw_dump_slot(sc, slot);
+ ++i;
+ }
+ if (others)
+ printf(" ... and %d more.\n", others);
+ printf("\n");
+}
+
+#define CPSW_DUMP_QUEUE(sc, q) do { \
+ IF_DEBUG(sc) { \
+ cpsw_dump_queue(sc, q); \
+ } \
+} while (0)
+
+
+/*
+ *
+ * Device Probe, Attach, Detach.
+ *
+ */
+
+static int
+cpsw_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,cpsw"))
+ return (ENXIO);
+
+ device_set_desc(dev, "3-port Switch Ethernet Subsystem");
+ return (BUS_PROBE_DEFAULT);
+}
+
+
+static void
+cpsw_init_slots(struct cpsw_softc *sc)
+{
+ struct cpsw_slot *slot;
+ int i;
+
+ STAILQ_INIT(&sc->avail);
+
+ /* Put the slot descriptors onto the global avail list. */
+ for (i = 0; i < sizeof(sc->_slots) / sizeof(sc->_slots[0]); i++) {
+ slot = &sc->_slots[i];
+ slot->bd_offset = cpsw_cpdma_bd_offset(i);
+ STAILQ_INSERT_TAIL(&sc->avail, slot, next);
+ }
+}
+
+/*
+ * bind an interrupt, add the relevant info to sc->interrupts
+ */
+static int
+cpsw_attach_interrupt(struct cpsw_softc *sc, struct resource *res, driver_intr_t *handler, const char *description)
+{
+ void **pcookie;
+ int error;
+
+ sc->interrupts[sc->interrupt_count].res = res;
+ sc->interrupts[sc->interrupt_count].description = description;
+ pcookie = &sc->interrupts[sc->interrupt_count].ih_cookie;
+
+ error = bus_setup_intr(sc->dev, res, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, *handler, sc, pcookie);
+ if (error)
+ device_printf(sc->dev,
+ "could not setup %s\n", description);
+ else
+ ++sc->interrupt_count;
+ return (error);
+}
+
+/*
+ * teardown everything in sc->interrupts.
+ */
+static void
+cpsw_detach_interrupts(struct cpsw_softc *sc)
+{
+ int error;
+ int i;
+
+ for (i = 0; i < sizeof(sc->interrupts) / sizeof(sc->interrupts[0]); ++i) {
+ if (!sc->interrupts[i].ih_cookie)
+ continue;
+ error = bus_teardown_intr(sc->dev,
+ sc->interrupts[i].res, sc->interrupts[i].ih_cookie);
+ if (error)
+ device_printf(sc->dev, "could not release %s\n",
+ sc->interrupts[i].description);
+ sc->interrupts[i].ih_cookie = NULL;
+ }
+}
+
+static int
+cpsw_add_slots(struct cpsw_softc *sc, struct cpsw_queue *queue, int requested)
+{
+ const int max_slots = sizeof(sc->_slots) / sizeof(sc->_slots[0]);
+ struct cpsw_slot *slot;
+ int i;
+
+ if (requested < 0)
+ requested = max_slots;
+
+ for (i = 0; i < requested; ++i) {
+ slot = STAILQ_FIRST(&sc->avail);
+ if (slot == NULL)
+ return (0);
+ if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
+ if_printf(sc->ifp, "failed to create dmamap\n");
+ return (ENOMEM);
+ }
+ STAILQ_REMOVE_HEAD(&sc->avail, next);
+ STAILQ_INSERT_TAIL(&queue->avail, slot, next);
+ ++queue->avail_queue_len;
+ ++queue->queue_slots;
+ }
+ return (0);
+}
+
+static int
+cpsw_attach(device_t dev)
+{
+ bus_dma_segment_t segs[1];
+ struct cpsw_softc *sc = device_get_softc(dev);
+ struct mii_softc *miisc;
+ struct ifnet *ifp;
+ void *phy_sc;
+ int error, phy, nsegs;
+ uint32_t reg;
+
+ CPSW_DEBUGF((""));
+
+ getbinuptime(&sc->attach_uptime);
+ sc->dev = dev;
+ sc->node = ofw_bus_get_node(dev);
+
+ /* Get phy address from fdt */
+ if (fdt_get_phyaddr(sc->node, sc->dev, &phy, &phy_sc) != 0) {
+ device_printf(dev, "failed to get PHY address from FDT\n");
+ return (ENXIO);
+ }
+ /* Initialize mutexes */
+ mtx_init(&sc->tx.lock, device_get_nameunit(dev),
+ "cpsw TX lock", MTX_DEF);
+ mtx_init(&sc->rx.lock, device_get_nameunit(dev),
+ "cpsw RX lock", MTX_DEF);
+
+ /* Allocate IO and IRQ resources */
+ error = bus_alloc_resources(dev, res_spec, sc->res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ cpsw_detach(dev);
+ return (ENXIO);
+ }
+
+ reg = cpsw_read_4(sc, CPSW_SS_IDVER);
+ device_printf(dev, "CPSW SS Version %d.%d (%d)\n", (reg >> 8 & 0x7),
+ reg & 0xFF, (reg >> 11) & 0x1F);
+
+ cpsw_add_sysctls(sc);
+
+ /* Allocate a busdma tag and DMA safe memory for mbufs. */
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev), /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ MCLBYTES, CPSW_TXFRAGS, /* maxsize, nsegments */
+ MCLBYTES, 0, /* maxsegsz, flags */
+ NULL, NULL, /* lockfunc, lockfuncarg */
+ &sc->mbuf_dtag); /* dmatag */
+ if (error) {
+ device_printf(dev, "bus_dma_tag_create failed\n");
+ cpsw_detach(dev);
+ return (error);
+ }
+
+ /* Allocate network interface */
+ ifp = sc->ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "if_alloc() failed\n");
+ cpsw_detach(dev);
+ return (ENOMEM);
+ }
+
+ /* Allocate the null mbuf and pre-sync it. */
+ sc->null_mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ memset(sc->null_mbuf->m_hdr.mh_data, 0, sc->null_mbuf->m_ext.ext_size);
+ bus_dmamap_create(sc->mbuf_dtag, 0, &sc->null_mbuf_dmamap);
+ bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, sc->null_mbuf_dmamap,
+ sc->null_mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
+ bus_dmamap_sync(sc->mbuf_dtag, sc->null_mbuf_dmamap,
+ BUS_DMASYNC_PREWRITE);
+ sc->null_mbuf_paddr = segs[0].ds_addr;
+
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
+ ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; //FIXME VLAN?
+ ifp->if_capenable = ifp->if_capabilities;
+
+ ifp->if_init = cpsw_init;
+ ifp->if_start = cpsw_start;
+ ifp->if_ioctl = cpsw_ioctl;
+
+ cpsw_init_slots(sc);
+
+ /* Allocate slots to TX and RX queues. */
+ STAILQ_INIT(&sc->rx.avail);
+ STAILQ_INIT(&sc->rx.active);
+ STAILQ_INIT(&sc->tx.avail);
+ STAILQ_INIT(&sc->tx.active);
+ // For now: 128 slots to TX, rest to RX.
+ // XXX TODO: start with 32/64 and grow dynamically based on demand.
+ if (cpsw_add_slots(sc, &sc->tx, 128) || cpsw_add_slots(sc, &sc->rx, -1)) {
+ device_printf(dev, "failed to allocate dmamaps\n");
+ cpsw_detach(dev);
+ return (ENOMEM);
+ }
+ device_printf(dev, "Initial queue size TX=%d RX=%d\n",
+ sc->tx.queue_slots, sc->rx.queue_slots);
+
+ ifp->if_snd.ifq_drv_maxlen = sc->tx.queue_slots;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
+ IFQ_SET_READY(&ifp->if_snd);
+
+ sc->tx.hdp_offset = CPSW_CPDMA_TX_HDP(0);
+ sc->rx.hdp_offset = CPSW_CPDMA_RX_HDP(0);
+
+ /* Get high part of MAC address from control module (mac_id0_hi) */
+ /* TODO: Get MAC ID1 as well as MAC ID0. */
+ ti_scm_reg_read_4(0x634, ®);
+ sc->mac_addr[0] = reg & 0xFF;
+ sc->mac_addr[1] = (reg >> 8) & 0xFF;
+ sc->mac_addr[2] = (reg >> 16) & 0xFF;
+ sc->mac_addr[3] = (reg >> 24) & 0xFF;
+
+ /* Get low part of MAC address from control module (mac_id0_lo) */
+ ti_scm_reg_read_4(0x630, ®);
+ sc->mac_addr[4] = reg & 0xFF;
+ sc->mac_addr[5] = (reg >> 8) & 0xFF;
+
+ /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
+ /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
+ cpsw_write_4(sc, MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+
+ /* Clear ALE */
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, 1 << 30);
+
+ /* Attach PHY(s) */
+ error = mii_attach(dev, &sc->miibus, ifp, cpsw_ifmedia_upd,
+ cpsw_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
+ if (error) {
+ device_printf(dev, "attaching PHYs failed\n");
+ cpsw_detach(dev);
+ return (error);
+ }
+ sc->mii = device_get_softc(sc->miibus);
+
+ /* Tell the MAC where to find the PHY so autoneg works */
+ miisc = LIST_FIRST(&sc->mii->mii_phys);
+
+ /* Select PHY and enable interrupts */
+ cpsw_write_4(sc, MDIOUSERPHYSEL0, 1 << 6 | (miisc->mii_phy & 0x1F));
+
+ /* Note: We don't use sc->res[3] (TX interrupt) */
+ if (cpsw_attach_interrupt(sc, sc->res[1],
+ cpsw_intr_rx_thresh, "CPSW RX threshold interrupt") ||
+ cpsw_attach_interrupt(sc, sc->res[2],
+ cpsw_intr_rx, "CPSW RX interrupt") ||
+ cpsw_attach_interrupt(sc, sc->res[4],
+ cpsw_intr_misc, "CPSW misc interrupt")) {
+ cpsw_detach(dev);
+ return (ENXIO);
+ }
+
+ ether_ifattach(ifp, sc->mac_addr);
+ callout_init(&sc->watchdog.callout, 0);
+
+ return (0);
+}
+
+static void
+cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
+{
+ int error;
+
+ if (slot->dmamap) {
+ error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
+ KASSERT(error == 0, ("Mapping still active"));
+ slot->dmamap = NULL;
+ }
+ if (slot->mbuf) {
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ }
+}
+
+static int
+cpsw_detach(device_t dev)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
+ int error, i;
+
+ CPSW_DEBUGF((""));
+
+ /* Stop controller and free TX queue */
+ if (device_is_attached(dev)) {
+ ether_ifdetach(sc->ifp);
+ CPSW_GLOBAL_LOCK(sc);
+ cpsw_shutdown_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ callout_drain(&sc->watchdog.callout);
+ }
+
+ bus_generic_detach(dev);
+ if (sc->miibus)
+ device_delete_child(dev, sc->miibus);
+
+ /* Stop and release all interrupts */
+ cpsw_detach_interrupts(sc);
+
+ /* Free dmamaps and mbufs */
+ for (i = 0; i < sizeof(sc->_slots) / sizeof(sc->_slots[0]); ++i)
+ cpsw_free_slot(sc, &sc->_slots[i]);
+ if (sc->null_mbuf_dmamap) {
+ error = bus_dmamap_destroy(sc->mbuf_dtag, sc->null_mbuf_dmamap);
+ KASSERT(error == 0, ("Mapping still active"));
+ }
+ if (sc->null_mbuf)
+ m_freem(sc->null_mbuf);
+
+ /* Free DMA tag */
+ error = bus_dma_tag_destroy(sc->mbuf_dtag);
+ KASSERT(error == 0, ("Unable to destroy DMA tag"));
+
+ /* Free IO memory handler */
+ bus_release_resources(dev, res_spec, sc->res);
+
+ if (sc->ifp != NULL)
+ if_free(sc->ifp);
+
+ /* Destroy mutexes */
+ mtx_destroy(&sc->rx.lock);
+ mtx_destroy(&sc->tx.lock);
+
+ return (0);
+}
+
+/*
+ *
+ * Init/Shutdown.
+ *
+ */
+
+static void
+cpsw_reset(struct cpsw_softc *sc)
+{
+ int i;
+
+ /* Reset RMII/RGMII wrapper. */
+ cpsw_write_4(sc, CPSW_WR_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_WR_SOFT_RESET) & 1)
+ ;
+
+ /* Disable TX and RX interrupts for all cores. */
+ for (i = 0; i < 3; ++i) {
+ cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_TX_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_RX_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_MISC_EN(i), 0x00);
+ }
+
+ /* Reset CPSW subsystem. */
+ cpsw_write_4(sc, CPSW_SS_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_SS_SOFT_RESET) & 1)
+ ;
+
+ /* Reset Sliver port 1 and 2 */
+ for (i = 0; i < 2; i++) {
+ /* Reset */
+ cpsw_write_4(sc, CPSW_SL_SOFT_RESET(i), 1);
+ while (cpsw_read_4(sc, CPSW_SL_SOFT_RESET(i)) & 1)
+ ;
+ }
+
+ /* Reset DMA controller. */
+ cpsw_write_4(sc, CPSW_CPDMA_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_CPDMA_SOFT_RESET) & 1)
+ ;
+
+ /* Disable TX & RX DMA */
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 0);
+
+ /* Clear all queues. */
+ for (i = 0; i < 8; i++) {
+ cpsw_write_4(sc, CPSW_CPDMA_TX_HDP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_HDP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CP(i), 0);
+ }
+
+ /* Clear all interrupt Masks */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
+ cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
+}
+
+static void
+cpsw_init(void *arg)
+{
+ struct cpsw_softc *sc = arg;
+
+ CPSW_DEBUGF((""));
+ CPSW_GLOBAL_LOCK(sc);
+ cpsw_init_locked(arg);
+ CPSW_GLOBAL_UNLOCK(sc);
+}
+
+static void
+cpsw_init_locked(void *arg)
+{
+ struct ifnet *ifp;
+ struct cpsw_softc *sc = arg;
+ struct cpsw_slot *slot;
+ uint32_t i;
+
+ CPSW_DEBUGF((""));
+ ifp = sc->ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
+ getbinuptime(&sc->init_uptime);
+
+ /* Reset the controller. */
+ cpsw_reset(sc);
+
+ /* Enable ALE */
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, 1 << 31 | 1 << 4);
+
+ /* Init Sliver port 1 and 2 */
+ for (i = 0; i < 2; i++) {
+ /* Set Slave Mapping */
+ cpsw_write_4(sc, CPSW_SL_RX_PRI_MAP(i), 0x76543210);
+ cpsw_write_4(sc, CPSW_PORT_P_TX_PRI_MAP(i + 1), 0x33221100);
+ cpsw_write_4(sc, CPSW_SL_RX_MAXLEN(i), 0x5f2);
+ /* Set MACCONTROL for ports 0,1: IFCTL_B(16), IFCTL_A(15),
+ GMII_EN(5), FULLDUPLEX(1) */
+ /* TODO: Docs claim that IFCTL_B and IFCTL_A do the same thing? */
+ /* Huh? Docs call bit 0 "Loopback" some places, "FullDuplex" others. */
+ cpsw_write_4(sc, CPSW_SL_MACCONTROL(i), 1 << 15 | 1 << 5 | 1);
+ }
+
+ /* Set Host Port Mapping */
+ cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
+ cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
+
+ /* Initialize ALE: all ports set to forwarding(3), initialize addrs */
+ for (i = 0; i < 3; i++)
+ cpsw_write_4(sc, CPSW_ALE_PORTCTL(i), 3);
+ cpsw_ale_update_addresses(sc, 1);
+
+ cpsw_write_4(sc, CPSW_SS_PTYPE, 0);
+
+ /* Enable statistics for ports 0, 1 and 2 */
+ cpsw_write_4(sc, CPSW_SS_STAT_PORT_EN, 7);
+
+ /* Experiment: Turn off flow control */
+ /* This seems to fix the watchdog resets that have plagued
+ earlier versions of this driver; I'm not yet sure if there
+ are negative effects yet. */
+ cpsw_write_4(sc, CPSW_SS_FLOW_CONTROL, 0);
+
+ /* Make IP hdr aligned with 4 */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
+
+ /* Initialize RX Buffer Descriptors */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), 0);
+
+ /* Enable TX & RX DMA */
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 1);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 1);
+
+ /* Enable Interrupts for core 0 */
+ cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(0), 0xFF);
+ cpsw_write_4(sc, CPSW_WR_C_RX_EN(0), 0xFF);
+ cpsw_write_4(sc, CPSW_WR_C_MISC_EN(0), 0x3F);
+
+ /* Enable host Error Interrupt */
+ cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_SET, 3);
+
+ /* Enable interrupts for RX Channel 0 */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_SET, 1);
+
+ /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
+ /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
+ cpsw_write_4(sc, MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+
+ /* Select MII in GMII_SEL, Internal Delay mode */
+ //ti_scm_reg_write_4(0x650, 0);
+
+ /* Initialize active queues. */
+ slot = STAILQ_FIRST(&sc->tx.active);
+ if (slot != NULL)
+ cpsw_write_hdp_slot(sc, &sc->tx, slot);
+ slot = STAILQ_FIRST(&sc->rx.active);
+ if (slot != NULL)
+ cpsw_write_hdp_slot(sc, &sc->rx, slot);
+ cpsw_rx_enqueue(sc);
+
+ /* Activate network interface */
+ sc->rx.running = 1;
+ sc->tx.running = 1;
+ sc->watchdog.timer = 0;
+ callout_reset(&sc->watchdog.callout, hz, cpsw_tick, sc);
+ sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+}
+
+static int
+cpsw_shutdown(device_t dev)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
+
+ CPSW_DEBUGF((""));
+ CPSW_GLOBAL_LOCK(sc);
+ cpsw_shutdown_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ return (0);
+}
+
+static void
+cpsw_rx_teardown_locked(struct cpsw_softc *sc)
+{
+ struct mbuf *received, *next;
+ int i = 0;
+
+ CPSW_DEBUGF(("starting RX teardown"));
+ cpsw_write_4(sc, CPSW_CPDMA_RX_TEARDOWN, 0);
+ for (;;) {
+ received = cpsw_rx_dequeue(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ while (received != NULL) {
+ next = received->m_nextpkt;
+ received->m_nextpkt = NULL;
+ (*sc->ifp->if_input)(sc->ifp, received);
+ received = next;
+ }
+ CPSW_GLOBAL_LOCK(sc);
+ if (!sc->rx.running) {
+ CPSW_DEBUGF(("finished RX teardown (%d retries)", i));
+ return;
+ }
+ if (++i > 10) {
+ if_printf(sc->ifp, "Unable to cleanly shutdown receiver\n");
+ return;
+ }
+ DELAY(10);
+ }
+}
+
+static void
+cpsw_tx_teardown_locked(struct cpsw_softc *sc)
+{
+ int i = 0;
+
+ CPSW_DEBUGF(("starting TX teardown"));
+ cpsw_write_4(sc, CPSW_CPDMA_TX_TEARDOWN, 0);
+ cpsw_tx_dequeue(sc);
+ while (sc->tx.running && ++i < 10) {
+ DELAY(10);
+ cpsw_tx_dequeue(sc);
+ }
+ if (sc->tx.running)
+ if_printf(sc->ifp, "Unable to cleanly shutdown transmitter\n");
+ CPSW_DEBUGF(("finished TX teardown (%d retries, %d idle buffers)",
+ i, sc->tx.active_queue_len));
+}
+
+static void
+cpsw_shutdown_locked(struct cpsw_softc *sc)
+{
+ struct ifnet *ifp;
+
+ CPSW_DEBUGF((""));
+ CPSW_GLOBAL_LOCK_ASSERT(sc);
+ ifp = sc->ifp;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
+ /* Disable interface */
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+
+ /* Stop ticker */
+ callout_stop(&sc->watchdog.callout);
+
+ /* Tear down the RX/TX queues. */
+ cpsw_rx_teardown_locked(sc);
+ cpsw_tx_teardown_locked(sc);
+
+ /* Capture stats before we reset controller. */
+ cpsw_stats_collect(sc);
+
+ cpsw_reset(sc);
+}
+
+/*
+ * Suspend/Resume.
+ */
+
+static int
+cpsw_suspend(device_t dev)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
+
+ CPSW_DEBUGF((""));
+ CPSW_GLOBAL_LOCK(sc);
+ cpsw_shutdown_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ return (0);
+}
+
+static int
+cpsw_resume(device_t dev)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
+
+ CPSW_DEBUGF(("UNIMPLEMENTED"));
+ return (0);
+}
+
+/*
+ *
+ * IOCTL
+ *
+ */
+
+static void
+cpsw_set_promisc(struct cpsw_softc *sc, int set)
+{
+ /*
+ * Enabling promiscuous mode requires two bits of work: First,
+ * ALE_BYPASS needs to be enabled. That disables the ALE
+ * forwarding logic and causes every packet to be sent to the
+ * host port. That makes us promiscuous wrt received packets.
+ *
+ * With ALE forwarding disabled, the transmitter needs to set
+ * an explicit output port on every packet to route it to the
+ * correct egress. This should be doable for systems such as
+ * BeagleBone where only one egress port is actually wired to
+ * a PHY. If you have both egress ports wired up, life gets a
+ * lot more interesting.
+ *
+ * Hmmm.... NetBSD driver uses ALE_BYPASS always and doesn't
+ * seem to set explicit egress ports. Does that mean they
+ * are always promiscuous?
+ */
+ if (set) {
+ printf("Promiscuous mode unimplemented\n");
+ }
+}
+
+static void
+cpsw_set_allmulti(struct cpsw_softc *sc, int set)
+{
+ if (set) {
+ printf("All-multicast mode unimplemented\n");
+ }
+}
+
+static int
+cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int error;
+ uint32_t changed;
+
+ error = 0;
+
+ switch (command) {
+ case SIOCSIFFLAGS:
+ CPSW_GLOBAL_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ changed = ifp->if_flags ^ sc->cpsw_if_flags;
+ CPSW_DEBUGF(("SIOCSIFFLAGS: UP & RUNNING (changed=0x%x)", changed));
+ if (changed & IFF_PROMISC)
+ cpsw_set_promisc(sc,
+ ifp->if_flags & IFF_PROMISC);
+ if (changed & IFF_ALLMULTI)
+ cpsw_set_allmulti(sc,
+ ifp->if_flags & IFF_ALLMULTI);
+ } else {
+ CPSW_DEBUGF(("SIOCSIFFLAGS: UP but not RUNNING; starting up"));
+ cpsw_init_locked(sc);
+ }
+ } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ CPSW_DEBUGF(("SIOCSIFFLAGS: not UP but RUNNING; shutting down"));
+ cpsw_shutdown_locked(sc);
+ }
+
+ sc->cpsw_if_flags = ifp->if_flags;
+ CPSW_GLOBAL_UNLOCK(sc);
+ break;
+ case SIOCADDMULTI:
+ cpsw_ale_update_addresses(sc, 0);
+ break;
+ case SIOCDELMULTI:
+ /* Ugh. DELMULTI doesn't provide the specific address
+ being removed, so the best we can do is remove
+ everything and rebuild it all. */
+ cpsw_ale_update_addresses(sc, 1);
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command);
+ break;
+ default:
+ error = ether_ioctl(ifp, command, data);
+ }
+ return (error);
+}
+
+/*
+ *
+ * MIIBUS
+ *
+ */
+static int
+cpsw_miibus_ready(struct cpsw_softc *sc)
+{
+ uint32_t r, retries = CPSW_MIIBUS_RETRIES;
+
+ while (--retries) {
+ r = cpsw_read_4(sc, MDIOUSERACCESS0);
+ if ((r & 1 << 31) == 0)
+ return 1;
+ DELAY(CPSW_MIIBUS_DELAY);
+ }
+ return 0;
+}
+
+static int
+cpsw_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
+ uint32_t cmd, r;
+
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO not ready to read\n");
+ return 0;
+ }
+
+ /* Set GO, reg, phy */
+ cmd = 1 << 31 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
+ cpsw_write_4(sc, MDIOUSERACCESS0, cmd);
+
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO timed out during read\n");
+ return 0;
+ }
+
+ r = cpsw_read_4(sc, MDIOUSERACCESS0);
+ if((r & 1 << 29) == 0) {
+ device_printf(dev, "Failed to read from PHY.\n");
+ r = 0;
+ }
+ return (r & 0xFFFF);
+}
+
+static int
+cpsw_miibus_writereg(device_t dev, int phy, int reg, int value)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
+ uint32_t cmd;
+
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO not ready to write\n");
+ return 0;
+ }
+
+ /* Set GO, WRITE, reg, phy, and value */
+ cmd = 3 << 30 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16
+ | (value & 0xFFFF);
+ cpsw_write_4(sc, MDIOUSERACCESS0, cmd);
+
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO timed out during write\n");
+ return 0;
+ }
+
+ if((cpsw_read_4(sc, MDIOUSERACCESS0) & (1 << 29)) == 0)
+ device_printf(dev, "Failed to write to PHY.\n");
+
+ return 0;
+}
+
+/*
+ *
+ * Transmit/Receive Packets.
+ *
+ */
+
+
+static void
+cpsw_intr_rx(void *arg)
+{
+ struct cpsw_softc *sc = arg;
+ struct mbuf *received, *next;
+
+ CPSW_RX_LOCK(sc);
+ received = cpsw_rx_dequeue(sc);
+ cpsw_rx_enqueue(sc);
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
+ CPSW_RX_UNLOCK(sc);
+
+ while (received != NULL) {
+ next = received->m_nextpkt;
+ received->m_nextpkt = NULL;
+ (*sc->ifp->if_input)(sc->ifp, received);
+ received = next;
+ }
+}
+
+static struct mbuf *
+cpsw_rx_dequeue(struct cpsw_softc *sc)
+{
+ struct cpsw_cpdma_bd bd;
+ struct cpsw_slot *slot;
+ struct ifnet *ifp;
+ struct mbuf *mb_head, *mb_tail;
+ int removed = 0;
+
+ ifp = sc->ifp;
+ mb_head = mb_tail = NULL;
+
+ /* Pull completed packets off hardware RX queue. */
+ while ((slot = STAILQ_FIRST(&sc->rx.active)) != NULL) {
+ cpsw_cpdma_read_bd(sc, slot, &bd);
+ if (bd.flags & CPDMA_BD_OWNER)
+ break; /* Still in use by hardware */
+
+ CPSW_DEBUGF(("Removing received packet from RX queue"));
+ ++removed;
+ STAILQ_REMOVE_HEAD(&sc->rx.active, next);
+ STAILQ_INSERT_TAIL(&sc->rx.avail, slot, next);
+
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+
+ if (bd.flags & CPDMA_BD_TDOWNCMPLT) {
+ CPSW_DEBUGF(("RX teardown in progress"));
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ cpsw_write_cp(sc, &sc->rx, 0xfffffffc);
+ sc->rx.running = 0;
+ break;
+ }
+
+ cpsw_write_cp_slot(sc, &sc->rx, slot);
+
+ /* Set up mbuf */
+ /* TODO: track SOP/EOP bits to assemble a full mbuf
+ out of received fragments. */
+ slot->mbuf->m_hdr.mh_data += bd.bufoff;
+ slot->mbuf->m_hdr.mh_len = bd.pktlen - 4;
+ slot->mbuf->m_pkthdr.len = bd.pktlen - 4;
+ slot->mbuf->m_flags |= M_PKTHDR;
+ slot->mbuf->m_pkthdr.rcvif = ifp;
+ slot->mbuf->m_nextpkt = NULL;
+
+ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
+ /* check for valid CRC by looking into pkt_err[5:4] */
+ if ((bd.flags & CPDMA_BD_PKT_ERR_MASK) == 0) {
+ slot->mbuf->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
+ slot->mbuf->m_pkthdr.csum_flags |= CSUM_IP_VALID;
+ slot->mbuf->m_pkthdr.csum_data = 0xffff;
+ }
+ }
+
+ /* Add mbuf to packet list to be returned. */
+ if (mb_tail) {
+ mb_tail->m_nextpkt = slot->mbuf;
+ } else {
+ mb_head = slot->mbuf;
+ }
+ mb_tail = slot->mbuf;
+ slot->mbuf = NULL;
+ }
+
+ if (removed != 0) {
+ sc->rx.queue_removes += removed;
+ sc->rx.active_queue_len -= removed;
+ sc->rx.avail_queue_len += removed;
+ if (sc->rx.avail_queue_len > sc->rx.max_avail_queue_len)
+ sc->rx.max_avail_queue_len = sc->rx.avail_queue_len;
+ }
+ return (mb_head);
+}
+
+static void
+cpsw_rx_enqueue(struct cpsw_softc *sc)
+{
+ bus_dma_segment_t seg[1];
+ struct cpsw_cpdma_bd bd;
+ struct ifnet *ifp = sc->ifp;
+ struct cpsw_slots tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
+ struct cpsw_slot *slot, *prev_slot = NULL;
+ struct cpsw_slot *last_old_slot, *first_new_slot;
+ int error, nsegs, added = 0;
+
+ /* Register new mbufs with hardware. */
+ while ((slot = STAILQ_FIRST(&sc->rx.avail)) != NULL) {
+ if (slot->mbuf == NULL) {
+ slot->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (slot->mbuf == NULL) {
+ if_printf(sc->ifp, "Unable to fill RX queue\n");
+ break;
+ }
+ slot->mbuf->m_len =
+ slot->mbuf->m_pkthdr.len =
+ slot->mbuf->m_ext.ext_size;
+ }
+
+ error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
+ slot->mbuf, seg, &nsegs, BUS_DMA_NOWAIT);
+
+ KASSERT(nsegs == 1, ("More than one segment (nsegs=%d)", nsegs));
+ KASSERT(error == 0, ("DMA error (error=%d)", error));
+ if (error != 0 || nsegs != 1) {
+ if_printf(ifp,
+ "%s: Can't prep RX buf for DMA (nsegs=%d, error=%d)\n",
+ __func__, nsegs, error);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ break;
+ }
+
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_PREREAD);
+
+ /* Create and submit new rx descriptor*/
+ bd.next = 0;
+ bd.bufptr = seg->ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = MCLBYTES - 1;
+ bd.pktlen = bd.buflen;
+ bd.flags = CPDMA_BD_OWNER;
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ ++added;
+
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ STAILQ_REMOVE_HEAD(&sc->rx.avail, next);
+ sc->rx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ }
+
+ if (added == 0)
+ return;
+
+ CPSW_DEBUGF(("Adding %d buffers to RX queue", added));
+
+ /* Link new entries to hardware RX queue. */
+ last_old_slot = STAILQ_LAST(&sc->rx.active, cpsw_slot, next);
+ first_new_slot = STAILQ_FIRST(&tmpqueue);
+ STAILQ_CONCAT(&sc->rx.active, &tmpqueue);
+ if (first_new_slot == NULL) {
+ return;
+ } else if (last_old_slot == NULL) {
+ /* Start a fresh queue. */
+ cpsw_write_hdp_slot(sc, &sc->rx, first_new_slot);
+ } else {
+ /* Add buffers to end of current queue. */
+ cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
+ /* If underrun, restart queue. */
+ if (cpsw_cpdma_read_bd_flags(sc, last_old_slot) & CPDMA_BD_EOQ) {
+ cpsw_write_hdp_slot(sc, &sc->rx, first_new_slot);
+ }
+ }
+ sc->rx.queue_adds += added;
+ sc->rx.active_queue_len += added;
+ if (sc->rx.active_queue_len > sc->rx.max_active_queue_len) {
+ sc->rx.max_active_queue_len = sc->rx.active_queue_len;
+ }
+}
+
+static void
+cpsw_start(struct ifnet *ifp)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+
+ CPSW_TX_LOCK(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && sc->tx.running) {
+ cpsw_tx_enqueue(sc);
+ cpsw_tx_dequeue(sc);
+ }
+ CPSW_TX_UNLOCK(sc);
+}
+
+static void
+cpsw_tx_enqueue(struct cpsw_softc *sc)
+{
+ bus_dma_segment_t segs[CPSW_TXFRAGS];
+ struct cpsw_cpdma_bd bd;
+ struct cpsw_slots tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
+ struct cpsw_slot *slot, *prev_slot = NULL;
+ struct cpsw_slot *last_old_slot, *first_new_slot;
+ struct mbuf *m0;
+ int error, nsegs, seg, added = 0, padlen;
+
+ /* Pull pending packets from IF queue and prep them for DMA. */
+ while ((slot = STAILQ_FIRST(&sc->tx.avail)) != NULL) {
+ IF_DEQUEUE(&sc->ifp->if_snd, m0);
+ if (m0 == NULL)
+ break;
+
+ slot->mbuf = m0;
+ padlen = ETHER_MIN_LEN - slot->mbuf->m_pkthdr.len;
+ if (padlen < 0)
+ padlen = 0;
+
+ /* Create mapping in DMA memory */
+ error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
+ slot->mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
+ /* If the packet is too fragmented, try to simplify. */
+ if (error == EFBIG ||
+ (error == 0 &&
+ nsegs + (padlen > 0 ? 1 : 0) > sc->tx.avail_queue_len)) {
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ if (padlen > 0) /* May as well add padding. */
+ m_append(slot->mbuf, padlen,
+ sc->null_mbuf->m_hdr.mh_data);
+ m0 = m_defrag(slot->mbuf, M_NOWAIT);
+ if (m0 == NULL) {
+ if_printf(sc->ifp,
+ "Can't defragment packet; dropping\n");
+ m_freem(slot->mbuf);
+ } else {
+ CPSW_DEBUGF(("Requeueing defragmented packet"));
+ IF_PREPEND(&sc->ifp->if_snd, m0);
+ }
+ slot->mbuf = NULL;
+ continue;
+ }
+ if (error != 0) {
+ if_printf(sc->ifp,
+ "%s: Can't setup DMA (error=%d), dropping packet\n",
+ __func__, error);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ break;
+ }
+
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap,
+ BUS_DMASYNC_PREWRITE);
+
+
+ CPSW_DEBUGF(("Queueing TX packet: %d segments + %d pad bytes",
+ nsegs, padlen));
+
+ /* If there is only one segment, the for() loop
+ * gets skipped and the single buffer gets set up
+ * as both SOP and EOP. */
+ /* Start by setting up the first buffer */
+ bd.next = 0;
+ bd.bufptr = segs[0].ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = segs[0].ds_len;
+ bd.pktlen = m_length(slot->mbuf, NULL) + padlen;
+ bd.flags = CPDMA_BD_SOP | CPDMA_BD_OWNER;
+ for (seg = 1; seg < nsegs; ++seg) {
+ /* Save the previous buffer (which isn't EOP) */
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+ slot = STAILQ_FIRST(&sc->tx.avail);
+
+ /* Setup next buffer (which isn't SOP) */
+ bd.next = 0;
+ bd.bufptr = segs[seg].ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = segs[seg].ds_len;
+ bd.pktlen = 0;
+ bd.flags = CPDMA_BD_OWNER;
+ }
+ /* Save the final buffer. */
+ if (padlen <= 0)
+ bd.flags |= CPDMA_BD_EOP;
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+
+ if (padlen > 0) {
+ slot = STAILQ_FIRST(&sc->tx.avail);
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+
+ /* Setup buffer of null pad bytes (definitely EOP) */
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ bd.next = 0;
+ bd.bufptr = sc->null_mbuf_paddr;
+ bd.bufoff = 0;
+ bd.buflen = padlen;
+ bd.pktlen = 0;
+ bd.flags = CPDMA_BD_EOP | CPDMA_BD_OWNER;
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ ++nsegs;
+ }
+
+ if (nsegs > sc->tx.longest_chain)
+ sc->tx.longest_chain = nsegs;
+
+ // TODO: Should we defer the BPF tap until
+ // after all packets are queued?
+ BPF_MTAP(sc->ifp, m0);
+ }
+
+ /* Attach the list of new buffers to the hardware TX queue. */
+ last_old_slot = STAILQ_LAST(&sc->tx.active, cpsw_slot, next);
+ first_new_slot = STAILQ_FIRST(&tmpqueue);
+ STAILQ_CONCAT(&sc->tx.active, &tmpqueue);
+ if (first_new_slot == NULL) {
+ return;
+ } else if (last_old_slot == NULL) {
+ /* Start a fresh queue. */
+ cpsw_write_hdp_slot(sc, &sc->tx, first_new_slot);
+ } else {
+ /* Add buffers to end of current queue. */
+ cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
+ /* If underrun, restart queue. */
+ if (cpsw_cpdma_read_bd_flags(sc, last_old_slot) & CPDMA_BD_EOQ) {
+ cpsw_write_hdp_slot(sc, &sc->tx, first_new_slot);
+ }
+ }
+ sc->tx.queue_adds += added;
+ sc->tx.active_queue_len += added;
+ if (sc->tx.active_queue_len > sc->tx.max_active_queue_len) {
+ sc->tx.max_active_queue_len = sc->tx.active_queue_len;
+ }
+}
+
+static int
+cpsw_tx_dequeue(struct cpsw_softc *sc)
+{
+ struct cpsw_slot *slot, *last_removed_slot = NULL;
+ uint32_t flags, removed = 0;
+
+ slot = STAILQ_FIRST(&sc->tx.active);
+ if (slot == NULL && cpsw_read_cp(sc, &sc->tx) == 0xfffffffc) {
+ CPSW_DEBUGF(("TX teardown of an empty queue"));
+ cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
+ sc->tx.running = 0;
+ return (0);
+ }
+
+ /* Pull completed buffers off the hardware TX queue. */
+ while (slot != NULL) {
+ flags = cpsw_cpdma_read_bd_flags(sc, slot);
+ if (flags & CPDMA_BD_OWNER)
+ break; /* Hardware is still using this packet. */
+
+ CPSW_DEBUGF(("TX removing completed packet"));
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+
+ /* Dequeue any additional buffers used by this packet. */
+ while (slot != NULL && slot->mbuf == NULL) {
+ STAILQ_REMOVE_HEAD(&sc->tx.active, next);
+ STAILQ_INSERT_TAIL(&sc->tx.avail, slot, next);
+ ++removed;
+ last_removed_slot = slot;
+ slot = STAILQ_FIRST(&sc->tx.active);
+ }
+
+ /* TearDown complete is only marked on the SOP for the packet. */
+ if (flags & CPDMA_BD_TDOWNCMPLT) {
+ CPSW_DEBUGF(("TX teardown in progress"));
+ cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
+ // TODO: Increment a count of dropped TX packets
+ sc->tx.running = 0;
+ break;
+ }
+ }
+
+ if (removed != 0) {
+ cpsw_write_cp_slot(sc, &sc->tx, last_removed_slot);
+ sc->tx.queue_removes += removed;
+ sc->tx.active_queue_len -= removed;
+ sc->tx.avail_queue_len += removed;
+ if (sc->tx.avail_queue_len > sc->tx.max_avail_queue_len)
+ sc->tx.max_avail_queue_len = sc->tx.avail_queue_len;
+ }
+ return (removed);
+}
+
+/*
+ *
+ * Miscellaneous interrupts.
+ *
+ */
+
+static void
+cpsw_intr_rx_thresh(void *arg)
+{
+ struct cpsw_softc *sc = arg;
+ uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_RX_THRESH_STAT(0));
+
+ CPSW_DEBUGF(("stat=%x", stat));
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 0);
+}
+
+static void
+cpsw_intr_misc_host_error(struct cpsw_softc *sc)
+{
+ uint32_t intstat;
+ uint32_t dmastat;
+ int txerr, rxerr, txchan, rxchan;
+
+ printf("\n\n");
+ device_printf(sc->dev,
+ "HOST ERROR: PROGRAMMING ERROR DETECTED BY HARDWARE\n");
+ printf("\n\n");
+ intstat = cpsw_read_4(sc, CPSW_CPDMA_DMA_INTSTAT_MASKED);
+ device_printf(sc->dev, "CPSW_CPDMA_DMA_INTSTAT_MASKED=0x%x\n", intstat);
+ dmastat = cpsw_read_4(sc, CPSW_CPDMA_DMASTATUS);
+ device_printf(sc->dev, "CPSW_CPDMA_DMASTATUS=0x%x\n", dmastat);
+
+ txerr = (dmastat >> 20) & 15;
+ txchan = (dmastat >> 16) & 7;
+ rxerr = (dmastat >> 12) & 15;
+ rxchan = (dmastat >> 8) & 7;
+
+ switch (txerr) {
+ case 0: break;
+ case 1: printf("SOP error on TX channel %d\n", txchan);
+ break;
+ case 2: printf("Ownership bit not set on SOP buffer on TX channel %d\n", txchan);
+ break;
+ case 3: printf("Zero Next Buffer but not EOP on TX channel %d\n", txchan);
+ break;
+ case 4: printf("Zero Buffer Pointer on TX channel %d\n", txchan);
+ break;
+ case 5: printf("Zero Buffer Length on TX channel %d\n", txchan);
+ break;
+ case 6: printf("Packet length error on TX channel %d\n", txchan);
+ break;
+ default: printf("Unknown error on TX channel %d\n", txchan);
+ break;
+ }
+
+ if (txerr != 0) {
+ printf("CPSW_CPDMA_TX%d_HDP=0x%x\n",
+ txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_HDP(txchan)));
+ printf("CPSW_CPDMA_TX%d_CP=0x%x\n",
+ txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_CP(txchan)));
+ cpsw_dump_queue(sc, &sc->tx.active);
+ }
+
+ switch (rxerr) {
+ case 0: break;
+ case 2: printf("Ownership bit not set on RX channel %d\n", rxchan);
+ break;
+ case 4: printf("Zero Buffer Pointer on RX channel %d\n", rxchan);
+ break;
+ case 5: printf("Zero Buffer Length on RX channel %d\n", rxchan);
+ break;
+ case 6: printf("Buffer offset too big on RX channel %d\n", rxchan);
+ break;
+ default: printf("Unknown RX error on RX channel %d\n", rxchan);
+ break;
+ }
+
+ if (rxerr != 0) {
+ printf("CPSW_CPDMA_RX%d_HDP=0x%x\n",
+ rxchan, cpsw_read_4(sc,CPSW_CPDMA_RX_HDP(rxchan)));
+ printf("CPSW_CPDMA_RX%d_CP=0x%x\n",
+ rxchan, cpsw_read_4(sc, CPSW_CPDMA_RX_CP(rxchan)));
+ cpsw_dump_queue(sc, &sc->rx.active);
+ }
+
+ printf("\nALE Table\n");
+ cpsw_ale_dump_table(sc);
+
+ // XXX do something useful here??
+ panic("CPSW HOST ERROR INTERRUPT");
+
+ // Suppress this interrupt in the future.
+ cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_CLEAR, intstat);
+ printf("XXX HOST ERROR INTERRUPT SUPPRESSED\n");
+ // The watchdog will probably reset the controller
+ // in a little while. It will probably fail again.
+}
+
+static void
+cpsw_intr_misc(void *arg)
+{
+ struct cpsw_softc *sc = arg;
+ uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_MISC_STAT(0));
+
+ if (stat & 16)
+ CPSW_DEBUGF(("Time sync event interrupt unimplemented"));
+ if (stat & 8)
+ cpsw_stats_collect(sc);
+ if (stat & 4)
+ cpsw_intr_misc_host_error(sc);
+ if (stat & 2)
+ CPSW_DEBUGF(("MDIO link change interrupt unimplemented"));
+ if (stat & 1)
+ CPSW_DEBUGF(("MDIO operation completed interrupt unimplemented"));
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
+}
+
+/*
+ *
+ * Periodic Checks and Watchdog.
+ *
+ */
+
+static void
+cpsw_tick(void *msc)
+{
+ struct cpsw_softc *sc = msc;
+
+ /* Check for TX timeout */
+ cpsw_tx_watchdog(sc);
+
+ /* Check for media type change */
+ mii_tick(sc->mii);
+ if(sc->cpsw_media_status != sc->mii->mii_media.ifm_media) {
+ printf("%s: media type changed (ifm_media=%x)\n", __func__,
+ sc->mii->mii_media.ifm_media);
+ cpsw_ifmedia_upd(sc->ifp);
+ }
+
+ /* Schedule another timeout one second from now */
+ callout_reset(&sc->watchdog.callout, hz, cpsw_tick, sc);
+}
+
+static void
+cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+
+ CPSW_DEBUGF((""));
+ CPSW_TX_LOCK(sc);
+
+ mii = sc->mii;
+ mii_pollstat(mii);
+
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+
+ CPSW_TX_UNLOCK(sc);
+}
+
+static int
+cpsw_ifmedia_upd(struct ifnet *ifp)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+
+ CPSW_DEBUGF((""));
+ if (ifp->if_flags & IFF_UP) {
+ CPSW_GLOBAL_LOCK(sc);
+ sc->cpsw_media_status = sc->mii->mii_media.ifm_media;
+ mii_mediachg(sc->mii);
+ cpsw_init_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ }
+
+ return (0);
+}
+
+static void
+cpsw_tx_watchdog_full_reset(struct cpsw_softc *sc)
+{
+ cpsw_debugf_head("CPSW watchdog");
+ if_printf(sc->ifp, "watchdog timeout\n");
+ cpsw_shutdown_locked(sc);
+ cpsw_init_locked(sc);
+}
+
+static void
+cpsw_tx_watchdog(struct cpsw_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
+
+ CPSW_GLOBAL_LOCK(sc);
+ if (sc->tx.active_queue_len == 0 || (ifp->if_flags & IFF_UP) == 0 ||
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || !sc->tx.running) {
+ sc->watchdog.timer = 0; /* Nothing to do. */
+ } else if (sc->tx.queue_removes > sc->tx.queue_removes_at_last_tick) {
+ sc->watchdog.timer = 0; /* Stuff done while we weren't looking. */
+ } else if (cpsw_tx_dequeue(sc) > 0) {
+ sc->watchdog.timer = 0; /* We just did something. */
+ } else {
+ /* There was something to do but it didn't get done. */
+ ++sc->watchdog.timer;
+ if (sc->watchdog.timer > 2) {
+ sc->watchdog.timer = 0;
+ ++ifp->if_oerrors;
+ ++sc->watchdog.resets;
+ cpsw_tx_watchdog_full_reset(sc);
+ }
+ }
+ sc->tx.queue_removes_at_last_tick = sc->tx.queue_removes;
+ CPSW_GLOBAL_UNLOCK(sc);
+}
+
+/*
+ *
+ * ALE support routines.
+ *
+ */
+
+static void
+cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
+{
+ cpsw_write_4(sc, CPSW_ALE_TBLCTL, idx & 1023);
+ ale_entry[0] = cpsw_read_4(sc, CPSW_ALE_TBLW0);
+ ale_entry[1] = cpsw_read_4(sc, CPSW_ALE_TBLW1);
+ ale_entry[2] = cpsw_read_4(sc, CPSW_ALE_TBLW2);
+}
+
+static void
+cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
+{
+ cpsw_write_4(sc, CPSW_ALE_TBLW0, ale_entry[0]);
+ cpsw_write_4(sc, CPSW_ALE_TBLW1, ale_entry[1]);
+ cpsw_write_4(sc, CPSW_ALE_TBLW2, ale_entry[2]);
+ cpsw_write_4(sc, CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023));
+}
+
+static int
+cpsw_ale_remove_all_mc_entries(struct cpsw_softc *sc)
+{
+ int i;
+ uint32_t ale_entry[3];
+
+ /* First two entries are link address and broadcast. */
+ for (i = 2; i < CPSW_MAX_ALE_ENTRIES; i++) {
+ cpsw_ale_read_entry(sc, i, ale_entry);
+ if (((ale_entry[1] >> 28) & 3) == 1 && /* Address entry */
+ ((ale_entry[1] >> 8) & 1) == 1) { /* MCast link addr */
+ ale_entry[0] = ale_entry[1] = ale_entry[2] = 0;
+ cpsw_ale_write_entry(sc, i, ale_entry);
+ }
+ }
+ return CPSW_MAX_ALE_ENTRIES;
+}
+
+static int
+cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
+{
+ int free_index = -1, matching_index = -1, i;
+ uint32_t ale_entry[3];
+
+ /* Find a matching entry or a free entry. */
+ for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
+ cpsw_ale_read_entry(sc, i, ale_entry);
+
+ /* Entry Type[61:60] is 0 for free entry */
+ if (free_index < 0 && ((ale_entry[1] >> 28) & 3) == 0) {
+ free_index = i;
+ }
+
+ if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) &&
+ (((ale_entry[1] >> 0) & 0xFF) == mac[1]) &&
+ (((ale_entry[0] >>24) & 0xFF) == mac[2]) &&
+ (((ale_entry[0] >>16) & 0xFF) == mac[3]) &&
+ (((ale_entry[0] >> 8) & 0xFF) == mac[4]) &&
+ (((ale_entry[0] >> 0) & 0xFF) == mac[5])) {
+ matching_index = i;
+ break;
+ }
+ }
+
+ if (matching_index < 0) {
+ if (free_index < 0)
+ return (ENOMEM);
+ i = free_index;
+ }
+
+ /* Set MAC address */
+ ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+ ale_entry[1] = mac[0] << 8 | mac[1];
+
+ /* Entry type[61:60] is addr entry(1), Mcast fwd state[63:62] is fw(3)*/
+ ale_entry[1] |= 0xd0 << 24;
+
+ /* Set portmask [68:66] */
+ ale_entry[2] = (portmap & 7) << 2;
+
+ cpsw_ale_write_entry(sc, i, ale_entry);
+
+ return 0;
+}
+
+static void
+cpsw_ale_dump_table(struct cpsw_softc *sc) {
+ int i;
+ uint32_t ale_entry[3];
+ for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
+ cpsw_ale_read_entry(sc, i, ale_entry);
+ if (ale_entry[0] || ale_entry[1] || ale_entry[2]) {
+ printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[0],
+ ale_entry[1], ale_entry[2]);
+ printf("mac: %02x:%02x:%02x:%02x:%02x:%02x ",
+ (ale_entry[1] >> 8) & 0xFF,
+ (ale_entry[1] >> 0) & 0xFF,
+ (ale_entry[0] >>24) & 0xFF,
+ (ale_entry[0] >>16) & 0xFF,
+ (ale_entry[0] >> 8) & 0xFF,
+ (ale_entry[0] >> 0) & 0xFF);
+ printf(((ale_entry[1] >> 8) & 1) ? "mcast " : "ucast ");
+ printf("type: %u ", (ale_entry[1] >> 28) & 3);
+ printf("port: %u ", (ale_entry[2] >> 2) & 7);
+ printf("\n");
+ }
+ }
+ printf("\n");
+}
+
+static int
+cpsw_ale_update_addresses(struct cpsw_softc *sc, int purge)
+{
+ uint8_t *mac;
+ uint32_t ale_entry[3];
+ struct ifnet *ifp = sc->ifp;
+ struct ifmultiaddr *ifma;
+ int i;
+
+ /* Route incoming packets for our MAC address to Port 0 (host). */
+ /* For simplicity, keep this entry at table index 0 in the ALE. */
+ if_addr_rlock(ifp);
+ mac = LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr);
+ ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+ ale_entry[1] = 0x10 << 24 | mac[0] << 8 | mac[1]; /* addr entry + mac */
+ ale_entry[2] = 0; /* port = 0 */
+ cpsw_ale_write_entry(sc, 0, ale_entry);
+
+ /* Set outgoing MAC Address for Ports 1 and 2. */
+ for (i = 1; i < 3; ++i) {
+ cpsw_write_4(sc, CPSW_PORT_P_SA_HI(i),
+ mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]);
+ cpsw_write_4(sc, CPSW_PORT_P_SA_LO(i),
+ mac[5] << 8 | mac[4]);
+ }
+ if_addr_runlock(ifp);
+
+ /* Keep the broadcast address at table entry 1. */
+ ale_entry[0] = 0xffffffff; /* Lower 32 bits of MAC */
+ ale_entry[1] = 0xd000ffff; /* FW (3 << 30), Addr entry (1 << 24), upper 16 bits of Mac */
+ ale_entry[2] = 0x0000001c; /* Forward to all ports */
+ cpsw_ale_write_entry(sc, 1, ale_entry);
+
+ /* SIOCDELMULTI doesn't specify the particular address
+ being removed, so we have to remove all and rebuild. */
+ if (purge)
+ cpsw_ale_remove_all_mc_entries(sc);
+
+ /* Set other multicast addrs desired. */
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ cpsw_ale_mc_entry_set(sc, 7,
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ }
+ if_maddr_runlock(ifp);
+
+ return (0);
+}
+
+/*
+ *
+ * Statistics and Sysctls.
+ *
+ */
+
+#if 0
+static void
+cpsw_stats_dump(struct cpsw_softc *sc)
+{
+ int i;
+ uint32_t r;
+
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
+ cpsw_stat_sysctls[i].reg);
+ CPSW_DEBUGF(("%s: %ju + %u = %ju", cpsw_stat_sysctls[i].oid,
+ (intmax_t)sc->shadow_stats[i], r,
+ (intmax_t)sc->shadow_stats[i] + r));
+ }
+}
+#endif
+
+static void
+cpsw_stats_collect(struct cpsw_softc *sc)
+{
+ int i;
+ uint32_t r;
+
+ CPSW_DEBUGF(("Controller shadow statistics updated."));
+
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
+ cpsw_stat_sysctls[i].reg);
+ sc->shadow_stats[i] += r;
+ cpsw_write_4(sc, CPSW_STATS_OFFSET + cpsw_stat_sysctls[i].reg, r);
+ }
+}
+
+static int
+cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct cpsw_stat *stat;
+ uint64_t result;
+
+ sc = (struct cpsw_softc *)arg1;
+ stat = &cpsw_stat_sysctls[oidp->oid_number];
+ result = sc->shadow_stats[oidp->oid_number];
+ result += cpsw_read_4(sc, CPSW_STATS_OFFSET + stat->reg);
+ return (sysctl_handle_64(oidp, &result, 0, req));
+}
+
+static int
+cpsw_stat_attached(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct bintime t;
+ unsigned result;
+
+ sc = (struct cpsw_softc *)arg1;
+ getbinuptime(&t);
+ bintime_sub(&t, &sc->attach_uptime);
+ result = t.sec;
+ return (sysctl_handle_int(oidp, &result, 0, req));
+}
+
+static int
+cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct bintime t;
+ unsigned result;
+
+ sc = (struct cpsw_softc *)arg1;
+ if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ getbinuptime(&t);
+ bintime_sub(&t, &sc->init_uptime);
+ result = t.sec;
+ } else
+ result = 0;
+ return (sysctl_handle_int(oidp, &result, 0, req));
+}
+
+static void
+cpsw_add_queue_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, struct cpsw_queue *queue)
+{
+ struct sysctl_oid_list *parent;
+
+ parent = SYSCTL_CHILDREN(node);
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "totalBuffers",
+ CTLFLAG_RD, &queue->queue_slots, 0,
+ "Total buffers currently assigned to this queue");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "activeBuffers",
+ CTLFLAG_RD, &queue->active_queue_len, 0,
+ "Buffers currently registered with hardware controller");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxActiveBuffers",
+ CTLFLAG_RD, &queue->max_active_queue_len, 0,
+ "Max value of activeBuffers since last driver reset");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "availBuffers",
+ CTLFLAG_RD, &queue->avail_queue_len, 0,
+ "Buffers allocated to this queue but not currently "
+ "registered with hardware controller");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxAvailBuffers",
+ CTLFLAG_RD, &queue->max_avail_queue_len, 0,
+ "Max value of availBuffers since last driver reset");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalEnqueued",
+ CTLFLAG_RD, &queue->queue_adds, 0,
+ "Total buffers added to queue");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalDequeued",
+ CTLFLAG_RD, &queue->queue_removes, 0,
+ "Total buffers removed from queue");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "longestChain",
+ CTLFLAG_RD, &queue->longest_chain, 0,
+ "Max buffers used for a single packet");
+}
+
+static void
+cpsw_add_watchdog_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, struct cpsw_softc *sc)
+{
+ struct sysctl_oid_list *parent;
+
+ parent = SYSCTL_CHILDREN(node);
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "resets",
+ CTLFLAG_RD, &sc->watchdog.resets, 0,
+ "Total number of watchdog resets");
+}
+
+static void
+cpsw_add_sysctls(struct cpsw_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *stats_node, *queue_node, *node;
+ struct sysctl_oid_list *parent, *stats_parent, *queue_parent;
+ int i;
+
+ ctx = device_get_sysctl_ctx(sc->dev);
+ parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
+
+ SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "attachedSecs",
+ CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_attached, "IU",
+ "Time since driver attach");
+
+ SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "uptime",
+ CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_uptime, "IU",
+ "Seconds since driver init");
+
+ stats_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats",
+ CTLFLAG_RD, NULL, "CPSW Statistics");
+ stats_parent = SYSCTL_CHILDREN(stats_node);
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ SYSCTL_ADD_PROC(ctx, stats_parent, i,
+ cpsw_stat_sysctls[i].oid,
+ CTLTYPE_U64 | CTLFLAG_RD, sc, 0,
+ cpsw_stats_sysctl, "IU",
+ cpsw_stat_sysctls[i].oid);
+ }
+
+ queue_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "queue",
+ CTLFLAG_RD, NULL, "CPSW Queue Statistics");
+ queue_parent = SYSCTL_CHILDREN(queue_node);
+
+ node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "tx",
+ CTLFLAG_RD, NULL, "TX Queue Statistics");
+ cpsw_add_queue_sysctls(ctx, node, &sc->tx);
+
+ node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "rx",
+ CTLFLAG_RD, NULL, "RX Queue Statistics");
+ cpsw_add_queue_sysctls(ctx, node, &sc->rx);
+
+ node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "watchdog",
+ CTLFLAG_RD, NULL, "Watchdog Statistics");
+ cpsw_add_watchdog_sysctls(ctx, node, sc);
+}
+
Property changes on: trunk/sys/arm/ti/cpsw/if_cpsw.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/cpsw/if_cpswreg.h
===================================================================
--- trunk/sys/arm/ti/cpsw/if_cpswreg.h (rev 0)
+++ trunk/sys/arm/ti/cpsw/if_cpswreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,138 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/cpsw/if_cpswreg.h 246276 2013-02-03 01:08:01Z kientzle $
+ */
+
+#ifndef _IF_CPSWREG_H
+#define _IF_CPSWREG_H
+
+#define CPSW_SS_OFFSET 0x0000
+#define CPSW_SS_IDVER (CPSW_SS_OFFSET + 0x00)
+#define CPSW_SS_SOFT_RESET (CPSW_SS_OFFSET + 0x08)
+#define CPSW_SS_STAT_PORT_EN (CPSW_SS_OFFSET + 0x0C)
+#define CPSW_SS_PTYPE (CPSW_SS_OFFSET + 0x10)
+#define CPSW_SS_FLOW_CONTROL (CPSW_SS_OFFSET + 0x24)
+
+#define CPSW_PORT_OFFSET 0x0100
+#define CPSW_PORT_P_MAX_BLKS(p) (CPSW_PORT_OFFSET + 0x08 + ((p) * 0x100))
+#define CPSW_PORT_P_BLK_CNT(p) (CPSW_PORT_OFFSET + 0x0C + ((p) * 0x100))
+#define CPSW_PORT_P_TX_PRI_MAP(p) (CPSW_PORT_OFFSET + 0x118 + ((p-1) * 0x100))
+#define CPSW_PORT_P0_CPDMA_TX_PRI_MAP (CPSW_PORT_OFFSET + 0x01C)
+#define CPSW_PORT_P0_CPDMA_RX_CH_MAP (CPSW_PORT_OFFSET + 0x020)
+#define CPSW_PORT_P_SA_LO(p) (CPSW_PORT_OFFSET + 0x120 + ((p-1) * 0x100))
+#define CPSW_PORT_P_SA_HI(p) (CPSW_PORT_OFFSET + 0x124 + ((p-1) * 0x100))
+
+#define CPSW_CPDMA_OFFSET 0x0800
+#define CPSW_CPDMA_TX_CONTROL (CPSW_CPDMA_OFFSET + 0x04)
+#define CPSW_CPDMA_TX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x08)
+#define CPSW_CPDMA_RX_CONTROL (CPSW_CPDMA_OFFSET + 0x14)
+#define CPSW_CPDMA_RX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x18)
+#define CPSW_CPDMA_SOFT_RESET (CPSW_CPDMA_OFFSET + 0x1c)
+#define CPSW_CPDMA_DMACONTROL (CPSW_CPDMA_OFFSET + 0x20)
+#define CPSW_CPDMA_DMASTATUS (CPSW_CPDMA_OFFSET + 0x24)
+#define CPSW_CPDMA_RX_BUFFER_OFFSET (CPSW_CPDMA_OFFSET + 0x28)
+#define CPSW_CPDMA_TX_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0x80)
+#define CPSW_CPDMA_TX_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0x84)
+#define CPSW_CPDMA_TX_INTMASK_SET (CPSW_CPDMA_OFFSET + 0x88)
+#define CPSW_CPDMA_TX_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0x8C)
+#define CPSW_CPDMA_CPDMA_EOI_VECTOR (CPSW_CPDMA_OFFSET + 0x94)
+#define CPSW_CPDMA_RX_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0xA0)
+#define CPSW_CPDMA_RX_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0xA4)
+#define CPSW_CPDMA_RX_INTMASK_SET (CPSW_CPDMA_OFFSET + 0xA8)
+#define CPSW_CPDMA_RX_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0xAc)
+#define CPSW_CPDMA_DMA_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0xB0)
+#define CPSW_CPDMA_DMA_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0xB4)
+#define CPSW_CPDMA_DMA_INTMASK_SET (CPSW_CPDMA_OFFSET + 0xB8)
+#define CPSW_CPDMA_DMA_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0xBC)
+#define CPSW_CPDMA_RX_FREEBUFFER(p) (CPSW_CPDMA_OFFSET + 0x0e0 + ((p) * 0x04))
+
+#define CPSW_STATS_OFFSET 0x0900
+
+#define CPSW_STATERAM_OFFSET 0x0A00
+#define CPSW_CPDMA_TX_HDP(p) (CPSW_STATERAM_OFFSET + 0x00 + ((p) * 0x04))
+#define CPSW_CPDMA_RX_HDP(p) (CPSW_STATERAM_OFFSET + 0x20 + ((p) * 0x04))
+#define CPSW_CPDMA_TX_CP(p) (CPSW_STATERAM_OFFSET + 0x40 + ((p) * 0x04))
+#define CPSW_CPDMA_RX_CP(p) (CPSW_STATERAM_OFFSET + 0x60 + ((p) * 0x04))
+
+#define CPSW_CPTS_OFFSET 0x0C00
+
+#define CPSW_ALE_OFFSET 0x0D00
+#define CPSW_ALE_CONTROL (CPSW_ALE_OFFSET + 0x08)
+#define CPSW_ALE_TBLCTL (CPSW_ALE_OFFSET + 0x20)
+#define CPSW_ALE_TBLW2 (CPSW_ALE_OFFSET + 0x34)
+#define CPSW_ALE_TBLW1 (CPSW_ALE_OFFSET + 0x38)
+#define CPSW_ALE_TBLW0 (CPSW_ALE_OFFSET + 0x3C)
+#define CPSW_ALE_PORTCTL(p) (CPSW_ALE_OFFSET + 0x40 + ((p) * 0x04))
+
+/* SL1 is at 0x0D80, SL2 is at 0x0DC0 */
+#define CPSW_SL_OFFSET 0x0D80
+#define CPSW_SL_MACCONTROL(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x04)
+#define CPSW_SL_MACSTATUS(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x08)
+#define CPSW_SL_SOFT_RESET(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x0C)
+#define CPSW_SL_RX_MAXLEN(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x10)
+#define CPSW_SL_RX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x18)
+#define CPSW_SL_TX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x1C)
+#define CPSW_SL_RX_PRI_MAP(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x24)
+
+#define MDIO_OFFSET 0x1000
+#define MDIOCONTROL (MDIO_OFFSET + 0x04)
+#define MDIOUSERACCESS0 (MDIO_OFFSET + 0x80)
+#define MDIOUSERPHYSEL0 (MDIO_OFFSET + 0x84)
+
+#define CPSW_WR_OFFSET 0x1200
+#define CPSW_WR_SOFT_RESET (CPSW_WR_OFFSET + 0x04)
+#define CPSW_WR_CONTROL (CPSW_WR_OFFSET + 0x08)
+#define CPSW_WR_INT_CONTROL (CPSW_WR_OFFSET + 0x0c)
+#define CPSW_WR_C_RX_THRESH_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x10)
+#define CPSW_WR_C_RX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x14)
+#define CPSW_WR_C_TX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x18)
+#define CPSW_WR_C_MISC_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x1C)
+#define CPSW_WR_C_RX_THRESH_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x40)
+#define CPSW_WR_C_RX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x44)
+#define CPSW_WR_C_TX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x48)
+#define CPSW_WR_C_MISC_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x4C)
+
+#define CPSW_CPPI_RAM_OFFSET 0x2000
+#define CPSW_CPPI_RAM_SIZE 0x2000
+
+#define CPDMA_BD_SOP (1<<15)
+#define CPDMA_BD_EOP (1<<14)
+#define CPDMA_BD_OWNER (1<<13)
+#define CPDMA_BD_EOQ (1<<12)
+#define CPDMA_BD_TDOWNCMPLT (1<<11)
+#define CPDMA_BD_PKT_ERR_MASK (3<< 4)
+
+struct cpsw_cpdma_bd {
+ volatile uint32_t next;
+ volatile uint32_t bufptr;
+ volatile uint16_t buflen;
+ volatile uint16_t bufoff;
+ volatile uint16_t pktlen;
+ volatile uint16_t flags;
+};
+
+#endif /*_IF_CPSWREG_H */
Property changes on: trunk/sys/arm/ti/cpsw/if_cpswreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/cpsw/if_cpswvar.h
===================================================================
--- trunk/sys/arm/ti/cpsw/if_cpswvar.h (rev 0)
+++ trunk/sys/arm/ti/cpsw/if_cpswvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,125 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/cpsw/if_cpswvar.h 246276 2013-02-03 01:08:01Z kientzle $
+ */
+
+#ifndef _IF_CPSWVAR_H
+#define _IF_CPSWVAR_H
+
+#define CPSW_INTR_COUNT 4
+
+/* MII BUS */
+#define CPSW_MIIBUS_RETRIES 5
+#define CPSW_MIIBUS_DELAY 1000
+
+#define CPSW_MAX_ALE_ENTRIES 1024
+
+#define CPSW_SYSCTL_COUNT 34
+
+struct cpsw_slot {
+ uint32_t bd_offset; /* Offset of corresponding BD within CPPI RAM. */
+ bus_dmamap_t dmamap;
+ struct mbuf *mbuf;
+ STAILQ_ENTRY(cpsw_slot) next;
+};
+STAILQ_HEAD(cpsw_slots, cpsw_slot);
+
+struct cpsw_queue {
+ struct mtx lock;
+ int running;
+ struct cpsw_slots active;
+ struct cpsw_slots avail;
+ uint32_t queue_adds; /* total bufs added */
+ uint32_t queue_removes; /* total bufs removed */
+ uint32_t queue_removes_at_last_tick; /* Used by watchdog */
+ int queue_slots;
+ int active_queue_len;
+ int max_active_queue_len;
+ int avail_queue_len;
+ int max_avail_queue_len;
+ int longest_chain; /* Largest # segments in a single packet. */
+ int hdp_offset;
+};
+
+struct cpsw_softc {
+ struct ifnet *ifp;
+ phandle_t node;
+ device_t dev;
+ struct bintime attach_uptime; /* system uptime when attach happened. */
+ struct bintime init_uptime; /* system uptime when init happened. */
+
+ /* TODO: We should set up a child structure for each port;
+ store mac, phy information, etc, in that structure. */
+ uint8_t mac_addr[ETHER_ADDR_LEN];
+
+ device_t miibus;
+ struct mii_data *mii;
+ /* We expect 1 memory resource and 4 interrupts from the device tree. */
+ struct resource *res[1 + CPSW_INTR_COUNT];
+
+ /* Interrupts get recorded here as we initialize them. */
+ /* Interrupt teardown just walks this list. */
+ struct {
+ struct resource *res;
+ void *ih_cookie;
+ const char *description;
+ } interrupts[CPSW_INTR_COUNT];
+ int interrupt_count;
+
+ uint32_t cpsw_if_flags;
+ int cpsw_media_status;
+
+ struct {
+ int resets;
+ int timer;
+ struct callout callout;
+ } watchdog;
+
+ bus_dma_tag_t mbuf_dtag;
+
+ /* An mbuf full of nulls for TX padding. */
+ bus_dmamap_t null_mbuf_dmamap;
+ struct mbuf *null_mbuf;
+ bus_addr_t null_mbuf_paddr;
+
+ /* RX and TX buffer tracking */
+ struct cpsw_queue rx, tx;
+
+ /* 64-bit versions of 32-bit hardware statistics counters */
+ uint64_t shadow_stats[CPSW_SYSCTL_COUNT];
+
+ /* CPPI STATERAM has 512 slots for building TX/RX queues. */
+ /* TODO: Size here supposedly varies with different versions
+ of the controller. Check DaVinci specs and find a good
+ way to adjust this. One option is to have a separate
+ Device Tree parameter for number slots; another option
+ is to calculate it from the memory size in the device tree. */
+ struct cpsw_slot _slots[CPSW_CPPI_RAM_SIZE / sizeof(struct cpsw_cpdma_bd)];
+ struct cpsw_slots avail;
+};
+
+#endif /*_IF_CPSWVAR_H */
Property changes on: trunk/sys/arm/ti/cpsw/if_cpswvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/files.ti
===================================================================
--- trunk/sys/arm/ti/files.ti (rev 0)
+++ trunk/sys/arm/ti/files.ti 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,28 @@
+#$FreeBSD: stable/10/sys/arm/ti/files.ti 278727 2015-02-13 22:32:02Z ian $
+
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+
+arm/ti/ti_common.c standard
+arm/ti/ti_cpuid.c standard
+arm/ti/ti_machdep.c standard
+arm/ti/ti_prcm.c standard
+arm/ti/ti_scm.c standard
+dev/mbox/mbox_if.m optional ti_mbox
+arm/ti/ti_mbox.c optional ti_mbox
+arm/ti/ti_pruss.c optional ti_pruss
+arm/ti/ti_wdt.c optional ti_wdt
+arm/ti/ti_adc.c optional ti_adc
+arm/ti/ti_gpio.c optional gpio
+arm/ti/ti_i2c.c optional ti_i2c
+
+dev/uart/uart_dev_ti8250.c optional uart
+dev/uart/uart_dev_ns8250.c optional uart
+
Property changes on: trunk/sys/arm/ti/files.ti
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/ti/omap3/omap3_reg.h
===================================================================
--- trunk/sys/arm/ti/omap3/omap3_reg.h (rev 0)
+++ trunk/sys/arm/ti/omap3/omap3_reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,781 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/omap3/omap3_reg.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+/*
+ * Texas Instruments - OMAP3xxx series processors
+ *
+ * Reference:
+ * OMAP35x Applications Processor
+ * Technical Reference Manual
+ * (omap35xx_techref.pdf)
+ *
+ *
+ * Note:
+ * The devices are mapped into address above 0xD000_0000 as the kernel space
+ * memory is at 0xC000_0000 and above. The first 256MB after this is reserved
+ * for the size of the kernel, everything above that is reserved for SoC
+ * devices.
+ *
+ */
+#ifndef _OMAP35XX_REG_H_
+#define _OMAP35XX_REG_H_
+
+#ifndef _LOCORE
+#include <sys/types.h> /* for uint32_t */
+#endif
+
+
+
+
+#define OMAP35XX_SDRAM0_START 0x80000000UL
+#define OMAP35XX_SDRAM1_START 0xA0000000UL
+#define OMAP35XX_SDRAM_BANKS 2
+#define OMAP35XX_SDRAM_BANK_SIZE 0x20000000UL
+
+
+/* Physical/Virtual address for SDRAM controller */
+
+#define OMAP35XX_SMS_VBASE 0x6C000000UL
+#define OMAP35XX_SMS_HWBASE 0x6C000000UL
+#define OMAP35XX_SMS_SIZE 0x01000000UL
+
+#define OMAP35XX_SDRC_VBASE 0x6D000000UL
+#define OMAP35XX_SDRC_HWBASE 0x6D000000UL
+#define OMAP35XX_SDRC_SIZE 0x01000000UL
+
+
+
+/* Physical/Virtual address for I/O space */
+
+#define OMAP35XX_L3_VBASE 0xD0000000UL
+#define OMAP35XX_L3_HWBASE 0x68000000UL
+#define OMAP35XX_L3_SIZE 0x01000000UL
+
+#define OMAP35XX_L4_CORE_VBASE 0xE8000000UL
+#define OMAP35XX_L4_CORE_HWBASE 0x48000000UL
+#define OMAP35XX_L4_CORE_SIZE 0x01000000UL
+
+#define OMAP35XX_L4_WAKEUP_VBASE 0xE8300000UL
+#define OMAP35XX_L4_WAKEUP_HWBASE 0x48300000UL
+#define OMAP35XX_L4_WAKEUP_SIZE 0x00040000UL
+
+#define OMAP35XX_L4_PERIPH_VBASE 0xE9000000UL
+#define OMAP35XX_L4_PERIPH_HWBASE 0x49000000UL
+#define OMAP35XX_L4_PERIPH_SIZE 0x00100000UL
+
+
+/*
+ * L4-CORE Physical/Virtual addresss offsets
+ */
+#define OMAP35XX_SCM_OFFSET 0x00002000UL
+#define OMAP35XX_CM_OFFSET 0x00004000UL
+#define OMAP35XX_SDMA_OFFSET 0x00056000UL
+#define OMAP35XX_I2C3_OFFSET 0x00060000UL
+#define OMAP35XX_USB_TLL_OFFSET 0x00062000UL
+#define OMAP35XX_USB_UHH_OFFSET 0x00064000UL
+#define OMAP35XX_USB_EHCI_OFFSET 0x00064800UL
+
+
+#define OMAP35XX_UART1_OFFSET 0x0006A000UL
+#define OMAP35XX_UART2_OFFSET 0x0006C000UL
+#define OMAP35XX_I2C1_OFFSET 0x00070000UL
+#define OMAP35XX_I2C2_OFFSET 0x00072000UL
+#define OMAP35XX_MCBSP1_OFFSET 0x00074000UL
+#define OMAP35XX_GPTIMER10_OFFSET 0x00086000UL
+#define OMAP35XX_GPTIMER11_OFFSET 0x00088000UL
+#define OMAP35XX_MCBSP5_OFFSET 0x00096000UL
+#define OMAP35XX_MMU1_OFFSET 0x000BD400UL
+#define OMAP35XX_INTCPS_OFFSET 0x00200000UL
+
+
+/*
+ * L4-WAKEUP Physical/Virtual addresss offsets
+ */
+#define OMAP35XX_PRM_OFFSET 0x00006000UL
+#define OMAP35XX_GPIO1_OFFSET 0x00010000UL
+#define OMAP35XX_GPTIMER1_OFFSET 0x00018000UL
+
+
+
+/*
+ * L4-PERIPH Physical/Virtual addresss offsets
+ */
+#define OMAP35XX_UART3_OFFSET 0x00020000UL
+#define OMAP35XX_MCBSP2_OFFSET 0x00022000UL
+#define OMAP35XX_MCBSP3_OFFSET 0x00024000UL
+#define OMAP35XX_MCBSP4_OFFSET 0x00026000UL
+#define OMAP35XX_SIDETONE_MCBSP2_OFFSET 0x00028000UL
+#define OMAP35XX_SIDETONE_MCBSP3_OFFSET 0x0002A000UL
+#define OMAP35XX_GPTIMER2_OFFSET 0x00032000UL
+#define OMAP35XX_GPTIMER3_OFFSET 0x00034000UL
+#define OMAP35XX_GPTIMER4_OFFSET 0x00036000UL
+#define OMAP35XX_GPTIMER5_OFFSET 0x00038000UL
+#define OMAP35XX_GPTIMER6_OFFSET 0x0003A000UL
+#define OMAP35XX_GPTIMER7_OFFSET 0x0003C000UL
+#define OMAP35XX_GPTIMER8_OFFSET 0x0003E000UL
+#define OMAP35XX_GPTIMER9_OFFSET 0x00040000UL
+#define OMAP35XX_GPIO2_OFFSET 0x00050000UL
+#define OMAP35XX_GPIO3_OFFSET 0x00052000UL
+#define OMAP35XX_GPIO4_OFFSET 0x00054000UL
+#define OMAP35XX_GPIO5_OFFSET 0x00056000UL
+#define OMAP35XX_GPIO6_OFFSET 0x00058000UL
+
+
+
+
+
+
+/*
+ * System Control Module
+ */
+#define OMAP35XX_SCM_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_SCM_OFFSET)
+#define OMAP35XX_SCM_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_SCM_OFFSET)
+#define OMAP35XX_SCM_SIZE 0x00001000UL
+
+#define OMAP35XX_SCM_REVISION 0x00000000UL
+#define OMAP35XX_SCM_SYSCONFIG 0x00000010UL
+#define OMAP35XX_SCM_PADCONFS_BASE 0x00000030UL
+#define OMAP35XX_SCM_DEVCONF0 0x00000274UL
+#define OMAP35XX_SCM_MEM_DFTRW0 0x00000278UL
+
+
+
+
+/*
+ *
+ */
+#define OMAP35XX_CM_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_CM_OFFSET)
+#define OMAP35XX_CM_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_CM_OFFSET)
+#define OMAP35XX_CM_SIZE 0x00001500UL
+
+#define OMAP35XX_CM_CORE_OFFSET 0x00000A00UL
+#define OMAP35XX_CM_CORE_SIZE 0x00000100UL
+#define OMAP35XX_CM_FCLKEN1_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0000UL)
+#define OMAP35XX_CM_FCLKEN3_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0008UL)
+#define OMAP35XX_CM_ICLKEN1_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0010UL)
+#define OMAP35XX_CM_ICLKEN2_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0014UL)
+#define OMAP35XX_CM_ICLKEN3_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0018UL)
+#define OMAP35XX_CM_IDLEST1_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0020UL)
+#define OMAP35XX_CM_IDLEST2_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0024UL)
+#define OMAP35XX_CM_IDLEST3_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0028UL)
+#define OMAP35XX_CM_AUTOIDLE1_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0030UL)
+#define OMAP35XX_CM_AUTOIDLE2_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0034UL)
+#define OMAP35XX_CM_AUTOIDLE3_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0038UL)
+#define OMAP35XX_CM_CLKSEL_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0040UL)
+#define OMAP35XX_CM_CLKSTCTRL_CORE (OMAP35XX_CM_CORE_OFFSET + 0x0048UL)
+#define OMAP35XX_CM_CLKSTST_CORE (OMAP35XX_CM_CORE_OFFSET + 0x004CUL)
+
+#define OMAP35XX_CM_WKUP_OFFSET 0x00000C00UL
+#define OMAP35XX_CM_WKUP_SIZE 0x00000100UL
+#define OMAP35XX_CM_FCLKEN_WKUP (OMAP35XX_CM_WKUP_OFFSET + 0x0000UL)
+#define OMAP35XX_CM_ICLKEN_WKUP (OMAP35XX_CM_WKUP_OFFSET + 0x0010UL)
+#define OMAP35XX_CM_IDLEST_WKUP (OMAP35XX_CM_WKUP_OFFSET + 0x0020UL)
+#define OMAP35XX_CM_AUTOIDLE_WKUP (OMAP35XX_CM_WKUP_OFFSET + 0x0030UL)
+#define OMAP35XX_CM_CLKSEL_WKUP (OMAP35XX_CM_WKUP_OFFSET + 0x0040UL)
+
+#define OMAP35XX_CM_PLL_OFFSET 0x00000D00UL
+#define OMAP35XX_CM_PLL_SIZE 0x00000100UL
+#define OMAP35XX_CM_CLKEN_PLL (OMAP35XX_CM_PLL_OFFSET + 0x0000UL)
+#define OMAP35XX_CM_CLKEN2_PLL (OMAP35XX_CM_PLL_OFFSET + 0x0004UL)
+#define OMAP35XX_CM_IDLEST_CKGEN (OMAP35XX_CM_PLL_OFFSET + 0x0020UL)
+#define OMAP35XX_CM_IDLEST2_CKGEN (OMAP35XX_CM_PLL_OFFSET + 0x0024UL)
+#define OMAP35XX_CM_AUTOIDLE_PLL (OMAP35XX_CM_PLL_OFFSET + 0x0030UL)
+#define OMAP35XX_CM_AUTOIDLE2_PLL (OMAP35XX_CM_PLL_OFFSET + 0x0034UL)
+#define OMAP35XX_CM_CLKSEL1_PLL (OMAP35XX_CM_PLL_OFFSET + 0x0040UL)
+#define OMAP35XX_CM_CLKSEL2_PLL (OMAP35XX_CM_PLL_OFFSET + 0x0044UL)
+#define OMAP35XX_CM_CLKSEL3_PLL (OMAP35XX_CM_PLL_OFFSET + 0x0048UL)
+#define OMAP35XX_CM_CLKSEL4_PLL (OMAP35XX_CM_PLL_OFFSET + 0x004CUL)
+#define OMAP35XX_CM_CLKSEL5_PLL (OMAP35XX_CM_PLL_OFFSET + 0x0050UL)
+#define OMAP35XX_CM_CLKOUT_CTRL (OMAP35XX_CM_PLL_OFFSET + 0x0070UL)
+
+#define OMAP35XX_CM_PER_OFFSET 0x00001000UL
+#define OMAP35XX_CM_PER_SIZE 0x00000100UL
+#define OMAP35XX_CM_FCLKEN_PER (OMAP35XX_CM_PER_OFFSET + 0x0000UL)
+#define OMAP35XX_CM_ICLKEN_PER (OMAP35XX_CM_PER_OFFSET + 0x0010UL)
+#define OMAP35XX_CM_IDLEST_PER (OMAP35XX_CM_PER_OFFSET + 0x0020UL)
+#define OMAP35XX_CM_AUTOIDLE_PER (OMAP35XX_CM_PER_OFFSET + 0x0030UL)
+#define OMAP35XX_CM_CLKSEL_PER (OMAP35XX_CM_PER_OFFSET + 0x0040UL)
+#define OMAP35XX_CM_SLEEPDEP_PER (OMAP35XX_CM_PER_OFFSET + 0x0044UL)
+#define OMAP35XX_CM_CLKSTCTRL_PER (OMAP35XX_CM_PER_OFFSET + 0x0048UL)
+#define OMAP35XX_CM_CLKSTST_PER (OMAP35XX_CM_PER_OFFSET + 0x004CUL)
+
+#define OMAP35XX_CM_USBHOST_OFFSET 0x00001400UL
+#define OMAP35XX_CM_USBHOST_SIZE 0x00000100UL
+#define OMAP35XX_CM_FCLKEN_USBHOST (OMAP35XX_CM_USBHOST_OFFSET + 0x0000UL)
+#define OMAP35XX_CM_ICLKEN_USBHOST (OMAP35XX_CM_USBHOST_OFFSET + 0x0010UL)
+#define OMAP35XX_CM_IDLEST_USBHOST (OMAP35XX_CM_USBHOST_OFFSET + 0x0020UL)
+#define OMAP35XX_CM_AUTOIDLE_USBHOST (OMAP35XX_CM_USBHOST_OFFSET + 0x0030UL)
+#define OMAP35XX_CM_SLEEPDEP_USBHOST (OMAP35XX_CM_USBHOST_OFFSET + 0x0044UL)
+#define OMAP35XX_CM_CLKSTCTRL_USBHOST (OMAP35XX_CM_USBHOST_OFFSET + 0x0048UL)
+#define OMAP35XX_CM_CLKSTST_USBHOST (OMAP35XX_CM_USBHOST_OFFSET + 0x004CUL)
+
+
+
+
+/*
+ *
+ */
+#define OMAP35XX_PRM_HWBASE (OMAP35XX_L4_WAKEUP_HWBASE + OMAP35XX_PRM_OFFSET)
+#define OMAP35XX_PRM_VBASE (OMAP35XX_L4_WAKEUP_VBASE + OMAP35XX_PRM_OFFSET)
+#define OMAP35XX_PRM_SIZE 0x00001600UL
+
+#define OMAP35XX_PRM_CLKCTRL_OFFSET 0x00000D00UL
+#define OMAP35XX_PRM_CLKCTRL_SIZE 0x00000100UL
+#define OMAP35XX_PRM_CLKSEL (OMAP35XX_PRM_CLKCTRL_OFFSET + 0x0040UL)
+#define OMAP35XX_PRM_CLKOUT_CTRL (OMAP35XX_PRM_CLKCTRL_OFFSET + 0x0070UL)
+
+#define OMAP35XX_PRM_GLOBAL_OFFSET 0x00001200UL
+#define OMAP35XX_PRM_GLOBAL_SIZE 0x00000100UL
+#define OMAP35XX_PRM_CLKSRC_CTRL (OMAP35XX_PRM_GLOBAL_OFFSET + 0x0070UL)
+
+
+
+
+
+/*
+ * Uarts
+ */
+#define OMAP35XX_UART1_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_UART1_OFFSET)
+#define OMAP35XX_UART1_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_UART1_OFFSET)
+#define OMAP35XX_UART1_SIZE 0x00001000UL
+
+#define OMAP35XX_UART2_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_UART2_OFFSET)
+#define OMAP35XX_UART2_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_UART2_OFFSET)
+#define OMAP35XX_UART2_SIZE 0x00001000UL
+
+#define OMAP35XX_UART3_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_UART3_OFFSET)
+#define OMAP35XX_UART3_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_UART3_OFFSET)
+#define OMAP35XX_UART3_SIZE 0x00001000UL
+
+
+
+
+/*
+ * I2C Modules
+ */
+#define OMAP35XX_I2C1_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_I2C1_OFFSET)
+#define OMAP35XX_I2C1_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_I2C1_OFFSET)
+#define OMAP35XX_I2C1_SIZE 0x00000080UL
+
+#define OMAP35XX_I2C2_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_I2C2_OFFSET)
+#define OMAP35XX_I2C2_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_I2C2_OFFSET)
+#define OMAP35XX_I2C2_SIZE 0x00000080UL
+
+#define OMAP35XX_I2C3_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_I2C3_OFFSET)
+#define OMAP35XX_I2C3_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_I2C3_OFFSET)
+#define OMAP35XX_I2C3_SIZE 0x00000080UL
+
+#define OMAP35XX_I2C_IE 0x04
+#define OMAP35XX_I2C_STAT 0x08
+#define OMAP35XX_I2C_WE 0x0C
+#define OMAP35XX_I2C_SYSS 0x10
+#define OMAP35XX_I2C_BUF 0x14
+#define OMAP35XX_I2C_CNT 0x18
+#define OMAP35XX_I2C_DATA 0x1C
+#define OMAP35XX_I2C_SYSC 0x20
+#define OMAP35XX_I2C_CON 0x24
+#define OMAP35XX_I2C_OA0 0x28
+#define OMAP35XX_I2C_SA 0x2C
+#define OMAP35XX_I2C_PSC 0x30
+#define OMAP35XX_I2C_SCLL 0x34
+#define OMAP35XX_I2C_SCLH 0x38
+#define OMAP35XX_I2C_SYSTEST 0x3C
+#define OMAP35XX_I2C_BUFSTAT 0x40
+#define OMAP35XX_I2C_OA1 0x44
+#define OMAP35XX_I2C_OA2 0x48
+#define OMAP35XX_I2C_OA3 0x4C
+#define OMAP35XX_I2C_ACTOA 0x50
+#define OMAP35XX_I2C_SBLOCK 0x54
+
+
+
+/*
+ * McBSP Modules
+ */
+#define OMAP35XX_MCBSP1_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_MCBSP1_OFFSET)
+#define OMAP35XX_MCBSP1_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_MCBSP1_OFFSET)
+#define OMAP35XX_MCBSP1_SIZE 0x00001000UL
+
+#define OMAP35XX_MCBSP2_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_MCBSP2_OFFSET)
+#define OMAP35XX_MCBSP2_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_MCBSP2_OFFSET)
+#define OMAP35XX_MCBSP2_SIZE 0x00001000UL
+
+#define OMAP35XX_MCBSP3_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_MCBSP3_OFFSET)
+#define OMAP35XX_MCBSP3_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_MCBSP3_OFFSET)
+#define OMAP35XX_MCBSP3_SIZE 0x00001000UL
+
+#define OMAP35XX_MCBSP4_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_MCBSP4_OFFSET)
+#define OMAP35XX_MCBSP4_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_MCBSP4_OFFSET)
+#define OMAP35XX_MCBSP4_SIZE 0x00001000UL
+
+#define OMAP35XX_MCBSP5_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_MCBSP5_OFFSET)
+#define OMAP35XX_MCBSP5_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_MCBSP5_OFFSET)
+#define OMAP35XX_MCBSP5_SIZE 0x00001000UL
+
+#define OMAP35XX_MCBSP_DRR 0x0000
+#define OMAP35XX_MCBSP_DXR 0x0008
+#define OMAP35XX_MCBSP_SPCR2 0x0010
+#define OMAP35XX_MCBSP_SPCR1 0x0014
+#define OMAP35XX_MCBSP_RCR2 0x0018
+#define OMAP35XX_MCBSP_RCR1 0x001C
+#define OMAP35XX_MCBSP_XCR2 0x0020
+#define OMAP35XX_MCBSP_XCR1 0x0024
+#define OMAP35XX_MCBSP_SRGR2 0x0028
+#define OMAP35XX_MCBSP_SRGR1 0x002C
+#define OMAP35XX_MCBSP_MCR2 0x0030
+#define OMAP35XX_MCBSP_MCR1 0x0034
+#define OMAP35XX_MCBSP_RCERA 0x0038
+#define OMAP35XX_MCBSP_RCERB 0x003C
+#define OMAP35XX_MCBSP_XCERA 0x0040
+#define OMAP35XX_MCBSP_XCERB 0x0044
+#define OMAP35XX_MCBSP_PCR 0x0048
+#define OMAP35XX_MCBSP_RCERC 0x004C
+#define OMAP35XX_MCBSP_RCERD 0x0050
+#define OMAP35XX_MCBSP_XCERC 0x0054
+#define OMAP35XX_MCBSP_XCERD 0x0058
+#define OMAP35XX_MCBSP_RCERE 0x005C
+#define OMAP35XX_MCBSP_RCERF 0x0060
+#define OMAP35XX_MCBSP_XCERE 0x0064
+#define OMAP35XX_MCBSP_XCERF 0x0068
+#define OMAP35XX_MCBSP_RCERG 0x006C
+#define OMAP35XX_MCBSP_RCERH 0x0070
+#define OMAP35XX_MCBSP_XCERG 0x0074
+#define OMAP35XX_MCBSP_XCERH 0x0078
+#define OMAP35XX_MCBSP_RINTCLR 0x0080
+#define OMAP35XX_MCBSP_XINTCLR 0x0084
+#define OMAP35XX_MCBSP_ROVFLCLR 0x0088
+#define OMAP35XX_MCBSP_SYSCONFIG 0x008C
+#define OMAP35XX_MCBSP_THRSH2 0x0090
+#define OMAP35XX_MCBSP_THRSH1 0x0094
+#define OMAP35XX_MCBSP_IRQSTATUS 0x00A0
+#define OMAP35XX_MCBSP_IRQENABLE 0x00A4
+#define OMAP35XX_MCBSP_WAKEUPEN 0x00A8
+#define OMAP35XX_MCBSP_XCCR 0x00AC
+#define OMAP35XX_MCBSP_RCCR 0x00B0
+#define OMAP35XX_MCBSP_XBUFFSTAT 0x00B4
+#define OMAP35XX_MCBSP_RBUFFSTAT 0x00B8
+#define OMAP35XX_MCBSP_SSELCR 0x00BC
+#define OMAP35XX_MCBSP_STATUS 0x00C0
+
+
+
+/*
+ * USB TTL Module
+ */
+#define OMAP35XX_USBTLL_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_USBTLL_OFFSET)
+#define OMAP35XX_USBTLL_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_USBTLL_OFFSET)
+#define OMAP35XX_USBTLL_SIZE 0x00001000UL
+
+#define OMAP35XX_USBTLL_REVISION 0x0000
+#define OMAP35XX_USBTLL_SYSCONFIG 0x0010
+#define OMAP35XX_USBTLL_SYSSTATUS 0x0014
+#define OMAP35XX_USBTLL_IRQSTATUS 0x0018
+#define OMAP35XX_USBTLL_IRQENABLE 0x001C
+#define OMAP35XX_USBTLL_TLL_SHARED_CONF 0x0030
+#define OMAP35XX_USBTLL_TLL_CHANNEL_CONF(i) (0x0040 + (0x04 * (i)))
+#define OMAP35XX_USBTLL_ULPI_VENDOR_ID_LO(i) (0x0800 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_VENDOR_ID_HI(i) (0x0801 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_PRODUCT_ID_LO(i) (0x0802 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_PRODUCT_ID_HI(i) (0x0803 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_FUNCTION_CTRL(i) (0x0804 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_FUNCTION_CTRL_SET(i) (0x0805 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_FUNCTION_CTRL_CLR(i) (0x0806 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_INTERFACE_CTRL(i) (0x0807 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_INTERFACE_CTRL_SET(i) (0x0808 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_INTERFACE_CTRL_CLR(i) (0x0809 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_OTG_CTRL(i) (0x080A + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_OTG_CTRL_SET(i) (0x080B + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_OTG_CTRL_CLR(i) (0x080C + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_EN_RISE(i) (0x080D + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_EN_RISE_SET(i) (0x080E + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_EN_RISE_CLR(i) (0x080F + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_EN_FALL(i) (0x0810 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_EN_FALL_SET(i) (0x0811 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_EN_FALL_CLR(i) (0x0812 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_STATUS(i) (0x0813 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_LATCH(i) (0x0814 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_DEBUG(i) (0x0815 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_SCRATCH_REGISTER(i) (0x0816 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_SCRATCH_REGISTER_SET(i) (0x0817 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_SCRATCH_REGISTER_CLR(i) (0x0818 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_EXTENDED_SET_ACCESS(i) (0x082F + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_UTMI_VCONTROL_EN(i) (0x0830 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_UTMI_VCONTROL_EN_SET(i) (0x0831 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_UTMI_VCONTROL_EN_CLR(i) (0x0832 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_UTMI_VCONTROL_STATUS(i) (0x0833 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_UTMI_VCONTROL_LATCH(i) (0x0834 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_UTMI_VSTATUS(i) (0x0835 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_UTMI_VSTATUS_SET(i) (0x0836 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_UTMI_VSTATUS_CLR(i) (0x0837 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_USB_INT_LATCH_NOCLR(i) (0x0838 + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_VENDOR_INT_EN(i) (0x083B + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_VENDOR_INT_EN_SET(i) (0x083C + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_VENDOR_INT_EN_CLR(i) (0x083D + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_VENDOR_INT_STATUS(i) (0x083E + (0x100 * (i)))
+#define OMAP35XX_USBTLL_ULPI_VENDOR_INT_LATCH(i) (0x083F + (0x100 * (i)))
+
+
+/*
+ * USB Host Module
+ */
+#define OMAP35XX_USB_TLL_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_USB_TLL_OFFSET)
+#define OMAP35XX_USB_TLL_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_USB_TLL_OFFSET)
+#define OMAP35XX_USB_TLL_SIZE 0x00001000UL
+
+#define OMAP35XX_USB_EHCI_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_USB_EHCI_OFFSET)
+#define OMAP35XX_USB_EHCI_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_USB_EHCI_OFFSET)
+#define OMAP35XX_USB_EHCI_SIZE 0x00000400UL
+
+#define OMAP35XX_USB_UHH_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_USB_UHH_OFFSET)
+#define OMAP35XX_USB_UHH_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_USB_UHH_OFFSET)
+#define OMAP35XX_USB_UHH_SIZE 0x00000400UL
+
+
+
+
+
+/*
+ * SDRAM Controler (SDRC)
+ * PA 0x6D00_0000
+ */
+
+#define OMAP35XX_SDRC_SYSCONFIG (OMAP35XX_SDRC_VBASE + 0x10)
+#define OMAP35XX_SDRC_SYSSTATUS (OMAP35XX_SDRC_VBASE + 0x14)
+#define OMAP35XX_SDRC_CS_CFG (OMAP35XX_SDRC_VBASE + 0x40)
+#define OMAP35XX_SDRC_SHARING (OMAP35XX_SDRC_VBASE + 0x44)
+#define OMAP35XX_SDRC_ERR_ADDR (OMAP35XX_SDRC_VBASE + 0x48)
+#define OMAP35XX_SDRC_ERR_TYPE (OMAP35XX_SDRC_VBASE + 0x4C)
+#define OMAP35XX_SDRC_DLLA_CTRL (OMAP35XX_SDRC_VBASE + 0x60)
+#define OMAP35XX_SDRC_DLLA_STATUS (OMAP35XX_SDRC_VBASE + 0x64)
+#define OMAP35XX_SDRC_POWER_REG (OMAP35XX_SDRC_VBASE + 0x70)
+#define OMAP35XX_SDRC_MCFG(p) (OMAP35XX_SDRC_VBASE + 0x80 + (0x30 * (p)))
+#define OMAP35XX_SDRC_MR(p) (OMAP35XX_SDRC_VBASE + 0x84 + (0x30 * (p)))
+#define OMAP35XX_SDRC_EMR2(p) (OMAP35XX_SDRC_VBASE + 0x8C + (0x30 * (p)))
+#define OMAP35XX_SDRC_ACTIM_CTRLA(p) (OMAP35XX_SDRC_VBASE + 0x9C + (0x28 * (p)))
+#define OMAP35XX_SDRC_ACTIM_CTRLB(p) (OMAP35XX_SDRC_VBASE + 0xA0 + (0x28 * (p)))
+#define OMAP35XX_SDRC_RFR_CTRL(p) (OMAP35XX_SDRC_VBASE + 0xA4 + (0x30 * (p)))
+#define OMAP35XX_SDRC_MANUAL(p) (OMAP35XX_SDRC_VBASE + 0xA8 + (0x30 * (p)))
+
+
+/*
+ * SDMA Offset
+ * PA 0x4805 6000
+ */
+
+#define OMAP35XX_SDMA_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_SDMA_OFFSET)
+#define OMAP35XX_SDMA_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_SDMA_OFFSET)
+#define OMAP35XX_SDMA_SIZE 0x00001000UL
+
+
+
+/*
+ * Interrupt Controller Unit.
+ * PA 0x4820_0000
+ */
+
+#define OMAP35XX_INTCPS_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_INTCPS_OFFSET)
+#define OMAP35XX_INTCPS_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_INTCPS_OFFSET)
+#define OMAP35XX_INTCPS_SIZE 0x00001000UL
+
+#define OMAP35XX_INTCPS_SYSCONFIG (OMAP35XX_INTCPS_VBASE + 0x10)
+#define OMAP35XX_INTCPS_SYSSTATUS (OMAP35XX_INTCPS_VBASE + 0x14)
+#define OMAP35XX_INTCPS_SIR_IRQ (OMAP35XX_INTCPS_VBASE + 0x40)
+#define OMAP35XX_INTCPS_SIR_FIQ (OMAP35XX_INTCPS_VBASE + 0x44)
+#define OMAP35XX_INTCPS_CONTROL (OMAP35XX_INTCPS_VBASE + 0x48)
+#define OMAP35XX_INTCPS_PROTECTION (OMAP35XX_INTCPS_VBASE + 0x4C)
+#define OMAP35XX_INTCPS_IDLE (OMAP35XX_INTCPS_VBASE + 0x50)
+#define OMAP35XX_INTCPS_IRQ_PRIORITY (OMAP35XX_INTCPS_VBASE + 0x60)
+#define OMAP35XX_INTCPS_FIQ_PRIORITY (OMAP35XX_INTCPS_VBASE + 0x64)
+#define OMAP35XX_INTCPS_THRESHOLD (OMAP35XX_INTCPS_VBASE + 0x68)
+#define OMAP35XX_INTCPS_ITR(n) (OMAP35XX_INTCPS_VBASE + 0x80 + (0x20 * (n)))
+#define OMAP35XX_INTCPS_MIR(n) (OMAP35XX_INTCPS_VBASE + 0x84 + (0x20 * (n)))
+#define OMAP35XX_INTCPS_MIR_CLEAR(n) (OMAP35XX_INTCPS_VBASE + 0x88 + (0x20 * (n)))
+#define OMAP35XX_INTCPS_MIR_SET(n) (OMAP35XX_INTCPS_VBASE + 0x8C + (0x20 * (n)))
+#define OMAP35XX_INTCPS_ISR_SET(n) (OMAP35XX_INTCPS_VBASE + 0x90 + (0x20 * (n)))
+#define OMAP35XX_INTCPS_ISR_CLEAR(n) (OMAP35XX_INTCPS_VBASE + 0x94 + (0x20 * (n)))
+#define OMAP35XX_INTCPS_PENDING_IRQ(n) (OMAP35XX_INTCPS_VBASE + 0x98 + (0x20 * (n)))
+#define OMAP35XX_INTCPS_PENDING_FIQ(n) (OMAP35XX_INTCPS_VBASE + 0x9C + (0x20 * (n)))
+#define OMAP35XX_INTCPS_ILR(m) (OMAP35XX_INTCPS_VBASE + 0x100 + (0x4 * (m)))
+
+
+#define OMAP35XX_IRQ_EMUINT 0 /* MPU emulation(2) */
+#define OMAP35XX_IRQ_COMMTX 1 /* MPU emulation(2) */
+#define OMAP35XX_IRQ_COMMRX 2 /* MPU emulation(2) */
+#define OMAP35XX_IRQ_BENCH 3 /* MPU emulation(2) */
+#define OMAP35XX_IRQ_MCBSP2_ST 4 /* Sidetone MCBSP2 overflow */
+#define OMAP35XX_IRQ_MCBSP3_ST 5 /* Sidetone MCBSP3 overflow */
+#define OMAP35XX_IRQ_SSM_ABORT 6 /* MPU subsystem secure state-machine abort (2) */
+#define OMAP35XX_IRQ_SYS_NIRQ 7 /* External source (active low) */
+#define OMAP35XX_IRQ_RESERVED8 8 /* RESERVED */
+#define OMAP35XX_IRQ_SMX_DBG 9 /* SMX error for debug */
+#define OMAP35XX_IRQ_SMX_APP 10 /* SMX error for application */
+#define OMAP35XX_IRQ_PRCM_MPU 11 /* PRCM module IRQ */
+#define OMAP35XX_IRQ_SDMA0 12 /* System DMA request 0(3) */
+#define OMAP35XX_IRQ_SDMA1 13 /* System DMA request 1(3) */
+#define OMAP35XX_IRQ_SDMA2 14 /* System DMA request 2 */
+#define OMAP35XX_IRQ_SDMA3 15 /* System DMA request 3 */
+#define OMAP35XX_IRQ_MCBSP1 16 /* McBSP module 1 IRQ (3) */
+#define OMAP35XX_IRQ_MCBSP2 17 /* McBSP module 2 IRQ (3) */
+#define OMAP35XX_IRQ_SR1 18 /* SmartReflexâ„¢ 1 */
+#define OMAP35XX_IRQ_SR2 19 /* SmartReflexâ„¢ 2 */
+#define OMAP35XX_IRQ_GPMC 20 /* General-purpose memory controller module */
+#define OMAP35XX_IRQ_SGX 21 /* 2D/3D graphics module */
+#define OMAP35XX_IRQ_MCBSP3 22 /* McBSP module 3(3) */
+#define OMAP35XX_IRQ_MCBSP4 23 /* McBSP module 4(3) */
+#define OMAP35XX_IRQ_CAM0 24 /* Camera interface request 0 */
+#define OMAP35XX_IRQ_DSS 25 /* Display subsystem module(3) */
+#define OMAP35XX_IRQ_MAIL_U0 26 /* Mailbox user 0 request */
+#define OMAP35XX_IRQ_MCBSP5_IRQ1 27 /* McBSP module 5 (3) */
+#define OMAP35XX_IRQ_IVA2_MMU 28 /* IVA2 MMU */
+#define OMAP35XX_IRQ_GPIO1_MPU 29 /* GPIO module 1(3) */
+#define OMAP35XX_IRQ_GPIO2_MPU 30 /* GPIO module 2(3) */
+#define OMAP35XX_IRQ_GPIO3_MPU 31 /* GPIO module 3(3) */
+#define OMAP35XX_IRQ_GPIO4_MPU 32 /* GPIO module 4(3) */
+#define OMAP35XX_IRQ_GPIO5_MPU 33 /* GPIO module 5(3) */
+#define OMAP35XX_IRQ_GPIO6_MPU 34 /* GPIO module 6(3) */
+#define OMAP35XX_IRQ_USIM 35 /* USIM interrupt (HS devices only) (4) */
+#define OMAP35XX_IRQ_WDT3 36 /* Watchdog timer module 3 overflow */
+#define OMAP35XX_IRQ_GPT1 37 /* General-purpose timer module 1 */
+#define OMAP35XX_IRQ_GPT2 38 /* General-purpose timer module 2 */
+#define OMAP35XX_IRQ_GPT3 39 /* General-purpose timer module 3 */
+#define OMAP35XX_IRQ_GPT4 40 /* General-purpose timer module 4 */
+#define OMAP35XX_IRQ_GPT5 41 /* General-purpose timer module 5(3) */
+#define OMAP35XX_IRQ_GPT6 42 /* General-purpose timer module 6(3) */
+#define OMAP35XX_IRQ_GPT7 43 /* General-purpose timer module 7(3) */
+#define OMAP35XX_IRQ_GPT8 44 /* General-purpose timer module 8(3) */
+#define OMAP35XX_IRQ_GPT9 45 /* General-purpose timer module 9 */
+#define OMAP35XX_IRQ_GPT10 46 /* General-purpose timer module 10 */
+#define OMAP35XX_IRQ_GPT11 47 /* General-purpose timer module 11 */
+#define OMAP35XX_IRQ_SPI4 48 /* McSPI module 4 */
+#define OMAP35XX_IRQ_SHA1MD5_2 49 /* SHA-1/MD5 crypto-accelerator 2 (HS devices only)(4) */
+#define OMAP35XX_IRQ_FPKA_IRQREADY_N 50 /* PKA crypto-accelerator (HS devices only) (4) */
+#define OMAP35XX_IRQ_SHA2MD5 51 /* SHA-2/MD5 crypto-accelerator 1 (HS devices only) (4) */
+#define OMAP35XX_IRQ_RNG 52 /* RNG module (HS devices only) (4) */
+#define OMAP35XX_IRQ_MG 53 /* MG function (3) */
+#define OMAP35XX_IRQ_MCBSP4_TX 54 /* McBSP module 4 transmit(3) */
+#define OMAP35XX_IRQ_MCBSP4_RX 55 /* McBSP module 4 receive(3) */
+#define OMAP35XX_IRQ_I2C1 56 /* I2C module 1 */
+#define OMAP35XX_IRQ_I2C2 57 /* I2C module 2 */
+#define OMAP35XX_IRQ_HDQ 58 /* HDQ / One-wire */
+#define OMAP35XX_IRQ_MCBSP1_TX 59 /* McBSP module 1 transmit(3) */
+#define OMAP35XX_IRQ_MCBSP1_RX 60 /* McBSP module 1 receive(3) */
+#define OMAP35XX_IRQ_I2C3 61 /* I2C module 3 */
+#define OMAP35XX_IRQ_McBSP2_TX 62 /* McBSP module 2 transmit(3) */
+#define OMAP35XX_IRQ_McBSP2_RX 63 /* McBSP module 2 receive(3) */
+#define OMAP35XX_IRQ_FPKA_IRQRERROR_N 64 /* PKA crypto-accelerator (HS devices only) (4) */
+#define OMAP35XX_IRQ_SPI1 65 /* McSPI module 1 */
+#define OMAP35XX_IRQ_SPI2 66 /* McSPI module 2 */
+#define OMAP35XX_IRQ_RESERVED67 67 /* RESERVED */
+#define OMAP35XX_IRQ_RESERVED68 68 /* RESERVED */
+#define OMAP35XX_IRQ_RESERVED69 69 /* RESERVED */
+#define OMAP35XX_IRQ_RESERVED70 70 /* RESERVED */
+#define OMAP35XX_IRQ_RESERVED71 71 /* RESERVED */
+#define OMAP35XX_IRQ_UART1 72 /* UART module 1 */
+#define OMAP35XX_IRQ_UART2 73 /* UART module 2 */
+#define OMAP35XX_IRQ_UART3 74 /* UART module 3 (also infrared)(3) */
+#define OMAP35XX_IRQ_PBIAS 75 /* Merged interrupt for PBIASlite1 and 2 */
+#define OMAP35XX_IRQ_OHCI 76 /* OHCI controller HSUSB MP Host Interrupt */
+#define OMAP35XX_IRQ_EHCI 77 /* EHCI controller HSUSB MP Host Interrupt */
+#define OMAP35XX_IRQ_TLL 78 /* HSUSB MP TLL Interrupt */
+#define OMAP35XX_IRQ_PARTHASH 79 /* SHA2/MD5 crypto-accelerator 1 (HS devices only) (4) */
+#define OMAP35XX_IRQ_RESERVED80 80 /* Reserved */
+#define OMAP35XX_IRQ_MCBSP5_TX 81 /* McBSP module 5 transmit(3) */
+#define OMAP35XX_IRQ_MCBSP5_RX 82 /* McBSP module 5 receive(3) */
+#define OMAP35XX_IRQ_MMC1 83 /* MMC/SD module 1 */
+#define OMAP35XX_IRQ_MS 84 /* MS-PROâ„¢ module */
+#define OMAP35XX_IRQ_RESERVED85 85 /* Reserved */
+#define OMAP35XX_IRQ_MMC2 86 /* MMC/SD module 2 */
+#define OMAP35XX_IRQ_MPU_ICR 87 /* MPU ICR */
+#define OMAP35XX_IRQ_RESERVED 88 /* RESERVED */
+#define OMAP35XX_IRQ_MCBSP3_TX 89 /* McBSP module 3 transmit(3) */
+#define OMAP35XX_IRQ_MCBSP3_RX 90 /* McBSP module 3 receive(3) */
+#define OMAP35XX_IRQ_SPI3 91 /* McSPI module 3 */
+#define OMAP35XX_IRQ_HSUSB_MC_NINT 92 /* High-Speed USB OTG controller */
+#define OMAP35XX_IRQ_HSUSB_DMA_NINT 93 /* High-Speed USB OTG DMA controller */
+#define OMAP35XX_IRQ_MMC3 94 /* MMC/SD module 3 */
+#define OMAP35XX_IRQ_GPT12 95 /* General-purpose timer module 12 */
+
+
+
+
+/*
+ * General Purpose Timers
+ */
+#define OMAP35XX_GPTIMER1_VBASE (OMAP35XX_L4_WAKEUP_VBASE + OMAP35XX_GPTIMER1_OFFSET)
+#define OMAP35XX_GPTIMER1_HWBASE (OMAP35XX_L4_WAKEUP_HWBASE + OMAP35XX_GPTIMER1_OFFSET)
+#define OMAP35XX_GPTIMER2_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPTIMER2_OFFSET)
+#define OMAP35XX_GPTIMER2_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPTIMER2_OFFSET)
+#define OMAP35XX_GPTIMER3_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPTIMER3_OFFSET)
+#define OMAP35XX_GPTIMER3_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPTIMER3_OFFSET)
+#define OMAP35XX_GPTIMER4_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPTIMER4_OFFSET)
+#define OMAP35XX_GPTIMER4_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPTIMER4_OFFSET)
+#define OMAP35XX_GPTIMER5_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPTIMER5_OFFSET)
+#define OMAP35XX_GPTIMER5_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPTIMER5_OFFSET)
+#define OMAP35XX_GPTIMER6_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPTIMER6_OFFSET)
+#define OMAP35XX_GPTIMER6_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPTIMER6_OFFSET)
+#define OMAP35XX_GPTIMER7_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPTIMER7_OFFSET)
+#define OMAP35XX_GPTIMER7_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPTIMER7_OFFSET)
+#define OMAP35XX_GPTIMER8_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPTIMER8_OFFSET)
+#define OMAP35XX_GPTIMER8_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPTIMER8_OFFSET)
+#define OMAP35XX_GPTIMER9_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPTIMER9_OFFSET)
+#define OMAP35XX_GPTIMER9_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPTIMER9_OFFSET)
+#define OMAP35XX_GPTIMER10_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_GPTIMER10_OFFSET)
+#define OMAP35XX_GPTIMER10_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_GPTIMER10_OFFSET)
+#define OMAP35XX_GPTIMER11_VBASE (OMAP35XX_L4_CORE_VBASE + OMAP35XX_GPTIMER11_OFFSET)
+#define OMAP35XX_GPTIMER11_HWBASE (OMAP35XX_L4_CORE_HWBASE + OMAP35XX_GPTIMER11_OFFSET)
+#define OMAP35XX_GPTIMER12_VBASE 0x48304000UL /* GPTIMER12 */
+#define OMAP35XX_GPTIMER_SIZE 0x00001000UL
+
+
+
+/* Timer register offsets */
+#define OMAP35XX_GPTIMER_TIOCP_CFG 0x010
+#define OMAP35XX_GPTIMER_TISTAT 0x014
+#define OMAP35XX_GPTIMER_TISR 0x018
+#define OMAP35XX_GPTIMER_TIER 0x01C
+#define OMAP35XX_GPTIMER_TWER 0x020
+#define OMAP35XX_GPTIMER_TCLR 0x024
+#define OMAP35XX_GPTIMER_TCRR 0x028
+#define OMAP35XX_GPTIMER_TLDR 0x02C
+#define OMAP35XX_GPTIMER_TTGR 0x030
+#define OMAP35XX_GPTIMER_TWPS 0x034
+#define OMAP35XX_GPTIMER_TMAR 0x038
+#define OMAP35XX_GPTIMER_TCAR1 0x03C
+#define OMAP35XX_GPTIMER_TSICR 0x040
+#define OMAP35XX_GPTIMER_TCAR2 0x044
+#define OMAP35XX_GPTIMER_TPIR 0x048
+#define OMAP35XX_GPTIMER_TNIR 0x04C
+#define OMAP35XX_GPTIMER_TCVR 0x050
+#define OMAP35XX_GPTIMER_TOCR 0x054
+#define OMAP35XX_GPTIMER_TOWR 0x058
+
+/* Bit values */
+#define MAT_IT_FLAG 0x01
+#define OVF_IT_FLAG 0x02
+#define TCAR_IT_FLAG 0x04
+
+
+
+/*
+ * GPIO - General Purpose IO
+ */
+
+/* Base addresses for the GPIO modules */
+#define OMAP35XX_GPIO1_HWBASE (OMAP35XX_L4_WAKEUP_HWBASE + OMAP35XX_GPIO1_OFFSET)
+#define OMAP35XX_GPIO1_VBASE (OMAP35XX_L4_WAKEUP_VBASE + OMAP35XX_GPIO1_OFFSET)
+#define OMAP35XX_GPIO1_SIZE 0x00001000UL
+#define OMAP35XX_GPIO2_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPIO2_OFFSET)
+#define OMAP35XX_GPIO2_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPIO2_OFFSET)
+#define OMAP35XX_GPIO2_SIZE 0x00001000UL
+#define OMAP35XX_GPIO3_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPIO3_OFFSET)
+#define OMAP35XX_GPIO3_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPIO3_OFFSET)
+#define OMAP35XX_GPIO3_SIZE 0x00001000UL
+#define OMAP35XX_GPIO4_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPIO4_OFFSET)
+#define OMAP35XX_GPIO4_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPIO4_OFFSET)
+#define OMAP35XX_GPIO4_SIZE 0x00001000UL
+#define OMAP35XX_GPIO5_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPIO5_OFFSET)
+#define OMAP35XX_GPIO5_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPIO5_OFFSET)
+#define OMAP35XX_GPIO5_SIZE 0x00001000UL
+#define OMAP35XX_GPIO6_HWBASE (OMAP35XX_L4_PERIPH_HWBASE + OMAP35XX_GPIO6_OFFSET)
+#define OMAP35XX_GPIO6_VBASE (OMAP35XX_L4_PERIPH_VBASE + OMAP35XX_GPIO6_OFFSET)
+#define OMAP35XX_GPIO6_SIZE 0x00001000UL
+
+
+
+/* Register offsets within the banks above */
+#define OMAP35XX_GPIO_SYSCONFIG 0x010
+#define OMAP35XX_GPIO_SYSSTATUS 0x014
+#define OMAP35XX_GPIO_IRQSTATUS1 0x018
+#define OMAP35XX_GPIO_IRQENABLE1 0x01C
+#define OMAP35XX_GPIO_WAKEUPENABLE 0x020
+#define OMAP35XX_GPIO_IRQSTATUS2 0x028
+#define OMAP35XX_GPIO_IRQENABLE2 0x02C
+#define OMAP35XX_GPIO_CTRL 0x030
+#define OMAP35XX_GPIO_OE 0x034
+#define OMAP35XX_GPIO_DATAIN 0x038
+#define OMAP35XX_GPIO_DATAOUT 0x03C
+#define OMAP35XX_GPIO_LEVELDETECT0 0x040
+#define OMAP35XX_GPIO_LEVELDETECT1 0x044
+#define OMAP35XX_GPIO_RISINGDETECT 0x048
+#define OMAP35XX_GPIO_FALLINGDETECT 0x04C
+#define OMAP35XX_GPIO_DEBOUNCENABLE 0x050
+#define OMAP35XX_GPIO_DEBOUNCINGTIME 0x054
+#define OMAP35XX_GPIO_CLEARIRQENABLE1 0x060
+#define OMAP35XX_GPIO_SETIRQENABLE1 0x064
+#define OMAP35XX_GPIO_CLEARIRQENABLE2 0x070
+#define OMAP35XX_GPIO_SETIRQENABLE2 0x074
+#define OMAP35XX_GPIO_CLEARWKUENA 0x080
+#define OMAP35XX_GPIO_SETWKUENA 0x084
+#define OMAP35XX_GPIO_CLEARDATAOUT 0x090
+#define OMAP35XX_GPIO_SETDATAOUT 0x094
+
+
+/*
+ * MMC/SD/SDIO
+ */
+
+/* Base addresses for the MMC/SD/SDIO modules */
+#define OMAP35XX_MMCHS1_HWBASE (OMAP35XX_L4_CORE_HWBASE + 0x0009C000)
+#define OMAP35XX_MMCHS1_VBASE (OMAP35XX_L4_CORE_VBASE + 0x0009C000)
+#define OMAP35XX_MMCHS2_HWBASE (OMAP35XX_L4_CORE_HWBASE + 0x000B4000)
+#define OMAP35XX_MMCHS2_VBASE (OMAP35XX_L4_CORE_VBASE + 0x000B4000)
+#define OMAP35XX_MMCHS3_HWBASE (OMAP35XX_L4_CORE_HWBASE + 0x000AD000)
+#define OMAP35XX_MMCHS3_VBASE (OMAP35XX_L4_CORE_VBASE + 0x000AD000)
+#define OMAP35XX_MMCHS_SIZE 0x00000200UL
+
+/* Register offsets within each of the MMC/SD/SDIO controllers */
+#define OMAP35XX_MMCHS_SYSCONFIG 0x010
+#define OMAP35XX_MMCHS_SYSSTATUS 0x014
+#define OMAP35XX_MMCHS_CSRE 0x024
+#define OMAP35XX_MMCHS_SYSTEST 0x028
+#define OMAP35XX_MMCHS_CON 0x02C
+#define OMAP35XX_MMCHS_PWCNT 0x030
+#define OMAP35XX_MMCHS_BLK 0x104
+#define OMAP35XX_MMCHS_ARG 0x108
+#define OMAP35XX_MMCHS_CMD 0x10C
+#define OMAP35XX_MMCHS_RSP10 0x110
+#define OMAP35XX_MMCHS_RSP32 0x114
+#define OMAP35XX_MMCHS_RSP54 0x118
+#define OMAP35XX_MMCHS_RSP76 0x11C
+#define OMAP35XX_MMCHS_DATA 0x120
+#define OMAP35XX_MMCHS_PSTATE 0x124
+#define OMAP35XX_MMCHS_HCTL 0x128
+#define OMAP35XX_MMCHS_SYSCTL 0x12C
+#define OMAP35XX_MMCHS_STAT 0x130
+#define OMAP35XX_MMCHS_IE 0x134
+#define OMAP35XX_MMCHS_ISE 0x138
+#define OMAP35XX_MMCHS_AC12 0x13C
+#define OMAP35XX_MMCHS_CAPA 0x140
+#define OMAP35XX_MMCHS_CUR_CAPA 0x148
+#define OMAP35XX_MMCHS_REV 0x1FC
+
+
+
+#endif /* _OMAP35XX_REG_H_ */
Property changes on: trunk/sys/arm/ti/omap3/omap3_reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/files.omap4
===================================================================
--- trunk/sys/arm/ti/omap4/files.omap4 (rev 0)
+++ trunk/sys/arm/ti/omap4/files.omap4 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,20 @@
+#$FreeBSD: stable/10/sys/arm/ti/omap4/files.omap4 266751 2014-05-27 15:30:24Z ian $
+
+arm/arm/gic.c standard
+arm/arm/mpcore_timer.c standard
+arm/ti/ti_smc.S standard
+
+arm/ti/usb/omap_ehci.c optional usb ehci
+arm/ti/ti_sdma.c optional ti_sdma
+arm/ti/ti_sdhci.c optional sdhci
+#arm/ti/ti_mmchs.c optional mmc
+
+arm/ti/omap4/omap4_l2cache.c optional pl310
+arm/ti/omap4/omap4_prcm_clks.c standard
+arm/ti/omap4/omap4_scm_padconf.c standard
+arm/ti/omap4/omap4_mp.c optional smp
+
+arm/ti/twl/twl.c optional twl
+arm/ti/twl/twl_vreg.c optional twl twl_vreg
+arm/ti/twl/twl_clks.c optional twl twl_clks
+
Property changes on: trunk/sys/arm/ti/omap4/files.omap4
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/omap4_l2cache.c
===================================================================
--- trunk/sys/arm/ti/omap4/omap4_l2cache.c (rev 0)
+++ trunk/sys/arm/ti/omap4/omap4_l2cache.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,83 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/omap4/omap4_l2cache.c 266375 2014-05-17 23:07:26Z ian $");
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <arm/ti/ti_smc.h>
+#include <arm/ti/omap4/omap4_smc.h>
+#include <machine/bus.h>
+#include <machine/pl310.h>
+
+void
+platform_pl310_init(struct pl310_softc *sc)
+{
+ uint32_t aux, prefetch;
+
+ aux = pl310_read4(sc, PL310_AUX_CTRL);
+ prefetch = pl310_read4(sc, PL310_PREFETCH_CTRL);
+
+ /*
+ * Disable instruction prefetch
+ */
+ prefetch &= ~PREFETCH_CTRL_INSTR_PREFETCH;
+ aux &= ~AUX_CTRL_INSTR_PREFETCH;
+
+ // prefetch &= ~PREFETCH_CTRL_DATA_PREFETCH;
+ // aux &= ~AUX_CTRL_DATA_PREFETCH;
+
+ /*
+ * Make sure data prefetch is on
+ */
+ prefetch |= PREFETCH_CTRL_DATA_PREFETCH;
+ aux |= AUX_CTRL_DATA_PREFETCH;
+
+ /*
+ * TODO: add tunable for prefetch offset
+ * and experiment with performance
+ */
+
+ ti_smc0(aux, 0, WRITE_AUXCTRL_REG);
+ ti_smc0(prefetch, 0, WRITE_PREFETCH_CTRL_REG);
+}
+
+void
+platform_pl310_write_ctrl(struct pl310_softc *sc, uint32_t val)
+{
+ ti_smc0(val, 0, L2CACHE_WRITE_CTRL_REG);
+}
+
+void
+platform_pl310_write_debug(struct pl310_softc *sc, uint32_t val)
+{
+ ti_smc0(val, 0, L2CACHE_WRITE_DEBUG_REG);
+}
Property changes on: trunk/sys/arm/ti/omap4/omap4_l2cache.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/omap4_mp.c
===================================================================
--- trunk/sys/arm/ti/omap4/omap4_mp.c (rev 0)
+++ trunk/sys/arm/ti/omap4/omap4_mp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,85 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/omap4/omap4_mp.c 266203 2014-05-16 00:14:50Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <arm/ti/ti_smc.h>
+#include <arm/ti/omap4/omap4_smc.h>
+
+void
+platform_mp_init_secondary(void)
+{
+ gic_init_secondary();
+}
+
+void
+platform_mp_setmaxid(void)
+{
+
+ mp_maxid = 1;
+}
+
+int
+platform_mp_probe(void)
+{
+
+ mp_ncpus = 2;
+ return (1);
+}
+
+void
+platform_mp_start_ap(void)
+{
+ bus_addr_t scu_addr;
+
+ if (bus_space_map(fdtbus_bs_tag, 0x48240000, 0x1000, 0, &scu_addr) != 0)
+ panic("Couldn't map the SCU\n");
+ /* Enable the SCU */
+ *(volatile unsigned int *)scu_addr |= 1;
+ //*(volatile unsigned int *)(scu_addr + 0x30) |= 1;
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+ ti_smc0(0x200, 0xfffffdff, MODIFY_AUX_CORE_0);
+ ti_smc0(pmap_kextract((vm_offset_t)mpentry), 0, WRITE_AUX_CORE_1);
+ armv7_sev();
+ bus_space_unmap(fdtbus_bs_tag, scu_addr, 0x1000);
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+ pic_ipi_send(cpus, ipi);
+}
Property changes on: trunk/sys/arm/ti/omap4/omap4_mp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/omap4_prcm_clks.c
===================================================================
--- trunk/sys/arm/ti/omap4/omap4_prcm_clks.c (rev 0)
+++ trunk/sys/arm/ti/omap4/omap4_prcm_clks.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1429 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/omap4/omap4_prcm_clks.c 283338 2015-05-23 23:08:54Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <arm/arm/mpcore_timervar.h>
+#include <arm/ti/tivar.h>
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/omap4/omap4_reg.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * This file defines the clock configuration for the OMAP4xxx series of
+ * devices.
+ *
+ * How This is Suppose to Work
+ * ===========================
+ * - There is a top level omap_prcm module that defines all OMAP SoC drivers
+ * should use to enable/disable the system clocks regardless of the version
+ * of OMAP device they are running on. This top level PRCM module is just
+ * a thin shim to chip specific functions that perform the donkey work of
+ * configuring the clock - this file is the 'donkey' for OMAP44xx devices.
+ *
+ * - The key bit in this file is the omap_clk_devmap array, it's
+ * used by the omap_prcm driver to determine what clocks are valid and which
+ * functions to call to manipulate them.
+ *
+ * - In essence you just need to define some callbacks for each of the
+ * clocks and then you're done.
+ *
+ * - The other thing that is worth noting is that when the omap_prcm device
+ * is registered you typically pass in some memory ranges which are the
+ * SYS_MEMORY resources. These resources are in turn allocated using
+ * bus_allocate_resources(...) and the resource handles are passed to all
+ * individual clock callback handlers.
+ *
+ *
+ *
+ * OMAP4 devices are different from the previous OMAP3 devices in that there
+ * is no longer a separate functional and interface clock for each module,
+ * instead there is typically an interface clock that spans many modules.
+ */
+
+#define FREQ_96MHZ 96000000
+#define FREQ_64MHZ 64000000
+#define FREQ_48MHZ 48000000
+#define FREQ_32KHZ 32000
+
+/**
+ * We need three memory regions to cover all the clock configuration registers.
+ *
+ * PRM Instance - 0x4A30 6000 : 0x4A30 8000
+ * CM1 Instance - 0x4A00 4000 : 0x4A00 5000
+ * CM2 Instance - 0x4A00 8000 : 0x4A00 A000
+ *
+ */
+#define PRM_INSTANCE_MEM_REGION 0
+#define CM1_INSTANCE_MEM_REGION 1
+#define CM2_INSTANCE_MEM_REGION 2
+
+/**
+ * Address offsets from the PRM memory region to the top level clock control
+ * registers.
+ */
+#define CKGEN_PRM_OFFSET 0x00000100UL
+#define MPU_PRM_OFFSET 0x00000300UL
+#define DSP_PRM_OFFSET 0x00000400UL
+#define ABE_PRM_OFFSET 0x00000500UL
+#define ALWAYS_ON_PRM_OFFSET 0x00000600UL
+#define CORE_PRM_OFFSET 0x00000700UL
+#define IVAHD_PRM_OFFSET 0x00000F00UL
+#define CAM_PRM_OFFSET 0x00001000UL
+#define DSS_PRM_OFFSET 0x00001100UL
+#define SGX_PRM_OFFSET 0x00001200UL
+#define L3INIT_PRM_OFFSET 0x00001300UL
+#define L4PER_PRM_OFFSET 0x00001400UL
+#define WKUP_PRM_OFFSET 0x00001700UL
+#define WKUP_CM_OFFSET 0x00001800UL
+#define EMU_PRM_OFFSET 0x00001900UL
+#define EMU_CM_OFFSET 0x00001A00UL
+#define DEVICE_PRM_OFFSET 0x00001B00UL
+#define INSTR_PRM_OFFSET 0x00001F00UL
+
+#define CM_ABE_DSS_SYS_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x0000UL)
+#define CM_L4_WKUP_CLKSELL_OFFSET (CKGEN_PRM_OFFSET + 0x0008UL)
+#define CM_ABE_PLL_REF_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x000CUL)
+#define CM_SYS_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x0010UL)
+
+/**
+ * Address offsets from the CM1 memory region to the top level clock control
+ * registers.
+ */
+#define CKGEN_CM1_OFFSET 0x00000100UL
+#define MPU_CM1_OFFSET 0x00000300UL
+#define DSP_CM1_OFFSET 0x00000400UL
+#define ABE_CM1_OFFSET 0x00000500UL
+#define RESTORE_CM1_OFFSET 0x00000E00UL
+#define INSTR_CM1_OFFSET 0x00000F00UL
+
+#define CM_CLKSEL_DPLL_MPU (CKGEN_CM1_OFFSET + 0x006CUL)
+
+/**
+ * Address offsets from the CM2 memory region to the top level clock control
+ * registers.
+ */
+#define INTRCONN_SOCKET_CM2_OFFSET 0x00000000UL
+#define CKGEN_CM2_OFFSET 0x00000100UL
+#define ALWAYS_ON_CM2_OFFSET 0x00000600UL
+#define CORE_CM2_OFFSET 0x00000700UL
+#define IVAHD_CM2_OFFSET 0x00000F00UL
+#define CAM_CM2_OFFSET 0x00001000UL
+#define DSS_CM2_OFFSET 0x00001100UL
+#define SGX_CM2_OFFSET 0x00001200UL
+#define L3INIT_CM2_OFFSET 0x00001300UL
+#define L4PER_CM2_OFFSET 0x00001400UL
+#define RESTORE_CM2_OFFSET 0x00001E00UL
+#define INSTR_CM2_OFFSET 0x00001F00UL
+
+#define CLKCTRL_MODULEMODE_MASK 0x00000003UL
+#define CLKCTRL_MODULEMODE_DISABLE 0x00000000UL
+#define CLKCTRL_MODULEMODE_AUTO 0x00000001UL
+#define CLKCTRL_MODULEMODE_ENABLE 0x00000001UL
+
+#define CLKCTRL_IDLEST_MASK 0x00030000UL
+#define CLKCTRL_IDLEST_ENABLED 0x00000000UL
+#define CLKCTRL_IDLEST_WAKING 0x00010000UL
+#define CLKCTRL_IDLEST_IDLE 0x00020000UL
+#define CLKCTRL_IDLEST_DISABLED 0x00030000UL
+
+static struct resource_spec omap4_scm_res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */
+ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* Control memory window */
+ { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* Control memory window */
+ { -1, 0 }
+};
+
+struct omap4_prcm_softc {
+ struct resource *sc_res[3];
+};
+
+static struct omap4_prcm_softc *omap4_prcm_sc;
+
+static int omap4_clk_generic_activate(struct ti_clock_dev *clkdev);
+static int omap4_clk_generic_deactivate(struct ti_clock_dev *clkdev);
+static int omap4_clk_generic_accessible(struct ti_clock_dev *clkdev);
+static int omap4_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
+static int omap4_clk_generic_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+
+static int omap4_clk_gptimer_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
+static int omap4_clk_gptimer_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+
+static int omap4_clk_hsmmc_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
+static int omap4_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+
+static int omap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
+static int omap4_clk_hsusbhost_activate(struct ti_clock_dev *clkdev);
+static int omap4_clk_hsusbhost_deactivate(struct ti_clock_dev *clkdev);
+static int omap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev);
+
+static int omap4_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+static int omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
+
+/**
+ * omap_clk_devmap - Array of clock devices available on OMAP4xxx devices
+ *
+ * This map only defines which clocks are valid and the callback functions
+ * for clock activate, deactivate, etc. It is used by the top level omap_prcm
+ * driver.
+ *
+ * The actual details of the clocks (config registers, bit fields, sources,
+ * etc) are in the private g_omap3_clk_details array below.
+ *
+ */
+
+#define OMAP4_GENERIC_CLOCK_DEV(i) \
+ { .id = (i), \
+ .clk_activate = omap4_clk_generic_activate, \
+ .clk_deactivate = omap4_clk_generic_deactivate, \
+ .clk_set_source = omap4_clk_generic_set_source, \
+ .clk_accessible = omap4_clk_generic_accessible, \
+ .clk_get_source_freq = omap4_clk_generic_get_source_freq \
+ }
+
+#define OMAP4_GPTIMER_CLOCK_DEV(i) \
+ { .id = (i), \
+ .clk_activate = omap4_clk_generic_activate, \
+ .clk_deactivate = omap4_clk_generic_deactivate, \
+ .clk_set_source = omap4_clk_gptimer_set_source, \
+ .clk_accessible = omap4_clk_generic_accessible, \
+ .clk_get_source_freq = omap4_clk_gptimer_get_source_freq \
+ }
+
+#define OMAP4_HSMMC_CLOCK_DEV(i) \
+ { .id = (i), \
+ .clk_activate = omap4_clk_generic_activate, \
+ .clk_deactivate = omap4_clk_generic_deactivate, \
+ .clk_set_source = omap4_clk_hsmmc_set_source, \
+ .clk_accessible = omap4_clk_generic_accessible, \
+ .clk_get_source_freq = omap4_clk_hsmmc_get_source_freq \
+ }
+
+#define OMAP4_HSUSBHOST_CLOCK_DEV(i) \
+ { .id = (i), \
+ .clk_activate = omap4_clk_hsusbhost_activate, \
+ .clk_deactivate = omap4_clk_hsusbhost_deactivate, \
+ .clk_set_source = omap4_clk_hsusbhost_set_source, \
+ .clk_accessible = omap4_clk_hsusbhost_accessible, \
+ .clk_get_source_freq = NULL \
+ }
+
+
+struct ti_clock_dev ti_clk_devmap[] = {
+
+ /* System clocks */
+ { .id = SYS_CLK,
+ .clk_activate = NULL,
+ .clk_deactivate = NULL,
+ .clk_set_source = NULL,
+ .clk_accessible = NULL,
+ .clk_get_source_freq = omap4_clk_get_sysclk_freq,
+ },
+ /* MPU (ARM) core clocks */
+ { .id = MPU_CLK,
+ .clk_activate = NULL,
+ .clk_deactivate = NULL,
+ .clk_set_source = NULL,
+ .clk_accessible = NULL,
+ .clk_get_source_freq = omap4_clk_get_arm_fclk_freq,
+ },
+
+
+ /* UART device clocks */
+ OMAP4_GENERIC_CLOCK_DEV(UART1_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(UART2_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(UART3_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(UART4_CLK),
+
+ /* Timer device source clocks */
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER1_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER2_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER3_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER4_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER5_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER6_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER7_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER8_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER9_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER10_CLK),
+ OMAP4_GPTIMER_CLOCK_DEV(GPTIMER11_CLK),
+
+ /* MMC device clocks (MMC1 and MMC2 can have different input clocks) */
+ OMAP4_HSMMC_CLOCK_DEV(MMC1_CLK),
+ OMAP4_HSMMC_CLOCK_DEV(MMC2_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(MMC3_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(MMC4_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(MMC5_CLK),
+
+ /* USB HS (high speed TLL, EHCI and OHCI) */
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBTLL_CLK),
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBHSHOST_CLK),
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBFSHOST_CLK),
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_PHY_CLK),
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_PHY_CLK),
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_UTMI_CLK),
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_UTMI_CLK),
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_HSIC_CLK),
+ OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_HSIC_CLK),
+
+ /* GPIO */
+ OMAP4_GENERIC_CLOCK_DEV(GPIO1_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(GPIO2_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(GPIO3_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(GPIO4_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(GPIO5_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(GPIO6_CLK),
+
+ /* sDMA */
+ OMAP4_GENERIC_CLOCK_DEV(SDMA_CLK),
+
+ /* I2C */
+ OMAP4_GENERIC_CLOCK_DEV(I2C1_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(I2C2_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(I2C3_CLK),
+ OMAP4_GENERIC_CLOCK_DEV(I2C4_CLK),
+
+ { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
+};
+
+/**
+ * omap4_clk_details - Stores details for all the different clocks supported
+ *
+ * Whenever an operation on a clock is being performed (activated, deactivated,
+ * etc) this array is looked up to find the correct register and bit(s) we
+ * should be modifying.
+ *
+ */
+struct omap4_clk_details {
+ clk_ident_t id;
+
+ uint32_t mem_region;
+ uint32_t clksel_reg;
+
+ int32_t src_freq;
+
+ uint32_t enable_mode;
+};
+
+#define OMAP4_GENERIC_CLOCK_DETAILS(i, f, m, r, e) \
+ { .id = (i), \
+ .mem_region = (m), \
+ .clksel_reg = (r), \
+ .src_freq = (f), \
+ .enable_mode = (e), \
+ }
+
+static struct omap4_clk_details g_omap4_clk_details[] = {
+
+ /* UART */
+ OMAP4_GENERIC_CLOCK_DETAILS(UART1_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x0140), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(UART2_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x0148), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(UART3_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x0140), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(UART4_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x0148), CLKCTRL_MODULEMODE_ENABLE),
+
+ /* General purpose timers */
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER1_CLK, -1, PRM_INSTANCE_MEM_REGION,
+ (WKUP_CM_OFFSET + 0x040), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER2_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x038), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER3_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x040), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER4_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x048), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER5_CLK, -1, CM1_INSTANCE_MEM_REGION,
+ (ABE_CM1_OFFSET + 0x068), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER6_CLK, -1, CM1_INSTANCE_MEM_REGION,
+ (ABE_CM1_OFFSET + 0x070), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER7_CLK, -1, CM1_INSTANCE_MEM_REGION,
+ (ABE_CM1_OFFSET + 0x078), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER8_CLK, -1, CM1_INSTANCE_MEM_REGION,
+ (ABE_CM1_OFFSET + 0x080), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER9_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x050), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER10_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x028), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER11_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x030), CLKCTRL_MODULEMODE_ENABLE),
+
+ /* HSMMC (MMC1 and MMC2 can have different input clocks) */
+ OMAP4_GENERIC_CLOCK_DETAILS(MMC1_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L3INIT_CM2_OFFSET + 0x028), /*CLKCTRL_MODULEMODE_ENABLE*/2),
+ OMAP4_GENERIC_CLOCK_DETAILS(MMC2_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L3INIT_CM2_OFFSET + 0x030), /*CLKCTRL_MODULEMODE_ENABLE*/2),
+ OMAP4_GENERIC_CLOCK_DETAILS(MMC3_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x120), /*CLKCTRL_MODULEMODE_ENABLE*/2),
+ OMAP4_GENERIC_CLOCK_DETAILS(MMC4_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x128), /*CLKCTRL_MODULEMODE_ENABLE*/2),
+ OMAP4_GENERIC_CLOCK_DETAILS(MMC5_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x160), /*CLKCTRL_MODULEMODE_ENABLE*/1),
+
+ /* GPIO modules */
+ OMAP4_GENERIC_CLOCK_DETAILS(GPIO1_CLK, -1, PRM_INSTANCE_MEM_REGION,
+ (WKUP_CM_OFFSET + 0x038), CLKCTRL_MODULEMODE_AUTO),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPIO2_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x060), CLKCTRL_MODULEMODE_AUTO),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPIO3_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x068), CLKCTRL_MODULEMODE_AUTO),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPIO4_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x070), CLKCTRL_MODULEMODE_AUTO),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPIO5_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x078), CLKCTRL_MODULEMODE_AUTO),
+ OMAP4_GENERIC_CLOCK_DETAILS(GPIO6_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x080), CLKCTRL_MODULEMODE_AUTO),
+
+ /* sDMA block */
+ OMAP4_GENERIC_CLOCK_DETAILS(SDMA_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (CORE_CM2_OFFSET + 0x300), CLKCTRL_MODULEMODE_AUTO),
+
+ /* I2C modules */
+ OMAP4_GENERIC_CLOCK_DETAILS(I2C1_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x0A0), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(I2C2_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x0A8), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(I2C3_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x0B0), CLKCTRL_MODULEMODE_ENABLE),
+ OMAP4_GENERIC_CLOCK_DETAILS(I2C4_CLK, -1, CM2_INSTANCE_MEM_REGION,
+ (L4PER_CM2_OFFSET + 0x0B8), CLKCTRL_MODULEMODE_ENABLE),
+
+ { INVALID_CLK_IDENT, 0, 0, 0, 0 },
+};
+
+/**
+ * MAX_MODULE_ENABLE_WAIT - the number of loops to wait for the module to come
+ * alive.
+ *
+ */
+#define MAX_MODULE_ENABLE_WAIT 100
+
+/**
+ * ARRAY_SIZE - Macro to return the number of elements in a static const array.
+ *
+ */
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+/**
+ * omap4_clk_details - writes a 32-bit value to one of the timer registers
+ * @timer: Timer device context
+ * @off: The offset of a register from the timer register address range
+ * @val: The value to write into the register
+ *
+ *
+ * RETURNS:
+ * nothing
+ */
+static struct omap4_clk_details*
+omap4_clk_details(clk_ident_t id)
+{
+ struct omap4_clk_details *walker;
+
+ for (walker = g_omap4_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
+ if (id == walker->id)
+ return (walker);
+ }
+
+ return NULL;
+}
+
+/**
+ * omap4_clk_generic_activate - checks if a module is accessible
+ * @module: identifier for the module to check, see omap3_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a positive error code on failure.
+ */
+static int
+omap4_clk_generic_activate(struct ti_clock_dev *clkdev)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct omap4_clk_details* clk_details;
+ struct resource* clk_mem_res;
+ uint32_t clksel;
+ unsigned int i;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = omap4_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ clk_mem_res = sc->sc_res[clk_details->mem_region];
+
+ if (clk_mem_res == NULL)
+ return (EINVAL);
+
+ /* All the 'generic' clocks have a CLKCTRL register which is more or less
+ * generic - the have at least two fielda called MODULEMODE and IDLEST.
+ */
+ clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
+ clksel &= ~CLKCTRL_MODULEMODE_MASK;
+ clksel |= clk_details->enable_mode;
+ bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
+
+ /* Now poll on the IDLEST register to tell us if the module has come up.
+ * TODO: We need to take into account the parent clocks.
+ */
+
+ /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */
+ for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
+ clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
+ if ((clksel & CLKCTRL_IDLEST_MASK) == CLKCTRL_IDLEST_ENABLED)
+ break;
+ DELAY(10);
+ }
+
+ /* Check the enabled state */
+ if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) {
+ printf("Error: failed to enable module with clock %d\n", clkdev->id);
+ printf("Error: 0x%08x => 0x%08x\n", clk_details->clksel_reg, clksel);
+ return (ETIMEDOUT);
+ }
+
+ return (0);
+}
+
+/**
+ * omap4_clk_generic_deactivate - checks if a module is accessible
+ * @module: identifier for the module to check, see omap3_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a positive error code on failure.
+ */
+static int
+omap4_clk_generic_deactivate(struct ti_clock_dev *clkdev)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct omap4_clk_details* clk_details;
+ struct resource* clk_mem_res;
+ uint32_t clksel;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = omap4_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ clk_mem_res = sc->sc_res[clk_details->mem_region];
+
+ if (clk_mem_res == NULL)
+ return (EINVAL);
+
+ /* All the 'generic' clocks have a CLKCTRL register which is more or less
+ * generic - the have at least two fielda called MODULEMODE and IDLEST.
+ */
+ clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
+ clksel &= ~CLKCTRL_MODULEMODE_MASK;
+ clksel |= CLKCTRL_MODULEMODE_DISABLE;
+ bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
+
+ return (0);
+}
+
+/**
+ * omap4_clk_generic_set_source - checks if a module is accessible
+ * @module: identifier for the module to check, see omap3_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a positive error code on failure.
+ */
+static int
+omap4_clk_generic_set_source(struct ti_clock_dev *clkdev,
+ clk_src_t clksrc)
+{
+
+ return (0);
+}
+
+/**
+ * omap4_clk_generic_accessible - checks if a module is accessible
+ * @module: identifier for the module to check, see omap3_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int
+omap4_clk_generic_accessible(struct ti_clock_dev *clkdev)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct omap4_clk_details* clk_details;
+ struct resource* clk_mem_res;
+ uint32_t clksel;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = omap4_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ clk_mem_res = sc->sc_res[clk_details->mem_region];
+
+ if (clk_mem_res == NULL)
+ return (EINVAL);
+
+ clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
+
+ /* Check the enabled state */
+ if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED)
+ return (0);
+
+ return (1);
+}
+
+/**
+ * omap4_clk_generic_get_source_freq - checks if a module is accessible
+ * @module: identifier for the module to check, see omap3_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int
+omap4_clk_generic_get_source_freq(struct ti_clock_dev *clkdev,
+ unsigned int *freq
+ )
+{
+ struct omap4_clk_details* clk_details = omap4_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ /* Simply return the stored frequency */
+ if (freq)
+ *freq = (unsigned int)clk_details->src_freq;
+
+ return (0);
+}
+
+
+/**
+ * omap4_clk_gptimer_set_source - checks if a module is accessible
+ * @module: identifier for the module to check, see omap3_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int
+omap4_clk_gptimer_set_source(struct ti_clock_dev *clkdev,
+ clk_src_t clksrc)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct omap4_clk_details* clk_details;
+ struct resource* clk_mem_res;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = omap4_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ clk_mem_res = sc->sc_res[clk_details->mem_region];
+
+ if (clk_mem_res == NULL)
+ return (EINVAL);
+
+ /* TODO: Implement */
+
+ return (0);
+}
+
+/**
+ * omap4_clk_gptimer_get_source_freq - checks if a module is accessible
+ * @module: identifier for the module to check, see omap3_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int
+omap4_clk_gptimer_get_source_freq(struct ti_clock_dev *clkdev,
+ unsigned int *freq
+ )
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct omap4_clk_details* clk_details;
+ struct resource* clk_mem_res;
+ uint32_t clksel;
+ unsigned int src_freq;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = omap4_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ clk_mem_res = sc->sc_res[clk_details->mem_region];
+
+ if (clk_mem_res == NULL)
+ return (EINVAL);
+
+ /* Need to read the CLKSEL field to determine the clock source */
+ clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
+ if (clksel & (0x1UL << 24))
+ src_freq = FREQ_32KHZ;
+ else
+ omap4_clk_get_sysclk_freq(NULL, &src_freq);
+
+ /* Return the frequency */
+ if (freq)
+ *freq = src_freq;
+
+ return (0);
+}
+
+/**
+ * omap4_clk_hsmmc_set_source - sets the source clock (freq)
+ * @clkdev: pointer to the clockdev structure (id field will contain clock id)
+ *
+ * The MMC 1 and 2 clocks can be source from either a 64MHz or 96MHz clock.
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int
+omap4_clk_hsmmc_set_source(struct ti_clock_dev *clkdev,
+ clk_src_t clksrc)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct omap4_clk_details* clk_details;
+ struct resource* clk_mem_res;
+ uint32_t clksel;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = omap4_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ clk_mem_res = sc->sc_res[clk_details->mem_region];
+
+ if (clk_mem_res == NULL)
+ return (EINVAL);
+
+ /* For MMC modules 3, 4 & 5 you can't change the freq, it's always 48MHz */
+ if ((clkdev->id == MMC3_CLK) || (clkdev->id == MMC4_CLK) ||
+ (clkdev->id == MMC5_CLK)) {
+ if (clksrc != F48MHZ_CLK)
+ return (EINVAL);
+ return 0;
+ }
+
+
+ clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
+
+ /* Bit 24 is set if 96MHz clock or cleared for 64MHz clock */
+ if (clksrc == F64MHZ_CLK)
+ clksel &= ~(0x1UL << 24);
+ else if (clksrc == F96MHZ_CLK)
+ clksel |= (0x1UL << 24);
+ else
+ return (EINVAL);
+
+ bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
+
+ return (0);
+}
+
+/**
+ * omap4_clk_hsmmc_get_source_freq - checks if a module is accessible
+ * @clkdev: pointer to the clockdev structure (id field will contain clock id)
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int
+omap4_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,
+ unsigned int *freq
+ )
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct omap4_clk_details* clk_details;
+ struct resource* clk_mem_res;
+ uint32_t clksel;
+ unsigned int src_freq;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ clk_details = omap4_clk_details(clkdev->id);
+
+ if (clk_details == NULL)
+ return (ENXIO);
+
+ clk_mem_res = sc->sc_res[clk_details->mem_region];
+
+ if (clk_mem_res == NULL)
+ return (EINVAL);
+
+ switch (clkdev->id) {
+ case MMC1_CLK:
+ case MMC2_CLK:
+ /* Need to read the CLKSEL field to determine the clock source */
+ clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
+ if (clksel & (0x1UL << 24))
+ src_freq = FREQ_96MHZ;
+ else
+ src_freq = FREQ_64MHZ;
+ break;
+ case MMC3_CLK:
+ case MMC4_CLK:
+ case MMC5_CLK:
+ src_freq = FREQ_48MHZ;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /* Return the frequency */
+ if (freq)
+ *freq = src_freq;
+
+ return (0);
+}
+
+/**
+ * omap4_clk_get_sysclk_freq - gets the sysclk frequency
+ * @sc: pointer to the clk module/device context
+ *
+ * Read the clocking information from the power-control/boot-strap registers,
+ * and stored in two global variables.
+ *
+ * RETURNS:
+ * nothing, values are saved in global variables
+ */
+static int
+omap4_clk_get_sysclk_freq(struct ti_clock_dev *clkdev,
+ unsigned int *freq)
+{
+ uint32_t clksel;
+ uint32_t sysclk;
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ /* Read the input clock freq from the configuration register (CM_SYS_CLKSEL) */
+ clksel = bus_read_4(sc->sc_res[PRM_INSTANCE_MEM_REGION], CM_SYS_CLKSEL_OFFSET);
+ switch (clksel & 0x7) {
+ case 0x1:
+ /* 12Mhz */
+ sysclk = 12000000;
+ break;
+ case 0x3:
+ /* 16.8Mhz */
+ sysclk = 16800000;
+ break;
+ case 0x4:
+ /* 19.2Mhz */
+ sysclk = 19200000;
+ break;
+ case 0x5:
+ /* 26Mhz */
+ sysclk = 26000000;
+ break;
+ case 0x7:
+ /* 38.4Mhz */
+ sysclk = 38400000;
+ break;
+ default:
+ panic("%s: Invalid clock freq", __func__);
+ }
+
+ /* Return the value */
+ if (freq)
+ *freq = sysclk;
+
+ return (0);
+}
+
+/**
+ * omap4_clk_get_arm_fclk_freq - gets the MPU clock frequency
+ * @clkdev: ignored
+ * @freq: pointer which upon return will contain the freq in hz
+ * @mem_res: array of allocated memory resources
+ *
+ * Reads the frequency setting information registers and returns the value
+ * in the freq variable.
+ *
+ * RETURNS:
+ * returns 0 on success, a positive error code on failure.
+ */
+static int
+omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev,
+ unsigned int *freq)
+{
+ uint32_t clksel;
+ uint32_t pll_mult, pll_div;
+ uint32_t mpuclk, sysclk;
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ /* Read the clksel register which contains the DPLL multiple and divide
+ * values. These are applied to the sysclk.
+ */
+ clksel = bus_read_4(sc->sc_res[CM1_INSTANCE_MEM_REGION], CM_CLKSEL_DPLL_MPU);
+
+ pll_mult = ((clksel >> 8) & 0x7ff);
+ pll_div = (clksel & 0x7f) + 1;
+
+
+ /* Get the system clock freq */
+ omap4_clk_get_sysclk_freq(NULL, &sysclk);
+
+
+ /* Calculate the MPU freq */
+ mpuclk = ((uint64_t)sysclk * pll_mult) / pll_div;
+
+ /* Return the value */
+ if (freq)
+ *freq = mpuclk;
+
+ return (0);
+}
+
+/**
+ * omap4_clk_hsusbhost_activate - activates the USB clocks for the given module
+ * @clkdev: pointer to the clock device structure.
+ * @mem_res: array of memory resources allocated by the top level PRCM driver.
+ *
+ * The USB clocking setup seems to be a bit more tricky than the other modules,
+ * to start with the clocking diagram for the HS host module shows 13 different
+ * clocks. So to try and make it easier to follow the clocking activation
+ * and deactivation is handled in it's own set of callbacks.
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a positive error code on failure.
+ */
+
+struct dpll_param {
+ unsigned int m;
+ unsigned int n;
+ unsigned int m2;
+ unsigned int m3;
+ unsigned int m4;
+ unsigned int m5;
+ unsigned int m6;
+ unsigned int m7;
+};
+/* USB parameters */
+struct dpll_param usb_dpll_param[7] = {
+ /* 12M values */
+ {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+ /* 13M values */
+ {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+ /* 16.8M values */
+ {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+ /* 19.2M values */
+ {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+ /* 26M values */
+ {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+ /* 27M values */
+ {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+ /* 38.4M values */
+#ifdef CONFIG_OMAP4_SDC
+ {0x32, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0},
+#else
+ {0x32, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0},
+#endif
+};
+static int
+omap4_clk_hsusbhost_activate(struct ti_clock_dev *clkdev)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct resource* clk_mem_res;
+ uint32_t clksel_reg_off;
+ uint32_t clksel;
+ unsigned int i;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ switch (clkdev->id) {
+ case USBTLL_CLK:
+ /* For the USBTLL module we need to enable the following clocks:
+ * - INIT_L4_ICLK (will be enabled by bootloader)
+ * - TLL_CH0_FCLK
+ * - TLL_CH1_FCLK
+ */
+
+ /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
+ clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION];
+ clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
+
+ /* Enable the module and also enable the optional func clocks for
+ * channels 0 & 1 (is this needed ?)
+ */
+ clksel = bus_read_4(clk_mem_res, clksel_reg_off);
+ clksel &= ~CLKCTRL_MODULEMODE_MASK;
+ clksel |= CLKCTRL_MODULEMODE_ENABLE;
+
+ clksel |= (0x1 << 8); /* USB-HOST optional clock: USB_CH0_CLK */
+ clksel |= (0x1 << 9); /* USB-HOST optional clock: USB_CH1_CLK */
+ break;
+
+ case USBHSHOST_CLK:
+ case USBP1_PHY_CLK:
+ case USBP2_PHY_CLK:
+ case USBP1_UTMI_CLK:
+ case USBP2_UTMI_CLK:
+ case USBP1_HSIC_CLK:
+ case USBP2_HSIC_CLK:
+ /* For the USB HS HOST module we need to enable the following clocks:
+ * - INIT_L4_ICLK (will be enabled by bootloader)
+ * - INIT_L3_ICLK (will be enabled by bootloader)
+ * - INIT_48MC_FCLK
+ * - UTMI_ROOT_GFCLK (UTMI only, create a new clock for that ?)
+ * - UTMI_P1_FCLK (UTMI only, create a new clock for that ?)
+ * - UTMI_P2_FCLK (UTMI only, create a new clock for that ?)
+ * - HSIC_P1_60 (HSIC only, create a new clock for that ?)
+ * - HSIC_P1_480 (HSIC only, create a new clock for that ?)
+ * - HSIC_P2_60 (HSIC only, create a new clock for that ?)
+ * - HSIC_P2_480 (HSIC only, create a new clock for that ?)
+ */
+
+ /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
+ clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION];
+ clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
+ clksel = bus_read_4(clk_mem_res, clksel_reg_off);
+ /* Enable the module and also enable the optional func clocks */
+ if (clkdev->id == USBHSHOST_CLK) {
+ clksel &= ~CLKCTRL_MODULEMODE_MASK;
+ clksel |= /*CLKCTRL_MODULEMODE_ENABLE*/2;
+
+ clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */
+ }
+
+ else if (clkdev->id == USBP1_UTMI_CLK)
+ clksel |= (0x1 << 8); /* UTMI_P1_CLK */
+ else if (clkdev->id == USBP2_UTMI_CLK)
+ clksel |= (0x1 << 9); /* UTMI_P2_CLK */
+
+ else if (clkdev->id == USBP1_HSIC_CLK)
+ clksel |= (0x5 << 11); /* HSIC60M_P1_CLK + HSIC480M_P1_CLK */
+ else if (clkdev->id == USBP2_HSIC_CLK)
+ clksel |= (0x5 << 12); /* HSIC60M_P2_CLK + HSIC480M_P2_CLK */
+
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ bus_write_4(clk_mem_res, clksel_reg_off, clksel);
+
+ /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */
+ for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
+ clksel = bus_read_4(clk_mem_res, clksel_reg_off);
+ if ((clksel & CLKCTRL_IDLEST_MASK) == CLKCTRL_IDLEST_ENABLED)
+ break;
+ }
+
+ /* Check the enabled state */
+ if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) {
+ printf("Error: HERE failed to enable module with clock %d\n", clkdev->id);
+ printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel);
+ return (ETIMEDOUT);
+ }
+
+ return (0);
+}
+
+/**
+ * omap4_clk_generic_deactivate - checks if a module is accessible
+ * @clkdev: pointer to the clock device structure.
+ * @mem_res: array of memory resources allocated by the top level PRCM driver.
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 on success or a positive error code on failure.
+ */
+static int
+omap4_clk_hsusbhost_deactivate(struct ti_clock_dev *clkdev)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct resource* clk_mem_res;
+ uint32_t clksel_reg_off;
+ uint32_t clksel;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ switch (clkdev->id) {
+ case USBTLL_CLK:
+ /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
+ clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION];
+ clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
+
+ clksel = bus_read_4(clk_mem_res, clksel_reg_off);
+ clksel &= ~CLKCTRL_MODULEMODE_MASK;
+ clksel |= CLKCTRL_MODULEMODE_DISABLE;
+ break;
+
+ case USBHSHOST_CLK:
+ case USBP1_PHY_CLK:
+ case USBP2_PHY_CLK:
+ case USBP1_UTMI_CLK:
+ case USBP2_UTMI_CLK:
+ case USBP1_HSIC_CLK:
+ case USBP2_HSIC_CLK:
+ /* For the USB HS HOST module we need to enable the following clocks:
+ * - INIT_L4_ICLK (will be enabled by bootloader)
+ * - INIT_L3_ICLK (will be enabled by bootloader)
+ * - INIT_48MC_FCLK
+ * - UTMI_ROOT_GFCLK (UTMI only, create a new clock for that ?)
+ * - UTMI_P1_FCLK (UTMI only, create a new clock for that ?)
+ * - UTMI_P2_FCLK (UTMI only, create a new clock for that ?)
+ * - HSIC_P1_60 (HSIC only, create a new clock for that ?)
+ * - HSIC_P1_480 (HSIC only, create a new clock for that ?)
+ * - HSIC_P2_60 (HSIC only, create a new clock for that ?)
+ * - HSIC_P2_480 (HSIC only, create a new clock for that ?)
+ */
+
+ /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
+ clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION];
+ clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
+ clksel = bus_read_4(clk_mem_res, clksel_reg_off);
+
+ /* Enable the module and also enable the optional func clocks */
+ if (clkdev->id == USBHSHOST_CLK) {
+ clksel &= ~CLKCTRL_MODULEMODE_MASK;
+ clksel |= CLKCTRL_MODULEMODE_DISABLE;
+
+ clksel &= ~(0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */
+ }
+
+ else if (clkdev->id == USBP1_UTMI_CLK)
+ clksel &= ~(0x1 << 8); /* UTMI_P1_CLK */
+ else if (clkdev->id == USBP2_UTMI_CLK)
+ clksel &= ~(0x1 << 9); /* UTMI_P2_CLK */
+
+ else if (clkdev->id == USBP1_HSIC_CLK)
+ clksel &= ~(0x5 << 11); /* HSIC60M_P1_CLK + HSIC480M_P1_CLK */
+ else if (clkdev->id == USBP2_HSIC_CLK)
+ clksel &= ~(0x5 << 12); /* HSIC60M_P2_CLK + HSIC480M_P2_CLK */
+
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ bus_write_4(clk_mem_res, clksel_reg_off, clksel);
+
+ return (0);
+}
+
+/**
+ * omap4_clk_hsusbhost_accessible - checks if a module is accessible
+ * @clkdev: pointer to the clock device structure.
+ * @mem_res: array of memory resources allocated by the top level PRCM driver.
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 if module is not enable, 1 if module is enabled or a negative
+ * error code on failure.
+ */
+static int
+omap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct resource* clk_mem_res;
+ uint32_t clksel_reg_off;
+ uint32_t clksel;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ if (clkdev->id == USBTLL_CLK) {
+ /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
+ clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION];
+ clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
+ }
+ else if (clkdev->id == USBHSHOST_CLK) {
+ /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
+ clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION];
+ clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
+ }
+ else {
+ return (EINVAL);
+ }
+
+ clksel = bus_read_4(clk_mem_res, clksel_reg_off);
+
+ /* Check the enabled state */
+ if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED)
+ return (0);
+
+ return (1);
+}
+
+/**
+ * omap4_clk_hsusbhost_set_source - sets the source clocks
+ * @clkdev: pointer to the clock device structure.
+ * @clksrc: the clock source ID for the given clock.
+ * @mem_res: array of memory resources allocated by the top level PRCM driver.
+ *
+ *
+ *
+ * LOCKING:
+ * Inherits the locks from the omap_prcm driver, no internal locking.
+ *
+ * RETURNS:
+ * Returns 0 if sucessful otherwise a negative error code on failure.
+ */
+static int
+omap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev,
+ clk_src_t clksrc)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ struct resource* clk_mem_res;
+ uint32_t clksel_reg_off;
+ uint32_t clksel;
+ unsigned int bit;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ if (clkdev->id == USBP1_PHY_CLK)
+ bit = 24;
+ else if (clkdev->id != USBP2_PHY_CLK)
+ bit = 25;
+ else
+ return (EINVAL);
+
+ /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
+ clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION];
+ clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
+ clksel = bus_read_4(clk_mem_res, clksel_reg_off);
+
+ /* Set the clock source to either external or internal */
+ if (clksrc == EXT_CLK)
+ clksel |= (0x1 << bit);
+ else
+ clksel &= ~(0x1 << bit);
+
+ bus_write_4(clk_mem_res, clksel_reg_off, clksel);
+
+ return (0);
+}
+
+#define PRM_RSTCTRL 0x1b00
+#define PRM_RSTCTRL_RESET 0x2
+
+static void
+omap4_prcm_reset(void)
+{
+ struct omap4_prcm_softc *sc = omap4_prcm_sc;
+ bus_write_4(sc->sc_res[0], PRM_RSTCTRL,
+ bus_read_4(sc->sc_res[0], PRM_RSTCTRL) | PRM_RSTCTRL_RESET);
+ bus_read_4(sc->sc_res[0], PRM_RSTCTRL);
+}
+
+/**
+ * omap4_prcm_probe - probe function for the driver
+ * @dev: prcm device handle
+ *
+ * Simply sets the name of the driver module.
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * Always returns 0
+ */
+static int
+omap4_prcm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,omap4_prcm"))
+ return (ENXIO);
+
+ device_set_desc(dev, "TI OMAP Power, Reset and Clock Management");
+ return (0);
+}
+
+/**
+ * omap_prcm_attach - attach function for the driver
+ * @dev: prcm device handle
+ *
+ * Allocates and sets up the driver context, this simply entails creating a
+ * bus mappings for the PRCM register set.
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * Always returns 0
+ */
+
+extern uint32_t platform_arm_tmr_freq;
+
+static int
+omap4_prcm_attach(device_t dev)
+{
+ struct omap4_prcm_softc *sc = device_get_softc(dev);
+ unsigned int freq;
+
+ if (bus_alloc_resources(dev, omap4_scm_res_spec, sc->sc_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ omap4_prcm_sc = sc;
+ ti_cpu_reset = omap4_prcm_reset;
+ omap4_clk_get_arm_fclk_freq(NULL, &freq);
+ arm_tmr_change_frequency(freq / 2);
+
+ return (0);
+}
+
+static device_method_t omap4_prcm_methods[] = {
+ DEVMETHOD(device_probe, omap4_prcm_probe),
+ DEVMETHOD(device_attach, omap4_prcm_attach),
+ {0, 0},
+};
+
+static driver_t omap4_prcm_driver = {
+ "omap4_prcm",
+ omap4_prcm_methods,
+ sizeof(struct omap4_prcm_softc),
+};
+
+static devclass_t omap4_prcm_devclass;
+
+EARLY_DRIVER_MODULE(omap4_prcm, simplebus, omap4_prcm_driver,
+ omap4_prcm_devclass, 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY);
+MODULE_VERSION(omap4_prcm, 1);
Property changes on: trunk/sys/arm/ti/omap4/omap4_prcm_clks.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/omap4_reg.h
===================================================================
--- trunk/sys/arm/ti/omap4/omap4_reg.h (rev 0)
+++ trunk/sys/arm/ti/omap4/omap4_reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,587 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/omap4/omap4_reg.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+/*
+ * Texas Instruments - OMAP44xx series processors
+ *
+ * Reference:
+ * OMAP44xx Applications Processor
+ * Technical Reference Manual
+ * (omap44xx_techref.pdf)
+ *
+ *
+ * Note:
+ * The devices are mapped into address above 0xD000_0000 as the kernel space
+ * memory is at 0xC000_0000 and above. The first 256MB after this is reserved
+ * for the size of the kernel, everything above that is reserved for SoC
+ * devices.
+ *
+ */
+#ifndef _OMAP44XX_REG_H_
+#define _OMAP44XX_REG_H_
+
+#ifndef _LOCORE
+#include <sys/types.h> /* for uint32_t */
+#endif
+
+
+
+
+
+/* Physical/Virtual address for SDRAM controller */
+
+#define OMAP44XX_SMS_VBASE 0x6C000000UL
+#define OMAP44XX_SMS_HWBASE 0x6C000000UL
+#define OMAP44XX_SMS_SIZE 0x01000000UL
+
+#define OMAP44XX_SDRC_VBASE 0x6D000000UL
+#define OMAP44XX_SDRC_HWBASE 0x6D000000UL
+#define OMAP44XX_SDRC_SIZE 0x01000000UL
+
+
+
+/* Physical/Virtual address for I/O space */
+
+#define OMAP44XX_L3_EMU_VBASE 0xD4000000UL
+#define OMAP44XX_L3_EMU_HWBASE 0x54000000UL
+#define OMAP44XX_L3_EMU_SIZE 0x00200000UL
+
+#define OMAP44XX_L3_EMIF1_VBASE 0xEC000000UL
+#define OMAP44XX_L3_EMIF1_HWBASE 0x4C000000UL
+#define OMAP44XX_L3_EMIF1_SIZE 0x01000000UL
+
+#define OMAP44XX_L3_EMIF2_VBASE 0xED000000UL
+#define OMAP44XX_L3_EMIF2_HWBASE 0x4D000000UL
+#define OMAP44XX_L3_EMIF2_SIZE 0x01000000UL
+
+
+#define OMAP44XX_L4_CORE_VBASE 0xEA000000UL
+#define OMAP44XX_L4_CORE_HWBASE 0x4A000000UL
+#define OMAP44XX_L4_CORE_SIZE 0x01000000UL
+
+#define OMAP44XX_L4_WAKEUP_VBASE 0xEA300000UL
+#define OMAP44XX_L4_WAKEUP_HWBASE 0x4A300000UL
+#define OMAP44XX_L4_WAKEUP_SIZE 0x00040000UL
+
+#define OMAP44XX_L4_PERIPH_VBASE 0xE8000000UL
+#define OMAP44XX_L4_PERIPH_HWBASE 0x48000000UL
+#define OMAP44XX_L4_PERIPH_SIZE 0x01000000UL
+
+#define OMAP44XX_L4_ABE_VBASE 0xE9000000UL
+#define OMAP44XX_L4_ABE_HWBASE 0x49000000UL
+#define OMAP44XX_L4_ABE_SIZE 0x00100000UL
+
+
+/* Physical/Virtual address for MPU Subsystem space */
+
+#define OMAP44XX_MPU_SUBSYS_VBASE (OMAP44XX_L4_PERIPH_VBASE + 0x00240000UL)
+#define OMAP44XX_MPU_SUBSYS_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + 0x00240000UL)
+#define OMAP44XX_MPU_SUBSYS_SIZE 0x00004000UL
+
+/*
+ * MPU Subsystem addresss offsets
+ */
+#define OMAP44XX_SCU_OFFSET 0x00000000UL
+#define OMAP44XX_GIC_CPU_OFFSET 0x00000100UL
+#define OMAP44XX_GBL_TIMER_OFFSET 0x00000200UL
+#define OMAP44XX_PRV_TIMER_OFFSET 0x00000600UL
+#define OMAP44XX_GIC_DIST_OFFSET 0x00001000UL
+#define OMAP44XX_PL310_OFFSET 0x00002000UL
+#define OMAP44XX_CORTEXA9_SOCKET_PRCM_OFFSET 0x00003000UL
+#define OMAP44XX_CORTEXA9_PRM_OFFSET 0x00003200UL
+#define OMAP44XX_CORTEXA9_CPU0_OFFSET 0x00003400UL
+#define OMAP44XX_CORTEXA9_CPU1_OFFSET 0x00003800UL
+
+#define OMAP44XX_SCU_HWBASE (OMAP44XX_MPU_SUBSYS_HWBASE + OMAP44XX_SCU_OFFSET)
+#define OMAP44XX_SCU_VBASE (OMAP44XX_MPU_SUBSYS_VBASE + OMAP44XX_SCU_OFFSET)
+#define OMAP44XX_SCU_SIZE 0x00000080UL
+#define OMAP44XX_GIC_CPU_HWBASE (OMAP44XX_MPU_SUBSYS_HWBASE + OMAP44XX_GIC_CPU_OFFSET)
+#define OMAP44XX_GIC_CPU_VBASE (OMAP44XX_MPU_SUBSYS_VBASE + OMAP44XX_GIC_CPU_OFFSET)
+#define OMAP44XX_GIC_CPU_SIZE 0x00000100UL
+#define OMAP44XX_GBL_TIMER_HWBASE (OMAP44XX_MPU_SUBSYS_HWBASE + OMAP44XX_GBL_TIMER_OFFSET)
+#define OMAP44XX_GBL_TIMER_VBASE (OMAP44XX_MPU_SUBSYS_VBASE + OMAP44XX_GBL_TIMER_OFFSET)
+#define OMAP44XX_GBL_TIMER_SIZE 0x00000100UL
+#define OMAP44XX_PRV_TIMER_HWBASE (OMAP44XX_MPU_SUBSYS_HWBASE + OMAP44XX_PRV_TIMER_OFFSET)
+#define OMAP44XX_PRV_TIMER_VBASE (OMAP44XX_MPU_SUBSYS_VBASE + OMAP44XX_PRV_TIMER_OFFSET)
+#define OMAP44XX_PRV_TIMER_SIZE 0x00000100UL
+#define OMAP44XX_GIC_DIST_HWBASE (OMAP44XX_MPU_SUBSYS_HWBASE + OMAP44XX_GIC_DIST_OFFSET)
+#define OMAP44XX_GIC_DIST_VBASE (OMAP44XX_MPU_SUBSYS_VBASE + OMAP44XX_GIC_DIST_OFFSET)
+#define OMAP44XX_GIC_DIST_SIZE 0x00000100UL
+#define OMAP44XX_PL310_HWBASE (OMAP44XX_MPU_SUBSYS_HWBASE + OMAP44XX_PL310_OFFSET)
+#define OMAP44XX_PL310_VBASE (OMAP44XX_MPU_SUBSYS_VBASE + OMAP44XX_PL310_OFFSET)
+#define OMAP44XX_PL310_SIZE 0x00001000UL
+
+
+
+
+/*
+ * L4-CORE Physical/Virtual addresss offsets
+ */
+#define OMAP44XX_SCM_OFFSET 0x00002000UL
+#define OMAP44XX_CM_OFFSET 0x00004000UL
+#define OMAP44XX_SDMA_OFFSET 0x00056000UL
+#define OMAP44XX_USB_TLL_OFFSET 0x00062000UL
+#define OMAP44XX_USB_UHH_OFFSET 0x00064000UL
+#define OMAP44XX_USB_OHCI_OFFSET 0x00064800UL
+#define OMAP44XX_USB_EHCI_OFFSET 0x00064C00UL
+#define OMAP44XX_MCBSP1_OFFSET 0x00074000UL
+#define OMAP44XX_MCBSP5_OFFSET 0x00096000UL
+#define OMAP44XX_SCM_PADCONF_OFFSET 0x00100000UL
+
+/*
+ * L4-WAKEUP Physical/Virtual addresss offsets
+ */
+#define OMAP44XX_PRM_OFFSET 0x00006000UL
+#define OMAP44XX_SCRM_OFFSET 0x0000A000UL
+#define OMAP44XX_GPIO1_OFFSET 0x00010000UL
+#define OMAP44XX_GPTIMER1_OFFSET 0x00018000UL
+
+
+
+/*
+ * L4-PERIPH Physical/Virtual addresss offsets
+ */
+#define OMAP44XX_UART3_OFFSET 0x00020000UL
+#define OMAP44XX_GPTIMER2_OFFSET 0x00032000UL
+#define OMAP44XX_GPTIMER3_OFFSET 0x00034000UL
+#define OMAP44XX_GPTIMER4_OFFSET 0x00036000UL
+#define OMAP44XX_GPTIMER9_OFFSET 0x0003E000UL
+#define OMAP44XX_GPIO2_OFFSET 0x00055000UL
+#define OMAP44XX_GPIO3_OFFSET 0x00057000UL
+#define OMAP44XX_GPIO4_OFFSET 0x00059000UL
+#define OMAP44XX_GPIO5_OFFSET 0x0005B000UL
+#define OMAP44XX_GPIO6_OFFSET 0x0005D000UL
+#define OMAP44XX_I2C3_OFFSET 0x00060000UL
+#define OMAP44XX_UART1_OFFSET 0x0006A000UL
+#define OMAP44XX_UART2_OFFSET 0x0006C000UL
+#define OMAP44XX_UART4_OFFSET 0x0006E000UL
+#define OMAP44XX_I2C1_OFFSET 0x00070000UL
+#define OMAP44XX_I2C2_OFFSET 0x00072000UL
+#define OMAP44XX_SLIMBUS2_OFFSET 0x00076000UL
+#define OMAP44XX_ELM_OFFSET 0x00078000UL
+#define OMAP44XX_GPTIMER10_OFFSET 0x00086000UL
+#define OMAP44XX_GPTIMER11_OFFSET 0x00088000UL
+#define OMAP44XX_MCBSP4_OFFSET 0x00096000UL
+#define OMAP44XX_MCSPI1_OFFSET 0x00098000UL
+#define OMAP44XX_MCSPI2_OFFSET 0x0009A000UL
+#define OMAP44XX_MMCHS1_OFFSET 0x0009C000UL
+#define OMAP44XX_MMCSD3_OFFSET 0x000AD000UL
+#define OMAP44XX_MMCHS2_OFFSET 0x000B4000UL
+#define OMAP44XX_MMCSD4_OFFSET 0x000D1000UL
+#define OMAP44XX_MMCSD5_OFFSET 0x000D5000UL
+#define OMAP44XX_I2C4_OFFSET 0x00350000UL
+
+/* The following are registers defined as part of the ARM MPCORE system,
+ * they are not SoC components rather registers that control the MPCORE core.
+ */
+// #define OMAP44XX_SCU_OFFSET 0x48240000 /* Snoop control unit */
+// #define OMAP44XX_GIC_PROC_OFFSET 0x48240100 /* Interrupt controller unit */
+// #define OMAP44XX_MPU_TIMER_OFFSET 0x48240600
+// #define OMAP44XX_GIC_INTR_OFFSET 0x48241000
+// #define OMAP44XX_PL310_OFFSET 0x48242000 /* L2 Cache controller */
+
+
+/*
+ * L4-ABE Physical/Virtual addresss offsets
+ */
+#define OMAP44XX_GPTIMER5_OFFSET 0x00038000UL
+#define OMAP44XX_GPTIMER6_OFFSET 0x0003A000UL
+#define OMAP44XX_GPTIMER7_OFFSET 0x0003C000UL
+#define OMAP44XX_GPTIMER8_OFFSET 0x0003E000UL
+
+
+
+
+
+/*
+ * System Control Module
+ */
+#define OMAP44XX_SCM_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_SCM_OFFSET)
+#define OMAP44XX_SCM_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_SCM_OFFSET)
+#define OMAP44XX_SCM_SIZE 0x00001000UL
+
+
+
+/*
+ *
+ */
+#define OMAP44XX_CM_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_CM_OFFSET)
+#define OMAP44XX_CM_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_CM_OFFSET)
+#define OMAP44XX_CM_SIZE 0x00001500UL
+
+
+/*
+ *
+ */
+#define OMAP44XX_PRM_HWBASE (OMAP44XX_L4_WAKEUP_HWBASE + OMAP44XX_PRM_OFFSET)
+#define OMAP44XX_PRM_VBASE (OMAP44XX_L4_WAKEUP_VBASE + OMAP44XX_PRM_OFFSET)
+#define OMAP44XX_PRM_SIZE 0x00001600UL
+
+/*
+ *
+ */
+#define OMAP44XX_SCRM_HWBASE (OMAP44XX_L4_WAKEUP_HWBASE + OMAP44XX_SCRM_OFFSET)
+#define OMAP44XX_SCRM_VBASE (OMAP44XX_L4_WAKEUP_VBASE + OMAP44XX_SCRM_OFFSET)
+#define OMAP44XX_SCRM_SIZE 0x00000800UL
+
+
+
+/*
+ * Uarts
+ */
+#define OMAP44XX_UART1_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_UART1_OFFSET)
+#define OMAP44XX_UART1_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_UART1_OFFSET)
+#define OMAP44XX_UART1_SIZE 0x00001000UL
+#define OMAP44XX_UART2_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_UART2_OFFSET)
+#define OMAP44XX_UART2_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_UART2_OFFSET)
+#define OMAP44XX_UART2_SIZE 0x00001000UL
+#define OMAP44XX_UART3_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_UART3_OFFSET)
+#define OMAP44XX_UART3_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_UART3_OFFSET)
+#define OMAP44XX_UART3_SIZE 0x00001000UL
+#define OMAP44XX_UART4_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_UART4_OFFSET)
+#define OMAP44XX_UART4_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_UART4_OFFSET)
+#define OMAP44XX_UART4_SIZE 0x00001000UL
+
+
+
+
+/*
+ * I2C Modules
+ */
+#define OMAP44XX_I2C1_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_I2C1_OFFSET)
+#define OMAP44XX_I2C1_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_I2C1_OFFSET)
+#define OMAP44XX_I2C1_SIZE 0x00000080UL
+#define OMAP44XX_I2C2_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_I2C2_OFFSET)
+#define OMAP44XX_I2C2_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_I2C2_OFFSET)
+#define OMAP44XX_I2C2_SIZE 0x00000080UL
+#define OMAP44XX_I2C3_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_I2C3_OFFSET)
+#define OMAP44XX_I2C3_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_I2C3_OFFSET)
+#define OMAP44XX_I2C3_SIZE 0x00000080UL
+
+
+
+/*
+ * McBSP Modules
+ */
+#define OMAP44XX_MCBSP1_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_MCBSP1_OFFSET)
+#define OMAP44XX_MCBSP1_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_MCBSP1_OFFSET)
+#define OMAP44XX_MCBSP1_SIZE 0x00001000UL
+#define OMAP44XX_MCBSP2_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_MCBSP2_OFFSET)
+#define OMAP44XX_MCBSP2_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_MCBSP2_OFFSET)
+#define OMAP44XX_MCBSP2_SIZE 0x00001000UL
+#define OMAP44XX_MCBSP3_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_MCBSP3_OFFSET)
+#define OMAP44XX_MCBSP3_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_MCBSP3_OFFSET)
+#define OMAP44XX_MCBSP3_SIZE 0x00001000UL
+#define OMAP44XX_MCBSP4_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_MCBSP4_OFFSET)
+#define OMAP44XX_MCBSP4_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_MCBSP4_OFFSET)
+#define OMAP44XX_MCBSP4_SIZE 0x00001000UL
+#define OMAP44XX_MCBSP5_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_MCBSP5_OFFSET)
+#define OMAP44XX_MCBSP5_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_MCBSP5_OFFSET)
+#define OMAP44XX_MCBSP5_SIZE 0x00001000UL
+
+
+
+/*
+ * USB TTL Module
+ */
+#define OMAP44XX_USB_TLL_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_USB_TLL_OFFSET)
+#define OMAP44XX_USB_TLL_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_USB_TLL_OFFSET)
+#define OMAP44XX_USB_TLL_SIZE 0x00001000UL
+
+/*
+ * USB Host Module
+ */
+#define OMAP44XX_USB_UHH_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_USB_UHH_OFFSET)
+#define OMAP44XX_USB_UHH_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_USB_UHH_OFFSET)
+#define OMAP44XX_USB_UHH_SIZE 0x00000700UL
+
+/*
+ * USB OHCI Module
+ */
+#define OMAP44XX_USB_OHCI_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_USB_OHCI_OFFSET)
+#define OMAP44XX_USB_OHCI_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_USB_OHCI_OFFSET)
+#define OMAP44XX_USB_OHCI_SIZE 0x00000400UL
+
+/*
+ * USB EHCI Module
+ */
+#define OMAP44XX_USB_EHCI_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_USB_EHCI_OFFSET)
+#define OMAP44XX_USB_EHCI_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_USB_EHCI_OFFSET)
+#define OMAP44XX_USB_EHCI_SIZE 0x0000400UL
+
+
+
+
+
+/*
+ * SDMA Offset
+ * PA 0x4805 6000
+ */
+
+#define OMAP44XX_SDMA_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_SDMA_OFFSET)
+#define OMAP44XX_SDMA_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_SDMA_OFFSET)
+#define OMAP44XX_SDMA_SIZE 0x00001000UL
+
+
+
+/*
+ * Interrupt Controller Unit.
+ *
+ * Refer to the omap4_intr.c file for interrupt controller (GIC)
+ * implementation.
+ *
+ * Note:
+ * - 16 Interprocessor interrupts (IPI): ID[15:0]
+ * - 2 private Timer/Watchdog interrupts: ID[30:29]
+ * - 2 legacy nFIQ & nIRQ: one per CPU, bypasses the interrupt distributor
+ * logic and directly drives interrupt requests into CPU if used in
+ * legacy mode (else treated like other interrupts lines with ID28
+ * and ID31 respectively)
+ * - 128 hardware interrupts: ID[159:32] (rising-edge or high-level sensitive).
+ */
+#define OMAP44XX_HARDIRQ(x) (32 + (x))
+
+#define OMAP44XX_IRQ_L2CACHE OMAP44XX_HARDIRQ(0) /* L2 cache controller interrupt */
+#define OMAP44XX_IRQ_CTI_0 OMAP44XX_HARDIRQ(1) /* Cross-trigger module 0 (CTI0) interrupt */
+#define OMAP44XX_IRQ_CTI_1 OMAP44XX_HARDIRQ(2) /* Cross-trigger module 1 (CTI1) interrupt */
+#define OMAP44XX_IRQ_RESERVED3 OMAP44XX_HARDIRQ(3) /* RESERVED */
+#define OMAP44XX_IRQ_ELM OMAP44XX_HARDIRQ(4) /* Error location process completion */
+#define OMAP44XX_IRQ_RESERVED5 OMAP44XX_HARDIRQ(5) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED6 OMAP44XX_HARDIRQ(6) /* RESERVED */
+#define OMAP44XX_IRQ_SYS_NIRQ OMAP44XX_HARDIRQ(7) /* External source (active low) */
+#define OMAP44XX_IRQ_RESERVED8 OMAP44XX_HARDIRQ(8) /* RESERVED */
+#define OMAP44XX_IRQ_L3_DBG OMAP44XX_HARDIRQ(9) /* L3 interconnect debug error */
+#define OMAP44XX_IRQ_L3_APP OMAP44XX_HARDIRQ(10) /* L3 interconnect application error */
+#define OMAP44XX_IRQ_PRCM_MPU OMAP44XX_HARDIRQ(11) /* PRCM module IRQ */
+#define OMAP44XX_IRQ_SDMA0 OMAP44XX_HARDIRQ(12) /* System DMA request 0(3) */
+#define OMAP44XX_IRQ_SDMA1 OMAP44XX_HARDIRQ(13) /* System DMA request 1(3) */
+#define OMAP44XX_IRQ_SDMA2 OMAP44XX_HARDIRQ(14) /* System DMA request 2 */
+#define OMAP44XX_IRQ_SDMA3 OMAP44XX_HARDIRQ(15) /* System DMA request 3 */
+#define OMAP44XX_IRQ_MCBSP4 OMAP44XX_HARDIRQ(16) /* McBSP module 4 IRQ */
+#define OMAP44XX_IRQ_MCBSP1 OMAP44XX_HARDIRQ(17) /* McBSP module 1 IRQ */
+#define OMAP44XX_IRQ_SR1 OMAP44XX_HARDIRQ(18) /* SmartReflexâ„¢ 1 */
+#define OMAP44XX_IRQ_SR2 OMAP44XX_HARDIRQ(19) /* SmartReflexâ„¢ 2 */
+#define OMAP44XX_IRQ_GPMC OMAP44XX_HARDIRQ(20) /* General-purpose memory controller module */
+#define OMAP44XX_IRQ_SGX OMAP44XX_HARDIRQ(21) /* 2D/3D graphics module */
+#define OMAP44XX_IRQ_MCBSP2 OMAP44XX_HARDIRQ(22) /* McBSP module 2 */
+#define OMAP44XX_IRQ_MCBSP3 OMAP44XX_HARDIRQ(23) /* McBSP module 3 */
+#define OMAP44XX_IRQ_ISS5 OMAP44XX_HARDIRQ(24) /* Imaging subsystem interrupt 5 */
+#define OMAP44XX_IRQ_DSS OMAP44XX_HARDIRQ(25) /* Display subsystem module(3) */
+#define OMAP44XX_IRQ_MAIL_U0 OMAP44XX_HARDIRQ(26) /* Mailbox user 0 request */
+#define OMAP44XX_IRQ_C2C_SSCM OMAP44XX_HARDIRQ(27) /* C2C status interrupt */
+#define OMAP44XX_IRQ_DSP_MMU OMAP44XX_HARDIRQ(28) /* DSP MMU */
+#define OMAP44XX_IRQ_GPIO1_MPU OMAP44XX_HARDIRQ(29) /* GPIO module 1(3) */
+#define OMAP44XX_IRQ_GPIO2_MPU OMAP44XX_HARDIRQ(30) /* GPIO module 2(3) */
+#define OMAP44XX_IRQ_GPIO3_MPU OMAP44XX_HARDIRQ(31) /* GPIO module 3(3) */
+#define OMAP44XX_IRQ_GPIO4_MPU OMAP44XX_HARDIRQ(32) /* GPIO module 4(3) */
+#define OMAP44XX_IRQ_GPIO5_MPU OMAP44XX_HARDIRQ(33) /* GPIO module 5(3) */
+#define OMAP44XX_IRQ_GPIO6_MPU OMAP44XX_HARDIRQ(34) /* GPIO module 6(3) */
+#define OMAP44XX_IRQ_RESERVED35 OMAP44XX_HARDIRQ(35) /* RESERVED */
+#define OMAP44XX_IRQ_WDT3 OMAP44XX_HARDIRQ(36) /* Watchdog timer module 3 overflow */
+#define OMAP44XX_IRQ_GPT1 OMAP44XX_HARDIRQ(37) /* General-purpose timer module 1 */
+#define OMAP44XX_IRQ_GPT2 OMAP44XX_HARDIRQ(38) /* General-purpose timer module 2 */
+#define OMAP44XX_IRQ_GPT3 OMAP44XX_HARDIRQ(39) /* General-purpose timer module 3 */
+#define OMAP44XX_IRQ_GPT4 OMAP44XX_HARDIRQ(40) /* General-purpose timer module 4 */
+#define OMAP44XX_IRQ_GPT5 OMAP44XX_HARDIRQ(41) /* General-purpose timer module 5 */
+#define OMAP44XX_IRQ_GPT6 OMAP44XX_HARDIRQ(42) /* General-purpose timer module 6 */
+#define OMAP44XX_IRQ_GPT7 OMAP44XX_HARDIRQ(43) /* General-purpose timer module 7 */
+#define OMAP44XX_IRQ_GPT8 OMAP44XX_HARDIRQ(44) /* General-purpose timer module 8 */
+#define OMAP44XX_IRQ_GPT9 OMAP44XX_HARDIRQ(45) /* General-purpose timer module 9 */
+#define OMAP44XX_IRQ_GPT10 OMAP44XX_HARDIRQ(46) /* General-purpose timer module 10 */
+#define OMAP44XX_IRQ_GPT11 OMAP44XX_HARDIRQ(47) /* General-purpose timer module 11 */
+#define OMAP44XX_IRQ_MCSPI4 OMAP44XX_HARDIRQ(48) /* McSPI module 4 */
+#define OMAP44XX_IRQ_RESERVED49 OMAP44XX_HARDIRQ(49) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED50 OMAP44XX_HARDIRQ(50) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED51 OMAP44XX_HARDIRQ(51) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED52 OMAP44XX_HARDIRQ(52) /* RESERVED */
+#define OMAP44XX_IRQ_DSS_DSI1 OMAP44XX_HARDIRQ(53) /* Display Subsystem DSI1 interrupt */
+#define OMAP44XX_IRQ_RESERVED54 OMAP44XX_HARDIRQ(54) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED55 OMAP44XX_HARDIRQ(55) /* RESERVED */
+#define OMAP44XX_IRQ_I2C1 OMAP44XX_HARDIRQ(56) /* I2C module 1 */
+#define OMAP44XX_IRQ_I2C2 OMAP44XX_HARDIRQ(57) /* I2C module 2 */
+#define OMAP44XX_IRQ_HDQ OMAP44XX_HARDIRQ(58) /* HDQ / One-wire */
+#define OMAP44XX_IRQ_MMC5 OMAP44XX_HARDIRQ(59) /* MMC5 interrupt */
+#define OMAP44XX_IRQ_RESERVED60 OMAP44XX_HARDIRQ(60) /* RESERVED */
+#define OMAP44XX_IRQ_I2C3 OMAP44XX_HARDIRQ(61) /* I2C module 3 */
+#define OMAP44XX_IRQ_I2C4 OMAP44XX_HARDIRQ(62) /* I2C module 4 */
+#define OMAP44XX_IRQ_RESERVED63 OMAP44XX_HARDIRQ(63) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED64 OMAP44XX_HARDIRQ(64) /* RESERVED */
+#define OMAP44XX_IRQ_MCSPI1 OMAP44XX_HARDIRQ(65) /* McSPI module 1 */
+#define OMAP44XX_IRQ_MCSPI2 OMAP44XX_HARDIRQ(66) /* McSPI module 2 */
+#define OMAP44XX_IRQ_HSI_P1 OMAP44XX_HARDIRQ(67) /* HSI Port 1 interrupt */
+#define OMAP44XX_IRQ_HSI_P2 OMAP44XX_HARDIRQ(68) /* HSI Port 2 interrupt */
+#define OMAP44XX_IRQ_FDIF_3 OMAP44XX_HARDIRQ(69) /* Face detect interrupt 3 */
+#define OMAP44XX_IRQ_UART4 OMAP44XX_HARDIRQ(70) /* UART module 4 interrupt */
+#define OMAP44XX_IRQ_HSI_DMA OMAP44XX_HARDIRQ(71) /* HSI DMA engine MPU request */
+#define OMAP44XX_IRQ_UART1 OMAP44XX_HARDIRQ(72) /* UART module 1 */
+#define OMAP44XX_IRQ_UART2 OMAP44XX_HARDIRQ(73) /* UART module 2 */
+#define OMAP44XX_IRQ_UART3 OMAP44XX_HARDIRQ(74) /* UART module 3 (also infrared)(3) */
+#define OMAP44XX_IRQ_PBIAS OMAP44XX_HARDIRQ(75) /* Merged interrupt for PBIASlite1 and 2 */
+#define OMAP44XX_IRQ_OHCI OMAP44XX_HARDIRQ(76) /* OHCI controller HSUSB MP Host Interrupt */
+#define OMAP44XX_IRQ_EHCI OMAP44XX_HARDIRQ(77) /* EHCI controller HSUSB MP Host Interrupt */
+#define OMAP44XX_IRQ_TLL OMAP44XX_HARDIRQ(78) /* HSUSB MP TLL Interrupt */
+#define OMAP44XX_IRQ_RESERVED79 OMAP44XX_HARDIRQ(79) /* RESERVED */
+#define OMAP44XX_IRQ_WDT2 OMAP44XX_HARDIRQ(80) /* WDTIMER2 interrupt */
+#define OMAP44XX_IRQ_RESERVED81 OMAP44XX_HARDIRQ(81) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED82 OMAP44XX_HARDIRQ(82) /* RESERVED */
+#define OMAP44XX_IRQ_MMC1 OMAP44XX_HARDIRQ(83) /* MMC/SD module 1 */
+#define OMAP44XX_IRQ_DSS_DSI2 OMAP44XX_HARDIRQ(84) /* Display subsystem DSI2 interrupt */
+#define OMAP44XX_IRQ_RESERVED85 OMAP44XX_HARDIRQ(85) /* Reserved */
+#define OMAP44XX_IRQ_MMC2 OMAP44XX_HARDIRQ(86) /* MMC/SD module 2 */
+#define OMAP44XX_IRQ_MPU_ICR OMAP44XX_HARDIRQ(87) /* MPU ICR */
+#define OMAP44XX_IRQ_C2C_GPI OMAP44XX_HARDIRQ(88) /* C2C GPI interrupt */
+#define OMAP44XX_IRQ_FSUSB OMAP44XX_HARDIRQ(89) /* FS-USB - host controller Interrupt */
+#define OMAP44XX_IRQ_FSUSB_SMI OMAP44XX_HARDIRQ(90) /* FS-USB - host controller SMI Interrupt */
+#define OMAP44XX_IRQ_MCSPI3 OMAP44XX_HARDIRQ(91) /* McSPI module 3 */
+#define OMAP44XX_IRQ_HSUSB_OTG OMAP44XX_HARDIRQ(92) /* High-Speed USB OTG controller */
+#define OMAP44XX_IRQ_HSUSB_OTG_DMA OMAP44XX_HARDIRQ(93) /* High-Speed USB OTG DMA controller */
+#define OMAP44XX_IRQ_MMC3 OMAP44XX_HARDIRQ(94) /* MMC/SD module 3 */
+#define OMAP44XX_IRQ_RESERVED95 OMAP44XX_HARDIRQ(95) /* RESERVED */
+#define OMAP44XX_IRQ_MMC4 OMAP44XX_HARDIRQ(96) /* MMC4 interrupt */
+#define OMAP44XX_IRQ_SLIMBUS1 OMAP44XX_HARDIRQ(97) /* SLIMBUS1 interrupt */
+#define OMAP44XX_IRQ_SLIMBUS2 OMAP44XX_HARDIRQ(98) /* SLIMBUS2 interrupt */
+#define OMAP44XX_IRQ_ABE OMAP44XX_HARDIRQ(99) /* Audio back-end interrupt */
+#define OMAP44XX_IRQ_CORTEXM3_MMU OMAP44XX_HARDIRQ(100) /* Cortex-M3 MMU interrupt */
+#define OMAP44XX_IRQ_DSS_HDMI OMAP44XX_HARDIRQ(101) /* Display subsystem HDMI interrupt */
+#define OMAP44XX_IRQ_SR_IVA OMAP44XX_HARDIRQ(102) /* SmartReflex IVA interrupt */
+#define OMAP44XX_IRQ_IVAHD1 OMAP44XX_HARDIRQ(103) /* Sync interrupt from iCONT2 (vDMA) */
+#define OMAP44XX_IRQ_IVAHD2 OMAP44XX_HARDIRQ(104) /* Sync interrupt from iCONT1 */
+#define OMAP44XX_IRQ_RESERVED105 OMAP44XX_HARDIRQ(105) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED106 OMAP44XX_HARDIRQ(106) /* RESERVED */
+#define OMAP44XX_IRQ_IVAHD_MAILBOX0 OMAP44XX_HARDIRQ(107) /* IVAHD mailbox interrupt */
+#define OMAP44XX_IRQ_RESERVED108 OMAP44XX_HARDIRQ(108) /* RESERVED */
+#define OMAP44XX_IRQ_MCASP1 OMAP44XX_HARDIRQ(109) /* McASP1 transmit interrupt */
+#define OMAP44XX_IRQ_EMIF1 OMAP44XX_HARDIRQ(110) /* EMIF1 interrupt */
+#define OMAP44XX_IRQ_EMIF2 OMAP44XX_HARDIRQ(111) /* EMIF2 interrupt */
+#define OMAP44XX_IRQ_MCPDM OMAP44XX_HARDIRQ(112) /* MCPDM interrupt */
+#define OMAP44XX_IRQ_DMM OMAP44XX_HARDIRQ(113) /* DMM interrupt */
+#define OMAP44XX_IRQ_DMIC OMAP44XX_HARDIRQ(114) /* DMIC interrupt */
+#define OMAP44XX_IRQ_RESERVED115 OMAP44XX_HARDIRQ(115) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED116 OMAP44XX_HARDIRQ(116) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED117 OMAP44XX_HARDIRQ(117) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED118 OMAP44XX_HARDIRQ(118) /* RESERVED */
+#define OMAP44XX_IRQ_SYS_NIRQ2 OMAP44XX_HARDIRQ(119) /* External source 2 (active low) */
+#define OMAP44XX_IRQ_KBD OMAP44XX_HARDIRQ(120) /* Keyboard controller interrupt */
+#define OMAP44XX_IRQ_RESERVED121 OMAP44XX_HARDIRQ(121) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED122 OMAP44XX_HARDIRQ(122) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED123 OMAP44XX_HARDIRQ(123) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED124 OMAP44XX_HARDIRQ(124) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED125 OMAP44XX_HARDIRQ(125) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED126 OMAP44XX_HARDIRQ(126) /* RESERVED */
+#define OMAP44XX_IRQ_RESERVED127 OMAP44XX_HARDIRQ(127) /* RESERVED */
+
+
+
+/*
+ * General Purpose Timers
+ */
+#define OMAP44XX_GPTIMER1_VBASE (OMAP44XX_L4_WAKEUP_VBASE + OMAP44XX_GPTIMER1_OFFSET)
+#define OMAP44XX_GPTIMER1_HWBASE (OMAP44XX_L4_WAKEUP_HWBASE + OMAP44XX_GPTIMER1_OFFSET)
+#define OMAP44XX_GPTIMER2_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPTIMER2_OFFSET)
+#define OMAP44XX_GPTIMER2_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPTIMER2_OFFSET)
+#define OMAP44XX_GPTIMER3_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPTIMER3_OFFSET)
+#define OMAP44XX_GPTIMER3_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPTIMER3_OFFSET)
+#define OMAP44XX_GPTIMER4_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPTIMER4_OFFSET)
+#define OMAP44XX_GPTIMER4_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPTIMER4_OFFSET)
+#define OMAP44XX_GPTIMER5_VBASE (OMAP44XX_L4_ABE_VBASE + OMAP44XX_GPTIMER5_OFFSET)
+#define OMAP44XX_GPTIMER5_HWBASE (OMAP44XX_L4_ABE_HWBASE + OMAP44XX_GPTIMER5_OFFSET)
+#define OMAP44XX_GPTIMER6_VBASE (OMAP44XX_L4_ABE_VBASE + OMAP44XX_GPTIMER6_OFFSET)
+#define OMAP44XX_GPTIMER6_HWBASE (OMAP44XX_L4_ABE_HWBASE + OMAP44XX_GPTIMER6_OFFSET)
+#define OMAP44XX_GPTIMER7_VBASE (OMAP44XX_L4_ABE_VBASE + OMAP44XX_GPTIMER7_OFFSET)
+#define OMAP44XX_GPTIMER7_HWBASE (OMAP44XX_L4_ABE_HWBASE + OMAP44XX_GPTIMER7_OFFSET)
+#define OMAP44XX_GPTIMER8_VBASE (OMAP44XX_L4_ABE_VBASE + OMAP44XX_GPTIMER8_OFFSET)
+#define OMAP44XX_GPTIMER8_HWBASE (OMAP44XX_L4_ABE_HWBASE + OMAP44XX_GPTIMER8_OFFSET)
+#define OMAP44XX_GPTIMER9_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPTIMER9_OFFSET)
+#define OMAP44XX_GPTIMER9_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPTIMER9_OFFSET)
+#define OMAP44XX_GPTIMER10_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPTIMER10_OFFSET)
+#define OMAP44XX_GPTIMER10_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPTIMER10_OFFSET)
+#define OMAP44XX_GPTIMER11_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPTIMER11_OFFSET)
+#define OMAP44XX_GPTIMER11_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPTIMER11_OFFSET)
+#define OMAP44XX_GPTIMER_SIZE 0x00001000UL
+
+
+
+/*
+ * GPIO - General Purpose IO
+ */
+
+/* Base addresses for the GPIO modules */
+#define OMAP44XX_GPIO1_HWBASE (OMAP44XX_L4_WAKEUP_HWBASE + OMAP44XX_GPIO1_OFFSET)
+#define OMAP44XX_GPIO1_VBASE (OMAP44XX_L4_WAKEUP_VBASE + OMAP44XX_GPIO1_OFFSET)
+#define OMAP44XX_GPIO1_SIZE 0x00001000UL
+#define OMAP44XX_GPIO2_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPIO2_OFFSET)
+#define OMAP44XX_GPIO2_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPIO2_OFFSET)
+#define OMAP44XX_GPIO2_SIZE 0x00001000UL
+#define OMAP44XX_GPIO3_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPIO3_OFFSET)
+#define OMAP44XX_GPIO3_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPIO3_OFFSET)
+#define OMAP44XX_GPIO3_SIZE 0x00001000UL
+#define OMAP44XX_GPIO4_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPIO4_OFFSET)
+#define OMAP44XX_GPIO4_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPIO4_OFFSET)
+#define OMAP44XX_GPIO4_SIZE 0x00001000UL
+#define OMAP44XX_GPIO5_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPIO5_OFFSET)
+#define OMAP44XX_GPIO5_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPIO5_OFFSET)
+#define OMAP44XX_GPIO5_SIZE 0x00001000UL
+#define OMAP44XX_GPIO6_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_GPIO6_OFFSET)
+#define OMAP44XX_GPIO6_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_GPIO6_OFFSET)
+#define OMAP44XX_GPIO6_SIZE 0x00001000UL
+
+
+/*
+ * MMC/SD/SDIO
+ */
+
+/* Base addresses for the MMC/SD/SDIO modules */
+#define OMAP44XX_MMCHS1_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_MMCHS1_OFFSET)
+#define OMAP44XX_MMCHS1_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_MMCHS1_OFFSET)
+#define OMAP44XX_MMCHS2_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_MMCHS2_OFFSET)
+#define OMAP44XX_MMCHS2_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_MMCHS2_OFFSET)
+#define OMAP44XX_MMCHS3_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_MMCSD3_OFFSET)
+#define OMAP44XX_MMCHS3_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_MMCSD3_OFFSET)
+#define OMAP44XX_MMCHS4_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_MMCSD4_OFFSET)
+#define OMAP44XX_MMCHS4_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_MMCSD4_OFFSET)
+#define OMAP44XX_MMCHS5_HWBASE (OMAP44XX_L4_PERIPH_HWBASE + OMAP44XX_MMCSD5_OFFSET)
+#define OMAP44XX_MMCHS5_VBASE (OMAP44XX_L4_PERIPH_VBASE + OMAP44XX_MMCSD5_OFFSET)
+#define OMAP44XX_MMCHS_SIZE 0x00001000UL
+
+
+
+/*
+ * SCM - System Control Module
+ */
+
+/* Base addresses for the SC modules */
+#define OMAP44XX_SCM_PADCONF_HWBASE (OMAP44XX_L4_CORE_HWBASE + OMAP44XX_SCM_PADCONF_OFFSET)
+#define OMAP44XX_SCM_PADCONF_VBASE (OMAP44XX_L4_CORE_VBASE + OMAP44XX_SCM_PADCONF_OFFSET)
+#define OMAP44XX_SCM_PADCONF_SIZE 0x00001000UL
+
+
+
+
+#endif /* _OMAP44XX_REG_H_ */
Property changes on: trunk/sys/arm/ti/omap4/omap4_reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/omap4_scm_padconf.c
===================================================================
--- trunk/sys/arm/ti/omap4/omap4_scm_padconf.c (rev 0)
+++ trunk/sys/arm/ti/omap4/omap4_scm_padconf.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,405 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/omap4/omap4_scm_padconf.c 279467 2015-03-01 01:08:14Z dim $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <sys/gpio.h>
+
+#include <arm/ti/tivar.h>
+#include <arm/ti/ti_scm.h>
+#include <arm/ti/omap4/omap4var.h>
+#include <arm/ti/omap4/omap4_reg.h>
+
+
+/*
+ * This file defines the pin mux configuration for the OMAP4xxx series of
+ * devices.
+ *
+ * How This is Suppose to Work
+ * ===========================
+ * - There is a top level ti_scm module (System Control Module) that is
+ * the interface for all omap drivers, which can use it to change the mux
+ * settings for individual pins. (That said, typically the pin mux settings
+ * are set to defaults by the 'hints' and then not altered by the driver).
+ *
+ * - For this to work the top level driver needs all the pin info, and hence
+ * this is where this file comes in. Here we define all the pin information
+ * that is supplied to the top level driver.
+ *
+ */
+
+#define CONTROL_PADCONF_WAKEUP_EVENT (1UL << 15)
+#define CONTROL_PADCONF_WAKEUP_ENABLE (1UL << 14)
+#define CONTROL_PADCONF_OFF_PULL_UP (1UL << 13)
+#define CONTROL_PADCONF_OFF_PULL_ENABLE (1UL << 12)
+#define CONTROL_PADCONF_OFF_OUT_HIGH (1UL << 11)
+#define CONTROL_PADCONF_OFF_OUT_ENABLE (1UL << 10)
+#define CONTROL_PADCONF_OFF_ENABLE (1UL << 9)
+#define CONTROL_PADCONF_INPUT_ENABLE (1UL << 8)
+#define CONTROL_PADCONF_PULL_UP (1UL << 4)
+#define CONTROL_PADCONF_PULL_ENABLE (1UL << 3)
+#define CONTROL_PADCONF_MUXMODE_MASK (0x7)
+
+#define CONTROL_PADCONF_SATE_MASK ( CONTROL_PADCONF_WAKEUP_EVENT \
+ | CONTROL_PADCONF_WAKEUP_ENABLE \
+ | CONTROL_PADCONF_OFF_PULL_UP \
+ | CONTROL_PADCONF_OFF_PULL_ENABLE \
+ | CONTROL_PADCONF_OFF_OUT_HIGH \
+ | CONTROL_PADCONF_OFF_OUT_ENABLE \
+ | CONTROL_PADCONF_OFF_ENABLE \
+ | CONTROL_PADCONF_INPUT_ENABLE \
+ | CONTROL_PADCONF_PULL_UP \
+ | CONTROL_PADCONF_PULL_ENABLE )
+
+/* Active pin states */
+#define PADCONF_PIN_OUTPUT 0
+#define PADCONF_PIN_INPUT CONTROL_PADCONF_INPUT_ENABLE
+#define PADCONF_PIN_INPUT_PULLUP ( CONTROL_PADCONF_INPUT_ENABLE \
+ | CONTROL_PADCONF_PULL_ENABLE \
+ | CONTROL_PADCONF_PULL_UP)
+#define PADCONF_PIN_INPUT_PULLDOWN ( CONTROL_PADCONF_INPUT_ENABLE \
+ | CONTROL_PADCONF_PULL_ENABLE )
+
+/* Off mode states */
+#define PADCONF_PIN_OFF_NONE 0
+#define PADCONF_PIN_OFF_OUTPUT_HIGH ( CONTROL_PADCONF_OFF_ENABLE \
+ | CONTROL_PADCONF_OFF_OUT_ENABLE \
+ | CONTROL_PADCONF_OFF_OUT_HIGH)
+#define PADCONF_PIN_OFF_OUTPUT_LOW ( CONTROL_PADCONF_OFF_ENABLE \
+ | CONTROL_PADCONF_OFF_OUT_ENABLE)
+#define PADCONF_PIN_OFF_INPUT_PULLUP ( CONTROL_PADCONF_OFF_ENABLE \
+ | CONTROL_PADCONF_OFF_PULL_ENABLE \
+ | CONTROL_PADCONF_OFF_PULL_UP)
+#define PADCONF_PIN_OFF_INPUT_PULLDOWN ( CONTROL_PADCONF_OFF_ENABLE \
+ | CONTROL_PADCONF_OFF_PULL_ENABLE)
+#define PADCONF_PIN_OFF_WAKEUPENABLE CONTROL_PADCONF_WAKEUP_ENABLE
+
+
+#define _PINDEF(r, b, gp, gm, m0, m1, m2, m3, m4, m5, m6, m7) \
+ { .reg_off = r, \
+ .gpio_pin = gp, \
+ .gpio_mode = gm, \
+ .ballname = b, \
+ .muxmodes[0] = m0, \
+ .muxmodes[1] = m1, \
+ .muxmodes[2] = m2, \
+ .muxmodes[3] = m3, \
+ .muxmodes[4] = m4, \
+ .muxmodes[5] = m5, \
+ .muxmodes[6] = m6, \
+ .muxmodes[7] = m7, \
+ }
+
+const struct ti_scm_padstate ti_padstate_devmap[] = {
+ {"output", PADCONF_PIN_OUTPUT},
+ {"input", PADCONF_PIN_INPUT},
+ {"input_pullup", PADCONF_PIN_INPUT_PULLUP},
+ {"input_pulldown", PADCONF_PIN_INPUT_PULLDOWN},
+ { .state = NULL }
+};
+
+/*
+ * Table 18-10, p. 3470
+ */
+const struct ti_scm_padconf ti_padconf_devmap[] = {
+ _PINDEF(0x0040, "c12", 0, 0, "gpmc_ad0", "sdmmc2_dat0", NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0042, "d12", 0, 0, "gpmc_ad1", "sdmmc2_dat1", NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0044, "c13", 0, 0, "gpmc_ad2", "sdmmc2_dat2", NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0046, "d13", 0, 0, "gpmc_ad3", "sdmmc2_dat3", NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0048, "c15", 0, 0, "gpmc_ad4", "sdmmc2_dat4", "sdmmc2_dir_dat0", NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x004a, "d15", 0, 0, "gpmc_ad5", "sdmmc2_dat5", "sdmmc2_dir_dat1", NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x004c, "a16", 0, 0, "gpmc_ad6", "sdmmc2_dat6", "sdmmc2_dir_cmd", NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x004e, "b16", 0, 0, "gpmc_ad7", "sdmmc2_dat7", "sdmmc2_clk_fdbk", NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0050, "c16", 32, 3, "gpmc_ad8", "kpd_row0", "c2c_data15", "gpio_32", NULL, "sdmmc1_dat0", NULL, NULL),
+ _PINDEF(0x0052, "d16", 33, 3, "gpmc_ad9", "kpd_row1", "c2c_data14", "gpio_33", NULL, "sdmmc1_dat1", NULL, NULL),
+ _PINDEF(0x0054, "c17", 34, 3, "gpmc_ad10", "kpd_row2", "c2c_data13", "gpio_34", NULL, "sdmmc1_dat2", NULL, NULL),
+ _PINDEF(0x0056, "d17", 35, 3, "gpmc_ad11", "kpd_row3", "c2c_data12", "gpio_35", NULL, "sdmmc1_dat3", NULL, NULL),
+ _PINDEF(0x0058, "c18", 36, 3, "gpmc_ad12", "kpd_col0", "c2c_data11", "gpio_36", NULL, "sdmmc1_dat4", NULL, NULL),
+ _PINDEF(0x005a, "d18", 37, 3, "gpmc_ad13", "kpd_col1", "c2c_data10", "gpio_37", NULL, "sdmmc1_dat5", NULL, NULL),
+ _PINDEF(0x005c, "c19", 38, 3, "gpmc_ad14", "kpd_col2", "c2c_data9", "gpio_38", NULL, "sdmmc1_dat6", NULL, NULL),
+ _PINDEF(0x005e, "d19", 39, 3, "gpmc_ad15", "kpd_col3", "c2c_data8", "gpio_39", NULL, "sdmmc1_dat7", NULL, NULL),
+ _PINDEF(0x0060, "b17", 40, 3, "gpmc_a16", "kpd_row4", "c2c_datain0", "gpio_40", "venc_656_data0", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0062, "a18", 41, 3, "gpmc_a17", "kpd_row5", "c2c_datain1", "gpio_41", "venc_656_data1", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0064, "b18", 42, 3, "gpmc_a18", "kpd_row6", "c2c_datain2", "gpio_42", "venc_656_data2", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0066, "a19", 43, 3, "gpmc_a19", "kpd_row7", "c2c_datain3", "gpio_43", "venc_656_data3", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0068, "b19", 44, 3, "gpmc_a20", "kpd_col4", "c2c_datain4", "gpio_44", "venc_656_data4", NULL, NULL, "safe_mode"),
+ _PINDEF(0x006a, "b20", 45, 3, "gpmc_a21", "kpd_col5", "c2c_datain5", "gpio_45", "venc_656_data5", NULL, NULL, "safe_mode"),
+ _PINDEF(0x006c, "a21", 46, 3, "gpmc_a22", "kpd_col6", "c2c_datain6", "gpio_46", "venc_656_data6", NULL, NULL, "safe_mode"),
+ _PINDEF(0x006e, "b21", 47, 3, "gpmc_a23", "kpd_col7", "c2c_datain7", "gpio_47", "venc_656_data7", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0070, "c20", 48, 3, "gpmc_a24", "kpd_col8", "c2c_clkout0", "gpio_48", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0072, "d20", 49, 3, "gpmc_a25", NULL, "c2c_clkout1", "gpio_49", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0074, "b25", 50, 3, "gpmc_ncs0", NULL, NULL, "gpio_50", "sys_ndmareq0", NULL, NULL, NULL),
+ _PINDEF(0x0076, "c21", 51, 3, "gpmc_ncs1", NULL, "c2c_dataout6", "gpio_51", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0078, "d21", 52, 3, "gpmc_ncs2", "kpd_row8", "c2c_dataout7", "gpio_52", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x007a, "c22", 53, 3, "gpmc_ncs3", "gpmc_dir", "c2c_dataout4", "gpio_53", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x007c, "c25", 54, 3, "gpmc_nwp", "dsi1_te0", NULL, "gpio_54", "sys_ndmareq1", NULL, NULL, NULL),
+ _PINDEF(0x007e, "b22", 55, 3, "gpmc_clk", NULL, NULL, "gpio_55", "sys_ndmareq2", "sdmmc1_cmd", NULL, NULL),
+ _PINDEF(0x0080, "d25", 56, 3, "gpmc_nadv_ale", "dsi1_te1", NULL, "gpio_56", "sys_ndmareq3", "sdmmc1_clk", NULL, NULL),
+ _PINDEF(0x0082, "b11", 0, 0, "gpmc_noe", "sdmmc2_clk", NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0084, "b12", 0, 0, "gpmc_nwe", "sdmmc2_cmd", NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0086, "c23", 59, 3, "gpmc_nbe0_cle", "dsi2_te0", NULL, "gpio_59", NULL, NULL, NULL, NULL),
+ _PINDEF(0x0088, "d22", 60, 3, "gpmc_nbe1", NULL, "c2c_dataout5", "gpio_60", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x008a, "b26", 61, 3, "gpmc_wait0", "dsi2_te1", NULL, "gpio_61", NULL, NULL, NULL, NULL),
+ _PINDEF(0x008c, "b23", 62, 3, "gpmc_wait1", NULL, "c2c_dataout2", "gpio_62", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x008e, "d23", 100, 3, "gpmc_wait2", "usbc1_icusb_txen", "c2c_dataout3", "gpio_100", "sys_ndmareq0", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0090, "a24", 101, 3, "gpmc_ncs4", "dsi1_te0", "c2c_clkin0", "gpio_101", "sys_ndmareq1", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0092, "b24", 102, 3, "gpmc_ncs5", "dsi1_te1", "c2c_clkin1", "gpio_102", "sys_ndmareq2", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0094, "c24", 103, 3, "gpmc_ncs6", "dsi2_te0", "c2c_dataout0", "gpio_103", "sys_ndmareq3", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0096, "d24", 104, 3, "gpmc_ncs7", "dsi2_te1", "c2c_dataout1", "gpio_104", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0098, "b9", 63, 3, "hdmi_hpd", NULL, NULL, "gpio_63", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x009a, "b10", 64, 3, "hdmi_cec", NULL, NULL, "gpio_64", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x009c, "a8", 65, 3, "hdmi_ddc_scl", NULL, NULL, "gpio_65", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x009e, "b8", 66, 3, "hdmi_ddc_sda", NULL, NULL, "gpio_66", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00a0, "r26", 0, 0, "csi21_dx0", NULL, NULL, "gpi_67", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00a2, "r25", 0, 0, "csi21_dy0", NULL, NULL, "gpi_68", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00a4, "t26", 0, 0, "csi21_dx1", NULL, NULL, "gpi_69", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00a6, "t25", 0, 0, "csi21_dy1", NULL, NULL, "gpi_70", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00a8, "u26", 0, 0, "csi21_dx2", NULL, NULL, "gpi_71", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00aa, "u25", 0, 0, "csi21_dy2", NULL, NULL, "gpi_72", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00ac, "v26", 0, 0, "csi21_dx3", NULL, NULL, "gpi_73", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00ae, "v25", 0, 0, "csi21_dy3", NULL, NULL, "gpi_74", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00b0, "w26", 0, 0, "csi21_dx4", NULL, NULL, "gpi_75", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00b2, "w25", 0, 0, "csi21_dy4", NULL, NULL, "gpi_76", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00b4, "m26", 0, 0, "csi22_dx0", NULL, NULL, "gpi_77", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00b6, "m25", 0, 0, "csi22_dy0", NULL, NULL, "gpi_78", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00b8, "n26", 0, 0, "csi22_dx1", NULL, NULL, "gpi_79", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00ba, "n25", 0, 0, "csi22_dy1", NULL, NULL, "gpi_80", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00bc, "t27", 81, 3, "cam_shutter", NULL, NULL, "gpio_81", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00be, "u27", 82, 3, "cam_strobe", NULL, NULL, "gpio_82", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00c0, "v27", 83, 3, "cam_globalreset", NULL, NULL, "gpio_83", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00c2, "ae18", 84, 3, "usbb1_ulpitll_clk", "hsi1_cawake", NULL, "gpio_84", "usbb1_ulpiphy_clk", NULL, "hw_dbg20", "safe_mode"),
+ _PINDEF(0x00c4, "ag19", 85, 3, "usbb1_ulpitll_stp", "hsi1_cadata", "mcbsp4_clkr", "gpio_85", "usbb1_ulpiphy_stp", "usbb1_mm_rxdp", "hw_dbg21", "safe_mode"),
+ _PINDEF(0x00c6, "af19", 86, 3, "usbb1_ulpitll_dir", "hsi1_caflag", "mcbsp4_fsr", "gpio_86", "usbb1_ulpiphy_dir", NULL, "hw_dbg22", "safe_mode"),
+ _PINDEF(0x00c8, "ae19", 87, 3, "usbb1_ulpitll_nxt", "hsi1_acready", "mcbsp4_fsx", "gpio_87", "usbb1_ulpiphy_nxt", "usbb1_mm_rxdm", "hw_dbg23", "safe_mode"),
+ _PINDEF(0x00ca, "af18", 88, 3, "usbb1_ulpitll_dat0", "hsi1_acwake", "mcbsp4_clkx", "gpio_88", "usbb1_ulpiphy_dat0", "usbb1_mm_txen", "hw_dbg24", "safe_mode"),
+ _PINDEF(0x00cc, "ag18", 89, 3, "usbb1_ulpitll_dat1", "hsi1_acdata", "mcbsp4_dx", "gpio_89", "usbb1_ulpiphy_dat1", "usbb1_mm_txdat", "hw_dbg25", "safe_mode"),
+ _PINDEF(0x00ce, "ae17", 90, 3, "usbb1_ulpitll_dat2", "hsi1_acflag", "mcbsp4_dr", "gpio_90", "usbb1_ulpiphy_dat2", "usbb1_mm_txse0", "hw_dbg26", "safe_mode"),
+ _PINDEF(0x00d0, "af17", 91, 3, "usbb1_ulpitll_dat3", "hsi1_caready", NULL, "gpio_91", "usbb1_ulpiphy_dat3", "usbb1_mm_rxrcv", "hw_dbg27", "safe_mode"),
+ _PINDEF(0x00d2, "ah17", 92, 3, "usbb1_ulpitll_dat4", "dmtimer8_pwm_evt", "abe_mcbsp3_dr", "gpio_92", "usbb1_ulpiphy_dat4", NULL, "hw_dbg28", "safe_mode"),
+ _PINDEF(0x00d4, "ae16", 93, 3, "usbb1_ulpitll_dat5", "dmtimer9_pwm_evt", "abe_mcbsp3_dx", "gpio_93", "usbb1_ulpiphy_dat5", NULL, "hw_dbg29", "safe_mode"),
+ _PINDEF(0x00d6, "af16", 94, 3, "usbb1_ulpitll_dat6", "dmtimer10_pwm_evt", "abe_mcbsp3_clkx", "gpio_94", "usbb1_ulpiphy_dat6", "abe_dmic_din3", "hw_dbg30", "safe_mode"),
+ _PINDEF(0x00d8, "ag16", 95, 3, "usbb1_ulpitll_dat7", "dmtimer11_pwm_evt", "abe_mcbsp3_fsx", "gpio_95", "usbb1_ulpiphy_dat7", "abe_dmic_clk3", "hw_dbg31", "safe_mode"),
+ _PINDEF(0x00da, "af14", 96, 3, "usbb1_hsic_data", NULL, NULL, "gpio_96", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00dc, "ae14", 97, 3, "usbb1_hsic_strobe", NULL, NULL, "gpio_97", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00de, "h2", 98, 3, "usbc1_icusb_dp", NULL, NULL, "gpio_98", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00e0, "h3", 99, 3, "usbc1_icusb_dm", NULL, NULL, "gpio_99", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00e2, "d2", 100, 3, "sdmmc1_clk", NULL, "dpm_emu19", "gpio_100", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00e4, "e3", 101, 3, "sdmmc1_cmd", NULL, "uart1_rx", "gpio_101", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00e6, "e4", 102, 3, "sdmmc1_dat0", NULL, "dpm_emu18", "gpio_102", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00e8, "e2", 103, 3, "sdmmc1_dat1", NULL, "dpm_emu17", "gpio_103", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00ea, "e1", 104, 3, "sdmmc1_dat2", NULL, "dpm_emu16", "gpio_104", "jtag_tms_tmsc", NULL, NULL, "safe_mode"),
+ _PINDEF(0x00ec, "f4", 105, 3, "sdmmc1_dat3", NULL, "dpm_emu15", "gpio_105", "jtag_tck", NULL, NULL, "safe_mode"),
+ _PINDEF(0x00ee, "f3", 106, 3, "sdmmc1_dat4", NULL, NULL, "gpio_106", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00f0, "f1", 107, 3, "sdmmc1_dat5", NULL, NULL, "gpio_107", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00f2, "g4", 108, 3, "sdmmc1_dat6", NULL, NULL, "gpio_108", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00f4, "g3", 109, 3, "sdmmc1_dat7", NULL, NULL, "gpio_109", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x00f6, "ad27", 110, 3, "abe_mcbsp2_clkx", "mcspi2_clk", "abe_mcasp_ahclkx", "gpio_110", "usbb2_mm_rxdm", NULL, NULL, "safe_mode"),
+ _PINDEF(0x00f8, "ad26", 111, 3, "abe_mcbsp2_dr", "mcspi2_somi", "abe_mcasp_axr", "gpio_111", "usbb2_mm_rxdp", NULL, NULL, "safe_mode"),
+ _PINDEF(0x00fa, "ad25", 112, 3, "abe_mcbsp2_dx", "mcspi2_simo", "abe_mcasp_amute", "gpio_112", "usbb2_mm_rxrcv", NULL, NULL, "safe_mode"),
+ _PINDEF(0x00fc, "ac28", 113, 3, "abe_mcbsp2_fsx", "mcspi2_cs0", "abe_mcasp_afsx", "gpio_113", "usbb2_mm_txen", NULL, NULL, "safe_mode"),
+ _PINDEF(0x00fe, "ac26", 114, 3, "abe_mcbsp1_clkx", "abe_slimbus1_clock", NULL, "gpio_114", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0100, "ac25", 115, 3, "abe_mcbsp1_dr", "abe_slimbus1_data", NULL, "gpio_115", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0102, "ab25", 116, 3, "abe_mcbsp1_dx", "sdmmc3_dat2", "abe_mcasp_aclkx", "gpio_116", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0104, "ac27", 117, 3, "abe_mcbsp1_fsx", "sdmmc3_dat3", "abe_mcasp_amutein", "gpio_117", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0106, "ag25", 0, 0, "abe_pdm_ul_data", "abe_mcbsp3_dr", NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0108, "af25", 0, 0, "abe_pdm_dl_data", "abe_mcbsp3_dx", NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x010a, "ae25", 0, 0, "abe_pdm_frame", "abe_mcbsp3_clkx", NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x010c, "af26", 0, 0, "abe_pdm_lb_clk", "abe_mcbsp3_fsx", NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x010e, "ah26", 118, 3, "abe_clks", NULL, NULL, "gpio_118", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0110, "ae24", 119, 3, "abe_dmic_clk1", NULL, NULL, "gpio_119", "usbb2_mm_txse0", "uart4_cts", NULL, "safe_mode"),
+ _PINDEF(0x0112, "af24", 120, 3, "abe_dmic_din1", NULL, NULL, "gpio_120", "usbb2_mm_txdat", "uart4_rts", NULL, "safe_mode"),
+ _PINDEF(0x0114, "ag24", 121, 3, "abe_dmic_din2", "slimbus2_clock", "abe_mcasp_axr", "gpio_121", NULL, "dmtimer11_pwm_evt", NULL, "safe_mode"),
+ _PINDEF(0x0116, "ah24", 122, 3, "abe_dmic_din3", "slimbus2_data", "abe_dmic_clk2", "gpio_122", NULL, "dmtimer9_pwm_evt", NULL, "safe_mode"),
+ _PINDEF(0x0118, "ab26", 123, 3, "uart2_cts", "sdmmc3_clk", NULL, "gpio_123", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x011a, "ab27", 124, 3, "uart2_rts", "sdmmc3_cmd", NULL, "gpio_124", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x011c, "aa25", 125, 3, "uart2_rx", "sdmmc3_dat0", NULL, "gpio_125", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x011e, "aa26", 126, 3, "uart2_tx", "sdmmc3_dat1", NULL, "gpio_126", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0120, "aa27", 127, 3, "hdq_sio", "i2c3_sccb", "i2c2_sccb", "gpio_127", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0122, "ae28", 0, 0, "i2c1_scl", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0124, "ae26", 0, 0, "i2c1_sda", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0126, "c26", 128, 3, "i2c2_scl", "uart1_rx", NULL, "gpio_128", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0128, "d26", 129, 3, "i2c2_sda", "uart1_tx", NULL, "gpio_129", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x012a, "w27", 130, 3, "i2c3_scl", NULL, NULL, "gpio_130", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x012c, "y27", 131, 3, "i2c3_sda", NULL, NULL, "gpio_131", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x012e, "ag21", 132, 3, "i2c4_scl", NULL, NULL, "gpio_132", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0130, "ah22", 133, 3, "i2c4_sda", NULL, NULL, "gpio_133", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0132, "af22", 134, 3, "mcspi1_clk", NULL, NULL, "gpio_134", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0134, "ae22", 135, 3, "mcspi1_somi", NULL, NULL, "gpio_135", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0136, "ag22", 136, 3, "mcspi1_simo", NULL, NULL, "gpio_136", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0138, "ae23", 137, 3, "mcspi1_cs0", NULL, NULL, "gpio_137", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x013a, "af23", 138, 3, "mcspi1_cs1", "uart1_rx", NULL, "gpio_138", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x013c, "ag23", 139, 3, "mcspi1_cs2", "uart1_cts", "slimbus2_clock", "gpio_139", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x013e, "ah23", 140, 3, "mcspi1_cs3", "uart1_rts", "slimbus2_data", "gpio_140", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0140, "f27", 141, 3, "uart3_cts_rctx", "uart1_tx", NULL, "gpio_141", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0142, "f28", 142, 3, "uart3_rts_sd", NULL, NULL, "gpio_142", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0144, "g27", 143, 3, "uart3_rx_irrx", "dmtimer8_pwm_evt", NULL, "gpio_143", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0146, "g28", 144, 3, "uart3_tx_irtx", "dmtimer9_pwm_evt", NULL, "gpio_144", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0148, "ae5", 145, 3, "sdmmc5_clk", "mcspi2_clk", "usbc1_icusb_dp", "gpio_145", NULL, "sdmmc2_clk", NULL, "safe_mode"),
+ _PINDEF(0x014a, "af5", 146, 3, "sdmmc5_cmd", "mcspi2_simo", "usbc1_icusb_dm", "gpio_146", NULL, "sdmmc2_cmd", NULL, "safe_mode"),
+ _PINDEF(0x014c, "ae4", 147, 3, "sdmmc5_dat0", "mcspi2_somi", "usbc1_icusb_rcv", "gpio_147", NULL, "sdmmc2_dat0", NULL, "safe_mode"),
+ _PINDEF(0x014e, "af4", 148, 3, "sdmmc5_dat1", NULL, "usbc1_icusb_txen", "gpio_148", NULL, "sdmmc2_dat1", NULL, "safe_mode"),
+ _PINDEF(0x0150, "ag3", 149, 3, "sdmmc5_dat2", "mcspi2_cs1", NULL, "gpio_149", NULL, "sdmmc2_dat2", NULL, "safe_mode"),
+ _PINDEF(0x0152, "af3", 150, 3, "sdmmc5_dat3", "mcspi2_cs0", NULL, "gpio_150", NULL, "sdmmc2_dat3", NULL, "safe_mode"),
+ _PINDEF(0x0154, "ae21", 151, 3, "mcspi4_clk", "sdmmc4_clk", "kpd_col6", "gpio_151", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0156, "af20", 152, 3, "mcspi4_simo", "sdmmc4_cmd", "kpd_col7", "gpio_152", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0158, "af21", 153, 3, "mcspi4_somi", "sdmmc4_dat0", "kpd_row6", "gpio_153", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x015a, "ae20", 154, 3, "mcspi4_cs0", "sdmmc4_dat3", "kpd_row7", "gpio_154", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x015c, "ag20", 155, 3, "uart4_rx", "sdmmc4_dat2", "kpd_row8", "gpio_155", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x015e, "ah19", 156, 3, "uart4_tx", "sdmmc4_dat1", "kpd_col8", "gpio_156", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0160, "ag12", 157, 3, "usbb2_ulpitll_clk", "usbb2_ulpiphy_clk", "sdmmc4_cmd", "gpio_157", "hsi2_cawake", NULL, NULL, "safe_mode"),
+ _PINDEF(0x0162, "af12", 158, 3, "usbb2_ulpitll_stp", "usbb2_ulpiphy_stp", "sdmmc4_clk", "gpio_158", "hsi2_cadata", "dispc2_data23", NULL, "safe_mode"),
+ _PINDEF(0x0164, "ae12", 159, 3, "usbb2_ulpitll_dir", "usbb2_ulpiphy_dir", "sdmmc4_dat0", "gpio_159", "hsi2_caflag", "dispc2_data22", NULL, "safe_mode"),
+ _PINDEF(0x0166, "ag13", 160, 3, "usbb2_ulpitll_nxt", "usbb2_ulpiphy_nxt", "sdmmc4_dat1", "gpio_160", "hsi2_acready", "dispc2_data21", NULL, "safe_mode"),
+ _PINDEF(0x0168, "ae11", 161, 3, "usbb2_ulpitll_dat0", "usbb2_ulpiphy_dat0", "sdmmc4_dat2", "gpio_161", "hsi2_acwake", "dispc2_data20", "usbb2_mm_txen", "safe_mode"),
+ _PINDEF(0x016a, "af11", 162, 3, "usbb2_ulpitll_dat1", "usbb2_ulpiphy_dat1", "sdmmc4_dat3", "gpio_162", "hsi2_acdata", "dispc2_data19", "usbb2_mm_txdat", "safe_mode"),
+ _PINDEF(0x016c, "ag11", 163, 3, "usbb2_ulpitll_dat2", "usbb2_ulpiphy_dat2", "sdmmc3_dat2", "gpio_163", "hsi2_acflag", "dispc2_data18", "usbb2_mm_txse0", "safe_mode"),
+ _PINDEF(0x016e, "ah11", 164, 3, "usbb2_ulpitll_dat3", "usbb2_ulpiphy_dat3", "sdmmc3_dat1", "gpio_164", "hsi2_caready", "dispc2_data15", "rfbi_data15", "safe_mode"),
+ _PINDEF(0x0170, "ae10", 165, 3, "usbb2_ulpitll_dat4", "usbb2_ulpiphy_dat4", "sdmmc3_dat0", "gpio_165", "mcspi3_somi", "dispc2_data14", "rfbi_data14", "safe_mode"),
+ _PINDEF(0x0172, "af10", 166, 3, "usbb2_ulpitll_dat5", "usbb2_ulpiphy_dat5", "sdmmc3_dat3", "gpio_166", "mcspi3_cs0", "dispc2_data13", "rfbi_data13", "safe_mode"),
+ _PINDEF(0x0174, "ag10", 167, 3, "usbb2_ulpitll_dat6", "usbb2_ulpiphy_dat6", "sdmmc3_cmd", "gpio_167", "mcspi3_simo", "dispc2_data12", "rfbi_data12", "safe_mode"),
+ _PINDEF(0x0176, "ae9", 168, 3, "usbb2_ulpitll_dat7", "usbb2_ulpiphy_dat7", "sdmmc3_clk", "gpio_168", "mcspi3_clk", "dispc2_data11", "rfbi_data11", "safe_mode"),
+ _PINDEF(0x0178, "af13", 169, 3, "usbb2_hsic_data", NULL, NULL, "gpio_169", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x017a, "ae13", 170, 3, "usbb2_hsic_strobe", NULL, NULL, "gpio_170", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x017c, "g26", 171, 3, "kpd_col3", "kpd_col0", NULL, "gpio_171", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x017e, "g25", 172, 3, "kpd_col4", "kpd_col1", NULL, "gpio_172", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0180, "h26", 173, 3, "kpd_col5", "kpd_col2", NULL, "gpio_173", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0182, "h25", 174, 3, "kpd_col0", "kpd_col3", NULL, "gpio_174", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0184, "j27", 0, 0, "kpd_col1", "kpd_col4", NULL, "gpio_0", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0186, "h27", 1, 3, "kpd_col2", "kpd_col5", NULL, "gpio_1", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0188, "j26", 175, 3, "kpd_row3", "kpd_row0", NULL, "gpio_175", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x018a, "j25", 176, 3, "kpd_row4", "kpd_row1", NULL, "gpio_176", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x018c, "k26", 177, 3, "kpd_row5", "kpd_row2", NULL, "gpio_177", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x018e, "k25", 178, 3, "kpd_row0", "kpd_row3", NULL, "gpio_178", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0190, "l27", 2, 3, "kpd_row1", "kpd_row4", NULL, "gpio_2", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0192, "k27", 3, 3, "kpd_row2", "kpd_row5", NULL, "gpio_3", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0194, "c3", 0, 0, "usba0_otg_ce", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PINDEF(0x0196, "b5", 0, 0, "usba0_otg_dp", "uart3_rx_irrx", "uart2_rx", NULL, NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x0198, "b4", 0, 0, "usba0_otg_dm", "uart3_tx_irtx", "uart2_tx", NULL, NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x019a, "aa28", 181, 3, "fref_clk1_out", NULL, NULL, "gpio_181", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x019c, "y28", 182, 3, "fref_clk2_out", NULL, NULL, "gpio_182", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x019e, "ae6", 0, 0, "sys_nirq1", NULL, NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x01a0, "af6", 183, 3, "sys_nirq2", NULL, NULL, "gpio_183", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x01a2, "f26", 184, 3, "sys_boot0", NULL, NULL, "gpio_184", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x01a4, "e27", 185, 3, "sys_boot1", NULL, NULL, "gpio_185", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x01a6, "e26", 186, 3, "sys_boot2", NULL, NULL, "gpio_186", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x01a8, "e25", 187, 3, "sys_boot3", NULL, NULL, "gpio_187", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x01aa, "d28", 188, 3, "sys_boot4", NULL, NULL, "gpio_188", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x01ac, "d27", 189, 3, "sys_boot5", NULL, NULL, "gpio_189", NULL, NULL, NULL, "safe_mode"),
+ _PINDEF(0x01ae, "m2", 11, 3, "dpm_emu0", NULL, NULL, "gpio_11", NULL, NULL, "hw_dbg0", "safe_mode"),
+ _PINDEF(0x01b0, "n2", 12, 3, "dpm_emu1", NULL, NULL, "gpio_12", NULL, NULL, "hw_dbg1", "safe_mode"),
+ _PINDEF(0x01b2, "p2", 13, 3, "dpm_emu2", "usba0_ulpiphy_clk", NULL, "gpio_13", NULL, "dispc2_fid", "hw_dbg2", "safe_mode"),
+ _PINDEF(0x01b4, "v1", 14, 3, "dpm_emu3", "usba0_ulpiphy_stp", NULL, "gpio_14", "rfbi_data10", "dispc2_data10", "hw_dbg3", "safe_mode"),
+ _PINDEF(0x01b6, "v2", 15, 3, "dpm_emu4", "usba0_ulpiphy_dir", NULL, "gpio_15", "rfbi_data9", "dispc2_data9", "hw_dbg4", "safe_mode"),
+ _PINDEF(0x01b8, "w1", 16, 3, "dpm_emu5", "usba0_ulpiphy_nxt", NULL, "gpio_16", "rfbi_te_vsync0", "dispc2_data16", "hw_dbg5", "safe_mode"),
+ _PINDEF(0x01ba, "w2", 17, 3, "dpm_emu6", "usba0_ulpiphy_dat0", "uart3_tx_irtx", "gpio_17", "rfbi_hsync0", "dispc2_data17", "hw_dbg6", "safe_mode"),
+ _PINDEF(0x01bc, "w3", 18, 3, "dpm_emu7", "usba0_ulpiphy_dat1", "uart3_rx_irrx", "gpio_18", "rfbi_cs0", "dispc2_hsync", "hw_dbg7", "safe_mode"),
+ _PINDEF(0x01be, "w4", 19, 3, "dpm_emu8", "usba0_ulpiphy_dat2", "uart3_rts_sd", "gpio_19", "rfbi_re", "dispc2_pclk", "hw_dbg8", "safe_mode"),
+ _PINDEF(0x01c0, "y2", 20, 3, "dpm_emu9", "usba0_ulpiphy_dat3", "uart3_cts_rctx", "gpio_20", "rfbi_we", "dispc2_vsync", "hw_dbg9", "safe_mode"),
+ _PINDEF(0x01c2, "y3", 21, 3, "dpm_emu10", "usba0_ulpiphy_dat4", NULL, "gpio_21", "rfbi_a0", "dispc2_de", "hw_dbg10", "safe_mode"),
+ _PINDEF(0x01c4, "y4", 22, 3, "dpm_emu11", "usba0_ulpiphy_dat5", NULL, "gpio_22", "rfbi_data8", "dispc2_data8", "hw_dbg11", "safe_mode"),
+ _PINDEF(0x01c6, "aa1", 23, 3, "dpm_emu12", "usba0_ulpiphy_dat6", NULL, "gpio_23", "rfbi_data7", "dispc2_data7", "hw_dbg12", "safe_mode"),
+ _PINDEF(0x01c8, "aa2", 24, 3, "dpm_emu13", "usba0_ulpiphy_dat7", NULL, "gpio_24", "rfbi_data6", "dispc2_data6", "hw_dbg13", "safe_mode"),
+ _PINDEF(0x01ca, "aa3", 25, 3, "dpm_emu14", "sys_drm_msecure", "uart1_rx", "gpio_25", "rfbi_data5", "dispc2_data5", "hw_dbg14", "safe_mode"),
+ _PINDEF(0x01cc, "aa4", 26, 3, "dpm_emu15", "sys_secure_indicator", NULL, "gpio_26", "rfbi_data4", "dispc2_data4", "hw_dbg15", "safe_mode"),
+ _PINDEF(0x01ce, "ab2", 27, 3, "dpm_emu16", "dmtimer8_pwm_evt", "dsi1_te0", "gpio_27", "rfbi_data3", "dispc2_data3", "hw_dbg16", "safe_mode"),
+ _PINDEF(0x01d0, "ab3", 28, 3, "dpm_emu17", "dmtimer9_pwm_evt", "dsi1_te1", "gpio_28", "rfbi_data2", "dispc2_data2", "hw_dbg17", "safe_mode"),
+ _PINDEF(0x01d2, "ab4", 190, 3, "dpm_emu18", "dmtimer10_pwm_evt", "dsi2_te0", "gpio_190", "rfbi_data1", "dispc2_data1", "hw_dbg18", "safe_mode"),
+ _PINDEF(0x01d4, "ac4", 191, 3, "dpm_emu19", "dmtimer11_pwm_evt", "dsi2_te1", "gpio_191", "rfbi_data0", "dispc2_data0", "hw_dbg19", "safe_mode"),
+ { .ballname = NULL },
+};
+
+const struct ti_scm_device ti_scm_dev = {
+ .padconf_muxmode_mask = CONTROL_PADCONF_MUXMODE_MASK,
+ .padconf_sate_mask = CONTROL_PADCONF_SATE_MASK,
+ .padstate = ti_padstate_devmap,
+ .padconf = ti_padconf_devmap,
+};
+
+int
+ti_scm_padconf_set_gpioflags(uint32_t gpio, uint32_t flags)
+{
+ unsigned int state = 0;
+ /* First the SCM driver needs to be told to put the pad into GPIO mode */
+ if (flags & GPIO_PIN_OUTPUT)
+ state = PADCONF_PIN_OUTPUT;
+ else if (flags & GPIO_PIN_INPUT) {
+ if (flags & GPIO_PIN_PULLUP)
+ state = PADCONF_PIN_INPUT_PULLUP;
+ else if (flags & GPIO_PIN_PULLDOWN)
+ state = PADCONF_PIN_INPUT_PULLDOWN;
+ else
+ state = PADCONF_PIN_INPUT;
+ }
+ return ti_scm_padconf_set_gpiomode(gpio, state);
+}
+
+void
+ti_scm_padconf_get_gpioflags(uint32_t gpio, uint32_t *flags)
+{
+ unsigned int state;
+ /* Get the current pin state */
+ if (ti_scm_padconf_get_gpiomode(gpio, &state) != 0)
+ *flags = 0;
+ else {
+ switch (state) {
+ case PADCONF_PIN_OUTPUT:
+ *flags = GPIO_PIN_OUTPUT;
+ break;
+ case PADCONF_PIN_INPUT:
+ *flags = GPIO_PIN_INPUT;
+ break;
+ case PADCONF_PIN_INPUT_PULLUP:
+ *flags = GPIO_PIN_INPUT | GPIO_PIN_PULLUP;
+ break;
+ case PADCONF_PIN_INPUT_PULLDOWN:
+ *flags = GPIO_PIN_INPUT | GPIO_PIN_PULLDOWN;
+ break;
+ default:
+ *flags = 0;
+ break;
+ }
+ }
+}
+
Property changes on: trunk/sys/arm/ti/omap4/omap4_scm_padconf.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/omap4_smc.h
===================================================================
--- trunk/sys/arm/ti/omap4/omap4_smc.h (rev 0)
+++ trunk/sys/arm/ti/omap4/omap4_smc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,53 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * $FreeBSD: stable/10/sys/arm/ti/omap4/omap4_smc.h 244914 2012-12-31 21:19:44Z gonzo $
+ */
+
+#ifndef OMAP4_SMC_H_
+#define OMAP4_SMC_H_
+/* Define the various function IDs used by the OMAP4 */
+#define L2CACHE_WRITE_DEBUG_REG 0x100
+#define L2CACHE_CLEAN_INV_RANG 0x101
+#define L2CACHE_WRITE_CTRL_REG 0x102
+#define READ_AUX_CORE_REGS 0x103
+#define MODIFY_AUX_CORE_0 0x104
+#define WRITE_AUX_CORE_1 0x105
+#define READ_WKG_CTRL_REG 0x106
+#define CLEAR_WKG_CTRL_REG 0x107
+#define SET_POWER_STATUS_REG 0x108
+#define WRITE_AUXCTRL_REG 0x109
+#define LOCKDOWN_TLB 0x10a
+#define SELECT_TLB_ENTRY_FOR_WRITE 0x10b
+#define READ_TLB_VA_ENTRY 0x10c
+#define WRITE_TLB_VA_ENTRY 0x10d
+#define READ_TLB_PA_ENTRY 0x10e
+#define WRITE_TLB_PA_ENTRY 0x10f
+#define READ_TLB_ATTR_ENTRY 0x110
+#define WRITE_TLB_ATTR_ENTRY 0x111
+#define WRITE_LATENCY_CTRL_REG 0x112
+#define WRITE_PREFETCH_CTRL_REG 0x113
+#endif /* OMAP4_SMC_H_ */
Property changes on: trunk/sys/arm/ti/omap4/omap4_smc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/omap4var.h
===================================================================
--- trunk/sys/arm/ti/omap4/omap4var.h (rev 0)
+++ trunk/sys/arm/ti/omap4/omap4var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,92 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/omap4/omap4var.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+#ifndef _OMAP4VAR_H_
+#define _OMAP4VAR_H_
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/endian.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+
+void omap4_mask_all_intr(void);
+void omap4_post_filter_intr(void *arg);
+
+struct omap4_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iotag;
+
+ /* Handles for the two generic interrupt controller (GIC) register mappings */
+ bus_space_handle_t sc_gic_cpu_ioh;
+ bus_space_handle_t sc_gic_dist_ioh;
+
+ /* Handle for the PL310 L2 cache controller */
+ bus_space_handle_t sc_pl310_ioh;
+
+ /* Handle for the global and provate timer register set in the Cortex core */
+ bus_space_handle_t sc_prv_timer_ioh;
+ bus_space_handle_t sc_gbl_timer_ioh;
+
+ /* SCM access */
+ struct resource *sc_scm_mem;
+ int sc_scm_rid;
+};
+
+struct omap4_intr_conf {
+ int num;
+ unsigned int priority;
+ unsigned int target_cpu;
+};
+
+int omap4_setup_intr_controller(device_t dev,
+ const struct omap4_intr_conf *irqs);
+int omap4_setup_gic_cpu(unsigned int prio_mask);
+
+void omap4_init_timer(device_t dev);
+
+int omap4_setup_l2cache_controller(struct omap4_softc *sc);
+void omap4_smc_call(uint32_t fn, uint32_t arg);
+
+#endif /* _OMAP4VAR_H_ */
Property changes on: trunk/sys/arm/ti/omap4/omap4var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/pandaboard/files.pandaboard
===================================================================
--- trunk/sys/arm/ti/omap4/pandaboard/files.pandaboard (rev 0)
+++ trunk/sys/arm/ti/omap4/pandaboard/files.pandaboard 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,3 @@
+# $FreeBSD: stable/10/sys/arm/ti/omap4/pandaboard/files.pandaboard 239281 2012-08-15 06:31:32Z gonzo $
+
+arm/ti/omap4/pandaboard/pandaboard.c standard
Property changes on: trunk/sys/arm/ti/omap4/pandaboard/files.pandaboard
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/pandaboard/pandaboard.c
===================================================================
--- trunk/sys/arm/ti/omap4/pandaboard/pandaboard.c (rev 0)
+++ trunk/sys/arm/ti/omap4/pandaboard/pandaboard.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,210 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/omap4/pandaboard/pandaboard.c 259329 2013-12-13 20:43:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/pte.h>
+#include <machine/vmparam.h>
+#include <machine/fdt.h>
+
+#include <arm/ti/omap4/omap4var.h>
+#include <arm/ti/omap4/omap4_reg.h>
+
+/* Registers in the SCRM that control the AUX clocks */
+#define SCRM_ALTCLKSRC (0x110)
+#define SCRM_AUXCLK0 (0x0310)
+#define SCRM_AUXCLK1 (0x0314)
+#define SCRM_AUXCLK2 (0x0318)
+#define SCRM_AUXCLK3 (0x031C)
+
+/* Some of the GPIO register set */
+#define GPIO1_OE (0x0134)
+#define GPIO1_CLEARDATAOUT (0x0190)
+#define GPIO1_SETDATAOUT (0x0194)
+#define GPIO2_OE (0x0134)
+#define GPIO2_CLEARDATAOUT (0x0190)
+#define GPIO2_SETDATAOUT (0x0194)
+
+/* Some of the PADCONF register set */
+#define CONTROL_WKUP_PAD0_FREF_CLK3_OUT (0x058)
+#define CONTROL_CORE_PAD1_KPD_COL2 (0x186)
+#define CONTROL_CORE_PAD0_GPMC_WAIT1 (0x08C)
+
+#define REG_WRITE32(r, x) *((volatile uint32_t*)(r)) = (uint32_t)(x)
+#define REG_READ32(r) *((volatile uint32_t*)(r))
+
+#define REG_WRITE16(r, x) *((volatile uint16_t*)(r)) = (uint16_t)(x)
+#define REG_READ16(r) *((volatile uint16_t*)(r))
+
+/**
+ * usb_hub_init - initialises and resets the external USB hub
+ *
+ * The USB hub needs to be held in reset while the power is being applied
+ * and the reference clock is enabled at 19.2MHz. The following is the
+ * layout of the USB hub taken from the Pandaboard reference manual.
+ *
+ *
+ * .-------------. .--------------. .----------------.
+ * | OMAP4430 | | USB3320C | | LAN9514 |
+ * | | | | | USB Hub / Eth |
+ * | CLK | <------ | CLKOUT | | |
+ * | STP | ------> | STP | | |
+ * | DIR | <------ | DIR | | |
+ * | NXT | <------ | NXT | | |
+ * | DAT0 | <-----> | DAT0 | | |
+ * | DAT1 | <-----> | DAT1 DP | <-----> | DP |
+ * | DAT2 | <-----> | DAT2 DM | <-----> | DM |
+ * | DAT3 | <-----> | DAT3 | | |
+ * | DAT4 | <-----> | DAT4 | | |
+ * | DAT5 | <-----> | DAT5 | +----> | N_RESET |
+ * | DAT6 | <-----> | DAT6 | | | |
+ * | DAT7 | <-----> | DAT7 | | | |
+ * | | | | | +-> | VDD33IO |
+ * | AUX_CLK3 | ------> | REFCLK | | +-> | VDD33A |
+ * | | | | | | | |
+ * | GPIO_62 | --+---> | RESET | | | | |
+ * | | | | | | | | |
+ * | | | '--------------' | | '----------------'
+ * | | | .--------------. | |
+ * | | '---->| VOLT CONVERT |--' |
+ * | | '--------------' |
+ * | | |
+ * | | .--------------. |
+ * | GPIO_1 | ------> | TPS73633 |-----'
+ * | | '--------------'
+ * '-------------'
+ *
+ *
+ * RETURNS:
+ * nothing.
+ */
+static void
+usb_hub_init(void)
+{
+ bus_space_handle_t scrm_addr, gpio1_addr, gpio2_addr, scm_addr;
+
+ if (bus_space_map(fdtbus_bs_tag, OMAP44XX_SCRM_HWBASE,
+ OMAP44XX_SCRM_SIZE, 0, &scrm_addr) != 0)
+ panic("Couldn't map SCRM registers");
+ if (bus_space_map(fdtbus_bs_tag, OMAP44XX_GPIO1_HWBASE,
+ OMAP44XX_GPIO1_SIZE, 0, &gpio1_addr) != 0)
+ panic("Couldn't map GPIO1 registers");
+ if (bus_space_map(fdtbus_bs_tag, OMAP44XX_GPIO2_HWBASE,
+ OMAP44XX_GPIO2_SIZE, 0, &gpio2_addr) != 0)
+ panic("Couldn't map GPIO2 registers");
+ if (bus_space_map(fdtbus_bs_tag, OMAP44XX_SCM_PADCONF_HWBASE,
+ OMAP44XX_SCM_PADCONF_SIZE, 0, &scm_addr) != 0)
+ panic("Couldn't map SCM Padconf registers");
+
+
+
+ /* Need to set FREF_CLK3_OUT to 19.2 MHz and pump it out on pin GPIO_WK31.
+ * We know the SYS_CLK is 38.4Mhz and therefore to get the needed 19.2Mhz,
+ * just use a 2x divider and ensure the SYS_CLK is used as the source.
+ */
+ REG_WRITE32(scrm_addr + SCRM_AUXCLK3, (1 << 16) | /* Divider of 2 */
+ (0 << 1) | /* Use the SYS_CLK as the source */
+ (1 << 8)); /* Enable the clock */
+
+ /* Enable the clock out to the pin (GPIO_WK31).
+ * muxmode=fref_clk3_out, pullup/down=disabled, input buffer=disabled,
+ * wakeup=disabled.
+ */
+ REG_WRITE16(scm_addr + CONTROL_WKUP_PAD0_FREF_CLK3_OUT, 0x0000);
+
+
+ /* Disable the power to the USB hub, drive GPIO1 low */
+ REG_WRITE32(gpio1_addr + GPIO1_OE, REG_READ32(gpio1_addr +
+ GPIO1_OE) & ~(1UL << 1));
+ REG_WRITE32(gpio1_addr + GPIO1_CLEARDATAOUT, (1UL << 1));
+ REG_WRITE16(scm_addr + CONTROL_CORE_PAD1_KPD_COL2, 0x0003);
+
+
+ /* Reset the USB PHY and Hub using GPIO_62 */
+ REG_WRITE32(gpio2_addr + GPIO2_OE,
+ REG_READ32(gpio2_addr + GPIO2_OE) & ~(1UL << 30));
+ REG_WRITE32(gpio2_addr + GPIO2_CLEARDATAOUT, (1UL << 30));
+ REG_WRITE16(scm_addr + CONTROL_CORE_PAD0_GPMC_WAIT1, 0x0003);
+ DELAY(10);
+ REG_WRITE32(gpio2_addr + GPIO2_SETDATAOUT, (1UL << 30));
+
+
+ /* Enable power to the hub (GPIO_1) */
+ REG_WRITE32(gpio1_addr + GPIO1_SETDATAOUT, (1UL << 1));
+ bus_space_unmap(fdtbus_bs_tag, scrm_addr, OMAP44XX_SCRM_SIZE);
+ bus_space_unmap(fdtbus_bs_tag, gpio1_addr, OMAP44XX_GPIO1_SIZE);
+ bus_space_unmap(fdtbus_bs_tag, gpio2_addr, OMAP44XX_GPIO2_SIZE);
+ bus_space_unmap(fdtbus_bs_tag, scm_addr, OMAP44XX_SCM_PADCONF_SIZE);
+}
+
+/**
+ * board_init - initialises the pandaboard
+ * @dummy: ignored
+ *
+ * This function is called before any of the driver are initialised, which is
+ * annoying because it means we can't use the SCM, PRCM and GPIO modules which
+ * would really be useful.
+ *
+ * So we don't have:
+ * - any drivers
+ * - no interrupts
+ *
+ * What we do have:
+ * - virt/phys mappings from the devmap (see omap4.c)
+ * -
+ *
+ *
+ * So we are hamstrung without the useful drivers and we have to go back to
+ * direct register manupulation. Luckly we don't have to do to much, basically
+ * just setup the usb hub/ethernet.
+ *
+ */
+static void
+board_init(void *dummy)
+{
+ /* Initialise the USB phy and hub */
+ usb_hub_init();
+
+ /*
+ * XXX Board identification e.g. read out from FPGA or similar should
+ * go here
+ */
+}
+
+SYSINIT(board_init, SI_SUB_CPU, SI_ORDER_THIRD, board_init, NULL);
Property changes on: trunk/sys/arm/ti/omap4/pandaboard/pandaboard.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/pandaboard/std.pandaboard
===================================================================
--- trunk/sys/arm/ti/omap4/pandaboard/std.pandaboard (rev 0)
+++ trunk/sys/arm/ti/omap4/pandaboard/std.pandaboard 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,4 @@
+# $FreeBSD: stable/10/sys/arm/ti/omap4/pandaboard/std.pandaboard 239281 2012-08-15 06:31:32Z gonzo $
+
+include "../ti/omap4/std.omap4"
+files "../ti/omap4/pandaboard/files.pandaboard"
Property changes on: trunk/sys/arm/ti/omap4/pandaboard/std.pandaboard
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/ti/omap4/std.omap4
===================================================================
--- trunk/sys/arm/ti/omap4/std.omap4 (rev 0)
+++ trunk/sys/arm/ti/omap4/std.omap4 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,23 @@
+# Omap4430 generic configuration
+#$FreeBSD: stable/10/sys/arm/ti/omap4/std.omap4 266110 2014-05-15 02:41:23Z ian $
+files "../ti/omap4/files.omap4"
+include "../ti/std.ti"
+makeoption ARM_LITTLE_ENDIAN
+
+# Physical memory starts at 0x80000000. We assume images are loaded at
+# 0x80200000, e.g. from u-boot with 'fatload mmc 0 0x80200000 kernel.bin'
+#
+#
+options PHYSADDR=0x80000000
+options KERNPHYSADDR=0x80200000
+makeoptions KERNPHYSADDR=0x80200000
+options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+makeoptions KERNVIRTADDR=0xc0200000
+
+options SOC_OMAP4
+
+options ARM_L2_PIPT
+
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
+
Property changes on: trunk/sys/arm/ti/omap4/std.omap4
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/ti/std.ti
===================================================================
--- trunk/sys/arm/ti/std.ti (rev 0)
+++ trunk/sys/arm/ti/std.ti 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,7 @@
+# $FreeBSD: stable/10/sys/arm/ti/std.ti 278601 2015-02-11 22:47:48Z ian $
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+
+files "../ti/files.ti"
Property changes on: trunk/sys/arm/ti/std.ti
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_adc.c
===================================================================
--- trunk/sys/arm/ti/ti_adc.c (rev 0)
+++ trunk/sys/arm/ti/ti_adc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,595 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_adc.c 270238 2014-08-20 18:10:12Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_adcreg.h>
+#include <arm/ti/ti_adcvar.h>
+
+/* Define our 8 steps, one for each input channel. */
+static struct ti_adc_input ti_adc_inputs[TI_ADC_NPINS] = {
+ { .stepconfig = ADC_STEPCFG1, .stepdelay = ADC_STEPDLY1 },
+ { .stepconfig = ADC_STEPCFG2, .stepdelay = ADC_STEPDLY2 },
+ { .stepconfig = ADC_STEPCFG3, .stepdelay = ADC_STEPDLY3 },
+ { .stepconfig = ADC_STEPCFG4, .stepdelay = ADC_STEPDLY4 },
+ { .stepconfig = ADC_STEPCFG5, .stepdelay = ADC_STEPDLY5 },
+ { .stepconfig = ADC_STEPCFG6, .stepdelay = ADC_STEPDLY6 },
+ { .stepconfig = ADC_STEPCFG7, .stepdelay = ADC_STEPDLY7 },
+ { .stepconfig = ADC_STEPCFG8, .stepdelay = ADC_STEPDLY8 },
+};
+
+static int ti_adc_samples[5] = { 0, 2, 4, 8, 16 };
+
+static void
+ti_adc_enable(struct ti_adc_softc *sc)
+{
+
+ TI_ADC_LOCK_ASSERT(sc);
+
+ if (sc->sc_last_state == 1)
+ return;
+
+ /* Enable the FIFO0 threshold and the end of sequence interrupt. */
+ ADC_WRITE4(sc, ADC_IRQENABLE_SET,
+ ADC_IRQ_FIFO0_THRES | ADC_IRQ_END_OF_SEQ);
+
+ /* Enable the ADC. Run thru enabled steps, start the conversions. */
+ ADC_WRITE4(sc, ADC_CTRL, ADC_READ4(sc, ADC_CTRL) | ADC_CTRL_ENABLE);
+
+ sc->sc_last_state = 1;
+}
+
+static void
+ti_adc_disable(struct ti_adc_softc *sc)
+{
+ int count;
+ uint32_t data;
+
+ TI_ADC_LOCK_ASSERT(sc);
+
+ if (sc->sc_last_state == 0)
+ return;
+
+ /* Disable all the enabled steps. */
+ ADC_WRITE4(sc, ADC_STEPENABLE, 0);
+
+ /* Disable the ADC. */
+ ADC_WRITE4(sc, ADC_CTRL, ADC_READ4(sc, ADC_CTRL) & ~ADC_CTRL_ENABLE);
+
+ /* Disable the FIFO0 threshold and the end of sequence interrupt. */
+ ADC_WRITE4(sc, ADC_IRQENABLE_CLR,
+ ADC_IRQ_FIFO0_THRES | ADC_IRQ_END_OF_SEQ);
+
+ /* ACK any pending interrupt. */
+ ADC_WRITE4(sc, ADC_IRQSTATUS, ADC_READ4(sc, ADC_IRQSTATUS));
+
+ /* Drain the FIFO data. */
+ count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK;
+ while (count > 0) {
+ data = ADC_READ4(sc, ADC_FIFO0DATA);
+ count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK;
+ }
+
+ sc->sc_last_state = 0;
+}
+
+static int
+ti_adc_setup(struct ti_adc_softc *sc)
+{
+ int ain;
+ uint32_t enabled;
+
+ TI_ADC_LOCK_ASSERT(sc);
+
+ /* Check for enabled inputs. */
+ enabled = 0;
+ for (ain = 0; ain < TI_ADC_NPINS; ain++) {
+ if (ti_adc_inputs[ain].enable)
+ enabled |= (1U << (ain + 1));
+ }
+
+ /* Set the ADC global status. */
+ if (enabled != 0) {
+ ti_adc_enable(sc);
+ /* Update the enabled steps. */
+ if (enabled != ADC_READ4(sc, ADC_STEPENABLE))
+ ADC_WRITE4(sc, ADC_STEPENABLE, enabled);
+ } else
+ ti_adc_disable(sc);
+
+ return (0);
+}
+
+static void
+ti_adc_input_setup(struct ti_adc_softc *sc, int32_t ain)
+{
+ struct ti_adc_input *input;
+ uint32_t reg, val;
+
+ TI_ADC_LOCK_ASSERT(sc);
+
+ input = &ti_adc_inputs[ain];
+ reg = input->stepconfig;
+ val = ADC_READ4(sc, reg);
+
+ /* Set single ended operation. */
+ val &= ~ADC_STEP_DIFF_CNTRL;
+
+ /* Set the negative voltage reference. */
+ val &= ~ADC_STEP_RFM_MSK;
+ val |= ADC_STEP_RFM_VREFN << ADC_STEP_RFM_SHIFT;
+
+ /* Set the positive voltage reference. */
+ val &= ~ADC_STEP_RFP_MSK;
+ val |= ADC_STEP_RFP_VREFP << ADC_STEP_RFP_SHIFT;
+
+ /* Set the samples average. */
+ val &= ~ADC_STEP_AVG_MSK;
+ val |= input->samples << ADC_STEP_AVG_SHIFT;
+
+ /* Select the desired input. */
+ val &= ~ADC_STEP_INP_MSK;
+ val |= ain << ADC_STEP_INP_SHIFT;
+
+ /* Set the ADC to one-shot mode. */
+ val &= ~ADC_STEP_MODE_MSK;
+
+ ADC_WRITE4(sc, reg, val);
+}
+
+static void
+ti_adc_reset(struct ti_adc_softc *sc)
+{
+ int ain;
+
+ TI_ADC_LOCK_ASSERT(sc);
+
+ /* Disable all the inputs. */
+ for (ain = 0; ain < TI_ADC_NPINS; ain++)
+ ti_adc_inputs[ain].enable = 0;
+}
+
+static int
+ti_adc_clockdiv_proc(SYSCTL_HANDLER_ARGS)
+{
+ int error, reg;
+ struct ti_adc_softc *sc;
+
+ sc = (struct ti_adc_softc *)arg1;
+
+ TI_ADC_LOCK(sc);
+ reg = (int)ADC_READ4(sc, ADC_CLKDIV) + 1;
+ TI_ADC_UNLOCK(sc);
+
+ error = sysctl_handle_int(oidp, ®, sizeof(reg), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ /*
+ * The actual written value is the prescaler setting - 1.
+ * Enforce a minimum value of 10 (i.e. 9) which limits the maximum
+ * ADC clock to ~2.4Mhz (CLK_M_OSC / 10).
+ */
+ reg--;
+ if (reg < 9)
+ reg = 9;
+ if (reg > USHRT_MAX)
+ reg = USHRT_MAX;
+
+ TI_ADC_LOCK(sc);
+ /* Disable the ADC. */
+ ti_adc_disable(sc);
+ /* Update the ADC prescaler setting. */
+ ADC_WRITE4(sc, ADC_CLKDIV, reg);
+ /* Enable the ADC again. */
+ ti_adc_setup(sc);
+ TI_ADC_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+ti_adc_enable_proc(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ int32_t enable;
+ struct ti_adc_softc *sc;
+ struct ti_adc_input *input;
+
+ input = (struct ti_adc_input *)arg1;
+ sc = input->sc;
+
+ enable = input->enable;
+ error = sysctl_handle_int(oidp, &enable, sizeof(enable),
+ req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (enable)
+ enable = 1;
+
+ TI_ADC_LOCK(sc);
+ /* Setup the ADC as needed. */
+ if (input->enable != enable) {
+ input->enable = enable;
+ ti_adc_setup(sc);
+ if (input->enable == 0)
+ input->value = 0;
+ }
+ TI_ADC_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+ti_adc_open_delay_proc(SYSCTL_HANDLER_ARGS)
+{
+ int error, reg;
+ struct ti_adc_softc *sc;
+ struct ti_adc_input *input;
+
+ input = (struct ti_adc_input *)arg1;
+ sc = input->sc;
+
+ TI_ADC_LOCK(sc);
+ reg = (int)ADC_READ4(sc, input->stepdelay) & ADC_STEP_OPEN_DELAY;
+ TI_ADC_UNLOCK(sc);
+
+ error = sysctl_handle_int(oidp, ®, sizeof(reg), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (reg < 0)
+ reg = 0;
+
+ TI_ADC_LOCK(sc);
+ ADC_WRITE4(sc, input->stepdelay, reg & ADC_STEP_OPEN_DELAY);
+ TI_ADC_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+ti_adc_samples_avg_proc(SYSCTL_HANDLER_ARGS)
+{
+ int error, samples, i;
+ struct ti_adc_softc *sc;
+ struct ti_adc_input *input;
+
+ input = (struct ti_adc_input *)arg1;
+ sc = input->sc;
+
+ if (input->samples > nitems(ti_adc_samples))
+ input->samples = nitems(ti_adc_samples);
+ samples = ti_adc_samples[input->samples];
+
+ error = sysctl_handle_int(oidp, &samples, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ TI_ADC_LOCK(sc);
+ if (samples != ti_adc_samples[input->samples]) {
+ input->samples = 0;
+ for (i = 0; i < nitems(ti_adc_samples); i++)
+ if (samples >= ti_adc_samples[i])
+ input->samples = i;
+ ti_adc_input_setup(sc, input->input);
+ }
+ TI_ADC_UNLOCK(sc);
+
+ return (error);
+}
+
+static void
+ti_adc_read_data(struct ti_adc_softc *sc)
+{
+ int count, ain;
+ struct ti_adc_input *input;
+ uint32_t data;
+
+ TI_ADC_LOCK_ASSERT(sc);
+
+ /* Read the available data. */
+ count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK;
+ while (count > 0) {
+ data = ADC_READ4(sc, ADC_FIFO0DATA);
+ ain = (data & ADC_FIFO_STEP_ID_MSK) >> ADC_FIFO_STEP_ID_SHIFT;
+ input = &ti_adc_inputs[ain];
+ if (input->enable == 0)
+ input->value = 0;
+ else
+ input->value = (int32_t)(data & ADC_FIFO_DATA_MSK);
+ count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK;
+ }
+}
+
+static void
+ti_adc_intr(void *arg)
+{
+ struct ti_adc_softc *sc;
+ uint32_t status;
+
+ sc = (struct ti_adc_softc *)arg;
+
+ status = ADC_READ4(sc, ADC_IRQSTATUS);
+ if (status == 0)
+ return;
+ if (status & ~(ADC_IRQ_FIFO0_THRES | ADC_IRQ_END_OF_SEQ))
+ device_printf(sc->sc_dev, "stray interrupt: %#x\n", status);
+
+ TI_ADC_LOCK(sc);
+ /* ACK the interrupt. */
+ ADC_WRITE4(sc, ADC_IRQSTATUS, status);
+
+ /* Read the available data. */
+ if (status & ADC_IRQ_FIFO0_THRES)
+ ti_adc_read_data(sc);
+
+ /* Start the next conversion ? */
+ if (status & ADC_IRQ_END_OF_SEQ)
+ ti_adc_setup(sc);
+ TI_ADC_UNLOCK(sc);
+}
+
+static void
+ti_adc_sysctl_init(struct ti_adc_softc *sc)
+{
+ char pinbuf[3];
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree_node, *inp_node, *inpN_node;
+ struct sysctl_oid_list *tree, *inp_tree, *inpN_tree;
+ int ain;
+
+ /*
+ * Add per-pin sysctl tree/handlers.
+ */
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ tree_node = device_get_sysctl_tree(sc->sc_dev);
+ tree = SYSCTL_CHILDREN(tree_node);
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "clockdiv",
+ CTLFLAG_RW | CTLTYPE_UINT, sc, 0,
+ ti_adc_clockdiv_proc, "IU", "ADC clock prescaler");
+ inp_node = SYSCTL_ADD_NODE(ctx, tree, OID_AUTO, "ain",
+ CTLFLAG_RD, NULL, "ADC inputs");
+ inp_tree = SYSCTL_CHILDREN(inp_node);
+
+ for (ain = 0; ain < TI_ADC_NPINS; ain++) {
+
+ snprintf(pinbuf, sizeof(pinbuf), "%d", ain);
+ inpN_node = SYSCTL_ADD_NODE(ctx, inp_tree, OID_AUTO, pinbuf,
+ CTLFLAG_RD, NULL, "ADC input");
+ inpN_tree = SYSCTL_CHILDREN(inpN_node);
+
+ SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "enable",
+ CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0,
+ ti_adc_enable_proc, "IU", "Enable ADC input");
+ SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "open_delay",
+ CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0,
+ ti_adc_open_delay_proc, "IU", "ADC open delay");
+ SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "samples_avg",
+ CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0,
+ ti_adc_samples_avg_proc, "IU", "ADC samples average");
+ SYSCTL_ADD_INT(ctx, inpN_tree, OID_AUTO, "input",
+ CTLFLAG_RD, &ti_adc_inputs[ain].value, 0,
+ "Converted raw value for the ADC input");
+ }
+}
+
+static void
+ti_adc_inputs_init(struct ti_adc_softc *sc)
+{
+ int ain;
+ struct ti_adc_input *input;
+
+ TI_ADC_LOCK(sc);
+ for (ain = 0; ain < TI_ADC_NPINS; ain++) {
+ input = &ti_adc_inputs[ain];
+ input->sc = sc;
+ input->input = ain;
+ input->value = 0;
+ input->enable = 0;
+ input->samples = 0;
+ ti_adc_input_setup(sc, ain);
+ }
+ TI_ADC_UNLOCK(sc);
+}
+
+static void
+ti_adc_idlestep_init(struct ti_adc_softc *sc)
+{
+ uint32_t val;
+
+ val = ADC_READ4(sc, ADC_IDLECONFIG);
+
+ /* Set single ended operation. */
+ val &= ~ADC_STEP_DIFF_CNTRL;
+
+ /* Set the negative voltage reference. */
+ val &= ~ADC_STEP_RFM_MSK;
+ val |= ADC_STEP_RFM_VREFN << ADC_STEP_RFM_SHIFT;
+
+ /* Set the positive voltage reference. */
+ val &= ~ADC_STEP_RFP_MSK;
+ val |= ADC_STEP_RFP_VREFP << ADC_STEP_RFP_SHIFT;
+
+ /* Connect the input to VREFN. */
+ val &= ~ADC_STEP_INP_MSK;
+ val |= ADC_STEP_IN_VREFN << ADC_STEP_INP_SHIFT;
+
+ ADC_WRITE4(sc, ADC_IDLECONFIG, val);
+}
+
+static int
+ti_adc_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "ti,adc"))
+ return (ENXIO);
+ device_set_desc(dev, "TI ADC controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_adc_attach(device_t dev)
+{
+ int err, rid;
+ struct ti_adc_softc *sc;
+ uint32_t reg, rev;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, ti_adc_intr, sc, &sc->sc_intrhand) != 0) {
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "Unable to setup the irq handler.\n");
+ return (ENXIO);
+ }
+
+ /* Activate the ADC_TSC module. */
+ err = ti_prcm_clk_enable(TSC_ADC_CLK);
+ if (err)
+ return (err);
+
+ /* Check the ADC revision. */
+ rev = ADC_READ4(sc, ADC_REVISION);
+ device_printf(dev,
+ "scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n",
+ (rev & ADC_REV_SCHEME_MSK) >> ADC_REV_SCHEME_SHIFT,
+ (rev & ADC_REV_FUNC_MSK) >> ADC_REV_FUNC_SHIFT,
+ (rev & ADC_REV_RTL_MSK) >> ADC_REV_RTL_SHIFT,
+ (rev & ADC_REV_MAJOR_MSK) >> ADC_REV_MAJOR_SHIFT,
+ rev & ADC_REV_MINOR_MSK,
+ (rev & ADC_REV_CUSTOM_MSK) >> ADC_REV_CUSTOM_SHIFT);
+
+ /*
+ * Disable the step write protect and make it store the step ID for
+ * the captured data on FIFO.
+ */
+ reg = ADC_READ4(sc, ADC_CTRL);
+ ADC_WRITE4(sc, ADC_CTRL, reg | ADC_CTRL_STEP_WP | ADC_CTRL_STEP_ID);
+
+ /*
+ * Set the ADC prescaler to 2400 (yes, the actual value written here
+ * is 2400 - 1).
+ * This sets the ADC clock to ~10Khz (CLK_M_OSC / 2400).
+ */
+ ADC_WRITE4(sc, ADC_CLKDIV, 2399);
+
+ TI_ADC_LOCK_INIT(sc);
+
+ ti_adc_idlestep_init(sc);
+ ti_adc_inputs_init(sc);
+ ti_adc_sysctl_init(sc);
+
+ return (0);
+}
+
+static int
+ti_adc_detach(device_t dev)
+{
+ struct ti_adc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Turn off the ADC. */
+ TI_ADC_LOCK(sc);
+ ti_adc_reset(sc);
+ ti_adc_setup(sc);
+ TI_ADC_UNLOCK(sc);
+
+ TI_ADC_LOCK_DESTROY(sc);
+
+ if (sc->sc_intrhand)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+
+ return (bus_generic_detach(dev));
+}
+
+static device_method_t ti_adc_methods[] = {
+ DEVMETHOD(device_probe, ti_adc_probe),
+ DEVMETHOD(device_attach, ti_adc_attach),
+ DEVMETHOD(device_detach, ti_adc_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t ti_adc_driver = {
+ "ti_adc",
+ ti_adc_methods,
+ sizeof(struct ti_adc_softc),
+};
+
+static devclass_t ti_adc_devclass;
+
+DRIVER_MODULE(ti_adc, simplebus, ti_adc_driver, ti_adc_devclass, 0, 0);
+MODULE_VERSION(ti_adc, 1);
+MODULE_DEPEND(ti_adc, simplebus, 1, 1, 1);
Property changes on: trunk/sys/arm/ti/ti_adc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_adcreg.h
===================================================================
--- trunk/sys/arm/ti/ti_adcreg.h (rev 0)
+++ trunk/sys/arm/ti/ti_adcreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,121 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_adcreg.h 270238 2014-08-20 18:10:12Z loos $
+ */
+
+#ifndef _TI_ADCREG_H_
+#define _TI_ADCREG_H_
+
+#define ADC_REVISION 0x000
+#define ADC_REV_SCHEME_MSK 0xc0000000
+#define ADC_REV_SCHEME_SHIFT 30
+#define ADC_REV_FUNC_MSK 0x0fff0000
+#define ADC_REV_FUNC_SHIFT 16
+#define ADC_REV_RTL_MSK 0x0000f800
+#define ADC_REV_RTL_SHIFT 11
+#define ADC_REV_MAJOR_MSK 0x00000700
+#define ADC_REV_MAJOR_SHIFT 8
+#define ADC_REV_CUSTOM_MSK 0x000000c0
+#define ADC_REV_CUSTOM_SHIFT 6
+#define ADC_REV_MINOR_MSK 0x0000003f
+#define ADC_SYSCFG 0x010
+#define ADC_SYSCFG_IDLE_MSK 0x000000c0
+#define ADC_SYSCFG_IDLE_SHIFT 2
+#define ADC_IRQSTATUS_RAW 0x024
+#define ADC_IRQSTATUS 0x028
+#define ADC_IRQENABLE_SET 0x02c
+#define ADC_IRQENABLE_CLR 0x030
+#define ADC_IRQ_HW_PEN_SYNC (1 << 10)
+#define ADC_IRQ_PEN_UP (1 << 9)
+#define ADC_IRQ_OUT_RANGE (1 << 8)
+#define ADC_IRQ_FIFO1_UNDR (1 << 7)
+#define ADC_IRQ_FIFO1_OVERR (1 << 6)
+#define ADC_IRQ_FIFO1_THRES (1 << 5)
+#define ADC_IRQ_FIFO0_UNDR (1 << 4)
+#define ADC_IRQ_FIFO0_OVERR (1 << 3)
+#define ADC_IRQ_FIFO0_THRES (1 << 2)
+#define ADC_IRQ_END_OF_SEQ (1 << 1)
+#define ADC_IRQ_HW_PEN_ASYNC (1 << 0)
+#define ADC_CTRL 0x040
+#define ADC_CTRL_STEP_WP (1 << 2)
+#define ADC_CTRL_STEP_ID (1 << 1)
+#define ADC_CTRL_ENABLE (1 << 0)
+#define ADC_STAT 0x044
+#define ADC_CLKDIV 0x04c
+#define ADC_STEPENABLE 0x054
+#define ADC_IDLECONFIG 0x058
+#define ADC_STEPCFG1 0x064
+#define ADC_STEPDLY1 0x068
+#define ADC_STEPCFG2 0x06c
+#define ADC_STEPDLY2 0x070
+#define ADC_STEPCFG3 0x074
+#define ADC_STEPDLY3 0x078
+#define ADC_STEPCFG4 0x07c
+#define ADC_STEPDLY4 0x080
+#define ADC_STEPCFG5 0x084
+#define ADC_STEPDLY5 0x088
+#define ADC_STEPCFG6 0x08c
+#define ADC_STEPDLY6 0x090
+#define ADC_STEPCFG7 0x094
+#define ADC_STEPDLY7 0x098
+#define ADC_STEPCFG8 0x09c
+#define ADC_STEPDLY8 0x0a0
+#define ADC_STEP_DIFF_CNTRL (1 << 25)
+#define ADC_STEP_RFM_MSK 0x01800000
+#define ADC_STEP_RFM_SHIFT 23
+#define ADC_STEP_RFM_VSSA 0
+#define ADC_STEP_RFM_XNUR 1
+#define ADC_STEP_RFM_YNLR 2
+#define ADC_STEP_RFM_VREFN 3
+#define ADC_STEP_INP_MSK 0x00780000
+#define ADC_STEP_INP_SHIFT 19
+#define ADC_STEP_INM_MSK 0x00078000
+#define ADC_STEP_INM_SHIFT 15
+#define ADC_STEP_IN_VREFN 8
+#define ADC_STEP_RFP_MSK 0x00007000
+#define ADC_STEP_RFP_SHIFT 12
+#define ADC_STEP_RFP_VDDA 0
+#define ADC_STEP_RFP_XPUL 1
+#define ADC_STEP_RFP_YPLL 2
+#define ADC_STEP_RFP_VREFP 3
+#define ADC_STEP_RFP_INTREF 4
+#define ADC_STEP_AVG_MSK 0x0000001c
+#define ADC_STEP_AVG_SHIFT 2
+#define ADC_STEP_MODE_MSK 0x00000003
+#define ADC_STEP_MODE_ONESHOT 0x00000000
+#define ADC_STEP_MODE_CONTINUOUS 0x00000001
+#define ADC_STEP_SAMPLE_DELAY 0xff000000
+#define ADC_STEP_OPEN_DELAY 0x0003ffff
+#define ADC_FIFO0COUNT 0x0e4
+#define ADC_FIFO0THRESHOLD 0x0e8
+#define ADC_FIFO0DATA 0x100
+#define ADC_FIFO_COUNT_MSK 0x0000007f
+#define ADC_FIFO_STEP_ID_MSK 0x000f0000
+#define ADC_FIFO_STEP_ID_SHIFT 16
+#define ADC_FIFO_DATA_MSK 0x00000fff
+
+#endif /* _TI_ADCREG_H_ */
Property changes on: trunk/sys/arm/ti/ti_adcreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_adcvar.h
===================================================================
--- trunk/sys/arm/ti/ti_adcvar.h (rev 0)
+++ trunk/sys/arm/ti/ti_adcvar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2014 Luiz Otavio O Souza <loos at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_adcvar.h 270238 2014-08-20 18:10:12Z loos $
+ */
+
+#ifndef _TI_ADCVAR_H_
+#define _TI_ADCVAR_H_
+
+#define TI_ADC_NPINS 8
+
+#define ADC_READ4(_sc, reg) bus_read_4((_sc)->sc_mem_res, reg)
+#define ADC_WRITE4(_sc, reg, value) \
+ bus_write_4((_sc)->sc_mem_res, reg, value)
+
+struct ti_adc_softc {
+ device_t sc_dev;
+ int sc_last_state;
+ struct mtx sc_mtx;
+ struct resource *sc_mem_res;
+ struct resource *sc_irq_res;
+ void *sc_intrhand;
+};
+
+struct ti_adc_input {
+ int32_t enable; /* input enabled */
+ int32_t samples; /* samples average */
+ int32_t input; /* input number */
+ int32_t value; /* raw converted value */
+ uint32_t stepconfig; /* step config register */
+ uint32_t stepdelay; /* step delay register */
+ struct ti_adc_softc *sc; /* pointer to adc softc */
+};
+
+#define TI_ADC_LOCK(_sc) \
+ mtx_lock(&(_sc)->sc_mtx)
+#define TI_ADC_UNLOCK(_sc) \
+ mtx_unlock(&(_sc)->sc_mtx)
+#define TI_ADC_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ "ti_adc", MTX_DEF)
+#define TI_ADC_LOCK_DESTROY(_sc) \
+ mtx_destroy(&_sc->sc_mtx);
+#define TI_ADC_LOCK_ASSERT(_sc) \
+ mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
+
+#endif /* _TI_ADCVAR_H_ */
Property changes on: trunk/sys/arm/ti/ti_adcvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_common.c
===================================================================
--- trunk/sys/arm/ti/ti_common.c (rev 0)
+++ trunk/sys/arm/ti/ti_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,99 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_global.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_common.c 266277 2014-05-17 00:53:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kdb.h>
+#include <sys/reboot.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+#ifdef SOC_OMAP4
+static int
+fdt_gic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (!fdt_is_compatible(node, "arm,gic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+#endif
+
+#ifdef SOC_TI_AM335X
+static int
+fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (!fdt_is_compatible(node, "ti,aintc"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+#endif
+
+fdt_pic_decode_t fdt_pic_table[] = {
+#ifdef SOC_OMAP4
+ &fdt_gic_decode_ic,
+#endif
+#ifdef SOC_TI_AM335X
+ &fdt_aintc_decode_ic,
+#endif
+ NULL
+};
Property changes on: trunk/sys/arm/ti/ti_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_cpuid.c
===================================================================
--- trunk/sys/arm/ti/ti_cpuid.c (rev 0)
+++ trunk/sys/arm/ti/ti_cpuid.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,331 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_cpuid.c 259329 2013-12-13 20:43:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <arm/ti/tivar.h>
+#include <arm/ti/ti_cpuid.h>
+
+#include <arm/ti/omap4/omap4_reg.h>
+#include <arm/ti/omap3/omap3_reg.h>
+#include <arm/ti/am335x/am335x_reg.h>
+
+#define OMAP4_STD_FUSE_DIE_ID_0 0x2200
+#define OMAP4_ID_CODE 0x2204
+#define OMAP4_STD_FUSE_DIE_ID_1 0x2208
+#define OMAP4_STD_FUSE_DIE_ID_2 0x220C
+#define OMAP4_STD_FUSE_DIE_ID_3 0x2210
+#define OMAP4_STD_FUSE_PROD_ID_0 0x2214
+#define OMAP4_STD_FUSE_PROD_ID_1 0x2218
+
+#define OMAP3_ID_CODE 0xA204
+
+static uint32_t chip_revision = 0xffffffff;
+
+/**
+ * ti_revision - Returns the revision number of the device
+ *
+ * Simply returns an identifier for the revision of the chip we are running
+ * on.
+ *
+ * RETURNS
+ * A 32-bit identifier for the current chip
+ */
+uint32_t
+ti_revision(void)
+{
+ return chip_revision;
+}
+
+/**
+ * omap4_get_revision - determines omap4 revision
+ *
+ * Reads the registers to determine the revision of the chip we are currently
+ * running on. Stores the information in global variables.
+ *
+ *
+ */
+static void
+omap4_get_revision(void)
+{
+ uint32_t id_code;
+ uint32_t revision;
+ uint32_t hawkeye;
+ bus_space_handle_t bsh;
+
+ /* The chip revsion is read from the device identification registers and
+ * the JTAG (?) tap registers, which are located in address 0x4A00_2200 to
+ * 0x4A00_2218. This is part of the L4_CORE memory range and should have
+ * been mapped in by the machdep.c code.
+ *
+ * STD_FUSE_DIE_ID_0 0x4A00 2200
+ * ID_CODE 0x4A00 2204 (this is the only one we need)
+ * STD_FUSE_DIE_ID_1 0x4A00 2208
+ * STD_FUSE_DIE_ID_2 0x4A00 220C
+ * STD_FUSE_DIE_ID_3 0x4A00 2210
+ * STD_FUSE_PROD_ID_0 0x4A00 2214
+ * STD_FUSE_PROD_ID_1 0x4A00 2218
+ */
+ /* FIXME Should we map somewhere else? */
+ bus_space_map(fdtbus_bs_tag,OMAP44XX_L4_CORE_HWBASE, 0x4000, 0, &bsh);
+ id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP4_ID_CODE);
+ bus_space_unmap(fdtbus_bs_tag, bsh, 0x4000);
+
+ hawkeye = ((id_code >> 12) & 0xffff);
+ revision = ((id_code >> 28) & 0xf);
+
+ /* Apparently according to the linux code there were some ES2.0 samples that
+ * have the wrong id code and report themselves as ES1.0 silicon. So used
+ * the ARM cpuid to get the correct revision.
+ */
+ if (revision == 0) {
+ id_code = cpufunc_id();
+ revision = (id_code & 0xf) - 1;
+ }
+
+ switch (hawkeye) {
+ case 0xB852:
+ switch (revision) {
+ case 0:
+ chip_revision = OMAP4430_REV_ES1_0;
+ break;
+ case 1:
+ chip_revision = OMAP4430_REV_ES2_1;
+ break;
+ default:
+ chip_revision = OMAP4430_REV_UNKNOWN;
+ break;
+ }
+ break;
+
+ case 0xB95C:
+ switch (revision) {
+ case 3:
+ chip_revision = OMAP4430_REV_ES2_1;
+ break;
+ case 4:
+ chip_revision = OMAP4430_REV_ES2_2;
+ break;
+ case 6:
+ chip_revision = OMAP4430_REV_ES2_3;
+ break;
+ default:
+ chip_revision = OMAP4430_REV_UNKNOWN;
+ break;
+ }
+ break;
+
+ case 0xB94E:
+ switch (revision) {
+ case 0:
+ chip_revision = OMAP4460_REV_ES1_0;
+ break;
+ case 2:
+ chip_revision = OMAP4460_REV_ES1_1;
+ break;
+ default:
+ chip_revision = OMAP4460_REV_UNKNOWN;
+ break;
+ }
+ break;
+
+ case 0xB975:
+ switch (revision) {
+ case 0:
+ chip_revision = OMAP4470_REV_ES1_0;
+ break;
+ default:
+ chip_revision = OMAP4470_REV_UNKNOWN;
+ break;
+ }
+ break;
+
+ default:
+ /* Default to the latest revision if we can't determine type */
+ chip_revision = OMAP_UNKNOWN_DEV;
+ break;
+ }
+ if (chip_revision != OMAP_UNKNOWN_DEV) {
+ printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n",
+ OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision),
+ OMAP_REV_MINOR(chip_revision));
+ }
+ else {
+ printf("Texas Instruments unknown OMAP chip: %04x, rev %d\n",
+ hawkeye, revision);
+ }
+}
+
+/**
+ * omap3_get_revision - determines omap3 revision
+ *
+ * Reads the registers to determine the revision of the chip we are currently
+ * running on. Stores the information in global variables.
+ *
+ * WARNING: This function currently only really works for OMAP3530 devices.
+ *
+ *
+ *
+ */
+static void
+omap3_get_revision(void)
+{
+ uint32_t id_code;
+ uint32_t revision;
+ uint32_t hawkeye;
+ bus_space_handle_t bsh;
+
+ /* The chip revsion is read from the device identification registers and
+ * the JTAG (?) tap registers, which are located in address 0x4A00_2200 to
+ * 0x4A00_2218. This is part of the L4_CORE memory range and should have
+ * been mapped in by the machdep.c code.
+ *
+ * CONTROL_IDCODE 0x4830 A204 (this is the only one we need)
+ *
+ *
+ */
+ bus_space_map(fdtbus_bs_tag, OMAP35XX_L4_WAKEUP_HWBASE, 0x10000, 0, &bsh);
+ id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP3_ID_CODE);
+ bus_space_unmap(fdtbus_bs_tag, bsh, 0x10000);
+
+ hawkeye = ((id_code >> 12) & 0xffff);
+ revision = ((id_code >> 28) & 0xf);
+
+ switch (hawkeye) {
+ case 0xB6D6:
+ chip_revision = OMAP3350_REV_ES1_0;
+ break;
+ case 0xB7AE:
+ if (revision == 1)
+ chip_revision = OMAP3530_REV_ES2_0;
+ else if (revision == 2)
+ chip_revision = OMAP3530_REV_ES2_1;
+ else if (revision == 3)
+ chip_revision = OMAP3530_REV_ES3_0;
+ else if (revision == 4)
+ chip_revision = OMAP3530_REV_ES3_1;
+ else if (revision == 7)
+ chip_revision = OMAP3530_REV_ES3_1_2;
+ break;
+ default:
+ /* Default to the latest revision if we can't determine type */
+ chip_revision = OMAP3530_REV_ES3_1_2;
+ break;
+ }
+ printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n",
+ OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision),
+ OMAP_REV_MINOR(chip_revision));
+}
+
+static void
+am335x_get_revision(void)
+{
+ uint32_t dev_feature;
+ uint8_t cpu_last_char;
+ bus_space_handle_t bsh;
+
+ bus_space_map(fdtbus_bs_tag, AM335X_CONTROL_BASE, AM335X_CONTROL_SIZE, 0, &bsh);
+ chip_revision = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEVICE_ID);
+ dev_feature = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEV_FEATURE);
+ bus_space_unmap(fdtbus_bs_tag, bsh, AM335X_CONTROL_SIZE);
+
+ switch (dev_feature) {
+ case 0x00FF0382:
+ cpu_last_char='2';
+ break;
+ case 0x20FF0382:
+ cpu_last_char='4';
+ break;
+ case 0x00FF0383:
+ cpu_last_char='6';
+ break;
+ case 0x00FE0383:
+ cpu_last_char='7';
+ break;
+ case 0x20FF0383:
+ cpu_last_char='8';
+ break;
+ case 0x20FE0383:
+ cpu_last_char='9';
+ break;
+ default:
+ cpu_last_char='x';
+ }
+
+ printf("Texas Instruments AM335%c Processor, Revision ES1.%u\n",
+ cpu_last_char, AM335X_DEVREV(chip_revision));
+}
+
+/**
+ * ti_cpu_ident - attempts to identify the chip we are running on
+ * @dummy: ignored
+ *
+ * This function is called before any of the driver are initialised, however
+ * the basic virt to phys maps have been setup in machdep.c so we can still
+ * access the required registers, we just have to use direct register reads
+ * and writes rather than going through the bus stuff.
+ *
+ *
+ */
+static void
+ti_cpu_ident(void *dummy)
+{
+ switch(ti_chip()) {
+ case CHIP_OMAP_3:
+ omap3_get_revision();
+ break;
+ case CHIP_OMAP_4:
+ omap4_get_revision();
+ break;
+ case CHIP_AM335X:
+ am335x_get_revision();
+ break;
+ default:
+ panic("Unknown chip type, fixme!\n");
+ }
+}
+
+SYSINIT(ti_cpu_ident, SI_SUB_CPU, SI_ORDER_SECOND, ti_cpu_ident, NULL);
Property changes on: trunk/sys/arm/ti/ti_cpuid.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_cpuid.h
===================================================================
--- trunk/sys/arm/ti/ti_cpuid.h (rev 0)
+++ trunk/sys/arm/ti/ti_cpuid.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,90 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_cpuid.h 245137 2013-01-07 23:30:53Z gonzo $
+ */
+
+#ifndef _TI_CPUID_H_
+#define _TI_CPUID_H_
+
+#define OMAP_MAKEREV(d, a, b, c) \
+ (uint32_t)(((d) << 16) | (((a) & 0xf) << 8) | (((b) & 0xf) << 4) | ((c) & 0xf))
+
+#define OMAP_REV_DEVICE(x) (((x) >> 16) & 0xffff)
+#define OMAP_REV_MAJOR(x) (((x) >> 8) & 0xf)
+#define OMAP_REV_MINOR(x) (((x) >> 4) & 0xf)
+#define OMAP_REV_MINOR_MINOR(x) (((x) >> 0) & 0xf)
+
+#define OMAP3350_DEV 0x3530
+#define OMAP3350_REV_ES1_0 OMAP_MAKEREV(OMAP3350_DEV, 1, 0, 0)
+#define OMAP3530_REV_ES2_0 OMAP_MAKEREV(OMAP3350_DEV, 2, 0, 0)
+#define OMAP3530_REV_ES2_1 OMAP_MAKEREV(OMAP3350_DEV, 2, 1, 0)
+#define OMAP3530_REV_ES3_0 OMAP_MAKEREV(OMAP3350_DEV, 3, 0, 0)
+#define OMAP3530_REV_ES3_1 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 0)
+#define OMAP3530_REV_ES3_1_2 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 2)
+
+#define OMAP4430_DEV 0x4430
+#define OMAP4430_REV_ES1_0 OMAP_MAKEREV(OMAP4430_DEV, 1, 0, 0)
+#define OMAP4430_REV_ES2_0 OMAP_MAKEREV(OMAP4430_DEV, 2, 0, 0)
+#define OMAP4430_REV_ES2_1 OMAP_MAKEREV(OMAP4430_DEV, 2, 1, 0)
+#define OMAP4430_REV_ES2_2 OMAP_MAKEREV(OMAP4430_DEV, 2, 2, 0)
+#define OMAP4430_REV_ES2_3 OMAP_MAKEREV(OMAP4430_DEV, 2, 3, 0)
+#define OMAP4430_REV_UNKNOWN OMAP_MAKEREV(OMAP4430_DEV, 9, 9, 9)
+
+#define OMAP4460_DEV 0x4460
+#define OMAP4460_REV_ES1_0 OMAP_MAKEREV(OMAP4460_DEV, 1, 0, 0)
+#define OMAP4460_REV_ES1_1 OMAP_MAKEREV(OMAP4460_DEV, 1, 1, 0)
+#define OMAP4460_REV_UNKNOWN OMAP_MAKEREV(OMAP4460_DEV, 9, 9, 9)
+
+#define OMAP4470_DEV 0x4470
+#define OMAP4470_REV_ES1_0 OMAP_MAKEREV(OMAP4470_DEV, 1, 0, 0)
+#define OMAP4470_REV_UNKNOWN OMAP_MAKEREV(OMAP4470_DEV, 9, 9, 9)
+
+#define OMAP_UNKNOWN_DEV OMAP_MAKEREV(0x9999, 9, 9, 9)
+
+#define AM335X_DEVREV(x) ((x) >> 28)
+
+#define CHIP_OMAP_3 0
+#define CHIP_OMAP_4 1
+#define CHIP_AM335X 2
+
+static __inline int ti_chip(void)
+{
+#if defined(SOC_OMAP4)
+ return CHIP_OMAP_4;
+#elif defined(SOC_OMAP3)
+ return CHIP_OMAP_3;
+#elif defined(SOC_TI_AM335X)
+ return CHIP_AM335X;
+#else
+# error Chip type not defined, ensure SOC_xxxx is defined
+#endif
+}
+
+uint32_t ti_revision(void);
+
+#endif /* _TI_CPUID_H_ */
Property changes on: trunk/sys/arm/ti/ti_cpuid.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_edma3.c
===================================================================
--- trunk/sys/arm/ti/ti_edma3.c (rev 0)
+++ trunk/sys/arm/ti/ti_edma3.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,429 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of authors nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_edma3.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/endian.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <sys/sockio.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_scm.h>
+#include <arm/ti/ti_prcm.h>
+
+#include <arm/ti/ti_edma3.h>
+
+#define TI_EDMA3_NUM_TCS 3
+#define TI_EDMA3_NUM_IRQS 3
+#define TI_EDMA3_NUM_DMA_CHS 64
+#define TI_EDMA3_NUM_QDMA_CHS 8
+
+#define TI_EDMA3CC_PID 0x000
+#define TI_EDMA3CC_DCHMAP(p) (0x100 + ((p)*4))
+#define TI_EDMA3CC_DMAQNUM(n) (0x240 + ((n)*4))
+#define TI_EDMA3CC_QDMAQNUM 0x260
+#define TI_EDMA3CC_EMCR 0x308
+#define TI_EDMA3CC_EMCRH 0x30C
+#define TI_EDMA3CC_QEMCR 0x314
+#define TI_EDMA3CC_CCERR 0x318
+#define TI_EDMA3CC_CCERRCLR 0x31C
+#define TI_EDMA3CC_DRAE(p) (0x340 + ((p)*8))
+#define TI_EDMA3CC_DRAEH(p) (0x344 + ((p)*8))
+#define TI_EDMA3CC_QRAE(p) (0x380 + ((p)*4))
+#define TI_EDMA3CC_S_ESR(p) (0x2010 + ((p)*0x200))
+#define TI_EDMA3CC_S_ESRH(p) (0x2014 + ((p)*0x200))
+#define TI_EDMA3CC_S_SECR(p) (0x2040 + ((p)*0x200))
+#define TI_EDMA3CC_S_SECRH(p) (0x2044 + ((p)*0x200))
+#define TI_EDMA3CC_S_EESR(p) (0x2030 + ((p)*0x200))
+#define TI_EDMA3CC_S_EESRH(p) (0x2034 + ((p)*0x200))
+#define TI_EDMA3CC_S_IESR(p) (0x2060 + ((p)*0x200))
+#define TI_EDMA3CC_S_IESRH(p) (0x2064 + ((p)*0x200))
+#define TI_EDMA3CC_S_IPR(p) (0x2068 + ((p)*0x200))
+#define TI_EDMA3CC_S_IPRH(p) (0x206C + ((p)*0x200))
+#define TI_EDMA3CC_S_QEESR(p) (0x208C + ((p)*0x200))
+
+#define TI_EDMA3CC_PARAM_OFFSET 0x4000
+#define TI_EDMA3CC_OPT(p) (TI_EDMA3CC_PARAM_OFFSET + 0x0 + ((p)*0x20))
+
+#define TI_EDMA3CC_DMAQNUM_SET(c,q) ((0x7 & (q)) << (((c) % 8) * 4))
+#define TI_EDMA3CC_DMAQNUM_CLR(c) (~(0x7 << (((c) % 8) * 4)))
+#define TI_EDMA3CC_QDMAQNUM_SET(c,q) ((0x7 & (q)) << ((c) * 4))
+#define TI_EDMA3CC_QDMAQNUM_CLR(c) (~(0x7 << ((c) * 4)))
+
+#define TI_EDMA3CC_OPT_TCC_CLR (~(0x3F000))
+#define TI_EDMA3CC_OPT_TCC_SET(p) (((0x3F000 >> 12) & (p)) << 12)
+
+struct ti_edma3_softc {
+ device_t sc_dev;
+ struct resource * mem_res[TI_EDMA3_NUM_TCS+1];
+ struct resource * irq_res[TI_EDMA3_NUM_IRQS];
+ void *ih_cookie[TI_EDMA3_NUM_IRQS];
+};
+
+static struct ti_edma3_softc *ti_edma3_sc = NULL;
+
+static struct resource_spec ti_edma3_mem_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+static struct resource_spec ti_edma3_irq_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+/* Read/Write macros */
+#define ti_edma3_cc_rd_4(reg) bus_read_4(ti_edma3_sc->mem_res[0], reg)
+#define ti_edma3_cc_wr_4(reg, val) bus_write_4(ti_edma3_sc->mem_res[0], reg, val)
+#define ti_edma3_tc_rd_4(c, reg) bus_read_4(ti_edma3_sc->mem_res[c+1], reg)
+#define ti_edma3_tc_wr_4(c, reg, val) bus_write_4(ti_edma3_sc->mem_res[c+1], reg, val)
+
+static void ti_edma3_intr_comp(void *arg);
+static void ti_edma3_intr_mperr(void *arg);
+static void ti_edma3_intr_err(void *arg);
+
+static struct {
+ driver_intr_t *handler;
+ char * description;
+} ti_edma3_intrs[TI_EDMA3_NUM_IRQS] = {
+ { ti_edma3_intr_comp, "EDMA Completion Interrupt" },
+ { ti_edma3_intr_mperr, "EDMA Memory Protection Error Interrupt" },
+ { ti_edma3_intr_err, "EDMA Error Interrupt" },
+};
+
+static int
+ti_edma3_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,edma3"))
+ return (ENXIO);
+
+ device_set_desc(dev, "TI EDMA Controller");
+ return (0);
+}
+
+static int
+ti_edma3_attach(device_t dev)
+{
+ struct ti_edma3_softc *sc = device_get_softc(dev);
+ uint32_t reg;
+ int err;
+ int i;
+
+ if (ti_edma3_sc)
+ return (ENXIO);
+
+ ti_edma3_sc = sc;
+ sc->sc_dev = dev;
+
+ /* Request the memory resources */
+ err = bus_alloc_resources(dev, ti_edma3_mem_spec, sc->mem_res);
+ if (err) {
+ device_printf(dev, "Error: could not allocate mem resources\n");
+ return (ENXIO);
+ }
+
+ /* Request the IRQ resources */
+ err = bus_alloc_resources(dev, ti_edma3_irq_spec, sc->irq_res);
+ if (err) {
+ device_printf(dev, "Error: could not allocate irq resources\n");
+ return (ENXIO);
+ }
+
+ /* Enable Channel Controller */
+ ti_prcm_clk_enable(EDMA_TPCC_CLK);
+
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_PID);
+
+ device_printf(dev, "EDMA revision %08x\n", reg);
+
+
+ /* Attach interrupt handlers */
+ for (i = 0; i < TI_EDMA3_NUM_IRQS; ++i) {
+ err = bus_setup_intr(dev, sc->irq_res[i], INTR_TYPE_MISC |
+ INTR_MPSAFE, NULL, *ti_edma3_intrs[i].handler,
+ sc, &sc->ih_cookie[i]);
+ if (err) {
+ device_printf(dev, "could not setup %s\n",
+ ti_edma3_intrs[i].description);
+ return (err);
+ }
+ }
+
+ return (0);
+}
+
+static device_method_t ti_edma3_methods[] = {
+ DEVMETHOD(device_probe, ti_edma3_probe),
+ DEVMETHOD(device_attach, ti_edma3_attach),
+ {0, 0},
+};
+
+static driver_t ti_edma3_driver = {
+ "ti_edma3",
+ ti_edma3_methods,
+ sizeof(struct ti_edma3_softc),
+};
+static devclass_t ti_edma3_devclass;
+
+DRIVER_MODULE(ti_edma3, simplebus, ti_edma3_driver, ti_edma3_devclass, 0, 0);
+MODULE_DEPEND(ti_edma3, ti_prcm, 1, 1, 1);
+
+static void
+ti_edma3_intr_comp(void *arg)
+{
+ printf("%s: unimplemented\n", __func__);
+}
+
+static void
+ti_edma3_intr_mperr(void *arg)
+{
+ printf("%s: unimplemented\n", __func__);
+}
+
+static void
+ti_edma3_intr_err(void *arg)
+{
+ printf("%s: unimplemented\n", __func__);
+}
+
+void
+ti_edma3_init(unsigned int eqn)
+{
+ uint32_t reg;
+ int i;
+
+ /* on AM335x Event queue 0 is always mapped to Transfer Controller 0,
+ * event queue 1 to TC2, etc. So we are asking PRCM to power on specific
+ * TC based on what event queue we need to initialize */
+ ti_prcm_clk_enable(EDMA_TPTC0_CLK + eqn);
+
+ /* Clear Event Missed Regs */
+ ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, 0xFFFFFFFF);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_EMCRH, 0xFFFFFFFF);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_QEMCR, 0xFFFFFFFF);
+
+ /* Clear Error Reg */
+ ti_edma3_cc_wr_4(TI_EDMA3CC_CCERRCLR, 0xFFFFFFFF);
+
+ /* Enable DMA channels 0-63 */
+ ti_edma3_cc_wr_4(TI_EDMA3CC_DRAE(0), 0xFFFFFFFF);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_DRAEH(0), 0xFFFFFFFF);
+
+ for (i = 0; i < 64; i++) {
+ ti_edma3_cc_wr_4(TI_EDMA3CC_DCHMAP(i), i<<5);
+ }
+
+ /* Initialize the DMA Queue Number Registers */
+ for (i = 0; i < TI_EDMA3_NUM_DMA_CHS; i++) {
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DMAQNUM(i>>3));
+ reg &= TI_EDMA3CC_DMAQNUM_CLR(i);
+ reg |= TI_EDMA3CC_DMAQNUM_SET(i, eqn);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_DMAQNUM(i>>3), reg);
+ }
+
+ /* Enable the QDMA Region access for all channels */
+ ti_edma3_cc_wr_4(TI_EDMA3CC_QRAE(0), (1 << TI_EDMA3_NUM_QDMA_CHS) - 1);
+
+ /*Initialize QDMA Queue Number Registers */
+ for (i = 0; i < TI_EDMA3_NUM_QDMA_CHS; i++) {
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QDMAQNUM);
+ reg &= TI_EDMA3CC_QDMAQNUM_CLR(i);
+ reg |= TI_EDMA3CC_QDMAQNUM_SET(i, eqn);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_QDMAQNUM, reg);
+ }
+}
+
+#ifdef notyet
+int
+ti_edma3_enable_event_intr(unsigned int ch)
+{
+ uint32_t reg;
+
+ if (ch >= TI_EDMA3_NUM_DMA_CHS)
+ return (EINVAL);
+
+ if (ch < 32) {
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_IESR(0), 1 << ch);
+ } else {
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_IESRH(0), 1 << (ch - 32));
+ }
+ return 0;
+}
+#endif
+
+int
+ti_edma3_request_dma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn)
+{
+ uint32_t reg;
+
+ if (ch >= TI_EDMA3_NUM_DMA_CHS)
+ return (EINVAL);
+
+ /* Enable the DMA channel in the DRAE/DRAEH registers */
+ if (ch < 32) {
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DRAE(0));
+ reg |= (0x01 << ch);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_DRAE(0), reg);
+ } else {
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DRAEH(0));
+ reg |= (0x01 << (ch - 32));
+ ti_edma3_cc_wr_4(TI_EDMA3CC_DRAEH(0), reg);
+ }
+
+ /* Associate DMA Channel to Event Queue */
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DMAQNUM(ch >> 3));
+ reg &= TI_EDMA3CC_DMAQNUM_CLR(ch);
+ reg |= TI_EDMA3CC_DMAQNUM_SET((ch), eqn);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_DMAQNUM(ch >> 3), reg);
+
+ /* Set TCC in corresponding PaRAM Entry */
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_OPT(ch));
+ reg &= TI_EDMA3CC_OPT_TCC_CLR;
+ reg |= TI_EDMA3CC_OPT_TCC_SET(ch);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_OPT(ch), reg);
+
+ return 0;
+}
+
+int
+ti_edma3_request_qdma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn)
+{
+ uint32_t reg;
+
+ if (ch >= TI_EDMA3_NUM_DMA_CHS)
+ return (EINVAL);
+
+ /* Enable the QDMA channel in the QRAE registers */
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QRAE(0));
+ reg |= (0x01 << ch);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_QRAE(0), reg);
+
+ /* Associate QDMA Channel to Event Queue */
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QDMAQNUM);
+ reg |= TI_EDMA3CC_QDMAQNUM_SET(ch, eqn);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_QDMAQNUM, reg);
+
+ /* Set TCC in corresponding PaRAM Entry */
+ reg = ti_edma3_cc_rd_4(TI_EDMA3CC_OPT(ch));
+ reg &= TI_EDMA3CC_OPT_TCC_CLR;
+ reg |= TI_EDMA3CC_OPT_TCC_SET(ch);
+ ti_edma3_cc_wr_4(TI_EDMA3CC_OPT(ch), reg);
+
+ return 0;
+}
+
+int
+ti_edma3_enable_transfer_manual(unsigned int ch)
+{
+ if (ch >= TI_EDMA3_NUM_DMA_CHS)
+ return (EINVAL);
+
+ /* set corresponding bit in ESR/ESRH to set a event */
+ if (ch < 32) {
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_ESR(0), 1 << ch);
+ } else {
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_ESRH(0), 1 << (ch - 32));
+ }
+
+ return 0;
+}
+
+int
+ti_edma3_enable_transfer_qdma(unsigned int ch)
+{
+ if (ch >= TI_EDMA3_NUM_QDMA_CHS)
+ return (EINVAL);
+
+ /* set corresponding bit in QEESR to enable QDMA event */
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_QEESR(0), (1 << ch));
+
+ return 0;
+}
+
+int
+ti_edma3_enable_transfer_event(unsigned int ch)
+{
+ if (ch >= TI_EDMA3_NUM_DMA_CHS)
+ return (EINVAL);
+
+ /* Clear SECR(H) & EMCR(H) to clean any previous NULL request
+ * and set corresponding bit in EESR to enable DMA event */
+ if(ch < 32) {
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_SECR(0), (1 << ch));
+ ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, (1 << ch));
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_EESR(0), (1 << ch));
+ } else {
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_SECRH(0), 1 << (ch - 32));
+ ti_edma3_cc_wr_4(TI_EDMA3CC_EMCRH, 1 << (ch - 32));
+ ti_edma3_cc_wr_4(TI_EDMA3CC_S_EESRH(0), 1 << (ch - 32));
+ }
+
+ return 0;
+}
+
+void
+ti_edma3_param_write(unsigned int ch, struct ti_edma3cc_param_set *prs)
+{
+ bus_write_region_4(ti_edma3_sc->mem_res[0], TI_EDMA3CC_OPT(ch),
+ (uint32_t *) prs, 8);
+}
+
+void
+ti_edma3_param_read(unsigned int ch, struct ti_edma3cc_param_set *prs)
+{
+ bus_read_region_4(ti_edma3_sc->mem_res[0], TI_EDMA3CC_OPT(ch),
+ (uint32_t *) prs, 8);
+}
Property changes on: trunk/sys/arm/ti/ti_edma3.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_edma3.h
===================================================================
--- trunk/sys/arm/ti/ti_edma3.h (rev 0)
+++ trunk/sys/arm/ti/ti_edma3.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,82 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_edma3.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+#ifndef _TI_EDMA3_H_
+#define _TI_EDMA3_H_
+
+/* Direct Mapped EDMA3 Events */
+#define TI_EDMA3_EVENT_SDTXEVT1 2
+#define TI_EDMA3_EVENT_SDRXEVT1 3
+#define TI_EDMA3_EVENT_SDTXEVT0 24
+#define TI_EDMA3_EVENT_SDRXEVT0 25
+
+struct ti_edma3cc_param_set {
+ struct {
+ uint32_t sam:1; /* Source address mode */
+ uint32_t dam:1; /* Destination address mode */
+ uint32_t syncdim:1; /* Transfer synchronization dimension */
+ uint32_t static_set:1; /* Static Set */
+ uint32_t :4;
+ uint32_t fwid:3; /* FIFO Width */
+ uint32_t tccmode:1; /* Transfer complete code mode */
+ uint32_t tcc:6; /* Transfer complete code */
+ uint32_t :2;
+ uint32_t tcinten:1; /* Transfer complete interrupt enable */
+ uint32_t itcinten:1; /* Intermediate xfer completion intr. ena */
+ uint32_t tcchen:1; /* Transfer complete chaining enable */
+ uint32_t itcchen:1; /* Intermediate xfer completion chaining ena */
+ uint32_t privid:4; /* Privilege identification */
+ uint32_t :3;
+ uint32_t priv:1; /* Privilege level */
+ } opt;
+ uint32_t src; /* Channel Source Address */
+ uint16_t acnt; /* Count for 1st Dimension */
+ uint16_t bcnt; /* Count for 2nd Dimension */
+ uint32_t dst; /* Channel Destination Address */
+ int16_t srcbidx; /* Source B Index */
+ int16_t dstbidx; /* Destination B Index */
+ uint16_t link; /* Link Address */
+ uint16_t bcntrld; /* BCNT Reload */
+ int16_t srccidx; /* Source C Index */
+ int16_t dstcidx; /* Destination C Index */
+ uint16_t ccnt; /* Count for 3rd Dimension */
+ uint16_t reserved; /* Reserved */
+};
+
+void ti_edma3_init(unsigned int eqn);
+int ti_edma3_request_dma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn);
+int ti_edma3_request_qdma_ch(unsigned int ch, unsigned int tccn, unsigned int eqn);
+int ti_edma3_enable_transfer_manual(unsigned int ch);
+int ti_edma3_enable_transfer_qdma(unsigned int ch);
+int ti_edma3_enable_transfer_event(unsigned int ch);
+
+void ti_edma3_param_write(unsigned int ch, struct ti_edma3cc_param_set *prs);
+void ti_edma3_param_read(unsigned int ch, struct ti_edma3cc_param_set *prs);
+
+#endif /* _TI_EDMA3_H_ */
Property changes on: trunk/sys/arm/ti/ti_edma3.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_gpio.c
===================================================================
--- trunk/sys/arm/ti/ti_gpio.c (rev 0)
+++ trunk/sys/arm/ti/ti_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,897 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * Very simple GPIO (general purpose IO) driver module for TI OMAP SoC's.
+ *
+ * Currently this driver only does the basics, get a value on a pin & set a
+ * value on a pin. Hopefully over time I'll expand this to be a bit more generic
+ * and support interrupts and other various bits on the SoC can do ... in the
+ * meantime this is all you get.
+ *
+ * Beware the OMA datasheet(s) lists GPIO banks 1-6, whereas I've used 0-5 here
+ * in the code.
+ *
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_gpio.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <arm/ti/ti_scm.h>
+#include <arm/ti/ti_prcm.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "gpio_if.h"
+
+/* Register definitions */
+#define TI_GPIO_REVISION 0x0000
+#define TI_GPIO_SYSCONFIG 0x0010
+#if defined(SOC_OMAP3)
+#define TI_GPIO_SYSSTATUS 0x0014
+#define TI_GPIO_IRQSTATUS1 0x0018
+#define TI_GPIO_IRQENABLE1 0x001C
+#define TI_GPIO_WAKEUPENABLE 0x0020
+#define TI_GPIO_IRQSTATUS2 0x0028
+#define TI_GPIO_IRQENABLE2 0x002C
+#define TI_GPIO_CTRL 0x0030
+#define TI_GPIO_OE 0x0034
+#define TI_GPIO_DATAIN 0x0038
+#define TI_GPIO_DATAOUT 0x003C
+#define TI_GPIO_LEVELDETECT0 0x0040
+#define TI_GPIO_LEVELDETECT1 0x0044
+#define TI_GPIO_RISINGDETECT 0x0048
+#define TI_GPIO_FALLINGDETECT 0x004C
+#define TI_GPIO_DEBOUNCENABLE 0x0050
+#define TI_GPIO_DEBOUNCINGTIME 0x0054
+#define TI_GPIO_CLEARIRQENABLE1 0x0060
+#define TI_GPIO_SETIRQENABLE1 0x0064
+#define TI_GPIO_CLEARIRQENABLE2 0x0070
+#define TI_GPIO_SETIRQENABLE2 0x0074
+#define TI_GPIO_CLEARWKUENA 0x0080
+#define TI_GPIO_SETWKUENA 0x0084
+#define TI_GPIO_CLEARDATAOUT 0x0090
+#define TI_GPIO_SETDATAOUT 0x0094
+#elif defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
+#define TI_GPIO_IRQSTATUS_RAW_0 0x0024
+#define TI_GPIO_IRQSTATUS_RAW_1 0x0028
+#define TI_GPIO_IRQSTATUS_0 0x002C
+#define TI_GPIO_IRQSTATUS_1 0x0030
+#define TI_GPIO_IRQSTATUS_SET_0 0x0034
+#define TI_GPIO_IRQSTATUS_SET_1 0x0038
+#define TI_GPIO_IRQSTATUS_CLR_0 0x003C
+#define TI_GPIO_IRQSTATUS_CLR_1 0x0040
+#define TI_GPIO_IRQWAKEN_0 0x0044
+#define TI_GPIO_IRQWAKEN_1 0x0048
+#define TI_GPIO_SYSSTATUS 0x0114
+#define TI_GPIO_IRQSTATUS1 0x0118
+#define TI_GPIO_IRQENABLE1 0x011C
+#define TI_GPIO_WAKEUPENABLE 0x0120
+#define TI_GPIO_IRQSTATUS2 0x0128
+#define TI_GPIO_IRQENABLE2 0x012C
+#define TI_GPIO_CTRL 0x0130
+#define TI_GPIO_OE 0x0134
+#define TI_GPIO_DATAIN 0x0138
+#define TI_GPIO_DATAOUT 0x013C
+#define TI_GPIO_LEVELDETECT0 0x0140
+#define TI_GPIO_LEVELDETECT1 0x0144
+#define TI_GPIO_RISINGDETECT 0x0148
+#define TI_GPIO_FALLINGDETECT 0x014C
+#define TI_GPIO_DEBOUNCENABLE 0x0150
+#define TI_GPIO_DEBOUNCINGTIME 0x0154
+#define TI_GPIO_CLEARWKUPENA 0x0180
+#define TI_GPIO_SETWKUENA 0x0184
+#define TI_GPIO_CLEARDATAOUT 0x0190
+#define TI_GPIO_SETDATAOUT 0x0194
+#else
+#error "Unknown SoC"
+#endif
+
+/* Other SoC Specific definitions */
+#if defined(SOC_OMAP3)
+#define MAX_GPIO_BANKS 6
+#define FIRST_GPIO_BANK 1
+#define INTR_PER_BANK 1
+#define TI_GPIO_REV 0x00000025
+#elif defined(SOC_OMAP4)
+#define MAX_GPIO_BANKS 6
+#define FIRST_GPIO_BANK 1
+#define INTR_PER_BANK 1
+#define TI_GPIO_REV 0x50600801
+#elif defined(SOC_TI_AM335X)
+#define MAX_GPIO_BANKS 4
+#define FIRST_GPIO_BANK 0
+#define INTR_PER_BANK 2
+#define TI_GPIO_REV 0x50600801
+#endif
+#define PINS_PER_BANK 32
+#define MAX_GPIO_INTRS MAX_GPIO_BANKS * INTR_PER_BANK
+
+/**
+ * ti_gpio_mem_spec - Resource specification used when allocating resources
+ * ti_gpio_irq_spec - Resource specification used when allocating resources
+ *
+ * This driver module can have up to six independent memory regions, each
+ * region typically controls 32 GPIO pins.
+ *
+ * On OMAP3 and OMAP4 there is only one physical interrupt line per bank,
+ * but there are two set of registers which control the interrupt delivery
+ * to internal subsystems. The first set of registers control the
+ * interrupts delivery to the MPU and the second set control the
+ * interrupts delivery to the DSP.
+ *
+ * On AM335x there are two physical interrupt lines for each GPIO module.
+ * Each interrupt line is controlled by a set of registers.
+ */
+static struct resource_spec ti_gpio_mem_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_OPTIONAL },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_OPTIONAL },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE | RF_OPTIONAL },
+#if !defined(SOC_TI_AM335X)
+ { SYS_RES_MEMORY, 4, RF_ACTIVE | RF_OPTIONAL },
+ { SYS_RES_MEMORY, 5, RF_ACTIVE | RF_OPTIONAL },
+#endif
+ { -1, 0, 0 }
+};
+static struct resource_spec ti_gpio_irq_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE | RF_OPTIONAL },
+ { SYS_RES_IRQ, 2, RF_ACTIVE | RF_OPTIONAL },
+ { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL },
+ { SYS_RES_IRQ, 4, RF_ACTIVE | RF_OPTIONAL },
+ { SYS_RES_IRQ, 5, RF_ACTIVE | RF_OPTIONAL },
+#if defined(SOC_TI_AM335X)
+ { SYS_RES_IRQ, 6, RF_ACTIVE | RF_OPTIONAL },
+ { SYS_RES_IRQ, 7, RF_ACTIVE | RF_OPTIONAL },
+#endif
+ { -1, 0, 0 }
+};
+
+/**
+ * Structure that stores the driver context.
+ *
+ * This structure is allocated during driver attach.
+ */
+struct ti_gpio_softc {
+ device_t sc_dev;
+
+ /*
+ * The memory resource(s) for the PRCM register set, when the device is
+ * created the caller can assign up to 6 memory regions depending on
+ * the SoC type.
+ */
+ struct resource *sc_mem_res[MAX_GPIO_BANKS];
+ struct resource *sc_irq_res[MAX_GPIO_INTRS];
+
+ /* The handle for the register IRQ handlers. */
+ void *sc_irq_hdl[MAX_GPIO_INTRS];
+
+ /*
+ * The following describes the H/W revision of each of the GPIO banks.
+ */
+ uint32_t sc_revision[MAX_GPIO_BANKS];
+
+ struct mtx sc_mtx;
+};
+
+/**
+ * Macros for driver mutex locking
+ */
+#define TI_GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define TI_GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define TI_GPIO_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ "ti_gpio", MTX_DEF)
+#define TI_GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx)
+#define TI_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
+#define TI_GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED)
+
+/**
+ * ti_gpio_read_4 - reads a 16-bit value from one of the PADCONFS registers
+ * @sc: GPIO device context
+ * @bank: The bank to read from
+ * @off: The offset of a register from the GPIO register address range
+ *
+ *
+ * RETURNS:
+ * 32-bit value read from the register.
+ */
+static inline uint32_t
+ti_gpio_read_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off)
+{
+ return (bus_read_4(sc->sc_mem_res[bank], off));
+}
+
+/**
+ * ti_gpio_write_4 - writes a 32-bit value to one of the PADCONFS registers
+ * @sc: GPIO device context
+ * @bank: The bank to write to
+ * @off: The offset of a register from the GPIO register address range
+ * @val: The value to write into the register
+ *
+ * RETURNS:
+ * nothing
+ */
+static inline void
+ti_gpio_write_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off,
+ uint32_t val)
+{
+ bus_write_4(sc->sc_mem_res[bank], off, val);
+}
+
+static inline void
+ti_gpio_intr_clr(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask)
+{
+
+ /* We clear both set of registers. */
+#if defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
+ ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_0, mask);
+ ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_1, mask);
+#else
+ ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE1, mask);
+ ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE2, mask);
+#endif
+}
+
+/**
+ * ti_gpio_pin_max - Returns the maximum number of GPIO pins
+ * @dev: gpio device handle
+ * @maxpin: pointer to a value that upon return will contain the maximum number
+ * of pins in the device.
+ *
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ * RETURNS:
+ * Returns 0 on success otherwise an error code
+ */
+static int
+ti_gpio_pin_max(device_t dev, int *maxpin)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ unsigned int i;
+ unsigned int banks = 0;
+
+ TI_GPIO_LOCK(sc);
+
+ /* Calculate how many valid banks we have and then multiply that by 32 to
+ * give use the total number of pins.
+ */
+ for (i = 0; i < MAX_GPIO_BANKS; i++) {
+ if (sc->sc_mem_res[i] != NULL)
+ banks++;
+ }
+
+ *maxpin = (banks * PINS_PER_BANK) - 1;
+
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_pin_getcaps - Gets the capabilties of a given pin
+ * @dev: gpio device handle
+ * @pin: the number of the pin
+ * @caps: pointer to a value that upon return will contain the capabilities
+ *
+ * Currently all pins have the same capability, notably:
+ * - GPIO_PIN_INPUT
+ * - GPIO_PIN_OUTPUT
+ * - GPIO_PIN_PULLUP
+ * - GPIO_PIN_PULLDOWN
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ * RETURNS:
+ * Returns 0 on success otherwise an error code
+ */
+static int
+ti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank = (pin / PINS_PER_BANK);
+
+ TI_GPIO_LOCK(sc);
+
+ /* Sanity check the pin number is valid */
+ if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
+ TI_GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |GPIO_PIN_PULLUP |
+ GPIO_PIN_PULLDOWN);
+
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_pin_getflags - Gets the current flags of a given pin
+ * @dev: gpio device handle
+ * @pin: the number of the pin
+ * @flags: upon return will contain the current flags of the pin
+ *
+ * Reads the current flags of a given pin, here we actually read the H/W
+ * registers to determine the flags, rather than storing the value in the
+ * setflags call.
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ * RETURNS:
+ * Returns 0 on success otherwise an error code
+ */
+static int
+ti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank = (pin / PINS_PER_BANK);
+
+ TI_GPIO_LOCK(sc);
+
+ /* Sanity check the pin number is valid */
+ if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
+ TI_GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* Get the current pin state */
+ ti_scm_padconf_get_gpioflags(pin, flags);
+
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_pin_getname - Gets the name of a given pin
+ * @dev: gpio device handle
+ * @pin: the number of the pin
+ * @name: buffer to put the name in
+ *
+ * The driver simply calls the pins gpio_n, where 'n' is obviously the number
+ * of the pin.
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ * RETURNS:
+ * Returns 0 on success otherwise an error code
+ */
+static int
+ti_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank = (pin / PINS_PER_BANK);
+
+ TI_GPIO_LOCK(sc);
+
+ /* Sanity check the pin number is valid */
+ if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
+ TI_GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* Set a very simple name */
+ snprintf(name, GPIOMAXNAME, "gpio_%u", pin);
+ name[GPIOMAXNAME - 1] = '\0';
+
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_pin_setflags - Sets the flags for a given pin
+ * @dev: gpio device handle
+ * @pin: the number of the pin
+ * @flags: the flags to set
+ *
+ * The flags of the pin correspond to things like input/output mode, pull-ups,
+ * pull-downs, etc. This driver doesn't support all flags, only the following:
+ * - GPIO_PIN_INPUT
+ * - GPIO_PIN_OUTPUT
+ * - GPIO_PIN_PULLUP
+ * - GPIO_PIN_PULLDOWN
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ * RETURNS:
+ * Returns 0 on success otherwise an error code
+ */
+static int
+ti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank = (pin / PINS_PER_BANK);
+ uint32_t mask = (1UL << (pin % PINS_PER_BANK));
+ uint32_t reg_val;
+
+ TI_GPIO_LOCK(sc);
+
+ /* Sanity check the pin number is valid */
+ if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
+ TI_GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* Set the GPIO mode and state */
+ if (ti_scm_padconf_set_gpioflags(pin, flags) != 0) {
+ TI_GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* If configuring as an output set the "output enable" bit */
+ reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
+ if (flags & GPIO_PIN_INPUT)
+ reg_val |= mask;
+ else
+ reg_val &= ~mask;
+ ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val);
+
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_pin_set - Sets the current level on a GPIO pin
+ * @dev: gpio device handle
+ * @pin: the number of the pin
+ * @value: non-zero value will drive the pin high, otherwise the pin is
+ * driven low.
+ *
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ * RETURNS:
+ * Returns 0 on success otherwise a error code
+ */
+static int
+ti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank = (pin / PINS_PER_BANK);
+ uint32_t mask = (1UL << (pin % PINS_PER_BANK));
+
+ TI_GPIO_LOCK(sc);
+
+ /* Sanity check the pin number is valid */
+ if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
+ TI_GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT
+ : TI_GPIO_SETDATAOUT, mask);
+
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_pin_get - Gets the current level on a GPIO pin
+ * @dev: gpio device handle
+ * @pin: the number of the pin
+ * @value: pointer to a value that upond return will contain the pin value
+ *
+ * The pin must be configured as an input pin beforehand, otherwise this
+ * function will fail.
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ * RETURNS:
+ * Returns 0 on success otherwise a error code
+ */
+static int
+ti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank = (pin / PINS_PER_BANK);
+ uint32_t mask = (1UL << (pin % PINS_PER_BANK));
+ uint32_t val = 0;
+
+ TI_GPIO_LOCK(sc);
+
+ /* Sanity check the pin number is valid */
+ if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
+ TI_GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* Sanity check the pin is not configured as an output */
+ val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
+
+ /* Read the value on the pin */
+ if (val & mask)
+ *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0;
+ else
+ *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0;
+
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_pin_toggle - Toggles a given GPIO pin
+ * @dev: gpio device handle
+ * @pin: the number of the pin
+ *
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ * RETURNS:
+ * Returns 0 on success otherwise a error code
+ */
+static int
+ti_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ uint32_t bank = (pin / PINS_PER_BANK);
+ uint32_t mask = (1UL << (pin % PINS_PER_BANK));
+ uint32_t val;
+
+ TI_GPIO_LOCK(sc);
+
+ /* Sanity check the pin number is valid */
+ if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) {
+ TI_GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* Toggle the pin */
+ val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT);
+ if (val & mask)
+ ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask);
+ else
+ ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask);
+
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_intr - ISR for all GPIO modules
+ * @arg: the soft context pointer
+ *
+ * Unsused
+ *
+ * LOCKING:
+ * Internally locks the context
+ *
+ */
+static void
+ti_gpio_intr(void *arg)
+{
+ struct ti_gpio_softc *sc = arg;
+
+ TI_GPIO_LOCK(sc);
+ /* TODO: something useful */
+ TI_GPIO_UNLOCK(sc);
+}
+
+/**
+ * ti_gpio_probe - probe function for the driver
+ * @dev: gpio device handle
+ *
+ * Simply sets the name of the driver
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * Always returns 0
+ */
+static int
+ti_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,gpio"))
+ return (ENXIO);
+
+ device_set_desc(dev, "TI General Purpose I/O (GPIO)");
+
+ return (0);
+}
+
+static int
+ti_gpio_attach_intr(device_t dev)
+{
+ int i;
+ struct ti_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < MAX_GPIO_INTRS; i++) {
+ if (sc->sc_irq_res[i] == NULL)
+ break;
+
+ /*
+ * Register our interrupt handler for each of the IRQ resources.
+ */
+ if (bus_setup_intr(dev, sc->sc_irq_res[i],
+ INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_gpio_intr, sc,
+ &sc->sc_irq_hdl[i]) != 0) {
+ device_printf(dev,
+ "WARNING: unable to register interrupt handler\n");
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+static int
+ti_gpio_detach_intr(device_t dev)
+{
+ int i;
+ struct ti_gpio_softc *sc;
+
+ /* Teardown our interrupt handlers. */
+ sc = device_get_softc(dev);
+ for (i = 0; i < MAX_GPIO_INTRS; i++) {
+ if (sc->sc_irq_res[i] == NULL)
+ break;
+
+ if (sc->sc_irq_hdl[i]) {
+ bus_teardown_intr(dev, sc->sc_irq_res[i],
+ sc->sc_irq_hdl[i]);
+ }
+ }
+
+ return (0);
+}
+
+static int
+ti_gpio_bank_init(device_t dev, int bank)
+{
+ int pin;
+ struct ti_gpio_softc *sc;
+ uint32_t flags, reg_oe;
+
+ sc = device_get_softc(dev);
+
+ /* Enable the interface and functional clocks for the module. */
+ ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + bank);
+
+ /*
+ * Read the revision number of the module. TI don't publish the
+ * actual revision numbers, so instead the values have been
+ * determined by experimentation.
+ */
+ sc->sc_revision[bank] = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION);
+
+ /* Check the revision. */
+ if (sc->sc_revision[bank] != TI_GPIO_REV) {
+ device_printf(dev, "Warning: could not determine the revision "
+ "of %u GPIO module (revision:0x%08x)\n",
+ bank, sc->sc_revision[bank]);
+ return (EINVAL);
+ }
+
+ /* Disable interrupts for all pins. */
+ ti_gpio_intr_clr(sc, bank, 0xffffffff);
+
+ /* Init OE register based on pads configuration. */
+ reg_oe = 0xffffffff;
+ for (pin = 0; pin < PINS_PER_BANK; pin++) {
+ ti_scm_padconf_get_gpioflags(PINS_PER_BANK * bank + pin,
+ &flags);
+ if (flags & GPIO_PIN_OUTPUT)
+ reg_oe &= ~(1UL << pin);
+ }
+ ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_oe);
+
+ return (0);
+}
+
+/**
+ * ti_gpio_attach - attach function for the driver
+ * @dev: gpio device handle
+ *
+ * Allocates and sets up the driver context for all GPIO banks. This function
+ * expects the memory ranges and IRQs to already be allocated to the driver.
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * Always returns 0
+ */
+static int
+ti_gpio_attach(device_t dev)
+{
+ struct ti_gpio_softc *sc;
+ unsigned int i;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ TI_GPIO_LOCK_INIT(sc);
+
+ /* There are up to 6 different GPIO register sets located in different
+ * memory areas on the chip. The memory range should have been set for
+ * the driver when it was added as a child.
+ */
+ if (bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res) != 0) {
+ device_printf(dev, "Error: could not allocate mem resources\n");
+ return (ENXIO);
+ }
+
+ /* Request the IRQ resources */
+ if (bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res) != 0) {
+ bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
+ device_printf(dev, "Error: could not allocate irq resources\n");
+ return (ENXIO);
+ }
+
+ /* Setup the IRQ resources */
+ if (ti_gpio_attach_intr(dev) != 0) {
+ ti_gpio_detach_intr(dev);
+ bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
+ bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
+ return (ENXIO);
+ }
+
+ /* We need to go through each block and ensure the clocks are running and
+ * the module is enabled. It might be better to do this only when the
+ * pins are configured which would result in less power used if the GPIO
+ * pins weren't used ...
+ */
+ for (i = 0; i < MAX_GPIO_BANKS; i++) {
+ if (sc->sc_mem_res[i] != NULL) {
+ /* Initialize the GPIO module. */
+ err = ti_gpio_bank_init(dev, i);
+ if (err != 0) {
+ ti_gpio_detach_intr(dev);
+ bus_release_resources(dev, ti_gpio_irq_spec,
+ sc->sc_irq_res);
+ bus_release_resources(dev, ti_gpio_mem_spec,
+ sc->sc_mem_res);
+ return (err);
+ }
+ }
+ }
+
+ /* Finish of the probe call */
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+/**
+ * ti_gpio_detach - detach function for the driver
+ * @dev: scm device handle
+ *
+ * Allocates and sets up the driver context, this simply entails creating a
+ * bus mappings for the SCM register set.
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * Always returns 0
+ */
+static int
+ti_gpio_detach(device_t dev)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ unsigned int i;
+
+ KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
+
+ /* Disable all interrupts */
+ for (i = 0; i < MAX_GPIO_BANKS; i++) {
+ if (sc->sc_mem_res[i] != NULL)
+ ti_gpio_intr_clr(sc, i, 0xffffffff);
+ }
+
+ bus_generic_detach(dev);
+
+ /* Release the memory and IRQ resources. */
+ ti_gpio_detach_intr(dev);
+ bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
+ bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
+
+ TI_GPIO_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static phandle_t
+ti_gpio_get_node(device_t bus, device_t dev)
+{
+
+ /* We only have one child, the GPIO bus, which needs our own node. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t ti_gpio_methods[] = {
+ DEVMETHOD(device_probe, ti_gpio_probe),
+ DEVMETHOD(device_attach, ti_gpio_attach),
+ DEVMETHOD(device_detach, ti_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, ti_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, ti_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, ti_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, ti_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, ti_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node),
+
+ {0, 0},
+};
+
+static driver_t ti_gpio_driver = {
+ "gpio",
+ ti_gpio_methods,
+ sizeof(struct ti_gpio_softc),
+};
+static devclass_t ti_gpio_devclass;
+
+DRIVER_MODULE(ti_gpio, simplebus, ti_gpio_driver, ti_gpio_devclass, 0, 0);
Property changes on: trunk/sys/arm/ti/ti_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_i2c.c
===================================================================
--- trunk/sys/arm/ti/ti_i2c.c (rev 0)
+++ trunk/sys/arm/ti/ti_i2c.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,982 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Ben Gray <ben.r.gray at gmail.com>.
+ * Copyright (c) 2014 Luiz Otavio O Souza <loos at freebsd.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * Driver for the I2C module on the TI SoC.
+ *
+ * This driver is heavily based on the TWI driver for the AT91 (at91_twi.c).
+ *
+ * CAUTION: The I2Ci registers are limited to 16 bit and 8 bit data accesses,
+ * 32 bit data access is not allowed and can corrupt register content.
+ *
+ * This driver currently doesn't use DMA for the transfer, although I hope to
+ * incorporate that sometime in the future. The idea being that for transaction
+ * larger than a certain size the DMA engine is used, for anything less the
+ * normal interrupt/fifo driven option is used.
+ *
+ *
+ * WARNING: This driver uses mtx_sleep and interrupts to perform transactions,
+ * which means you can't do a transaction during startup before the interrupts
+ * have been enabled. Hint - the freebsd function config_intrhook_establish().
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_i2c.c 276278 2014-12-27 02:37:52Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_cpuid.h>
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_i2c.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include "iicbus_if.h"
+
+/**
+ * I2C device driver context, a pointer to this is stored in the device
+ * driver structure.
+ */
+struct ti_i2c_softc
+{
+ device_t sc_dev;
+ uint32_t device_id;
+ struct resource* sc_irq_res;
+ struct resource* sc_mem_res;
+ device_t sc_iicbus;
+
+ void* sc_irq_h;
+
+ struct mtx sc_mtx;
+
+ struct iic_msg* sc_buffer;
+ int sc_bus_inuse;
+ int sc_buffer_pos;
+ int sc_error;
+ int sc_fifo_trsh;
+
+ uint16_t sc_con_reg;
+ uint16_t sc_rev;
+};
+
+struct ti_i2c_clock_config
+{
+ u_int frequency; /* Bus frequency in Hz */
+ uint8_t psc; /* Fast/Standard mode prescale divider */
+ uint8_t scll; /* Fast/Standard mode SCL low time */
+ uint8_t sclh; /* Fast/Standard mode SCL high time */
+ uint8_t hsscll; /* High Speed mode SCL low time */
+ uint8_t hssclh; /* High Speed mode SCL high time */
+};
+
+#if defined(SOC_OMAP3)
+#error "Unsupported SoC"
+#endif
+
+#if defined(SOC_OMAP4)
+/*
+ * OMAP4 i2c bus clock is 96MHz / ((psc + 1) * (scll + 7 + sclh + 5)).
+ * The prescaler values for 100KHz and 400KHz modes come from the table in the
+ * OMAP4 TRM. The table doesn't list 1MHz; these values should give that speed.
+ */
+static struct ti_i2c_clock_config ti_omap4_i2c_clock_configs[] = {
+ { 100000, 23, 13, 15, 0, 0},
+ { 400000, 9, 5, 7, 0, 0},
+ { 1000000, 3, 5, 7, 0, 0},
+/* { 3200000, 1, 113, 115, 7, 10}, - HS mode */
+ { 0 /* Table terminator */ }
+};
+#endif
+
+#if defined(SOC_TI_AM335X)
+/*
+ * AM335x i2c bus clock is 48MHZ / ((psc + 1) * (scll + 7 + sclh + 5))
+ * In all cases we prescale the clock to 24MHz as recommended in the manual.
+ */
+static struct ti_i2c_clock_config ti_am335x_i2c_clock_configs[] = {
+ { 100000, 1, 111, 117, 0, 0},
+ { 400000, 1, 23, 25, 0, 0},
+ { 1000000, 1, 5, 7, 0, 0},
+ { 0 /* Table terminator */ }
+};
+#endif
+
+/**
+ * Locking macros used throughout the driver
+ */
+#define TI_I2C_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define TI_I2C_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define TI_I2C_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ "ti_i2c", MTX_DEF)
+#define TI_I2C_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx)
+#define TI_I2C_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
+#define TI_I2C_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED)
+
+#ifdef DEBUG
+#define ti_i2c_dbg(_sc, fmt, args...) \
+ device_printf((_sc)->sc_dev, fmt, ##args)
+#else
+#define ti_i2c_dbg(_sc, fmt, args...)
+#endif
+
+/**
+ * ti_i2c_read_2 - reads a 16-bit value from one of the I2C registers
+ * @sc: I2C device context
+ * @off: the byte offset within the register bank to read from.
+ *
+ *
+ * LOCKING:
+ * No locking required
+ *
+ * RETURNS:
+ * 16-bit value read from the register.
+ */
+static inline uint16_t
+ti_i2c_read_2(struct ti_i2c_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_2(sc->sc_mem_res, off));
+}
+
+/**
+ * ti_i2c_write_2 - writes a 16-bit value to one of the I2C registers
+ * @sc: I2C device context
+ * @off: the byte offset within the register bank to read from.
+ * @val: the value to write into the register
+ *
+ * LOCKING:
+ * No locking required
+ *
+ * RETURNS:
+ * 16-bit value read from the register.
+ */
+static inline void
+ti_i2c_write_2(struct ti_i2c_softc *sc, bus_size_t off, uint16_t val)
+{
+
+ bus_write_2(sc->sc_mem_res, off, val);
+}
+
+static int
+ti_i2c_transfer_intr(struct ti_i2c_softc* sc, uint16_t status)
+{
+ int amount, done, i;
+
+ done = 0;
+ amount = 0;
+ /* Check for the error conditions. */
+ if (status & I2C_STAT_NACK) {
+ /* No ACK from slave. */
+ ti_i2c_dbg(sc, "NACK\n");
+ ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_NACK);
+ sc->sc_error = ENXIO;
+ } else if (status & I2C_STAT_AL) {
+ /* Arbitration lost. */
+ ti_i2c_dbg(sc, "Arbitration lost\n");
+ ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_AL);
+ sc->sc_error = ENXIO;
+ }
+
+ /* Check if we have finished. */
+ if (status & I2C_STAT_ARDY) {
+ /* Register access ready - transaction complete basically. */
+ ti_i2c_dbg(sc, "ARDY transaction complete\n");
+ if (sc->sc_error != 0 && sc->sc_buffer->flags & IIC_M_NOSTOP) {
+ ti_i2c_write_2(sc, I2C_REG_CON,
+ sc->sc_con_reg | I2C_CON_STP);
+ }
+ ti_i2c_write_2(sc, I2C_REG_STATUS,
+ I2C_STAT_ARDY | I2C_STAT_RDR | I2C_STAT_RRDY |
+ I2C_STAT_XDR | I2C_STAT_XRDY);
+ return (1);
+ }
+
+ if (sc->sc_buffer->flags & IIC_M_RD) {
+ /* Read some data. */
+ if (status & I2C_STAT_RDR) {
+ /*
+ * Receive draining interrupt - last data received.
+ * The set FIFO threshold wont be reached to trigger
+ * RRDY.
+ */
+ ti_i2c_dbg(sc, "Receive draining interrupt\n");
+
+ /*
+ * Drain the FIFO. Read the pending data in the FIFO.
+ */
+ amount = sc->sc_buffer->len - sc->sc_buffer_pos;
+ } else if (status & I2C_STAT_RRDY) {
+ /*
+ * Receive data ready interrupt - FIFO has reached the
+ * set threshold.
+ */
+ ti_i2c_dbg(sc, "Receive data ready interrupt\n");
+
+ amount = min(sc->sc_fifo_trsh,
+ sc->sc_buffer->len - sc->sc_buffer_pos);
+ }
+
+ /* Read the bytes from the fifo. */
+ for (i = 0; i < amount; i++)
+ sc->sc_buffer->buf[sc->sc_buffer_pos++] =
+ (uint8_t)(ti_i2c_read_2(sc, I2C_REG_DATA) & 0xff);
+
+ if (status & I2C_STAT_RDR)
+ ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_RDR);
+ if (status & I2C_STAT_RRDY)
+ ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_RRDY);
+
+ } else {
+ /* Write some data. */
+ if (status & I2C_STAT_XDR) {
+ /*
+ * Transmit draining interrupt - FIFO level is below
+ * the set threshold and the amount of data still to
+ * be transferred wont reach the set FIFO threshold.
+ */
+ ti_i2c_dbg(sc, "Transmit draining interrupt\n");
+
+ /*
+ * Drain the TX data. Write the pending data in the
+ * FIFO.
+ */
+ amount = sc->sc_buffer->len - sc->sc_buffer_pos;
+ } else if (status & I2C_STAT_XRDY) {
+ /*
+ * Transmit data ready interrupt - the FIFO level
+ * is below the set threshold.
+ */
+ ti_i2c_dbg(sc, "Transmit data ready interrupt\n");
+
+ amount = min(sc->sc_fifo_trsh,
+ sc->sc_buffer->len - sc->sc_buffer_pos);
+ }
+
+ /* Write the bytes from the fifo. */
+ for (i = 0; i < amount; i++)
+ ti_i2c_write_2(sc, I2C_REG_DATA,
+ sc->sc_buffer->buf[sc->sc_buffer_pos++]);
+
+ if (status & I2C_STAT_XDR)
+ ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_XDR);
+ if (status & I2C_STAT_XRDY)
+ ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_XRDY);
+ }
+
+ return (done);
+}
+
+/**
+ * ti_i2c_intr - interrupt handler for the I2C module
+ * @dev: i2c device handle
+ *
+ *
+ *
+ * LOCKING:
+ * Called from timer context
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+static void
+ti_i2c_intr(void *arg)
+{
+ int done;
+ struct ti_i2c_softc *sc;
+ uint16_t events, status;
+
+ sc = (struct ti_i2c_softc *)arg;
+
+ TI_I2C_LOCK(sc);
+
+ status = ti_i2c_read_2(sc, I2C_REG_STATUS);
+ if (status == 0) {
+ TI_I2C_UNLOCK(sc);
+ return;
+ }
+
+ /* Save enabled interrupts. */
+ events = ti_i2c_read_2(sc, I2C_REG_IRQENABLE_SET);
+
+ /* We only care about enabled interrupts. */
+ status &= events;
+
+ done = 0;
+
+ if (sc->sc_buffer != NULL)
+ done = ti_i2c_transfer_intr(sc, status);
+ else {
+ ti_i2c_dbg(sc, "Transfer interrupt without buffer\n");
+ sc->sc_error = EINVAL;
+ done = 1;
+ }
+
+ if (done)
+ /* Wakeup the process that started the transaction. */
+ wakeup(sc);
+
+ TI_I2C_UNLOCK(sc);
+}
+
+/**
+ * ti_i2c_transfer - called to perform the transfer
+ * @dev: i2c device handle
+ * @msgs: the messages to send/receive
+ * @nmsgs: the number of messages in the msgs array
+ *
+ *
+ * LOCKING:
+ * Internally locked
+ *
+ * RETURNS:
+ * 0 on function succeeded
+ * EINVAL if invalid message is passed as an arg
+ */
+static int
+ti_i2c_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+ int err, i, repstart, timeout;
+ struct ti_i2c_softc *sc;
+ uint16_t reg;
+
+ sc = device_get_softc(dev);
+ TI_I2C_LOCK(sc);
+
+ /* If the controller is busy wait until it is available. */
+ while (sc->sc_bus_inuse == 1)
+ mtx_sleep(sc, &sc->sc_mtx, 0, "i2cbuswait", 0);
+
+ /* Now we have control over the I2C controller. */
+ sc->sc_bus_inuse = 1;
+
+ err = 0;
+ repstart = 0;
+ for (i = 0; i < nmsgs; i++) {
+
+ sc->sc_buffer = &msgs[i];
+ sc->sc_buffer_pos = 0;
+ sc->sc_error = 0;
+
+ /* Zero byte transfers aren't allowed. */
+ if (sc->sc_buffer == NULL || sc->sc_buffer->buf == NULL ||
+ sc->sc_buffer->len == 0) {
+ err = EINVAL;
+ break;
+ }
+
+ /* Check if the i2c bus is free. */
+ if (repstart == 0) {
+ /*
+ * On repeated start we send the START condition while
+ * the bus _is_ busy.
+ */
+ timeout = 0;
+ while (ti_i2c_read_2(sc, I2C_REG_STATUS_RAW) & I2C_STAT_BB) {
+ if (timeout++ > 100) {
+ err = EBUSY;
+ goto out;
+ }
+ DELAY(1000);
+ }
+ timeout = 0;
+ } else
+ repstart = 0;
+
+ if (sc->sc_buffer->flags & IIC_M_NOSTOP)
+ repstart = 1;
+
+ /* Set the slave address. */
+ ti_i2c_write_2(sc, I2C_REG_SA, msgs[i].slave >> 1);
+
+ /* Write the data length. */
+ ti_i2c_write_2(sc, I2C_REG_CNT, sc->sc_buffer->len);
+
+ /* Clear the RX and the TX FIFO. */
+ reg = ti_i2c_read_2(sc, I2C_REG_BUF);
+ reg |= I2C_BUF_RXFIFO_CLR | I2C_BUF_TXFIFO_CLR;
+ ti_i2c_write_2(sc, I2C_REG_BUF, reg);
+
+ reg = sc->sc_con_reg | I2C_CON_STT;
+ if (repstart == 0)
+ reg |= I2C_CON_STP;
+ if ((sc->sc_buffer->flags & IIC_M_RD) == 0)
+ reg |= I2C_CON_TRX;
+ ti_i2c_write_2(sc, I2C_REG_CON, reg);
+
+ /* Wait for an event. */
+ err = mtx_sleep(sc, &sc->sc_mtx, 0, "i2ciowait", hz);
+ if (err == 0)
+ err = sc->sc_error;
+
+ if (err)
+ break;
+ }
+
+out:
+ if (timeout == 0) {
+ while (ti_i2c_read_2(sc, I2C_REG_STATUS_RAW) & I2C_STAT_BB) {
+ if (timeout++ > 100)
+ break;
+ DELAY(1000);
+ }
+ }
+ /* Put the controller in master mode again. */
+ if ((ti_i2c_read_2(sc, I2C_REG_CON) & I2C_CON_MST) == 0)
+ ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg);
+
+ sc->sc_buffer = NULL;
+ sc->sc_bus_inuse = 0;
+
+ /* Wake up the processes that are waiting for the bus. */
+ wakeup(sc);
+
+ TI_I2C_UNLOCK(sc);
+
+ return (err);
+}
+
+/**
+ * ti_i2c_callback - as we only provide iicbus_transfer() interface
+ * we don't need to implement the serialization here.
+ * @dev: i2c device handle
+ *
+ *
+ *
+ * LOCKING:
+ * Called from timer context
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+static int
+ti_i2c_callback(device_t dev, int index, caddr_t data)
+{
+ int error = 0;
+
+ switch (index) {
+ case IIC_REQUEST_BUS:
+ break;
+
+ case IIC_RELEASE_BUS:
+ break;
+
+ default:
+ error = EINVAL;
+ }
+
+ return (error);
+}
+
+static int
+ti_i2c_reset(struct ti_i2c_softc *sc, u_char speed)
+{
+ int timeout;
+ struct ti_i2c_clock_config *clkcfg;
+ u_int busfreq;
+ uint16_t fifo_trsh, reg, scll, sclh;
+
+ switch (ti_chip()) {
+#ifdef SOC_OMAP4
+ case CHIP_OMAP_4:
+ clkcfg = ti_omap4_i2c_clock_configs;
+ break;
+#endif
+#ifdef SOC_TI_AM335X
+ case CHIP_AM335X:
+ clkcfg = ti_am335x_i2c_clock_configs;
+ break;
+#endif
+ default:
+ panic("Unknown Ti SoC, unable to reset the i2c");
+ }
+
+ /*
+ * If we haven't attached the bus yet, just init at the default slow
+ * speed. This lets us get the hardware initialized enough to attach
+ * the bus which is where the real speed configuration is handled. After
+ * the bus is attached, get the configured speed from it. Search the
+ * configuration table for the best speed we can do that doesn't exceed
+ * the requested speed.
+ */
+ if (sc->sc_iicbus == NULL)
+ busfreq = 100000;
+ else
+ busfreq = IICBUS_GET_FREQUENCY(sc->sc_iicbus, speed);
+ for (;;) {
+ if (clkcfg[1].frequency == 0 || clkcfg[1].frequency > busfreq)
+ break;
+ clkcfg++;
+ }
+
+ /*
+ * 23.1.4.3 - HS I2C Software Reset
+ * From OMAP4 TRM at page 4068.
+ *
+ * 1. Ensure that the module is disabled.
+ */
+ sc->sc_con_reg = 0;
+ ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg);
+
+ /* 2. Issue a softreset to the controller. */
+ bus_write_2(sc->sc_mem_res, I2C_REG_SYSC, I2C_REG_SYSC_SRST);
+
+ /*
+ * 3. Enable the module.
+ * The I2Ci.I2C_SYSS[0] RDONE bit is asserted only after the module
+ * is enabled by setting the I2Ci.I2C_CON[15] I2C_EN bit to 1.
+ */
+ ti_i2c_write_2(sc, I2C_REG_CON, I2C_CON_I2C_EN);
+
+ /* 4. Wait for the software reset to complete. */
+ timeout = 0;
+ while ((ti_i2c_read_2(sc, I2C_REG_SYSS) & I2C_SYSS_RDONE) == 0) {
+ if (timeout++ > 100)
+ return (EBUSY);
+ DELAY(100);
+ }
+
+ /*
+ * Disable the I2C controller once again, now that the reset has
+ * finished.
+ */
+ ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg);
+
+ /*
+ * The following sequence is taken from the OMAP4 TRM at page 4077.
+ *
+ * 1. Enable the functional and interface clocks (see Section
+ * 23.1.5.1.1.1.1). Done at ti_i2c_activate().
+ *
+ * 2. Program the prescaler to obtain an approximately 12MHz internal
+ * sampling clock (I2Ci_INTERNAL_CLK) by programming the
+ * corresponding value in the I2Ci.I2C_PSC[3:0] PSC field.
+ * This value depends on the frequency of the functional clock
+ * (I2Ci_FCLK). Because this frequency is 96MHz, the
+ * I2Ci.I2C_PSC[7:0] PSC field value is 0x7.
+ */
+ ti_i2c_write_2(sc, I2C_REG_PSC, clkcfg->psc);
+
+ /*
+ * 3. Program the I2Ci.I2C_SCLL[7:0] SCLL and I2Ci.I2C_SCLH[7:0] SCLH
+ * bit fields to obtain a bit rate of 100 Kbps, 400 Kbps or 1Mbps.
+ * These values depend on the internal sampling clock frequency
+ * (see Table 23-8).
+ */
+ scll = clkcfg->scll & I2C_SCLL_MASK;
+ sclh = clkcfg->sclh & I2C_SCLH_MASK;
+
+ /*
+ * 4. (Optional) Program the I2Ci.I2C_SCLL[15:8] HSSCLL and
+ * I2Ci.I2C_SCLH[15:8] HSSCLH fields to obtain a bit rate of
+ * 400K bps or 3.4M bps (for the second phase of HS mode). These
+ * values depend on the internal sampling clock frequency (see
+ * Table 23-8).
+ *
+ * 5. (Optional) If a bit rate of 3.4M bps is used and the bus line
+ * capacitance exceeds 45 pF, (see Section 18.4.8, PAD Functional
+ * Multiplexing and Configuration).
+ */
+ switch (ti_chip()) {
+#ifdef SOC_OMAP4
+ case CHIP_OMAP_4:
+ if ((clkcfg->hsscll + clkcfg->hssclh) > 0) {
+ scll |= clkcfg->hsscll << I2C_HSSCLL_SHIFT;
+ sclh |= clkcfg->hssclh << I2C_HSSCLH_SHIFT;
+ sc->sc_con_reg |= I2C_CON_OPMODE_HS;
+ }
+ break;
+#endif
+ }
+
+ /* Write the selected bit rate. */
+ ti_i2c_write_2(sc, I2C_REG_SCLL, scll);
+ ti_i2c_write_2(sc, I2C_REG_SCLH, sclh);
+
+ /*
+ * 6. Configure the Own Address of the I2C controller by storing it in
+ * the I2Ci.I2C_OA0 register. Up to four Own Addresses can be
+ * programmed in the I2Ci.I2C_OAi registers (where i = 0, 1, 2, 3)
+ * for each I2C controller.
+ *
+ * Note: For a 10-bit address, set the corresponding expand Own Address
+ * bit in the I2Ci.I2C_CON register.
+ *
+ * Driver currently always in single master mode so ignore this step.
+ */
+
+ /*
+ * 7. Set the TX threshold (in transmitter mode) and the RX threshold
+ * (in receiver mode) by setting the I2Ci.I2C_BUF[5:0]XTRSH field to
+ * (TX threshold - 1) and the I2Ci.I2C_BUF[13:8]RTRSH field to (RX
+ * threshold - 1), where the TX and RX thresholds are greater than
+ * or equal to 1.
+ *
+ * The threshold is set to 5 for now.
+ */
+ fifo_trsh = (sc->sc_fifo_trsh - 1) & I2C_BUF_TRSH_MASK;
+ reg = fifo_trsh | (fifo_trsh << I2C_BUF_RXTRSH_SHIFT);
+ ti_i2c_write_2(sc, I2C_REG_BUF, reg);
+
+ /*
+ * 8. Take the I2C controller out of reset by setting the
+ * I2Ci.I2C_CON[15] I2C_EN bit to 1.
+ *
+ * 23.1.5.1.1.1.2 - Initialize the I2C Controller
+ *
+ * To initialize the I2C controller, perform the following steps:
+ *
+ * 1. Configure the I2Ci.I2C_CON register:
+ * . For master or slave mode, set the I2Ci.I2C_CON[10] MST bit
+ * (0: slave, 1: master).
+ * . For transmitter or receiver mode, set the I2Ci.I2C_CON[9] TRX
+ * bit (0: receiver, 1: transmitter).
+ */
+
+ /* Enable the I2C controller in master mode. */
+ sc->sc_con_reg |= I2C_CON_I2C_EN | I2C_CON_MST;
+ ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg);
+
+ /*
+ * 2. If using an interrupt to transmit/receive data, set the
+ * corresponding bit in the I2Ci.I2C_IE register (the I2Ci.I2C_IE[4]
+ * XRDY_IE bit for the transmit interrupt, the I2Ci.I2C_IE[3] RRDY
+ * bit for the receive interrupt).
+ */
+
+ /* Set the interrupts we want to be notified. */
+ reg = I2C_IE_XDR | /* Transmit draining interrupt. */
+ I2C_IE_XRDY | /* Transmit Data Ready interrupt. */
+ I2C_IE_RDR | /* Receive draining interrupt. */
+ I2C_IE_RRDY | /* Receive Data Ready interrupt. */
+ I2C_IE_ARDY | /* Register Access Ready interrupt. */
+ I2C_IE_NACK | /* No Acknowledgment interrupt. */
+ I2C_IE_AL; /* Arbitration lost interrupt. */
+
+ /* Enable the interrupts. */
+ ti_i2c_write_2(sc, I2C_REG_IRQENABLE_SET, reg);
+
+ /*
+ * 3. If using DMA to receive/transmit data, set to 1 the corresponding
+ * bit in the I2Ci.I2C_BUF register (the I2Ci.I2C_BUF[15] RDMA_EN
+ * bit for the receive DMA channel, the I2Ci.I2C_BUF[7] XDMA_EN bit
+ * for the transmit DMA channel).
+ *
+ * Not using DMA for now, so ignore this.
+ */
+
+ return (0);
+}
+
+static int
+ti_i2c_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+ struct ti_i2c_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ TI_I2C_LOCK(sc);
+ err = ti_i2c_reset(sc, speed);
+ TI_I2C_UNLOCK(sc);
+ if (err)
+ return (err);
+
+ return (IIC_ENOADDR);
+}
+
+static int
+ti_i2c_activate(device_t dev)
+{
+ clk_ident_t clk;
+ int err;
+ struct ti_i2c_softc *sc;
+
+ sc = (struct ti_i2c_softc*)device_get_softc(dev);
+
+ /*
+ * 1. Enable the functional and interface clocks (see Section
+ * 23.1.5.1.1.1.1).
+ */
+ clk = I2C0_CLK + sc->device_id;
+ err = ti_prcm_clk_enable(clk);
+ if (err)
+ return (err);
+
+ return (ti_i2c_reset(sc, IIC_UNKNOWN));
+}
+
+/**
+ * ti_i2c_deactivate - deactivates the controller and releases resources
+ * @dev: i2c device handle
+ *
+ *
+ *
+ * LOCKING:
+ * Assumed called in an atomic context.
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+ti_i2c_deactivate(device_t dev)
+{
+ struct ti_i2c_softc *sc = device_get_softc(dev);
+ clk_ident_t clk;
+
+ /* Disable the controller - cancel all transactions. */
+ ti_i2c_write_2(sc, I2C_REG_IRQENABLE_CLR, 0xffff);
+ ti_i2c_write_2(sc, I2C_REG_STATUS, 0xffff);
+ ti_i2c_write_2(sc, I2C_REG_CON, 0);
+
+ /* Release the interrupt handler. */
+ if (sc->sc_irq_h != NULL) {
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_h);
+ sc->sc_irq_h = NULL;
+ }
+
+ bus_generic_detach(sc->sc_dev);
+
+ /* Unmap the I2C controller registers. */
+ if (sc->sc_mem_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ sc->sc_mem_res = NULL;
+ }
+
+ /* Release the IRQ resource. */
+ if (sc->sc_irq_res != NULL) {
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+
+ /* Finally disable the functional and interface clocks. */
+ clk = I2C0_CLK + sc->device_id;
+ ti_prcm_clk_disable(clk);
+}
+
+static int
+ti_i2c_sysctl_clk(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev;
+ int clk, psc, sclh, scll;
+ struct ti_i2c_softc *sc;
+
+ dev = (device_t)arg1;
+ sc = device_get_softc(dev);
+
+ TI_I2C_LOCK(sc);
+ /* Get the system prescaler value. */
+ psc = (int)ti_i2c_read_2(sc, I2C_REG_PSC) + 1;
+
+ /* Get the bitrate. */
+ scll = (int)ti_i2c_read_2(sc, I2C_REG_SCLL) & I2C_SCLL_MASK;
+ sclh = (int)ti_i2c_read_2(sc, I2C_REG_SCLH) & I2C_SCLH_MASK;
+
+ clk = I2C_CLK / psc / (scll + 7 + sclh + 5);
+ TI_I2C_UNLOCK(sc);
+
+ return (sysctl_handle_int(oidp, &clk, 0, req));
+}
+
+static int
+ti_i2c_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (!ofw_bus_is_compatible(dev, "ti,i2c"))
+ return (ENXIO);
+ device_set_desc(dev, "TI I2C Controller");
+
+ return (0);
+}
+
+static int
+ti_i2c_attach(device_t dev)
+{
+ int err, rid;
+ phandle_t node;
+ struct ti_i2c_softc *sc;
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid_list *tree;
+ uint16_t fifosz;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ /* Get the i2c device id from FDT. */
+ node = ofw_bus_get_node(dev);
+ if ((OF_getencprop(node, "i2c-device-id", &sc->device_id,
+ sizeof(sc->device_id))) <= 0) {
+ device_printf(dev, "missing i2c-device-id attribute in FDT\n");
+ return (ENXIO);
+ }
+
+ /* Get the memory resource for the register mapping. */
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ device_printf(dev, "Cannot map registers.\n");
+ return (ENXIO);
+ }
+
+ /* Allocate our IRQ resource. */
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->sc_irq_res == NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "Cannot allocate interrupt.\n");
+ return (ENXIO);
+ }
+
+ TI_I2C_LOCK_INIT(sc);
+
+ /* First of all, we _must_ activate the H/W. */
+ err = ti_i2c_activate(dev);
+ if (err) {
+ device_printf(dev, "ti_i2c_activate failed\n");
+ goto out;
+ }
+
+ /* Read the version number of the I2C module */
+ sc->sc_rev = ti_i2c_read_2(sc, I2C_REG_REVNB_HI) & 0xff;
+
+ /* Get the fifo size. */
+ fifosz = ti_i2c_read_2(sc, I2C_REG_BUFSTAT);
+ fifosz >>= I2C_BUFSTAT_FIFODEPTH_SHIFT;
+ fifosz &= I2C_BUFSTAT_FIFODEPTH_MASK;
+
+ device_printf(dev, "I2C revision %d.%d FIFO size: %d bytes\n",
+ sc->sc_rev >> 4, sc->sc_rev & 0xf, 8 << fifosz);
+
+ /* Set the FIFO threshold to 5 for now. */
+ sc->sc_fifo_trsh = 5;
+
+ ctx = device_get_sysctl_ctx(dev);
+ tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "i2c_clock",
+ CTLFLAG_RD | CTLTYPE_UINT | CTLFLAG_MPSAFE, dev, 0,
+ ti_i2c_sysctl_clk, "IU", "I2C bus clock");
+
+ /* Activate the interrupt. */
+ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, ti_i2c_intr, sc, &sc->sc_irq_h);
+ if (err)
+ goto out;
+
+ /* Attach the iicbus. */
+ if ((sc->sc_iicbus = device_add_child(dev, "iicbus", -1)) == NULL) {
+ device_printf(dev, "could not allocate iicbus instance\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ /* Probe and attach the iicbus */
+ bus_generic_attach(dev);
+
+out:
+ if (err) {
+ ti_i2c_deactivate(dev);
+ TI_I2C_LOCK_DESTROY(sc);
+ }
+
+ return (err);
+}
+
+static int
+ti_i2c_detach(device_t dev)
+{
+ struct ti_i2c_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ ti_i2c_deactivate(dev);
+ TI_I2C_LOCK_DESTROY(sc);
+ if (sc->sc_iicbus &&
+ (rv = device_delete_child(dev, sc->sc_iicbus)) != 0)
+ return (rv);
+
+ return (0);
+}
+
+static phandle_t
+ti_i2c_get_node(device_t bus, device_t dev)
+{
+
+ /* Share controller node with iibus device. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t ti_i2c_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_i2c_probe),
+ DEVMETHOD(device_attach, ti_i2c_attach),
+ DEVMETHOD(device_detach, ti_i2c_detach),
+
+ /* OFW methods */
+ DEVMETHOD(ofw_bus_get_node, ti_i2c_get_node),
+
+ /* iicbus interface */
+ DEVMETHOD(iicbus_callback, ti_i2c_callback),
+ DEVMETHOD(iicbus_reset, ti_i2c_iicbus_reset),
+ DEVMETHOD(iicbus_transfer, ti_i2c_transfer),
+
+ DEVMETHOD_END
+};
+
+static driver_t ti_i2c_driver = {
+ "iichb",
+ ti_i2c_methods,
+ sizeof(struct ti_i2c_softc),
+};
+
+static devclass_t ti_i2c_devclass;
+
+DRIVER_MODULE(ti_iic, simplebus, ti_i2c_driver, ti_i2c_devclass, 0, 0);
+DRIVER_MODULE(iicbus, ti_iic, iicbus_driver, iicbus_devclass, 0, 0);
+
+MODULE_DEPEND(ti_iic, ti_prcm, 1, 1, 1);
+MODULE_DEPEND(ti_iic, iicbus, 1, 1, 1);
Property changes on: trunk/sys/arm/ti/ti_i2c.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_i2c.h
===================================================================
--- trunk/sys/arm/ti/ti_i2c.h (rev 0)
+++ trunk/sys/arm/ti/ti_i2c.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,132 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_i2c.h 273735 2014-10-27 12:18:07Z loos $
+ */
+
+#ifndef _TI_I2C_H_
+#define _TI_I2C_H_
+
+/**
+ * Header file for the OMAP I2C driver.
+ *
+ * Simply contains register bit flags.
+ */
+
+/*
+ * OMAP4 I2C Registers, Summary 1
+ */
+#define I2C_REG_IE 0x84
+#define I2C_IE_XDR (1UL << 14) /* Transmit draining interrupt */
+#define I2C_IE_RDR (1UL << 13) /* Receive draining interrupt */
+#define I2C_IE_AAS (1UL << 9) /* Addressed as Slave interrupt */
+#define I2C_IE_BF (1UL << 8) /* Bus Free interrupt */
+#define I2C_IE_AERR (1UL << 7) /* Access Error interrupt */
+#define I2C_IE_STC (1UL << 6) /* Start Condition interrupt */
+#define I2C_IE_GC (1UL << 5) /* General Call interrupt */
+#define I2C_IE_XRDY (1UL << 4) /* Transmit Data Ready interrupt */
+#define I2C_IE_RRDY (1UL << 3) /* Receive Data Ready interrupt */
+#define I2C_IE_ARDY (1UL << 2) /* Register Access Ready interrupt */
+#define I2C_IE_NACK (1UL << 1) /* No Acknowledgment interrupt */
+#define I2C_IE_AL (1UL << 0) /* Arbitration Lost interrupt */
+#define I2C_REG_STAT 0x88
+#define I2C_STAT_XDR (1UL << 14)
+#define I2C_STAT_RDR (1UL << 13)
+#define I2C_STAT_BB (1UL << 12)
+#define I2C_STAT_ROVR (1UL << 11)
+#define I2C_STAT_XUDF (1UL << 10)
+#define I2C_STAT_AAS (1UL << 9)
+#define I2C_STAT_BF (1UL << 8)
+#define I2C_STAT_AERR (1UL << 7)
+#define I2C_STAT_STC (1UL << 6)
+#define I2C_STAT_GC (1UL << 5)
+#define I2C_STAT_XRDY (1UL << 4)
+#define I2C_STAT_RRDY (1UL << 3)
+#define I2C_STAT_ARDY (1UL << 2)
+#define I2C_STAT_NACK (1UL << 1)
+#define I2C_STAT_AL (1UL << 0)
+#define I2C_REG_SYSS 0x90
+#define I2C_SYSS_RDONE (1UL << 0)
+#define I2C_REG_BUF 0x94
+#define I2C_BUF_RXFIFO_CLR (1UL << 14)
+#define I2C_BUF_TXFIFO_CLR (1UL << 6)
+#define I2C_BUF_RXTRSH_SHIFT 8
+#define I2C_BUF_TRSH_MASK 0x3f
+#define I2C_REG_CNT 0x98
+#define I2C_REG_DATA 0x9c
+#define I2C_REG_CON 0xa4
+#define I2C_CON_I2C_EN (1UL << 15)
+#define I2C_CON_OPMODE_STD (0UL << 12)
+#define I2C_CON_OPMODE_HS (1UL << 12)
+#define I2C_CON_OPMODE_SCCB (2UL << 12)
+#define I2C_CON_OPMODE_MASK (3UL << 13)
+#define I2C_CON_I2C_STB (1UL << 11)
+#define I2C_CON_MST (1UL << 10)
+#define I2C_CON_TRX (1UL << 9)
+#define I2C_CON_XSA (1UL << 8)
+#define I2C_CON_XOA0 (1UL << 7)
+#define I2C_CON_XOA1 (1UL << 6)
+#define I2C_CON_XOA2 (1UL << 5)
+#define I2C_CON_XOA3 (1UL << 4)
+#define I2C_CON_STP (1UL << 1)
+#define I2C_CON_STT (1UL << 0)
+#define I2C_REG_OA0 0xa8
+#define I2C_REG_SA 0xac
+#define I2C_REG_PSC 0xb0
+#define I2C_PSC_MASK 0xff
+#define I2C_REG_SCLL 0xb4
+#define I2C_SCLL_MASK 0xff
+#define I2C_HSSCLL_SHIFT 8
+#define I2C_REG_SCLH 0xb8
+#define I2C_SCLH_MASK 0xff
+#define I2C_HSSCLH_SHIFT 8
+#define I2C_REG_SYSTEST 0xbc
+#define I2C_REG_BUFSTAT 0xc0
+#define I2C_BUFSTAT_FIFODEPTH_MASK 0x3
+#define I2C_BUFSTAT_FIFODEPTH_SHIFT 14
+#define I2C_REG_OA1 0xc4
+#define I2C_REG_OA2 0xc8
+#define I2C_REG_OA3 0xcc
+#define I2C_REG_ACTOA 0xd0
+#define I2C_REG_SBLOCK 0xd4
+
+/*
+ * OMAP4 I2C Registers, Summary 2
+ */
+#define I2C_REG_REVNB_LO 0x00
+#define I2C_REG_REVNB_HI 0x04
+#define I2C_REG_SYSC 0x10
+#define I2C_REG_SYSC_SRST (1UL << 1)
+#define I2C_REG_STATUS_RAW 0x24
+#define I2C_REG_STATUS 0x28
+#define I2C_REG_IRQENABLE_SET 0x2C
+#define I2C_REG_IRQENABLE_CLR 0x30
+
+#define I2C_CLK 96000000UL /* 96MHz */
+#define I2C_ICLK 12000000UL /* 12MHz */
+
+#endif /* _TI_I2C_H_ */
Property changes on: trunk/sys/arm/ti/ti_i2c.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_machdep.c
===================================================================
--- trunk/sys/arm/ti/ti_machdep.c (rev 0)
+++ trunk/sys/arm/ti/ti_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,129 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/at91/kb920x_machdep.c, rev 45
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_machdep.c 266084 2014-05-14 19:18:58Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <arm/ti/omap4/omap4_reg.h>
+
+void (*ti_cpu_reset)(void) = NULL;
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+}
+
+void
+initarm_gpio_init(void)
+{
+}
+
+void
+initarm_late_init(void)
+{
+}
+
+/*
+ * Construct static devmap entries to map out the most frequently used
+ * peripherals using 1mb section mappings.
+ */
+int
+initarm_devmap_init(void)
+{
+#if defined(SOC_OMAP4)
+ arm_devmap_add_entry(0x48000000, 0x01000000); /*16mb L4_PER devices */
+ arm_devmap_add_entry(0x4A000000, 0x01000000); /*16mb L4_CFG devices */
+#elif defined(SOC_TI_AM335X)
+ arm_devmap_add_entry(0x44C00000, 0x00400000); /* 4mb L4_WKUP devices*/
+ arm_devmap_add_entry(0x47400000, 0x00100000); /* 1mb USB */
+ arm_devmap_add_entry(0x47800000, 0x00100000); /* 1mb mmchs2 */
+ arm_devmap_add_entry(0x48000000, 0x01000000); /*16mb L4_PER devices */
+ arm_devmap_add_entry(0x49000000, 0x00100000); /* 1mb edma3 */
+ arm_devmap_add_entry(0x49800000, 0x00300000); /* 3mb edma3 */
+ arm_devmap_add_entry(0x4A000000, 0x01000000); /*16mb L4_FAST devices*/
+#else
+#error "Unknown SoC"
+#endif
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+void
+cpu_reset()
+{
+ if (ti_cpu_reset)
+ (*ti_cpu_reset)();
+ else
+ printf("no cpu_reset implementation\n");
+ printf("Reset failed!\n");
+ while (1);
+}
Property changes on: trunk/sys/arm/ti/ti_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_mbox.c
===================================================================
--- trunk/sys/arm/ti/ti_mbox.c (rev 0)
+++ trunk/sys/arm/ti/ti_mbox.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,267 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Rui Paulo <rpaulo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_mbox.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/ti/ti_mbox.h>
+#include <arm/ti/ti_prcm.h>
+
+#include "mbox_if.h"
+
+#define DEBUG
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) do { \
+ printf("%s: ", __func__); \
+ printf(fmt, __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+static device_probe_t ti_mbox_probe;
+static device_attach_t ti_mbox_attach;
+static device_detach_t ti_mbox_detach;
+static void ti_mbox_intr(void *);
+static int ti_mbox_read(device_t, int, uint32_t *);
+static int ti_mbox_write(device_t, int, uint32_t);
+
+struct ti_mbox_softc {
+ struct mtx sc_mtx;
+ struct resource *sc_mem_res;
+ struct resource *sc_irq_res;
+ void *sc_intr;
+ bus_space_tag_t sc_bt;
+ bus_space_handle_t sc_bh;
+};
+
+#define TI_MBOX_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define TI_MBOX_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+
+static device_method_t ti_mbox_methods[] = {
+ DEVMETHOD(device_probe, ti_mbox_probe),
+ DEVMETHOD(device_attach, ti_mbox_attach),
+ DEVMETHOD(device_detach, ti_mbox_detach),
+
+ DEVMETHOD(mbox_read, ti_mbox_read),
+ DEVMETHOD(mbox_write, ti_mbox_write),
+
+ DEVMETHOD_END
+};
+
+static driver_t ti_mbox_driver = {
+ "ti_mbox",
+ ti_mbox_methods,
+ sizeof(struct ti_mbox_softc)
+};
+
+static devclass_t ti_mbox_devclass;
+
+DRIVER_MODULE(ti_mbox, simplebus, ti_mbox_driver, ti_mbox_devclass, 0, 0);
+
+static __inline uint32_t
+ti_mbox_reg_read(struct ti_mbox_softc *sc, uint16_t reg)
+{
+ return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
+}
+
+static __inline void
+ti_mbox_reg_write(struct ti_mbox_softc *sc, uint16_t reg, uint32_t val)
+{
+ bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
+}
+
+static int
+ti_mbox_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "ti,system-mbox")) {
+ device_set_desc(dev, "TI System Mailbox");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+ti_mbox_attach(device_t dev)
+{
+ struct ti_mbox_softc *sc;
+ int rid, delay, chan;
+ uint32_t rev, sysconfig;
+
+ if (ti_prcm_clk_enable(MAILBOX0_CLK) != 0) {
+ device_printf(dev, "could not enable MBOX clock\n");
+ return (ENXIO);
+ }
+ sc = device_get_softc(dev);
+ rid = 0;
+ mtx_init(&sc->sc_mtx, "TI mbox", NULL, MTX_DEF);
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+ sc->sc_bt = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bh = rman_get_bushandle(sc->sc_mem_res);
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(dev, "could not allocate interrupt resource\n");
+ ti_mbox_detach(dev);
+ return (ENXIO);
+ }
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE | INTR_TYPE_MISC,
+ NULL, ti_mbox_intr, sc, &sc->sc_intr) != 0) {
+ device_printf(dev, "unable to setup the interrupt handler\n");
+ ti_mbox_detach(dev);
+ return (ENXIO);
+ }
+ /*
+ * Reset the controller.
+ */
+ sysconfig = ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG);
+ DPRINTF("initial sysconfig %d\n", sysconfig);
+ sysconfig |= TI_MBOX_SYSCONFIG_SOFTRST;
+ delay = 100;
+ while (ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG) &
+ TI_MBOX_SYSCONFIG_SOFTRST) {
+ delay--;
+ DELAY(10);
+ }
+ if (delay == 0) {
+ device_printf(dev, "controller reset failed\n");
+ ti_mbox_detach(dev);
+ return (ENXIO);
+ }
+ /*
+ * Enable smart idle mode.
+ */
+ ti_mbox_reg_write(sc, TI_MBOX_SYSCONFIG,
+ ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG) | TI_MBOX_SYSCONFIG_SMARTIDLE);
+ rev = ti_mbox_reg_read(sc, TI_MBOX_REVISION);
+ DPRINTF("rev %d\n", rev);
+ device_printf(dev, "revision %d.%d\n", (rev >> 8) & 0x4, rev & 0x40);
+ /*
+ * Enable message interrupts.
+ */
+ for (chan = 0; chan < 8; chan++)
+ ti_mbox_reg_write(sc, TI_MBOX_IRQENABLE_SET(chan), 1);
+
+ return (0);
+}
+
+static int
+ti_mbox_detach(device_t dev)
+{
+ struct ti_mbox_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->sc_intr)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->sc_irq_res),
+ sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_mem_res),
+ sc->sc_mem_res);
+
+ return (0);
+}
+
+static void
+ti_mbox_intr(void *arg)
+{
+ struct ti_mbox_softc *sc;
+
+ sc = arg;
+ DPRINTF("interrupt %p", sc);
+}
+
+static int
+ti_mbox_read(device_t dev, int chan, uint32_t *data)
+{
+ struct ti_mbox_softc *sc;
+
+ if (chan < 0 || chan > 7)
+ return (EINVAL);
+ sc = device_get_softc(dev);
+
+ return (ti_mbox_reg_read(sc, TI_MBOX_MESSAGE(chan)));
+}
+
+static int
+ti_mbox_write(device_t dev, int chan, uint32_t data)
+{
+ int limit = 500;
+ struct ti_mbox_softc *sc;
+
+ if (chan < 0 || chan > 7)
+ return (EINVAL);
+ sc = device_get_softc(dev);
+ TI_MBOX_LOCK(sc);
+ /* XXX implement interrupt method */
+ while (ti_mbox_reg_read(sc, TI_MBOX_FIFOSTATUS(chan)) == 1 &&
+ limit--) {
+ DELAY(10);
+ }
+ if (limit == 0) {
+ device_printf(dev, "FIFOSTAUS%d stuck\n", chan);
+ TI_MBOX_UNLOCK(sc);
+ return (EAGAIN);
+ }
+ ti_mbox_reg_write(sc, TI_MBOX_MESSAGE(chan), data);
+
+ return (0);
+}
Property changes on: trunk/sys/arm/ti/ti_mbox.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_mbox.h
===================================================================
--- trunk/sys/arm/ti/ti_mbox.h (rev 0)
+++ trunk/sys/arm/ti/ti_mbox.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,45 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Rui Paulo <rpaulo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_mbox.h 266098 2014-05-14 23:57:07Z ian $
+ */
+
+#ifndef _TI_MBOX_H_
+#define _TI_MBOX_H_
+
+#define TI_MBOX_REVISION 0x00
+#define TI_MBOX_SYSCONFIG 0x10
+#define TI_MBOX_SYSCONFIG_SOFTRST 0x01
+#define TI_MBOX_SYSCONFIG_SMARTIDLE (0x02 << 2)
+#define TI_MBOX_MESSAGE(n) (0x40 + (n) * 0x4)
+#define TI_MBOX_FIFOSTATUS(n) (0x80 + (n) * 0x4)
+#define TI_MBOX_MSGSTATUS(n) (0xc0 + (n) * 0x4)
+#define TI_MBOX_IRQSTATUS_RAW(n) (0x100 + (n) * 0x10)
+#define TI_MBOX_IRQSTATUS_CLR(n) (0x104 + (n) * 0x10)
+#define TI_MBOX_IRQENABLE_SET(n) (0x108 + (n) * 0x10)
+#define TI_MBOX_IRQENABLE_CLR(n) (0x10c + (n) * 0x10)
+
+#endif /* _TI_MBOX_H_ */
Property changes on: trunk/sys/arm/ti/ti_mbox.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_mmchs.c
===================================================================
--- trunk/sys/arm/ti/ti_mmchs.c (rev 0)
+++ trunk/sys/arm/ti/ti_mmchs.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1844 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * Driver for the MMC/SD/SDIO module on the TI OMAP series of SoCs.
+ *
+ * This driver is heavily based on the SD/MMC driver for the AT91 (at91_mci.c).
+ *
+ * It's important to realise that the MMC state machine is already in the kernel
+ * and this driver only exposes the specific interfaces of the controller.
+ *
+ * This driver is still very much a work in progress, I've verified that basic
+ * sector reading can be performed. But I've yet to test it with a file system
+ * or even writing. In addition I've only tested the driver with an SD card,
+ * I've no idea if MMC cards work.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_mmchs.c 266159 2014-05-15 16:59:47Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcbrvar.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "gpio_if.h"
+
+#include "mmcbr_if.h"
+#include "mmcbus_if.h"
+
+#include <arm/ti/ti_sdma.h>
+#include <arm/ti/ti_edma3.h>
+#include <arm/ti/ti_mmchs.h>
+#include <arm/ti/ti_cpuid.h>
+#include <arm/ti/ti_prcm.h>
+
+#include <arm/ti/twl/twl.h>
+#include <arm/ti/twl/twl_vreg.h>
+
+#ifdef DEBUG
+#define ti_mmchs_dbg(sc, fmt, args...) \
+ device_printf((sc)->sc_dev, fmt, ## args);
+#else
+#define ti_mmchs_dbg(sc, fmt, args...)
+#endif
+
+/**
+ * Structure that stores the driver context
+ */
+struct ti_mmchs_softc {
+ device_t sc_dev;
+ uint32_t device_id;
+ struct resource* sc_irq_res;
+ struct resource* sc_mem_res;
+
+ void* sc_irq_h;
+
+ bus_dma_tag_t sc_dmatag;
+ bus_dmamap_t sc_dmamap;
+ int sc_dmamapped;
+
+ unsigned int sc_dmach_rd;
+ unsigned int sc_dmach_wr;
+ int dma_rx_trig;
+ int dma_tx_trig;
+
+ device_t sc_gpio_dev;
+ int sc_wp_gpio_pin; /* GPIO pin for MMC write protect */
+
+ device_t sc_vreg_dev;
+ const char* sc_vreg_name;
+
+ struct mtx sc_mtx;
+
+ struct mmc_host host;
+ struct mmc_request* req;
+ struct mmc_command* curcmd;
+
+ int flags;
+#define CMD_STARTED 1
+#define STOP_STARTED 2
+
+ int bus_busy; /* TODO: Needed ? */
+
+ void* sc_cmd_data_vaddr;
+ int sc_cmd_data_len;
+
+ /* The offset applied to each of the register base addresses, OMAP4
+ * register sets are offset 0x100 from the OMAP3 series.
+ */
+ unsigned long sc_reg_off;
+
+ /* The physical address of the MMCHS_DATA register, used for the DMA xfers */
+ unsigned long sc_data_reg_paddr;
+
+ /* The reference clock frequency */
+ unsigned int sc_ref_freq;
+
+ enum mmc_power_mode sc_cur_power_mode;
+};
+
+/**
+ * Macros for driver mutex locking
+ */
+#define TI_MMCHS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define TI_MMCHS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define TI_MMCHS_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ "ti_mmchs", MTX_DEF)
+#define TI_MMCHS_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define TI_MMCHS_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define TI_MMCHS_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+static void ti_mmchs_start(struct ti_mmchs_softc *sc);
+
+/**
+ * ti_mmchs_read_4 - reads a 32-bit value from a register
+ * ti_mmchs_write_4 - writes a 32-bit value to a register
+ * @sc: pointer to the driver context
+ * @off: register offset to read from
+ * @val: the value to write into the register
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * The 32-bit value read from the register
+ */
+static inline uint32_t
+ti_mmchs_read_4(struct ti_mmchs_softc *sc, bus_size_t off)
+{
+ return bus_read_4(sc->sc_mem_res, (sc->sc_reg_off + off));
+}
+
+static inline void
+ti_mmchs_write_4(struct ti_mmchs_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->sc_mem_res, (sc->sc_reg_off + off), val);
+}
+
+/**
+ * ti_mmchs_reset_controller -
+ * @arg: caller supplied arg
+ * @segs: array of segments (although in our case should only be one)
+ * @nsegs: number of segments (in our case should be 1)
+ * @error:
+ *
+ *
+ *
+ */
+static void
+ti_mmchs_reset_controller(struct ti_mmchs_softc *sc, uint32_t bit)
+{
+ unsigned long attempts;
+ uint32_t sysctl;
+
+ ti_mmchs_dbg(sc, "reseting controller - bit 0x%08x\n", bit);
+
+ sysctl = ti_mmchs_read_4(sc, MMCHS_SYSCTL);
+ ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl | bit);
+ /*
+ * AM335x and OMAP4 >= ES2 have an updated reset logic.
+ * Monitor a 0->1 transition first.
+ */
+ if ((ti_chip() == CHIP_AM335X) ||
+ ((ti_chip() == CHIP_OMAP_4) && (ti_revision() > OMAP4430_REV_ES1_0))) {
+ attempts = 10000;
+ while (!(ti_mmchs_read_4(sc, MMCHS_SYSCTL) & bit) && (attempts-- > 0))
+ continue;
+ }
+
+ attempts = 10000;
+ while ((ti_mmchs_read_4(sc, MMCHS_SYSCTL) & bit) && (attempts-- > 0))
+ continue;
+
+ if (ti_mmchs_read_4(sc, MMCHS_SYSCTL) & bit)
+ device_printf(sc->sc_dev, "Error - Timeout waiting on controller reset\n");
+}
+
+/**
+ * ti_mmchs_getaddr - called by the DMA function to simply return the phys addr
+ * @arg: caller supplied arg
+ * @segs: array of segments (although in our case should only be one)
+ * @nsegs: number of segments (in our case should be 1)
+ * @error:
+ *
+ * This function is called by bus_dmamap_load() after it has compiled an array
+ * of segments, each segment is a phsyical chunk of memory. However in our case
+ * we should only have one segment, because we don't (yet?) support DMA scatter
+ * gather. To ensure we only have one segment, the DMA tag was created by
+ * bus_dma_tag_create() (called from ti_mmchs_attach) with nsegments set to 1.
+ *
+ */
+static void
+ti_mmchs_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ if (error != 0)
+ return;
+
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+#ifndef SOC_TI_AM335X
+/**
+ * ti_mmchs_dma_intr - interrupt handler for DMA events triggered by the controller
+ * @ch: the dma channel number
+ * @status: bit field of the status bytes
+ * @data: callback data, in this case a pointer to the controller struct
+ *
+ *
+ * LOCKING:
+ * Called from interrupt context
+ *
+ */
+static void
+ti_mmchs_dma_intr(unsigned int ch, uint32_t status, void *data)
+{
+ /* Ignore for now ... we don't need this interrupt as we already have the
+ * interrupt from the MMC controller.
+ */
+}
+#endif
+
+/**
+ * ti_mmchs_intr_xfer_compl - called if a 'transfer complete' IRQ was received
+ * @sc: pointer to the driver context
+ * @cmd: the command that was sent previously
+ *
+ * This function is simply responsible for syncing up the DMA buffer.
+ *
+ * LOCKING:
+ * Called from interrupt context
+ *
+ * RETURNS:
+ * Return value indicates if the transaction is complete, not done = 0, done != 0
+ */
+static int
+ti_mmchs_intr_xfer_compl(struct ti_mmchs_softc *sc, struct mmc_command *cmd)
+{
+ uint32_t cmd_reg;
+
+ /* Read command register to test whether this command was a read or write. */
+ cmd_reg = ti_mmchs_read_4(sc, MMCHS_CMD);
+
+ /* Sync-up the DMA buffer so the caller can access the new memory */
+ if (cmd_reg & MMCHS_CMD_DDIR) {
+ bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap);
+ }
+ else {
+ bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap);
+ }
+ sc->sc_dmamapped--;
+
+ /* Debugging dump of the data received */
+#if 0
+ {
+ int i;
+ uint8_t *p = (uint8_t*) sc->sc_cmd_data_vaddr;
+ for (i=0; i<sc->sc_cmd_data_len; i++) {
+ if ((i % 16) == 0)
+ printf("\n0x%04x : ", i);
+ printf("%02X ", *p++);
+ }
+ printf("\n");
+ }
+#endif
+
+ /* We are done, transfer complete */
+ return 1;
+}
+
+/**
+ * ti_mmchs_intr_cmd_compl - called if a 'command complete' IRQ was received
+ * @sc: pointer to the driver context
+ * @cmd: the command that was sent previously
+ *
+ *
+ * LOCKING:
+ * Called from interrupt context
+ *
+ * RETURNS:
+ * Return value indicates if the transaction is complete, not done = 0, done != 0
+ */
+static int
+ti_mmchs_intr_cmd_compl(struct ti_mmchs_softc *sc, struct mmc_command *cmd)
+{
+ uint32_t cmd_reg;
+
+ /* Copy the response into the request struct ... if a response was
+ * expected */
+ if (cmd != NULL && (cmd->flags & MMC_RSP_PRESENT)) {
+ if (cmd->flags & MMC_RSP_136) {
+ cmd->resp[3] = ti_mmchs_read_4(sc, MMCHS_RSP10);
+ cmd->resp[2] = ti_mmchs_read_4(sc, MMCHS_RSP32);
+ cmd->resp[1] = ti_mmchs_read_4(sc, MMCHS_RSP54);
+ cmd->resp[0] = ti_mmchs_read_4(sc, MMCHS_RSP76);
+ } else {
+ cmd->resp[0] = ti_mmchs_read_4(sc, MMCHS_RSP10);
+ }
+ }
+
+ /* Check if the command was expecting some data transfer, if not
+ * we are done. */
+ cmd_reg = ti_mmchs_read_4(sc, MMCHS_CMD);
+ return ((cmd_reg & MMCHS_CMD_DP) == 0);
+}
+
+/**
+ * ti_mmchs_intr_error - handles error interrupts
+ * @sc: pointer to the driver context
+ * @cmd: the command that was sent previously
+ * @stat_reg: the value that was in the status register
+ *
+ *
+ * LOCKING:
+ * Called from interrupt context
+ *
+ * RETURNS:
+ * Return value indicates if the transaction is complete, not done = 0, done != 0
+ */
+static int
+ti_mmchs_intr_error(struct ti_mmchs_softc *sc, struct mmc_command *cmd,
+ uint32_t stat_reg)
+{
+ ti_mmchs_dbg(sc, "error in xfer - stat 0x%08x\n", stat_reg);
+
+ /* Ignore CRC errors on CMD2 and ACMD47, per relevant standards */
+ if ((stat_reg & MMCHS_STAT_CCRC) && (cmd->opcode == MMC_SEND_OP_COND ||
+ cmd->opcode == ACMD_SD_SEND_OP_COND))
+ cmd->error = MMC_ERR_NONE;
+ else if (stat_reg & (MMCHS_STAT_CTO | MMCHS_STAT_DTO))
+ cmd->error = MMC_ERR_TIMEOUT;
+ else if (stat_reg & (MMCHS_STAT_CCRC | MMCHS_STAT_DCRC))
+ cmd->error = MMC_ERR_BADCRC;
+ else
+ cmd->error = MMC_ERR_FAILED;
+
+ /* If a dma transaction we should also stop the dma transfer */
+ if (ti_mmchs_read_4(sc, MMCHS_CMD) & MMCHS_CMD_DE) {
+
+ /* Abort the DMA transfer (DDIR bit tells direction) */
+ if (ti_mmchs_read_4(sc, MMCHS_CMD) & MMCHS_CMD_DDIR)
+#ifdef SOC_TI_AM335X
+ printf("%s: DMA unimplemented\n", __func__);
+#else
+ ti_sdma_stop_xfer(sc->sc_dmach_rd);
+#endif
+ else
+#ifdef SOC_TI_AM335X
+ printf("%s: DMA unimplemented\n", __func__);
+#else
+ ti_sdma_stop_xfer(sc->sc_dmach_wr);
+#endif
+
+ /* If an error occure abort the DMA operation and free the dma map */
+ if ((sc->sc_dmamapped > 0) && (cmd->error != MMC_ERR_NONE)) {
+ bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap);
+ sc->sc_dmamapped--;
+ }
+ }
+
+ /* Command error occured? ... if so issue a soft reset for the cmd fsm */
+ if (stat_reg & (MMCHS_STAT_CCRC | MMCHS_STAT_CTO)) {
+ ti_mmchs_reset_controller(sc, MMCHS_SYSCTL_SRC);
+ }
+
+ /* Data error occured? ... if so issue a soft reset for the data line */
+ if (stat_reg & (MMCHS_STAT_DEB | MMCHS_STAT_DCRC | MMCHS_STAT_DTO)) {
+ ti_mmchs_reset_controller(sc, MMCHS_SYSCTL_SRD);
+ }
+
+ /* On any error the command is cancelled ... so we are done */
+ return 1;
+}
+
+/**
+ * ti_mmchs_intr - interrupt handler for MMC/SD/SDIO controller
+ * @arg: pointer to the driver context
+ *
+ * Interrupt handler for the MMC/SD/SDIO controller, responsible for handling
+ * the IRQ and clearing the status flags.
+ *
+ * LOCKING:
+ * Called from interrupt context
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+ti_mmchs_intr(void *arg)
+{
+ struct ti_mmchs_softc *sc = (struct ti_mmchs_softc *) arg;
+ uint32_t stat_reg;
+ int done = 0;
+
+ TI_MMCHS_LOCK(sc);
+
+ stat_reg = ti_mmchs_read_4(sc, MMCHS_STAT) & (ti_mmchs_read_4(sc,
+ MMCHS_IE) | MMCHS_STAT_ERRI);
+
+ if (sc->curcmd == NULL) {
+ device_printf(sc->sc_dev, "Error: current cmd NULL, already done?\n");
+ ti_mmchs_write_4(sc, MMCHS_STAT, stat_reg);
+ TI_MMCHS_UNLOCK(sc);
+ return;
+ }
+
+ if (stat_reg & MMCHS_STAT_ERRI) {
+ /* An error has been tripped in the status register */
+ done = ti_mmchs_intr_error(sc, sc->curcmd, stat_reg);
+
+ } else {
+
+ /* NOTE: This implementation could be a bit inefficent, I don't think
+ * it is necessary to handle both the 'command complete' and 'transfer
+ * complete' for data transfers ... presumably just transfer complete
+ * is enough.
+ */
+
+ /* No error */
+ sc->curcmd->error = MMC_ERR_NONE;
+
+ /* Check if the command completed */
+ if (stat_reg & MMCHS_STAT_CC) {
+ done = ti_mmchs_intr_cmd_compl(sc, sc->curcmd);
+ }
+
+ /* Check if the transfer has completed */
+ if (stat_reg & MMCHS_STAT_TC) {
+ done = ti_mmchs_intr_xfer_compl(sc, sc->curcmd);
+ }
+
+ }
+
+ /* Clear all the interrupt status bits by writing the value back */
+ ti_mmchs_write_4(sc, MMCHS_STAT, stat_reg);
+
+ /* This may mark the command as done if there is no stop request */
+ /* TODO: This is a bit ugly, needs fix-up */
+ if (done) {
+ ti_mmchs_start(sc);
+ }
+
+ TI_MMCHS_UNLOCK(sc);
+}
+
+#ifdef SOC_TI_AM335X
+static void
+ti_mmchs_edma3_rx_xfer_setup(struct ti_mmchs_softc *sc, uint32_t src_paddr,
+ uint32_t dst_paddr, uint16_t blk_size, uint16_t num_blks)
+{
+ struct ti_edma3cc_param_set ps;
+
+ bzero(&ps, sizeof(struct ti_edma3cc_param_set));
+ ps.src = src_paddr;
+ ps.dst = dst_paddr;
+ ps.dstbidx = 4;
+ ps.dstcidx = blk_size;
+ ps.acnt = 4;
+ ps.bcnt = blk_size/4;
+ ps.ccnt = num_blks;
+ ps.link = 0xffff;
+ ps.opt.tcc = sc->dma_rx_trig;
+ ps.opt.tcinten = 1;
+ ps.opt.fwid = 2; /* fifo width is 32 */
+ ps.opt.sam = 1;
+ ps.opt.syncdim = 1;
+
+ ti_edma3_param_write(sc->dma_rx_trig, &ps);
+ ti_edma3_enable_transfer_event(sc->dma_rx_trig);
+}
+
+static void
+ti_mmchs_edma3_tx_xfer_setup(struct ti_mmchs_softc *sc, uint32_t src_paddr,
+ uint32_t dst_paddr, uint16_t blk_size, uint16_t num_blks)
+{
+ struct ti_edma3cc_param_set ps;
+
+ bzero(&ps, sizeof(struct ti_edma3cc_param_set));
+ ps.src = src_paddr;
+ ps.dst = dst_paddr;
+ ps.srccidx = blk_size;
+ ps.bcnt = blk_size/4;
+ ps.ccnt = num_blks;
+ ps.srcbidx = 4;
+ ps.acnt = 0x4;
+ ps.link = 0xffff;
+ ps.opt.tcc = sc->dma_tx_trig;
+ ps.opt.tcinten = 1;
+ ps.opt.fwid = 2; /* fifo width is 32 */
+ ps.opt.dam = 1;
+ ps.opt.syncdim = 1;
+
+ ti_edma3_param_write(sc->dma_tx_trig, &ps);
+ ti_edma3_enable_transfer_event(sc->dma_tx_trig);
+}
+#endif
+
+/**
+ * ti_mmchs_start_cmd - starts the given command
+ * @sc: pointer to the driver context
+ * @cmd: the command to start
+ *
+ * The call tree for this function is
+ * - ti_mmchs_start_cmd
+ * - ti_mmchs_start
+ * - ti_mmchs_request
+ *
+ * LOCKING:
+ * Caller should be holding the OMAP_MMC lock.
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+ti_mmchs_start_cmd(struct ti_mmchs_softc *sc, struct mmc_command *cmd)
+{
+ uint32_t cmd_reg, con_reg, ise_reg;
+ struct mmc_data *data;
+ struct mmc_request *req;
+ void *vaddr;
+ bus_addr_t paddr;
+#ifndef SOC_TI_AM335X
+ uint32_t pktsize;
+#endif
+ sc->curcmd = cmd;
+ data = cmd->data;
+ req = cmd->mrq;
+
+ /* Ensure the STR and MIT bits are cleared, these are only used for special
+ * command types.
+ */
+ con_reg = ti_mmchs_read_4(sc, MMCHS_CON);
+ con_reg &= ~(MMCHS_CON_STR | MMCHS_CON_MIT);
+
+ /* Load the command into bits 29:24 of the CMD register */
+ cmd_reg = (uint32_t)(cmd->opcode & 0x3F) << 24;
+
+ /* Set the default set of interrupts */
+ ise_reg = (MMCHS_STAT_CERR | MMCHS_STAT_CTO | MMCHS_STAT_CC | MMCHS_STAT_CEB);
+
+ /* Enable CRC checking if requested */
+ if (cmd->flags & MMC_RSP_CRC)
+ ise_reg |= MMCHS_STAT_CCRC;
+
+ /* Enable reply index checking if the response supports it */
+ if (cmd->flags & MMC_RSP_OPCODE)
+ ise_reg |= MMCHS_STAT_CIE;
+
+ /* Set the expected response length */
+ if (MMC_RSP(cmd->flags) == MMC_RSP_NONE) {
+ cmd_reg |= MMCHS_CMD_RSP_TYPE_NO;
+ } else {
+ if (cmd->flags & MMC_RSP_136)
+ cmd_reg |= MMCHS_CMD_RSP_TYPE_136;
+ else if (cmd->flags & MMC_RSP_BUSY)
+ cmd_reg |= MMCHS_CMD_RSP_TYPE_48_BSY;
+ else
+ cmd_reg |= MMCHS_CMD_RSP_TYPE_48;
+
+ /* Enable command index/crc checks if necessary expected */
+ if (cmd->flags & MMC_RSP_CRC)
+ cmd_reg |= MMCHS_CMD_CCCE;
+ if (cmd->flags & MMC_RSP_OPCODE)
+ cmd_reg |= MMCHS_CMD_CICE;
+ }
+
+ /* Set the bits for the special commands CMD12 (MMC_STOP_TRANSMISSION) and
+ * CMD52 (SD_IO_RW_DIRECT) */
+ if (cmd->opcode == MMC_STOP_TRANSMISSION)
+ cmd_reg |= MMCHS_CMD_CMD_TYPE_IO_ABORT;
+
+ /* Check if there is any data to write */
+ if (data == NULL) {
+ /* Clear the block count */
+ ti_mmchs_write_4(sc, MMCHS_BLK, 0);
+
+ /* The no data case is fairly simple */
+ ti_mmchs_write_4(sc, MMCHS_CON, con_reg);
+ ti_mmchs_write_4(sc, MMCHS_IE, ise_reg);
+ ti_mmchs_write_4(sc, MMCHS_ISE, ise_reg);
+ ti_mmchs_write_4(sc, MMCHS_ARG, cmd->arg);
+ ti_mmchs_write_4(sc, MMCHS_CMD, cmd_reg);
+ return;
+ }
+
+ /* Indicate that data is present */
+ cmd_reg |= MMCHS_CMD_DP | MMCHS_CMD_MSBS | MMCHS_CMD_BCE;
+
+ /* Indicate a read operation */
+ if (data->flags & MMC_DATA_READ)
+ cmd_reg |= MMCHS_CMD_DDIR;
+
+ /* Streaming mode */
+ if (data->flags & MMC_DATA_STREAM) {
+ con_reg |= MMCHS_CON_STR;
+ }
+
+ /* Multi-block mode */
+ if (data->flags & MMC_DATA_MULTI) {
+ cmd_reg |= MMCHS_CMD_MSBS;
+ }
+
+ /* Enable extra interrupt sources for the transfer */
+ ise_reg |= (MMCHS_STAT_TC | MMCHS_STAT_DTO | MMCHS_STAT_DEB | MMCHS_STAT_CEB);
+ if (cmd->flags & MMC_RSP_CRC)
+ ise_reg |= MMCHS_STAT_DCRC;
+
+ /* Enable the DMA transfer bit */
+ cmd_reg |= MMCHS_CMD_DE;
+
+ /* Set the block size and block count */
+ ti_mmchs_write_4(sc, MMCHS_BLK, (1 << 16) | data->len);
+
+ /* Setup the DMA stuff */
+ if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) {
+
+ vaddr = data->data;
+ data->xfer_len = 0;
+
+ /* Map the buffer buf into bus space using the dmamap map. */
+ if (bus_dmamap_load(sc->sc_dmatag, sc->sc_dmamap, vaddr, data->len,
+ ti_mmchs_getaddr, &paddr, 0) != 0) {
+
+ if (req->cmd->flags & STOP_STARTED)
+ req->stop->error = MMC_ERR_NO_MEMORY;
+ else
+ req->cmd->error = MMC_ERR_NO_MEMORY;
+ sc->req = NULL;
+ sc->curcmd = NULL;
+ req->done(req);
+ return;
+ }
+
+#ifndef SOC_TI_AM335X
+ /* Calculate the packet size, the max packet size is 512 bytes
+ * (or 128 32-bit elements).
+ */
+ pktsize = min((data->len / 4), (512 / 4));
+#endif
+ /* Sync the DMA buffer and setup the DMA controller */
+ if (data->flags & MMC_DATA_READ) {
+ bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, BUS_DMASYNC_PREREAD);
+#ifdef SOC_TI_AM335X
+ ti_mmchs_edma3_rx_xfer_setup(sc, sc->sc_data_reg_paddr,
+ paddr, data->len, 1);
+#else
+ ti_sdma_start_xfer_packet(sc->sc_dmach_rd, sc->sc_data_reg_paddr,
+ paddr, 1, (data->len / 4), pktsize);
+#endif
+ } else {
+ bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, BUS_DMASYNC_PREWRITE);
+#ifdef SOC_TI_AM335X
+ ti_mmchs_edma3_tx_xfer_setup(sc, paddr,
+ sc->sc_data_reg_paddr, data->len, 1);
+#else
+ ti_sdma_start_xfer_packet(sc->sc_dmach_wr, paddr,
+ sc->sc_data_reg_paddr, 1, (data->len / 4), pktsize);
+#endif
+ }
+
+ /* Increase the mapped count */
+ sc->sc_dmamapped++;
+
+ sc->sc_cmd_data_vaddr = vaddr;
+ sc->sc_cmd_data_len = data->len;
+ }
+
+ /* Finally kick off the command */
+ ti_mmchs_write_4(sc, MMCHS_CON, con_reg);
+ ti_mmchs_write_4(sc, MMCHS_IE, ise_reg);
+ ti_mmchs_write_4(sc, MMCHS_ISE, ise_reg);
+ ti_mmchs_write_4(sc, MMCHS_ARG, cmd->arg);
+ ti_mmchs_write_4(sc, MMCHS_CMD, cmd_reg);
+
+ /* and we're done */
+}
+
+/**
+ * ti_mmchs_start - starts a request stored in the driver context
+ * @sc: pointer to the driver context
+ *
+ * This function is called by ti_mmchs_request() in response to a read/write
+ * request from the MMC core module.
+ *
+ * LOCKING:
+ * Caller should be holding the OMAP_MMC lock.
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+ti_mmchs_start(struct ti_mmchs_softc *sc)
+{
+ struct mmc_request *req;
+
+ /* Sanity check we have a request */
+ req = sc->req;
+ if (req == NULL)
+ return;
+
+ /* assert locked */
+ if (!(sc->flags & CMD_STARTED)) {
+ sc->flags |= CMD_STARTED;
+ ti_mmchs_start_cmd(sc, req->cmd);
+ return;
+ }
+
+ if (!(sc->flags & STOP_STARTED) && req->stop) {
+ sc->flags |= STOP_STARTED;
+ ti_mmchs_start_cmd(sc, req->stop);
+ return;
+ }
+
+ /* We must be done -- bad idea to do this while locked? */
+ sc->req = NULL;
+ sc->curcmd = NULL;
+ req->done(req);
+}
+
+/**
+ * ti_mmchs_request - entry point for all read/write/cmd requests
+ * @brdev: mmc bridge device handle
+ * @reqdev: the device doing the requesting ?
+ * @req: the action requested
+ *
+ * LOCKING:
+ * None, internally takes the OMAP_MMC lock.
+ *
+ * RETURNS:
+ * 0 on success
+ * EBUSY if the driver is already performing a request
+ */
+static int
+ti_mmchs_request(device_t brdev, device_t reqdev, struct mmc_request *req)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(brdev);
+
+ TI_MMCHS_LOCK(sc);
+
+ /*
+ * XXX do we want to be able to queue up multiple commands?
+ * XXX sounds like a good idea, but all protocols are sync, so
+ * XXX maybe the idea is naive...
+ */
+ if (sc->req != NULL) {
+ TI_MMCHS_UNLOCK(sc);
+ return (EBUSY);
+ }
+
+ /* Store the request and start the command */
+ sc->req = req;
+ sc->flags = 0;
+ ti_mmchs_start(sc);
+
+ TI_MMCHS_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_mmchs_get_ro - returns the status of the read-only setting
+ * @brdev: mmc bridge device handle
+ * @reqdev: device doing the request
+ *
+ * This function is relies on hint'ed values to determine which GPIO is used
+ * to determine if the write protect is enabled. On the BeagleBoard the pin
+ * is GPIO_23.
+ *
+ * LOCKING:
+ * -
+ *
+ * RETURNS:
+ * 0 if not read-only
+ * 1 if read only
+ */
+static int
+ti_mmchs_get_ro(device_t brdev, device_t reqdev)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(brdev);
+ unsigned int readonly = 0;
+
+ TI_MMCHS_LOCK(sc);
+
+ if ((sc->sc_wp_gpio_pin != -1) && (sc->sc_gpio_dev != NULL)) {
+ if (GPIO_PIN_GET(sc->sc_gpio_dev, sc->sc_wp_gpio_pin, &readonly) != 0)
+ readonly = 0;
+ else
+ readonly = (readonly == 0) ? 0 : 1;
+ }
+
+ TI_MMCHS_UNLOCK(sc);
+
+ return (readonly);
+}
+
+/**
+ * ti_mmchs_send_init_stream - sets bus/controller settings
+ * @brdev: mmc bridge device handle
+ * @reqdev: device doing the request
+ *
+ * Send init stream sequence to card before sending IDLE command
+ *
+ * LOCKING:
+ *
+ *
+ * RETURNS:
+ * 0 if function succeeded
+ */
+static void
+ti_mmchs_send_init_stream(struct ti_mmchs_softc *sc)
+{
+ unsigned long timeout;
+ uint32_t ie, ise, con;
+
+ ti_mmchs_dbg(sc, "Performing init sequence\n");
+
+ /* Prior to issuing any command, the MMCHS controller has to execute a
+ * special INIT procedure. The MMCHS controller has to generate a clock
+ * during 1ms. During the INIT procedure, the MMCHS controller generates 80
+ * clock periods. In order to keep the 1ms gap, the MMCHS controller should
+ * be configured to generate a clock whose frequency is smaller or equal to
+ * 80 KHz. If the MMCHS controller divider bitfield width doesn't allow to
+ * choose big values, the MMCHS controller driver should perform the INIT
+ * procedure twice or three times. Twice is generally enough.
+ *
+ * The INIt procedure is executed by setting MMCHS1.MMCHS_CON[1] INIT
+ * bitfield to 1 and by sending a dummy command, writing 0x00000000 in
+ * MMCHS1.MMCHS_CMD register.
+ */
+
+ /* Disable interrupt status events but enable interrupt generation.
+ * This doesn't seem right to me, but if the interrupt generation is not
+ * enabled the CC bit doesn't seem to be set in the STAT register.
+ */
+
+ /* Enable interrupt generation */
+ ie = ti_mmchs_read_4(sc, MMCHS_IE);
+ ti_mmchs_write_4(sc, MMCHS_IE, 0x307F0033);
+
+ /* Disable generation of status events (stops interrupt triggering) */
+ ise = ti_mmchs_read_4(sc, MMCHS_ISE);
+ ti_mmchs_write_4(sc, MMCHS_ISE, 0);
+
+ /* Set the initialise stream bit */
+ con = ti_mmchs_read_4(sc, MMCHS_CON);
+ con |= MMCHS_CON_INIT;
+ ti_mmchs_write_4(sc, MMCHS_CON, con);
+
+ /* Write a dummy command 0x00 */
+ ti_mmchs_write_4(sc, MMCHS_CMD, 0x00000000);
+
+ /* Loop waiting for the command to finish */
+ timeout = hz;
+ do {
+ pause("MMCINIT", 1);
+ if (timeout-- == 0) {
+ device_printf(sc->sc_dev, "Error: first stream init timed out\n");
+ break;
+ }
+ } while (!(ti_mmchs_read_4(sc, MMCHS_STAT) & MMCHS_STAT_CC));
+
+ /* Clear the command complete status bit */
+ ti_mmchs_write_4(sc, MMCHS_STAT, MMCHS_STAT_CC);
+
+ /* Write another dummy command 0x00 */
+ ti_mmchs_write_4(sc, MMCHS_CMD, 0x00000000);
+
+ /* Loop waiting for the second command to finish */
+ timeout = hz;
+ do {
+ pause("MMCINIT", 1);
+ if (timeout-- == 0) {
+ device_printf(sc->sc_dev, "Error: second stream init timed out\n");
+ break;
+ }
+ } while (!(ti_mmchs_read_4(sc, MMCHS_STAT) & MMCHS_STAT_CC));
+
+ /* Clear the stream init bit */
+ con &= ~MMCHS_CON_INIT;
+ ti_mmchs_write_4(sc, MMCHS_CON, con);
+
+ /* Clear the status register, then restore the IE and ISE registers */
+ ti_mmchs_write_4(sc, MMCHS_STAT, 0xffffffff);
+ ti_mmchs_read_4(sc, MMCHS_STAT);
+
+ ti_mmchs_write_4(sc, MMCHS_ISE, ise);
+ ti_mmchs_write_4(sc, MMCHS_IE, ie);
+}
+
+/**
+ * ti_mmchs_update_ios - sets bus/controller settings
+ * @brdev: mmc bridge device handle
+ * @reqdev: device doing the request
+ *
+ * Called to set the bus and controller settings that need to be applied to
+ * the actual HW. Currently this function just sets the bus width and the
+ * clock speed.
+ *
+ * LOCKING:
+ *
+ *
+ * RETURNS:
+ * 0 if function succeeded
+ */
+static int
+ti_mmchs_update_ios(device_t brdev, device_t reqdev)
+{
+ struct ti_mmchs_softc *sc;
+ struct mmc_host *host;
+ struct mmc_ios *ios;
+ uint32_t clkdiv;
+ uint32_t hctl_reg;
+ uint32_t con_reg;
+ uint32_t sysctl_reg;
+#ifndef SOC_TI_AM335X
+ uint16_t mv;
+#endif
+ unsigned long timeout;
+ int do_card_init = 0;
+
+ sc = device_get_softc(brdev);
+ host = &sc->host;
+ ios = &host->ios;
+
+ /* Read the initial values of the registers */
+ hctl_reg = ti_mmchs_read_4(sc, MMCHS_HCTL);
+ con_reg = ti_mmchs_read_4(sc, MMCHS_CON);
+
+ /* Set the bus width */
+ switch (ios->bus_width) {
+ case bus_width_1:
+ hctl_reg &= ~MMCHS_HCTL_DTW;
+ con_reg &= ~MMCHS_CON_DW8;
+ break;
+ case bus_width_4:
+ hctl_reg |= MMCHS_HCTL_DTW;
+ con_reg &= ~MMCHS_CON_DW8;
+ break;
+ case bus_width_8:
+ con_reg |= MMCHS_CON_DW8;
+ break;
+ }
+
+ /* Finally write all these settings back to the registers */
+ ti_mmchs_write_4(sc, MMCHS_HCTL, hctl_reg);
+ ti_mmchs_write_4(sc, MMCHS_CON, con_reg);
+
+ /* Check if we need to change the external voltage regulator */
+ if (sc->sc_cur_power_mode != ios->power_mode) {
+
+ if (ios->power_mode == power_up) {
+
+ /* Set the power level */
+ hctl_reg = ti_mmchs_read_4(sc, MMCHS_HCTL);
+ hctl_reg &= ~(MMCHS_HCTL_SDVS_MASK | MMCHS_HCTL_SDBP);
+
+ if ((ios->vdd == -1) || (ios->vdd >= vdd_240)) {
+#ifndef SOC_TI_AM335X
+ mv = 3000;
+#endif
+ hctl_reg |= MMCHS_HCTL_SDVS_V30;
+ } else {
+#ifndef SOC_TI_AM335X
+ mv = 1800;
+#endif
+ hctl_reg |= MMCHS_HCTL_SDVS_V18;
+ }
+
+ ti_mmchs_write_4(sc, MMCHS_HCTL, hctl_reg);
+
+#ifdef SOC_TI_AM335X
+ printf("%s: TWL unimplemented\n", __func__);
+#else
+ /* Set the desired voltage on the regulator */
+ if (sc->sc_vreg_dev && sc->sc_vreg_name)
+ twl_vreg_set_voltage(sc->sc_vreg_dev, sc->sc_vreg_name, mv);
+#endif
+ /* Enable the bus power */
+ ti_mmchs_write_4(sc, MMCHS_HCTL, (hctl_reg | MMCHS_HCTL_SDBP));
+ timeout = hz;
+ while (!(ti_mmchs_read_4(sc, MMCHS_HCTL) & MMCHS_HCTL_SDBP)) {
+ if (timeout-- == 0)
+ break;
+ pause("MMC_PWRON", 1);
+ }
+
+ } else if (ios->power_mode == power_off) {
+ /* Disable the bus power */
+ hctl_reg = ti_mmchs_read_4(sc, MMCHS_HCTL);
+ ti_mmchs_write_4(sc, MMCHS_HCTL, (hctl_reg & ~MMCHS_HCTL_SDBP));
+
+#ifdef SOC_TI_AM335X
+ printf("%s: TWL unimplemented\n", __func__);
+#else
+ /* Turn the power off on the voltage regulator */
+ if (sc->sc_vreg_dev && sc->sc_vreg_name)
+ twl_vreg_set_voltage(sc->sc_vreg_dev, sc->sc_vreg_name, 0);
+#endif
+ } else if (ios->power_mode == power_on) {
+ /* Force a card re-initialisation sequence */
+ do_card_init = 1;
+ }
+
+ /* Save the new power state */
+ sc->sc_cur_power_mode = ios->power_mode;
+ }
+
+ /* need the MMCHS_SYSCTL register */
+ sysctl_reg = ti_mmchs_read_4(sc, MMCHS_SYSCTL);
+
+ /* Just in case this hasn't been setup before, set the timeout to the default */
+ sysctl_reg &= ~MMCHS_SYSCTL_DTO_MASK;
+ sysctl_reg |= MMCHS_SYSCTL_DTO(0xe);
+
+ /* Disable the clock output while configuring the new clock */
+ sysctl_reg &= ~(MMCHS_SYSCTL_ICE | MMCHS_SYSCTL_CEN);
+ ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl_reg);
+
+ /* bus mode? */
+ if (ios->clock == 0) {
+ clkdiv = 0;
+ } else {
+ clkdiv = sc->sc_ref_freq / ios->clock;
+ if (clkdiv < 1)
+ clkdiv = 1;
+ if ((sc->sc_ref_freq / clkdiv) > ios->clock)
+ clkdiv += 1;
+ if (clkdiv > 250)
+ clkdiv = 250;
+ }
+
+ /* Set the new clock divider */
+ sysctl_reg &= ~MMCHS_SYSCTL_CLKD_MASK;
+ sysctl_reg |= MMCHS_SYSCTL_CLKD(clkdiv);
+
+ /* Write the new settings ... */
+ ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl_reg);
+ /* ... write the internal clock enable bit ... */
+ ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl_reg | MMCHS_SYSCTL_ICE);
+ /* ... wait for the clock to stablise ... */
+ while (((sysctl_reg = ti_mmchs_read_4(sc, MMCHS_SYSCTL)) &
+ MMCHS_SYSCTL_ICS) == 0) {
+ continue;
+ }
+ /* ... then enable */
+ sysctl_reg |= MMCHS_SYSCTL_CEN;
+ ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl_reg);
+
+ /* If the power state has changed to 'power_on' then run the init sequence*/
+ if (do_card_init) {
+ ti_mmchs_send_init_stream(sc);
+ }
+
+ /* Set the bus mode (opendrain or normal) */
+ con_reg = ti_mmchs_read_4(sc, MMCHS_CON);
+ if (ios->bus_mode == opendrain)
+ con_reg |= MMCHS_CON_OD;
+ else
+ con_reg &= ~MMCHS_CON_OD;
+ ti_mmchs_write_4(sc, MMCHS_CON, con_reg);
+
+ return (0);
+}
+
+/**
+ * ti_mmchs_acquire_host -
+ * @brdev: mmc bridge device handle
+ * @reqdev: device doing the request
+ *
+ * TODO: Is this function needed ?
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * 0 function succeeded
+ *
+ */
+static int
+ti_mmchs_acquire_host(device_t brdev, device_t reqdev)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(brdev);
+ int err = 0;
+
+ TI_MMCHS_LOCK(sc);
+
+ while (sc->bus_busy) {
+ msleep(sc, &sc->sc_mtx, PZERO, "mmc", hz / 5);
+ }
+
+ sc->bus_busy++;
+
+ TI_MMCHS_UNLOCK(sc);
+
+ return (err);
+}
+
+/**
+ * ti_mmchs_release_host -
+ * @brdev: mmc bridge device handle
+ * @reqdev: device doing the request
+ *
+ * TODO: Is this function needed ?
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * 0 function succeeded
+ *
+ */
+static int
+ti_mmchs_release_host(device_t brdev, device_t reqdev)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(brdev);
+
+ TI_MMCHS_LOCK(sc);
+
+ sc->bus_busy--;
+ wakeup(sc);
+
+ TI_MMCHS_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_mmchs_read_ivar - returns driver conf variables
+ * @bus:
+ * @child:
+ * @which: The variable to get the result for
+ * @result: Upon return will store the variable value
+ *
+ *
+ *
+ * LOCKING:
+ * None, caller must hold locks
+ *
+ * RETURNS:
+ * 0 on success
+ * EINVAL if the variable requested is invalid
+ */
+static int
+ti_mmchs_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(bus);
+
+ switch (which) {
+ case MMCBR_IVAR_BUS_MODE:
+ *(int *)result = sc->host.ios.bus_mode;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ *(int *)result = sc->host.ios.bus_width;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ *(int *)result = sc->host.ios.chip_select;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ *(int *)result = sc->host.ios.clock;
+ break;
+ case MMCBR_IVAR_F_MIN:
+ *(int *)result = sc->host.f_min;
+ break;
+ case MMCBR_IVAR_F_MAX:
+ *(int *)result = sc->host.f_max;
+ break;
+ case MMCBR_IVAR_HOST_OCR:
+ *(int *)result = sc->host.host_ocr;
+ break;
+ case MMCBR_IVAR_MODE:
+ *(int *)result = sc->host.mode;
+ break;
+ case MMCBR_IVAR_OCR:
+ *(int *)result = sc->host.ocr;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ *(int *)result = sc->host.ios.power_mode;
+ break;
+ case MMCBR_IVAR_VDD:
+ *(int *)result = sc->host.ios.vdd;
+ break;
+ case MMCBR_IVAR_CAPS:
+ *(int *)result = sc->host.caps;
+ break;
+ case MMCBR_IVAR_MAX_DATA:
+ *(int *)result = 1;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+/**
+ * ti_mmchs_write_ivar - writes a driver conf variables
+ * @bus:
+ * @child:
+ * @which: The variable to set
+ * @value: The value to write into the variable
+ *
+ *
+ *
+ * LOCKING:
+ * None, caller must hold locks
+ *
+ * RETURNS:
+ * 0 on success
+ * EINVAL if the variable requested is invalid
+ */
+static int
+ti_mmchs_write_ivar(device_t bus, device_t child, int which, uintptr_t value)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(bus);
+
+ switch (which) {
+ case MMCBR_IVAR_BUS_MODE:
+ sc->host.ios.bus_mode = value;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ sc->host.ios.bus_width = value;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ sc->host.ios.chip_select = value;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ sc->host.ios.clock = value;
+ break;
+ case MMCBR_IVAR_MODE:
+ sc->host.mode = value;
+ break;
+ case MMCBR_IVAR_OCR:
+ sc->host.ocr = value;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ sc->host.ios.power_mode = value;
+ break;
+ case MMCBR_IVAR_VDD:
+ sc->host.ios.vdd = value;
+ break;
+ /* These are read-only */
+ case MMCBR_IVAR_CAPS:
+ case MMCBR_IVAR_HOST_OCR:
+ case MMCBR_IVAR_F_MIN:
+ case MMCBR_IVAR_F_MAX:
+ case MMCBR_IVAR_MAX_DATA:
+ return (EINVAL);
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+/**
+ * ti_mmchs_hw_init - initialises the MMC/SD/SIO controller
+ * @dev: mmc device handle
+ *
+ * Called by the driver attach function during driver initialisation. This
+ * function is responsibly to setup the controller ready for transactions.
+ *
+ * LOCKING:
+ * No locking, assumed to only be called during initialisation.
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+ti_mmchs_hw_init(device_t dev)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(dev);
+ clk_ident_t clk;
+ unsigned long timeout;
+ uint32_t sysctl;
+ uint32_t capa;
+ uint32_t con, sysconfig;
+
+ /* 1: Enable the controller and interface/functional clocks */
+ clk = MMC0_CLK + sc->device_id;
+
+ if (ti_prcm_clk_enable(clk) != 0) {
+ device_printf(dev, "Error: failed to enable MMC clock\n");
+ return;
+ }
+
+ /* 1a: Get the frequency of the source clock */
+ if (ti_prcm_clk_get_source_freq(clk, &sc->sc_ref_freq) != 0) {
+ device_printf(dev, "Error: failed to get source clock freq\n");
+ return;
+ }
+
+ /* 2: Issue a softreset to the controller */
+ sysconfig = ti_mmchs_read_4(sc, MMCHS_SYSCONFIG);
+ sysconfig |= MMCHS_SYSCONFIG_SRST;
+ ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, sysconfig);
+ timeout = 100;
+ while ((ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & 0x01) == 0x0) {
+ DELAY(1000);
+ if (timeout-- == 0) {
+ device_printf(dev, "Error: reset operation timed out\n");
+ return;
+ }
+ }
+
+ /* 3: Reset both the command and data state machines */
+ sysctl = ti_mmchs_read_4(sc, MMCHS_SYSCTL);
+ ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl | MMCHS_SYSCTL_SRA);
+ timeout = 100;
+ while ((ti_mmchs_read_4(sc, MMCHS_SYSCTL) & MMCHS_SYSCTL_SRA) != 0x0) {
+ DELAY(1000);
+ if (timeout-- == 0) {
+ device_printf(dev, "Error: reset operation timed out\n");
+ return;
+ }
+ }
+
+ /* 4: Set initial host configuration (1-bit mode, pwroff) and capabilities */
+ ti_mmchs_write_4(sc, MMCHS_HCTL, MMCHS_HCTL_SDVS_V30);
+
+ capa = ti_mmchs_read_4(sc, MMCHS_CAPA);
+ ti_mmchs_write_4(sc, MMCHS_CAPA, capa | MMCHS_CAPA_VS30 | MMCHS_CAPA_VS18);
+
+ /* 5: Set the initial bus configuration
+ * 0 CTPL_MMC_SD : Control Power for DAT1 line
+ * 0 WPP_ACTIVE_HIGH : Write protect polarity
+ * 0 CDP_ACTIVE_HIGH : Card detect polarity
+ * 0 CTO_ENABLED : MMC interrupt command
+ * 0 DW8_DISABLED : 8-bit mode MMC select
+ * 0 MODE_FUNC : Mode select
+ * 0 STREAM_DISABLED : Stream command
+ * 0 HR_DISABLED : Broadcast host response
+ * 0 INIT_DISABLED : Send initialization stream
+ * 0 OD_DISABLED : No Open Drain
+ */
+ con = ti_mmchs_read_4(sc, MMCHS_CON) & MMCHS_CON_DVAL_MASK;
+ ti_mmchs_write_4(sc, MMCHS_CON, con);
+
+}
+
+/**
+ * ti_mmchs_fini - shutdown the MMC/SD/SIO controller
+ * @dev: mmc device handle
+ *
+ * Responsible for shutting done the MMC controller, this function may be
+ * called as part of a reset sequence.
+ *
+ * LOCKING:
+ * No locking, assumed to be called during tear-down/reset.
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+ti_mmchs_hw_fini(device_t dev)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(dev);
+
+ /* Disable all interrupts */
+ ti_mmchs_write_4(sc, MMCHS_ISE, 0x00000000);
+ ti_mmchs_write_4(sc, MMCHS_IE, 0x00000000);
+
+ /* Disable the functional and interface clocks */
+ ti_prcm_clk_disable(MMC0_CLK + sc->device_id);
+}
+
+/**
+ * ti_mmchs_init_dma_channels - initalise the DMA channels
+ * @sc: driver soft context
+ *
+ * Attempts to activate an RX and TX DMA channel for the MMC device.
+ *
+ * LOCKING:
+ * No locking, assumed to be called during tear-down/reset.
+ *
+ * RETURNS:
+ * 0 on success, a negative error code on failure.
+ */
+static int
+ti_mmchs_init_dma_channels(struct ti_mmchs_softc *sc)
+{
+#ifdef SOC_TI_AM335X
+ switch (sc->device_id) {
+ case 0:
+ sc->dma_tx_trig = TI_EDMA3_EVENT_SDTXEVT0;
+ sc->dma_rx_trig = TI_EDMA3_EVENT_SDRXEVT0;
+ break;
+ case 1:
+ sc->dma_tx_trig = TI_EDMA3_EVENT_SDTXEVT1;
+ sc->dma_rx_trig = TI_EDMA3_EVENT_SDRXEVT1;
+ break;
+ default:
+ return(EINVAL);
+ }
+
+#define EVTQNUM 0
+ /* TODO EDMA3 have 3 queues, so we need some queue allocation call */
+ ti_edma3_init(EVTQNUM);
+ ti_edma3_request_dma_ch(sc->dma_tx_trig, sc->dma_tx_trig, EVTQNUM);
+ ti_edma3_request_dma_ch(sc->dma_rx_trig, sc->dma_rx_trig, EVTQNUM);
+#else
+ int err;
+ uint32_t rev;
+
+ /* Get the current chip revision */
+ rev = ti_revision();
+ if ((OMAP_REV_DEVICE(rev) != OMAP4430_DEV) && (sc->device_id > 3))
+ return(EINVAL);
+
+ /* Get the DMA MMC triggers */
+ switch (sc->device_id) {
+ case 1:
+ sc->dma_tx_trig = 60;
+ sc->dma_rx_trig = 61;
+ break;
+ case 2:
+ sc->dma_tx_trig = 46;
+ sc->dma_rx_trig = 47;
+ break;
+ case 3:
+ sc->dma_tx_trig = 76;
+ sc->dma_rx_trig = 77;
+ break;
+ /* The following are OMAP4 only */
+ case 4:
+ sc->dma_tx_trig = 56;
+ sc->dma_rx_trig = 57;
+ break;
+ case 5:
+ sc->dma_tx_trig = 58;
+ sc->dma_rx_trig = 59;
+ break;
+ default:
+ return(EINVAL);
+ }
+
+ /* Activate a RX channel from the OMAP DMA driver */
+ err = ti_sdma_activate_channel(&sc->sc_dmach_rd, ti_mmchs_dma_intr, sc);
+ if (err != 0)
+ return(err);
+
+ /* Setup the RX channel for MMC data transfers */
+ ti_sdma_set_xfer_burst(sc->sc_dmach_rd, TI_SDMA_BURST_NONE,
+ TI_SDMA_BURST_64);
+ ti_sdma_set_xfer_data_type(sc->sc_dmach_rd, TI_SDMA_DATA_32BITS_SCALAR);
+ ti_sdma_sync_params(sc->sc_dmach_rd, sc->dma_rx_trig,
+ TI_SDMA_SYNC_PACKET | TI_SDMA_SYNC_TRIG_ON_SRC);
+ ti_sdma_set_addr_mode(sc->sc_dmach_rd, TI_SDMA_ADDR_CONSTANT,
+ TI_SDMA_ADDR_POST_INCREMENT);
+
+ /* Activate and configure the TX DMA channel */
+ err = ti_sdma_activate_channel(&sc->sc_dmach_wr, ti_mmchs_dma_intr, sc);
+ if (err != 0)
+ return(err);
+
+ /* Setup the TX channel for MMC data transfers */
+ ti_sdma_set_xfer_burst(sc->sc_dmach_wr, TI_SDMA_BURST_64,
+ TI_SDMA_BURST_NONE);
+ ti_sdma_set_xfer_data_type(sc->sc_dmach_wr, TI_SDMA_DATA_32BITS_SCALAR);
+ ti_sdma_sync_params(sc->sc_dmach_wr, sc->dma_tx_trig,
+ TI_SDMA_SYNC_PACKET | TI_SDMA_SYNC_TRIG_ON_DST);
+ ti_sdma_set_addr_mode(sc->sc_dmach_wr, TI_SDMA_ADDR_POST_INCREMENT,
+ TI_SDMA_ADDR_CONSTANT);
+#endif
+ return(0);
+}
+
+/**
+ * ti_mmchs_deactivate - deactivates the driver
+ * @dev: mmc device handle
+ *
+ * Unmaps the register set and releases the IRQ resource.
+ *
+ * LOCKING:
+ * None required
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+ti_mmchs_deactivate(device_t dev)
+{
+ struct ti_mmchs_softc *sc= device_get_softc(dev);
+
+ /* Remove the IRQ handler */
+ if (sc->sc_irq_h != NULL) {
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_h);
+ sc->sc_irq_h = NULL;
+ }
+
+ /* Do the generic detach */
+ bus_generic_detach(sc->sc_dev);
+
+#ifdef SOC_TI_AM335X
+ printf("%s: DMA unimplemented\n", __func__);
+#else
+ /* Deactivate the DMA channels */
+ ti_sdma_deactivate_channel(sc->sc_dmach_rd);
+ ti_sdma_deactivate_channel(sc->sc_dmach_wr);
+#endif
+
+ /* Unmap the MMC controller registers */
+ if (sc->sc_mem_res != 0) {
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_irq_res),
+ sc->sc_mem_res);
+ sc->sc_mem_res = NULL;
+ }
+
+ /* Release the IRQ resource */
+ if (sc->sc_irq_res != NULL) {
+ bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->sc_irq_res),
+ sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+
+ return;
+}
+
+/**
+ * ti_mmchs_activate - activates the driver
+ * @dev: mmc device handle
+ *
+ * Maps in the register set and requests an IRQ handler for the MMC controller.
+ *
+ * LOCKING:
+ * None required
+ *
+ * RETURNS:
+ * 0 on sucess
+ * ENOMEM if failed to map register set
+ */
+static int
+ti_mmchs_activate(device_t dev)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(dev);
+ int rid;
+ int err;
+
+ /* Get the memory resource for the register mapping */
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL)
+ panic("%s: Cannot map registers", device_get_name(dev));
+
+ /* Allocate an IRQ resource for the MMC controller */
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->sc_irq_res == NULL)
+ goto errout;
+
+ /* Allocate DMA tags and maps */
+ err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
+ NULL, MAXPHYS, 1, MAXPHYS, BUS_DMA_ALLOCNOW, NULL,
+ NULL, &sc->sc_dmatag);
+ if (err != 0)
+ goto errout;
+
+ err = bus_dmamap_create(sc->sc_dmatag, 0, &sc->sc_dmamap);
+ if (err != 0)
+ goto errout;
+
+ /* Initialise the DMA channels to be used by the controller */
+ err = ti_mmchs_init_dma_channels(sc);
+ if (err != 0)
+ goto errout;
+
+ /* Set the register offset */
+ if (ti_chip() == CHIP_OMAP_3)
+ sc->sc_reg_off = OMAP3_MMCHS_REG_OFFSET;
+ else if (ti_chip() == CHIP_OMAP_4)
+ sc->sc_reg_off = OMAP4_MMCHS_REG_OFFSET;
+ else if (ti_chip() == CHIP_AM335X)
+ sc->sc_reg_off = AM335X_MMCHS_REG_OFFSET;
+ else
+ panic("Unknown OMAP device\n");
+
+ /* Get the physical address of the MMC data register, needed for DMA */
+ sc->sc_data_reg_paddr = BUS_SPACE_PHYSADDR(sc->sc_mem_res,
+ sc->sc_reg_off + MMCHS_DATA);
+
+ /* Set the initial power state to off */
+ sc->sc_cur_power_mode = power_off;
+
+ return (0);
+
+errout:
+ ti_mmchs_deactivate(dev);
+ return (ENOMEM);
+}
+
+/**
+ * ti_mmchs_probe - probe function for the driver
+ * @dev: mmc device handle
+ *
+ *
+ *
+ * RETURNS:
+ * always returns 0
+ */
+static int
+ti_mmchs_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,mmchs"))
+ return (ENXIO);
+
+ device_set_desc(dev, "TI MMC/SD/SDIO High Speed Interface");
+ return (0);
+}
+
+/**
+ * ti_mmchs_attach - attach function for the driver
+ * @dev: mmc device handle
+ *
+ * Driver initialisation, sets-up the bus mappings, DMA mapping/channels and
+ * the actual controller by calling ti_mmchs_init().
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code.
+ */
+static int
+ti_mmchs_attach(device_t dev)
+{
+ struct ti_mmchs_softc *sc = device_get_softc(dev);
+ int unit = device_get_unit(dev);
+ phandle_t node;
+ pcell_t did;
+ int err;
+
+ /* Save the device and bus tag */
+ sc->sc_dev = dev;
+
+ /* Get the mmchs device id from FDT */
+ node = ofw_bus_get_node(dev);
+ if ((OF_getprop(node, "mmchs-device-id", &did, sizeof(did))) <= 0) {
+ device_printf(dev, "missing mmchs-device-id attribute in FDT\n");
+ return (ENXIO);
+ }
+ sc->device_id = fdt32_to_cpu(did);
+
+ /* Initiate the mtex lock */
+ TI_MMCHS_LOCK_INIT(sc);
+
+ /* Indicate the DMA channels haven't yet been allocated */
+ sc->sc_dmach_rd = (unsigned int)-1;
+ sc->sc_dmach_wr = (unsigned int)-1;
+
+ /* Get the hint'ed write detect pin */
+ /* TODO: take this from FDT */
+ if (resource_int_value("ti_mmchs", unit, "wp_gpio", &sc->sc_wp_gpio_pin) != 0){
+ sc->sc_wp_gpio_pin = -1;
+ } else {
+ /* Get the GPIO device, we need this for the write protect pin */
+ sc->sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (sc->sc_gpio_dev == NULL)
+ device_printf(dev, "Error: failed to get the GPIO device\n");
+ else
+ GPIO_PIN_SETFLAGS(sc->sc_gpio_dev, sc->sc_wp_gpio_pin,
+ GPIO_PIN_INPUT);
+ }
+
+ /* Get the TWL voltage regulator device, we need this to for setting the
+ * voltage of the bus on certain OMAP platforms.
+ */
+ sc->sc_vreg_name = NULL;
+
+ /* TODO: add voltage regulator knob to FDT */
+#ifdef notyet
+ sc->sc_vreg_dev = devclass_get_device(devclass_find("twl_vreg"), 0);
+ if (sc->sc_vreg_dev == NULL) {
+ device_printf(dev, "Error: failed to get the votlage regulator"
+ " device\n");
+ sc->sc_vreg_name = NULL;
+ }
+#endif
+
+ /* Activate the device */
+ err = ti_mmchs_activate(dev);
+ if (err)
+ goto out;
+
+ /* Initialise the controller */
+ ti_mmchs_hw_init(dev);
+
+ /* Activate the interrupt and attach a handler */
+ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, ti_mmchs_intr, sc, &sc->sc_irq_h);
+ if (err != 0)
+ goto out;
+
+ /* Add host details */
+ sc->host.f_min = sc->sc_ref_freq / 1023;
+ sc->host.f_max = sc->sc_ref_freq;
+ sc->host.host_ocr = MMC_OCR_290_300 | MMC_OCR_300_310;
+ sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+
+ device_add_child(dev, "mmc", 0);
+
+ err = bus_generic_attach(dev);
+
+out:
+ if (err) {
+ TI_MMCHS_LOCK_DESTROY(sc);
+ ti_mmchs_deactivate(dev);
+
+#ifdef SOC_TI_AM335X
+ printf("%s: DMA unimplemented\n", __func__);
+#else
+ if (sc->sc_dmach_rd != (unsigned int)-1)
+ ti_sdma_deactivate_channel(sc->sc_dmach_rd);
+ if (sc->sc_dmach_wr != (unsigned int)-1)
+ ti_sdma_deactivate_channel(sc->sc_dmach_wr);
+#endif
+ }
+
+ return (err);
+}
+
+/**
+ * ti_mmchs_detach - dettach function for the driver
+ * @dev: mmc device handle
+ *
+ * Shutdowns the controll and release resources allocated by the driver.
+ *
+ * RETURNS:
+ * Always returns 0.
+ */
+static int
+ti_mmchs_detach(device_t dev)
+{
+#ifndef SOC_TI_AM335X
+ struct ti_mmchs_softc *sc = device_get_softc(dev);
+#endif
+
+ ti_mmchs_hw_fini(dev);
+ ti_mmchs_deactivate(dev);
+
+#ifdef SOC_TI_AM335X
+ printf("%s: DMA unimplemented\n", __func__);
+#else
+ ti_sdma_deactivate_channel(sc->sc_dmach_wr);
+ ti_sdma_deactivate_channel(sc->sc_dmach_rd);
+#endif
+
+ return (0);
+}
+
+static device_method_t ti_mmchs_methods[] = {
+ /* device_if */
+ DEVMETHOD(device_probe, ti_mmchs_probe),
+ DEVMETHOD(device_attach, ti_mmchs_attach),
+ DEVMETHOD(device_detach, ti_mmchs_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, ti_mmchs_read_ivar),
+ DEVMETHOD(bus_write_ivar, ti_mmchs_write_ivar),
+
+ /* mmcbr_if - MMC state machine callbacks */
+ DEVMETHOD(mmcbr_update_ios, ti_mmchs_update_ios),
+ DEVMETHOD(mmcbr_request, ti_mmchs_request),
+ DEVMETHOD(mmcbr_get_ro, ti_mmchs_get_ro),
+ DEVMETHOD(mmcbr_acquire_host, ti_mmchs_acquire_host),
+ DEVMETHOD(mmcbr_release_host, ti_mmchs_release_host),
+
+ {0, 0},
+};
+
+static driver_t ti_mmchs_driver = {
+ "ti_mmchs",
+ ti_mmchs_methods,
+ sizeof(struct ti_mmchs_softc),
+};
+static devclass_t ti_mmchs_devclass;
+
+DRIVER_MODULE(ti_mmchs, simplebus, ti_mmchs_driver, ti_mmchs_devclass, 0, 0);
+MODULE_DEPEND(ti_mmchs, ti_prcm, 1, 1, 1);
+#ifdef SOC_TI_AM335X
+MODULE_DEPEND(ti_mmchs, ti_edma, 1, 1, 1);
+#else
+MODULE_DEPEND(ti_mmchs, ti_sdma, 1, 1, 1);
+#endif
+MODULE_DEPEND(ti_mmchs, ti_gpio, 1, 1, 1);
+
+/* FIXME: MODULE_DEPEND(ti_mmchs, twl_vreg, 1, 1, 1); */
Property changes on: trunk/sys/arm/ti/ti_mmchs.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_mmchs.h
===================================================================
--- trunk/sys/arm/ti/ti_mmchs.h (rev 0)
+++ trunk/sys/arm/ti/ti_mmchs.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,177 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_mmchs.h 252863 2013-07-06 04:18:34Z rpaulo $
+ */
+#ifndef _TI_MMCHS_H_
+#define _TI_MMCHS_H_
+
+/**
+ * Header file for the TI MMC/SD/SDIO driver.
+ *
+ * Simply contains register addresses and bit flags.
+ */
+
+/* Register offsets within each of the MMC/SD/SDIO controllers */
+#define MMCHS_SYSCONFIG 0x010
+#define MMCHS_SYSSTATUS 0x014
+#define MMCHS_CSRE 0x024
+#define MMCHS_SYSTEST 0x028
+#define MMCHS_CON 0x02C
+#define MMCHS_PWCNT 0x030
+#define MMCHS_BLK 0x104
+#define MMCHS_ARG 0x108
+#define MMCHS_CMD 0x10C
+#define MMCHS_RSP10 0x110
+#define MMCHS_RSP32 0x114
+#define MMCHS_RSP54 0x118
+#define MMCHS_RSP76 0x11C
+#define MMCHS_DATA 0x120
+#define MMCHS_PSTATE 0x124
+#define MMCHS_HCTL 0x128
+#define MMCHS_SYSCTL 0x12C
+#define MMCHS_STAT 0x130
+#define MMCHS_IE 0x134
+#define MMCHS_ISE 0x138
+#define MMCHS_AC12 0x13C
+#define MMCHS_CAPA 0x140
+#define MMCHS_CUR_CAPA 0x148
+#define MMCHS_REV 0x1FC
+
+/* OMAP4 and OMAP4 have different register addresses */
+#define OMAP3_MMCHS_REG_OFFSET 0x000
+#define OMAP4_MMCHS_REG_OFFSET 0x100
+#define AM335X_MMCHS_REG_OFFSET 0x100
+
+/* Register bit settings */
+#define MMCHS_SYSCONFIG_CLK_FUN (2 << 8)
+#define MMCHS_SYSCONFIG_CLK_IFC (1 << 8)
+#define MMCHS_SYSCONFIG_SIDL (2 << 3)
+#define MMCHS_SYSCONFIG_ENW (1 << 2)
+#define MMCHS_SYSCONFIG_SRST (1 << 1)
+#define MMCHS_SYSCONFIG_AIDL (1 << 0)
+#define MMCHS_STAT_BADA (1UL << 29)
+#define MMCHS_STAT_CERR (1UL << 28)
+#define MMCHS_STAT_ACE (1UL << 24)
+#define MMCHS_STAT_DEB (1UL << 22)
+#define MMCHS_STAT_DCRC (1UL << 21)
+#define MMCHS_STAT_DTO (1UL << 20)
+#define MMCHS_STAT_CIE (1UL << 19)
+#define MMCHS_STAT_CEB (1UL << 18)
+#define MMCHS_STAT_CCRC (1UL << 17)
+#define MMCHS_STAT_CTO (1UL << 16)
+#define MMCHS_STAT_ERRI (1UL << 15)
+#define MMCHS_STAT_OBI (1UL << 9)
+#define MMCHS_STAT_CIRQ (1UL << 8)
+#define MMCHS_STAT_BRR (1UL << 5)
+#define MMCHS_STAT_BWR (1UL << 4)
+#define MMCHS_STAT_BGE (1UL << 2)
+#define MMCHS_STAT_TC (1UL << 1)
+#define MMCHS_STAT_CC (1UL << 0)
+
+#define MMCHS_STAT_CLEAR_MASK 0x3BFF8337UL
+
+#define MMCHS_SYSCTL_SRD (1UL << 26)
+#define MMCHS_SYSCTL_SRC (1UL << 25)
+#define MMCHS_SYSCTL_SRA (1UL << 24)
+#define MMCHS_SYSCTL_DTO(x) (((x) & 0xf) << 16)
+#define MMCHS_SYSCTL_DTO_MASK MMCHS_SYSCTL_DTO(0xf)
+#define MMCHS_SYSCTL_CLKD(x) (((x) & 0x3ff) << 6)
+#define MMCHS_SYSCTL_CLKD_MASK MMCHS_SYSCTL_CLKD(0x3ff)
+#define MMCHS_SYSCTL_CEN (1UL << 2)
+#define MMCHS_SYSCTL_ICS (1UL << 1)
+#define MMCHS_SYSCTL_ICE (1UL << 0)
+
+#define MMCHS_HCTL_OBWE (1UL << 27)
+#define MMCHS_HCTL_REM (1UL << 26)
+#define MMCHS_HCTL_INS (1UL << 25)
+#define MMCHS_HCTL_IWE (1UL << 24)
+#define MMCHS_HCTL_IBG (1UL << 19)
+#define MMCHS_HCTL_RWC (1UL << 18)
+#define MMCHS_HCTL_CR (1UL << 17)
+#define MMCHS_HCTL_SBGR (1UL << 16)
+#define MMCHS_HCTL_SDVS_MASK (7UL << 9)
+#define MMCHS_HCTL_SDVS_V18 (5UL << 9)
+#define MMCHS_HCTL_SDVS_V30 (6UL << 9)
+#define MMCHS_HCTL_SDVS_V33 (7UL << 9)
+#define MMCHS_HCTL_SDBP (1UL << 8)
+#define MMCHS_HCTL_DTW (1UL << 1)
+
+#define MMCHS_CAPA_VS18 (1UL << 26)
+#define MMCHS_CAPA_VS30 (1UL << 25)
+#define MMCHS_CAPA_VS33 (1UL << 24)
+
+#define MMCHS_CMD_CMD_TYPE_IO_ABORT (3UL << 21)
+#define MMCHS_CMD_CMD_TYPE_FUNC_SEL (2UL << 21)
+#define MMCHS_CMD_CMD_TYPE_SUSPEND (1UL << 21)
+#define MMCHS_CMD_CMD_TYPE_OTHERS (0UL << 21)
+#define MMCHS_CMD_CMD_TYPE_MASK (3UL << 22)
+
+#define MMCHS_CMD_DP (1UL << 21)
+#define MMCHS_CMD_CICE (1UL << 20)
+#define MMCHS_CMD_CCCE (1UL << 19)
+
+#define MMCHS_CMD_RSP_TYPE_MASK (3UL << 16)
+#define MMCHS_CMD_RSP_TYPE_NO (0UL << 16)
+#define MMCHS_CMD_RSP_TYPE_136 (1UL << 16)
+#define MMCHS_CMD_RSP_TYPE_48 (2UL << 16)
+#define MMCHS_CMD_RSP_TYPE_48_BSY (3UL << 16)
+
+#define MMCHS_CMD_MSBS (1UL << 5)
+#define MMCHS_CMD_DDIR (1UL << 4)
+#define MMCHS_CMD_ACEN (1UL << 2)
+#define MMCHS_CMD_BCE (1UL << 1)
+#define MMCHS_CMD_DE (1UL << 0)
+
+#define MMCHS_CON_CLKEXTFREE (1UL << 16)
+#define MMCHS_CON_PADEN (1UL << 15)
+#define MMCHS_CON_OBIE (1UL << 14)
+#define MMCHS_CON_OBIP (1UL << 13)
+#define MMCHS_CON_CEATA (1UL << 12)
+#define MMCHS_CON_CTPL (1UL << 11)
+
+#define MMCHS_CON_DVAL_8_4MS (3UL << 9)
+#define MMCHS_CON_DVAL_1MS (2UL << 9)
+#define MMCHS_CON_DVAL_231US (1UL << 9)
+#define MMCHS_CON_DVAL_33US (0UL << 9)
+#define MMCHS_CON_DVAL_MASK (3UL << 9)
+
+#define MMCHS_CON_WPP (1UL << 8)
+#define MMCHS_CON_CDP (1UL << 7)
+#define MMCHS_CON_MIT (1UL << 6)
+#define MMCHS_CON_DW8 (1UL << 5)
+#define MMCHS_CON_MODE (1UL << 4)
+#define MMCHS_CON_STR (1UL << 3)
+#define MMCHS_CON_HR (1UL << 2)
+#define MMCHS_CON_INIT (1UL << 1)
+#define MMCHS_CON_OD (1UL << 0)
+
+#define MMCHS_CAPA_VS18 (1UL << 26)
+#define MMCHS_CAPA_VS30 (1UL << 25)
+#define MMCHS_CAPA_VS33 (1UL << 24)
+
+#endif /* _TI_MMCHS_H_ */
Property changes on: trunk/sys/arm/ti/ti_mmchs.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_prcm.c
===================================================================
--- trunk/sys/arm/ti/ti_prcm.c (rev 0)
+++ trunk/sys/arm/ti/ti_prcm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,309 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Power, Reset and Clock Managment Module
+ *
+ * This is a very simple driver wrapper around the PRCM set of registers in
+ * the OMAP3 chip. It allows you to turn on and off things like the functional
+ * and interface clocks to the various on-chip modules.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_prcm.c 259329 2013-12-13 20:43:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <arm/ti/ti_prcm.h>
+
+/**
+ * ti_clk_devmap - Array of clock devices, should be defined one per SoC
+ *
+ * This array is typically defined in one of the targeted *_prcm_clk.c
+ * files and is specific to the given SoC platform. Each entry in the array
+ * corresponds to an individual clock device.
+ */
+extern struct ti_clock_dev ti_clk_devmap[];
+
+/**
+ * ti_prcm_clk_dev - returns a pointer to the clock device with given id
+ * @clk: the ID of the clock device to get
+ *
+ * Simply iterates through the clk_devmap global array and returns a pointer
+ * to the clock device if found.
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * The pointer to the clock device on success, on failure NULL is returned.
+ */
+static struct ti_clock_dev *
+ti_prcm_clk_dev(clk_ident_t clk)
+{
+ struct ti_clock_dev *clk_dev;
+
+ /* Find the clock within the devmap - it's a bit inefficent having a for
+ * loop for this, but this function should only called when a driver is
+ * being activated so IMHO not a big issue.
+ */
+ clk_dev = &(ti_clk_devmap[0]);
+ while (clk_dev->id != INVALID_CLK_IDENT) {
+ if (clk_dev->id == clk) {
+ return (clk_dev);
+ }
+ clk_dev++;
+ }
+
+ /* Sanity check we managed to find the clock */
+ printf("ti_prcm: Failed to find clock device (%d)\n", clk);
+ return (NULL);
+}
+
+/**
+ * ti_prcm_clk_valid - enables a clock for a particular module
+ * @clk: identifier for the module to enable, see ti_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
+ *
+ * This function can enable either a functional or interface clock.
+ *
+ * The real work done to enable the clock is really done in the callback
+ * function associated with the clock, this function is simply a wrapper
+ * around that.
+ *
+ * LOCKING:
+ * Internally locks the driver context.
+ *
+ * RETURNS:
+ * Returns 0 on success or positive error code on failure.
+ */
+int
+ti_prcm_clk_valid(clk_ident_t clk)
+{
+ int ret = 0;
+
+ if (ti_prcm_clk_dev(clk) == NULL)
+ ret = EINVAL;
+
+ return (ret);
+}
+
+
+/**
+ * ti_prcm_clk_enable - enables a clock for a particular module
+ * @clk: identifier for the module to enable, see ti_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
+ *
+ * This function can enable either a functional or interface clock.
+ *
+ * The real work done to enable the clock is really done in the callback
+ * function associated with the clock, this function is simply a wrapper
+ * around that.
+ *
+ * LOCKING:
+ * Internally locks the driver context.
+ *
+ * RETURNS:
+ * Returns 0 on success or positive error code on failure.
+ */
+int
+ti_prcm_clk_enable(clk_ident_t clk)
+{
+ struct ti_clock_dev *clk_dev;
+ int ret;
+
+ /* Find the clock within the devmap - it's a bit inefficent having a for
+ * loop for this, but this function should only called when a driver is
+ * being activated so IMHO not a big issue.
+ */
+ clk_dev = ti_prcm_clk_dev(clk);
+
+ /* Sanity check we managed to find the clock */
+ if (clk_dev == NULL)
+ return (EINVAL);
+
+ /* Activate the clock */
+ if (clk_dev->clk_activate)
+ ret = clk_dev->clk_activate(clk_dev);
+ else
+ ret = EINVAL;
+
+ return (ret);
+}
+
+
+/**
+ * ti_prcm_clk_disable - disables a clock for a particular module
+ * @clk: identifier for the module to enable, see ti_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
+ *
+ * This function can enable either a functional or interface clock.
+ *
+ * The real work done to enable the clock is really done in the callback
+ * function associated with the clock, this function is simply a wrapper
+ * around that.
+ *
+ * LOCKING:
+ * Internally locks the driver context.
+ *
+ * RETURNS:
+ * Returns 0 on success or positive error code on failure.
+ */
+int
+ti_prcm_clk_disable(clk_ident_t clk)
+{
+ struct ti_clock_dev *clk_dev;
+ int ret;
+
+ /* Find the clock within the devmap - it's a bit inefficent having a for
+ * loop for this, but this function should only called when a driver is
+ * being activated so IMHO not a big issue.
+ */
+ clk_dev = ti_prcm_clk_dev(clk);
+
+ /* Sanity check we managed to find the clock */
+ if (clk_dev == NULL)
+ return (EINVAL);
+
+ /* Activate the clock */
+ if (clk_dev->clk_deactivate)
+ ret = clk_dev->clk_deactivate(clk_dev);
+ else
+ ret = EINVAL;
+
+ return (ret);
+}
+
+/**
+ * ti_prcm_clk_set_source - sets the source
+ * @clk: identifier for the module to enable, see ti_prcm.h for a list
+ * of possible modules.
+ * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
+ *
+ * This function can enable either a functional or interface clock.
+ *
+ * The real work done to enable the clock is really done in the callback
+ * function associated with the clock, this function is simply a wrapper
+ * around that.
+ *
+ * LOCKING:
+ * Internally locks the driver context.
+ *
+ * RETURNS:
+ * Returns 0 on success or positive error code on failure.
+ */
+int
+ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc)
+{
+ struct ti_clock_dev *clk_dev;
+ int ret;
+
+ /* Find the clock within the devmap - it's a bit inefficent having a for
+ * loop for this, but this function should only called when a driver is
+ * being activated so IMHO not a big issue.
+ */
+ clk_dev = ti_prcm_clk_dev(clk);
+
+ /* Sanity check we managed to find the clock */
+ if (clk_dev == NULL)
+ return (EINVAL);
+
+ /* Activate the clock */
+ if (clk_dev->clk_set_source)
+ ret = clk_dev->clk_set_source(clk_dev, clksrc);
+ else
+ ret = EINVAL;
+
+ return (ret);
+}
+
+
+/**
+ * ti_prcm_clk_get_source_freq - gets the source clock frequency
+ * @clk: identifier for the module to enable, see ti_prcm.h for a list
+ * of possible modules.
+ * @freq: pointer to an integer that upon return will contain the src freq
+ *
+ * This function returns the frequency of the source clock.
+ *
+ * The real work done to enable the clock is really done in the callback
+ * function associated with the clock, this function is simply a wrapper
+ * around that.
+ *
+ * LOCKING:
+ * Internally locks the driver context.
+ *
+ * RETURNS:
+ * Returns 0 on success or positive error code on failure.
+ */
+int
+ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq)
+{
+ struct ti_clock_dev *clk_dev;
+ int ret;
+
+ /* Find the clock within the devmap - it's a bit inefficent having a for
+ * loop for this, but this function should only called when a driver is
+ * being activated so IMHO not a big issue.
+ */
+ clk_dev = ti_prcm_clk_dev(clk);
+
+ /* Sanity check we managed to find the clock */
+ if (clk_dev == NULL)
+ return (EINVAL);
+
+ /* Get the source frequency of the clock */
+ if (clk_dev->clk_get_source_freq)
+ ret = clk_dev->clk_get_source_freq(clk_dev, freq);
+ else
+ ret = EINVAL;
+
+ return (ret);
+}
Property changes on: trunk/sys/arm/ti/ti_prcm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_prcm.h
===================================================================
--- trunk/sys/arm/ti/ti_prcm.h (rev 0)
+++ trunk/sys/arm/ti/ti_prcm.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,212 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_prcm.h 278079 2015-02-02 12:48:13Z loos $
+ */
+
+
+/*
+ * Texas Instruments - OMAP3xxx series processors
+ *
+ * Reference:
+ * OMAP35x Applications Processor
+ * Technical Reference Manual
+ * (omap35xx_techref.pdf)
+ */
+#ifndef _TI_PRCM_H_
+#define _TI_PRCM_H_
+
+typedef enum {
+
+ /* System clocks, typically you can only call ti_prcm_clk_get_source_freq()
+ * on these clocks as they are enabled by default.
+ */
+ SYS_CLK = 1,
+
+ /* The MPU (ARM) core clock */
+ MPU_CLK = 20,
+
+ /* MMC modules */
+ MMC0_CLK = 100,
+ MMC1_CLK,
+ MMC2_CLK,
+ MMC3_CLK,
+ MMC4_CLK,
+ MMC5_CLK,
+
+ /* I2C modules */
+ I2C0_CLK = 200,
+ I2C1_CLK,
+ I2C2_CLK,
+ I2C3_CLK,
+ I2C4_CLK,
+
+ /* USB module(s) */
+ USBTLL_CLK = 300,
+ USBHSHOST_CLK,
+ USBFSHOST_CLK,
+ USBP1_PHY_CLK,
+ USBP2_PHY_CLK,
+ USBP1_UTMI_CLK,
+ USBP2_UTMI_CLK,
+ USBP1_HSIC_CLK,
+ USBP2_HSIC_CLK,
+
+ /* UART modules */
+ UART0_CLK = 400,
+ UART1_CLK,
+ UART2_CLK,
+ UART3_CLK,
+ UART4_CLK,
+ UART5_CLK,
+ UART6_CLK,
+ UART7_CLK,
+ UART8_CLK,
+
+ /* General purpose timer modules */
+ GPTIMER1_CLK = 500,
+ GPTIMER2_CLK,
+ GPTIMER3_CLK,
+ GPTIMER4_CLK,
+ GPTIMER5_CLK,
+ GPTIMER6_CLK,
+ GPTIMER7_CLK,
+ GPTIMER8_CLK,
+ GPTIMER9_CLK,
+ GPTIMER10_CLK,
+ GPTIMER11_CLK,
+ GPTIMER12_CLK,
+
+ /* McBSP module(s) */
+ MCBSP1_CLK = 600,
+ MCBSP2_CLK,
+ MCBSP3_CLK,
+ MCBSP4_CLK,
+ MCBSP5_CLK,
+
+ /* General purpose I/O modules */
+ GPIO0_CLK = 700,
+ GPIO1_CLK,
+ GPIO2_CLK,
+ GPIO3_CLK,
+ GPIO4_CLK,
+ GPIO5_CLK,
+ GPIO6_CLK,
+
+ /* sDMA module */
+ SDMA_CLK = 800,
+
+ /* DMTimer modules */
+ DMTIMER0_CLK = 900,
+ DMTIMER1_CLK,
+ DMTIMER2_CLK,
+ DMTIMER3_CLK,
+ DMTIMER4_CLK,
+ DMTIMER5_CLK,
+ DMTIMER6_CLK,
+ DMTIMER7_CLK,
+
+ /* CPSW modules */
+ CPSW_CLK = 1000,
+
+ /* Mentor USB modules */
+ MUSB0_CLK = 1100,
+
+ /* EDMA module */
+ EDMA_TPCC_CLK = 1200,
+ EDMA_TPTC0_CLK,
+ EDMA_TPTC1_CLK,
+ EDMA_TPTC2_CLK,
+
+ /* LCD controller module */
+ LCDC_CLK = 1300,
+
+ /* PWM modules */
+ PWMSS0_CLK = 1400,
+ PWMSS1_CLK,
+ PWMSS2_CLK,
+
+ /* Mailbox modules */
+ MAILBOX0_CLK = 1500,
+
+ /* Spinlock modules */
+ SPINLOCK0_CLK = 1600,
+
+ PRUSS_CLK = 1700,
+
+ TSC_ADC_CLK = 1800,
+
+ /* RTC module */
+ RTC_CLK = 1900,
+
+ INVALID_CLK_IDENT
+
+} clk_ident_t;
+
+/*
+ *
+ */
+typedef enum {
+ SYSCLK_CLK, /* System clock */
+ EXT_CLK,
+
+ F32KHZ_CLK, /* 32KHz clock */
+ F48MHZ_CLK, /* 48MHz clock */
+ F64MHZ_CLK, /* 64MHz clock */
+ F96MHZ_CLK, /* 96MHz clock */
+
+} clk_src_t;
+
+struct ti_clock_dev {
+ /* The profile of the timer */
+ clk_ident_t id;
+
+ /* A bunch of callbacks associated with the clock device */
+ int (*clk_activate)(struct ti_clock_dev *clkdev);
+ int (*clk_deactivate)(struct ti_clock_dev *clkdev);
+ int (*clk_set_source)(struct ti_clock_dev *clkdev,
+ clk_src_t clksrc);
+ int (*clk_accessible)(struct ti_clock_dev *clkdev);
+ int (*clk_get_source_freq)(struct ti_clock_dev *clkdev,
+ unsigned int *freq);
+};
+
+int ti_prcm_clk_valid(clk_ident_t clk);
+int ti_prcm_clk_enable(clk_ident_t clk);
+int ti_prcm_clk_disable(clk_ident_t clk);
+int ti_prcm_clk_accessible(clk_ident_t clk);
+int ti_prcm_clk_disable_autoidle(clk_ident_t clk);
+int ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc);
+int ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq);
+void ti_prcm_reset(void);
+
+#endif /* _TI_PRCM_H_ */
Property changes on: trunk/sys/arm/ti/ti_prcm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_pruss.c
===================================================================
--- trunk/sys/arm/ti/ti_pruss.c (rev 0)
+++ trunk/sys/arm/ti/ti_pruss.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,307 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Rui Paulo <rpaulo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_pruss.c 278432 2015-02-09 02:49:10Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/event.h>
+#include <sys/selinfo.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_pruss.h>
+
+#define DEBUG
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) do { \
+ printf("%s: ", __func__); \
+ printf(fmt, __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+static device_probe_t ti_pruss_probe;
+static device_attach_t ti_pruss_attach;
+static device_detach_t ti_pruss_detach;
+static void ti_pruss_intr(void *);
+static d_open_t ti_pruss_open;
+static d_mmap_t ti_pruss_mmap;
+static void ti_pruss_kq_read_detach(struct knote *);
+static int ti_pruss_kq_read_event(struct knote *, long);
+static d_kqfilter_t ti_pruss_kqfilter;
+
+#define TI_PRUSS_IRQS 8
+struct ti_pruss_softc {
+ struct mtx sc_mtx;
+ struct resource *sc_mem_res;
+ struct resource *sc_irq_res[TI_PRUSS_IRQS];
+ void *sc_intr[TI_PRUSS_IRQS];
+ bus_space_tag_t sc_bt;
+ bus_space_handle_t sc_bh;
+ struct cdev *sc_pdev;
+ struct selinfo sc_selinfo;
+};
+
+static struct cdevsw ti_pruss_cdevsw = {
+ .d_version = D_VERSION,
+ .d_name = "ti_pruss",
+ .d_open = ti_pruss_open,
+ .d_mmap = ti_pruss_mmap,
+ .d_kqfilter = ti_pruss_kqfilter,
+};
+
+static device_method_t ti_pruss_methods[] = {
+ DEVMETHOD(device_probe, ti_pruss_probe),
+ DEVMETHOD(device_attach, ti_pruss_attach),
+ DEVMETHOD(device_detach, ti_pruss_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t ti_pruss_driver = {
+ "ti_pruss",
+ ti_pruss_methods,
+ sizeof(struct ti_pruss_softc)
+};
+
+static devclass_t ti_pruss_devclass;
+
+DRIVER_MODULE(ti_pruss, simplebus, ti_pruss_driver, ti_pruss_devclass, 0, 0);
+
+static struct resource_spec ti_pruss_irq_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { SYS_RES_IRQ, 4, RF_ACTIVE },
+ { SYS_RES_IRQ, 5, RF_ACTIVE },
+ { SYS_RES_IRQ, 6, RF_ACTIVE },
+ { SYS_RES_IRQ, 7, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+static struct ti_pruss_irq_arg {
+ int irq;
+ struct ti_pruss_softc *sc;
+} ti_pruss_irq_args[TI_PRUSS_IRQS];
+
+static __inline uint32_t
+ti_pruss_reg_read(struct ti_pruss_softc *sc, uint32_t reg)
+{
+ return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
+}
+
+static __inline void
+ti_pruss_reg_write(struct ti_pruss_softc *sc, uint32_t reg, uint32_t val)
+{
+ bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
+}
+
+static int
+ti_pruss_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "ti,pruss-v1") ||
+ ofw_bus_is_compatible(dev, "ti,pruss-v2")) {
+ device_set_desc(dev, "TI Programmable Realtime Unit Subsystem");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+ti_pruss_attach(device_t dev)
+{
+ struct ti_pruss_softc *sc;
+ int rid, i;
+
+ if (ti_prcm_clk_enable(PRUSS_CLK) != 0) {
+ device_printf(dev, "could not enable PRUSS clock\n");
+ return (ENXIO);
+ }
+ sc = device_get_softc(dev);
+ rid = 0;
+ mtx_init(&sc->sc_mtx, "TI PRUSS", NULL, MTX_DEF);
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+ sc->sc_bt = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bh = rman_get_bushandle(sc->sc_mem_res);
+ if (bus_alloc_resources(dev, ti_pruss_irq_spec, sc->sc_irq_res) != 0) {
+ device_printf(dev, "could not allocate interrupt resource\n");
+ ti_pruss_detach(dev);
+ return (ENXIO);
+ }
+ for (i = 0; i < TI_PRUSS_IRQS; i++) {
+ ti_pruss_irq_args[i].irq = i;
+ ti_pruss_irq_args[i].sc = sc;
+ if (bus_setup_intr(dev, sc->sc_irq_res[i],
+ INTR_MPSAFE | INTR_TYPE_MISC,
+ NULL, ti_pruss_intr, &ti_pruss_irq_args[i],
+ &sc->sc_intr[i]) != 0) {
+ device_printf(dev,
+ "unable to setup the interrupt handler\n");
+ ti_pruss_detach(dev);
+ return (ENXIO);
+ }
+ }
+ if (ti_pruss_reg_read(sc, PRUSS_AM18XX_INTC) == PRUSS_AM18XX_REV)
+ device_printf(dev, "AM18xx PRU-ICSS\n");
+ else if (ti_pruss_reg_read(sc, PRUSS_AM33XX_INTC) == PRUSS_AM33XX_REV)
+ device_printf(dev, "AM33xx PRU-ICSS\n");
+
+ sc->sc_pdev = make_dev(&ti_pruss_cdevsw, 0, UID_ROOT, GID_WHEEL,
+ 0600, "pruss%d", device_get_unit(dev));
+ sc->sc_pdev->si_drv1 = dev;
+
+ return (0);
+}
+
+static int
+ti_pruss_detach(device_t dev)
+{
+ struct ti_pruss_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < TI_PRUSS_IRQS; i++) {
+ if (sc->sc_intr[i])
+ bus_teardown_intr(dev, sc->sc_irq_res[i], sc->sc_intr[i]);
+ if (sc->sc_irq_res[i])
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->sc_irq_res[i]),
+ sc->sc_irq_res[i]);
+ }
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_mem_res),
+ sc->sc_mem_res);
+ if (sc->sc_pdev)
+ destroy_dev(sc->sc_pdev);
+
+ return (0);
+}
+
+static void
+ti_pruss_intr(void *arg)
+{
+ struct ti_pruss_irq_arg *iap;
+ struct ti_pruss_softc *sc;
+
+ iap = arg;
+ sc = iap->sc;
+ DPRINTF("interrupt %p", sc);
+ KNOTE_UNLOCKED(&sc->sc_selinfo.si_note, iap->irq);
+}
+
+static int
+ti_pruss_open(struct cdev *cdev __unused, int oflags __unused,
+ int devtype __unused, struct thread *td __unused)
+{
+ return (0);
+}
+
+static int
+ti_pruss_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int nprot, vm_memattr_t *memattr)
+{
+ device_t dev = cdev->si_drv1;
+ struct ti_pruss_softc *sc = device_get_softc(dev);
+
+ if (offset > rman_get_size(sc->sc_mem_res))
+ return (-1);
+ *paddr = rman_get_start(sc->sc_mem_res) + offset;
+ *memattr = VM_MEMATTR_UNCACHEABLE;
+
+ return (0);
+}
+
+static struct filterops ti_pruss_kq_read = {
+ .f_isfd = 1,
+ .f_detach = ti_pruss_kq_read_detach,
+ .f_event = ti_pruss_kq_read_event,
+};
+
+static void
+ti_pruss_kq_read_detach(struct knote *kn)
+{
+ struct ti_pruss_softc *sc = kn->kn_hook;
+
+ knlist_remove(&sc->sc_selinfo.si_note, kn, 0);
+}
+
+static int
+ti_pruss_kq_read_event(struct knote *kn, long hint)
+{
+ kn->kn_data = hint;
+
+ return (hint);
+}
+
+static int
+ti_pruss_kqfilter(struct cdev *cdev, struct knote *kn)
+{
+ device_t dev = cdev->si_drv1;
+ struct ti_pruss_softc *sc = device_get_softc(dev);
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_hook = sc;
+ kn->kn_fop = &ti_pruss_kq_read;
+ knlist_add(&sc->sc_selinfo.si_note, kn, 1);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
Property changes on: trunk/sys/arm/ti/ti_pruss.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_pruss.h
===================================================================
--- trunk/sys/arm/ti/ti_pruss.h (rev 0)
+++ trunk/sys/arm/ti/ti_pruss.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Rui Paulo <rpaulo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_pruss.h 266098 2014-05-14 23:57:07Z ian $
+ */
+#ifndef _TI_PRUSS_H_
+#define _TI_PRUSS_H_
+
+#define PRUSS_AM18XX_INTC 0x04000
+#define PRUSS_AM18XX_REV 0x4e825900
+#define PRUSS_AM33XX_REV 0x4e82A900
+#define PRUSS_AM33XX_INTC 0x20000
+
+#endif /* _TI_PRUSS_H_ */
Property changes on: trunk/sys/arm/ti/ti_pruss.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_scm.c
===================================================================
--- trunk/sys/arm/ti/ti_scm.c (rev 0)
+++ trunk/sys/arm/ti/ti_scm.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,504 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * SCM - System Control Module
+ *
+ * Hopefully in the end this module will contain a bunch of utility functions
+ * for configuring and querying the general system control registers, but for
+ * now it only does pin(pad) multiplexing.
+ *
+ * This is different from the GPIO module in that it is used to configure the
+ * pins between modules not just GPIO input/output.
+ *
+ * This file contains the generic top level driver, however it relies on chip
+ * specific settings and therefore expects an array of ti_scm_padconf structs
+ * call ti_padconf_devmap to be located somewhere in the kernel.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_scm.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "ti_scm.h"
+
+static struct resource_spec ti_scm_res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */
+ { -1, 0 }
+};
+
+static struct ti_scm_softc *ti_scm_sc;
+
+#define ti_scm_read_2(sc, reg) \
+ bus_space_read_2((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define ti_scm_write_2(sc, reg, val) \
+ bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+#define ti_scm_read_4(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define ti_scm_write_4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+
+/**
+ * ti_padconf_devmap - Array of pins, should be defined one per SoC
+ *
+ * This array is typically defined in one of the targeted *_scm_pinumx.c
+ * files and is specific to the given SoC platform. Each entry in the array
+ * corresponds to an individual pin.
+ */
+extern const struct ti_scm_device ti_scm_dev;
+
+
+/**
+ * ti_scm_padconf_from_name - searches the list of pads and returns entry
+ * with matching ball name.
+ * @ballname: the name of the ball
+ *
+ * RETURNS:
+ * A pointer to the matching padconf or NULL if the ball wasn't found.
+ */
+static const struct ti_scm_padconf*
+ti_scm_padconf_from_name(const char *ballname)
+{
+ const struct ti_scm_padconf *padconf;
+
+ padconf = ti_scm_dev.padconf;
+ while (padconf->ballname != NULL) {
+ if (strcmp(ballname, padconf->ballname) == 0)
+ return(padconf);
+ padconf++;
+ }
+
+ return (NULL);
+}
+
+/**
+ * ti_scm_padconf_set_internal - sets the muxmode and state for a pad/pin
+ * @padconf: pointer to the pad structure
+ * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
+ * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+static int
+ti_scm_padconf_set_internal(struct ti_scm_softc *sc,
+ const struct ti_scm_padconf *padconf,
+ const char *muxmode, unsigned int state)
+{
+ unsigned int mode;
+ uint16_t reg_val;
+
+ /* populate the new value for the PADCONF register */
+ reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask);
+
+ /* find the new mode requested */
+ for (mode = 0; mode < 8; mode++) {
+ if ((padconf->muxmodes[mode] != NULL) &&
+ (strcmp(padconf->muxmodes[mode], muxmode) == 0)) {
+ break;
+ }
+ }
+
+ /* couldn't find the mux mode */
+ if (mode >= 8) {
+ printf("Invalid mode \"%s\"\n", muxmode);
+ return (EINVAL);
+ }
+
+ /* set the mux mode */
+ reg_val |= (uint16_t)(mode & ti_scm_dev.padconf_muxmode_mask);
+
+ if (bootverbose)
+ device_printf(sc->sc_dev, "setting internal %x for %s\n",
+ reg_val, muxmode);
+ /* write the register value (16-bit writes) */
+ ti_scm_write_2(sc, padconf->reg_off, reg_val);
+
+ return (0);
+}
+
+/**
+ * ti_scm_padconf_set - sets the muxmode and state for a pad/pin
+ * @padname: the name of the pad, i.e. "c12"
+ * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
+ * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+int
+ti_scm_padconf_set(const char *padname, const char *muxmode, unsigned int state)
+{
+ const struct ti_scm_padconf *padconf;
+
+ if (!ti_scm_sc)
+ return (ENXIO);
+
+ /* find the pin in the devmap */
+ padconf = ti_scm_padconf_from_name(padname);
+ if (padconf == NULL)
+ return (EINVAL);
+
+ return (ti_scm_padconf_set_internal(ti_scm_sc, padconf, muxmode, state));
+}
+
+/**
+ * ti_scm_padconf_get - gets the muxmode and state for a pad/pin
+ * @padname: the name of the pad, i.e. "c12"
+ * @muxmode: upon return will contain the name of the muxmode of the pin
+ * @state: upon return will contain the state of the pad/pin
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+int
+ti_scm_padconf_get(const char *padname, const char **muxmode,
+ unsigned int *state)
+{
+ const struct ti_scm_padconf *padconf;
+ uint16_t reg_val;
+
+ if (!ti_scm_sc)
+ return (ENXIO);
+
+ /* find the pin in the devmap */
+ padconf = ti_scm_padconf_from_name(padname);
+ if (padconf == NULL)
+ return (EINVAL);
+
+ /* read the register value (16-bit reads) */
+ reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off);
+
+ /* save the state */
+ if (state)
+ *state = (reg_val & ti_scm_dev.padconf_sate_mask);
+
+ /* save the mode */
+ if (muxmode)
+ *muxmode = padconf->muxmodes[(reg_val & ti_scm_dev.padconf_muxmode_mask)];
+
+ return (0);
+}
+
+/**
+ * ti_scm_padconf_set_gpiomode - converts a pad to GPIO mode.
+ * @gpio: the GPIO pin number (0-195)
+ * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
+ *
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+int
+ti_scm_padconf_set_gpiomode(uint32_t gpio, unsigned int state)
+{
+ const struct ti_scm_padconf *padconf;
+ uint16_t reg_val;
+
+ if (!ti_scm_sc)
+ return (ENXIO);
+
+ /* find the gpio pin in the padconf array */
+ padconf = ti_scm_dev.padconf;
+ while (padconf->ballname != NULL) {
+ if (padconf->gpio_pin == gpio)
+ break;
+ padconf++;
+ }
+ if (padconf->ballname == NULL)
+ return (EINVAL);
+
+ /* populate the new value for the PADCONF register */
+ reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask);
+
+ /* set the mux mode */
+ reg_val |= (uint16_t)(padconf->gpio_mode & ti_scm_dev.padconf_muxmode_mask);
+
+ /* write the register value (16-bit writes) */
+ ti_scm_write_2(ti_scm_sc, padconf->reg_off, reg_val);
+
+ return (0);
+}
+
+/**
+ * ti_scm_padconf_get_gpiomode - gets the current GPIO mode of the pin
+ * @gpio: the GPIO pin number (0-195)
+ * @state: upon return will contain the state
+ *
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or not configured as GPIO.
+ */
+int
+ti_scm_padconf_get_gpiomode(uint32_t gpio, unsigned int *state)
+{
+ const struct ti_scm_padconf *padconf;
+ uint16_t reg_val;
+
+ if (!ti_scm_sc)
+ return (ENXIO);
+
+ /* find the gpio pin in the padconf array */
+ padconf = ti_scm_dev.padconf;
+ while (padconf->ballname != NULL) {
+ if (padconf->gpio_pin == gpio)
+ break;
+ padconf++;
+ }
+ if (padconf->ballname == NULL)
+ return (EINVAL);
+
+ /* read the current register settings */
+ reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off);
+
+ /* check to make sure the pins is configured as GPIO in the first state */
+ if ((reg_val & ti_scm_dev.padconf_muxmode_mask) != padconf->gpio_mode)
+ return (EINVAL);
+
+ /* read and store the reset of the state, i.e. pull-up, pull-down, etc */
+ if (state)
+ *state = (reg_val & ti_scm_dev.padconf_sate_mask);
+
+ return (0);
+}
+
+/**
+ * ti_scm_padconf_init_from_hints - processes the hints for padconf
+ * @sc: the driver soft context
+ *
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+static int
+ti_scm_padconf_init_from_fdt(struct ti_scm_softc *sc)
+{
+ const struct ti_scm_padconf *padconf;
+ const struct ti_scm_padstate *padstates;
+ int err;
+ phandle_t node;
+ int len;
+ char *fdt_pad_config;
+ int i;
+ char *padname, *muxname, *padstate;
+
+ node = ofw_bus_get_node(sc->sc_dev);
+ len = OF_getproplen(node, "scm-pad-config");
+ OF_getprop_alloc(node, "scm-pad-config", 1, (void **)&fdt_pad_config);
+
+ i = len;
+ while (i > 0) {
+ padname = fdt_pad_config;
+ fdt_pad_config += strlen(padname) + 1;
+ i -= strlen(padname) + 1;
+ if (i <= 0)
+ break;
+
+ muxname = fdt_pad_config;
+ fdt_pad_config += strlen(muxname) + 1;
+ i -= strlen(muxname) + 1;
+ if (i <= 0)
+ break;
+
+ padstate = fdt_pad_config;
+ fdt_pad_config += strlen(padstate) + 1;
+ i -= strlen(padstate) + 1;
+ if (i < 0)
+ break;
+
+ padconf = ti_scm_dev.padconf;
+
+ while (padconf->ballname != NULL) {
+ if (strcmp(padconf->ballname, padname) == 0) {
+ padstates = ti_scm_dev.padstate;
+ err = 1;
+ while (padstates->state != NULL) {
+ if (strcmp(padstates->state, padstate) == 0) {
+ err = ti_scm_padconf_set_internal(sc,
+ padconf, muxname, padstates->reg);
+ }
+ padstates++;
+ }
+ if (err)
+ device_printf(sc->sc_dev,
+ "err: failed to configure "
+ "pin \"%s\" as \"%s\"\n",
+ padconf->ballname,
+ muxname);
+ }
+ padconf++;
+ }
+ }
+ return (0);
+}
+
+/*
+ * Device part of OMAP SCM driver
+ */
+
+static int
+ti_scm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,scm"))
+ return (ENXIO);
+
+ device_set_desc(dev, "TI Control Module");
+ return (BUS_PROBE_DEFAULT);
+}
+
+/**
+ * ti_scm_attach - attaches the timer to the simplebus
+ * @dev: new device
+ *
+ * Reserves memory and interrupt resources, stores the softc structure
+ * globally and registers both the timecount and eventtimer objects.
+ *
+ * RETURNS
+ * Zero on sucess or ENXIO if an error occuried.
+ */
+static int
+ti_scm_attach(device_t dev)
+{
+ struct ti_scm_softc *sc = device_get_softc(dev);
+
+ if (ti_scm_sc)
+ return (ENXIO);
+
+ sc->sc_dev = dev;
+
+ if (bus_alloc_resources(dev, ti_scm_res_spec, sc->sc_res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Global timer interface */
+ sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
+
+ ti_scm_sc = sc;
+
+ ti_scm_padconf_init_from_fdt(sc);
+
+ return (0);
+}
+
+int
+ti_scm_reg_read_4(uint32_t reg, uint32_t *val)
+{
+ if (!ti_scm_sc)
+ return (ENXIO);
+
+ *val = ti_scm_read_4(ti_scm_sc, reg);
+ return (0);
+}
+
+int
+ti_scm_reg_write_4(uint32_t reg, uint32_t val)
+{
+ if (!ti_scm_sc)
+ return (ENXIO);
+
+ ti_scm_write_4(ti_scm_sc, reg, val);
+ return (0);
+}
+
+
+static device_method_t ti_scm_methods[] = {
+ DEVMETHOD(device_probe, ti_scm_probe),
+ DEVMETHOD(device_attach, ti_scm_attach),
+ { 0, 0 }
+};
+
+static driver_t ti_scm_driver = {
+ "ti_scm",
+ ti_scm_methods,
+ sizeof(struct ti_scm_softc),
+};
+
+static devclass_t ti_scm_devclass;
+
+DRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, ti_scm_devclass, 0, 0);
Property changes on: trunk/sys/arm/ti/ti_scm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_scm.h
===================================================================
--- trunk/sys/arm/ti/ti_scm.h (rev 0)
+++ trunk/sys/arm/ti/ti_scm.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,85 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_scm.h 279467 2015-03-01 01:08:14Z dim $
+ */
+
+
+/**
+ * Functions to configure the PIN multiplexing on the chip.
+ *
+ * This is different from the GPIO module in that it is used to configure the
+ * pins between modules not just GPIO input output.
+ *
+ */
+#ifndef _TI_SCM_H_
+#define _TI_SCM_H_
+
+struct ti_scm_padconf {
+ uint16_t reg_off;
+ uint16_t gpio_pin;
+ uint16_t gpio_mode;
+ const char *ballname;
+ const char *muxmodes[8];
+};
+
+struct ti_scm_padstate {
+ const char *state;
+ uint16_t reg;
+};
+
+struct ti_scm_device {
+ uint16_t padconf_muxmode_mask;
+ uint16_t padconf_sate_mask;
+ const struct ti_scm_padstate *padstate;
+ const struct ti_scm_padconf *padconf;
+};
+
+struct ti_scm_softc {
+ device_t sc_dev;
+ struct resource * sc_res[4];
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+};
+
+int ti_scm_padconf_set(const char *padname, const char *muxmode,
+ unsigned int state);
+int ti_scm_padconf_get(const char *padname, const char **muxmode,
+ unsigned int *state);
+int ti_scm_padconf_set_gpiomode(uint32_t gpio, unsigned int state);
+int ti_scm_padconf_get_gpiomode(uint32_t gpio, unsigned int *state);
+int ti_scm_padconf_set_gpioflags(uint32_t gpio, uint32_t flags);
+void ti_scm_padconf_get_gpioflags(uint32_t gpio, uint32_t *flags);
+int ti_scm_reg_read_4(uint32_t reg, uint32_t *val);
+int ti_scm_reg_write_4(uint32_t reg, uint32_t val);
+
+#endif /* _TI_SCM_H_ */
Property changes on: trunk/sys/arm/ti/ti_scm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_sdhci.c
===================================================================
--- trunk/sys/arm/ti/ti_sdhci.c (rev 0)
+++ trunk/sys/arm/ti/ti_sdhci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,726 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore <ian at freebsd.org>
+ * Copyright (c) 2011 Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_sdhci.c 318198 2017-05-11 21:01:02Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcbrvar.h>
+
+#include <dev/sdhci/sdhci.h>
+#include "sdhci_if.h"
+
+#include <arm/ti/ti_cpuid.h>
+#include <arm/ti/ti_prcm.h>
+#include "gpio_if.h"
+
+struct ti_sdhci_softc {
+ device_t dev;
+ device_t gpio_dev;
+ struct resource * mem_res;
+ struct resource * irq_res;
+ void * intr_cookie;
+ struct sdhci_slot slot;
+ uint32_t mmchs_device_id;
+ uint32_t mmchs_reg_off;
+ uint32_t sdhci_reg_off;
+ uint32_t baseclk_hz;
+ uint32_t wp_gpio_pin;
+ uint32_t cmd_and_mode;
+ uint32_t sdhci_clkdiv;
+ boolean_t disable_highspeed;
+ boolean_t force_card_present;
+};
+
+/*
+ * Table of supported FDT compat strings.
+ *
+ * Note that "ti,mmchs" is our own invention, and should be phased out in favor
+ * of the documented names.
+ *
+ * Note that vendor Beaglebone dtsi files use "ti,omap3-hsmmc" for the am335x.
+ */
+static struct ofw_compat_data compat_data[] = {
+ {"ti,omap3-hsmmc", 1},
+ {"ti,omap4-hsmmc", 1},
+ {"ti,mmchs", 1},
+ {NULL, 0},
+};
+
+/*
+ * The MMCHS hardware has a few control and status registers at the beginning of
+ * the device's memory map, followed by the standard sdhci register block.
+ * Different SoCs have the register blocks at different offsets from the
+ * beginning of the device. Define some constants to map out the registers we
+ * access, and the various per-SoC offsets. The SDHCI_REG_OFFSET is how far
+ * beyond the MMCHS block the SDHCI block is found; it's the same on all SoCs.
+ */
+#define OMAP3_MMCHS_REG_OFFSET 0x000
+#define OMAP4_MMCHS_REG_OFFSET 0x100
+#define AM335X_MMCHS_REG_OFFSET 0x100
+#define SDHCI_REG_OFFSET 0x100
+
+#define MMCHS_SYSCONFIG 0x010
+#define MMCHS_SYSCONFIG_RESET (1 << 1)
+#define MMCHS_SYSSTATUS 0x014
+#define MMCHS_SYSSTATUS_RESETDONE (1 << 0)
+#define MMCHS_CON 0x02C
+#define MMCHS_CON_DW8 (1 << 5)
+#define MMCHS_CON_DVAL_8_4MS (3 << 9)
+#define MMCHS_CON_OD (1 << 0)
+#define MMCHS_SYSCTL 0x12C
+#define MMCHS_SYSCTL_CLKD_MASK 0x3FF
+#define MMCHS_SYSCTL_CLKD_SHIFT 6
+#define MMCHS_SD_CAPA 0x140
+#define MMCHS_SD_CAPA_VS18 (1 << 26)
+#define MMCHS_SD_CAPA_VS30 (1 << 25)
+#define MMCHS_SD_CAPA_VS33 (1 << 24)
+
+static inline uint32_t
+ti_mmchs_read_4(struct ti_sdhci_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off + sc->mmchs_reg_off));
+}
+
+static inline void
+ti_mmchs_write_4(struct ti_sdhci_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off + sc->mmchs_reg_off, val);
+}
+
+static inline uint32_t
+RD4(struct ti_sdhci_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off + sc->sdhci_reg_off));
+}
+
+static inline void
+WR4(struct ti_sdhci_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off + sc->sdhci_reg_off, val);
+}
+
+static uint8_t
+ti_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+
+ return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xff);
+}
+
+static uint16_t
+ti_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t clkdiv, val32;
+
+ /*
+ * The MMCHS hardware has a non-standard interpretation of the sdclock
+ * divisor bits. It uses the same bit positions as SDHCI 3.0 (15..6)
+ * but doesn't split them into low:high fields. Instead they're a
+ * single number in the range 0..1023 and the number is exactly the
+ * clock divisor (with 0 and 1 both meaning divide by 1). The SDHCI
+ * driver code expects a v2.0 or v3.0 divisor. The shifting and masking
+ * here extracts the MMCHS representation from the hardware word, cleans
+ * those bits out, applies the 2N adjustment, and plugs the result into
+ * the bit positions for the 2.0 or 3.0 divisor in the returned register
+ * value. The ti_sdhci_write_2() routine performs the opposite
+ * transformation when the SDHCI driver writes to the register.
+ */
+ if (off == SDHCI_CLOCK_CONTROL) {
+ val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
+ clkdiv = ((val32 >> MMCHS_SYSCTL_CLKD_SHIFT) &
+ MMCHS_SYSCTL_CLKD_MASK) / 2;
+ val32 &= ~(MMCHS_SYSCTL_CLKD_MASK << MMCHS_SYSCTL_CLKD_SHIFT);
+ val32 |= (clkdiv & SDHCI_DIVIDER_MASK) << SDHCI_DIVIDER_SHIFT;
+ if (slot->version >= SDHCI_SPEC_300)
+ val32 |= ((clkdiv >> SDHCI_DIVIDER_MASK_LEN) &
+ SDHCI_DIVIDER_HI_MASK) << SDHCI_DIVIDER_HI_SHIFT;
+ return (val32 & 0xffff);
+ }
+
+ /*
+ * Standard 32-bit handling of command and transfer mode.
+ */
+ if (off == SDHCI_TRANSFER_MODE) {
+ return (sc->cmd_and_mode >> 16);
+ } else if (off == SDHCI_COMMAND_FLAGS) {
+ return (sc->cmd_and_mode & 0x0000ffff);
+ }
+
+ return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xffff);
+}
+
+static uint32_t
+ti_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32;
+
+ val32 = RD4(sc, off);
+
+ /*
+ * If we need to disallow highspeed mode due to the OMAP4 erratum, strip
+ * that flag from the returned capabilities.
+ */
+ if (off == SDHCI_CAPABILITIES && sc->disable_highspeed)
+ val32 &= ~SDHCI_CAN_DO_HISPD;
+
+ /*
+ * Force the card-present state if necessary.
+ */
+ if (off == SDHCI_PRESENT_STATE && sc->force_card_present)
+ val32 |= SDHCI_CARD_PRESENT;
+
+ return (val32);
+}
+
+static void
+ti_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t *data, bus_size_t count)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+
+ bus_read_multi_4(sc->mem_res, off + sc->sdhci_reg_off, data, count);
+}
+
+static void
+ti_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint8_t val)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t val32;
+
+ val32 = RD4(sc, off & ~3);
+ val32 &= ~(0xff << (off & 3) * 8);
+ val32 |= (val << (off & 3) * 8);
+
+ WR4(sc, off & ~3, val32);
+}
+
+static void
+ti_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint16_t val)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+ uint32_t clkdiv, val32;
+
+ /*
+ * Translate between the hardware and SDHCI 2.0 or 3.0 representations
+ * of the clock divisor. See the comments in ti_sdhci_read_2() for
+ * details.
+ */
+ if (off == SDHCI_CLOCK_CONTROL) {
+ clkdiv = (val >> SDHCI_DIVIDER_SHIFT) & SDHCI_DIVIDER_MASK;
+ if (slot->version >= SDHCI_SPEC_300)
+ clkdiv |= ((val >> SDHCI_DIVIDER_HI_SHIFT) &
+ SDHCI_DIVIDER_HI_MASK) << SDHCI_DIVIDER_MASK_LEN;
+ clkdiv *= 2;
+ if (clkdiv > MMCHS_SYSCTL_CLKD_MASK)
+ clkdiv = MMCHS_SYSCTL_CLKD_MASK;
+ val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
+ val32 &= 0xffff0000;
+ val32 |= val & ~(MMCHS_SYSCTL_CLKD_MASK <<
+ MMCHS_SYSCTL_CLKD_SHIFT);
+ val32 |= clkdiv << MMCHS_SYSCTL_CLKD_SHIFT;
+ WR4(sc, SDHCI_CLOCK_CONTROL, val32);
+ return;
+ }
+
+ /*
+ * Standard 32-bit handling of command and transfer mode.
+ */
+ if (off == SDHCI_TRANSFER_MODE) {
+ sc->cmd_and_mode = (sc->cmd_and_mode & 0xffff0000) |
+ ((uint32_t)val & 0x0000ffff);
+ return;
+ } else if (off == SDHCI_COMMAND_FLAGS) {
+ sc->cmd_and_mode = (sc->cmd_and_mode & 0x0000ffff) |
+ ((uint32_t)val << 16);
+ WR4(sc, SDHCI_TRANSFER_MODE, sc->cmd_and_mode);
+ return;
+ }
+
+ val32 = RD4(sc, off & ~3);
+ val32 &= ~(0xffff << (off & 3) * 8);
+ val32 |= ((val & 0xffff) << (off & 3) * 8);
+ WR4(sc, off & ~3, val32);
+}
+
+static void
+ti_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t val)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+
+ WR4(sc, off, val);
+}
+
+static void
+ti_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t *data, bus_size_t count)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+
+ bus_write_multi_4(sc->mem_res, off + sc->sdhci_reg_off, data, count);
+}
+
+static void
+ti_sdhci_intr(void *arg)
+{
+ struct ti_sdhci_softc *sc = arg;
+
+ sdhci_generic_intr(&sc->slot);
+}
+
+static int
+ti_sdhci_update_ios(device_t brdev, device_t reqdev)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(brdev);
+ struct sdhci_slot *slot;
+ struct mmc_ios *ios;
+ uint32_t val32, newval32;
+
+ slot = device_get_ivars(reqdev);
+ ios = &slot->host.ios;
+
+ /*
+ * There is an 8-bit-bus bit in the MMCHS control register which, when
+ * set, overrides the 1 vs 4 bit setting in the standard SDHCI
+ * registers. Set that bit first according to whether an 8-bit bus is
+ * requested, then let the standard driver handle everything else.
+ */
+ val32 = ti_mmchs_read_4(sc, MMCHS_CON);
+ newval32 = val32;
+
+ if (ios->bus_width == bus_width_8)
+ newval32 |= MMCHS_CON_DW8;
+ else
+ newval32 &= ~MMCHS_CON_DW8;
+
+ if (ios->bus_mode == opendrain)
+ newval32 |= MMCHS_CON_OD;
+ else /* if (ios->bus_mode == pushpull) */
+ newval32 &= ~MMCHS_CON_OD;
+
+ if (newval32 != val32)
+ ti_mmchs_write_4(sc, MMCHS_CON, newval32);
+
+ return (sdhci_generic_update_ios(brdev, reqdev));
+}
+
+static int
+ti_sdhci_get_ro(device_t brdev, device_t reqdev)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(brdev);
+ unsigned int readonly = 0;
+
+ /* If a gpio pin is configured, read it. */
+ if (sc->gpio_dev != NULL) {
+ GPIO_PIN_GET(sc->gpio_dev, sc->wp_gpio_pin, &readonly);
+ }
+
+ return (readonly);
+}
+
+static int
+ti_sdhci_detach(device_t dev)
+{
+
+ return (EBUSY);
+}
+
+static void
+ti_sdhci_hw_init(device_t dev)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+ clk_ident_t clk;
+ uint32_t regval;
+ unsigned long timeout;
+
+ /* Enable the controller and interface/functional clocks */
+ clk = MMC0_CLK + sc->mmchs_device_id;
+ if (ti_prcm_clk_enable(clk) != 0) {
+ device_printf(dev, "Error: failed to enable MMC clock\n");
+ return;
+ }
+
+ /* Get the frequency of the source clock */
+ if (ti_prcm_clk_get_source_freq(clk, &sc->baseclk_hz) != 0) {
+ device_printf(dev, "Error: failed to get source clock freq\n");
+ return;
+ }
+
+ /* Issue a softreset to the controller */
+ ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, MMCHS_SYSCONFIG_RESET);
+ timeout = 1000;
+ while (!(ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) &
+ MMCHS_SYSSTATUS_RESETDONE)) {
+ if (--timeout == 0) {
+ device_printf(dev,
+ "Error: Controller reset operation timed out\n");
+ break;
+ }
+ DELAY(100);
+ }
+
+ /*
+ * Reset the command and data state machines and also other aspects of
+ * the controller such as bus clock and power.
+ *
+ * If we read the software reset register too fast after writing it we
+ * can get back a zero that means the reset hasn't started yet rather
+ * than that the reset is complete. Per TI recommendations, work around
+ * it by reading until we see the reset bit asserted, then read until
+ * it's clear. We also set the SDHCI_QUIRK_WAITFOR_RESET_ASSERTED quirk
+ * so that the main sdhci driver uses this same logic in its resets.
+ */
+ ti_sdhci_write_1(dev, NULL, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL);
+ timeout = 10000;
+ while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) &
+ SDHCI_RESET_ALL) != SDHCI_RESET_ALL) {
+ if (--timeout == 0) {
+ break;
+ }
+ DELAY(1);
+ }
+ timeout = 10000;
+ while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) &
+ SDHCI_RESET_ALL)) {
+ if (--timeout == 0) {
+ device_printf(dev,
+ "Error: Software reset operation timed out\n");
+ break;
+ }
+ DELAY(100);
+ }
+
+ /*
+ * The attach() routine has examined fdt data and set flags in
+ * slot.host.caps to reflect what voltages we can handle. Set those
+ * values in the CAPA register. The manual says that these values can
+ * only be set once, "before initialization" whatever that means, and
+ * that they survive a reset. So maybe doing this will be a no-op if
+ * u-boot has already initialized the hardware.
+ */
+ regval = ti_mmchs_read_4(sc, MMCHS_SD_CAPA);
+ if (sc->slot.host.caps & MMC_OCR_LOW_VOLTAGE)
+ regval |= MMCHS_SD_CAPA_VS18;
+ if (sc->slot.host.caps & (MMC_OCR_290_300 | MMC_OCR_300_310))
+ regval |= MMCHS_SD_CAPA_VS30;
+ ti_mmchs_write_4(sc, MMCHS_SD_CAPA, regval);
+
+ /* Set initial host configuration (1-bit, std speed, pwr off). */
+ ti_sdhci_write_1(dev, NULL, SDHCI_HOST_CONTROL, 0);
+ ti_sdhci_write_1(dev, NULL, SDHCI_POWER_CONTROL, 0);
+
+ /* Set the initial controller configuration. */
+ ti_mmchs_write_4(sc, MMCHS_CON, MMCHS_CON_DVAL_8_4MS);
+}
+
+static int
+ti_sdhci_attach(device_t dev)
+{
+ struct ti_sdhci_softc *sc = device_get_softc(dev);
+ int rid, err;
+ pcell_t prop;
+ phandle_t node;
+
+ sc->dev = dev;
+
+ /*
+ * Get the MMCHS device id from FDT. If it's not there use the newbus
+ * unit number (which will work as long as the devices are in order and
+ * none are skipped in the fdt). Note that this is a property we made
+ * up and added in freebsd, it doesn't exist in the published bindings.
+ */
+ node = ofw_bus_get_node(dev);
+ if ((OF_getprop(node, "mmchs-device-id", &prop, sizeof(prop))) <= 0) {
+ sc->mmchs_device_id = device_get_unit(dev);
+ device_printf(dev, "missing mmchs-device-id attribute in FDT, "
+ "using unit number (%d)", sc->mmchs_device_id);
+ } else
+ sc->mmchs_device_id = fdt32_to_cpu(prop);
+
+ /*
+ * The hardware can inherently do dual-voltage (1p8v, 3p0v) on the first
+ * device, and only 1p8v on other devices unless an external transceiver
+ * is used. The only way we could know about a transceiver is fdt data.
+ * Note that we have to do this before calling ti_sdhci_hw_init() so
+ * that it can set the right values in the CAPA register, which can only
+ * be done once and never reset.
+ */
+ sc->slot.host.caps |= MMC_OCR_LOW_VOLTAGE;
+ if (sc->mmchs_device_id == 0 || OF_hasprop(node, "ti,dual-volt")) {
+ sc->slot.host.caps |= MMC_OCR_290_300 | MMC_OCR_300_310;
+ }
+
+ /*
+ * See if we've got a GPIO-based write detect pin. This is not the
+ * standard documented property for this, we added it in freebsd.
+ */
+ if ((OF_getprop(node, "mmchs-wp-gpio-pin", &prop, sizeof(prop))) <= 0)
+ sc->wp_gpio_pin = 0xffffffff;
+ else
+ sc->wp_gpio_pin = fdt32_to_cpu(prop);
+
+ if (sc->wp_gpio_pin != 0xffffffff) {
+ sc->gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (sc->gpio_dev == NULL)
+ device_printf(dev, "Error: No GPIO device, "
+ "Write Protect pin will not function\n");
+ else
+ GPIO_PIN_SETFLAGS(sc->gpio_dev, sc->wp_gpio_pin,
+ GPIO_PIN_INPUT);
+ }
+
+ /*
+ * Set the offset from the device's memory start to the MMCHS registers.
+ * Also for OMAP4 disable high speed mode due to erratum ID i626.
+ */
+ if (ti_chip() == CHIP_OMAP_3)
+ sc->mmchs_reg_off = OMAP3_MMCHS_REG_OFFSET;
+ else if (ti_chip() == CHIP_OMAP_4) {
+ sc->mmchs_reg_off = OMAP4_MMCHS_REG_OFFSET;
+ sc->disable_highspeed = true;
+ } else if (ti_chip() == CHIP_AM335X)
+ sc->mmchs_reg_off = AM335X_MMCHS_REG_OFFSET;
+ else
+ panic("Unknown OMAP device\n");
+
+ /*
+ * The standard SDHCI registers are at a fixed offset (the same on all
+ * SoCs) beyond the MMCHS registers.
+ */
+ sc->sdhci_reg_off = sc->mmchs_reg_off + SDHCI_REG_OFFSET;
+
+ /* Resource setup. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, ti_sdhci_intr, sc, &sc->intr_cookie)) {
+ device_printf(dev, "cannot setup interrupt handler\n");
+ err = ENXIO;
+ goto fail;
+ }
+
+ /* Initialise the MMCHS hardware. */
+ ti_sdhci_hw_init(dev);
+
+ /*
+ * The capabilities register can only express base clock frequencies in
+ * the range of 0-63MHz for a v2.0 controller. Since our clock runs
+ * faster than that, the hardware sets the frequency to zero in the
+ * register. When the register contains zero, the sdhci driver expects
+ * slot.max_clk to already have the right value in it.
+ */
+ sc->slot.max_clk = sc->baseclk_hz;
+
+ /*
+ * The MMCHS timeout counter is based on the output sdclock. Tell the
+ * sdhci driver to recalculate the timeout clock whenever the output
+ * sdclock frequency changes.
+ */
+ sc->slot.quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
+
+ /*
+ * The MMCHS hardware shifts the 136-bit response data (in violation of
+ * the spec), so tell the sdhci driver not to do the same in software.
+ */
+ sc->slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE;
+
+ /*
+ * Reset bits are broken, have to wait to see the bits asserted
+ * before waiting to see them de-asserted.
+ */
+ sc->slot.quirks |= SDHCI_QUIRK_WAITFOR_RESET_ASSERTED;
+
+ /*
+ * The controller waits for busy responses.
+ */
+ sc->slot.quirks |= SDHCI_QUIRK_WAIT_WHILE_BUSY;
+
+ /*
+ * DMA is not really broken, I just haven't implemented it yet.
+ */
+ sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA;
+
+ /*
+ * Set up the hardware and go. Note that this sets many of the
+ * slot.host.* fields, so we have to do this before overriding any of
+ * those values based on fdt data, below.
+ */
+ sdhci_init_slot(dev, &sc->slot, 0);
+
+ /*
+ * The SDHCI controller doesn't realize it, but we can support 8-bit
+ * even though we're not a v3.0 controller. If there's an fdt bus-width
+ * property, honor it.
+ */
+ if (OF_getencprop(node, "bus-width", &prop, sizeof(prop)) > 0) {
+ sc->slot.host.caps &= ~(MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA);
+ switch (prop) {
+ case 8:
+ sc->slot.host.caps |= MMC_CAP_8_BIT_DATA;
+ /* FALLTHROUGH */
+ case 4:
+ sc->slot.host.caps |= MMC_CAP_4_BIT_DATA;
+ break;
+ case 1:
+ break;
+ default:
+ device_printf(dev, "Bad bus-width value %u\n", prop);
+ break;
+ }
+ }
+
+ /*
+ * If the slot is flagged with the non-removable property, set our flag
+ * to always force the SDHCI_CARD_PRESENT bit on.
+ */
+ node = ofw_bus_get_node(dev);
+ if (OF_hasprop(node, "non-removable"))
+ sc->force_card_present = true;
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ sdhci_start_slot(&sc->slot);
+
+ return (0);
+
+fail:
+ if (sc->intr_cookie)
+ bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie);
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (err);
+}
+
+static int
+ti_sdhci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "TI MMCHS (SDHCI 2.0)");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static device_method_t ti_sdhci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_sdhci_probe),
+ DEVMETHOD(device_attach, ti_sdhci_attach),
+ DEVMETHOD(device_detach, ti_sdhci_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
+ DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
+
+ /* MMC bridge interface */
+ DEVMETHOD(mmcbr_update_ios, ti_sdhci_update_ios),
+ DEVMETHOD(mmcbr_request, sdhci_generic_request),
+ DEVMETHOD(mmcbr_get_ro, ti_sdhci_get_ro),
+ DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host),
+ DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
+
+ /* SDHCI registers accessors */
+ DEVMETHOD(sdhci_read_1, ti_sdhci_read_1),
+ DEVMETHOD(sdhci_read_2, ti_sdhci_read_2),
+ DEVMETHOD(sdhci_read_4, ti_sdhci_read_4),
+ DEVMETHOD(sdhci_read_multi_4, ti_sdhci_read_multi_4),
+ DEVMETHOD(sdhci_write_1, ti_sdhci_write_1),
+ DEVMETHOD(sdhci_write_2, ti_sdhci_write_2),
+ DEVMETHOD(sdhci_write_4, ti_sdhci_write_4),
+ DEVMETHOD(sdhci_write_multi_4, ti_sdhci_write_multi_4),
+
+ DEVMETHOD_END
+};
+
+static devclass_t ti_sdhci_devclass;
+
+static driver_t ti_sdhci_driver = {
+ "sdhci_ti",
+ ti_sdhci_methods,
+ sizeof(struct ti_sdhci_softc),
+};
+
+DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, NULL,
+ NULL);
+MODULE_DEPEND(sdhci_ti, sdhci, 1, 1, 1);
+MMC_DECLARE_BRIDGE(sdhci_ti);
Property changes on: trunk/sys/arm/ti/ti_sdhci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_sdma.c
===================================================================
--- trunk/sys/arm/ti/ti_sdma.c (rev 0)
+++ trunk/sys/arm/ti/ti_sdma.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1251 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_sdma.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/interrupt.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/timetc.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_cpuid.h>
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sdma.h>
+#include <arm/ti/ti_sdmareg.h>
+
+/**
+ * Kernel functions for using the DMA controller
+ *
+ *
+ * DMA TRANSFERS:
+ * A DMA transfer block consists of a number of frames (FN). Each frame
+ * consists of a number of elements, and each element can have a size of 8, 16,
+ * or 32 bits.
+ *
+ * OMAP44xx and newer chips support linked list (aka scatter gather) transfers,
+ * where a linked list of source/destination pairs can be placed in memory
+ * for the H/W to process. Earlier chips only allowed you to chain multiple
+ * channels together. However currently this linked list feature is not
+ * supported by the driver.
+ *
+ */
+
+/**
+ * Data structure per DMA channel.
+ *
+ *
+ */
+struct ti_sdma_channel {
+
+ /*
+ * The configuration registers for the given channel, these are modified
+ * by the set functions and only written to the actual registers when a
+ * transaction is started.
+ */
+ uint32_t reg_csdp;
+ uint32_t reg_ccr;
+ uint32_t reg_cicr;
+
+ /* Set when one of the configuration registers above change */
+ uint32_t need_reg_write;
+
+ /* Callback function used when an interrupt is tripped on the given channel */
+ void (*callback)(unsigned int ch, uint32_t ch_status, void *data);
+
+ /* Callback data passed in the callback ... duh */
+ void* callback_data;
+
+};
+
+/**
+ * DMA driver context, allocated and stored globally, this driver is not
+ * intetned to ever be unloaded (see ti_sdma_sc).
+ *
+ */
+struct ti_sdma_softc {
+ device_t sc_dev;
+ struct resource* sc_irq_res;
+ struct resource* sc_mem_res;
+
+ /*
+ * I guess in theory we should have a mutex per DMA channel for register
+ * modifications. But since we know we are never going to be run on a SMP
+ * system, we can use just the single lock for all channels.
+ */
+ struct mtx sc_mtx;
+
+ /* Stores the H/W revision read from the registers */
+ uint32_t sc_hw_rev;
+
+ /*
+ * Bits in the sc_active_channels data field indicate if the channel has
+ * been activated.
+ */
+ uint32_t sc_active_channels;
+
+ struct ti_sdma_channel sc_channel[NUM_DMA_CHANNELS];
+
+};
+
+static struct ti_sdma_softc *ti_sdma_sc = NULL;
+
+/**
+ * Macros for driver mutex locking
+ */
+#define TI_SDMA_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
+#define TI_SDMA_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx)
+#define TI_SDMA_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ "ti_sdma", MTX_SPIN)
+#define TI_SDMA_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define TI_SDMA_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define TI_SDMA_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+/**
+ * Function prototypes
+ *
+ */
+static void ti_sdma_intr(void *);
+
+/**
+ * ti_sdma_read_4 - reads a 32-bit value from one of the DMA registers
+ * @sc: DMA device context
+ * @off: The offset of a register from the DMA register address range
+ *
+ *
+ * RETURNS:
+ * 32-bit value read from the register.
+ */
+static inline uint32_t
+ti_sdma_read_4(struct ti_sdma_softc *sc, bus_size_t off)
+{
+ return bus_read_4(sc->sc_mem_res, off);
+}
+
+/**
+ * ti_sdma_write_4 - writes a 32-bit value to one of the DMA registers
+ * @sc: DMA device context
+ * @off: The offset of a register from the DMA register address range
+ *
+ *
+ * RETURNS:
+ * 32-bit value read from the register.
+ */
+static inline void
+ti_sdma_write_4(struct ti_sdma_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->sc_mem_res, off, val);
+}
+
+/**
+ * ti_sdma_is_omap3_rev - returns true if H/W is from OMAP3 series
+ * @sc: DMA device context
+ *
+ */
+static inline int
+ti_sdma_is_omap3_rev(struct ti_sdma_softc *sc)
+{
+ return (sc->sc_hw_rev == DMA4_OMAP3_REV);
+}
+
+/**
+ * ti_sdma_is_omap4_rev - returns true if H/W is from OMAP4 series
+ * @sc: DMA device context
+ *
+ */
+static inline int
+ti_sdma_is_omap4_rev(struct ti_sdma_softc *sc)
+{
+ return (sc->sc_hw_rev == DMA4_OMAP4_REV);
+}
+
+/**
+ * ti_sdma_intr - interrupt handler for all 4 DMA IRQs
+ * @arg: ignored
+ *
+ * Called when any of the four DMA IRQs are triggered.
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+ti_sdma_intr(void *arg)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ uint32_t intr;
+ uint32_t csr;
+ unsigned int ch, j;
+ struct ti_sdma_channel* channel;
+
+ TI_SDMA_LOCK(sc);
+
+ for (j = 0; j < NUM_DMA_IRQS; j++) {
+
+ /* Get the flag interrupts (enabled) */
+ intr = ti_sdma_read_4(sc, DMA4_IRQSTATUS_L(j));
+ intr &= ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j));
+ if (intr == 0x00000000)
+ continue;
+
+ /* Loop through checking the status bits */
+ for (ch = 0; ch < NUM_DMA_CHANNELS; ch++) {
+ if (intr & (1 << ch)) {
+ channel = &sc->sc_channel[ch];
+
+ /* Read the CSR regsiter and verify we don't have a spurious IRQ */
+ csr = ti_sdma_read_4(sc, DMA4_CSR(ch));
+ if (csr == 0) {
+ device_printf(sc->sc_dev, "Spurious DMA IRQ for channel "
+ "%d\n", ch);
+ continue;
+ }
+
+ /* Sanity check this channel is active */
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ device_printf(sc->sc_dev, "IRQ %d for a non-activated "
+ "channel %d\n", j, ch);
+ continue;
+ }
+
+ /* Check the status error codes */
+ if (csr & DMA4_CSR_DROP)
+ device_printf(sc->sc_dev, "Synchronization event drop "
+ "occurred during the transfer on channel %u\n",
+ ch);
+ if (csr & DMA4_CSR_SECURE_ERR)
+ device_printf(sc->sc_dev, "Secure transaction error event "
+ "on channel %u\n", ch);
+ if (csr & DMA4_CSR_MISALIGNED_ADRS_ERR)
+ device_printf(sc->sc_dev, "Misaligned address error event "
+ "on channel %u\n", ch);
+ if (csr & DMA4_CSR_TRANS_ERR) {
+ device_printf(sc->sc_dev, "Transaction error event on "
+ "channel %u\n", ch);
+ /*
+ * Apparently according to linux code, there is an errata
+ * that says the channel is not disabled upon this error.
+ * They explicitly disable the channel here .. since I
+ * haven't seen the errata, I'm going to ignore for now.
+ */
+ }
+
+ /* Clear the status flags for the IRQ */
+ ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
+ ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
+
+ /* Call the callback for the given channel */
+ if (channel->callback)
+ channel->callback(ch, csr, channel->callback_data);
+ }
+ }
+ }
+
+ TI_SDMA_UNLOCK(sc);
+
+ return;
+}
+
+/**
+ * ti_sdma_activate_channel - activates a DMA channel
+ * @ch: upon return contains the channel allocated
+ * @callback: a callback function to associate with the channel
+ * @data: optional data supplied when the callback is called
+ *
+ * Simply activates a channel be enabling and writing default values to the
+ * channel's register set. It doesn't start a transaction, just populates the
+ * internal data structures and sets defaults.
+ *
+ * Note this function doesn't enable interrupts, for that you need to call
+ * ti_sdma_enable_channel_irq(). If not using IRQ to detect the end of the
+ * transfer, you can use ti_sdma_status_poll() to detect a change in the
+ * status.
+ *
+ * A channel must be activated before any of the other DMA functions can be
+ * called on it.
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * 0 on success, otherwise an error code
+ */
+int
+ti_sdma_activate_channel(unsigned int *ch,
+ void (*callback)(unsigned int ch, uint32_t status, void *data),
+ void *data)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ struct ti_sdma_channel *channel = NULL;
+ uint32_t addr;
+ unsigned int i;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ if (ch == NULL)
+ return (EINVAL);
+
+ TI_SDMA_LOCK(sc);
+
+ /* Check to see if all channels are in use */
+ if (sc->sc_active_channels == 0xffffffff) {
+ TI_SDMA_UNLOCK(sc);
+ return (ENOMEM);
+ }
+
+ /* Find the first non-active channel */
+ for (i = 0; i < NUM_DMA_CHANNELS; i++) {
+ if (!(sc->sc_active_channels & (0x1 << i))) {
+ sc->sc_active_channels |= (0x1 << i);
+ *ch = i;
+ break;
+ }
+ }
+
+ /* Get the channel struct and populate the fields */
+ channel = &sc->sc_channel[*ch];
+
+ channel->callback = callback;
+ channel->callback_data = data;
+
+ channel->need_reg_write = 1;
+
+ /* Set the default configuration for the DMA channel */
+ channel->reg_csdp = DMA4_CSDP_DATA_TYPE(0x2)
+ | DMA4_CSDP_SRC_BURST_MODE(0)
+ | DMA4_CSDP_DST_BURST_MODE(0)
+ | DMA4_CSDP_SRC_ENDIANISM(0)
+ | DMA4_CSDP_DST_ENDIANISM(0)
+ | DMA4_CSDP_WRITE_MODE(0)
+ | DMA4_CSDP_SRC_PACKED(0)
+ | DMA4_CSDP_DST_PACKED(0);
+
+ channel->reg_ccr = DMA4_CCR_DST_ADDRESS_MODE(1)
+ | DMA4_CCR_SRC_ADDRESS_MODE(1)
+ | DMA4_CCR_READ_PRIORITY(0)
+ | DMA4_CCR_WRITE_PRIORITY(0)
+ | DMA4_CCR_SYNC_TRIGGER(0)
+ | DMA4_CCR_FRAME_SYNC(0)
+ | DMA4_CCR_BLOCK_SYNC(0);
+
+ channel->reg_cicr = DMA4_CICR_TRANS_ERR_IE
+ | DMA4_CICR_SECURE_ERR_IE
+ | DMA4_CICR_SUPERVISOR_ERR_IE
+ | DMA4_CICR_MISALIGNED_ADRS_ERR_IE;
+
+ /* Clear all the channel registers, this should abort any transaction */
+ for (addr = DMA4_CCR(*ch); addr <= DMA4_COLOR(*ch); addr += 4)
+ ti_sdma_write_4(sc, addr, 0x00000000);
+
+ TI_SDMA_UNLOCK(sc);
+
+ return 0;
+}
+
+/**
+ * ti_sdma_deactivate_channel - deactivates a channel
+ * @ch: the channel to deactivate
+ *
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_deactivate_channel(unsigned int ch)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ unsigned int j;
+ unsigned int addr;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ /* First check if the channel is currently active */
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EBUSY);
+ }
+
+ /* Mark the channel as inactive */
+ sc->sc_active_channels &= ~(1 << ch);
+
+ /* Disable all DMA interrupts for the channel. */
+ ti_sdma_write_4(sc, DMA4_CICR(ch), 0);
+
+ /* Make sure the DMA transfer is stopped. */
+ ti_sdma_write_4(sc, DMA4_CCR(ch), 0);
+
+ /* Clear the CSR register and IRQ status register */
+ ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
+ for (j = 0; j < NUM_DMA_IRQS; j++) {
+ ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
+ }
+
+ /* Clear all the channel registers, this should abort any transaction */
+ for (addr = DMA4_CCR(ch); addr <= DMA4_COLOR(ch); addr += 4)
+ ti_sdma_write_4(sc, addr, 0x00000000);
+
+ TI_SDMA_UNLOCK(sc);
+
+ return 0;
+}
+
+/**
+ * ti_sdma_disable_channel_irq - disables IRQ's on the given channel
+ * @ch: the channel to disable IRQ's on
+ *
+ * Disable interupt generation for the given channel.
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_disable_channel_irq(unsigned int ch)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ uint32_t irq_enable;
+ unsigned int j;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* Disable all the individual error conditions */
+ sc->sc_channel[ch].reg_cicr = 0x0000;
+ ti_sdma_write_4(sc, DMA4_CICR(ch), 0x0000);
+
+ /* Disable the channel interrupt enable */
+ for (j = 0; j < NUM_DMA_IRQS; j++) {
+ irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j));
+ irq_enable &= ~(1 << ch);
+
+ ti_sdma_write_4(sc, DMA4_IRQENABLE_L(j), irq_enable);
+ }
+
+ /* Indicate the registers need to be rewritten on the next transaction */
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_sdma_disable_channel_irq - enables IRQ's on the given channel
+ * @ch: the channel to enable IRQ's on
+ * @flags: bitmask of interrupt types to enable
+ *
+ * Flags can be a bitmask of the following options:
+ * DMA_IRQ_FLAG_DROP
+ * DMA_IRQ_FLAG_HALF_FRAME_COMPL
+ * DMA_IRQ_FLAG_FRAME_COMPL
+ * DMA_IRQ_FLAG_START_LAST_FRAME
+ * DMA_IRQ_FLAG_BLOCK_COMPL
+ * DMA_IRQ_FLAG_ENDOF_PKT
+ * DMA_IRQ_FLAG_DRAIN
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_enable_channel_irq(unsigned int ch, uint32_t flags)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ uint32_t irq_enable;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* Always enable the error interrupts if we have interrupts enabled */
+ flags |= DMA4_CICR_TRANS_ERR_IE | DMA4_CICR_SECURE_ERR_IE |
+ DMA4_CICR_SUPERVISOR_ERR_IE | DMA4_CICR_MISALIGNED_ADRS_ERR_IE;
+
+ sc->sc_channel[ch].reg_cicr = flags;
+
+ /* Write the values to the register */
+ ti_sdma_write_4(sc, DMA4_CICR(ch), flags);
+
+ /* Enable the channel interrupt enable */
+ irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(0));
+ irq_enable |= (1 << ch);
+
+ ti_sdma_write_4(sc, DMA4_IRQENABLE_L(0), irq_enable);
+
+ /* Indicate the registers need to be rewritten on the next transaction */
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_sdma_get_channel_status - returns the status of a given channel
+ * @ch: the channel number to get the status of
+ * @status: upon return will contain the status bitmask, see below for possible
+ * values.
+ *
+ * DMA_STATUS_DROP
+ * DMA_STATUS_HALF
+ * DMA_STATUS_FRAME
+ * DMA_STATUS_LAST
+ * DMA_STATUS_BLOCK
+ * DMA_STATUS_SYNC
+ * DMA_STATUS_PKT
+ * DMA_STATUS_TRANS_ERR
+ * DMA_STATUS_SECURE_ERR
+ * DMA_STATUS_SUPERVISOR_ERR
+ * DMA_STATUS_MISALIGNED_ADRS_ERR
+ * DMA_STATUS_DRAIN_END
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_get_channel_status(unsigned int ch, uint32_t *status)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ uint32_t csr;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ TI_SDMA_UNLOCK(sc);
+
+ csr = ti_sdma_read_4(sc, DMA4_CSR(ch));
+
+ if (status != NULL)
+ *status = csr;
+
+ return (0);
+}
+
+/**
+ * ti_sdma_start_xfer - starts a DMA transfer
+ * @ch: the channel number to set the endianess of
+ * @src_paddr: the source phsyical address
+ * @dst_paddr: the destination phsyical address
+ * @frmcnt: the number of frames per block
+ * @elmcnt: the number of elements in a frame, an element is either an 8, 16
+ * or 32-bit value as defined by ti_sdma_set_xfer_burst()
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_start_xfer(unsigned int ch, unsigned int src_paddr,
+ unsigned long dst_paddr,
+ unsigned int frmcnt, unsigned int elmcnt)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ struct ti_sdma_channel *channel;
+ uint32_t ccr;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ channel = &sc->sc_channel[ch];
+
+ /* a) Write the CSDP register */
+ ti_sdma_write_4(sc, DMA4_CSDP(ch),
+ channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1));
+
+ /* b) Set the number of element per frame CEN[23:0] */
+ ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt);
+
+ /* c) Set the number of frame per block CFN[15:0] */
+ ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt);
+
+ /* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0] */
+ ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr);
+ ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr);
+
+ /* e) Write the CCR register */
+ ti_sdma_write_4(sc, DMA4_CCR(ch), channel->reg_ccr);
+
+ /* f) - Set the source element index increment CSEI[15:0] */
+ ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001);
+
+ /* - Set the source frame index increment CSFI[15:0] */
+ ti_sdma_write_4(sc, DMA4_CSF(ch), 0x0001);
+
+ /* - Set the destination element index increment CDEI[15:0]*/
+ ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001);
+
+ /* - Set the destination frame index increment CDFI[31:0] */
+ ti_sdma_write_4(sc, DMA4_CDF(ch), 0x0001);
+
+ /* Clear the status register */
+ ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE);
+
+ /* Write the start-bit and away we go */
+ ccr = ti_sdma_read_4(sc, DMA4_CCR(ch));
+ ccr |= (1 << 7);
+ ti_sdma_write_4(sc, DMA4_CCR(ch), ccr);
+
+ /* Clear the reg write flag */
+ channel->need_reg_write = 0;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_sdma_start_xfer_packet - starts a packet DMA transfer
+ * @ch: the channel number to use for the transfer
+ * @src_paddr: the source physical address
+ * @dst_paddr: the destination physical address
+ * @frmcnt: the number of frames to transfer
+ * @elmcnt: the number of elements in a frame, an element is either an 8, 16
+ * or 32-bit value as defined by ti_sdma_set_xfer_burst()
+ * @pktsize: the number of elements in each transfer packet
+ *
+ * The @frmcnt and @elmcnt define the overall number of bytes to transfer,
+ * typically @frmcnt is 1 and @elmcnt contains the total number of elements.
+ * @pktsize is the size of each individual packet, there might be multiple
+ * packets per transfer. i.e. for the following with element size of 32-bits
+ *
+ * frmcnt = 1, elmcnt = 512, pktsize = 128
+ *
+ * Total transfer bytes = 1 * 512 = 512 elements or 2048 bytes
+ * Packets transfered = 128 / 512 = 4
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_start_xfer_packet(unsigned int ch, unsigned int src_paddr,
+ unsigned long dst_paddr, unsigned int frmcnt,
+ unsigned int elmcnt, unsigned int pktsize)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ struct ti_sdma_channel *channel;
+ uint32_t ccr;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ channel = &sc->sc_channel[ch];
+
+ /* a) Write the CSDP register */
+ if (channel->need_reg_write)
+ ti_sdma_write_4(sc, DMA4_CSDP(ch),
+ channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1));
+
+ /* b) Set the number of elements to transfer CEN[23:0] */
+ ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt);
+
+ /* c) Set the number of frames to transfer CFN[15:0] */
+ ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt);
+
+ /* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0] */
+ ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr);
+ ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr);
+
+ /* e) Write the CCR register */
+ ti_sdma_write_4(sc, DMA4_CCR(ch),
+ channel->reg_ccr | DMA4_CCR_PACKET_TRANS);
+
+ /* f) - Set the source element index increment CSEI[15:0] */
+ ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001);
+
+ /* - Set the packet size, this is dependent on the sync source */
+ if (channel->reg_ccr & DMA4_CCR_SEL_SRC_DST_SYNC(1))
+ ti_sdma_write_4(sc, DMA4_CSF(ch), pktsize);
+ else
+ ti_sdma_write_4(sc, DMA4_CDF(ch), pktsize);
+
+ /* - Set the destination frame index increment CDFI[31:0] */
+ ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001);
+
+ /* Clear the status register */
+ ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE);
+
+ /* Write the start-bit and away we go */
+ ccr = ti_sdma_read_4(sc, DMA4_CCR(ch));
+ ccr |= (1 << 7);
+ ti_sdma_write_4(sc, DMA4_CCR(ch), ccr);
+
+ /* Clear the reg write flag */
+ channel->need_reg_write = 0;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_sdma_stop_xfer - stops any currently active transfers
+ * @ch: the channel number to set the endianess of
+ *
+ * This function call is effectively a NOP if no transaction is in progress.
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_stop_xfer(unsigned int ch)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ unsigned int j;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ /* Disable all DMA interrupts for the channel. */
+ ti_sdma_write_4(sc, DMA4_CICR(ch), 0);
+
+ /* Make sure the DMA transfer is stopped. */
+ ti_sdma_write_4(sc, DMA4_CCR(ch), 0);
+
+ /* Clear the CSR register and IRQ status register */
+ ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
+ for (j = 0; j < NUM_DMA_IRQS; j++) {
+ ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
+ }
+
+ /* Configuration registers need to be re-written on the next xfer */
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return (0);
+}
+
+/**
+ * ti_sdma_set_xfer_endianess - sets the endianess of subsequent transfers
+ * @ch: the channel number to set the endianess of
+ * @src: the source endianess (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG)
+ * @dst: the destination endianess (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG)
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_set_xfer_endianess(unsigned int ch, unsigned int src, unsigned int dst)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_ENDIANISM(1);
+ sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_ENDIANISM(src);
+
+ sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_ENDIANISM(1);
+ sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_ENDIANISM(dst);
+
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return 0;
+}
+
+/**
+ * ti_sdma_set_xfer_burst - sets the source and destination element size
+ * @ch: the channel number to set the burst settings of
+ * @src: the source endianess (either DMA_BURST_NONE, DMA_BURST_16, DMA_BURST_32
+ * or DMA_BURST_64)
+ * @dst: the destination endianess (either DMA_BURST_NONE, DMA_BURST_16,
+ * DMA_BURST_32 or DMA_BURST_64)
+ *
+ * This function sets the size of the elements for all subsequent transfers.
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_set_xfer_burst(unsigned int ch, unsigned int src, unsigned int dst)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_BURST_MODE(0x3);
+ sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_BURST_MODE(src);
+
+ sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_BURST_MODE(0x3);
+ sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_BURST_MODE(dst);
+
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return 0;
+}
+
+/**
+ * ti_sdma_set_xfer_data_type - driver attach function
+ * @ch: the channel number to set the endianess of
+ * @type: the xfer data type (either DMA_DATA_8BITS_SCALAR, DMA_DATA_16BITS_SCALAR
+ * or DMA_DATA_32BITS_SCALAR)
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_set_xfer_data_type(unsigned int ch, unsigned int type)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DATA_TYPE(0x3);
+ sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DATA_TYPE(type);
+
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return 0;
+}
+
+/**
+ * ti_sdma_set_callback - driver attach function
+ * @dev: dma device handle
+ *
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_set_callback(unsigned int ch,
+ void (*callback)(unsigned int ch, uint32_t status, void *data),
+ void *data)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ sc->sc_channel[ch].callback = callback;
+ sc->sc_channel[ch].callback_data = data;
+
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return 0;
+}
+
+/**
+ * ti_sdma_sync_params - sets channel sync settings
+ * @ch: the channel number to set the sync on
+ * @trigger: the number of the sync trigger, this depends on what other H/W
+ * module is triggering/receiving the DMA transactions
+ * @mode: flags describing the sync mode to use, it may have one or more of
+ * the following bits set; TI_SDMA_SYNC_FRAME,
+ * TI_SDMA_SYNC_BLOCK, TI_SDMA_SYNC_TRIG_ON_SRC.
+ *
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_sync_params(unsigned int ch, unsigned int trigger, unsigned int mode)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ uint32_t ccr;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ ccr = sc->sc_channel[ch].reg_ccr;
+
+ ccr &= ~DMA4_CCR_SYNC_TRIGGER(0x7F);
+ ccr |= DMA4_CCR_SYNC_TRIGGER(trigger + 1);
+
+ if (mode & TI_SDMA_SYNC_FRAME)
+ ccr |= DMA4_CCR_FRAME_SYNC(1);
+ else
+ ccr &= ~DMA4_CCR_FRAME_SYNC(1);
+
+ if (mode & TI_SDMA_SYNC_BLOCK)
+ ccr |= DMA4_CCR_BLOCK_SYNC(1);
+ else
+ ccr &= ~DMA4_CCR_BLOCK_SYNC(1);
+
+ if (mode & TI_SDMA_SYNC_TRIG_ON_SRC)
+ ccr |= DMA4_CCR_SEL_SRC_DST_SYNC(1);
+ else
+ ccr &= ~DMA4_CCR_SEL_SRC_DST_SYNC(1);
+
+ sc->sc_channel[ch].reg_ccr = ccr;
+
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return 0;
+}
+
+/**
+ * ti_sdma_set_addr_mode - driver attach function
+ * @ch: the channel number to set the endianess of
+ * @rd_mode: the xfer source addressing mode (either DMA_ADDR_CONSTANT,
+ * DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or
+ * DMA_ADDR_DOUBLE_INDEX)
+ * @wr_mode: the xfer destination addressing mode (either DMA_ADDR_CONSTANT,
+ * DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or
+ * DMA_ADDR_DOUBLE_INDEX)
+ *
+ *
+ * LOCKING:
+ * DMA registers protected by internal mutex
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+int
+ti_sdma_set_addr_mode(unsigned int ch, unsigned int src_mode,
+ unsigned int dst_mode)
+{
+ struct ti_sdma_softc *sc = ti_sdma_sc;
+ uint32_t ccr;
+
+ /* Sanity check */
+ if (sc == NULL)
+ return (ENOMEM);
+
+ TI_SDMA_LOCK(sc);
+
+ if ((sc->sc_active_channels & (1 << ch)) == 0) {
+ TI_SDMA_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ ccr = sc->sc_channel[ch].reg_ccr;
+
+ ccr &= ~DMA4_CCR_SRC_ADDRESS_MODE(0x3);
+ ccr |= DMA4_CCR_SRC_ADDRESS_MODE(src_mode);
+
+ ccr &= ~DMA4_CCR_DST_ADDRESS_MODE(0x3);
+ ccr |= DMA4_CCR_DST_ADDRESS_MODE(dst_mode);
+
+ sc->sc_channel[ch].reg_ccr = ccr;
+
+ sc->sc_channel[ch].need_reg_write = 1;
+
+ TI_SDMA_UNLOCK(sc);
+
+ return 0;
+}
+
+/**
+ * ti_sdma_probe - driver probe function
+ * @dev: dma device handle
+ *
+ *
+ *
+ * RETURNS:
+ * Always returns 0.
+ */
+static int
+ti_sdma_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,sdma"))
+ return (ENXIO);
+
+ device_set_desc(dev, "TI sDMA Controller");
+ return (0);
+}
+
+/**
+ * ti_sdma_attach - driver attach function
+ * @dev: dma device handle
+ *
+ * Initialises memory mapping/pointers to the DMA register set and requests
+ * IRQs. This is effectively the setup function for the driver.
+ *
+ * RETURNS:
+ * 0 on success or a negative error code failure.
+ */
+static int
+ti_sdma_attach(device_t dev)
+{
+ struct ti_sdma_softc *sc = device_get_softc(dev);
+ unsigned int timeout;
+ unsigned int i;
+ int rid;
+ void *ihl;
+ int err;
+
+ /* Setup the basics */
+ sc->sc_dev = dev;
+
+ /* No channels active at the moment */
+ sc->sc_active_channels = 0x00000000;
+
+ /* Mutex to protect the shared data structures */
+ TI_SDMA_LOCK_INIT(sc);
+
+ /* Get the memory resource for the register mapping */
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->sc_mem_res == NULL)
+ panic("%s: Cannot map registers", device_get_name(dev));
+
+ /* Enable the interface and functional clocks */
+ ti_prcm_clk_enable(SDMA_CLK);
+
+ /* Read the sDMA revision register and sanity check it's known */
+ sc->sc_hw_rev = ti_sdma_read_4(sc, DMA4_REVISION);
+ device_printf(dev, "sDMA revision %08x\n", sc->sc_hw_rev);
+
+ if (!ti_sdma_is_omap4_rev(sc) && !ti_sdma_is_omap3_rev(sc)) {
+ device_printf(sc->sc_dev, "error - unknown sDMA H/W revision\n");
+ return (EINVAL);
+ }
+
+ /* Disable all interrupts */
+ for (i = 0; i < NUM_DMA_IRQS; i++) {
+ ti_sdma_write_4(sc, DMA4_IRQENABLE_L(i), 0x00000000);
+ }
+
+ /* Soft-reset is only supported on pre-OMAP44xx devices */
+ if (ti_sdma_is_omap3_rev(sc)) {
+
+ /* Soft-reset */
+ ti_sdma_write_4(sc, DMA4_OCP_SYSCONFIG, 0x0002);
+
+ /* Set the timeout to 100ms*/
+ timeout = (hz < 10) ? 1 : ((100 * hz) / 1000);
+
+ /* Wait for DMA reset to complete */
+ while ((ti_sdma_read_4(sc, DMA4_SYSSTATUS) & 0x1) == 0x0) {
+
+ /* Sleep for a tick */
+ pause("DMARESET", 1);
+
+ if (timeout-- == 0) {
+ device_printf(sc->sc_dev, "sDMA reset operation timed out\n");
+ return (EINVAL);
+ }
+ }
+ }
+
+ /*
+ * Install interrupt handlers for the for possible interrupts. Any channel
+ * can trip one of the four IRQs
+ */
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->sc_irq_res == NULL)
+ panic("Unable to setup the dma irq handler.\n");
+
+ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, ti_sdma_intr, NULL, &ihl);
+ if (err)
+ panic("%s: Cannot register IRQ", device_get_name(dev));
+
+ /* Store the DMA structure globally ... this driver should never be unloaded */
+ ti_sdma_sc = sc;
+
+ return (0);
+}
+
+static device_method_t ti_sdma_methods[] = {
+ DEVMETHOD(device_probe, ti_sdma_probe),
+ DEVMETHOD(device_attach, ti_sdma_attach),
+ {0, 0},
+};
+
+static driver_t ti_sdma_driver = {
+ "ti_sdma",
+ ti_sdma_methods,
+ sizeof(struct ti_sdma_softc),
+};
+static devclass_t ti_sdma_devclass;
+
+DRIVER_MODULE(ti_sdma, simplebus, ti_sdma_driver, ti_sdma_devclass, 0, 0);
+MODULE_DEPEND(ti_sdma, ti_prcm, 1, 1, 1);
Property changes on: trunk/sys/arm/ti/ti_sdma.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_sdma.h
===================================================================
--- trunk/sys/arm/ti/ti_sdma.h (rev 0)
+++ trunk/sys/arm/ti/ti_sdma.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,112 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_sdma.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+/**
+ * sDMA device driver interface for the TI SoC
+ *
+ * See the ti_sdma.c file for implementation details.
+ *
+ * Reference:
+ * OMAP35x Applications Processor
+ * Technical Reference Manual
+ * (omap35xx_techref.pdf)
+ */
+#ifndef _TI_DMA_H_
+#define _TI_DMA_H_
+
+#define TI_SDMA_ENDIAN_BIG 0x1
+#define TI_SDMA_ENDIAN_LITTLE 0x0
+
+#define TI_SDMA_BURST_NONE 0x0
+#define TI_SDMA_BURST_16 0x1
+#define TI_SDMA_BURST_32 0x2
+#define TI_SDMA_BURST_64 0x3
+
+#define TI_SDMA_DATA_8BITS_SCALAR 0x0
+#define TI_SDMA_DATA_16BITS_SCALAR 0x1
+#define TI_SDMA_DATA_32BITS_SCALAR 0x2
+
+#define TI_SDMA_ADDR_CONSTANT 0x0
+#define TI_SDMA_ADDR_POST_INCREMENT 0x1
+#define TI_SDMA_ADDR_SINGLE_INDEX 0x2
+#define TI_SDMA_ADDR_DOUBLE_INDEX 0x3
+
+/**
+ * Status flags for the DMA callback
+ *
+ */
+#define TI_SDMA_STATUS_DROP (1UL << 1)
+#define TI_SDMA_STATUS_HALF (1UL << 2)
+#define TI_SDMA_STATUS_FRAME (1UL << 3)
+#define TI_SDMA_STATUS_LAST (1UL << 4)
+#define TI_SDMA_STATUS_BLOCK (1UL << 5)
+#define TI_SDMA_STATUS_SYNC (1UL << 6)
+#define TI_SDMA_STATUS_PKT (1UL << 7)
+#define TI_SDMA_STATUS_TRANS_ERR (1UL << 8)
+#define TI_SDMA_STATUS_SECURE_ERR (1UL << 9)
+#define TI_SDMA_STATUS_SUPERVISOR_ERR (1UL << 10)
+#define TI_SDMA_STATUS_MISALIGNED_ADRS_ERR (1UL << 11)
+#define TI_SDMA_STATUS_DRAIN_END (1UL << 12)
+
+#define TI_SDMA_SYNC_FRAME (1UL << 0)
+#define TI_SDMA_SYNC_BLOCK (1UL << 1)
+#define TI_SDMA_SYNC_PACKET (TI_SDMA_SYNC_FRAME | TI_SDMA_SYNC_BLOCK)
+#define TI_SDMA_SYNC_TRIG_ON_SRC (1UL << 8)
+#define TI_SDMA_SYNC_TRIG_ON_DST (1UL << 9)
+
+#define TI_SDMA_IRQ_FLAG_DROP (1UL << 1)
+#define TI_SDMA_IRQ_FLAG_HALF_FRAME_COMPL (1UL << 2)
+#define TI_SDMA_IRQ_FLAG_FRAME_COMPL (1UL << 3)
+#define TI_SDMA_IRQ_FLAG_START_LAST_FRAME (1UL << 4)
+#define TI_SDMA_IRQ_FLAG_BLOCK_COMPL (1UL << 5)
+#define TI_SDMA_IRQ_FLAG_ENDOF_PKT (1UL << 7)
+#define TI_SDMA_IRQ_FLAG_DRAIN (1UL << 12)
+
+int ti_sdma_activate_channel(unsigned int *ch,
+ void (*callback)(unsigned int ch, uint32_t status, void *data), void *data);
+int ti_sdma_deactivate_channel(unsigned int ch);
+int ti_sdma_start_xfer(unsigned int ch, unsigned int src_paddr,
+ unsigned long dst_paddr, unsigned int frmcnt, unsigned int elmcnt);
+int ti_sdma_start_xfer_packet(unsigned int ch, unsigned int src_paddr,
+ unsigned long dst_paddr, unsigned int frmcnt, unsigned int elmcnt,
+ unsigned int pktsize);
+int ti_sdma_stop_xfer(unsigned int ch);
+int ti_sdma_enable_channel_irq(unsigned int ch, uint32_t flags);
+int ti_sdma_disable_channel_irq(unsigned int ch);
+int ti_sdma_get_channel_status(unsigned int ch, uint32_t *status);
+int ti_sdma_set_xfer_endianess(unsigned int ch, unsigned int src, unsigned int dst);
+int ti_sdma_set_xfer_burst(unsigned int ch, unsigned int src, unsigned int dst);
+int ti_sdma_set_xfer_data_type(unsigned int ch, unsigned int type);
+int ti_sdma_set_callback(unsigned int ch,
+ void (*callback)(unsigned int ch, uint32_t status, void *data), void *data);
+int ti_sdma_sync_params(unsigned int ch, unsigned int trigger, unsigned int mode);
+int ti_sdma_set_addr_mode(unsigned int ch, unsigned int src_mode, unsigned int dst_mode);
+
+#endif /* _TI_SDMA_H_ */
Property changes on: trunk/sys/arm/ti/ti_sdma.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_sdmareg.h
===================================================================
--- trunk/sys/arm/ti/ti_sdmareg.h (rev 0)
+++ trunk/sys/arm/ti/ti_sdmareg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,134 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_sdmareg.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+#ifndef __TI_SDMAREG_H__
+#define __TI_SDMAREG_H__
+
+/**
+ * The number of DMA channels possible on the controller.
+ */
+#define NUM_DMA_CHANNELS 32
+#define NUM_DMA_IRQS 4
+
+/**
+ * Register offsets
+ */
+#define DMA4_REVISION 0x0000
+#define DMA4_IRQSTATUS_L(j) (0x0008 + ((j) * 0x4))
+#define DMA4_IRQENABLE_L(j) (0x0018 + ((j) * 0x4))
+#define DMA4_SYSSTATUS 0x0028
+#define DMA4_OCP_SYSCONFIG 0x002C
+#define DMA4_CAPS_0 0x0064
+#define DMA4_CAPS_2 0x006C
+#define DMA4_CAPS_3 0x0070
+#define DMA4_CAPS_4 0x0074
+#define DMA4_GCR 0x0078
+#define DMA4_CCR(i) (0x0080 + ((i) * 0x60))
+#define DMA4_CLNK_CTRL(i) (0x0084 + ((i) * 0x60))
+#define DMA4_CICR(i) (0x0088 + ((i) * 0x60))
+#define DMA4_CSR(i) (0x008C + ((i) * 0x60))
+#define DMA4_CSDP(i) (0x0090 + ((i) * 0x60))
+#define DMA4_CEN(i) (0x0094 + ((i) * 0x60))
+#define DMA4_CFN(i) (0x0098 + ((i) * 0x60))
+#define DMA4_CSSA(i) (0x009C + ((i) * 0x60))
+#define DMA4_CDSA(i) (0x00A0 + ((i) * 0x60))
+#define DMA4_CSE(i) (0x00A4 + ((i) * 0x60))
+#define DMA4_CSF(i) (0x00A8 + ((i) * 0x60))
+#define DMA4_CDE(i) (0x00AC + ((i) * 0x60))
+#define DMA4_CDF(i) (0x00B0 + ((i) * 0x60))
+#define DMA4_CSAC(i) (0x00B4 + ((i) * 0x60))
+#define DMA4_CDAC(i) (0x00B8 + ((i) * 0x60))
+#define DMA4_CCEN(i) (0x00BC + ((i) * 0x60))
+#define DMA4_CCFN(i) (0x00C0 + ((i) * 0x60))
+#define DMA4_COLOR(i) (0x00C4 + ((i) * 0x60))
+
+/* The following register are only defined on OMAP44xx (and newer?) */
+#define DMA4_CDP(i) (0x00D0 + ((i) * 0x60))
+#define DMA4_CNDP(i) (0x00D4 + ((i) * 0x60))
+#define DMA4_CCDN(i) (0x00D8 + ((i) * 0x60))
+
+/**
+ * Various register field settings
+ */
+#define DMA4_CSDP_DATA_TYPE(x) (((x) & 0x3) << 0)
+#define DMA4_CSDP_SRC_BURST_MODE(x) (((x) & 0x3) << 7)
+#define DMA4_CSDP_DST_BURST_MODE(x) (((x) & 0x3) << 14)
+#define DMA4_CSDP_SRC_ENDIANISM(x) (((x) & 0x1) << 21)
+#define DMA4_CSDP_DST_ENDIANISM(x) (((x) & 0x1) << 19)
+#define DMA4_CSDP_WRITE_MODE(x) (((x) & 0x3) << 16)
+#define DMA4_CSDP_SRC_PACKED(x) (((x) & 0x1) << 6)
+#define DMA4_CSDP_DST_PACKED(x) (((x) & 0x1) << 13)
+
+#define DMA4_CCR_DST_ADDRESS_MODE(x) (((x) & 0x3) << 14)
+#define DMA4_CCR_SRC_ADDRESS_MODE(x) (((x) & 0x3) << 12)
+#define DMA4_CCR_READ_PRIORITY(x) (((x) & 0x1) << 6)
+#define DMA4_CCR_WRITE_PRIORITY(x) (((x) & 0x1) << 26)
+#define DMA4_CCR_SYNC_TRIGGER(x) ((((x) & 0x60) << 14) \
+ | ((x) & 0x1f))
+#define DMA4_CCR_FRAME_SYNC(x) (((x) & 0x1) << 5)
+#define DMA4_CCR_BLOCK_SYNC(x) (((x) & 0x1) << 18)
+#define DMA4_CCR_SEL_SRC_DST_SYNC(x) (((x) & 0x1) << 24)
+
+#define DMA4_CCR_PACKET_TRANS (DMA4_CCR_FRAME_SYNC(1) | \
+ DMA4_CCR_BLOCK_SYNC(1) )
+
+#define DMA4_CSR_DROP (1UL << 1)
+#define DMA4_CSR_HALF (1UL << 2)
+#define DMA4_CSR_FRAME (1UL << 3)
+#define DMA4_CSR_LAST (1UL << 4)
+#define DMA4_CSR_BLOCK (1UL << 5)
+#define DMA4_CSR_SYNC (1UL << 6)
+#define DMA4_CSR_PKT (1UL << 7)
+#define DMA4_CSR_TRANS_ERR (1UL << 8)
+#define DMA4_CSR_SECURE_ERR (1UL << 9)
+#define DMA4_CSR_SUPERVISOR_ERR (1UL << 10)
+#define DMA4_CSR_MISALIGNED_ADRS_ERR (1UL << 11)
+#define DMA4_CSR_DRAIN_END (1UL << 12)
+#define DMA4_CSR_CLEAR_MASK (0xffe)
+
+#define DMA4_CICR_DROP_IE (1UL << 1)
+#define DMA4_CICR_HALF_IE (1UL << 2)
+#define DMA4_CICR_FRAME_IE (1UL << 3)
+#define DMA4_CICR_LAST_IE (1UL << 4)
+#define DMA4_CICR_BLOCK_IE (1UL << 5)
+#define DMA4_CICR_PKT_IE (1UL << 7)
+#define DMA4_CICR_TRANS_ERR_IE (1UL << 8)
+#define DMA4_CICR_SECURE_ERR_IE (1UL << 9)
+#define DMA4_CICR_SUPERVISOR_ERR_IE (1UL << 10)
+#define DMA4_CICR_MISALIGNED_ADRS_ERR_IE (1UL << 11)
+#define DMA4_CICR_DRAIN_IE (1UL << 12)
+
+/**
+ * The following H/W revision values were found be experimentation, TI don't
+ * publish the revision numbers. The TRM says "TI internal Data".
+ */
+#define DMA4_OMAP3_REV 0x00000040
+#define DMA4_OMAP4_REV 0x00010900
+
+#endif /* __TI_SDMAREG_H__ */
Property changes on: trunk/sys/arm/ti/ti_sdmareg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_smc.S
===================================================================
--- trunk/sys/arm/ti/ti_smc.S (rev 0)
+++ trunk/sys/arm/ti/ti_smc.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,41 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/armreg.h>
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_smc.S 275767 2014-12-14 16:28:53Z andrew $");
+
+ .cpu cortex-a8
+ .arch_extension sec
+
+/* Issue a smc #0 call */
+/* r0 and r1 contains the eventual arguments, r2 contains the function ID */
+ENTRY(ti_smc0)
+ stmfd sp!, {r4-r12, lr}
+ mov r12, r2 /* the rom expects the function ID in r12 */
+ dsb
+ smc #0
+ ldmfd sp!, {r4-r12, pc}
+
Property changes on: trunk/sys/arm/ti/ti_smc.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_smc.h
===================================================================
--- trunk/sys/arm/ti/ti_smc.h (rev 0)
+++ trunk/sys/arm/ti/ti_smc.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,34 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * $FreeBSD: stable/10/sys/arm/ti/ti_smc.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+#ifndef TI_SMC_H_
+#define TI_SMC_H_
+uint32_t ti_smc0(uint32_t r0, uint32_t r1, uint32_t function_id);
+#endif /* TI_SMC_H_ */
Property changes on: trunk/sys/arm/ti/ti_smc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_wdt.c
===================================================================
--- trunk/sys/arm/ti/ti_wdt.c (rev 0)
+++ trunk/sys/arm/ti/ti_wdt.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,278 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Rui Paulo <rpaulo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_wdt.c 276290 2014-12-27 05:11:34Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/event.h>
+#include <sys/selinfo.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_wdt.h>
+
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) do { \
+ printf("%s: ", __func__); \
+ printf(fmt, __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+static device_probe_t ti_wdt_probe;
+static device_attach_t ti_wdt_attach;
+static device_detach_t ti_wdt_detach;
+static void ti_wdt_intr(void *);
+static void ti_wdt_event(void *, unsigned int, int *);
+
+struct ti_wdt_softc {
+ struct resource *sc_mem_res;
+ struct resource *sc_irq_res;
+ void *sc_intr;
+ bus_space_tag_t sc_bt;
+ bus_space_handle_t sc_bh;
+ eventhandler_tag sc_ev_tag;
+};
+
+static device_method_t ti_wdt_methods[] = {
+ DEVMETHOD(device_probe, ti_wdt_probe),
+ DEVMETHOD(device_attach, ti_wdt_attach),
+ DEVMETHOD(device_detach, ti_wdt_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t ti_wdt_driver = {
+ "ti_wdt",
+ ti_wdt_methods,
+ sizeof(struct ti_wdt_softc)
+};
+
+static devclass_t ti_wdt_devclass;
+
+DRIVER_MODULE(ti_wdt, simplebus, ti_wdt_driver, ti_wdt_devclass, 0, 0);
+
+static __inline uint32_t
+ti_wdt_reg_read(struct ti_wdt_softc *sc, uint32_t reg)
+{
+
+ return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
+}
+
+static __inline void
+ti_wdt_reg_write(struct ti_wdt_softc *sc, uint32_t reg, uint32_t val)
+{
+
+ bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
+}
+
+/*
+ * Wait for the write to a specific synchronised register to complete.
+ */
+static __inline void
+ti_wdt_reg_wait(struct ti_wdt_softc *sc, uint32_t bit)
+{
+
+ while (ti_wdt_reg_read(sc, TI_WDT_WWPS) & bit)
+ DELAY(10);
+}
+
+static __inline void
+ti_wdt_disable(struct ti_wdt_softc *sc)
+{
+
+ DPRINTF("disabling watchdog %p\n", sc);
+ ti_wdt_reg_write(sc, TI_WDT_WSPR, 0xAAAA);
+ ti_wdt_reg_wait(sc, TI_W_PEND_WSPR);
+ ti_wdt_reg_write(sc, TI_WDT_WSPR, 0x5555);
+ ti_wdt_reg_wait(sc, TI_W_PEND_WSPR);
+}
+
+static __inline void
+ti_wdt_enable(struct ti_wdt_softc *sc)
+{
+
+ DPRINTF("enabling watchdog %p\n", sc);
+ ti_wdt_reg_write(sc, TI_WDT_WSPR, 0xBBBB);
+ ti_wdt_reg_wait(sc, TI_W_PEND_WSPR);
+ ti_wdt_reg_write(sc, TI_WDT_WSPR, 0x4444);
+ ti_wdt_reg_wait(sc, TI_W_PEND_WSPR);
+}
+
+static int
+ti_wdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (ofw_bus_is_compatible(dev, "ti,omap3-wdt")) {
+ device_set_desc(dev, "TI Watchdog Timer");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+ti_wdt_attach(device_t dev)
+{
+ struct ti_wdt_softc *sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+ sc->sc_bt = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bh = rman_get_bushandle(sc->sc_mem_res);
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(dev, "could not allocate interrupt resource\n");
+ ti_wdt_detach(dev);
+ return (ENXIO);
+ }
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE | INTR_TYPE_MISC,
+ NULL, ti_wdt_intr, sc, &sc->sc_intr) != 0) {
+ device_printf(dev,
+ "unable to setup the interrupt handler\n");
+ ti_wdt_detach(dev);
+ return (ENXIO);
+ }
+ /* Reset, enable interrupts and stop the watchdog. */
+ ti_wdt_reg_write(sc, TI_WDT_WDSC,
+ ti_wdt_reg_read(sc, TI_WDT_WDSC) | TI_WDSC_SR);
+ while (ti_wdt_reg_read(sc, TI_WDT_WDSC) & TI_WDSC_SR)
+ DELAY(10);
+ ti_wdt_reg_write(sc, TI_WDT_WIRQENSET, TI_IRQ_EN_OVF | TI_IRQ_EN_DLY);
+ ti_wdt_disable(sc);
+ if (bootverbose)
+ device_printf(dev, "revision: 0x%x\n",
+ ti_wdt_reg_read(sc, TI_WDT_WIDR));
+ sc->sc_ev_tag = EVENTHANDLER_REGISTER(watchdog_list, ti_wdt_event, sc,
+ 0);
+
+ return (0);
+}
+
+static int
+ti_wdt_detach(device_t dev)
+{
+ struct ti_wdt_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->sc_ev_tag)
+ EVENTHANDLER_DEREGISTER(watchdog_list, sc->sc_ev_tag);
+ if (sc->sc_intr)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->sc_mem_res), sc->sc_mem_res);
+
+ return (0);
+}
+
+static void
+ti_wdt_intr(void *arg)
+{
+ struct ti_wdt_softc *sc;
+
+ sc = arg;
+ DPRINTF("interrupt %p", sc);
+ ti_wdt_reg_write(sc, TI_WDT_WIRQSTAT, TI_IRQ_EV_OVF | TI_IRQ_EV_DLY);
+ /* TODO: handle interrupt */
+}
+
+static void
+ti_wdt_event(void *arg, unsigned int cmd, int *error)
+{
+ struct ti_wdt_softc *sc;
+ uint8_t s;
+ uint32_t wldr;
+ uint32_t ptv;
+
+ sc = arg;
+ ti_wdt_disable(sc);
+ if (cmd == WD_TO_NEVER) {
+ *error = 0;
+ return;
+ }
+ DPRINTF("cmd 0x%x\n", cmd);
+ cmd &= WD_INTERVAL;
+ if (cmd < WD_TO_1SEC) {
+ *error = EINVAL;
+ return;
+ }
+ s = 1 << (cmd - WD_TO_1SEC);
+ DPRINTF("seconds %u\n", s);
+ /*
+ * Leave the pre-scaler with its default values:
+ * PTV = 0 == 2**0 == 1
+ * PRE = 1 (enabled)
+ *
+ * Compute the load register value assuming a 32kHz clock.
+ * See OVF_Rate in the WDT section of the AM335x TRM.
+ */
+ ptv = 0;
+ wldr = 0xffffffff - (s * (32768 / (1 << ptv))) + 1;
+ DPRINTF("wldr 0x%x\n", wldr);
+ ti_wdt_reg_write(sc, TI_WDT_WLDR, wldr);
+ /*
+ * Trigger a timer reload.
+ */
+ ti_wdt_reg_write(sc, TI_WDT_WTGR,
+ ti_wdt_reg_read(sc, TI_WDT_WTGR) + 1);
+ ti_wdt_reg_wait(sc, TI_W_PEND_WTGR);
+ ti_wdt_enable(sc);
+ *error = 0;
+}
Property changes on: trunk/sys/arm/ti/ti_wdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/ti_wdt.h
===================================================================
--- trunk/sys/arm/ti/ti_wdt.h (rev 0)
+++ trunk/sys/arm/ti/ti_wdt.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,75 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Rui Paulo <rpaulo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/ti_wdt.h 273624 2014-10-25 02:05:21Z rpaulo $
+ */
+#ifndef _TI_WDT_H_
+#define _TI_WDT_H_
+
+/* TI WDT registers */
+#define TI_WDT_WIDR 0x00 /* Watchdog Identification Register */
+#define TI_WDT_WDSC 0x10 /* Watchdog System Control Register */
+#define TI_WDT_WDST 0x14 /* Watchdog Status Register */
+#define TI_WDT_WISR 0x18 /* Watchdog Interrupt Status Register */
+#define TI_WDT_WIER 0x1c /* Watchdog Interrupt Enable Register */
+#define TI_WDT_WCLR 0x24 /* Watchdog Control Register */
+#define TI_WDT_WCRR 0x28 /* Watchdog Counter Register */
+#define TI_WDT_WLDR 0x2c /* Watchdog Load Register */
+#define TI_WDT_WTGR 0x30 /* Watchdog Trigger Register */
+#define TI_WDT_WWPS 0x34 /* Watchdog Write Posting Register */
+#define TI_WDT_WDLY 0x44 /* Watchdog Delay Configuration Reg */
+#define TI_WDT_WSPR 0x48 /* Watchdog Start/Stop Register */
+#define TI_WDT_WIRQSTATRAW 0x54 /* Watchdog Raw Interrupt Status Reg. */
+#define TI_WDT_WIRQSTAT 0x58 /* Watchdog Int. Status Register */
+#define TI_WDT_WIRQENSET 0x5c /* Watchdog Int. Enable Set Register */
+#define TI_WDT_WIRQENCLR 0x60 /* Watchdog Int. Enable Clear Reg. */
+
+/* WDT_WDSC Register */
+#define TI_WDSC_SR (1 << 1) /* Soft reset */
+
+/*
+ * WDT_WWPS Register
+ *
+ * Writes to some registers require synchronisation with a different clock
+ * domain. The WDT_WWPS register is the place where this synchronisation
+ * happens.
+ */
+#define TI_W_PEND_WCLR (1 << 0)
+#define TI_W_PEND_WCRR (1 << 1)
+#define TI_W_PEND_WLDR (1 << 2)
+#define TI_W_PEND_WTGR (1 << 3)
+#define TI_W_PEND_WSPR (1 << 4)
+#define TI_W_PEND_WDLY (1 << 5)
+
+/* WDT_WIRQENSET Register */
+#define TI_IRQ_EN_OVF (1 << 0) /* Overflow interrupt */
+#define TI_IRQ_EN_DLY (1 << 1) /* Delay interrupt */
+
+/* WDT_WIRQSTAT Register */
+#define TI_IRQ_EV_OVF (1 << 0) /* Overflow event */
+#define TI_IRQ_EV_DLY (1 << 1) /* Delay event */
+
+#endif /* _TI_WDT_H_ */
Property changes on: trunk/sys/arm/ti/ti_wdt.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/tivar.h
===================================================================
--- trunk/sys/arm/ti/tivar.h (rev 0)
+++ trunk/sys/arm/ti/tivar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,42 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/tivar.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+#ifndef _TIVAR_H_
+#define _TIVAR_H_
+
+/* board-dependent reset function implementation */
+extern void (*ti_cpu_reset)(void);
+
+#endif /* _TIVAR_H_ */
Property changes on: trunk/sys/arm/ti/tivar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/twl/twl.c
===================================================================
--- trunk/sys/arm/ti/twl/twl.c (rev 0)
+++ trunk/sys/arm/ti/twl/twl.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,464 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/twl/twl.c 259329 2013-12-13 20:43:11Z ian $");
+
+/*
+ * Texas Instruments TWL4030/TWL5030/TWL60x0/TPS659x0 Power Management and
+ * Audio CODEC devices.
+ *
+ * This code is based on the Linux TWL multifunctional device driver, which is
+ * copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * These chips are typically used as support ICs for the OMAP range of embedded
+ * ARM processes/SOC from Texas Instruments. They are typically used to control
+ * on board voltages, however some variants have other features like audio
+ * codecs, USB OTG transceivers, RTC, PWM, etc.
+ *
+ * This driver acts as a bus for more specific companion devices.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "arm/ti/twl/twl.h"
+
+/* TWL device IDs */
+#define TWL_DEVICE_UNKNOWN 0xffff
+#define TWL_DEVICE_4030 0x4030
+#define TWL_DEVICE_6025 0x6025
+#define TWL_DEVICE_6030 0x6030
+
+/* Each TWL device typically has more than one I2C address */
+#define TWL_MAX_SUBADDRS 4
+
+/* The maxium number of bytes that can be written in one call */
+#define TWL_MAX_IIC_DATA_SIZE 63
+
+/* The TWL devices typically use 4 I2C address for the different internal
+ * register sets, plus one SmartReflex I2C address.
+ */
+#define TWL_CHIP_ID0 0x48
+#define TWL_CHIP_ID1 0x49
+#define TWL_CHIP_ID2 0x4A
+#define TWL_CHIP_ID3 0x4B
+
+#define TWL_SMARTREFLEX_CHIP_ID 0x12
+
+#define TWL_INVALID_CHIP_ID 0xff
+
+struct twl_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ unsigned int sc_type;
+
+ uint8_t sc_subaddr_map[TWL_MAX_SUBADDRS];
+
+ struct intr_config_hook sc_scan_hook;
+
+ device_t sc_vreg;
+ device_t sc_clks;
+};
+
+/**
+ * Macros for driver mutex locking
+ */
+#define TWL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define TWL_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define TWL_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ "twl", MTX_DEF)
+#define TWL_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define TWL_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define TWL_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+
+/**
+ * twl_is_4030 - returns true if the device is TWL4030
+ * twl_is_6025 - returns true if the device is TWL6025
+ * twl_is_6030 - returns true if the device is TWL6030
+ * @sc: device soft context
+ *
+ * Returns a non-zero value if the device matches.
+ *
+ * RETURNS:
+ * Returns a non-zero value if the device matches, otherwise zero.
+ */
+int
+twl_is_4030(device_t dev)
+{
+ struct twl_softc *sc = device_get_softc(dev);
+ return (sc->sc_type == TWL_DEVICE_4030);
+}
+
+int
+twl_is_6025(device_t dev)
+{
+ struct twl_softc *sc = device_get_softc(dev);
+ return (sc->sc_type == TWL_DEVICE_6025);
+}
+
+int
+twl_is_6030(device_t dev)
+{
+ struct twl_softc *sc = device_get_softc(dev);
+ return (sc->sc_type == TWL_DEVICE_6030);
+}
+
+
+/**
+ * twl_read - read one or more registers from the TWL device
+ * @sc: device soft context
+ * @nsub: the sub-module to read from
+ * @reg: the register offset within the module to read
+ * @buf: buffer to store the bytes in
+ * @cnt: the number of bytes to read
+ *
+ * Reads one or more registers and stores the result in the suppled buffer.
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+int
+twl_read(device_t dev, uint8_t nsub, uint8_t reg, uint8_t *buf, uint16_t cnt)
+{
+ struct twl_softc *sc;
+ struct iic_msg msg[2];
+ uint8_t addr;
+ int rc;
+
+ sc = device_get_softc(dev);
+
+ TWL_LOCK(sc);
+ addr = sc->sc_subaddr_map[nsub];
+ TWL_UNLOCK(sc);
+
+ if (addr == TWL_INVALID_CHIP_ID)
+ return (EIO);
+
+
+ /* Set the address to read from */
+ msg[0].slave = addr;
+ msg[0].flags = IIC_M_WR | IIC_M_NOSTOP;
+ msg[0].len = 1;
+ msg[0].buf = ®
+ /* Read the data back */
+ msg[1].slave = addr;
+ msg[1].flags = IIC_M_RD;
+ msg[1].len = cnt;
+ msg[1].buf = buf;
+
+ rc = iicbus_transfer(dev, msg, 2);
+ if (rc != 0) {
+ device_printf(dev, "iicbus read failed (adr:0x%02x, reg:0x%02x)\n",
+ addr, reg);
+ return (EIO);
+ }
+
+ return (0);
+}
+
+/**
+ * twl_write - writes one or more registers to the TWL device
+ * @sc: device soft context
+ * @nsub: the sub-module to read from
+ * @reg: the register offset within the module to read
+ * @buf: data to write
+ * @cnt: the number of bytes to write
+ *
+ * Writes one or more registers.
+ *
+ * RETURNS:
+ * Zero on success or a negative error code on failure.
+ */
+int
+twl_write(device_t dev, uint8_t nsub, uint8_t reg, uint8_t *buf, uint16_t cnt)
+{
+ struct twl_softc *sc;
+ struct iic_msg msg;
+ uint8_t addr;
+ uint8_t tmp_buf[TWL_MAX_IIC_DATA_SIZE + 1];
+ int rc;
+
+ if (cnt > TWL_MAX_IIC_DATA_SIZE)
+ return (ENOMEM);
+
+ /* Set the register address as the first byte */
+ tmp_buf[0] = reg;
+ memcpy(&tmp_buf[1], buf, cnt);
+
+ sc = device_get_softc(dev);
+
+ TWL_LOCK(sc);
+ addr = sc->sc_subaddr_map[nsub];
+ TWL_UNLOCK(sc);
+
+ if (addr == TWL_INVALID_CHIP_ID)
+ return (EIO);
+
+
+ /* Setup the transfer and execute it */
+ msg.slave = addr;
+ msg.flags = IIC_M_WR;
+ msg.len = cnt + 1;
+ msg.buf = tmp_buf;
+
+ rc = iicbus_transfer(dev, &msg, 1);
+ if (rc != 0) {
+ device_printf(sc->sc_dev, "iicbus write failed (adr:0x%02x, reg:0x%02x)\n",
+ addr, reg);
+ return (EIO);
+ }
+
+ return (0);
+}
+
+/**
+ * twl_test_present - checks if a device with given address is present
+ * @sc: device soft context
+ * @addr: the address of the device to scan for
+ *
+ * Sends just the address byte and checks for an ACK. If no ACK then device
+ * is assumed to not be present.
+ *
+ * RETURNS:
+ * EIO if device is not present, otherwise 0 is returned.
+ */
+static int
+twl_test_present(struct twl_softc *sc, uint8_t addr)
+{
+ struct iic_msg msg;
+ uint8_t tmp;
+
+ /* Set the address to read from */
+ msg.slave = addr;
+ msg.flags = IIC_M_RD;
+ msg.len = 1;
+ msg.buf = &tmp;
+
+ if (iicbus_transfer(sc->sc_dev, &msg, 1) != 0)
+ return (EIO);
+
+ return (0);
+}
+
+/**
+ * twl_scan - scans the i2c bus for sub modules
+ * @dev: the twl device
+ *
+ * TWL devices don't just have one i2c slave address, rather they have up to
+ * 5 other addresses, each is for separate modules within the device. This
+ * function scans the bus for 4 possible sub-devices and stores the info
+ * internally.
+ *
+ */
+static void
+twl_scan(void *dev)
+{
+ struct twl_softc *sc;
+ unsigned i;
+ uint8_t devs[TWL_MAX_SUBADDRS];
+ uint8_t base = TWL_CHIP_ID0;
+
+ sc = device_get_softc((device_t)dev);
+
+ memset(devs, TWL_INVALID_CHIP_ID, TWL_MAX_SUBADDRS);
+
+ /* Try each of the addresses (0x48, 0x49, 0x4a & 0x4b) to determine which
+ * sub modules we have.
+ */
+ for (i = 0; i < TWL_MAX_SUBADDRS; i++) {
+ if (twl_test_present(sc, (base + i)) == 0) {
+ devs[i] = (base + i);
+ device_printf(sc->sc_dev, "Found (sub)device at 0x%02x\n", (base + i));
+ }
+ }
+
+ TWL_LOCK(sc);
+ memcpy(sc->sc_subaddr_map, devs, TWL_MAX_SUBADDRS);
+ TWL_UNLOCK(sc);
+
+ /* Finished with the interrupt hook */
+ config_intrhook_disestablish(&sc->sc_scan_hook);
+}
+
+/**
+ * twl_probe -
+ * @dev: the twl device
+ *
+ * Scans the FDT for a match for the device, possible compatible device
+ * strings are; "ti,twl6030", "ti,twl6025", "ti,twl4030".
+ *
+ * The FDT compat string also determines the type of device (it is currently
+ * not possible to dynamically determine the device type).
+ *
+ */
+static int
+twl_probe(device_t dev)
+{
+ phandle_t node;
+ const char *compat;
+ int len, l;
+ struct twl_softc *sc;
+
+ if ((compat = ofw_bus_get_compat(dev)) == NULL)
+ return (ENXIO);
+
+ if ((node = ofw_bus_get_node(dev)) == 0)
+ return (ENXIO);
+
+ /* Get total 'compatible' prop len */
+ if ((len = OF_getproplen(node, "compatible")) <= 0)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_type = TWL_DEVICE_UNKNOWN;
+
+ while (len > 0) {
+ if (strncasecmp(compat, "ti,twl6030", 10) == 0)
+ sc->sc_type = TWL_DEVICE_6030;
+ else if (strncasecmp(compat, "ti,twl6025", 10) == 0)
+ sc->sc_type = TWL_DEVICE_6025;
+ else if (strncasecmp(compat, "ti,twl4030", 10) == 0)
+ sc->sc_type = TWL_DEVICE_4030;
+
+ if (sc->sc_type != TWL_DEVICE_UNKNOWN)
+ break;
+
+ /* Slide to the next sub-string. */
+ l = strlen(compat) + 1;
+ compat += l;
+ len -= l;
+ }
+
+ switch (sc->sc_type) {
+ case TWL_DEVICE_4030:
+ device_set_desc(dev, "TI TWL4030/TPS659x0 Companion IC");
+ break;
+ case TWL_DEVICE_6025:
+ device_set_desc(dev, "TI TWL6025 Companion IC");
+ break;
+ case TWL_DEVICE_6030:
+ device_set_desc(dev, "TI TWL6030 Companion IC");
+ break;
+ case TWL_DEVICE_UNKNOWN:
+ default:
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+twl_attach(device_t dev)
+{
+ struct twl_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ TWL_LOCK_INIT(sc);
+
+ /* We have to wait until interrupts are enabled. I2C read and write
+ * only works if the interrupts are available.
+ */
+ sc->sc_scan_hook.ich_func = twl_scan;
+ sc->sc_scan_hook.ich_arg = dev;
+
+ if (config_intrhook_establish(&sc->sc_scan_hook) != 0)
+ return (ENOMEM);
+
+ /* FIXME: should be in DTS file */
+ if ((sc->sc_vreg = device_add_child(dev, "twl_vreg", -1)) == NULL)
+ device_printf(dev, "could not allocate twl_vreg instance\n");
+ if ((sc->sc_clks = device_add_child(dev, "twl_clks", -1)) == NULL)
+ device_printf(dev, "could not allocate twl_clks instance\n");
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+twl_detach(device_t dev)
+{
+ struct twl_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->sc_vreg)
+ device_delete_child(dev, sc->sc_vreg);
+ if (sc->sc_clks)
+ device_delete_child(dev, sc->sc_clks);
+
+
+ TWL_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static device_method_t twl_methods[] = {
+ DEVMETHOD(device_probe, twl_probe),
+ DEVMETHOD(device_attach, twl_attach),
+ DEVMETHOD(device_detach, twl_detach),
+
+ {0, 0},
+};
+
+static driver_t twl_driver = {
+ "twl",
+ twl_methods,
+ sizeof(struct twl_softc),
+};
+static devclass_t twl_devclass;
+
+DRIVER_MODULE(twl, iicbus, twl_driver, twl_devclass, 0, 0);
+MODULE_VERSION(twl, 1);
Property changes on: trunk/sys/arm/ti/twl/twl.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/twl/twl.h
===================================================================
--- trunk/sys/arm/ti/twl/twl.h (rev 0)
+++ trunk/sys/arm/ti/twl/twl.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,40 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/twl/twl.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+#ifndef _TWL_H_
+#define _TWL_H_
+
+int twl_read(device_t dev, uint8_t nsub, uint8_t reg, uint8_t *buf, uint16_t cnt);
+int twl_write(device_t dev, uint8_t nsub, uint8_t reg, uint8_t *buf, uint16_t cnt);
+
+int twl_is_4030(device_t dev);
+int twl_is_6025(device_t dev);
+int twl_is_6030(device_t dev);
+
+#endif /* _TWL_H_ */
Property changes on: trunk/sys/arm/ti/twl/twl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/twl/twl_clks.c
===================================================================
--- trunk/sys/arm/ti/twl/twl_clks.c (rev 0)
+++ trunk/sys/arm/ti/twl/twl_clks.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,675 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012
+ * Ben Gray <bgray at freebsd.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/twl/twl_clks.c 259329 2013-12-13 20:43:11Z ian $");
+
+/*
+ * Texas Instruments TWL4030/TWL5030/TWL60x0/TPS659x0 Power Management.
+ *
+ * This driver covers the external clocks, allows for enabling &
+ * disabling their output.
+ *
+ *
+ *
+ * FLATTENED DEVICE TREE (FDT)
+ * Startup override settings can be specified in the FDT, if they are they
+ * should be under the twl parent device and take the following form:
+ *
+ * external-clocks = "name1", "state1",
+ * "name2", "state2",
+ * etc;
+ *
+ * Each override should be a pair, the first entry is the name of the clock
+ * the second is the state to set, possible strings are either "on" or "off".
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+
+#include "twl.h"
+#include "twl_clks.h"
+
+
+static int twl_clks_debug = 1;
+
+
+/*
+ * Power Groups bits for the 4030 and 6030 devices
+ */
+#define TWL4030_P3_GRP 0x80 /* Peripherals, power group */
+#define TWL4030_P2_GRP 0x40 /* Modem power group */
+#define TWL4030_P1_GRP 0x20 /* Application power group (FreeBSD control) */
+
+#define TWL6030_P3_GRP 0x04 /* Modem power group */
+#define TWL6030_P2_GRP 0x02 /* Connectivity power group */
+#define TWL6030_P1_GRP 0x01 /* Application power group (FreeBSD control) */
+
+/*
+ * Register offsets within a clk regulator register set
+ */
+#define TWL_CLKS_GRP 0x00 /* Regulator GRP register */
+#define TWL_CLKS_STATE 0x02 /* TWL6030 only */
+
+
+
+/**
+ * Support voltage regulators for the different IC's
+ */
+struct twl_clock {
+ const char *name;
+ uint8_t subdev;
+ uint8_t regbase;
+};
+
+static const struct twl_clock twl4030_clocks[] = {
+ { "32kclkout", 0, 0x8e },
+ { NULL, 0, 0x00 }
+};
+
+static const struct twl_clock twl6030_clocks[] = {
+ { "clk32kg", 0, 0xbc },
+ { "clk32kao", 0, 0xb9 },
+ { "clk32kaudio", 0, 0xbf },
+ { NULL, 0, 0x00 }
+};
+
+#define TWL_CLKS_MAX_NAMELEN 32
+
+struct twl_clk_entry {
+ LIST_ENTRY(twl_clk_entry) link;
+ struct sysctl_oid *oid;
+ char name[TWL_CLKS_MAX_NAMELEN];
+ uint8_t sub_dev; /* the sub-device number for the clock */
+ uint8_t reg_off; /* register base address of the clock */
+};
+
+struct twl_clks_softc {
+ device_t sc_dev; /* twl_clk device */
+ device_t sc_pdev; /* parent device (twl) */
+ struct sx sc_sx; /* internal locking */
+ struct intr_config_hook sc_init_hook;
+ LIST_HEAD(twl_clk_list, twl_clk_entry) sc_clks_list;
+};
+
+/**
+ * Macros for driver shared locking
+ */
+#define TWL_CLKS_XLOCK(_sc) sx_xlock(&(_sc)->sc_sx)
+#define TWL_CLKS_XUNLOCK(_sc) sx_xunlock(&(_sc)->sc_sx)
+#define TWL_CLKS_SLOCK(_sc) sx_slock(&(_sc)->sc_sx)
+#define TWL_CLKS_SUNLOCK(_sc) sx_sunlock(&(_sc)->sc_sx)
+#define TWL_CLKS_LOCK_INIT(_sc) sx_init(&(_sc)->sc_sx, "twl_clks")
+#define TWL_CLKS_LOCK_DESTROY(_sc) sx_destroy(&(_sc)->sc_sx);
+
+#define TWL_CLKS_ASSERT_LOCKED(_sc) sx_assert(&(_sc)->sc_sx, SA_LOCKED);
+
+#define TWL_CLKS_LOCK_UPGRADE(_sc) \
+ do { \
+ while (!sx_try_upgrade(&(_sc)->sc_sx)) \
+ pause("twl_clks_ex", (hz / 100)); \
+ } while(0)
+#define TWL_CLKS_LOCK_DOWNGRADE(_sc) sx_downgrade(&(_sc)->sc_sx);
+
+
+
+
+/**
+ * twl_clks_read_1 - read single register from the TWL device
+ * twl_clks_write_1 - writes a single register in the TWL device
+ * @sc: device context
+ * @clk: the clock device we're reading from / writing to
+ * @off: offset within the clock's register set
+ * @val: the value to write or a pointer to a variable to store the result
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+static inline int
+twl_clks_read_1(struct twl_clks_softc *sc, struct twl_clk_entry *clk,
+ uint8_t off, uint8_t *val)
+{
+ return (twl_read(sc->sc_pdev, clk->sub_dev, clk->reg_off + off, val, 1));
+}
+
+static inline int
+twl_clks_write_1(struct twl_clks_softc *sc, struct twl_clk_entry *clk,
+ uint8_t off, uint8_t val)
+{
+ return (twl_write(sc->sc_pdev, clk->sub_dev, clk->reg_off + off, &val, 1));
+}
+
+
+/**
+ * twl_clks_is_enabled - determines if a clock is enabled
+ * @dev: TWL CLK device
+ * @name: the name of the clock
+ * @enabled: upon return will contain the 'enabled' state
+ *
+ * LOCKING:
+ * Internally the function takes and releases the TWL lock.
+ *
+ * RETURNS:
+ * Zero on success or a negative error code on failure.
+ */
+int
+twl_clks_is_enabled(device_t dev, const char *name, int *enabled)
+{
+ struct twl_clks_softc *sc = device_get_softc(dev);
+ struct twl_clk_entry *clk;
+ int found = 0;
+ int err;
+ uint8_t grp, state;
+
+ TWL_CLKS_SLOCK(sc);
+
+ LIST_FOREACH(clk, &sc->sc_clks_list, link) {
+ if (strcmp(clk->name, name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ TWL_CLKS_SUNLOCK(sc);
+ return (EINVAL);
+ }
+
+
+ if (twl_is_4030(sc->sc_pdev)) {
+
+ err = twl_clks_read_1(sc, clk, TWL_CLKS_GRP, &grp);
+ if (!err)
+ *enabled = (grp & TWL4030_P1_GRP);
+
+ } else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) {
+
+ TWL_CLKS_LOCK_UPGRADE(sc);
+
+ /* Check the clock is in the application group */
+ if (twl_is_6030(sc->sc_pdev)) {
+ err = twl_clks_read_1(sc, clk, TWL_CLKS_GRP, &grp);
+ if (err) {
+ TWL_CLKS_LOCK_DOWNGRADE(sc);
+ goto done;
+ }
+
+ if (!(grp & TWL6030_P1_GRP)) {
+ TWL_CLKS_LOCK_DOWNGRADE(sc);
+ *enabled = 0; /* disabled */
+ goto done;
+ }
+ }
+
+ /* Read the application mode state and verify it's ON */
+ err = twl_clks_read_1(sc, clk, TWL_CLKS_STATE, &state);
+ if (!err)
+ *enabled = ((state & 0x0C) == 0x04);
+
+ TWL_CLKS_LOCK_DOWNGRADE(sc);
+
+ } else {
+ err = EINVAL;
+ }
+
+done:
+ TWL_CLKS_SUNLOCK(sc);
+ return (err);
+}
+
+
+/**
+ * twl_clks_set_state - enables/disables a clock output
+ * @sc: device context
+ * @clk: the clock entry to enable/disable
+ * @enable: non-zero the clock is enabled, zero the clock is disabled
+ *
+ * LOCKING:
+ * The TWL CLK lock must be held before this function is called.
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+static int
+twl_clks_set_state(struct twl_clks_softc *sc, struct twl_clk_entry *clk,
+ int enable)
+{
+ int xlocked;
+ int err;
+ uint8_t grp;
+
+ TWL_CLKS_ASSERT_LOCKED(sc);
+
+ /* Upgrade the lock to exclusive because about to perform read-mod-write */
+ xlocked = sx_xlocked(&sc->sc_sx);
+ if (!xlocked)
+ TWL_CLKS_LOCK_UPGRADE(sc);
+
+ err = twl_clks_read_1(sc, clk, TWL_CLKS_GRP, &grp);
+ if (err)
+ goto done;
+
+ if (twl_is_4030(sc->sc_pdev)) {
+
+ /* On the TWL4030 we just need to ensure the clock is in the right
+ * power domain, don't need to turn on explicitly like TWL6030.
+ */
+ if (enable)
+ grp |= TWL4030_P1_GRP;
+ else
+ grp &= ~(TWL4030_P1_GRP | TWL4030_P2_GRP | TWL4030_P3_GRP);
+
+ err = twl_clks_write_1(sc, clk, TWL_CLKS_GRP, grp);
+
+ } else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) {
+
+ /* Make sure the clock belongs to at least the APP power group */
+ if (twl_is_6030(sc->sc_pdev) && !(grp & TWL6030_P1_GRP)) {
+ grp |= TWL6030_P1_GRP;
+ err = twl_clks_write_1(sc, clk, TWL_CLKS_GRP, grp);
+ if (err)
+ goto done;
+ }
+
+ /* On TWL6030 we need to make sure we disable power for all groups */
+ if (twl_is_6030(sc->sc_pdev))
+ grp = TWL6030_P1_GRP | TWL6030_P2_GRP | TWL6030_P3_GRP;
+ else
+ grp = 0x00;
+
+ /* Set the state of the clock */
+ if (enable)
+ err = twl_clks_write_1(sc, clk, TWL_CLKS_STATE, (grp << 5) | 0x01);
+ else
+ err = twl_clks_write_1(sc, clk, TWL_CLKS_STATE, (grp << 5));
+
+ } else {
+
+ err = EINVAL;
+ }
+
+done:
+ if (!xlocked)
+ TWL_CLKS_LOCK_DOWNGRADE(sc);
+
+ if ((twl_clks_debug > 1) && !err)
+ device_printf(sc->sc_dev, "%s : %sabled\n", clk->name,
+ enable ? "en" : "dis");
+
+ return (err);
+}
+
+
+/**
+ * twl_clks_disable - disables a clock output
+ * @dev: TWL clk device
+* @name: the name of the clock
+ *
+ * LOCKING:
+ * Internally the function takes and releases the TWL lock.
+ *
+ * RETURNS:
+* Zero on success or an error code on failure.
+ */
+int
+twl_clks_disable(device_t dev, const char *name)
+{
+ struct twl_clks_softc *sc = device_get_softc(dev);
+ struct twl_clk_entry *clk;
+ int err = EINVAL;
+
+ TWL_CLKS_SLOCK(sc);
+
+ LIST_FOREACH(clk, &sc->sc_clks_list, link) {
+ if (strcmp(clk->name, name) == 0) {
+ err = twl_clks_set_state(sc, clk, 0);
+ break;
+ }
+ }
+
+ TWL_CLKS_SUNLOCK(sc);
+ return (err);
+}
+
+/**
+ * twl_clks_enable - enables a clock output
+ * @dev: TWL clk device
+ * @name: the name of the clock
+ *
+ * LOCKING:
+ * Internally the function takes and releases the TWL CLKS lock.
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+int
+twl_clks_enable(device_t dev, const char *name)
+{
+ struct twl_clks_softc *sc = device_get_softc(dev);
+ struct twl_clk_entry *clk;
+ int err = EINVAL;
+
+ TWL_CLKS_SLOCK(sc);
+
+ LIST_FOREACH(clk, &sc->sc_clks_list, link) {
+ if (strcmp(clk->name, name) == 0) {
+ err = twl_clks_set_state(sc, clk, 1);
+ break;
+ }
+ }
+
+ TWL_CLKS_SUNLOCK(sc);
+ return (err);
+}
+
+/**
+ * twl_clks_sysctl_clock - reads the state of the clock
+ * @SYSCTL_HANDLER_ARGS: arguments for the callback
+ *
+ * Returns the clock status; disabled is zero and enabled is non-zero.
+ *
+ * LOCKING:
+ * It's expected the TWL lock is held while this function is called.
+ *
+ * RETURNS:
+ * EIO if device is not present, otherwise 0 is returned.
+ */
+static int
+twl_clks_sysctl_clock(SYSCTL_HANDLER_ARGS)
+{
+ struct twl_clks_softc *sc = (struct twl_clks_softc*)arg1;
+ int err;
+ int enabled = 0;
+
+ if ((err = twl_clks_is_enabled(sc->sc_dev, oidp->oid_name, &enabled)) != 0)
+ return err;
+
+ return sysctl_handle_int(oidp, &enabled, 0, req);
+}
+
+/**
+ * twl_clks_add_clock - adds single clock sysctls for the device
+ * @sc: device soft context
+ * @name: the name of the regulator
+ * @nsub: the number of the subdevice
+ * @regbase: the base address of the clocks registers
+ *
+ * Adds a single clock to the device and also a sysctl interface for
+ * querying it's status.
+ *
+ * LOCKING:
+ * It's expected the exclusive lock is held while this function is called.
+ *
+ * RETURNS:
+ * Pointer to the new clock entry on success, otherwise NULL on failure.
+ */
+static struct twl_clk_entry*
+twl_clks_add_clock(struct twl_clks_softc *sc, const char *name,
+ uint8_t nsub, uint8_t regbase)
+{
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
+ struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
+ struct twl_clk_entry *new;
+
+ TWL_CLKS_ASSERT_LOCKED(sc);
+
+ new = malloc(sizeof(struct twl_clk_entry), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (new == NULL)
+ return (NULL);
+
+
+ strncpy(new->name, name, TWL_CLKS_MAX_NAMELEN);
+ new->name[TWL_CLKS_MAX_NAMELEN - 1] = '\0';
+
+ new->sub_dev = nsub;
+ new->reg_off = regbase;
+
+
+
+ /* Add a sysctl entry for the clock */
+ new->oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, name,
+ CTLTYPE_INT | CTLFLAG_RD, sc, 0,
+ twl_clks_sysctl_clock, "I", "external clock");
+
+ /* Finally add the regulator to list of supported regulators */
+ LIST_INSERT_HEAD(&sc->sc_clks_list, new, link);
+
+ return (new);
+}
+
+/**
+ * twl_clks_add_clocks - populates the internal list of clocks
+ * @sc: device soft context
+ * @chip: the name of the chip used in the hints
+ * @clks the list of clocks supported by the device
+ *
+ * Loops over the list of clocks and adds them to the device context. Also
+ * scans the FDT to determine if there are any clocks that should be
+ * enabled/disabled automatically.
+ *
+ * LOCKING:
+ * Internally takes the exclusive lock while adding the clocks to the
+ * device context.
+ *
+ * RETURNS:
+ * Always returns 0.
+ */
+static int
+twl_clks_add_clocks(struct twl_clks_softc *sc, const struct twl_clock *clks)
+{
+ int err;
+ const struct twl_clock *walker;
+ struct twl_clk_entry *entry;
+ phandle_t child;
+ char rnames[256];
+ char *name, *state;
+ int len = 0, prop_len;
+ int enable;
+
+
+ TWL_CLKS_XLOCK(sc);
+
+ /* Add the regulators from the list */
+ walker = &clks[0];
+ while (walker->name != NULL) {
+
+ /* Add the regulator to the list */
+ entry = twl_clks_add_clock(sc, walker->name, walker->subdev,
+ walker->regbase);
+ if (entry == NULL)
+ continue;
+
+ walker++;
+ }
+
+ /* Check for any FDT settings that need to be applied */
+ child = ofw_bus_get_node(sc->sc_pdev);
+ if (child) {
+
+ prop_len = OF_getprop(child, "external-clocks", rnames, sizeof(rnames));
+ while (len < prop_len) {
+ name = rnames + len;
+ len += strlen(name) + 1;
+ if ((len >= prop_len) || (name[0] == '\0'))
+ break;
+
+ state = rnames + len;
+ len += strlen(state) + 1;
+ if (state[0] == '\0')
+ break;
+
+ enable = !strncmp(state, "on", 2);
+
+ LIST_FOREACH(entry, &sc->sc_clks_list, link) {
+ if (strcmp(entry->name, name) == 0) {
+ twl_clks_set_state(sc, entry, enable);
+ break;
+ }
+ }
+ }
+ }
+
+ TWL_CLKS_XUNLOCK(sc);
+
+
+ if (twl_clks_debug) {
+ LIST_FOREACH(entry, &sc->sc_clks_list, link) {
+ err = twl_clks_is_enabled(sc->sc_dev, entry->name, &enable);
+ if (!err)
+ device_printf(sc->sc_dev, "%s : %s\n", entry->name,
+ enable ? "on" : "off");
+ }
+ }
+
+ return (0);
+}
+
+/**
+ * twl_clks_init - initialises the list of clocks
+ * @dev: the twl_clks device
+ *
+ * This function is called as an intrhook once interrupts have been enabled,
+ * this is done so that the driver has the option to enable/disable a clock
+ * based on settings providied in the FDT.
+ *
+ * LOCKING:
+ * May takes the exclusive lock in the function.
+ */
+static void
+twl_clks_init(void *dev)
+{
+ struct twl_clks_softc *sc;
+
+ sc = device_get_softc((device_t)dev);
+
+ if (twl_is_4030(sc->sc_pdev))
+ twl_clks_add_clocks(sc, twl4030_clocks);
+ else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev))
+ twl_clks_add_clocks(sc, twl6030_clocks);
+
+ config_intrhook_disestablish(&sc->sc_init_hook);
+}
+
+static int
+twl_clks_probe(device_t dev)
+{
+ if (twl_is_4030(device_get_parent(dev)))
+ device_set_desc(dev, "TI TWL4030 PMIC External Clocks");
+ else if (twl_is_6025(device_get_parent(dev)) ||
+ twl_is_6030(device_get_parent(dev)))
+ device_set_desc(dev, "TI TWL6025/TWL6030 PMIC External Clocks");
+ else
+ return (ENXIO);
+
+ return (0);
+}
+
+static int
+twl_clks_attach(device_t dev)
+{
+ struct twl_clks_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_pdev = device_get_parent(dev);
+
+ TWL_CLKS_LOCK_INIT(sc);
+
+ LIST_INIT(&sc->sc_clks_list);
+
+
+ sc->sc_init_hook.ich_func = twl_clks_init;
+ sc->sc_init_hook.ich_arg = dev;
+
+ if (config_intrhook_establish(&sc->sc_init_hook) != 0)
+ return (ENOMEM);
+
+ return (0);
+}
+
+static int
+twl_clks_detach(device_t dev)
+{
+ struct twl_clks_softc *sc;
+ struct twl_clk_entry *clk;
+ struct twl_clk_entry *tmp;
+
+ sc = device_get_softc(dev);
+
+ TWL_CLKS_XLOCK(sc);
+
+ LIST_FOREACH_SAFE(clk, &sc->sc_clks_list, link, tmp) {
+ LIST_REMOVE(clk, link);
+ sysctl_remove_oid(clk->oid, 1, 0);
+ free(clk, M_DEVBUF);
+ }
+
+ TWL_CLKS_XUNLOCK(sc);
+
+ TWL_CLKS_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static device_method_t twl_clks_methods[] = {
+ DEVMETHOD(device_probe, twl_clks_probe),
+ DEVMETHOD(device_attach, twl_clks_attach),
+ DEVMETHOD(device_detach, twl_clks_detach),
+
+ {0, 0},
+};
+
+static driver_t twl_clks_driver = {
+ "twl_clks",
+ twl_clks_methods,
+ sizeof(struct twl_clks_softc),
+};
+
+static devclass_t twl_clks_devclass;
+
+DRIVER_MODULE(twl_clks, twl, twl_clks_driver, twl_clks_devclass, 0, 0);
+MODULE_VERSION(twl_clks, 1);
Property changes on: trunk/sys/arm/ti/twl/twl_clks.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/twl/twl_clks.h
===================================================================
--- trunk/sys/arm/ti/twl/twl_clks.h (rev 0)
+++ trunk/sys/arm/ti/twl/twl_clks.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,39 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012
+ * Ben Gray <bgray at freebsd.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/twl/twl_clks.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+#ifndef _TWL_CLKS_H_
+#define _TWL_CLKS_H_
+
+
+int twl_clks_enable(device_t dev, const char *name);
+int twl_clks_disable(device_t dev, const char *name);
+int twl_clks_is_enabled(device_t dev, const char *name, int *enabled);
+
+
+#endif /* _TWL_CLKS_H_ */
Property changes on: trunk/sys/arm/ti/twl/twl_clks.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/twl/twl_vreg.c
===================================================================
--- trunk/sys/arm/ti/twl/twl_vreg.c (rev 0)
+++ trunk/sys/arm/ti/twl/twl_vreg.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1055 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/twl/twl_vreg.c 263456 2014-03-21 00:19:20Z dim $");
+
+/*
+ * Texas Instruments TWL4030/TWL5030/TWL60x0/TPS659x0 Power Management.
+ *
+ * This driver covers the voltages regulators (LDO), allows for enabling &
+ * disabling the voltage output and adjusting the voltage level.
+ *
+ * Voltage regulators can belong to different power groups, in this driver we
+ * put the regulators under our control in the "Application power group".
+ *
+ *
+ * FLATTENED DEVICE TREE (FDT)
+ * Startup override settings can be specified in the FDT, if they are they
+ * should be under the twl parent device and take the following form:
+ *
+ * voltage-regulators = "name1", "millivolts1",
+ * "name2", "millivolts2";
+ *
+ * Each override should be a pair, the first entry is the name of the regulator
+ * the second is the voltage (in millivolts) to set for the given regulator.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+
+#include "twl.h"
+#include "twl_vreg.h"
+
+static int twl_vreg_debug = 1;
+
+
+/*
+ * Power Groups bits for the 4030 and 6030 devices
+ */
+#define TWL4030_P3_GRP 0x80 /* Peripherals, power group */
+#define TWL4030_P2_GRP 0x40 /* Modem power group */
+#define TWL4030_P1_GRP 0x20 /* Application power group (FreeBSD control) */
+
+#define TWL6030_P3_GRP 0x04 /* Modem power group */
+#define TWL6030_P2_GRP 0x02 /* Connectivity power group */
+#define TWL6030_P1_GRP 0x01 /* Application power group (FreeBSD control) */
+
+/*
+ * Register offsets within a LDO regulator register set
+ */
+#define TWL_VREG_GRP 0x00 /* Regulator GRP register */
+#define TWL_VREG_STATE 0x02
+#define TWL_VREG_VSEL 0x03 /* Voltage select register */
+
+#define UNDF 0xFFFF
+
+static const uint16_t twl6030_voltages[] = {
+ 0000, 1000, 1100, 1200, 1300, 1400, 1500, 1600,
+ 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400,
+ 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200,
+ 3300, UNDF, UNDF, UNDF, UNDF, UNDF, UNDF, 2750
+};
+
+static const uint16_t twl4030_vaux1_voltages[] = {
+ 1500, 1800, 2500, 2800, 3000, 3000, 3000, 3000
+};
+static const uint16_t twl4030_vaux2_voltages[] = {
+ 1700, 1700, 1900, 1300, 1500, 1800, 2000, 2500,
+ 2100, 2800, 2200, 2300, 2400, 2400, 2400, 2400
+};
+static const uint16_t twl4030_vaux3_voltages[] = {
+ 1500, 1800, 2500, 2800, 3000, 3000, 3000, 3000
+};
+static const uint16_t twl4030_vaux4_voltages[] = {
+ 700, 1000, 1200, 1300, 1500, 1800, 1850, 2500,
+ 2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150
+};
+static const uint16_t twl4030_vmmc1_voltages[] = {
+ 1850, 2850, 3000, 3150
+};
+static const uint16_t twl4030_vmmc2_voltages[] = {
+ 1000, 1000, 1200, 1300, 1500, 1800, 1850, 2500,
+ 2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150
+};
+static const uint16_t twl4030_vpll1_voltages[] = {
+ 1000, 1200, 1300, 1800, 2800, 3000, 3000, 3000
+};
+static const uint16_t twl4030_vpll2_voltages[] = {
+ 700, 1000, 1200, 1300, 1500, 1800, 1850, 2500,
+ 2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150
+};
+static const uint16_t twl4030_vsim_voltages[] = {
+ 1000, 1200, 1300, 1800, 2800, 3000, 3000, 3000
+};
+static const uint16_t twl4030_vdac_voltages[] = {
+ 1200, 1300, 1800, 1800
+};
+#if 0 /* vdd1, vdd2, vdio, not currently used. */
+static const uint16_t twl4030_vdd1_voltages[] = {
+ 800, 1450
+};
+static const uint16_t twl4030_vdd2_voltages[] = {
+ 800, 1450, 1500
+};
+static const uint16_t twl4030_vio_voltages[] = {
+ 1800, 1850
+};
+#endif
+static const uint16_t twl4030_vintana2_voltages[] = {
+ 2500, 2750
+};
+
+/**
+ * Support voltage regulators for the different IC's
+ */
+struct twl_regulator {
+ const char *name;
+ uint8_t subdev;
+ uint8_t regbase;
+
+ uint16_t fixedvoltage;
+
+ const uint16_t *voltages;
+ uint32_t num_voltages;
+};
+
+#define TWL_REGULATOR_ADJUSTABLE(name, subdev, reg, voltages) \
+ { name, subdev, reg, 0, voltages, (sizeof(voltages)/sizeof(voltages[0])) }
+#define TWL_REGULATOR_FIXED(name, subdev, reg, voltage) \
+ { name, subdev, reg, voltage, NULL, 0 }
+
+static const struct twl_regulator twl4030_regulators[] = {
+ TWL_REGULATOR_ADJUSTABLE("vaux1", 0, 0x17, twl4030_vaux1_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vaux2", 0, 0x1B, twl4030_vaux2_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vaux3", 0, 0x1F, twl4030_vaux3_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vaux4", 0, 0x23, twl4030_vaux4_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vmmc1", 0, 0x27, twl4030_vmmc1_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vmmc2", 0, 0x2B, twl4030_vmmc2_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vpll1", 0, 0x2F, twl4030_vpll1_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vpll2", 0, 0x33, twl4030_vpll2_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vsim", 0, 0x37, twl4030_vsim_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vdac", 0, 0x3B, twl4030_vdac_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vintana2", 0, 0x43, twl4030_vintana2_voltages),
+ TWL_REGULATOR_FIXED("vintana1", 0, 0x3F, 1500),
+ TWL_REGULATOR_FIXED("vintdig", 0, 0x47, 1500),
+ TWL_REGULATOR_FIXED("vusb1v5", 0, 0x71, 1500),
+ TWL_REGULATOR_FIXED("vusb1v8", 0, 0x74, 1800),
+ TWL_REGULATOR_FIXED("vusb3v1", 0, 0x77, 3100),
+ { NULL, 0, 0x00, 0, NULL, 0 }
+};
+
+static const struct twl_regulator twl6030_regulators[] = {
+ TWL_REGULATOR_ADJUSTABLE("vaux1", 0, 0x84, twl6030_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vaux2", 0, 0x89, twl6030_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vaux3", 0, 0x8C, twl6030_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vmmc", 0, 0x98, twl6030_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vpp", 0, 0x9C, twl6030_voltages),
+ TWL_REGULATOR_ADJUSTABLE("vusim", 0, 0xA4, twl6030_voltages),
+ TWL_REGULATOR_FIXED("vmem", 0, 0x64, 1800),
+ TWL_REGULATOR_FIXED("vusb", 0, 0xA0, 3300),
+ TWL_REGULATOR_FIXED("v1v8", 0, 0x46, 1800),
+ TWL_REGULATOR_FIXED("v2v1", 0, 0x4C, 2100),
+ TWL_REGULATOR_FIXED("v1v29", 0, 0x40, 1290),
+ TWL_REGULATOR_FIXED("vcxio", 0, 0x90, 1800),
+ TWL_REGULATOR_FIXED("vdac", 0, 0x94, 1800),
+ TWL_REGULATOR_FIXED("vana", 0, 0x80, 2100),
+ { NULL, 0, 0x00, 0, NULL, 0 }
+};
+
+#define TWL_VREG_MAX_NAMELEN 32
+
+struct twl_regulator_entry {
+ LIST_ENTRY(twl_regulator_entry) entries;
+ char name[TWL_VREG_MAX_NAMELEN];
+ struct sysctl_oid *oid;
+ uint8_t sub_dev; /* TWL sub-device group */
+ uint8_t reg_off; /* base register offset for the LDO */
+ uint16_t fixed_voltage; /* the (milli)voltage if LDO is fixed */
+ const uint16_t *supp_voltages; /* pointer to an array of possible voltages */
+ uint32_t num_supp_voltages; /* the number of supplied voltages */
+};
+
+struct twl_vreg_softc {
+ device_t sc_dev;
+ device_t sc_pdev;
+ struct sx sc_sx;
+
+ struct intr_config_hook sc_init_hook;
+ LIST_HEAD(twl_regulator_list, twl_regulator_entry) sc_vreg_list;
+};
+
+
+#define TWL_VREG_XLOCK(_sc) sx_xlock(&(_sc)->sc_sx)
+#define TWL_VREG_XUNLOCK(_sc) sx_xunlock(&(_sc)->sc_sx)
+#define TWL_VREG_SLOCK(_sc) sx_slock(&(_sc)->sc_sx)
+#define TWL_VREG_SUNLOCK(_sc) sx_sunlock(&(_sc)->sc_sx)
+#define TWL_VREG_LOCK_INIT(_sc) sx_init(&(_sc)->sc_sx, "twl_vreg")
+#define TWL_VREG_LOCK_DESTROY(_sc) sx_destroy(&(_sc)->sc_sx);
+
+#define TWL_VREG_ASSERT_LOCKED(_sc) sx_assert(&(_sc)->sc_sx, SA_LOCKED);
+
+#define TWL_VREG_LOCK_UPGRADE(_sc) \
+ do { \
+ while (!sx_try_upgrade(&(_sc)->sc_sx)) \
+ pause("twl_vreg_ex", (hz / 100)); \
+ } while(0)
+#define TWL_VREG_LOCK_DOWNGRADE(_sc) sx_downgrade(&(_sc)->sc_sx);
+
+
+
+
+/**
+ * twl_vreg_read_1 - read single register from the TWL device
+ * twl_vreg_write_1 - write a single register in the TWL device
+ * @sc: device context
+ * @clk: the clock device we're reading from / writing to
+ * @off: offset within the clock's register set
+ * @val: the value to write or a pointer to a variable to store the result
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+static inline int
+twl_vreg_read_1(struct twl_vreg_softc *sc, struct twl_regulator_entry *regulator,
+ uint8_t off, uint8_t *val)
+{
+ return (twl_read(sc->sc_pdev, regulator->sub_dev,
+ regulator->reg_off + off, val, 1));
+}
+
+static inline int
+twl_vreg_write_1(struct twl_vreg_softc *sc, struct twl_regulator_entry *regulator,
+ uint8_t off, uint8_t val)
+{
+ return (twl_write(sc->sc_pdev, regulator->sub_dev,
+ regulator->reg_off + off, &val, 1));
+}
+
+/**
+ * twl_millivolt_to_vsel - gets the vsel bit value to write into the register
+ * for a desired voltage and regulator
+ * @sc: the device soft context
+ * @regulator: pointer to the regulator device
+ * @millivolts: the millivolts to find the bit value for
+ * @vsel: upon return will contain the corresponding register value
+ *
+ * Accepts a (milli)voltage value and tries to find the closest match to the
+ * actual supported voltages for the given regulator. If a match is found
+ * within 100mv of the target, @vsel is written with the match and 0 is
+ * returned. If no voltage match is found the function returns an non-zero
+ * value.
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+static int
+twl_vreg_millivolt_to_vsel(struct twl_vreg_softc *sc,
+ struct twl_regulator_entry *regulator, int millivolts, uint8_t *vsel)
+{
+ int delta, smallest_delta;
+ unsigned i, closest_idx;
+
+ TWL_VREG_ASSERT_LOCKED(sc);
+
+ if (regulator->supp_voltages == NULL)
+ return (EINVAL);
+
+ /* Loop over the support voltages and try and find the closest match */
+ closest_idx = 0;
+ smallest_delta = 0x7fffffff;
+ for (i = 0; i < regulator->num_supp_voltages; i++) {
+
+ /* Ignore undefined values */
+ if (regulator->supp_voltages[i] == UNDF)
+ continue;
+
+ /* Calculate the difference */
+ delta = millivolts - (int)regulator->supp_voltages[i];
+ if (abs(delta) < smallest_delta) {
+ smallest_delta = abs(delta);
+ closest_idx = i;
+ }
+ }
+
+ /* Check we got a voltage that was within 100mv of the actual target, this
+ * is just a value I picked out of thin air.
+ */
+ if ((smallest_delta > 100) && (closest_idx < 0x100))
+ return (EINVAL);
+
+ *vsel = closest_idx;
+ return (0);
+}
+
+/**
+ * twl_vreg_is_regulator_enabled - returns the enabled status of the regulator
+ * @sc: the device soft context
+ * @regulator: pointer to the regulator device
+ * @enabled: stores the enabled status, zero disabled, non-zero enabled
+ *
+ * LOCKING:
+ * On entry expects the TWL VREG lock to be held. Will upgrade the lock to
+ * exclusive if not already but, if so, it will be downgraded again before
+ * returning.
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+static int
+twl_vreg_is_regulator_enabled(struct twl_vreg_softc *sc,
+ struct twl_regulator_entry *regulator, int *enabled)
+{
+ int err;
+ uint8_t grp;
+ uint8_t state;
+ int xlocked;
+
+ if (enabled == NULL)
+ return (EINVAL);
+
+ TWL_VREG_ASSERT_LOCKED(sc);
+
+ xlocked = sx_xlocked(&sc->sc_sx);
+ if (!xlocked)
+ TWL_VREG_LOCK_UPGRADE(sc);
+
+ /* The status reading is different for the different devices */
+ if (twl_is_4030(sc->sc_pdev)) {
+
+ err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &state);
+ if (err)
+ goto done;
+
+ *enabled = (state & TWL4030_P1_GRP);
+
+ } else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) {
+
+ /* Check the regulator is in the application group */
+ if (twl_is_6030(sc->sc_pdev)) {
+ err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp);
+ if (err)
+ goto done;
+
+ if (!(grp & TWL6030_P1_GRP)) {
+ *enabled = 0; /* disabled */
+ goto done;
+ }
+ }
+
+ /* Read the application mode state and verify it's ON */
+ err = twl_vreg_read_1(sc, regulator, TWL_VREG_STATE, &state);
+ if (err)
+ goto done;
+
+ *enabled = ((state & 0x0C) == 0x04);
+
+ } else {
+ err = EINVAL;
+ }
+
+done:
+ if (!xlocked)
+ TWL_VREG_LOCK_DOWNGRADE(sc);
+
+ return (err);
+}
+
+/**
+ * twl_vreg_disable_regulator - disables a voltage regulator
+ * @sc: the device soft context
+ * @regulator: pointer to the regulator device
+ *
+ * Disables the regulator which will stop the output drivers.
+ *
+ * LOCKING:
+ * On entry expects the TWL VREG lock to be held. Will upgrade the lock to
+ * exclusive if not already but, if so, it will be downgraded again before
+ * returning.
+ *
+ * RETURNS:
+ * Zero on success or a positive error code on failure.
+ */
+static int
+twl_vreg_disable_regulator(struct twl_vreg_softc *sc,
+ struct twl_regulator_entry *regulator)
+{
+ int err = 0;
+ uint8_t grp;
+ int xlocked;
+
+ TWL_VREG_ASSERT_LOCKED(sc);
+
+ xlocked = sx_xlocked(&sc->sc_sx);
+ if (!xlocked)
+ TWL_VREG_LOCK_UPGRADE(sc);
+
+ if (twl_is_4030(sc->sc_pdev)) {
+
+ /* Read the regulator CFG_GRP register */
+ err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp);
+ if (err)
+ goto done;
+
+ /* On the TWL4030 we just need to remove the regulator from all the
+ * power groups.
+ */
+ grp &= ~(TWL4030_P1_GRP | TWL4030_P2_GRP | TWL4030_P3_GRP);
+ err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp);
+
+ } else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) {
+
+ /* On TWL6030 we need to make sure we disable power for all groups */
+ if (twl_is_6030(sc->sc_pdev))
+ grp = TWL6030_P1_GRP | TWL6030_P2_GRP | TWL6030_P3_GRP;
+ else
+ grp = 0x00;
+
+ /* Write the resource state to "OFF" */
+ err = twl_vreg_write_1(sc, regulator, TWL_VREG_STATE, (grp << 5));
+ }
+
+done:
+ if (!xlocked)
+ TWL_VREG_LOCK_DOWNGRADE(sc);
+
+ return (err);
+}
+
+/**
+ * twl_vreg_enable_regulator - enables the voltage regulator
+ * @sc: the device soft context
+ * @regulator: pointer to the regulator device
+ *
+ * Enables the regulator which will enable the voltage out at the currently
+ * set voltage. Set the voltage before calling this function to avoid
+ * driving the voltage too high/low by mistake.
+ *
+ * LOCKING:
+ * On entry expects the TWL VREG lock to be held. Will upgrade the lock to
+ * exclusive if not already but, if so, it will be downgraded again before
+ * returning.
+ *
+ * RETURNS:
+ * Zero on success or a positive error code on failure.
+ */
+static int
+twl_vreg_enable_regulator(struct twl_vreg_softc *sc,
+ struct twl_regulator_entry *regulator)
+{
+ int err;
+ uint8_t grp;
+ int xlocked;
+
+ TWL_VREG_ASSERT_LOCKED(sc);
+
+ xlocked = sx_xlocked(&sc->sc_sx);
+ if (!xlocked)
+ TWL_VREG_LOCK_UPGRADE(sc);
+
+
+ err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp);
+ if (err)
+ goto done;
+
+ /* Enable the regulator by ensuring it's in the application power group
+ * and is in the "on" state.
+ */
+ if (twl_is_4030(sc->sc_pdev)) {
+
+ /* On the TWL4030 we just need to ensure the regulator is in the right
+ * power domain, don't need to turn on explicitly like TWL6030.
+ */
+ grp |= TWL4030_P1_GRP;
+ err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp);
+
+ } else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) {
+
+ if (twl_is_6030(sc->sc_pdev) && !(grp & TWL6030_P1_GRP)) {
+ grp |= TWL6030_P1_GRP;
+ err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp);
+ if (err)
+ goto done;
+ }
+
+ /* Write the resource state to "ON" */
+ err = twl_vreg_write_1(sc, regulator, TWL_VREG_STATE, (grp << 5) | 0x01);
+ }
+
+done:
+ if (!xlocked)
+ TWL_VREG_LOCK_DOWNGRADE(sc);
+
+ return (err);
+}
+
+/**
+ * twl_vreg_write_regulator_voltage - sets the voltage level on a regulator
+ * @sc: the device soft context
+ * @regulator: pointer to the regulator structure
+ * @millivolts: the voltage to set
+ *
+ * Sets the voltage output on a given regulator, if the regulator is not
+ * enabled, it will be enabled.
+ *
+ * LOCKING:
+ * On entry expects the TWL VREG lock to be held, may upgrade the lock to
+ * exclusive but if so it will be downgraded once again before returning.
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+static int
+twl_vreg_write_regulator_voltage(struct twl_vreg_softc *sc,
+ struct twl_regulator_entry *regulator, int millivolts)
+{
+ int err;
+ uint8_t vsel;
+ int xlocked;
+
+ TWL_VREG_ASSERT_LOCKED(sc);
+
+ /* If millivolts is zero then we simply disable the output */
+ if (millivolts == 0)
+ return (twl_vreg_disable_regulator(sc, regulator));
+
+ /* If the regulator has a fixed voltage then check the setting matches
+ * and simply enable.
+ */
+ if (regulator->supp_voltages == NULL || regulator->num_supp_voltages == 0) {
+ if (millivolts != regulator->fixed_voltage)
+ return (EINVAL);
+
+ return (twl_vreg_enable_regulator(sc, regulator));
+ }
+
+ /* Get the VSEL value for the given voltage */
+ err = twl_vreg_millivolt_to_vsel(sc, regulator, millivolts, &vsel);
+ if (err)
+ return (err);
+
+
+ /* Need to upgrade because writing the voltage and enabling should be atomic */
+ xlocked = sx_xlocked(&sc->sc_sx);
+ if (!xlocked)
+ TWL_VREG_LOCK_UPGRADE(sc);
+
+
+ /* Set voltage and enable (atomically) */
+ err = twl_vreg_write_1(sc, regulator, TWL_VREG_VSEL, (vsel & 0x1f));
+ if (!err) {
+ err = twl_vreg_enable_regulator(sc, regulator);
+ }
+
+ if (!xlocked)
+ TWL_VREG_LOCK_DOWNGRADE(sc);
+
+ if ((twl_vreg_debug > 1) && !err)
+ device_printf(sc->sc_dev, "%s : setting voltage to %dmV (vsel: 0x%x)\n",
+ regulator->name, millivolts, vsel);
+
+ return (err);
+}
+
+/**
+ * twl_vreg_read_regulator_voltage - reads the voltage on a given regulator
+ * @sc: the device soft context
+ * @regulator: pointer to the regulator structure
+ * @millivolts: upon return will contain the voltage on the regulator
+ *
+ * LOCKING:
+ * On entry expects the TWL VREG lock to be held. It will upgrade the lock to
+ * exclusive if not already, but if so, it will be downgraded again before
+ * returning.
+ *
+ * RETURNS:
+ * Zero on success, or otherwise an error code.
+ */
+static int
+twl_vreg_read_regulator_voltage(struct twl_vreg_softc *sc,
+ struct twl_regulator_entry *regulator, int *millivolts)
+{
+ int err;
+ int en = 0;
+ int xlocked;
+ uint8_t vsel;
+
+ TWL_VREG_ASSERT_LOCKED(sc);
+
+ /* Need to upgrade the lock because checking enabled state and voltage
+ * should be atomic.
+ */
+ xlocked = sx_xlocked(&sc->sc_sx);
+ if (!xlocked)
+ TWL_VREG_LOCK_UPGRADE(sc);
+
+
+ /* Check if the regulator is currently enabled */
+ err = twl_vreg_is_regulator_enabled(sc, regulator, &en);
+ if (err)
+ goto done;
+
+ *millivolts = 0;
+ if (!en)
+ goto done;
+
+
+ /* Not all voltages are adjustable */
+ if (regulator->supp_voltages == NULL || !regulator->num_supp_voltages) {
+ *millivolts = regulator->fixed_voltage;
+ goto done;
+ }
+
+ /* For variable voltages read the voltage register */
+ err = twl_vreg_read_1(sc, regulator, TWL_VREG_VSEL, &vsel);
+ if (err)
+ goto done;
+
+ vsel &= (regulator->num_supp_voltages - 1);
+ if (regulator->supp_voltages[vsel] == UNDF) {
+ err = EINVAL;
+ goto done;
+ }
+
+ *millivolts = regulator->supp_voltages[vsel];
+
+done:
+ if (!xlocked)
+ TWL_VREG_LOCK_DOWNGRADE(sc);
+
+ if ((twl_vreg_debug > 1) && !err)
+ device_printf(sc->sc_dev, "%s : reading voltage is %dmV (vsel: 0x%x)\n",
+ regulator->name, *millivolts, vsel);
+
+ return (err);
+}
+
+/**
+ * twl_vreg_get_voltage - public interface to read the voltage on a regulator
+ * @dev: TWL VREG device
+ * @name: the name of the regulator to read the voltage of
+ * @millivolts: pointer to an integer that upon return will contain the mV
+ *
+ * If the regulator is disabled the function will set the @millivolts to zero.
+ *
+ * LOCKING:
+ * Internally the function takes and releases the TWL VREG lock.
+ *
+ * RETURNS:
+ * Zero on success or a negative error code on failure.
+ */
+int
+twl_vreg_get_voltage(device_t dev, const char *name, int *millivolts)
+{
+ struct twl_vreg_softc *sc;
+ struct twl_regulator_entry *regulator;
+ int err = EINVAL;
+
+ if (millivolts == NULL)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ TWL_VREG_SLOCK(sc);
+
+ LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) {
+ if (strcmp(regulator->name, name) == 0) {
+ err = twl_vreg_read_regulator_voltage(sc, regulator, millivolts);
+ break;
+ }
+ }
+
+ TWL_VREG_SUNLOCK(sc);
+
+ return (err);
+}
+
+/**
+ * twl_vreg_set_voltage - public interface to write the voltage on a regulator
+ * @dev: TWL VREG device
+ * @name: the name of the regulator to read the voltage of
+ * @millivolts: the voltage to set in millivolts
+ *
+ * Sets the output voltage on a given regulator. If the regulator is a fixed
+ * voltage reg then the @millivolts value should match the fixed voltage. If
+ * a variable regulator then the @millivolt value must fit within the max/min
+ * range of the given regulator.
+ *
+ * LOCKING:
+ * Internally the function takes and releases the TWL VREG lock.
+ *
+ * RETURNS:
+ * Zero on success or a negative error code on failure.
+ */
+int
+twl_vreg_set_voltage(device_t dev, const char *name, int millivolts)
+{
+ struct twl_vreg_softc *sc;
+ struct twl_regulator_entry *regulator;
+ int err = EINVAL;
+
+ sc = device_get_softc(dev);
+
+ TWL_VREG_SLOCK(sc);
+
+ LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) {
+ if (strcmp(regulator->name, name) == 0) {
+ err = twl_vreg_write_regulator_voltage(sc, regulator, millivolts);
+ break;
+ }
+ }
+
+ TWL_VREG_SUNLOCK(sc);
+
+ return (err);
+}
+
+/**
+ * twl_sysctl_voltage - reads or writes the voltage for a regulator
+ * @SYSCTL_HANDLER_ARGS: arguments for the callback
+ *
+ * Callback for the sysctl entry for the regulator, simply used to return
+ * the voltage on a particular regulator.
+ *
+ * LOCKING:
+ * Takes the TWL_VREG shared lock internally.
+ *
+ * RETURNS:
+ * Zero on success or an error code on failure.
+ */
+static int
+twl_vreg_sysctl_voltage(SYSCTL_HANDLER_ARGS)
+{
+ struct twl_vreg_softc *sc = (struct twl_vreg_softc*)arg1;
+ struct twl_regulator_entry *regulator;
+ int voltage;
+ int found = 0;
+
+ TWL_VREG_SLOCK(sc);
+
+ /* Find the regulator with the matching name */
+ LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) {
+ if (strcmp(regulator->name, oidp->oid_name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ /* Sanity check that we found the regulator */
+ if (!found) {
+ TWL_VREG_SUNLOCK(sc);
+ return (EINVAL);
+ }
+
+ twl_vreg_read_regulator_voltage(sc, regulator, &voltage);
+
+ TWL_VREG_SUNLOCK(sc);
+
+ return sysctl_handle_int(oidp, &voltage, 0, req);
+}
+
+/**
+ * twl_add_regulator - adds single voltage regulator sysctls for the device
+ * @sc: device soft context
+ * @name: the name of the regulator
+ * @nsub: the number of the subdevice
+ * @regbase: the base address of the voltage regulator registers
+ * @fixed_voltage: if a fixed voltage regulator this defines it's voltage
+ * @voltages: if a variable voltage regulator, an array of possible voltages
+ * @num_voltages: the number of entries @voltages
+ *
+ * Adds a voltage regulator to the device and also a sysctl interface for the
+ * regulator.
+ *
+ * LOCKING:
+ * The TWL_VEG exclusive lock must be held while this function is called.
+ *
+ * RETURNS:
+ * Pointer to the new regulator entry on success, otherwise on failure NULL.
+ */
+static struct twl_regulator_entry*
+twl_vreg_add_regulator(struct twl_vreg_softc *sc, const char *name,
+ uint8_t nsub, uint8_t regbase, uint16_t fixed_voltage,
+ const uint16_t *voltages, uint32_t num_voltages)
+{
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
+ struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
+ struct twl_regulator_entry *new;
+
+ new = malloc(sizeof(struct twl_regulator_entry), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (new == NULL)
+ return (NULL);
+
+
+ strncpy(new->name, name, TWL_VREG_MAX_NAMELEN);
+ new->name[TWL_VREG_MAX_NAMELEN - 1] = '\0';
+
+ new->sub_dev = nsub;
+ new->reg_off = regbase;
+
+ new->fixed_voltage = fixed_voltage;
+
+ new->supp_voltages = voltages;
+ new->num_supp_voltages = num_voltages;
+
+
+ /* Add a sysctl entry for the voltage */
+ new->oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, name,
+ CTLTYPE_INT | CTLFLAG_RD, sc, 0,
+ twl_vreg_sysctl_voltage, "I", "voltage regulator");
+
+ /* Finally add the regulator to list of supported regulators */
+ LIST_INSERT_HEAD(&sc->sc_vreg_list, new, entries);
+
+ return (new);
+}
+
+/**
+ * twl_vreg_add_regulators - adds any voltage regulators to the device
+ * @sc: device soft context
+ * @chip: the name of the chip used in the hints
+ * @regulators: the list of possible voltage regulators
+ *
+ * Loops over the list of regulators and matches up with the FDT values,
+ * adjusting the actual voltage based on the supplied values.
+ *
+ * LOCKING:
+ * The TWL_VEG exclusive lock must be held while this function is called.
+ *
+ * RETURNS:
+ * Always returns 0.
+ */
+static int
+twl_vreg_add_regulators(struct twl_vreg_softc *sc,
+ const struct twl_regulator *regulators)
+{
+ int err;
+ int millivolts;
+ const struct twl_regulator *walker;
+ struct twl_regulator_entry *entry;
+ phandle_t child;
+ char rnames[256];
+ char *name, *voltage;
+ int len = 0, prop_len;
+
+
+ /* Add the regulators from the list */
+ walker = ®ulators[0];
+ while (walker->name != NULL) {
+
+ /* Add the regulator to the list */
+ entry = twl_vreg_add_regulator(sc, walker->name, walker->subdev,
+ walker->regbase, walker->fixedvoltage,
+ walker->voltages, walker->num_voltages);
+ if (entry == NULL)
+ continue;
+
+ walker++;
+ }
+
+
+ /* Check if the FDT is telling us to set any voltages */
+ child = ofw_bus_get_node(sc->sc_pdev);
+ if (child) {
+
+ prop_len = OF_getprop(child, "voltage-regulators", rnames, sizeof(rnames));
+ while (len < prop_len) {
+ name = rnames + len;
+ len += strlen(name) + 1;
+ if ((len >= prop_len) || (name[0] == '\0'))
+ break;
+
+ voltage = rnames + len;
+ len += strlen(voltage) + 1;
+ if (voltage[0] == '\0')
+ break;
+
+ millivolts = strtoul(voltage, NULL, 0);
+
+ LIST_FOREACH(entry, &sc->sc_vreg_list, entries) {
+ if (strcmp(entry->name, name) == 0) {
+ twl_vreg_write_regulator_voltage(sc, entry, millivolts);
+ break;
+ }
+ }
+ }
+ }
+
+
+ if (twl_vreg_debug) {
+ LIST_FOREACH(entry, &sc->sc_vreg_list, entries) {
+ err = twl_vreg_read_regulator_voltage(sc, entry, &millivolts);
+ if (!err)
+ device_printf(sc->sc_dev, "%s : %d mV\n", entry->name, millivolts);
+ }
+ }
+
+ return (0);
+}
+
+/**
+ * twl_vreg_init - initialises the list of regulators
+ * @dev: the twl_vreg device
+ *
+ * This function is called as an intrhook once interrupts have been enabled,
+ * this is done so that the driver has the option to enable/disable or set
+ * the voltage level based on settings providied in the FDT.
+ *
+ * LOCKING:
+ * Takes the exclusive lock in the function.
+ */
+static void
+twl_vreg_init(void *dev)
+{
+ struct twl_vreg_softc *sc;
+
+ sc = device_get_softc((device_t)dev);
+
+ TWL_VREG_XLOCK(sc);
+
+ if (twl_is_4030(sc->sc_pdev))
+ twl_vreg_add_regulators(sc, twl4030_regulators);
+ else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev))
+ twl_vreg_add_regulators(sc, twl6030_regulators);
+
+ TWL_VREG_XUNLOCK(sc);
+
+ config_intrhook_disestablish(&sc->sc_init_hook);
+}
+
+static int
+twl_vreg_probe(device_t dev)
+{
+ if (twl_is_4030(device_get_parent(dev)))
+ device_set_desc(dev, "TI TWL4030 PMIC Voltage Regulators");
+ else if (twl_is_6025(device_get_parent(dev)) ||
+ twl_is_6030(device_get_parent(dev)))
+ device_set_desc(dev, "TI TWL6025/TWL6030 PMIC Voltage Regulators");
+ else
+ return (ENXIO);
+
+ return (0);
+}
+
+static int
+twl_vreg_attach(device_t dev)
+{
+ struct twl_vreg_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_pdev = device_get_parent(dev);
+
+ TWL_VREG_LOCK_INIT(sc);
+
+ LIST_INIT(&sc->sc_vreg_list);
+
+ /* We have to wait until interrupts are enabled. I2C read and write
+ * only works if the interrupts are available.
+ */
+ sc->sc_init_hook.ich_func = twl_vreg_init;
+ sc->sc_init_hook.ich_arg = dev;
+
+ if (config_intrhook_establish(&sc->sc_init_hook) != 0)
+ return (ENOMEM);
+
+ return (0);
+}
+
+static int
+twl_vreg_detach(device_t dev)
+{
+ struct twl_vreg_softc *sc;
+ struct twl_regulator_entry *regulator;
+ struct twl_regulator_entry *tmp;
+
+ sc = device_get_softc(dev);
+
+ /* Take the lock and free all the added regulators */
+ TWL_VREG_XLOCK(sc);
+
+ LIST_FOREACH_SAFE(regulator, &sc->sc_vreg_list, entries, tmp) {
+ LIST_REMOVE(regulator, entries);
+ sysctl_remove_oid(regulator->oid, 1, 0);
+ free(regulator, M_DEVBUF);
+ }
+
+ TWL_VREG_XUNLOCK(sc);
+
+ TWL_VREG_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static device_method_t twl_vreg_methods[] = {
+ DEVMETHOD(device_probe, twl_vreg_probe),
+ DEVMETHOD(device_attach, twl_vreg_attach),
+ DEVMETHOD(device_detach, twl_vreg_detach),
+
+ {0, 0},
+};
+
+static driver_t twl_vreg_driver = {
+ "twl_vreg",
+ twl_vreg_methods,
+ sizeof(struct twl_vreg_softc),
+};
+
+static devclass_t twl_vreg_devclass;
+
+DRIVER_MODULE(twl_vreg, twl, twl_vreg_driver, twl_vreg_devclass, 0, 0);
+MODULE_VERSION(twl_vreg, 1);
Property changes on: trunk/sys/arm/ti/twl/twl_vreg.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/twl/twl_vreg.h
===================================================================
--- trunk/sys/arm/ti/twl/twl_vreg.h (rev 0)
+++ trunk/sys/arm/ti/twl/twl_vreg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/twl/twl_vreg.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+#ifndef _TWL_VREG_H_
+#define _TWL_VREG_H_
+
+
+int twl_vreg_get_voltage(device_t dev, const char *name, int *millivolts);
+int twl_vreg_set_voltage(device_t dev, const char *name, int millivolts);
+
+#endif /* _TWL_VREG_H_ */
Property changes on: trunk/sys/arm/ti/twl/twl_vreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/usb/omap_ehci.c
===================================================================
--- trunk/sys/arm/ti/usb/omap_ehci.c (rev 0)
+++ trunk/sys/arm/ti/usb/omap_ehci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1017 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * Driver for the High Speed USB EHCI module on the TI OMAP3530 SoC.
+ *
+ * WARNING: I've only tried this driver on a limited number of USB peripherals,
+ * it is still very raw and bound to have numerous bugs in it.
+ *
+ * This driver is based on the FreeBSD IXP4xx EHCI driver with a lot of the
+ * setup sequence coming from the Linux community and their EHCI driver for
+ * OMAP. Without these as a base I don't think I would have been able to get
+ * this driver working.
+ *
+ * The driver only contains the EHCI parts, the module also supports OHCI and
+ * USB on-the-go (OTG), currently neither are supported.
+ *
+ * CAUTION: This driver was written to run on the beaglebaord dev board, so I
+ * have made some assumptions about the type of PHY used and some of the other
+ * settings. Bare that in mind if you intend to use this driver on another
+ * platform.
+ *
+ * NOTE: This module uses a few different clocks, one being a 60Mhz clock for
+ * the TTL part of the module. This clock is derived from DPPL5 which must be
+ * configured prior to loading this driver - it is not configured by the
+ * bootloader. It took me a long time to figure this out, and caused much
+ * frustration. This PLL is now setup in the timer/clocks part of the BSP,
+ * check out the omap_prcm_setup_dpll5() function in omap_prcm.c for more info.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/ti/usb/omap_ehci.c 308402 2016-11-07 09:19:04Z hselasky $");
+
+#include "opt_bus.h"
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/linker_set.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+#include <sys/gpio.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include <arm/ti/tivar.h>
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_scm.h>
+
+#include <arm/ti/usb/omap_usb.h>
+
+#include "gpio_if.h"
+
+struct omap_ehci_softc {
+ ehci_softc_t base; /* storage for EHCI code */
+
+ device_t sc_dev;
+ device_t sc_gpio_dev;
+
+ /* TLL register set */
+ struct resource* tll_mem_res;
+
+ /* UHH register set */
+ struct resource* uhh_mem_res;
+
+ /* The revision of the HS USB HOST read from UHH_REVISION */
+ uint32_t ehci_rev;
+
+ /* The following details are provided by conf hints */
+ int port_mode[3];
+ int phy_reset[3];
+ int reset_gpio_pin[3];
+};
+
+static device_attach_t omap_ehci_attach;
+static device_detach_t omap_ehci_detach;
+static device_shutdown_t omap_ehci_shutdown;
+static device_suspend_t omap_ehci_suspend;
+static device_resume_t omap_ehci_resume;
+
+/**
+ * omap_tll_read_4 - read a 32-bit value from the USBTLL registers
+ * omap_tll_write_4 - write a 32-bit value from the USBTLL registers
+ * omap_tll_readb - read an 8-bit value from the USBTLL registers
+ * omap_tll_writeb - write an 8-bit value from the USBTLL registers
+ * @sc: omap ehci device context
+ * @off: byte offset within the register set to read from
+ * @val: the value to write into the register
+ *
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * nothing in case of write function, if read function returns the value read.
+ */
+static inline uint32_t
+omap_tll_read_4(struct omap_ehci_softc *sc, bus_size_t off)
+{
+ return bus_read_4(sc->tll_mem_res, off);
+}
+
+static inline void
+omap_tll_write_4(struct omap_ehci_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->tll_mem_res, off, val);
+}
+
+static inline uint8_t
+omap_tll_readb(struct omap_ehci_softc *sc, bus_size_t off)
+{
+ return bus_read_1(sc->tll_mem_res, off);
+}
+
+static inline void
+omap_tll_writeb(struct omap_ehci_softc *sc, bus_size_t off, uint8_t val)
+{
+ bus_write_1(sc->tll_mem_res, off, val);
+}
+
+/**
+ * omap_ehci_read_4 - read a 32-bit value from the EHCI registers
+ * omap_ehci_write_4 - write a 32-bit value from the EHCI registers
+ * @sc: omap ehci device context
+ * @off: byte offset within the register set to read from
+ * @val: the value to write into the register
+ *
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * nothing in case of write function, if read function returns the value read.
+ */
+static inline uint32_t
+omap_ehci_read_4(struct omap_ehci_softc *sc, bus_size_t off)
+{
+ return (bus_read_4(sc->base.sc_io_res, off));
+}
+static inline void
+omap_ehci_write_4(struct omap_ehci_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->base.sc_io_res, off, val);
+}
+
+/**
+ * omap_uhh_read_4 - read a 32-bit value from the UHH registers
+ * omap_uhh_write_4 - write a 32-bit value from the UHH registers
+ * @sc: omap ehci device context
+ * @off: byte offset within the register set to read from
+ * @val: the value to write into the register
+ *
+ *
+ * LOCKING:
+ * None
+ *
+ * RETURNS:
+ * nothing in case of write function, if read function returns the value read.
+ */
+static inline uint32_t
+omap_uhh_read_4(struct omap_ehci_softc *sc, bus_size_t off)
+{
+ return bus_read_4(sc->uhh_mem_res, off);
+}
+static inline void
+omap_uhh_write_4(struct omap_ehci_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->uhh_mem_res, off, val);
+}
+
+/**
+ * omap_ehci_utmi_init - initialises the UTMI part of the controller
+ * @isc: omap ehci device context
+ *
+ *
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+omap_ehci_utmi_init(struct omap_ehci_softc *isc, unsigned int en_mask)
+{
+ unsigned int i;
+ uint32_t reg;
+
+ /* There are 3 TLL channels, one per USB controller so set them all up the
+ * same, SDR mode, bit stuffing and no autoidle.
+ */
+ for (i=0; i<3; i++) {
+ reg = omap_tll_read_4(isc, OMAP_USBTLL_TLL_CHANNEL_CONF(i));
+
+ reg &= ~(TLL_CHANNEL_CONF_UTMIAUTOIDLE
+ | TLL_CHANNEL_CONF_ULPINOBITSTUFF
+ | TLL_CHANNEL_CONF_ULPIDDRMODE);
+
+ omap_tll_write_4(isc, OMAP_USBTLL_TLL_CHANNEL_CONF(i), reg);
+ }
+
+ /* Program the common TLL register */
+ reg = omap_tll_read_4(isc, OMAP_USBTLL_TLL_SHARED_CONF);
+
+ reg &= ~( TLL_SHARED_CONF_USB_90D_DDR_EN
+ | TLL_SHARED_CONF_USB_DIVRATIO_MASK);
+ reg |= ( TLL_SHARED_CONF_FCLK_IS_ON
+ | TLL_SHARED_CONF_USB_DIVRATIO_2
+ | TLL_SHARED_CONF_USB_180D_SDR_EN);
+
+ omap_tll_write_4(isc, OMAP_USBTLL_TLL_SHARED_CONF, reg);
+
+ /* Enable channels now */
+ for (i = 0; i < 3; i++) {
+ reg = omap_tll_read_4(isc, OMAP_USBTLL_TLL_CHANNEL_CONF(i));
+
+ /* Enable only the reg that is needed */
+ if ((en_mask & (1 << i)) == 0)
+ continue;
+
+ reg |= TLL_CHANNEL_CONF_CHANEN;
+ omap_tll_write_4(isc, OMAP_USBTLL_TLL_CHANNEL_CONF(i), reg);
+ }
+}
+
+/**
+ * omap_ehci_soft_phy_reset - resets the phy using the reset command
+ * @isc: omap ehci device context
+ * @port: port to send the reset over
+ *
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+omap_ehci_soft_phy_reset(struct omap_ehci_softc *isc, unsigned int port)
+{
+ unsigned long timeout = (hz < 10) ? 1 : ((100 * hz) / 1000);
+ uint32_t reg;
+
+ reg = ULPI_FUNC_CTRL_RESET
+ /* FUNCTION_CTRL_SET register */
+ | (ULPI_SET(ULPI_FUNC_CTRL) << OMAP_USBHOST_INSNREG05_ULPI_REGADD_SHIFT)
+ /* Write */
+ | (2 << OMAP_USBHOST_INSNREG05_ULPI_OPSEL_SHIFT)
+ /* PORTn */
+ | ((port + 1) << OMAP_USBHOST_INSNREG05_ULPI_PORTSEL_SHIFT)
+ /* start ULPI access*/
+ | (1 << OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT);
+
+ omap_ehci_write_4(isc, OMAP_USBHOST_INSNREG05_ULPI, reg);
+
+ /* Wait for ULPI access completion */
+ while ((omap_ehci_read_4(isc, OMAP_USBHOST_INSNREG05_ULPI)
+ & (1 << OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT))) {
+
+ /* Sleep for a tick */
+ pause("USBPHY_RESET", 1);
+
+ if (timeout-- == 0) {
+ device_printf(isc->sc_dev, "PHY reset operation timed out\n");
+ break;
+ }
+ }
+}
+
+
+/**
+ * omap_ehci_init - initialises the USB host EHCI controller
+ * @isc: omap ehci device context
+ *
+ * This initialisation routine is quite heavily based on the work done by the
+ * OMAP Linux team (for which I thank them very much). The init sequence is
+ * almost identical, diverging only for the FreeBSD specifics.
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * 0 on success, a negative error code on failure.
+ */
+static int
+omap_ehci_init(struct omap_ehci_softc *isc)
+{
+ unsigned long timeout;
+ int ret = 0;
+ uint8_t tll_ch_mask = 0;
+ uint32_t reg = 0;
+ int reset_performed = 0;
+ int i;
+
+ device_printf(isc->sc_dev, "Starting TI EHCI USB Controller\n");
+
+
+ /* Enable Clocks for high speed USBHOST */
+ ti_prcm_clk_enable(USBHSHOST_CLK);
+
+ /* Hold the PHY in reset while configuring */
+ for (int i = 0; i < 3; i++) {
+ if (isc->phy_reset[i]) {
+ /* Configure the GPIO to drive low (hold in reset) */
+ if ((isc->reset_gpio_pin[i] != -1) && (isc->sc_gpio_dev != NULL)) {
+ GPIO_PIN_SETFLAGS(isc->sc_gpio_dev, isc->reset_gpio_pin[i],
+ GPIO_PIN_OUTPUT);
+ GPIO_PIN_SET(isc->sc_gpio_dev, isc->reset_gpio_pin[i],
+ GPIO_PIN_LOW);
+ reset_performed = 1;
+ }
+ }
+ }
+
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ if (reset_performed)
+ DELAY(10);
+
+ /* Read the UHH revision */
+ isc->ehci_rev = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_REVISION);
+ device_printf(isc->sc_dev, "UHH revision 0x%08x\n", isc->ehci_rev);
+
+ /* Initilise the low level interface module(s) */
+ if (isc->ehci_rev == OMAP_EHCI_REV1) {
+
+ /* Enable the USB TLL */
+ ti_prcm_clk_enable(USBTLL_CLK);
+
+ /* Perform TLL soft reset, and wait until reset is complete */
+ omap_tll_write_4(isc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_SOFTRESET);
+
+ /* Set the timeout to 100ms*/
+ timeout = (hz < 10) ? 1 : ((100 * hz) / 1000);
+
+ /* Wait for TLL reset to complete */
+ while ((omap_tll_read_4(isc, OMAP_USBTLL_SYSSTATUS) &
+ TLL_SYSSTATUS_RESETDONE) == 0x00) {
+
+ /* Sleep for a tick */
+ pause("USBRESET", 1);
+
+ if (timeout-- == 0) {
+ device_printf(isc->sc_dev, "TLL reset operation timed out\n");
+ ret = EINVAL;
+ goto err_sys_status;
+ }
+ }
+
+ device_printf(isc->sc_dev, "TLL RESET DONE\n");
+
+ /* CLOCKACTIVITY = 1 : OCP-derived internal clocks ON during idle
+ * SIDLEMODE = 2 : Smart-idle mode. Sidleack asserted after Idlereq
+ * assertion when no more activity on the USB.
+ * ENAWAKEUP = 1 : Wakeup generation enabled
+ */
+ omap_tll_write_4(isc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_ENAWAKEUP |
+ TLL_SYSCONFIG_AUTOIDLE |
+ TLL_SYSCONFIG_SIDLE_SMART_IDLE |
+ TLL_SYSCONFIG_CACTIVITY);
+
+ } else if (isc->ehci_rev == OMAP_EHCI_REV2) {
+
+ /* For OMAP44xx devices you have to enable the per-port clocks:
+ * PHY_MODE - External ULPI clock
+ * TTL_MODE - Internal UTMI clock
+ * HSIC_MODE - Internal 480Mhz and 60Mhz clocks
+ */
+ if (isc->ehci_rev == OMAP_EHCI_REV2) {
+ if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) {
+ ti_prcm_clk_set_source(USBP1_PHY_CLK, EXT_CLK);
+ ti_prcm_clk_enable(USBP1_PHY_CLK);
+ } else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
+ ti_prcm_clk_enable(USBP1_UTMI_CLK);
+ else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_HSIC)
+ ti_prcm_clk_enable(USBP1_HSIC_CLK);
+
+ if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) {
+ ti_prcm_clk_set_source(USBP2_PHY_CLK, EXT_CLK);
+ ti_prcm_clk_enable(USBP2_PHY_CLK);
+ } else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
+ ti_prcm_clk_enable(USBP2_UTMI_CLK);
+ else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_HSIC)
+ ti_prcm_clk_enable(USBP2_HSIC_CLK);
+ }
+ }
+
+ /* Put UHH in SmartIdle/SmartStandby mode */
+ reg = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_SYSCONFIG);
+ if (isc->ehci_rev == OMAP_EHCI_REV1) {
+ reg &= ~(UHH_SYSCONFIG_SIDLEMODE_MASK |
+ UHH_SYSCONFIG_MIDLEMODE_MASK);
+ reg |= (UHH_SYSCONFIG_ENAWAKEUP |
+ UHH_SYSCONFIG_AUTOIDLE |
+ UHH_SYSCONFIG_CLOCKACTIVITY |
+ UHH_SYSCONFIG_SIDLEMODE_SMARTIDLE |
+ UHH_SYSCONFIG_MIDLEMODE_SMARTSTANDBY);
+ } else if (isc->ehci_rev == OMAP_EHCI_REV2) {
+ reg &= ~UHH_SYSCONFIG_IDLEMODE_MASK;
+ reg |= UHH_SYSCONFIG_IDLEMODE_NOIDLE;
+ reg &= ~UHH_SYSCONFIG_STANDBYMODE_MASK;
+ reg |= UHH_SYSCONFIG_STANDBYMODE_NOSTDBY;
+ }
+ omap_uhh_write_4(isc, OMAP_USBHOST_UHH_SYSCONFIG, reg);
+ device_printf(isc->sc_dev, "OMAP_UHH_SYSCONFIG: 0x%08x\n", reg);
+
+ reg = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_HOSTCONFIG);
+
+ /* Setup ULPI bypass and burst configurations */
+ reg |= (UHH_HOSTCONFIG_ENA_INCR4 |
+ UHH_HOSTCONFIG_ENA_INCR8 |
+ UHH_HOSTCONFIG_ENA_INCR16);
+ reg &= ~UHH_HOSTCONFIG_ENA_INCR_ALIGN;
+
+ if (isc->ehci_rev == OMAP_EHCI_REV1) {
+ if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+ reg &= ~UHH_HOSTCONFIG_P1_CONNECT_STATUS;
+ if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+ reg &= ~UHH_HOSTCONFIG_P2_CONNECT_STATUS;
+ if (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+ reg &= ~UHH_HOSTCONFIG_P3_CONNECT_STATUS;
+
+ /* Bypass the TLL module for PHY mode operation */
+ if ((isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ||
+ (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ||
+ (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY))
+ reg &= ~UHH_HOSTCONFIG_P1_ULPI_BYPASS;
+ else
+ reg |= UHH_HOSTCONFIG_P1_ULPI_BYPASS;
+
+ } else if (isc->ehci_rev == OMAP_EHCI_REV2) {
+ reg |= UHH_HOSTCONFIG_APP_START_CLK;
+
+ /* Clear port mode fields for PHY mode*/
+ reg &= ~UHH_HOSTCONFIG_P1_MODE_MASK;
+ reg &= ~UHH_HOSTCONFIG_P2_MODE_MASK;
+
+ if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
+ reg |= UHH_HOSTCONFIG_P1_MODE_UTMI_PHY;
+ else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_HSIC)
+ reg |= UHH_HOSTCONFIG_P1_MODE_HSIC;
+
+ if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
+ reg |= UHH_HOSTCONFIG_P2_MODE_UTMI_PHY;
+ else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_HSIC)
+ reg |= UHH_HOSTCONFIG_P2_MODE_HSIC;
+ }
+
+ omap_uhh_write_4(isc, OMAP_USBHOST_UHH_HOSTCONFIG, reg);
+ device_printf(isc->sc_dev, "UHH setup done, uhh_hostconfig=0x%08x\n", reg);
+
+
+ /* I found the code and comments in the Linux EHCI driver - thanks guys :)
+ *
+ * "An undocumented "feature" in the OMAP3 EHCI controller, causes suspended
+ * ports to be taken out of suspend when the USBCMD.Run/Stop bit is cleared
+ * (for example when we do ehci_bus_suspend). This breaks suspend-resume if
+ * the root-hub is allowed to suspend. Writing 1 to this undocumented
+ * register bit disables this feature and restores normal behavior."
+ */
+#if 0
+ omap_ehci_write_4(isc, OMAP_USBHOST_INSNREG04,
+ OMAP_USBHOST_INSNREG04_DISABLE_UNSUSPEND);
+#endif
+
+ /* If any of the ports are configured in TLL mode, enable them */
+ if ((isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
+ (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
+ (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
+
+ if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
+ tll_ch_mask |= 0x1;
+ if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
+ tll_ch_mask |= 0x2;
+ if (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
+ tll_ch_mask |= 0x4;
+
+ /* Enable UTMI mode for required TLL channels */
+ omap_ehci_utmi_init(isc, tll_ch_mask);
+ }
+
+
+ /* Release the PHY reset signal now we have configured everything */
+ if (reset_performed) {
+
+ /* Delay for 10ms */
+ DELAY(10000);
+
+ for (i = 0; i < 3; i++) {
+ /* Release reset */
+
+ if (isc->phy_reset[i] && (isc->reset_gpio_pin[i] != -1)
+ && (isc->sc_gpio_dev != NULL)) {
+ GPIO_PIN_SET(isc->sc_gpio_dev,
+ isc->reset_gpio_pin[i], GPIO_PIN_HIGH);
+ }
+ }
+ }
+
+ /* Set the interrupt threshold control, it controls the maximum rate at
+ * which the host controller issues interrupts. We set it to 1 microframe
+ * at startup - the default is 8 mircoframes (equates to 1ms).
+ */
+ reg = omap_ehci_read_4(isc, OMAP_USBHOST_USBCMD);
+ reg &= 0xff00ffff;
+ reg |= (1 << 16);
+ omap_ehci_write_4(isc, OMAP_USBHOST_USBCMD, reg);
+
+ /* Soft reset the PHY using PHY reset command over ULPI */
+ if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
+ omap_ehci_soft_phy_reset(isc, 0);
+ if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
+ omap_ehci_soft_phy_reset(isc, 1);
+
+ return(0);
+
+err_sys_status:
+
+ /* Disable the TLL clocks */
+ ti_prcm_clk_disable(USBTLL_CLK);
+
+ /* Disable Clocks for USBHOST */
+ ti_prcm_clk_disable(USBHSHOST_CLK);
+
+ return(ret);
+}
+
+
+/**
+ * omap_ehci_fini - shutdown the EHCI controller
+ * @isc: omap ehci device context
+ *
+ *
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * 0 on success, a negative error code on failure.
+ */
+static void
+omap_ehci_fini(struct omap_ehci_softc *isc)
+{
+ unsigned long timeout;
+
+ device_printf(isc->sc_dev, "Stopping TI EHCI USB Controller\n");
+
+ /* Set the timeout */
+ if (hz < 10)
+ timeout = 1;
+ else
+ timeout = (100 * hz) / 1000;
+
+ /* Reset the UHH, OHCI and EHCI modules */
+ omap_uhh_write_4(isc, OMAP_USBHOST_UHH_SYSCONFIG, 0x0002);
+ while ((omap_uhh_read_4(isc, OMAP_USBHOST_UHH_SYSSTATUS) & 0x07) == 0x00) {
+ /* Sleep for a tick */
+ pause("USBRESET", 1);
+
+ if (timeout-- == 0) {
+ device_printf(isc->sc_dev, "operation timed out\n");
+ break;
+ }
+ }
+
+
+ /* Set the timeout */
+ if (hz < 10)
+ timeout = 1;
+ else
+ timeout = (100 * hz) / 1000;
+
+ /* Reset the TLL module */
+ omap_tll_write_4(isc, OMAP_USBTLL_SYSCONFIG, 0x0002);
+ while ((omap_tll_read_4(isc, OMAP_USBTLL_SYSSTATUS) & (0x01)) == 0x00) {
+ /* Sleep for a tick */
+ pause("USBRESET", 1);
+
+ if (timeout-- == 0) {
+ device_printf(isc->sc_dev, "operation timed out\n");
+ break;
+ }
+ }
+
+
+ /* Disable functional and interface clocks for the TLL and HOST modules */
+ ti_prcm_clk_disable(USBTLL_CLK);
+ ti_prcm_clk_disable(USBHSHOST_CLK);
+
+ device_printf(isc->sc_dev, "Clock to USB host has been disabled\n");
+
+}
+
+
+
+/**
+ * omap_ehci_suspend - suspends the bus
+ * @dev: omap ehci device
+ *
+ * Effectively boilerplate EHCI suspend code.
+ *
+ * TODO: There is a lot more we could do here - i.e. force the controller into
+ * idle mode and disable all the clocks for start.
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * 0 on success or a positive error code
+ */
+static int
+omap_ehci_suspend(device_t dev)
+{
+ int err;
+
+ err = bus_generic_suspend(dev);
+ if (err)
+ return (err);
+ return (0);
+}
+
+
+/**
+ * omap_ehci_resume - resumes a suspended bus
+ * @dev: omap ehci device
+ *
+ * Effectively boilerplate EHCI resume code.
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * 0 on success or a positive error code on failure
+ */
+static int
+omap_ehci_resume(device_t dev)
+{
+
+ bus_generic_resume(dev);
+
+ return (0);
+}
+
+
+/**
+ * omap_ehci_shutdown - starts the given command
+ * @dev:
+ *
+ * Effectively boilerplate EHCI shutdown code.
+ *
+ * LOCKING:
+ * none.
+ *
+ * RETURNS:
+ * 0 on success or a positive error code on failure
+ */
+static int
+omap_ehci_shutdown(device_t dev)
+{
+ int err;
+
+ err = bus_generic_shutdown(dev);
+ if (err)
+ return (err);
+
+ return (0);
+}
+
+
+/**
+ * omap_ehci_probe - starts the given command
+ * @dev:
+ *
+ * Effectively boilerplate EHCI resume code.
+ *
+ * LOCKING:
+ * Caller should be holding the OMAP3_MMC lock.
+ *
+ * RETURNS:
+ * EH_HANDLED or EH_NOT_HANDLED
+ */
+static int
+omap_ehci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,usb-ehci"))
+ return (ENXIO);
+
+ device_set_desc(dev, OMAP_EHCI_HC_DEVSTR);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+/**
+ * omap_ehci_attach - driver entry point, sets up the ECHI controller/driver
+ * @dev: the new device handle
+ *
+ * Sets up bus spaces, interrupt handles, etc for the EHCI controller. It also
+ * parses the resource hints and calls omap_ehci_init() to initialise the
+ * H/W.
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * 0 on success or a positive error code on failure.
+ */
+static int
+omap_ehci_attach(device_t dev)
+{
+ struct omap_ehci_softc *isc = device_get_softc(dev);
+ phandle_t node;
+ /* 3 ports with 3 cells per port */
+ pcell_t phyconf[3 * 3];
+ pcell_t *phyconf_ptr;
+ ehci_softc_t *sc = &isc->base;
+ int err;
+ int rid;
+ int len, tuple_size;
+ int i;
+
+ /* initialise some bus fields */
+ sc->sc_bus.parent = dev;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
+
+ /* save the device */
+ isc->sc_dev = dev;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev),
+ &ehci_iterate_hw_softc)) {
+ return (ENOMEM);
+ }
+
+ /* When the EHCI driver is added to the tree it is expected that 3
+ * memory resources and 1 interrupt resource is assigned. The memory
+ * resources should be:
+ * 0 => EHCI register range
+ * 1 => UHH register range
+ * 2 => TLL register range
+ *
+ * The interrupt resource is just the single interupt for the controller.
+ */
+
+ /* Allocate resource for the EHCI register set */
+ rid = 0;
+ sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->sc_io_res) {
+ device_printf(dev, "Error: Could not map EHCI memory\n");
+ goto error;
+ }
+ /* Request an interrupt resource */
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(dev, "Error: could not allocate irq\n");
+ goto error;
+ }
+
+ /* Allocate resource for the UHH register set */
+ rid = 1;
+ isc->uhh_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!isc->uhh_mem_res) {
+ device_printf(dev, "Error: Could not map UHH memory\n");
+ goto error;
+ }
+ /* Allocate resource for the TLL register set */
+ rid = 2;
+ isc->tll_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!isc->tll_mem_res) {
+ device_printf(dev, "Error: Could not map TLL memory\n");
+ goto error;
+ }
+
+ /* Add this device as a child of the USBus device */
+ sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(dev, "Error: could not add USB device\n");
+ goto error;
+ }
+
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+ device_set_desc(sc->sc_bus.bdev, OMAP_EHCI_HC_DEVSTR);
+
+ /* Set the vendor name */
+ sprintf(sc->sc_vendor, "Texas Instruments");
+
+ /* Get the GPIO device, we may need this if the driver needs to toggle
+ * some pins for external PHY resets.
+ */
+ isc->sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+ if (isc->sc_gpio_dev == NULL) {
+ device_printf(dev, "Error: failed to get the GPIO device\n");
+ goto error;
+ }
+
+ /* Set the defaults for the hints */
+ for (i = 0; i < 3; i++) {
+ isc->phy_reset[i] = 0;
+ isc->port_mode[i] = EHCI_HCD_OMAP_MODE_UNKNOWN;
+ isc->reset_gpio_pin[i] = -1;
+ }
+
+ tuple_size = sizeof(pcell_t) * 3;
+ node = ofw_bus_get_node(dev);
+ len = OF_getprop(node, "phy-config", phyconf, sizeof(phyconf));
+ if (len > 0) {
+ if (len % tuple_size)
+ goto error;
+ if ((len / tuple_size) != 3)
+ goto error;
+
+ phyconf_ptr = phyconf;
+ for (i = 0; i < 3; i++) {
+ isc->port_mode[i] = fdt32_to_cpu(*phyconf_ptr);
+ isc->phy_reset[i] = fdt32_to_cpu(*(phyconf_ptr + 1));
+ isc->reset_gpio_pin[i] = fdt32_to_cpu(*(phyconf_ptr + 2));
+
+ phyconf_ptr += 3;
+ }
+ }
+
+ /* Initialise the ECHI registers */
+ err = omap_ehci_init(isc);
+ if (err) {
+ device_printf(dev, "Error: could not setup OMAP EHCI, %d\n", err);
+ goto error;
+ }
+
+
+ /* Set the tag and size of the register set in the EHCI context */
+ sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+ sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+ sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+
+ /* Setup the interrupt */
+ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+ if (err) {
+ device_printf(dev, "Error: could not setup irq, %d\n", err);
+ sc->sc_intr_hdl = NULL;
+ goto error;
+ }
+
+
+ /* Finally we are ready to kick off the ECHI host controller */
+ err = ehci_init(sc);
+ if (err == 0) {
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ }
+ if (err) {
+ device_printf(dev, "Error: USB init failed err=%d\n", err);
+ goto error;
+ }
+
+ return (0);
+
+error:
+ omap_ehci_detach(dev);
+ return (ENXIO);
+}
+
+/**
+ * omap_ehci_detach - detach the device and cleanup the driver
+ * @dev: device handle
+ *
+ * Clean-up routine where everything initialised in omap_ehci_attach is
+ * freed and cleaned up. This function calls omap_ehci_fini() to shutdown
+ * the on-chip module.
+ *
+ * LOCKING:
+ * none
+ *
+ * RETURNS:
+ * Always returns 0 (success).
+ */
+static int
+omap_ehci_detach(device_t dev)
+{
+ struct omap_ehci_softc *isc = device_get_softc(dev);
+ ehci_softc_t *sc = &isc->base;
+ int err;
+
+ /* during module unload there are lots of children leftover */
+ device_delete_children(dev);
+
+ /*
+ * disable interrupts that might have been switched on in ehci_init
+ */
+ if (sc->sc_io_res) {
+ EWRITE4(sc, EHCI_USBINTR, 0);
+ }
+
+ if (sc->sc_irq_res && sc->sc_intr_hdl) {
+ /*
+ * only call ehci_detach() after ehci_init()
+ */
+ ehci_detach(sc);
+
+ err = bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr_hdl);
+ if (err)
+ device_printf(dev, "Error: could not tear down irq, %d\n", err);
+ sc->sc_intr_hdl = NULL;
+ }
+
+ /* Free the resources stored in the base EHCI handler */
+ if (sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+ if (sc->sc_io_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_io_res);
+ sc->sc_io_res = NULL;
+ }
+
+ /* Release the other register set memory maps */
+ if (isc->tll_mem_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, isc->tll_mem_res);
+ isc->tll_mem_res = NULL;
+ }
+ if (isc->uhh_mem_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, isc->uhh_mem_res);
+ isc->uhh_mem_res = NULL;
+ }
+
+ usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
+
+ omap_ehci_fini(isc);
+
+ return (0);
+}
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, omap_ehci_probe),
+ DEVMETHOD(device_attach, omap_ehci_attach),
+ DEVMETHOD(device_detach, omap_ehci_detach),
+ DEVMETHOD(device_suspend, omap_ehci_suspend),
+ DEVMETHOD(device_resume, omap_ehci_resume),
+ DEVMETHOD(device_shutdown, omap_ehci_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+ {0, 0}
+};
+
+static driver_t ehci_driver = {
+ "ehci",
+ ehci_methods,
+ sizeof(struct omap_ehci_softc),
+};
+
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
Property changes on: trunk/sys/arm/ti/usb/omap_ehci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/ti/usb/omap_usb.h
===================================================================
--- trunk/sys/arm/ti/usb/omap_usb.h (rev 0)
+++ trunk/sys/arm/ti/usb/omap_usb.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,265 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray at gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/ti/usb/omap_usb.h 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+#ifndef _OMAP_USB_H_
+#define _OMAP_USB_H_
+
+/*
+ * USB TTL Module
+ */
+#define OMAP_USBTLL_REVISION 0x0000
+#define OMAP_USBTLL_SYSCONFIG 0x0010
+#define OMAP_USBTLL_SYSSTATUS 0x0014
+#define OMAP_USBTLL_IRQSTATUS 0x0018
+#define OMAP_USBTLL_IRQENABLE 0x001C
+#define OMAP_USBTLL_TLL_SHARED_CONF 0x0030
+#define OMAP_USBTLL_TLL_CHANNEL_CONF(i) (0x0040 + (0x04 * (i)))
+#define OMAP_USBTLL_SAR_CNTX(i) (0x0400 + (0x04 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_ID_LO(i) (0x0800 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_ID_HI(i) (0x0801 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_PRODUCT_ID_LO(i) (0x0802 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_PRODUCT_ID_HI(i) (0x0803 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_FUNCTION_CTRL(i) (0x0804 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_FUNCTION_CTRL_SET(i) (0x0805 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_FUNCTION_CTRL_CLR(i) (0x0806 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_INTERFACE_CTRL(i) (0x0807 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_INTERFACE_CTRL_SET(i) (0x0808 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_INTERFACE_CTRL_CLR(i) (0x0809 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_OTG_CTRL(i) (0x080A + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_OTG_CTRL_SET(i) (0x080B + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_OTG_CTRL_CLR(i) (0x080C + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_RISE(i) (0x080D + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_RISE_SET(i) (0x080E + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_RISE_CLR(i) (0x080F + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_FALL(i) (0x0810 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_FALL_SET(i) (0x0811 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_FALL_CLR(i) (0x0812 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_STATUS(i) (0x0813 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_LATCH(i) (0x0814 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_DEBUG(i) (0x0815 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_SCRATCH_REGISTER(i) (0x0816 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_SCRATCH_REGISTER_SET(i) (0x0817 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_SCRATCH_REGISTER_CLR(i) (0x0818 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_EXTENDED_SET_ACCESS(i) (0x082F + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_EN(i) (0x0830 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_EN_SET(i) (0x0831 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_EN_CLR(i) (0x0832 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_STATUS(i) (0x0833 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_LATCH(i) (0x0834 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VSTATUS(i) (0x0835 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VSTATUS_SET(i) (0x0836 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VSTATUS_CLR(i) (0x0837 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_LATCH_NOCLR(i) (0x0838 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_EN(i) (0x083B + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_EN_SET(i) (0x083C + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_EN_CLR(i) (0x083D + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_STATUS(i) (0x083E + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_LATCH(i) (0x083F + (0x100 * (i)))
+
+
+/*
+ * USB Host Module
+ */
+
+/* UHH */
+#define OMAP_USBHOST_UHH_REVISION 0x0000
+#define OMAP_USBHOST_UHH_SYSCONFIG 0x0010
+#define OMAP_USBHOST_UHH_SYSSTATUS 0x0014
+#define OMAP_USBHOST_UHH_HOSTCONFIG 0x0040
+#define OMAP_USBHOST_UHH_DEBUG_CSR 0x0044
+
+/* EHCI */
+#define OMAP_USBHOST_HCCAPBASE 0x0000
+#define OMAP_USBHOST_HCSPARAMS 0x0004
+#define OMAP_USBHOST_HCCPARAMS 0x0008
+#define OMAP_USBHOST_USBCMD 0x0010
+#define OMAP_USBHOST_USBSTS 0x0014
+#define OMAP_USBHOST_USBINTR 0x0018
+#define OMAP_USBHOST_FRINDEX 0x001C
+#define OMAP_USBHOST_CTRLDSSEGMENT 0x0020
+#define OMAP_USBHOST_PERIODICLISTBASE 0x0024
+#define OMAP_USBHOST_ASYNCLISTADDR 0x0028
+#define OMAP_USBHOST_CONFIGFLAG 0x0050
+#define OMAP_USBHOST_PORTSC(i) (0x0054 + (0x04 * (i)))
+#define OMAP_USBHOST_INSNREG00 0x0090
+#define OMAP_USBHOST_INSNREG01 0x0094
+#define OMAP_USBHOST_INSNREG02 0x0098
+#define OMAP_USBHOST_INSNREG03 0x009C
+#define OMAP_USBHOST_INSNREG04 0x00A0
+#define OMAP_USBHOST_INSNREG05_UTMI 0x00A4
+#define OMAP_USBHOST_INSNREG05_ULPI 0x00A4
+#define OMAP_USBHOST_INSNREG06 0x00A8
+#define OMAP_USBHOST_INSNREG07 0x00AC
+#define OMAP_USBHOST_INSNREG08 0x00B0
+
+#define OMAP_USBHOST_INSNREG04_DISABLE_UNSUSPEND (1 << 5)
+
+#define OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT 31
+#define OMAP_USBHOST_INSNREG05_ULPI_PORTSEL_SHIFT 24
+#define OMAP_USBHOST_INSNREG05_ULPI_OPSEL_SHIFT 22
+#define OMAP_USBHOST_INSNREG05_ULPI_REGADD_SHIFT 16
+#define OMAP_USBHOST_INSNREG05_ULPI_EXTREGADD_SHIFT 8
+#define OMAP_USBHOST_INSNREG05_ULPI_WRDATA_SHIFT 0
+
+
+
+
+
+/* TLL Register Set */
+#define TLL_SYSCONFIG_CACTIVITY (1UL << 8)
+#define TLL_SYSCONFIG_SIDLE_SMART_IDLE (2UL << 3)
+#define TLL_SYSCONFIG_SIDLE_NO_IDLE (1UL << 3)
+#define TLL_SYSCONFIG_SIDLE_FORCED_IDLE (0UL << 3)
+#define TLL_SYSCONFIG_ENAWAKEUP (1UL << 2)
+#define TLL_SYSCONFIG_SOFTRESET (1UL << 1)
+#define TLL_SYSCONFIG_AUTOIDLE (1UL << 0)
+
+#define TLL_SYSSTATUS_RESETDONE (1UL << 0)
+
+#define TLL_SHARED_CONF_USB_90D_DDR_EN (1UL << 6)
+#define TLL_SHARED_CONF_USB_180D_SDR_EN (1UL << 5)
+#define TLL_SHARED_CONF_USB_DIVRATIO_MASK (7UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_128 (7UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_64 (6UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_32 (5UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_16 (4UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_8 (3UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_4 (2UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_2 (1UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_1 (0UL << 2)
+#define TLL_SHARED_CONF_FCLK_REQ (1UL << 1)
+#define TLL_SHARED_CONF_FCLK_IS_ON (1UL << 0)
+
+#define TLL_CHANNEL_CONF_DRVVBUS (1UL << 16)
+#define TLL_CHANNEL_CONF_CHRGVBUS (1UL << 15)
+#define TLL_CHANNEL_CONF_ULPINOBITSTUFF (1UL << 11)
+#define TLL_CHANNEL_CONF_ULPIAUTOIDLE (1UL << 10)
+#define TLL_CHANNEL_CONF_UTMIAUTOIDLE (1UL << 9)
+#define TLL_CHANNEL_CONF_ULPIDDRMODE (1UL << 8)
+#define TLL_CHANNEL_CONF_ULPIOUTCLKMODE (1UL << 7)
+#define TLL_CHANNEL_CONF_TLLFULLSPEED (1UL << 6)
+#define TLL_CHANNEL_CONF_TLLCONNECT (1UL << 5)
+#define TLL_CHANNEL_CONF_TLLATTACH (1UL << 4)
+#define TLL_CHANNEL_CONF_UTMIISADEV (1UL << 3)
+#define TLL_CHANNEL_CONF_CHANEN (1UL << 0)
+
+
+/* UHH Register Set */
+#define UHH_SYSCONFIG_MIDLEMODE_MASK (3UL << 12)
+#define UHH_SYSCONFIG_MIDLEMODE_SMARTSTANDBY (2UL << 12)
+#define UHH_SYSCONFIG_MIDLEMODE_NOSTANDBY (1UL << 12)
+#define UHH_SYSCONFIG_MIDLEMODE_FORCESTANDBY (0UL << 12)
+#define UHH_SYSCONFIG_CLOCKACTIVITY (1UL << 8)
+#define UHH_SYSCONFIG_SIDLEMODE_MASK (3UL << 3)
+#define UHH_SYSCONFIG_SIDLEMODE_SMARTIDLE (2UL << 3)
+#define UHH_SYSCONFIG_SIDLEMODE_NOIDLE (1UL << 3)
+#define UHH_SYSCONFIG_SIDLEMODE_FORCEIDLE (0UL << 3)
+#define UHH_SYSCONFIG_ENAWAKEUP (1UL << 2)
+#define UHH_SYSCONFIG_SOFTRESET (1UL << 1)
+#define UHH_SYSCONFIG_AUTOIDLE (1UL << 0)
+
+#define UHH_HOSTCONFIG_APP_START_CLK (1UL << 31)
+#define UHH_HOSTCONFIG_P3_CONNECT_STATUS (1UL << 10)
+#define UHH_HOSTCONFIG_P2_CONNECT_STATUS (1UL << 9)
+#define UHH_HOSTCONFIG_P1_CONNECT_STATUS (1UL << 8)
+#define UHH_HOSTCONFIG_ENA_INCR_ALIGN (1UL << 5)
+#define UHH_HOSTCONFIG_ENA_INCR16 (1UL << 4)
+#define UHH_HOSTCONFIG_ENA_INCR8 (1UL << 3)
+#define UHH_HOSTCONFIG_ENA_INCR4 (1UL << 2)
+#define UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN (1UL << 1)
+#define UHH_HOSTCONFIG_P1_ULPI_BYPASS (1UL << 0)
+
+/* The following are on rev2 (OMAP44xx) of the EHCI only */
+#define UHH_SYSCONFIG_IDLEMODE_MASK (3UL << 2)
+#define UHH_SYSCONFIG_IDLEMODE_NOIDLE (1UL << 2)
+#define UHH_SYSCONFIG_STANDBYMODE_MASK (3UL << 4)
+#define UHH_SYSCONFIG_STANDBYMODE_NOSTDBY (1UL << 4)
+
+#define UHH_HOSTCONFIG_P1_MODE_MASK (3UL << 16)
+#define UHH_HOSTCONFIG_P1_MODE_ULPI_PHY (0UL << 16)
+#define UHH_HOSTCONFIG_P1_MODE_UTMI_PHY (1UL << 16)
+#define UHH_HOSTCONFIG_P1_MODE_HSIC (3UL << 16)
+#define UHH_HOSTCONFIG_P2_MODE_MASK (3UL << 18)
+#define UHH_HOSTCONFIG_P2_MODE_ULPI_PHY (0UL << 18)
+#define UHH_HOSTCONFIG_P2_MODE_UTMI_PHY (1UL << 18)
+#define UHH_HOSTCONFIG_P2_MODE_HSIC (3UL << 18)
+
+#define ULPI_FUNC_CTRL_RESET (1 << 5)
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Macros for Set and Clear
+ * See ULPI 1.1 specification to find the registers with Set and Clear offsets
+ */
+#define ULPI_SET(a) (a + 1)
+#define ULPI_CLR(a) (a + 2)
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Register Map
+ */
+#define ULPI_VENDOR_ID_LOW 0x00
+#define ULPI_VENDOR_ID_HIGH 0x01
+#define ULPI_PRODUCT_ID_LOW 0x02
+#define ULPI_PRODUCT_ID_HIGH 0x03
+#define ULPI_FUNC_CTRL 0x04
+#define ULPI_IFC_CTRL 0x07
+#define ULPI_OTG_CTRL 0x0a
+#define ULPI_USB_INT_EN_RISE 0x0d
+#define ULPI_USB_INT_EN_FALL 0x10
+#define ULPI_USB_INT_STS 0x13
+#define ULPI_USB_INT_LATCH 0x14
+#define ULPI_DEBUG 0x15
+#define ULPI_SCRATCH 0x16
+
+/*
+ * Values of UHH_REVISION - Note: these are not given in the TRM but taken
+ * from the linux OMAP EHCI driver (thanks guys). It has been verified on
+ * a Panda and Beagle board.
+ */
+#define OMAP_EHCI_REV1 0x00000010 /* OMAP3 */
+#define OMAP_EHCI_REV2 0x50700100 /* OMAP4 */
+
+#define EHCI_VENDORID_OMAP3 0x42fa05
+#define OMAP_EHCI_HC_DEVSTR "TI OMAP USB 2.0 controller"
+
+#define EHCI_HCD_OMAP_MODE_UNKNOWN 0
+#define EHCI_HCD_OMAP_MODE_PHY 1
+#define EHCI_HCD_OMAP_MODE_TLL 2
+#define EHCI_HCD_OMAP_MODE_HSIC 3
+
+#endif /* _OMAP_USB_H_ */
Property changes on: trunk/sys/arm/ti/usb/omap_usb.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/files.versatile
===================================================================
--- trunk/sys/arm/versatile/files.versatile (rev 0)
+++ trunk/sys/arm/versatile/files.versatile 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,21 @@
+# $FreeBSD: stable/10/sys/arm/versatile/files.versatile 278727 2015-02-13 22:32:02Z ian $
+
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_arm11x6.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_armv6.S standard
+
+arm/versatile/pl050.c optional sc
+arm/versatile/sp804.c standard
+arm/versatile/versatile_machdep.c standard
+arm/versatile/versatile_clcd.c optional sc
+arm/versatile/versatile_common.c standard
+arm/versatile/versatile_pci.c optional pci
+arm/versatile/versatile_sic.c standard
+arm/versatile/versatile_timer.c standard
+arm/versatile/if_smc_fdt.c optional smc
+
+kern/kern_clocksource.c standard
Property changes on: trunk/sys/arm/versatile/files.versatile
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/versatile/if_smc_fdt.c
===================================================================
--- trunk/sys/arm/versatile/if_smc_fdt.c (rev 0)
+++ trunk/sys/arm/versatile/if_smc_fdt.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,136 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Benno Rice
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/if_smc_fdt.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
+
+#include <dev/smc/if_smcvar.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "miibus_if.h"
+
+static int smc_fdt_probe(device_t);
+static int smc_fdt_attach(device_t);
+static int smc_fdt_detach(device_t);
+
+static int
+smc_fdt_probe(device_t dev)
+{
+ struct smc_softc *sc;
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "smsc,lan91c111")) {
+ sc = device_get_softc(dev);
+ sc->smc_usemem = 1;
+
+ if (smc_probe(dev) != 0) {
+ return (ENXIO);
+ }
+
+ return (0);
+ }
+
+ return (ENXIO);
+}
+
+static int
+smc_fdt_attach(device_t dev)
+{
+ int err;
+ struct smc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ err = smc_attach(dev);
+ if (err) {
+ return (err);
+ }
+
+ return (0);
+}
+
+static int
+smc_fdt_detach(device_t dev)
+{
+
+ smc_detach(dev);
+
+ return (0);
+}
+
+static device_method_t smc_fdt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, smc_fdt_probe),
+ DEVMETHOD(device_attach, smc_fdt_attach),
+ DEVMETHOD(device_detach, smc_fdt_detach),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, smc_miibus_readreg),
+ DEVMETHOD(miibus_writereg, smc_miibus_writereg),
+ DEVMETHOD(miibus_statchg, smc_miibus_statchg),
+
+ { 0, 0 }
+};
+
+static driver_t smc_fdt_driver = {
+ "smc",
+ smc_fdt_methods,
+ sizeof(struct smc_softc),
+};
+
+extern devclass_t smc_devclass;
+
+DRIVER_MODULE(smc, simplebus, smc_fdt_driver, smc_devclass, 0, 0);
+DRIVER_MODULE(miibus, smc, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(smc, fdt, 1, 1, 1);
+MODULE_DEPEND(smc, ether, 1, 1, 1);
+MODULE_DEPEND(smc, miibus, 1, 1, 1);
Property changes on: trunk/sys/arm/versatile/if_smc_fdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/pl050.c
===================================================================
--- trunk/sys/arm/versatile/pl050.c (rev 0)
+++ trunk/sys/arm/versatile/pl050.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,716 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Based on dev/usb/input/ukbd.c
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/pl050.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <sys/ioccom.h>
+#include <sys/filio.h>
+#include <sys/tty.h>
+#include <sys/kbio.h>
+
+#include <dev/kbd/kbdreg.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/kbd/kbdtables.h>
+
+#define KMI_LOCK() mtx_lock(&Giant)
+#define KMI_UNLOCK() mtx_unlock(&Giant)
+
+#ifdef INVARIANTS
+/*
+ * Assert that the lock is held in all contexts
+ * where the code can be executed.
+ */
+#define KMI_LOCK_ASSERT() mtx_assert(&Giant, MA_OWNED)
+/*
+ * Assert that the lock is held in the contexts
+ * where it really has to be so.
+ */
+#define KMI_CTX_LOCK_ASSERT() \
+ do { \
+ if (!kdb_active && panicstr == NULL) \
+ mtx_assert(&Giant, MA_OWNED); \
+ } while (0)
+#else
+#define KMI_LOCK_ASSERT() (void)0
+#define KMI_CTX_LOCK_ASSERT() (void)0
+#endif
+
+#define KMICR 0x00
+#define KMICR_TYPE_NONPS2 (1 << 5)
+#define KMICR_RXINTREN (1 << 4)
+#define KMICR_TXINTREN (1 << 3)
+#define KMICR_EN (1 << 2)
+#define KMICR_FKMID (1 << 1)
+#define KMICR_FKMIC (1 << 0)
+#define KMISTAT 0x04
+#define KMISTAT_TXEMPTY (1 << 6)
+#define KMISTAT_TXBUSY (1 << 5)
+#define KMISTAT_RXFULL (1 << 4)
+#define KMISTAT_RXBUSY (1 << 3)
+#define KMISTAT_RXPARITY (1 << 2)
+#define KMISTAT_KMIC (1 << 1)
+#define KMISTAT_KMID (1 << 0)
+#define KMIDATA 0x08
+#define KMICLKDIV 0x0C
+#define KMIIR 0x10
+#define KMIIR_TXINTR (1 << 1)
+#define KMIIR_RXINTR (1 << 0)
+
+#define KMI_DRIVER_NAME "kmi"
+#define KMI_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */
+
+struct kmi_softc {
+ keyboard_t sc_kbd;
+ keymap_t sc_keymap;
+ accentmap_t sc_accmap;
+ fkeytab_t sc_fkeymap[KMI_NFKEY];
+
+ struct resource* sc_mem_res;
+ struct resource* sc_irq_res;
+ void* sc_intr_hl;
+
+ int sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
+ int sc_state; /* shift/lock key state */
+ int sc_accents; /* accent key index (> 0) */
+ uint32_t sc_flags; /* flags */
+#define KMI_FLAG_COMPOSE 0x00000001
+#define KMI_FLAG_POLLING 0x00000002
+
+ struct thread *sc_poll_thread;
+};
+
+/* Read/Write macros for Timer used as timecounter */
+#define pl050_kmi_read_4(sc, reg) \
+ bus_read_4((sc)->sc_mem_res, (reg))
+
+#define pl050_kmi_write_4(sc, reg, val) \
+ bus_write_4((sc)->sc_mem_res, (reg), (val))
+
+/* prototypes */
+static void kmi_set_leds(struct kmi_softc *, uint8_t);
+static int kmi_set_typematic(keyboard_t *, int);
+static uint32_t kmi_read_char(keyboard_t *, int);
+static void kmi_clear_state(keyboard_t *);
+static int kmi_ioctl(keyboard_t *, u_long, caddr_t);
+static int kmi_enable(keyboard_t *);
+static int kmi_disable(keyboard_t *);
+
+/* early keyboard probe, not supported */
+static int
+kmi_configure(int flags)
+{
+ return (0);
+}
+
+/* detect a keyboard, not used */
+static int
+kmi_probe(int unit, void *arg, int flags)
+{
+ return (ENXIO);
+}
+
+/* reset and initialize the device, not used */
+static int
+kmi_init(int unit, keyboard_t **kbdp, void *arg, int flags)
+{
+ return (ENXIO);
+}
+
+/* test the interface to the device, not used */
+static int
+kmi_test_if(keyboard_t *kbd)
+{
+ return (0);
+}
+
+/* finish using this keyboard, not used */
+static int
+kmi_term(keyboard_t *kbd)
+{
+ return (ENXIO);
+}
+
+/* keyboard interrupt routine, not used */
+static int
+kmi_intr(keyboard_t *kbd, void *arg)
+{
+
+ return (0);
+}
+
+/* lock the access to the keyboard, not used */
+static int
+kmi_lock(keyboard_t *kbd, int lock)
+{
+ return (1);
+}
+
+/*
+ * Enable the access to the device; until this function is called,
+ * the client cannot read from the keyboard.
+ */
+static int
+kmi_enable(keyboard_t *kbd)
+{
+
+ KMI_LOCK();
+ KBD_ACTIVATE(kbd);
+ KMI_UNLOCK();
+
+ return (0);
+}
+
+/* disallow the access to the device */
+static int
+kmi_disable(keyboard_t *kbd)
+{
+
+ KMI_LOCK();
+ KBD_DEACTIVATE(kbd);
+ KMI_UNLOCK();
+
+ return (0);
+}
+
+/* check if data is waiting */
+static int
+kmi_check(keyboard_t *kbd)
+{
+ struct kmi_softc *sc = kbd->kb_data;
+ uint32_t reg;
+
+ KMI_CTX_LOCK_ASSERT();
+
+ if (!KBD_IS_ACTIVE(kbd))
+ return (0);
+
+ reg = pl050_kmi_read_4(sc, KMIIR);
+ return (reg & KMIIR_RXINTR);
+}
+
+/* check if char is waiting */
+static int
+kmi_check_char_locked(keyboard_t *kbd)
+{
+ KMI_CTX_LOCK_ASSERT();
+
+ if (!KBD_IS_ACTIVE(kbd))
+ return (0);
+
+ return (kmi_check(kbd));
+}
+
+static int
+kmi_check_char(keyboard_t *kbd)
+{
+ int result;
+
+ KMI_LOCK();
+ result = kmi_check_char_locked(kbd);
+ KMI_UNLOCK();
+
+ return (result);
+}
+
+/* read one byte from the keyboard if it's allowed */
+/* Currently unused. */
+static int
+kmi_read(keyboard_t *kbd, int wait)
+{
+ KMI_CTX_LOCK_ASSERT();
+
+ if (!KBD_IS_ACTIVE(kbd))
+ return (-1);
+
+ ++(kbd->kb_count);
+ printf("Implement ME: %s\n", __func__);
+ return (0);
+}
+
+/* read char from the keyboard */
+static uint32_t
+kmi_read_char_locked(keyboard_t *kbd, int wait)
+{
+ struct kmi_softc *sc = kbd->kb_data;
+ uint32_t reg, data;
+
+ KMI_CTX_LOCK_ASSERT();
+
+ if (!KBD_IS_ACTIVE(kbd))
+ return (NOKEY);
+
+ reg = pl050_kmi_read_4(sc, KMIIR);
+ if (reg & KMIIR_RXINTR) {
+ data = pl050_kmi_read_4(sc, KMIDATA);
+ return (data);
+ }
+
+ ++kbd->kb_count;
+ return (NOKEY);
+}
+
+/* Currently wait is always false. */
+static uint32_t
+kmi_read_char(keyboard_t *kbd, int wait)
+{
+ uint32_t keycode;
+
+ KMI_LOCK();
+ keycode = kmi_read_char_locked(kbd, wait);
+ KMI_UNLOCK();
+
+ return (keycode);
+}
+
+/* some useful control functions */
+static int
+kmi_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg)
+{
+ struct kmi_softc *sc = kbd->kb_data;
+ int i;
+#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
+ int ival;
+
+#endif
+
+ KMI_LOCK_ASSERT();
+
+ switch (cmd) {
+ case KDGKBMODE: /* get keyboard mode */
+ *(int *)arg = sc->sc_mode;
+ break;
+#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
+ case _IO('K', 7):
+ ival = IOCPARM_IVAL(arg);
+ arg = (caddr_t)&ival;
+ /* FALLTHROUGH */
+#endif
+ case KDSKBMODE: /* set keyboard mode */
+ switch (*(int *)arg) {
+ case K_XLATE:
+ if (sc->sc_mode != K_XLATE) {
+ /* make lock key state and LED state match */
+ sc->sc_state &= ~LOCK_MASK;
+ sc->sc_state |= KBD_LED_VAL(kbd);
+ }
+ /* FALLTHROUGH */
+ case K_RAW:
+ case K_CODE:
+ if (sc->sc_mode != *(int *)arg) {
+ if ((sc->sc_flags & KMI_FLAG_POLLING) == 0)
+ kmi_clear_state(kbd);
+ sc->sc_mode = *(int *)arg;
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+
+ case KDGETLED: /* get keyboard LED */
+ *(int *)arg = KBD_LED_VAL(kbd);
+ break;
+#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
+ case _IO('K', 66):
+ ival = IOCPARM_IVAL(arg);
+ arg = (caddr_t)&ival;
+ /* FALLTHROUGH */
+#endif
+ case KDSETLED: /* set keyboard LED */
+ /* NOTE: lock key state in "sc_state" won't be changed */
+ if (*(int *)arg & ~LOCK_MASK)
+ return (EINVAL);
+
+ i = *(int *)arg;
+
+ /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
+ if (sc->sc_mode == K_XLATE &&
+ kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
+ if (i & ALKED)
+ i |= CLKED;
+ else
+ i &= ~CLKED;
+ }
+ if (KBD_HAS_DEVICE(kbd))
+ kmi_set_leds(sc, i);
+
+ KBD_LED_VAL(kbd) = *(int *)arg;
+ break;
+ case KDGKBSTATE: /* get lock key state */
+ *(int *)arg = sc->sc_state & LOCK_MASK;
+ break;
+#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
+ case _IO('K', 20):
+ ival = IOCPARM_IVAL(arg);
+ arg = (caddr_t)&ival;
+ /* FALLTHROUGH */
+#endif
+ case KDSKBSTATE: /* set lock key state */
+ if (*(int *)arg & ~LOCK_MASK) {
+ return (EINVAL);
+ }
+ sc->sc_state &= ~LOCK_MASK;
+ sc->sc_state |= *(int *)arg;
+
+ /* set LEDs and quit */
+ return (kmi_ioctl(kbd, KDSETLED, arg));
+
+ case KDSETREPEAT: /* set keyboard repeat rate (new
+ * interface) */
+ if (!KBD_HAS_DEVICE(kbd)) {
+ return (0);
+ }
+ if (((int *)arg)[1] < 0) {
+ return (EINVAL);
+ }
+ if (((int *)arg)[0] < 0) {
+ return (EINVAL);
+ }
+ if (((int *)arg)[0] < 200) /* fastest possible value */
+ kbd->kb_delay1 = 200;
+ else
+ kbd->kb_delay1 = ((int *)arg)[0];
+ kbd->kb_delay2 = ((int *)arg)[1];
+ return (0);
+
+#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
+ case _IO('K', 67):
+ ival = IOCPARM_IVAL(arg);
+ arg = (caddr_t)&ival;
+ /* FALLTHROUGH */
+#endif
+ case KDSETRAD: /* set keyboard repeat rate (old
+ * interface) */
+ return (kmi_set_typematic(kbd, *(int *)arg));
+
+ case PIO_KEYMAP: /* set keyboard translation table */
+ case OPIO_KEYMAP: /* set keyboard translation table
+ * (compat) */
+ case PIO_KEYMAPENT: /* set keyboard translation table
+ * entry */
+ case PIO_DEADKEYMAP: /* set accent key translation table */
+ sc->sc_accents = 0;
+ /* FALLTHROUGH */
+ default:
+ return (genkbd_commonioctl(kbd, cmd, arg));
+ }
+
+ return (0);
+}
+
+static int
+kmi_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
+{
+ int result;
+
+ /*
+ * XXX KDGKBSTATE, KDSKBSTATE and KDSETLED can be called from any
+ * context where printf(9) can be called, which among other things
+ * includes interrupt filters and threads with any kinds of locks
+ * already held. For this reason it would be dangerous to acquire
+ * the Giant here unconditionally. On the other hand we have to
+ * have it to handle the ioctl.
+ * So we make our best effort to auto-detect whether we can grab
+ * the Giant or not. Blame syscons(4) for this.
+ */
+ switch (cmd) {
+ case KDGKBSTATE:
+ case KDSKBSTATE:
+ case KDSETLED:
+ if (!mtx_owned(&Giant) && !SCHEDULER_STOPPED())
+ return (EDEADLK); /* best I could come up with */
+ /* FALLTHROUGH */
+ default:
+ KMI_LOCK();
+ result = kmi_ioctl_locked(kbd, cmd, arg);
+ KMI_UNLOCK();
+ return (result);
+ }
+}
+
+
+/* clear the internal state of the keyboard */
+static void
+kmi_clear_state(keyboard_t *kbd)
+{
+ struct kmi_softc *sc = kbd->kb_data;
+
+ KMI_CTX_LOCK_ASSERT();
+
+ sc->sc_flags &= ~(KMI_FLAG_COMPOSE | KMI_FLAG_POLLING);
+ sc->sc_state &= LOCK_MASK; /* preserve locking key state */
+ sc->sc_accents = 0;
+}
+
+/* save the internal state, not used */
+static int
+kmi_get_state(keyboard_t *kbd, void *buf, size_t len)
+{
+ return (len == 0) ? 1 : -1;
+}
+
+/* set the internal state, not used */
+static int
+kmi_set_state(keyboard_t *kbd, void *buf, size_t len)
+{
+ return (EINVAL);
+}
+
+static int
+kmi_poll(keyboard_t *kbd, int on)
+{
+ struct kmi_softc *sc = kbd->kb_data;
+
+ KMI_LOCK();
+ if (on) {
+ sc->sc_flags |= KMI_FLAG_POLLING;
+ sc->sc_poll_thread = curthread;
+ } else {
+ sc->sc_flags &= ~KMI_FLAG_POLLING;
+ }
+ KMI_UNLOCK();
+
+ return (0);
+}
+
+/* local functions */
+
+static void
+kmi_set_leds(struct kmi_softc *sc, uint8_t leds)
+{
+
+ KMI_LOCK_ASSERT();
+
+ /* start transfer, if not already started */
+ printf("Implement me: %s\n", __func__);
+}
+
+static int
+kmi_set_typematic(keyboard_t *kbd, int code)
+{
+ static const int delays[] = {250, 500, 750, 1000};
+ static const int rates[] = {34, 38, 42, 46, 50, 55, 59, 63,
+ 68, 76, 84, 92, 100, 110, 118, 126,
+ 136, 152, 168, 184, 200, 220, 236, 252,
+ 272, 304, 336, 368, 400, 440, 472, 504};
+
+ if (code & ~0x7f) {
+ return (EINVAL);
+ }
+ kbd->kb_delay1 = delays[(code >> 5) & 3];
+ kbd->kb_delay2 = rates[code & 0x1f];
+ return (0);
+}
+
+static keyboard_switch_t kmisw = {
+ .probe = &kmi_probe,
+ .init = &kmi_init,
+ .term = &kmi_term,
+ .intr = &kmi_intr,
+ .test_if = &kmi_test_if,
+ .enable = &kmi_enable,
+ .disable = &kmi_disable,
+ .read = &kmi_read,
+ .check = &kmi_check,
+ .read_char = &kmi_read_char,
+ .check_char = &kmi_check_char,
+ .ioctl = &kmi_ioctl,
+ .lock = &kmi_lock,
+ .clear_state = &kmi_clear_state,
+ .get_state = &kmi_get_state,
+ .set_state = &kmi_set_state,
+ .get_fkeystr = &genkbd_get_fkeystr,
+ .poll = &kmi_poll,
+ .diag = &genkbd_diag,
+};
+
+KEYBOARD_DRIVER(kmi, kmisw, kmi_configure);
+
+static void
+pl050_kmi_intr(void *arg)
+{
+ struct kmi_softc *sc = arg;
+ uint32_t c;
+
+ KMI_CTX_LOCK_ASSERT();
+
+ if ((sc->sc_flags & KMI_FLAG_POLLING) != 0)
+ return;
+
+ if (KBD_IS_ACTIVE(&sc->sc_kbd) &&
+ KBD_IS_BUSY(&sc->sc_kbd)) {
+ /* let the callback function process the input */
+ (sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
+ sc->sc_kbd.kb_callback.kc_arg);
+ } else {
+ /* read and discard the input, no one is waiting for it */
+ do {
+ c = kmi_read_char_locked(&sc->sc_kbd, 0);
+ } while (c != NOKEY);
+ }
+
+}
+
+static int
+pl050_kmi_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "arm,pl050")) {
+ device_set_desc(dev, "PL050 Keyboard/Mouse Interface");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+pl050_kmi_attach(device_t dev)
+{
+ struct kmi_softc *sc = device_get_softc(dev);
+ keyboard_t *kbd;
+ int rid;
+ int i;
+
+ kbd = &sc->sc_kbd;
+ rid = 0;
+
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ /* Request the IRQ resources */
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(dev, "Error: could not allocate irq resources\n");
+ return (ENXIO);
+ }
+
+ /* Setup and enable the timer */
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_CLK,
+ NULL, pl050_kmi_intr, sc,
+ &sc->sc_intr_hl) != 0) {
+ bus_release_resource(dev, SYS_RES_IRQ, rid,
+ sc->sc_irq_res);
+ device_printf(dev, "Unable to setup the clock irq handler.\n");
+ return (ENXIO);
+ }
+
+ /* TODO: clock & divisor */
+
+ pl050_kmi_write_4(sc, KMICR, KMICR_EN | KMICR_RXINTREN);
+
+ kbd_init_struct(kbd, KMI_DRIVER_NAME, KB_OTHER,
+ device_get_unit(dev), 0, 0, 0);
+ kbd->kb_data = (void *)sc;
+
+ sc->sc_keymap = key_map;
+ sc->sc_accmap = accent_map;
+ for (i = 0; i < KMI_NFKEY; i++) {
+ sc->sc_fkeymap[i] = fkey_tab[i];
+ }
+
+ kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap,
+ sc->sc_fkeymap, KMI_NFKEY);
+
+ KBD_FOUND_DEVICE(kbd);
+ kmi_clear_state(kbd);
+ KBD_PROBE_DONE(kbd);
+
+ KBD_INIT_DONE(kbd);
+
+ if (kbd_register(kbd) < 0) {
+ goto detach;
+ }
+ KBD_CONFIG_DONE(kbd);
+
+#ifdef KBD_INSTALL_CDEV
+ if (kbd_attach(kbd)) {
+ goto detach;
+ }
+#endif
+
+ if (bootverbose) {
+ genkbd_diag(kbd, bootverbose);
+ }
+ return (0);
+
+detach:
+ return (ENXIO);
+
+}
+
+static device_method_t pl050_kmi_methods[] = {
+ DEVMETHOD(device_probe, pl050_kmi_probe),
+ DEVMETHOD(device_attach, pl050_kmi_attach),
+ { 0, 0 }
+};
+
+static driver_t pl050_kmi_driver = {
+ "kmi",
+ pl050_kmi_methods,
+ sizeof(struct kmi_softc),
+};
+
+static devclass_t pl050_kmi_devclass;
+
+DRIVER_MODULE(pl050_kmi, simplebus, pl050_kmi_driver, pl050_kmi_devclass, 0, 0);
Property changes on: trunk/sys/arm/versatile/pl050.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/sp804.c
===================================================================
--- trunk/sys/arm/versatile/sp804.c (rev 0)
+++ trunk/sys/arm/versatile/sp804.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,363 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012 Damjan Marion <dmarion at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/sp804.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#define SP804_TIMER1_LOAD 0x00
+#define SP804_TIMER1_VALUE 0x04
+#define SP804_TIMER1_CONTROL 0x08
+#define TIMER_CONTROL_EN (1 << 7)
+#define TIMER_CONTROL_FREERUN (0 << 6)
+#define TIMER_CONTROL_PERIODIC (1 << 6)
+#define TIMER_CONTROL_INTREN (1 << 5)
+#define TIMER_CONTROL_DIV1 (0 << 2)
+#define TIMER_CONTROL_DIV16 (1 << 2)
+#define TIMER_CONTROL_DIV256 (2 << 2)
+#define TIMER_CONTROL_32BIT (1 << 1)
+#define TIMER_CONTROL_ONESHOT (1 << 0)
+#define SP804_TIMER1_INTCLR 0x0C
+#define SP804_TIMER1_RIS 0x10
+#define SP804_TIMER1_MIS 0x14
+#define SP804_TIMER1_BGLOAD 0x18
+#define SP804_TIMER2_LOAD 0x20
+#define SP804_TIMER2_VALUE 0x24
+#define SP804_TIMER2_CONTROL 0x28
+#define SP804_TIMER2_INTCLR 0x2C
+#define SP804_TIMER2_RIS 0x30
+#define SP804_TIMER2_MIS 0x34
+#define SP804_TIMER2_BGLOAD 0x38
+
+#define SP804_PERIPH_ID0 0xFE0
+#define SP804_PERIPH_ID1 0xFE4
+#define SP804_PERIPH_ID2 0xFE8
+#define SP804_PERIPH_ID3 0xFEC
+#define SP804_PRIMECELL_ID0 0xFF0
+#define SP804_PRIMECELL_ID1 0xFF4
+#define SP804_PRIMECELL_ID2 0xFF8
+#define SP804_PRIMECELL_ID3 0xFFC
+
+#define DEFAULT_FREQUENCY 1000000
+/*
+ * QEMU seems to have problem with full frequency
+ */
+#define DEFAULT_DIVISOR 16
+#define DEFAULT_CONTROL_DIV TIMER_CONTROL_DIV16
+
+struct sp804_timer_softc {
+ struct resource* mem_res;
+ struct resource* irq_res;
+ void* intr_hl;
+ uint32_t sysclk_freq;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ struct timecounter tc;
+ bool et_enabled;
+ struct eventtimer et;
+ int timer_initialized;
+};
+
+/* Read/Write macros for Timer used as timecounter */
+#define sp804_timer_tc_read_4(reg) \
+ bus_space_read_4(sc->bst, sc->bsh, reg)
+
+#define sp804_timer_tc_write_4(reg, val) \
+ bus_space_write_4(sc->bst, sc->bsh, reg, val)
+
+static unsigned sp804_timer_tc_get_timecount(struct timecounter *);
+
+static unsigned
+sp804_timer_tc_get_timecount(struct timecounter *tc)
+{
+ struct sp804_timer_softc *sc = tc->tc_priv;
+ return 0xffffffff - sp804_timer_tc_read_4(SP804_TIMER1_VALUE);
+}
+
+static int
+sp804_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct sp804_timer_softc *sc = et->et_priv;
+ uint32_t count, reg;
+
+ if (first != 0) {
+ sc->et_enabled = 1;
+
+ count = ((uint32_t)et->et_frequency * first) >> 32;
+
+ sp804_timer_tc_write_4(SP804_TIMER2_LOAD, count);
+ reg = TIMER_CONTROL_32BIT | TIMER_CONTROL_INTREN |
+ TIMER_CONTROL_PERIODIC | DEFAULT_CONTROL_DIV |
+ TIMER_CONTROL_EN;
+ sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, reg);
+
+ return (0);
+ }
+
+ if (period != 0) {
+ panic("period");
+ }
+
+ return (EINVAL);
+}
+
+static int
+sp804_timer_stop(struct eventtimer *et)
+{
+ struct sp804_timer_softc *sc = et->et_priv;
+ uint32_t reg;
+
+ sc->et_enabled = 0;
+ reg = sp804_timer_tc_read_4(SP804_TIMER2_CONTROL);
+ reg &= ~(TIMER_CONTROL_EN);
+ sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, reg);
+
+ return (0);
+}
+
+static int
+sp804_timer_intr(void *arg)
+{
+ struct sp804_timer_softc *sc = arg;
+ static uint32_t prev = 0;
+ uint32_t x = 0;
+
+ x = sp804_timer_tc_read_4(SP804_TIMER1_VALUE);
+
+ prev =x ;
+ sp804_timer_tc_write_4(SP804_TIMER2_INTCLR, 1);
+ if (sc->et_enabled) {
+ if (sc->et.et_active) {
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+ }
+ }
+
+ return (FILTER_HANDLED);
+}
+
+static int
+sp804_timer_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "arm,sp804")) {
+ device_set_desc(dev, "SP804 System Timer");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+sp804_timer_attach(device_t dev)
+{
+ struct sp804_timer_softc *sc = device_get_softc(dev);
+ int rid = 0;
+ int i;
+ uint32_t id, reg;
+ phandle_t node;
+ pcell_t clock;
+
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->mem_res);
+ sc->bsh = rman_get_bushandle(sc->mem_res);
+
+ /* Request the IRQ resources */
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Error: could not allocate irq resources\n");
+ return (ENXIO);
+ }
+
+ sc->sysclk_freq = DEFAULT_FREQUENCY;
+ /* Get the base clock frequency */
+ node = ofw_bus_get_node(dev);
+ if ((OF_getprop(node, "clock-frequency", &clock, sizeof(clock))) > 0) {
+ sc->sysclk_freq = fdt32_to_cpu(clock);
+ }
+
+ /* Setup and enable the timer */
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CLK,
+ sp804_timer_intr, NULL, sc,
+ &sc->intr_hl) != 0) {
+ bus_release_resource(dev, SYS_RES_IRQ, rid,
+ sc->irq_res);
+ device_printf(dev, "Unable to setup the clock irq handler.\n");
+ return (ENXIO);
+ }
+
+ sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, 0);
+ sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, 0);
+
+ /*
+ * Timer 1, timecounter
+ */
+ sc->tc.tc_frequency = sc->sysclk_freq;
+ sc->tc.tc_name = "SP804 Time Counter";
+ sc->tc.tc_get_timecount = sp804_timer_tc_get_timecount;
+ sc->tc.tc_poll_pps = NULL;
+ sc->tc.tc_counter_mask = ~0u;
+ sc->tc.tc_quality = 1000;
+ sc->tc.tc_priv = sc;
+
+ sp804_timer_tc_write_4(SP804_TIMER1_VALUE, 0xffffffff);
+ sp804_timer_tc_write_4(SP804_TIMER1_LOAD, 0xffffffff);
+ reg = TIMER_CONTROL_PERIODIC | TIMER_CONTROL_32BIT;
+ sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, reg);
+ reg |= TIMER_CONTROL_EN;
+ sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, reg);
+ tc_init(&sc->tc);
+
+ /*
+ * Timer 2, event timer
+ */
+ sc->et_enabled = 0;
+ sc->et.et_name = malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
+ sprintf(sc->et.et_name, "SP804 Event Timer %d",
+ device_get_unit(dev));
+ sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
+ sc->et.et_quality = 1000;
+ sc->et.et_frequency = sc->sysclk_freq / DEFAULT_DIVISOR;
+ sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
+ sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
+ sc->et.et_start = sp804_timer_start;
+ sc->et.et_stop = sp804_timer_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ id = 0;
+ for (i = 3; i >= 0; i--) {
+ id = (id << 8) |
+ (sp804_timer_tc_read_4(SP804_PERIPH_ID0 + i*4) & 0xff);
+ }
+
+ device_printf(dev, "peripheral ID: %08x\n", id);
+
+ id = 0;
+ for (i = 3; i >= 0; i--) {
+ id = (id << 8) |
+ (sp804_timer_tc_read_4(SP804_PRIMECELL_ID0 + i*4) & 0xff);
+ }
+
+ device_printf(dev, "PrimeCell ID: %08x\n", id);
+
+ sc->timer_initialized = 1;
+
+ return (0);
+}
+
+static device_method_t sp804_timer_methods[] = {
+ DEVMETHOD(device_probe, sp804_timer_probe),
+ DEVMETHOD(device_attach, sp804_timer_attach),
+ { 0, 0 }
+};
+
+static driver_t sp804_timer_driver = {
+ "timer",
+ sp804_timer_methods,
+ sizeof(struct sp804_timer_softc),
+};
+
+static devclass_t sp804_timer_devclass;
+
+DRIVER_MODULE(sp804_timer, simplebus, sp804_timer_driver, sp804_timer_devclass, 0, 0);
+
+void
+DELAY(int usec)
+{
+ int32_t counts;
+ uint32_t first, last;
+ device_t timer_dev;
+ struct sp804_timer_softc *sc;
+ int timer_initialized = 0;
+
+ timer_dev = devclass_get_device(sp804_timer_devclass, 0);
+
+ if (timer_dev) {
+ sc = device_get_softc(timer_dev);
+
+ if (sc)
+ timer_initialized = sc->timer_initialized;
+ }
+
+ if (!timer_initialized) {
+ /*
+ * Timer is not initialized yet
+ */
+ for (; usec > 0; usec--)
+ for (counts = 200; counts > 0; counts--)
+ /* Prevent gcc from optimizing out the loop */
+ cpufunc_nullop();
+ return;
+ }
+
+ /* Get the number of times to count */
+ counts = usec * ((sc->tc.tc_frequency / 1000000) + 1);
+
+ first = sp804_timer_tc_get_timecount(&sc->tc);
+
+ while (counts > 0) {
+ last = sp804_timer_tc_get_timecount(&sc->tc);
+ if (last == first)
+ continue;
+ if (last>first) {
+ counts -= (int32_t)(last - first);
+ } else {
+ counts -= (int32_t)((0xFFFFFFFF - first) + last);
+ }
+ first = last;
+ }
+}
Property changes on: trunk/sys/arm/versatile/sp804.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/versatile_clcd.c
===================================================================
--- trunk/sys/arm/versatile/versatile_clcd.c (rev 0)
+++ trunk/sys/arm/versatile/versatile_clcd.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,962 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/versatile_clcd.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#define PL110_VENDOR_ARM926PXP 1
+
+#define MEM_SYS 0
+#define MEM_CLCD 1
+#define MEM_REGIONS 2
+
+#define SYS_CLCD 0x00
+#define SYS_CLCD_CLCDID_SHIFT 0x08
+#define SYS_CLCD_CLCDID_MASK 0x1f
+#define SYS_CLCD_PWR3V5VSWITCH (1 << 4)
+#define SYS_CLCD_VDDPOSSWITCH (1 << 3)
+#define SYS_CLCD_NLCDIOON (1 << 2)
+#define SYS_CLCD_LCD_MODE_MASK 0x03
+
+#define CLCD_MODE_RGB888 0x0
+#define CLCD_MODE_RGB555 0x01
+#define CLCD_MODE_RBG565 0x02
+#define CLCD_MODE_RGB565 0x03
+
+#define CLCDC_TIMING0 0x00
+#define CLCDC_TIMING1 0x04
+#define CLCDC_TIMING2 0x08
+#define CLCDC_TIMING3 0x0C
+#define CLCDC_TIMING3 0x0C
+#define CLCDC_UPBASE 0x10
+#define CLCDC_LPBASE 0x14
+#ifdef PL110_VENDOR_ARM926PXP
+#define CLCDC_CONTROL 0x18
+#define CLCDC_IMSC 0x1C
+#else
+#define CLCDC_IMSC 0x18
+#define CLCDC_CONTROL 0x1C
+#endif
+#define CONTROL_WATERMARK (1 << 16)
+#define CONTROL_VCOMP_VS (0 << 12)
+#define CONTROL_VCOMP_BP (1 << 12)
+#define CONTROL_VCOMP_SAV (2 << 12)
+#define CONTROL_VCOMP_FP (3 << 12)
+#define CONTROL_PWR (1 << 11)
+#define CONTROL_BEPO (1 << 10)
+#define CONTROL_BEBO (1 << 9)
+#define CONTROL_BGR (1 << 8)
+#define CONTROL_DUAL (1 << 7)
+#define CONTROL_MONO8 (1 << 6)
+#define CONTROL_TFT (1 << 5)
+#define CONTROL_BW (1 << 4)
+#define CONTROL_BPP1 (0x00 << 1)
+#define CONTROL_BPP2 (0x01 << 1)
+#define CONTROL_BPP4 (0x02 << 1)
+#define CONTROL_BPP8 (0x03 << 1)
+#define CONTROL_BPP16 (0x04 << 1)
+#define CONTROL_BPP24 (0x05 << 1)
+#define CONTROL_EN (1 << 0)
+#define CLCDC_RIS 0x20
+#define CLCDC_MIS 0x24
+#define INTR_MBERR (1 << 4)
+#define INTR_VCOMP (1 << 3)
+#define INTR_LNB (1 << 2)
+#define INTR_FUF (1 << 1)
+#define CLCDC_ICR 0x28
+
+#ifdef DEBUG
+#define dprintf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+#define versatile_clcdc_sys_read_4(sc, reg) \
+ bus_read_4((sc)->mem_res[MEM_SYS], (reg))
+#define versatile_clcdc_sys_write_4(sc, reg, val) \
+ bus_write_4((sc)->mem_res[MEM_SYS], (reg), (val))
+
+#define versatile_clcdc_read_4(sc, reg) \
+ bus_read_4((sc)->mem_res[MEM_CLCD], (reg))
+#define versatile_clcdc_write_4(sc, reg, val) \
+ bus_write_4((sc)->mem_res[MEM_CLCD], (reg), (val))
+
+struct versatile_clcdc_softc {
+ struct resource* mem_res[MEM_REGIONS];
+
+ struct mtx mtx;
+
+ int width;
+ int height;
+ int mode;
+
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+ bus_addr_t fb_phys;
+ uint8_t *fb_base;
+
+};
+
+struct video_adapter_softc {
+ /* Videoadpater part */
+ video_adapter_t va;
+ int console;
+
+ intptr_t fb_addr;
+ unsigned int fb_size;
+
+ unsigned int height;
+ unsigned int width;
+ unsigned int depth;
+ unsigned int stride;
+
+ unsigned int xmargin;
+ unsigned int ymargin;
+
+ unsigned char *font;
+ int initialized;
+};
+
+struct argb {
+ uint8_t a;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+};
+
+static struct argb versatilefb_palette[16] = {
+ {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0xaa},
+ {0x00, 0x00, 0xaa, 0x00},
+ {0x00, 0x00, 0xaa, 0xaa},
+ {0x00, 0xaa, 0x00, 0x00},
+ {0x00, 0xaa, 0x00, 0xaa},
+ {0x00, 0xaa, 0x55, 0x00},
+ {0x00, 0xaa, 0xaa, 0xaa},
+ {0x00, 0x55, 0x55, 0x55},
+ {0x00, 0x55, 0x55, 0xff},
+ {0x00, 0x55, 0xff, 0x55},
+ {0x00, 0x55, 0xff, 0xff},
+ {0x00, 0xff, 0x55, 0x55},
+ {0x00, 0xff, 0x55, 0xff},
+ {0x00, 0xff, 0xff, 0x55},
+ {0x00, 0xff, 0xff, 0xff}
+};
+
+/* mouse pointer from dev/syscons/scgfbrndr.c */
+static u_char mouse_pointer[16] = {
+ 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
+ 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
+};
+
+#define FB_WIDTH 640
+#define FB_HEIGHT 480
+#define FB_DEPTH 16
+
+#define VERSATILE_FONT_HEIGHT 16
+
+static struct video_adapter_softc va_softc;
+
+static struct resource_spec versatile_clcdc_mem_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+static int versatilefb_configure(int);
+static void versatilefb_update_margins(video_adapter_t *adp);
+
+static void
+versatile_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+
+ addr = (bus_addr_t*)arg;
+ *addr = segs[0].ds_addr;
+}
+
+static int
+versatile_clcdc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "arm,pl110")) {
+ device_set_desc(dev, "PL110 CLCD controller");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+versatile_clcdc_attach(device_t dev)
+{
+ struct versatile_clcdc_softc *sc = device_get_softc(dev);
+ struct video_adapter_softc *va_sc = &va_softc;
+ int err;
+ uint32_t reg;
+ int clcdid;
+ int dma_size;
+
+ /* Request memory resources */
+ err = bus_alloc_resources(dev, versatile_clcdc_mem_spec,
+ sc->mem_res);
+ if (err) {
+ device_printf(dev, "Error: could not allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ reg = versatile_clcdc_sys_read_4(sc, SYS_CLCD);
+ clcdid = (reg >> SYS_CLCD_CLCDID_SHIFT) & SYS_CLCD_CLCDID_MASK;
+ switch (clcdid) {
+ case 31:
+ device_printf(dev, "QEMU VGA 640x480\n");
+ sc->width = 640;
+ sc->height = 480;
+ break;
+ default:
+ device_printf(dev, "Unsupported: %d\n", clcdid);
+ goto fail;
+ }
+
+ reg &= ~SYS_CLCD_LCD_MODE_MASK;
+ reg |= CLCD_MODE_RGB565;
+ sc->mode = CLCD_MODE_RGB565;
+ versatile_clcdc_sys_write_4(sc, SYS_CLCD, reg);
+ dma_size = sc->width*sc->height*2;
+
+ /*
+ * Power on LCD
+ */
+ reg |= SYS_CLCD_PWR3V5VSWITCH | SYS_CLCD_NLCDIOON;
+ versatile_clcdc_sys_write_4(sc, SYS_CLCD, reg);
+
+ /*
+ * XXX: hardcoded timing for VGA. For other modes/panels
+ * we need to keep table of timing register values
+ */
+ /*
+ * XXX: set SYS_OSC1
+ */
+ versatile_clcdc_write_4(sc, CLCDC_TIMING0, 0x3F1F3F9C);
+ versatile_clcdc_write_4(sc, CLCDC_TIMING1, 0x090B61DF);
+ versatile_clcdc_write_4(sc, CLCDC_TIMING2, 0x067F1800);
+ /* XXX: timing 3? */
+
+ /*
+ * Now allocate framebuffer memory
+ */
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(dev),
+ 4, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ dma_size, 1, /* maxsize, nsegments */
+ dma_size, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->dma_tag);
+
+ err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_base,
+ 0, &sc->dma_map);
+ if (err) {
+ device_printf(dev, "cannot allocate framebuffer\n");
+ goto fail;
+ }
+
+ err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_base,
+ dma_size, versatile_fb_dmamap_cb, &sc->fb_phys, BUS_DMA_NOWAIT);
+
+ if (err) {
+ device_printf(dev, "cannot load DMA map\n");
+ goto fail;
+ }
+
+ /* Make sure it's blank */
+ memset(sc->fb_base, 0x00, dma_size);
+
+ versatile_clcdc_write_4(sc, CLCDC_UPBASE, sc->fb_phys);
+
+ err = (sc_attach_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD));
+
+ if (err) {
+ device_printf(dev, "failed to attach syscons\n");
+ goto fail;
+ }
+
+ /*
+ * XXX: hardcoded for VGA
+ */
+ reg = CONTROL_VCOMP_BP | CONTROL_TFT | CONTROL_BGR | CONTROL_EN;
+ reg |= CONTROL_BPP16;
+ versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg);
+ DELAY(20);
+ reg |= CONTROL_PWR;
+ versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg);
+
+ va_sc->fb_addr = (vm_offset_t)sc->fb_base;
+ va_sc->fb_size = dma_size;
+ va_sc->width = sc->width;
+ va_sc->height = sc->height;
+ va_sc->depth = 16;
+ va_sc->stride = sc->width * 2;
+ versatilefb_update_margins(&va_sc->va);
+
+ return (0);
+
+fail:
+ if (sc->fb_base)
+ bus_dmamem_free(sc->dma_tag, sc->fb_base, sc->dma_map);
+ if (sc->dma_map)
+ bus_dmamap_destroy(sc->dma_tag, sc->dma_map);
+ if (sc->dma_tag)
+ bus_dma_tag_destroy(sc->dma_tag);
+ return (err);
+}
+
+static device_method_t versatile_clcdc_methods[] = {
+ DEVMETHOD(device_probe, versatile_clcdc_probe),
+ DEVMETHOD(device_attach, versatile_clcdc_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t versatile_clcdc_driver = {
+ "clcdc",
+ versatile_clcdc_methods,
+ sizeof(struct versatile_clcdc_softc),
+};
+
+static devclass_t versatile_clcdc_devclass;
+
+DRIVER_MODULE(versatile_clcdc, simplebus, versatile_clcdc_driver, versatile_clcdc_devclass, 0, 0);
+
+/*
+ * Video driver routines and glue.
+ */
+static vi_probe_t versatilefb_probe;
+static vi_init_t versatilefb_init;
+static vi_get_info_t versatilefb_get_info;
+static vi_query_mode_t versatilefb_query_mode;
+static vi_set_mode_t versatilefb_set_mode;
+static vi_save_font_t versatilefb_save_font;
+static vi_load_font_t versatilefb_load_font;
+static vi_show_font_t versatilefb_show_font;
+static vi_save_palette_t versatilefb_save_palette;
+static vi_load_palette_t versatilefb_load_palette;
+static vi_set_border_t versatilefb_set_border;
+static vi_save_state_t versatilefb_save_state;
+static vi_load_state_t versatilefb_load_state;
+static vi_set_win_org_t versatilefb_set_win_org;
+static vi_read_hw_cursor_t versatilefb_read_hw_cursor;
+static vi_set_hw_cursor_t versatilefb_set_hw_cursor;
+static vi_set_hw_cursor_shape_t versatilefb_set_hw_cursor_shape;
+static vi_blank_display_t versatilefb_blank_display;
+static vi_mmap_t versatilefb_mmap;
+static vi_ioctl_t versatilefb_ioctl;
+static vi_clear_t versatilefb_clear;
+static vi_fill_rect_t versatilefb_fill_rect;
+static vi_bitblt_t versatilefb_bitblt;
+static vi_diag_t versatilefb_diag;
+static vi_save_cursor_palette_t versatilefb_save_cursor_palette;
+static vi_load_cursor_palette_t versatilefb_load_cursor_palette;
+static vi_copy_t versatilefb_copy;
+static vi_putp_t versatilefb_putp;
+static vi_putc_t versatilefb_putc;
+static vi_puts_t versatilefb_puts;
+static vi_putm_t versatilefb_putm;
+
+static video_switch_t versatilefbvidsw = {
+ .probe = versatilefb_probe,
+ .init = versatilefb_init,
+ .get_info = versatilefb_get_info,
+ .query_mode = versatilefb_query_mode,
+ .set_mode = versatilefb_set_mode,
+ .save_font = versatilefb_save_font,
+ .load_font = versatilefb_load_font,
+ .show_font = versatilefb_show_font,
+ .save_palette = versatilefb_save_palette,
+ .load_palette = versatilefb_load_palette,
+ .set_border = versatilefb_set_border,
+ .save_state = versatilefb_save_state,
+ .load_state = versatilefb_load_state,
+ .set_win_org = versatilefb_set_win_org,
+ .read_hw_cursor = versatilefb_read_hw_cursor,
+ .set_hw_cursor = versatilefb_set_hw_cursor,
+ .set_hw_cursor_shape = versatilefb_set_hw_cursor_shape,
+ .blank_display = versatilefb_blank_display,
+ .mmap = versatilefb_mmap,
+ .ioctl = versatilefb_ioctl,
+ .clear = versatilefb_clear,
+ .fill_rect = versatilefb_fill_rect,
+ .bitblt = versatilefb_bitblt,
+ .diag = versatilefb_diag,
+ .save_cursor_palette = versatilefb_save_cursor_palette,
+ .load_cursor_palette = versatilefb_load_cursor_palette,
+ .copy = versatilefb_copy,
+ .putp = versatilefb_putp,
+ .putc = versatilefb_putc,
+ .puts = versatilefb_puts,
+ .putm = versatilefb_putm,
+};
+
+VIDEO_DRIVER(versatilefb, versatilefbvidsw, versatilefb_configure);
+
+static vr_init_t clcdr_init;
+static vr_clear_t clcdr_clear;
+static vr_draw_border_t clcdr_draw_border;
+static vr_draw_t clcdr_draw;
+static vr_set_cursor_t clcdr_set_cursor;
+static vr_draw_cursor_t clcdr_draw_cursor;
+static vr_blink_cursor_t clcdr_blink_cursor;
+static vr_set_mouse_t clcdr_set_mouse;
+static vr_draw_mouse_t clcdr_draw_mouse;
+
+/*
+ * We use our own renderer; this is because we must emulate a hardware
+ * cursor.
+ */
+static sc_rndr_sw_t clcdrend = {
+ clcdr_init,
+ clcdr_clear,
+ clcdr_draw_border,
+ clcdr_draw,
+ clcdr_set_cursor,
+ clcdr_draw_cursor,
+ clcdr_blink_cursor,
+ clcdr_set_mouse,
+ clcdr_draw_mouse
+};
+
+RENDERER(versatilefb, 0, clcdrend, gfb_set);
+RENDERER_MODULE(versatilefb, gfb_set);
+
+static void
+clcdr_init(scr_stat* scp)
+{
+}
+
+static void
+clcdr_clear(scr_stat* scp, int c, int attr)
+{
+}
+
+static void
+clcdr_draw_border(scr_stat* scp, int color)
+{
+}
+
+static void
+clcdr_draw(scr_stat* scp, int from, int count, int flip)
+{
+ video_adapter_t* adp = scp->sc->adp;
+ int i, c, a;
+
+ if (!flip) {
+ /* Normal printing */
+ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count);
+ } else {
+ /* This is for selections and such: invert the color attribute */
+ for (i = count; i-- > 0; ++from) {
+ c = sc_vtb_getc(&scp->vtb, from);
+ a = sc_vtb_geta(&scp->vtb, from) >> 8;
+ vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4));
+ }
+ }
+}
+
+static void
+clcdr_set_cursor(scr_stat* scp, int base, int height, int blink)
+{
+}
+
+static void
+clcdr_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip)
+{
+ video_adapter_t* adp = scp->sc->adp;
+ struct video_adapter_softc *sc;
+ int row, col;
+ uint8_t *addr;
+ int i,j;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ if (scp->curs_attr.height <= 0)
+ return;
+
+ if (sc->fb_addr == 0)
+ return;
+
+ if (off >= adp->va_info.vi_width * adp->va_info.vi_height)
+ return;
+
+ /* calculate the coordinates in the video buffer */
+ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+ col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+
+ addr = (uint8_t *)sc->fb_addr
+ + (row + sc->ymargin)*(sc->stride)
+ + (sc->depth/8) * (col + sc->xmargin);
+
+ /* our cursor consists of simply inverting the char under it */
+ for (i = 0; i < adp->va_info.vi_cheight; i++) {
+ for (j = 0; j < adp->va_info.vi_cwidth; j++) {
+
+ addr[2*j] ^= 0xff;
+ addr[2*j + 1] ^= 0xff;
+ }
+
+ addr += sc->stride;
+ }
+}
+
+static void
+clcdr_blink_cursor(scr_stat* scp, int at, int flip)
+{
+}
+
+static void
+clcdr_set_mouse(scr_stat* scp)
+{
+}
+
+static void
+clcdr_draw_mouse(scr_stat* scp, int x, int y, int on)
+{
+ vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8);
+
+}
+
+static uint16_t versatilefb_static_window[ROW*COL];
+extern u_char dflt_font_16[];
+
+/*
+ * Update videoadapter settings after changing resolution
+ */
+static void
+versatilefb_update_margins(video_adapter_t *adp)
+{
+ struct video_adapter_softc *sc;
+ video_info_t *vi;
+
+ sc = (struct video_adapter_softc *)adp;
+ vi = &adp->va_info;
+
+ sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
+}
+
+static int
+versatilefb_configure(int flags)
+{
+ struct video_adapter_softc *va_sc;
+
+ va_sc = &va_softc;
+
+ if (va_sc->initialized)
+ return (0);
+
+ va_sc->width = FB_WIDTH;
+ va_sc->height = FB_HEIGHT;
+ va_sc->depth = FB_DEPTH;
+
+ versatilefb_init(0, &va_sc->va, 0);
+
+ va_sc->initialized = 1;
+
+ return (0);
+}
+
+static int
+versatilefb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_init(int unit, video_adapter_t *adp, int flags)
+{
+ struct video_adapter_softc *sc;
+ video_info_t *vi;
+
+ sc = (struct video_adapter_softc *)adp;
+ vi = &adp->va_info;
+
+ vid_init_struct(adp, "versatilefb", -1, unit);
+
+ sc->font = dflt_font_16;
+ vi->vi_cheight = VERSATILE_FONT_HEIGHT;
+ vi->vi_cwidth = 8;
+
+ vi->vi_width = sc->width/8;
+ vi->vi_height = sc->height/vi->vi_cheight;
+
+ /*
+ * Clamp width/height to syscons maximums
+ */
+ if (vi->vi_width > COL)
+ vi->vi_width = COL;
+ if (vi->vi_height > ROW)
+ vi->vi_height = ROW;
+
+ sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
+
+
+ adp->va_window = (vm_offset_t) versatilefb_static_window;
+ adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
+
+ vid_register(&sc->va);
+
+ return (0);
+}
+
+static int
+versatilefb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
+{
+ bcopy(&adp->va_info, info, sizeof(*info));
+ return (0);
+}
+
+static int
+versatilefb_query_mode(video_adapter_t *adp, video_info_t *info)
+{
+ return (0);
+}
+
+static int
+versatilefb_set_mode(video_adapter_t *adp, int mode)
+{
+ return (0);
+}
+
+static int
+versatilefb_save_font(video_adapter_t *adp, int page, int size, int width,
+ u_char *data, int c, int count)
+{
+ return (0);
+}
+
+static int
+versatilefb_load_font(video_adapter_t *adp, int page, int size, int width,
+ u_char *data, int c, int count)
+{
+ struct video_adapter_softc *sc = (struct video_adapter_softc *)adp;
+
+ sc->font = data;
+
+ return (0);
+}
+
+static int
+versatilefb_show_font(video_adapter_t *adp, int page)
+{
+ return (0);
+}
+
+static int
+versatilefb_save_palette(video_adapter_t *adp, u_char *palette)
+{
+ return (0);
+}
+
+static int
+versatilefb_load_palette(video_adapter_t *adp, u_char *palette)
+{
+ return (0);
+}
+
+static int
+versatilefb_set_border(video_adapter_t *adp, int border)
+{
+ return (versatilefb_blank_display(adp, border));
+}
+
+static int
+versatilefb_save_state(video_adapter_t *adp, void *p, size_t size)
+{
+ return (0);
+}
+
+static int
+versatilefb_load_state(video_adapter_t *adp, void *p)
+{
+ return (0);
+}
+
+static int
+versatilefb_set_win_org(video_adapter_t *adp, off_t offset)
+{
+ return (0);
+}
+
+static int
+versatilefb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
+{
+ *col = *row = 0;
+
+ return (0);
+}
+
+static int
+versatilefb_set_hw_cursor(video_adapter_t *adp, int col, int row)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
+ int celsize, int blink)
+{
+ return (0);
+}
+
+static int
+versatilefb_blank_display(video_adapter_t *adp, int mode)
+{
+
+ struct video_adapter_softc *sc;
+
+ sc = (struct video_adapter_softc *)adp;
+ if (sc && sc->fb_addr)
+ memset((void*)sc->fb_addr, 0, sc->fb_size);
+
+ return (0);
+}
+
+static int
+versatilefb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int prot, vm_memattr_t *memattr)
+{
+ struct video_adapter_softc *sc;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ /*
+ * This might be a legacy VGA mem request: if so, just point it at the
+ * framebuffer, since it shouldn't be touched
+ */
+ if (offset < sc->stride*sc->height) {
+ *paddr = sc->fb_addr + offset;
+ return (0);
+ }
+
+ return (EINVAL);
+}
+
+static int
+versatilefb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_clear(video_adapter_t *adp)
+{
+
+ return (versatilefb_blank_display(adp, 0));
+}
+
+static int
+versatilefb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_bitblt(video_adapter_t *adp, ...)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_diag(video_adapter_t *adp, int level)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
+ int size, int bpp, int bit_ltor, int byte_ltor)
+{
+
+ return (0);
+}
+
+static int
+versatilefb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+{
+ struct video_adapter_softc *sc;
+ int row;
+ int col;
+ int i, j, k;
+ uint8_t *addr;
+ u_char *p;
+ uint8_t fg, bg, color;
+ uint16_t rgb;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ if (sc->fb_addr == 0)
+ return (0);
+
+ if (off >= adp->va_info.vi_width * adp->va_info.vi_height)
+ return (0);
+
+ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+ col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+ p = sc->font + c*VERSATILE_FONT_HEIGHT;
+ addr = (uint8_t *)sc->fb_addr
+ + (row + sc->ymargin)*(sc->stride)
+ + (sc->depth/8) * (col + sc->xmargin);
+
+ fg = a & 0xf ;
+ bg = (a >> 4) & 0xf;
+
+ for (i = 0; i < VERSATILE_FONT_HEIGHT; i++) {
+ for (j = 0, k = 7; j < 8; j++, k--) {
+ if ((p[i] & (1 << k)) == 0)
+ color = bg;
+ else
+ color = fg;
+
+ switch (sc->depth) {
+ case 16:
+ rgb = (versatilefb_palette[color].r >> 3) << 11;
+ rgb |= (versatilefb_palette[color].g >> 2) << 5;
+ rgb |= (versatilefb_palette[color].b >> 3);
+ addr[2*j] = rgb & 0xff;
+ addr[2*j + 1] = (rgb >> 8) & 0xff;
+ default:
+ /* Not supported yet */
+ break;
+ }
+ }
+
+ addr += (sc->stride);
+ }
+
+ return (0);
+}
+
+static int
+versatilefb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ versatilefb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
+
+ return (0);
+}
+
+static int
+versatilefb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+ uint32_t pixel_mask, int size, int width)
+{
+
+ return (0);
+}
+
+/*
+ * Define a stub keyboard driver in case one hasn't been
+ * compiled into the kernel
+ */
+#include <sys/kbio.h>
+#include <dev/kbd/kbdreg.h>
+
+static int dummy_kbd_configure(int flags);
+
+keyboard_switch_t bcmdummysw;
+
+static int
+dummy_kbd_configure(int flags)
+{
+
+ return (0);
+}
+KEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure);
Property changes on: trunk/sys/arm/versatile/versatile_clcd.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/versatile_common.c
===================================================================
--- trunk/sys/arm/versatile/versatile_common.c (rev 0)
+++ trunk/sys/arm/versatile/versatile_common.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,76 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_global.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/versatile_common.c 266277 2014-05-17 00:53:12Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kdb.h>
+#include <sys/reboot.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (!fdt_is_compatible(node, "arm,versatile-vic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_intc_decode_ic,
+ NULL
+};
Property changes on: trunk/sys/arm/versatile/versatile_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/versatile_machdep.c
===================================================================
--- trunk/sys/arm/versatile/versatile_machdep.c (rev 0)
+++ trunk/sys/arm/versatile/versatile_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,128 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+#include "opt_global.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/versatile_machdep.c 259365 2013-12-14 00:16:08Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <dev/fdt/fdt_common.h>
+
+/* Start of address space used for bootstrap map */
+#define DEVMAP_BOOTSTRAP_MAP_START 0xE0000000
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (DEVMAP_BOOTSTRAP_MAP_START);
+}
+
+void
+initarm_early_init(void)
+{
+
+}
+
+void
+initarm_gpio_init(void)
+{
+}
+
+void
+initarm_late_init(void)
+{
+}
+
+#define FDT_DEVMAP_MAX (2) /* FIXME */
+static struct arm_devmap_entry fdt_devmap[FDT_DEVMAP_MAX] = {
+ { 0, 0, 0, 0, 0, },
+ { 0, 0, 0, 0, 0, }
+};
+
+
+/*
+ * Construct pmap_devmap[] with DT-derived config data.
+ */
+int
+initarm_devmap_init(void)
+{
+ int i = 0;
+ fdt_devmap[i].pd_va = 0xf0100000;
+ fdt_devmap[i].pd_pa = 0x10100000;
+ fdt_devmap[i].pd_size = 0x01000000; /* 1 MB */
+ fdt_devmap[i].pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ fdt_devmap[i].pd_cache = PTE_DEVICE;
+
+ arm_devmap_register_table(&fdt_devmap[0]);
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+void
+cpu_reset()
+{
+ printf("cpu_reset\n");
+ while (1);
+}
+
Property changes on: trunk/sys/arm/versatile/versatile_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/versatile_pci.c
===================================================================
--- trunk/sys/arm/versatile/versatile_pci.c (rev 0)
+++ trunk/sys/arm/versatile/versatile_pci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,518 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/versatile_pci.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <dev/pci/pcib_private.h>
+#include "pcib_if.h"
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#define MEM_SYS 0
+#define MEM_CORE 1
+#define MEM_BASE 2
+#define MEM_CONF_BASE 3
+#define MEM_REGIONS 4
+
+#define SYS_PCICTL 0x00
+
+#define PCI_CORE_IMAP0 0x00
+#define PCI_CORE_IMAP1 0x04
+#define PCI_CORE_IMAP2 0x08
+#define PCI_CORE_SELFID 0x0C
+#define PCI_CORE_SMAP0 0x10
+#define PCI_CORE_SMAP1 0x14
+#define PCI_CORE_SMAP2 0x18
+
+#define VERSATILE_PCI_DEV 0x030010ee
+#define VERSATILE_PCI_CLASS 0x0b400000
+
+#define PCI_IO_WINDOW 0x44000000
+#define PCI_IO_SIZE 0x0c000000
+#define PCI_NPREFETCH_WINDOW 0x50000000
+#define PCI_NPREFETCH_SIZE 0x10000000
+#define PCI_PREFETCH_WINDOW 0x60000000
+#define PCI_PREFETCH_SIZE 0x10000000
+
+#define VERSATILE_PCI_IRQ_START 27
+#define VERSATILE_PCI_IRQ_END 30
+
+#ifdef DEBUG
+#define dprintf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+
+#define versatile_pci_sys_read_4(reg) \
+ bus_read_4(sc->mem_res[MEM_SYS], (reg))
+#define versatile_pci_sys_write_4(reg, val) \
+ bus_write_4(sc->mem_res[MEM_SYS], (reg), (val))
+
+#define versatile_pci_core_read_4(reg) \
+ bus_read_4(sc->mem_res[MEM_CORE], (reg))
+#define versatile_pci_core_write_4(reg, val) \
+ bus_write_4(sc->mem_res[MEM_CORE], (reg), (val))
+
+#define versatile_pci_read_4(reg) \
+ bus_read_4(sc->mem_res[MEM_BASE], (reg))
+#define versatile_pci_write_4(reg, val) \
+ bus_write_4(sc->mem_res[MEM_BASE], (reg), (val))
+
+#define versatile_pci_conf_read_4(reg) \
+ bus_read_4(sc->mem_res[MEM_CONF_BASE], (reg))
+#define versatile_pci_conf_write_4(reg, val) \
+ bus_write_4(sc->mem_res[MEM_CONF_BASE], (reg), (val))
+#define versatile_pci_conf_write_2(reg, val) \
+ bus_write_2(sc->mem_res[MEM_CONF_BASE], (reg), (val))
+#define versatile_pci_conf_write_1(reg, val) \
+ bus_write_1(sc->mem_res[MEM_CONF_BASE], (reg), (val))
+
+struct versatile_pci_softc {
+ struct resource* mem_res[MEM_REGIONS];
+ struct resource* irq_res;
+ void* intr_hl;
+
+ int pcib_slot;
+
+ /* Bus part */
+ int busno;
+ struct rman io_rman;
+ struct rman irq_rman;
+ struct rman mem_rman;
+
+ struct mtx mtx;
+};
+
+static struct resource_spec versatile_pci_mem_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE },
+ { -1, 0, 0 }
+};
+
+static int
+versatile_pci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "versatile,pci")) {
+ device_set_desc(dev, "Versatile PCI controller");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+versatile_pci_attach(device_t dev)
+{
+ struct versatile_pci_softc *sc = device_get_softc(dev);
+ int err;
+ int slot;
+ uint32_t vendordev_id, class_id;
+ uint32_t val;
+
+ /* Request memory resources */
+ err = bus_alloc_resources(dev, versatile_pci_mem_spec,
+ sc->mem_res);
+ if (err) {
+ device_printf(dev, "Error: could not allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Setup memory windows
+ */
+ versatile_pci_core_write_4(PCI_CORE_IMAP0, (PCI_IO_WINDOW >> 28));
+ versatile_pci_core_write_4(PCI_CORE_IMAP1, (PCI_NPREFETCH_WINDOW >> 28));
+ versatile_pci_core_write_4(PCI_CORE_IMAP2, (PCI_PREFETCH_WINDOW >> 28));
+
+ /*
+ * XXX: this is SDRAM offset >> 28
+ * Unused as of QEMU 1.5
+ */
+ versatile_pci_core_write_4(PCI_CORE_SMAP0, (PCI_IO_WINDOW >> 28));
+ versatile_pci_core_write_4(PCI_CORE_SMAP1, (PCI_NPREFETCH_WINDOW >> 28));
+ versatile_pci_core_write_4(PCI_CORE_SMAP2, (PCI_NPREFETCH_WINDOW >> 28));
+
+ versatile_pci_sys_write_4(SYS_PCICTL, 1);
+
+ for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
+ vendordev_id = versatile_pci_read_4((slot << 11) + PCIR_DEVVENDOR);
+ class_id = versatile_pci_read_4((slot << 11) + PCIR_REVID);
+ if ((vendordev_id == VERSATILE_PCI_DEV) &&
+ (class_id == VERSATILE_PCI_CLASS))
+ break;
+ }
+
+ if (slot == (PCI_SLOTMAX + 1)) {
+ bus_release_resources(dev, versatile_pci_mem_spec,
+ sc->mem_res);
+ device_printf(dev, "Versatile PCI core not found\n");
+ return (ENXIO);
+ }
+
+ sc->pcib_slot = slot;
+ device_printf(dev, "PCI core at slot #%d\n", slot);
+
+ versatile_pci_core_write_4(PCI_CORE_SELFID, slot);
+ val = versatile_pci_conf_read_4((slot << 11) + PCIR_COMMAND);
+ val |= (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | PCIM_CMD_MWRICEN);
+ versatile_pci_conf_write_4((slot << 11) + PCIR_COMMAND, val);
+
+ /* Again SDRAM start >> 28 */
+ versatile_pci_write_4((slot << 11) + PCIR_BAR(0), 0);
+ versatile_pci_write_4((slot << 11) + PCIR_BAR(1), 0);
+ versatile_pci_write_4((slot << 11) + PCIR_BAR(2), 0);
+
+ /* Prepare resource managers */
+ sc->mem_rman.rm_type = RMAN_ARRAY;
+ sc->mem_rman.rm_descr = "versatile PCI memory window";
+ if (rman_init(&sc->mem_rman) != 0 ||
+ rman_manage_region(&sc->mem_rman, PCI_NPREFETCH_WINDOW,
+ PCI_NPREFETCH_WINDOW + PCI_NPREFETCH_SIZE - 1) != 0) {
+ panic("versatile_pci_attach: failed to set up memory rman");
+ }
+
+ bootverbose = 1;
+ sc->io_rman.rm_type = RMAN_ARRAY;
+ sc->io_rman.rm_descr = "versatile PCI IO window";
+ if (rman_init(&sc->io_rman) != 0 ||
+ rman_manage_region(&sc->io_rman, PCI_IO_WINDOW,
+ PCI_IO_WINDOW + PCI_IO_SIZE - 1) != 0) {
+ panic("versatile_pci_attach: failed to set up I/O rman");
+ }
+
+ sc->irq_rman.rm_type = RMAN_ARRAY;
+ sc->irq_rman.rm_descr = "versatile PCI IRQs";
+ if (rman_init(&sc->irq_rman) != 0 ||
+ rman_manage_region(&sc->irq_rman, VERSATILE_PCI_IRQ_START,
+ VERSATILE_PCI_IRQ_END) != 0) {
+ panic("versatile_pci_attach: failed to set up IRQ rman");
+ }
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), "versatilepci",
+ MTX_SPIN);
+
+ val = versatile_pci_conf_read_4((12 << 11) + PCIR_COMMAND);
+
+ for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
+ vendordev_id = versatile_pci_read_4((slot << 11) + PCIR_DEVVENDOR);
+ class_id = versatile_pci_read_4((slot << 11) + PCIR_REVID);
+
+ if (slot == sc->pcib_slot)
+ continue;
+
+ if ((vendordev_id == 0xffffffff) &&
+ (class_id == 0xffffffff))
+ continue;
+
+ val = versatile_pci_conf_read_4((slot << 11) + PCIR_COMMAND);
+ val |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
+ versatile_pci_conf_write_4((slot << 11) + PCIR_COMMAND, val);
+ }
+
+ device_add_child(dev, "pci", 0);
+ return (bus_generic_attach(dev));
+}
+
+static int
+versatile_pci_read_ivar(device_t dev, device_t child, int which,
+ uintptr_t *result)
+{
+ struct versatile_pci_softc *sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = 0;
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = sc->busno;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+versatile_pci_write_ivar(device_t dev, device_t child, int which,
+ uintptr_t result)
+{
+ struct versatile_pci_softc * sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ sc->busno = result;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static struct resource *
+versatile_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+
+ struct versatile_pci_softc *sc = device_get_softc(bus);
+ struct resource *rv;
+ struct rman *rm;
+
+ dprintf("Alloc resources %d, %08lx..%08lx, %ld\n", type, start, end, count);
+
+ switch (type) {
+ case SYS_RES_IOPORT:
+ rm = &sc->io_rman;
+ break;
+ case SYS_RES_IRQ:
+ rm = &sc->irq_rman;
+ break;
+ case SYS_RES_MEMORY:
+ rm = &sc->mem_rman;
+ break;
+ default:
+ return (NULL);
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+
+ if (rv == NULL)
+ return (NULL);
+
+ rman_set_rid(rv, *rid);
+
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+ return (rv);
+}
+
+static int
+versatile_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ vm_offset_t vaddr;
+ int res;
+
+ switch(type) {
+ case SYS_RES_MEMORY:
+ case SYS_RES_IOPORT:
+ vaddr = (vm_offset_t)pmap_mapdev(rman_get_start(r),
+ rman_get_size(r));
+ rman_set_bushandle(r, vaddr);
+ rman_set_bustag(r, arm_base_bs_tag);
+ res = rman_activate_resource(r);
+ break;
+ case SYS_RES_IRQ:
+ res = (BUS_ACTIVATE_RESOURCE(device_get_parent(bus),
+ child, type, rid, r));
+ break;
+ default:
+ res = ENXIO;
+ break;
+ }
+
+ return (res);
+}
+
+static int
+versatile_pci_setup_intr(device_t bus, device_t child, struct resource *ires,
+ int flags, driver_filter_t *filt, driver_intr_t *handler,
+ void *arg, void **cookiep)
+{
+
+ return BUS_SETUP_INTR(device_get_parent(bus), bus, ires, flags,
+ filt, handler, arg, cookiep);
+}
+
+static int
+versatile_pci_teardown_intr(device_t dev, device_t child, struct resource *ires,
+ void *cookie)
+{
+
+ return BUS_TEARDOWN_INTR(device_get_parent(dev), dev, ires, cookie);
+}
+
+
+
+static int
+versatile_pci_maxslots(device_t dev)
+{
+
+ return (PCI_SLOTMAX);
+}
+
+static int
+versatile_pci_route_interrupt(device_t pcib, device_t device, int pin)
+{
+
+ return (27 + ((pci_get_slot(device) + pin - 1) & 3));
+}
+
+static uint32_t
+versatile_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, int bytes)
+{
+ struct versatile_pci_softc *sc = device_get_softc(dev);
+ uint32_t data;
+ uint32_t shift, mask;
+ uint32_t addr;
+
+ if (sc->pcib_slot == slot) {
+ switch (bytes) {
+ case 4:
+ return (0xffffffff);
+ break;
+ case 2:
+ return (0xffff);
+ break;
+ case 1:
+ return (0xff);
+ break;
+ }
+ }
+
+ addr = (bus << 16) | (slot << 11) | (func << 8) | (reg & ~3);
+
+ /* register access is 32-bit aligned */
+ shift = (reg & 3) * 8;
+
+ /* Create a mask based on the width, post-shift */
+ if (bytes == 2)
+ mask = 0xffff;
+ else if (bytes == 1)
+ mask = 0xff;
+ else
+ mask = 0xffffffff;
+
+ dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot,
+ func, reg, bytes);
+
+ mtx_lock_spin(&sc->mtx);
+ data = versatile_pci_conf_read_4(addr);
+ mtx_unlock_spin(&sc->mtx);
+
+ /* get request bytes from 32-bit word */
+ data = (data >> shift) & mask;
+
+ dprintf("%s: read 0x%x\n", __func__, data);
+
+ return (data);
+}
+
+static void
+versatile_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, uint32_t data, int bytes)
+{
+
+ struct versatile_pci_softc *sc = device_get_softc(dev);
+ uint32_t addr;
+
+ dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot,
+ func, reg, bytes);
+
+ if (sc->pcib_slot == slot)
+ return;
+
+ addr = (bus << 16) | (slot << 11) | (func << 8) | reg;
+ mtx_lock_spin(&sc->mtx);
+ switch (bytes) {
+ case 4:
+ versatile_pci_conf_write_4(addr, data);
+ break;
+ case 2:
+ versatile_pci_conf_write_2(addr, data);
+ break;
+ case 1:
+ versatile_pci_conf_write_1(addr, data);
+ break;
+ }
+ mtx_unlock_spin(&sc->mtx);
+}
+
+static device_method_t versatile_pci_methods[] = {
+ DEVMETHOD(device_probe, versatile_pci_probe),
+ DEVMETHOD(device_attach, versatile_pci_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, versatile_pci_read_ivar),
+ DEVMETHOD(bus_write_ivar, versatile_pci_write_ivar),
+ DEVMETHOD(bus_alloc_resource, versatile_pci_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, versatile_pci_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, versatile_pci_setup_intr),
+ DEVMETHOD(bus_teardown_intr, versatile_pci_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, versatile_pci_maxslots),
+ DEVMETHOD(pcib_read_config, versatile_pci_read_config),
+ DEVMETHOD(pcib_write_config, versatile_pci_write_config),
+ DEVMETHOD(pcib_route_interrupt, versatile_pci_route_interrupt),
+
+ DEVMETHOD_END
+};
+
+static driver_t versatile_pci_driver = {
+ "pcib",
+ versatile_pci_methods,
+ sizeof(struct versatile_pci_softc),
+};
+
+static devclass_t versatile_pci_devclass;
+
+DRIVER_MODULE(versatile_pci, simplebus, versatile_pci_driver, versatile_pci_devclass, 0, 0);
Property changes on: trunk/sys/arm/versatile/versatile_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/versatile_sic.c
===================================================================
--- trunk/sys/arm/versatile/versatile_sic.c (rev 0)
+++ trunk/sys/arm/versatile/versatile_sic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,138 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/versatile_sic.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#ifdef DEBUG
+#define dprintf(fmt, args...) printf(fmt, ##args)
+#else
+#define dprintf(fmt, args...)
+#endif
+
+#define SIC_STATUS 0x00
+#define SIC_RAWSTAT 0x04
+#define SIC_ENABLE 0x08
+#define SIC_ENSET 0x08
+#define SIC_ENCLR 0x0C
+#define SIC_SOFTINTSET 0x10
+#define SIC_SOFTINTCLR 0x14
+#define SIC_PICENABLE 0x20
+#define SIC_PICENSET 0x20
+#define SIC_PICENCLR 0x24
+
+struct versatile_sic_softc {
+ device_t sc_dev;
+ struct resource * mem_res;
+};
+
+#define sic_read_4(sc, reg) \
+ bus_read_4(sc->mem_res, (reg))
+#define sic_write_4(sc, reg, val) \
+ bus_write_4(sc->mem_res, (reg), (val))
+
+static int
+versatile_sic_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "arm,versatile-sic"))
+ return (ENXIO);
+ device_set_desc(dev, "ARM Versatile SIC");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+versatile_sic_attach(device_t dev)
+{
+ struct versatile_sic_softc *sc = device_get_softc(dev);
+ uint32_t pass_irqs;
+ int rid;
+
+ sc->sc_dev = dev;
+
+ /* Request memory resources */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Error: could not allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ /* Disable all interrupts on SIC */
+ sic_write_4(sc, SIC_ENCLR, 0xffffffff);
+
+ /*
+ * XXX: Enable IRQ3 for KMI
+ * Should be replaced by proper interrupts cascading
+ */
+ sic_write_4(sc, SIC_ENSET, (1 << 3));
+
+ /*
+ * Let PCI and Ethernet interrupts pass through
+ * IRQ25, IRQ27..IRQ31
+ */
+ pass_irqs = (0x1f << 27) | (1 << 25);
+ sic_write_4(sc, SIC_PICENSET, pass_irqs);
+
+ return (0);
+}
+
+static device_method_t versatile_sic_methods[] = {
+ DEVMETHOD(device_probe, versatile_sic_probe),
+ DEVMETHOD(device_attach, versatile_sic_attach),
+ { 0, 0 }
+};
+
+static driver_t versatile_sic_driver = {
+ "sic",
+ versatile_sic_methods,
+ sizeof(struct versatile_sic_softc),
+};
+
+static devclass_t versatile_sic_devclass;
+
+DRIVER_MODULE(sic, simplebus, versatile_sic_driver, versatile_sic_devclass, 0, 0);
Property changes on: trunk/sys/arm/versatile/versatile_sic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/versatile/versatile_timer.c
===================================================================
--- trunk/sys/arm/versatile/versatile_timer.c (rev 0)
+++ trunk/sys/arm/versatile/versatile_timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,59 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/versatile/versatile_timer.c 259329 2013-12-13 20:43:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+void
+cpu_initclocks(void)
+{
+ cpu_initclocks_bsp();
+}
+
+
Property changes on: trunk/sys/arm/versatile/versatile_timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/files.zynq7
===================================================================
--- trunk/sys/arm/xilinx/files.zynq7 (rev 0)
+++ trunk/sys/arm/xilinx/files.zynq7 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,31 @@
+#
+# files.zynq7
+#
+# $FreeBSD: stable/10/sys/arm/xilinx/files.zynq7 278727 2015-02-13 22:32:02Z ian $
+
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+
+arm/arm/gic.c standard
+arm/arm/mpcore_timer.c standard
+arm/arm/pl310.c standard
+
+arm/xilinx/zy7_machdep.c standard
+arm/xilinx/zy7_l2cache.c standard
+arm/xilinx/zy7_slcr.c standard
+arm/xilinx/zy7_devcfg.c standard
+arm/xilinx/zy7_mp.c optional smp
+
+dev/cadence/if_cgem.c optional cgem
+dev/sdhci/sdhci_fdt.c optional sdhci
+arm/xilinx/zy7_ehci.c optional ehci
+arm/xilinx/uart_dev_cdnc.c optional uart
+arm/xilinx/zy7_gpio.c optional gpio
+
Property changes on: trunk/sys/arm/xilinx/files.zynq7
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xilinx/std.zynq7
===================================================================
--- trunk/sys/arm/xilinx/std.zynq7 (rev 0)
+++ trunk/sys/arm/xilinx/std.zynq7 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,25 @@
+#
+# std.zynq7 - Generic configuration for Xilinx Zynq-7000 PS.
+#
+# $FreeBSD: stable/10/sys/arm/xilinx/std.zynq7 278601 2015-02-11 22:47:48Z ian $
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
+
+files "../xilinx/files.zynq7"
+
+# Physical memory starts at 0x00000000. We assume images are loaded at
+# 0x00100000, e.g. from u-boot with 'fatload mmc 0 0x100000 kernel.bin'
+#
+#
+options PHYSADDR=0x00000000
+options KERNPHYSADDR=0x00100000
+makeoptions KERNPHYSADDR=0x00100000
+options KERNVIRTADDR=0xc0100000 # Used in ldscript.arm
+makeoptions KERNVIRTADDR=0xc0100000
+
+options ARM_L2_PIPT
+
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
Property changes on: trunk/sys/arm/xilinx/std.zynq7
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xilinx/uart_dev_cdnc.c
===================================================================
--- trunk/sys/arm/xilinx/uart_dev_cdnc.c (rev 0)
+++ trunk/sys/arm/xilinx/uart_dev_cdnc.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,717 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 M. Warner Losh
+ * Copyright (c) 2005 Olivier Houchard
+ * Copyright (c) 2012 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* A driver for the Cadence AMBA UART as used by the Xilinx Zynq-7000.
+ *
+ * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
+ * (v1.4) November 16, 2012. Xilinx doc UG585. UART is covered in Ch. 19
+ * and register definitions are in appendix B.33.
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/uart_dev_cdnc.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include "opt_global.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/tty.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+
+#include "uart_if.h"
+
+#define UART_FIFO_SIZE 64
+
+#define RD4(bas, reg) \
+ bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs((bas), (reg)))
+#define WR4(bas, reg, value) \
+ bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs((bas), (reg)), \
+ (value))
+
+/* Register definitions for Cadence UART Controller.
+ */
+#define CDNC_UART_CTRL_REG 0x00 /* Control Register. */
+#define CDNC_UART_CTRL_REG_STOPBRK (1<<8)
+#define CDNC_UART_CTRL_REG_STARTBRK (1<<7)
+#define CDNC_UART_CTRL_REG_TORST (1<<6)
+#define CDNC_UART_CTRL_REG_TX_DIS (1<<5)
+#define CDNC_UART_CTRL_REG_TX_EN (1<<4)
+#define CDNC_UART_CTRL_REG_RX_DIS (1<<3)
+#define CDNC_UART_CTRL_REG_RX_EN (1<<2)
+#define CDNC_UART_CTRL_REG_TXRST (1<<1)
+#define CDNC_UART_CTRL_REG_RXRST (1<<0)
+
+#define CDNC_UART_MODE_REG 0x04 /* Mode Register. */
+#define CDNC_UART_MODE_REG_CHMOD_R_LOOP (3<<8) /* [9:8] - channel mode */
+#define CDNC_UART_MODE_REG_CHMOD_L_LOOP (2<<8)
+#define CDNC_UART_MODE_REG_CHMOD_AUTECHO (1<<8)
+#define CDNC_UART_MODE_REG_STOP2 (2<<6) /* [7:6] - stop bits */
+#define CDNC_UART_MODE_REG_PAR_NONE (4<<3) /* [5:3] - parity type */
+#define CDNC_UART_MODE_REG_PAR_MARK (3<<3)
+#define CDNC_UART_MODE_REG_PAR_SPACE (2<<3)
+#define CDNC_UART_MODE_REG_PAR_ODD (1<<3)
+#define CDNC_UART_MODE_REG_PAR_EVEN (0<<3)
+#define CDNC_UART_MODE_REG_6BIT (3<<1) /* [2:1] - character len */
+#define CDNC_UART_MODE_REG_7BIT (2<<1)
+#define CDNC_UART_MODE_REG_8BIT (0<<1)
+#define CDNC_UART_MODE_REG_CLKSEL (1<<0)
+
+#define CDNC_UART_IEN_REG 0x08 /* Interrupt registers. */
+#define CDNC_UART_IDIS_REG 0x0C
+#define CDNC_UART_IMASK_REG 0x10
+#define CDNC_UART_ISTAT_REG 0x14
+#define CDNC_UART_INT_TXOVR (1<<12)
+#define CDNC_UART_INT_TXNRLYFUL (1<<11) /* tx "nearly" full */
+#define CDNC_UART_INT_TXTRIG (1<<10)
+#define CDNC_UART_INT_DMSI (1<<9) /* delta modem status */
+#define CDNC_UART_INT_RXTMOUT (1<<8)
+#define CDNC_UART_INT_PARITY (1<<7)
+#define CDNC_UART_INT_FRAMING (1<<6)
+#define CDNC_UART_INT_RXOVR (1<<5)
+#define CDNC_UART_INT_TXFULL (1<<4)
+#define CDNC_UART_INT_TXEMPTY (1<<3)
+#define CDNC_UART_INT_RXFULL (1<<2)
+#define CDNC_UART_INT_RXEMPTY (1<<1)
+#define CDNC_UART_INT_RXTRIG (1<<0)
+#define CDNC_UART_INT_ALL 0x1FFF
+
+#define CDNC_UART_BAUDGEN_REG 0x18
+#define CDNC_UART_RX_TIMEO_REG 0x1C
+#define CDNC_UART_RX_WATER_REG 0x20
+
+#define CDNC_UART_MODEM_CTRL_REG 0x24
+#define CDNC_UART_MODEM_CTRL_REG_FCM (1<<5) /* automatic flow control */
+#define CDNC_UART_MODEM_CTRL_REG_RTS (1<<1)
+#define CDNC_UART_MODEM_CTRL_REG_DTR (1<<0)
+
+#define CDNC_UART_MODEM_STAT_REG 0x28
+#define CDNC_UART_MODEM_STAT_REG_FCMS (1<<8) /* flow control mode (rw) */
+#define CDNC_UART_MODEM_STAT_REG_DCD (1<<7)
+#define CDNC_UART_MODEM_STAT_REG_RI (1<<6)
+#define CDNC_UART_MODEM_STAT_REG_DSR (1<<5)
+#define CDNC_UART_MODEM_STAT_REG_CTS (1<<4)
+#define CDNC_UART_MODEM_STAT_REG_DDCD (1<<3) /* change in DCD (w1tc) */
+#define CDNC_UART_MODEM_STAT_REG_TERI (1<<2) /* trail edge ring (w1tc) */
+#define CDNC_UART_MODEM_STAT_REG_DDSR (1<<1) /* change in DSR (w1tc) */
+#define CDNC_UART_MODEM_STAT_REG_DCTS (1<<0) /* change in CTS (w1tc) */
+
+#define CDNC_UART_CHAN_STAT_REG 0x2C /* Channel status register. */
+#define CDNC_UART_CHAN_STAT_REG_TXNRLYFUL (1<<14) /* tx "nearly" full */
+#define CDNC_UART_CHAN_STAT_REG_TXTRIG (1<<13)
+#define CDNC_UART_CHAN_STAT_REG_FDELT (1<<12)
+#define CDNC_UART_CHAN_STAT_REG_TXACTIVE (1<<11)
+#define CDNC_UART_CHAN_STAT_REG_RXACTIVE (1<<10)
+#define CDNC_UART_CHAN_STAT_REG_TXFULL (1<<4)
+#define CDNC_UART_CHAN_STAT_REG_TXEMPTY (1<<3)
+#define CDNC_UART_CHAN_STAT_REG_RXEMPTY (1<<1)
+#define CDNC_UART_CHAN_STAT_REG_RXTRIG (1<<0)
+
+#define CDNC_UART_FIFO 0x30 /* Data FIFO (tx and rx) */
+#define CDNC_UART_BAUDDIV_REG 0x34
+#define CDNC_UART_FLOWDEL_REG 0x38
+#define CDNC_UART_TX_WATER_REG 0x44
+
+
+/*
+ * Low-level UART interface.
+ */
+static int cdnc_uart_probe(struct uart_bas *bas);
+static void cdnc_uart_init(struct uart_bas *bas, int, int, int, int);
+static void cdnc_uart_term(struct uart_bas *bas);
+static void cdnc_uart_putc(struct uart_bas *bas, int);
+static int cdnc_uart_rxready(struct uart_bas *bas);
+static int cdnc_uart_getc(struct uart_bas *bas, struct mtx *mtx);
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+
+static struct uart_ops cdnc_uart_ops = {
+ .probe = cdnc_uart_probe,
+ .init = cdnc_uart_init,
+ .term = cdnc_uart_term,
+ .putc = cdnc_uart_putc,
+ .rxready = cdnc_uart_rxready,
+ .getc = cdnc_uart_getc,
+};
+
+#define SIGCHG(c, i, s, d) \
+ if (c) { \
+ i |= (i & s) ? s : s | d; \
+ } else { \
+ i = (i & s) ? (i & ~s) | d : i; \
+ }
+
+static int
+cdnc_uart_probe(struct uart_bas *bas)
+{
+
+ return (0);
+}
+
+static int
+cdnc_uart_set_baud(struct uart_bas *bas, int baudrate)
+{
+ uint32_t baudgen, bauddiv;
+ uint32_t best_bauddiv, best_baudgen, best_error;
+ uint32_t baud_out, err;
+
+ best_bauddiv = 0;
+ best_baudgen = 0;
+ best_error = ~0;
+
+ /* Try all possible bauddiv values and pick best match. */
+ for (bauddiv = 4; bauddiv <= 255; bauddiv++) {
+ baudgen = (bas->rclk + (baudrate * (bauddiv + 1)) / 2) /
+ (baudrate * (bauddiv + 1));
+ if (baudgen < 1 || baudgen > 0xffff)
+ continue;
+
+ baud_out = bas->rclk / (baudgen * (bauddiv + 1));
+ err = baud_out > baudrate ?
+ baud_out - baudrate : baudrate - baud_out;
+
+ if (err < best_error) {
+ best_error = err;
+ best_bauddiv = bauddiv;
+ best_baudgen = baudgen;
+ }
+ }
+
+ if (best_bauddiv > 0) {
+ WR4(bas, CDNC_UART_BAUDDIV_REG, best_bauddiv);
+ WR4(bas, CDNC_UART_BAUDGEN_REG, best_baudgen);
+ return (0);
+ } else
+ return (-1); /* out of range */
+}
+
+static int
+cdnc_uart_set_params(struct uart_bas *bas, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ uint32_t mode_reg_value = 0;
+
+ switch (databits) {
+ case 6:
+ mode_reg_value |= CDNC_UART_MODE_REG_6BIT;
+ break;
+ case 7:
+ mode_reg_value |= CDNC_UART_MODE_REG_7BIT;
+ break;
+ case 8:
+ default:
+ mode_reg_value |= CDNC_UART_MODE_REG_8BIT;
+ break;
+ }
+
+ if (stopbits == 2)
+ mode_reg_value |= CDNC_UART_MODE_REG_STOP2;
+
+ switch (parity) {
+ case UART_PARITY_MARK:
+ mode_reg_value |= CDNC_UART_MODE_REG_PAR_MARK;
+ break;
+ case UART_PARITY_SPACE:
+ mode_reg_value |= CDNC_UART_MODE_REG_PAR_SPACE;
+ break;
+ case UART_PARITY_ODD:
+ mode_reg_value |= CDNC_UART_MODE_REG_PAR_ODD;
+ break;
+ case UART_PARITY_EVEN:
+ mode_reg_value |= CDNC_UART_MODE_REG_PAR_EVEN;
+ break;
+ case UART_PARITY_NONE:
+ default:
+ mode_reg_value |= CDNC_UART_MODE_REG_PAR_NONE;
+ break;
+ }
+
+ WR4(bas, CDNC_UART_MODE_REG, mode_reg_value);
+
+ if (baudrate > 0 && cdnc_uart_set_baud(bas, baudrate) < 0)
+ return (EINVAL);
+
+ return(0);
+}
+
+static void
+cdnc_uart_hw_init(struct uart_bas *bas)
+{
+
+ /* Reset RX and TX. */
+ WR4(bas, CDNC_UART_CTRL_REG,
+ CDNC_UART_CTRL_REG_RXRST | CDNC_UART_CTRL_REG_TXRST);
+
+ /* Interrupts all off. */
+ WR4(bas, CDNC_UART_IDIS_REG, CDNC_UART_INT_ALL);
+ WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_ALL);
+
+ /* Clear delta bits. */
+ WR4(bas, CDNC_UART_MODEM_STAT_REG,
+ CDNC_UART_MODEM_STAT_REG_DDCD | CDNC_UART_MODEM_STAT_REG_TERI |
+ CDNC_UART_MODEM_STAT_REG_DDSR | CDNC_UART_MODEM_STAT_REG_DCTS);
+
+ /* RX FIFO water level, stale timeout */
+ WR4(bas, CDNC_UART_RX_WATER_REG, UART_FIFO_SIZE/2);
+ WR4(bas, CDNC_UART_RX_TIMEO_REG, 10);
+
+ /* TX FIFO water level (not used.) */
+ WR4(bas, CDNC_UART_TX_WATER_REG, UART_FIFO_SIZE/2);
+
+ /* Bring RX and TX online. */
+ WR4(bas, CDNC_UART_CTRL_REG,
+ CDNC_UART_CTRL_REG_RX_EN | CDNC_UART_CTRL_REG_TX_EN |
+ CDNC_UART_CTRL_REG_TORST | CDNC_UART_CTRL_REG_STOPBRK);
+
+ /* Set DTR and RTS. */
+ WR4(bas, CDNC_UART_MODEM_CTRL_REG, CDNC_UART_MODEM_CTRL_REG_DTR |
+ CDNC_UART_MODEM_CTRL_REG_RTS);
+}
+
+/*
+ * Initialize this device for use as a console.
+ */
+static void
+cdnc_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+
+ /* Initialize hardware. */
+ cdnc_uart_hw_init(bas);
+
+ /* Set baudrate, parameters. */
+ (void)cdnc_uart_set_params(bas, baudrate, databits, stopbits, parity);
+}
+
+/*
+ * Free resources now that we're no longer the console. This appears to
+ * be never called, and I'm unsure quite what to do if I am called.
+ */
+static void
+cdnc_uart_term(struct uart_bas *bas)
+{
+
+ /* XXX */
+}
+
+/*
+ * Put a character of console output (so we do it here polling rather than
+ * interrutp driven).
+ */
+static void
+cdnc_uart_putc(struct uart_bas *bas, int c)
+{
+
+ /* Wait for room. */
+ while ((RD4(bas,CDNC_UART_CHAN_STAT_REG) &
+ CDNC_UART_CHAN_STAT_REG_TXFULL) != 0)
+ ;
+
+ WR4(bas, CDNC_UART_FIFO, c);
+
+ while ((RD4(bas,CDNC_UART_CHAN_STAT_REG) &
+ CDNC_UART_CHAN_STAT_REG_TXEMPTY) == 0)
+ ;
+}
+
+/*
+ * Check for a character available.
+ */
+static int
+cdnc_uart_rxready(struct uart_bas *bas)
+{
+
+ return ((RD4(bas, CDNC_UART_CHAN_STAT_REG) &
+ CDNC_UART_CHAN_STAT_REG_RXEMPTY) == 0);
+}
+
+/*
+ * Block waiting for a character.
+ */
+static int
+cdnc_uart_getc(struct uart_bas *bas, struct mtx *mtx)
+{
+ int c;
+
+ uart_lock(mtx);
+
+ while ((RD4(bas, CDNC_UART_CHAN_STAT_REG) &
+ CDNC_UART_CHAN_STAT_REG_RXEMPTY) != 0) {
+ uart_unlock(mtx);
+ DELAY(4);
+ uart_lock(mtx);
+ }
+
+ c = RD4(bas, CDNC_UART_FIFO);
+
+ uart_unlock(mtx);
+
+ c &= 0xff;
+ return (c);
+}
+
+/*****************************************************************************/
+/*
+ * High-level UART interface.
+ */
+
+static int cdnc_uart_bus_probe(struct uart_softc *sc);
+static int cdnc_uart_bus_attach(struct uart_softc *sc);
+static int cdnc_uart_bus_flush(struct uart_softc *, int);
+static int cdnc_uart_bus_getsig(struct uart_softc *);
+static int cdnc_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int cdnc_uart_bus_ipend(struct uart_softc *);
+static int cdnc_uart_bus_param(struct uart_softc *, int, int, int, int);
+static int cdnc_uart_bus_receive(struct uart_softc *);
+static int cdnc_uart_bus_setsig(struct uart_softc *, int);
+static int cdnc_uart_bus_transmit(struct uart_softc *);
+static void cdnc_uart_bus_grab(struct uart_softc *);
+static void cdnc_uart_bus_ungrab(struct uart_softc *);
+
+static kobj_method_t cdnc_uart_bus_methods[] = {
+ KOBJMETHOD(uart_probe, cdnc_uart_bus_probe),
+ KOBJMETHOD(uart_attach, cdnc_uart_bus_attach),
+ KOBJMETHOD(uart_flush, cdnc_uart_bus_flush),
+ KOBJMETHOD(uart_getsig, cdnc_uart_bus_getsig),
+ KOBJMETHOD(uart_ioctl, cdnc_uart_bus_ioctl),
+ KOBJMETHOD(uart_ipend, cdnc_uart_bus_ipend),
+ KOBJMETHOD(uart_param, cdnc_uart_bus_param),
+ KOBJMETHOD(uart_receive, cdnc_uart_bus_receive),
+ KOBJMETHOD(uart_setsig, cdnc_uart_bus_setsig),
+ KOBJMETHOD(uart_transmit, cdnc_uart_bus_transmit),
+ KOBJMETHOD(uart_grab, cdnc_uart_bus_grab),
+ KOBJMETHOD(uart_ungrab, cdnc_uart_bus_ungrab),
+
+ KOBJMETHOD_END
+};
+
+int
+cdnc_uart_bus_probe(struct uart_softc *sc)
+{
+
+ sc->sc_txfifosz = UART_FIFO_SIZE;
+ sc->sc_rxfifosz = UART_FIFO_SIZE;
+ sc->sc_hwiflow = 0;
+ sc->sc_hwoflow = 0;
+
+ device_set_desc(sc->sc_dev, "Cadence UART");
+
+ return (0);
+}
+
+static int
+cdnc_uart_bus_attach(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+ struct uart_devinfo *di;
+
+ if (sc->sc_sysdev != NULL) {
+ di = sc->sc_sysdev;
+ (void)cdnc_uart_set_params(bas, di->baudrate, di->databits,
+ di->stopbits, di->parity);
+ } else
+ cdnc_uart_hw_init(bas);
+
+ (void)cdnc_uart_bus_getsig(sc);
+
+ /* Enable interrupts. */
+ WR4(bas, CDNC_UART_IEN_REG,
+ CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT |
+ CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR |
+ CDNC_UART_INT_DMSI);
+
+ return (0);
+}
+
+static int
+cdnc_uart_bus_transmit(struct uart_softc *sc)
+{
+ int i;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ uart_lock(sc->sc_hwmtx);
+
+ /* Clear sticky TXEMPTY status bit. */
+ WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_TXEMPTY);
+
+ for (i = 0; i < sc->sc_txdatasz; i++)
+ WR4(bas, CDNC_UART_FIFO, sc->sc_txbuf[i]);
+
+ /* Enable TX empty interrupt. */
+ WR4(bas, CDNC_UART_IEN_REG, CDNC_UART_INT_TXEMPTY);
+ sc->sc_txbusy = 1;
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static int
+cdnc_uart_bus_setsig(struct uart_softc *sc, int sig)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+ uint32_t new, old, modem_ctrl;
+
+ do {
+ old = sc->sc_hwsig;
+ new = old;
+ if (sig & SER_DDTR) {
+ SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR);
+ }
+ if (sig & SER_DRTS) {
+ SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS);
+ }
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ uart_lock(sc->sc_hwmtx);
+ modem_ctrl = RD4(bas, CDNC_UART_MODEM_CTRL_REG) &
+ ~(CDNC_UART_MODEM_CTRL_REG_DTR | CDNC_UART_MODEM_CTRL_REG_RTS);
+ if ((new & SER_DTR) != 0)
+ modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_DTR;
+ if ((new & SER_RTS) != 0)
+ modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_RTS;
+ WR4(bas, CDNC_UART_MODEM_CTRL_REG, modem_ctrl);
+
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+static int
+cdnc_uart_bus_receive(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+ uint32_t status;
+ int c, c_status = 0;
+
+ uart_lock(sc->sc_hwmtx);
+
+ /* Check for parity or framing errors and clear the status bits. */
+ status = RD4(bas, CDNC_UART_ISTAT_REG);
+ if ((status & (CDNC_UART_INT_FRAMING | CDNC_UART_INT_PARITY)) != 0) {
+ WR4(bas, CDNC_UART_ISTAT_REG,
+ status & (CDNC_UART_INT_FRAMING | CDNC_UART_INT_PARITY));
+ if ((status & CDNC_UART_INT_PARITY) != 0)
+ c_status |= UART_STAT_PARERR;
+ if ((status & CDNC_UART_INT_FRAMING) != 0)
+ c_status |= UART_STAT_FRAMERR;
+ }
+
+ while ((RD4(bas, CDNC_UART_CHAN_STAT_REG) &
+ CDNC_UART_CHAN_STAT_REG_RXEMPTY) == 0) {
+ c = RD4(bas, CDNC_UART_FIFO) & 0xff;
+#ifdef KDB
+ /* Detect break and drop into debugger. */
+ if (c == 0 && (c_status & UART_STAT_FRAMERR) != 0 &&
+ sc->sc_sysdev != NULL &&
+ sc->sc_sysdev->type == UART_DEV_CONSOLE) {
+ kdb_break();
+ WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_FRAMING);
+ }
+#endif
+ uart_rx_put(sc, c | c_status);
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static int
+cdnc_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+
+ return (cdnc_uart_set_params(&sc->sc_bas, baudrate,
+ databits, stopbits, parity));
+}
+
+static int
+cdnc_uart_bus_ipend(struct uart_softc *sc)
+{
+ int ipend = 0;
+ struct uart_bas *bas = &sc->sc_bas;
+ uint32_t istatus;
+
+ uart_lock(sc->sc_hwmtx);
+
+ istatus = RD4(bas, CDNC_UART_ISTAT_REG);
+
+ /* Clear interrupt bits. */
+ WR4(bas, CDNC_UART_ISTAT_REG, istatus &
+ (CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT |
+ CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR |
+ CDNC_UART_INT_TXEMPTY | CDNC_UART_INT_DMSI));
+
+ /* Receive data. */
+ if ((istatus & (CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT)) != 0)
+ ipend |= SER_INT_RXREADY;
+
+ /* Transmit fifo empty. */
+ if (sc->sc_txbusy && (istatus & CDNC_UART_INT_TXEMPTY) != 0) {
+ /* disable txempty interrupt. */
+ WR4(bas, CDNC_UART_IDIS_REG, CDNC_UART_INT_TXEMPTY);
+ ipend |= SER_INT_TXIDLE;
+ }
+
+ /* TX Overflow. */
+ if ((istatus & CDNC_UART_INT_TXOVR) != 0)
+ ipend |= SER_INT_OVERRUN;
+
+ /* RX Overflow. */
+ if ((istatus & CDNC_UART_INT_RXOVR) != 0)
+ ipend |= SER_INT_OVERRUN;
+
+ /* Modem signal change. */
+ if ((istatus & CDNC_UART_INT_DMSI) != 0) {
+ WR4(bas, CDNC_UART_MODEM_STAT_REG,
+ CDNC_UART_MODEM_STAT_REG_DDCD |
+ CDNC_UART_MODEM_STAT_REG_TERI |
+ CDNC_UART_MODEM_STAT_REG_DDSR |
+ CDNC_UART_MODEM_STAT_REG_DCTS);
+ ipend |= SER_INT_SIGCHG;
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+ return (ipend);
+}
+
+static int
+cdnc_uart_bus_flush(struct uart_softc *sc, int what)
+{
+
+ return (0);
+}
+
+static int
+cdnc_uart_bus_getsig(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+ uint32_t new, old, sig;
+ uint8_t modem_status;
+
+ do {
+ old = sc->sc_hwsig;
+ sig = old;
+ uart_lock(sc->sc_hwmtx);
+ modem_status = RD4(bas, CDNC_UART_MODEM_STAT_REG);
+ uart_unlock(sc->sc_hwmtx);
+ SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_DSR,
+ sig, SER_DSR, SER_DDSR);
+ SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_CTS,
+ sig, SER_CTS, SER_DCTS);
+ SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_DCD,
+ sig, SER_DCD, SER_DDCD);
+ SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_RI,
+ sig, SER_RI, SER_DRI);
+ new = sig & ~SER_MASK_DELTA;
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ return (sig);
+}
+
+static int
+cdnc_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+ uint32_t uart_ctrl, modem_ctrl;
+ int error = 0;
+
+ uart_lock(sc->sc_hwmtx);
+
+ switch (request) {
+ case UART_IOCTL_BREAK:
+ uart_ctrl = RD4(bas, CDNC_UART_CTRL_REG);
+ if (data) {
+ uart_ctrl |= CDNC_UART_CTRL_REG_STARTBRK;
+ uart_ctrl &= ~CDNC_UART_CTRL_REG_STOPBRK;
+ } else {
+ uart_ctrl |= CDNC_UART_CTRL_REG_STOPBRK;
+ uart_ctrl &= ~CDNC_UART_CTRL_REG_STARTBRK;
+ }
+ WR4(bas, CDNC_UART_CTRL_REG, uart_ctrl);
+ break;
+ case UART_IOCTL_IFLOW:
+ modem_ctrl = RD4(bas, CDNC_UART_MODEM_CTRL_REG);
+ if (data)
+ modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_RTS;
+ else
+ modem_ctrl &= ~CDNC_UART_MODEM_CTRL_REG_RTS;
+ WR4(bas, CDNC_UART_MODEM_CTRL_REG, modem_ctrl);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (error);
+}
+
+static void
+cdnc_uart_bus_grab(struct uart_softc *sc)
+{
+
+ /* Enable interrupts. */
+ WR4(&sc->sc_bas, CDNC_UART_IEN_REG,
+ CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR |
+ CDNC_UART_INT_DMSI);
+}
+
+static void
+cdnc_uart_bus_ungrab(struct uart_softc *sc)
+{
+
+ /* Enable interrupts. */
+ WR4(&sc->sc_bas, CDNC_UART_IEN_REG,
+ CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT |
+ CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR |
+ CDNC_UART_INT_DMSI);
+}
+
+static struct uart_class uart_cdnc_class = {
+ "cdnc_uart",
+ cdnc_uart_bus_methods,
+ sizeof(struct uart_softc),
+ .uc_ops = &cdnc_uart_ops,
+ .uc_range = 8
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"cadence,uart", (uintptr_t)&uart_cdnc_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
Property changes on: trunk/sys/arm/xilinx/uart_dev_cdnc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zedboard/files.zedboard
===================================================================
--- trunk/sys/arm/xilinx/zedboard/files.zedboard (rev 0)
+++ trunk/sys/arm/xilinx/zedboard/files.zedboard 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+#
+# files.zedboard
+#
+# $FreeBSD: stable/10/sys/arm/xilinx/zedboard/files.zedboard 249997 2013-04-27 22:38:29Z wkoszek $
+
+# We'll need board specific files once we start implementing drivers
+# for Zedboard PL peripherals such as HDMI, VGA, or Audio Codecs. For
+# now, nothing is needed.
+#
Property changes on: trunk/sys/arm/xilinx/zedboard/files.zedboard
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zedboard/std.zedboard
===================================================================
--- trunk/sys/arm/xilinx/zedboard/std.zedboard (rev 0)
+++ trunk/sys/arm/xilinx/zedboard/std.zedboard 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,8 @@
+#
+# std.zedboard
+#
+# $FreeBSD: stable/10/sys/arm/xilinx/zedboard/std.zedboard 249997 2013-04-27 22:38:29Z wkoszek $
+
+include "../xilinx/std.zynq7"
+files "../xilinx/zedboard/files.zedboard"
+
Property changes on: trunk/sys/arm/xilinx/zedboard/std.zedboard
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_devcfg.c
===================================================================
--- trunk/sys/arm/xilinx/zy7_devcfg.c (rev 0)
+++ trunk/sys/arm/xilinx/zy7_devcfg.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,669 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xilinx/zy7_devcfg.c 266379 2014-05-17 23:25:20Z ian $
+ */
+
+/*
+ * Zynq-7000 Devcfg driver. This allows programming the PL (FPGA) section
+ * of Zynq.
+ *
+ * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
+ * (v1.4) November 16, 2012. Xilinx doc UG585. PL Configuration is
+ * covered in section 6.4.5.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/zy7_devcfg.c 266379 2014-05-17 23:25:20Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/stdarg.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/xilinx/zy7_slcr.h>
+
+struct zy7_devcfg_softc {
+ device_t dev;
+ struct mtx sc_mtx;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ struct cdev *sc_ctl_dev;
+ void *intrhandle;
+
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+
+ int is_open;
+};
+
+static struct zy7_devcfg_softc *zy7_devcfg_softc_p;
+
+#define DEVCFG_SC_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define DEVCFG_SC_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define DEVCFG_SC_LOCK_INIT(sc) \
+ mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \
+ "zy7_devcfg", MTX_DEF)
+#define DEVCFG_SC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx);
+#define DEVCFG_SC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED);
+
+#define RD4(sc, off) (bus_read_4((sc)->mem_res, (off)))
+#define WR4(sc, off, val) (bus_write_4((sc)->mem_res, (off), (val)))
+
+SYSCTL_NODE(_hw, OID_AUTO, fpga, CTLFLAG_RD, 0, \
+ "Xilinx Zynq-7000 PL (FPGA) section");
+
+static int zy7_devcfg_sysctl_pl_done(SYSCTL_HANDLER_ARGS);
+SYSCTL_PROC(_hw_fpga, OID_AUTO, pl_done, CTLTYPE_INT | CTLFLAG_RD, NULL, 0,
+ zy7_devcfg_sysctl_pl_done, "I", "PL section config DONE signal");
+
+static int zy7_en_level_shifters = 1;
+SYSCTL_INT(_hw_fpga, OID_AUTO, en_level_shifters, CTLFLAG_RW,
+ &zy7_en_level_shifters, 0,
+ "Enable PS-PL level shifters after device config");
+
+static int zy7_ps_vers = 0;
+SYSCTL_INT(_hw, OID_AUTO, ps_vers, CTLFLAG_RD, &zy7_ps_vers, 0,
+ "Zynq-7000 PS version");
+
+
+/* cdev entry points. */
+static int zy7_devcfg_open(struct cdev *, int, int, struct thread *);
+static int zy7_devcfg_write(struct cdev *, struct uio *, int);
+static int zy7_devcfg_close(struct cdev *, int, int, struct thread *);
+
+
+struct cdevsw zy7_devcfg_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = zy7_devcfg_open,
+ .d_write = zy7_devcfg_write,
+ .d_close = zy7_devcfg_close,
+ .d_name = "devcfg",
+};
+
+/* Devcfg block registers. */
+#define ZY7_DEVCFG_CTRL 0x0000
+#define ZY7_DEVCFG_CTRL_FORCE_RST (1<<31)
+#define ZY7_DEVCFG_CTRL_PCFG_PROG_B (1<<30)
+#define ZY7_DEVCFG_CTRL_PCFG_POR_CNT_4K (1<<29)
+#define ZY7_DEVCFG_CTRL_PCAP_PR (1<<27)
+#define ZY7_DEVCFG_CTRL_PCAP_MODE (1<<26)
+#define ZY7_DEVCFG_CTRL_QTR_PCAP_RATE_EN (1<<25)
+#define ZY7_DEVCFG_CTRL_MULTIBOOT_EN (1<<24)
+#define ZY7_DEVCFG_CTRL_JTAG_CHAIN_DIS (1<<23)
+#define ZY7_DEVCFG_CTRL_USER_MODE (1<<15)
+#define ZY7_DEVCFG_CTRL_RESVD_WR11 (3<<13) /* always write 11 */
+#define ZY7_DEVCFG_CTRL_PCFG_AES_FUSE (1<<12)
+#define ZY7_DEVCFG_CTRL_PCFG_AES_EN_MASK (7<<9) /* all 1's or 0's */
+#define ZY7_DEVCFG_CTRL_SEU_EN (1<<8)
+#define ZY7_DEVCFG_CTRL_SEC_EN (1<<7)
+#define ZY7_DEVCFG_CTRL_SPNIDEN (1<<6)
+#define ZY7_DEVCFG_CTRL_SPIDEN (1<<5)
+#define ZY7_DEVCFG_CTRL_NIDEN (1<<4)
+#define ZY7_DEVCFG_CTRL_DBGEN (1<<3)
+#define ZY7_DEVCFG_CTRL_DAP_EN_MASK (7<<0) /* all 1's to enable */
+
+#define ZY7_DEVCFG_LOCK 0x004
+#define ZY7_DEVCFG_LOCK_AES_FUSE_LOCK (1<<4)
+#define ZY7_DEVCFG_LOCK_AES_EN (1<<3)
+#define ZY7_DEVCFG_LOCK_SEU_LOCK (1<<2)
+#define ZY7_DEVCFG_LOCK_SEC_LOCK (1<<1)
+#define ZY7_DEVCFG_LOCK_DBG_LOCK (1<<0)
+
+#define ZY7_DEVCFG_CFG 0x008
+#define ZY7_DEVCFG_CFG_RFIFO_TH_MASK (3<<10)
+#define ZY7_DEVCFG_CFG_WFIFO_TH_MASK (3<<8)
+#define ZY7_DEVCFG_CFG_RCLK_EDGE (1<<7)
+#define ZY7_DEVCFG_CFG_WCLK_EDGE (1<<6)
+#define ZY7_DEVCFG_CFG_DIS_SRC_INC (1<<5)
+#define ZY7_DEVCFG_CFG_DIS_DST_INC (1<<4)
+
+#define ZY7_DEVCFG_INT_STATUS 0x00C
+#define ZY7_DEVCFG_INT_MASK 0x010
+#define ZY7_DEVCFG_INT_PSS_GTS_USR_B (1<<31)
+#define ZY7_DEVCFG_INT_PSS_FST_CFG_B (1<<30)
+#define ZY7_DEVCFG_INT_PSS_GPWRDWN_B (1<<29)
+#define ZY7_DEVCFG_INT_PSS_GTS_CFG_B (1<<28)
+#define ZY7_DEVCFG_INT_CFG_RESET_B (1<<27)
+#define ZY7_DEVCFG_INT_AXI_WTO (1<<23) /* axi write timeout */
+#define ZY7_DEVCFG_INT_AXI_WERR (1<<22) /* axi write err */
+#define ZY7_DEVCFG_INT_AXI_RTO (1<<21) /* axi read timeout */
+#define ZY7_DEVCFG_INT_AXI_RERR (1<<20) /* axi read err */
+#define ZY7_DEVCFG_INT_RX_FIFO_OV (1<<18) /* rx fifo overflow */
+#define ZY7_DEVCFG_INT_WR_FIFO_LVL (1<<17) /* wr fifo < level */
+#define ZY7_DEVCFG_INT_RD_FIFO_LVL (1<<16) /* rd fifo >= level */
+#define ZY7_DEVCFG_INT_DMA_CMD_ERR (1<<15)
+#define ZY7_DEVCFG_INT_DMA_Q_OV (1<<14)
+#define ZY7_DEVCFG_INT_DMA_DONE (1<<13)
+#define ZY7_DEVCFG_INT_DMA_PCAP_DONE (1<<12)
+#define ZY7_DEVCFG_INT_P2D_LEN_ERR (1<<11)
+#define ZY7_DEVCFG_INT_PCFG_HMAC_ERR (1<<6)
+#define ZY7_DEVCFG_INT_PCFG_SEU_ERR (1<<5)
+#define ZY7_DEVCFG_INT_PCFG_POR_B (1<<4)
+#define ZY7_DEVCFG_INT_PCFG_CFG_RST (1<<3)
+#define ZY7_DEVCFG_INT_PCFG_DONE (1<<2)
+#define ZY7_DEVCFG_INT_PCFG_INIT_PE (1<<1)
+#define ZY7_DEVCFG_INT_PCFG_INIT_NE (1<<0)
+#define ZY7_DEVCFG_INT_ERRORS 0x00f0f860
+#define ZY7_DEVCFG_INT_ALL 0xf8f7f87f
+
+#define ZY7_DEVCFG_STATUS 0x014
+#define ZY7_DEVCFG_STATUS_DMA_CMD_Q_F (1<<31) /* cmd queue full */
+#define ZY7_DEVCFG_STATUS_DMA_CMD_Q_E (1<<30) /* cmd queue empty */
+#define ZY7_DEVCFG_STATUS_DONE_COUNT_MASK (3<<28)
+#define ZY7_DEVCFG_STATUS_DONE_COUNT_SHIFT 28
+#define ZY7_DEVCFG_STATUS_RX_FIFO_LVL_MASK (0x1f<<20)
+#define ZY7_DEVCFG_STATUS_RX_FIFO_LVL_SHIFT 20
+#define ZY7_DEVCFG_STATUS_TX_FIFO_LVL_MASK (0x7f<<12)
+#define ZY7_DEVCFG_STATUS_TX_FIFO_LVL_SHIFT 12
+#define ZY7_DEVCFG_STATUS_PSS_GTS_USR_B (1<<11)
+#define ZY7_DEVCFG_STATUS_PSS_FST_CFG_B (1<<10)
+#define ZY7_DEVCFG_STATUS_PSS_GPWRDWN_B (1<<9)
+#define ZY7_DEVCFG_STATUS_PSS_GTS_CFG_B (1<<8)
+#define ZY7_DEVCFG_STATUS_ILL_APB_ACCE (1<<6)
+#define ZY7_DEVCFG_STATUS_PSS_CFG_RESET_B (1<<5)
+#define ZY7_DEVCFG_STATUS_PCFG_INIT (1<<4)
+#define ZY7_DEVCFG_STATUS_EFUSE_BBRAM_KEY_DIS (1<<3)
+#define ZY7_DEVCFG_STATUS_EFUSE_SEC_EN (1<<2)
+#define ZY7_DEVCFG_STATUS_EFUSE_JTAG_DIS (1<<1)
+
+#define ZY7_DEVCFG_DMA_SRC_ADDR 0x018
+#define ZY7_DEVCFG_DMA_DST_ADDR 0x01c
+#define ZY7_DEVCFG_DMA_ADDR_WAIT_PCAP 1
+#define ZY7_DEVCFG_DMA_ADDR_ILLEGAL 0xffffffff
+
+#define ZY7_DEVCFG_DMA_SRC_LEN 0x020 /* in 4-byte words. */
+#define ZY7_DEVCFG_DMA_SRC_LEN_MAX 0x7ffffff
+#define ZY7_DEVCFG_DMA_DST_LEN 0x024
+#define ZY7_DEVCFG_ROM_SHADOW 0x028
+#define ZY7_DEVCFG_MULTIBOOT_ADDR 0x02c
+#define ZY7_DEVCFG_SW_ID 0x030
+#define ZY7_DEVCFG_UNLOCK 0x034
+#define ZY7_DEVCFG_UNLOCK_MAGIC 0x757bdf0d
+#define ZY7_DEVCFG_MCTRL 0x080
+#define ZY7_DEVCFG_MCTRL_PS_VERS_MASK (0xf<<28)
+#define ZY7_DEVCFG_MCTRL_PS_VERS_SHIFT 28
+#define ZY7_DEVCFG_MCTRL_PCFG_POR_B (1<<8)
+#define ZY7_DEVCFG_MCTRL_INT_PCAP_LPBK (1<<4)
+#define ZY7_DEVCFG_XADCIF_CFG 0x100
+#define ZY7_DEVCFG_XADCIF_INT_STAT 0x104
+#define ZY7_DEVCFG_XADCIF_INT_MASK 0x108
+#define ZY7_DEVCFG_XADCIF_MSTS 0x10c
+#define ZY7_DEVCFG_XADCIF_CMD_FIFO 0x110
+#define ZY7_DEVCFG_XADCIF_RD_FIFO 0x114
+#define ZY7_DEVCFG_XADCIF_MCTL 0x118
+
+
+/* Enable programming the PL through PCAP. */
+static void
+zy7_devcfg_init_hw(struct zy7_devcfg_softc *sc)
+{
+
+ DEVCFG_SC_ASSERT_LOCKED(sc);
+
+ /* Set devcfg control register. */
+ WR4(sc, ZY7_DEVCFG_CTRL,
+ ZY7_DEVCFG_CTRL_PCFG_PROG_B |
+ ZY7_DEVCFG_CTRL_PCAP_PR |
+ ZY7_DEVCFG_CTRL_PCAP_MODE |
+ ZY7_DEVCFG_CTRL_USER_MODE |
+ ZY7_DEVCFG_CTRL_RESVD_WR11 |
+ ZY7_DEVCFG_CTRL_SPNIDEN |
+ ZY7_DEVCFG_CTRL_SPIDEN |
+ ZY7_DEVCFG_CTRL_NIDEN |
+ ZY7_DEVCFG_CTRL_DBGEN |
+ ZY7_DEVCFG_CTRL_DAP_EN_MASK);
+
+ /* Turn off internal PCAP loopback. */
+ WR4(sc, ZY7_DEVCFG_MCTRL, RD4(sc, ZY7_DEVCFG_MCTRL) &
+ ~ZY7_DEVCFG_MCTRL_INT_PCAP_LPBK);
+}
+
+/* Clear previous configuration of the PL by asserting PROG_B. */
+static int
+zy7_devcfg_reset_pl(struct zy7_devcfg_softc *sc)
+{
+ uint32_t devcfg_ctl;
+ int tries, err;
+
+ DEVCFG_SC_ASSERT_LOCKED(sc);
+
+ devcfg_ctl = RD4(sc, ZY7_DEVCFG_CTRL);
+
+ /* Clear sticky bits and set up INIT signal positive edge interrupt. */
+ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL);
+ WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_PCFG_INIT_PE);
+
+ /* Deassert PROG_B (active low). */
+ devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B;
+ WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl);
+
+ /*
+ * Wait for INIT to assert. If it is already asserted, we may not get
+ * an edge interrupt so cancel it and continue.
+ */
+ if ((RD4(sc, ZY7_DEVCFG_STATUS) &
+ ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) {
+ /* Already asserted. Cancel interrupt. */
+ WR4(sc, ZY7_DEVCFG_INT_MASK, ~0);
+ }
+ else {
+ /* Wait for positive edge interrupt. */
+ err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i1", hz);
+ if (err != 0)
+ return (err);
+ }
+
+ /* Reassert PROG_B (active low). */
+ devcfg_ctl &= ~ZY7_DEVCFG_CTRL_PCFG_PROG_B;
+ WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl);
+
+ /* Wait for INIT deasserted. This happens almost instantly. */
+ tries = 0;
+ while ((RD4(sc, ZY7_DEVCFG_STATUS) &
+ ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) {
+ if (++tries >= 100)
+ return (EIO);
+ DELAY(5);
+ }
+
+ /* Clear sticky bits and set up INIT positive edge interrupt. */
+ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL);
+ WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_PCFG_INIT_PE);
+
+ /* Deassert PROG_B again. */
+ devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B;
+ WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl);
+
+ /*
+ * Wait for INIT asserted indicating FPGA internal initialization
+ * is complete.
+ */
+ err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i2", hz);
+ if (err != 0)
+ return (err);
+
+ /* Clear sticky DONE bit in interrupt status. */
+ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL);
+
+ return (0);
+}
+
+/* Callback function for bus_dmamap_load(). */
+static void
+zy7_dma_cb2(void *arg, bus_dma_segment_t *seg, int nsegs, int error)
+{
+ if (!error && nsegs == 1)
+ *(bus_addr_t *)arg = seg[0].ds_addr;
+}
+
+
+static int
+zy7_devcfg_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct zy7_devcfg_softc *sc = dev->si_drv1;
+ int err;
+
+ DEVCFG_SC_LOCK(sc);
+ if (sc->is_open) {
+ DEVCFG_SC_UNLOCK(sc);
+ return (EBUSY);
+ }
+
+ sc->dma_map = NULL;
+ err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 4, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ PAGE_SIZE,
+ 1,
+ PAGE_SIZE,
+ 0,
+ busdma_lock_mutex,
+ &sc->sc_mtx,
+ &sc->dma_tag);
+ if (err) {
+ DEVCFG_SC_UNLOCK(sc);
+ return (err);
+ }
+
+ sc->is_open = 1;
+ DEVCFG_SC_UNLOCK(sc);
+ return (0);
+}
+
+static int
+zy7_devcfg_write(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct zy7_devcfg_softc *sc = dev->si_drv1;
+ void *dma_mem;
+ bus_addr_t dma_physaddr;
+ int segsz, err;
+
+ DEVCFG_SC_LOCK(sc);
+
+ /* First write? Reset PL. */
+ if (uio->uio_offset == 0 && uio->uio_resid > 0) {
+ zy7_devcfg_init_hw(sc);
+ zy7_slcr_preload_pl();
+ err = zy7_devcfg_reset_pl(sc);
+ if (err != 0) {
+ DEVCFG_SC_UNLOCK(sc);
+ return (err);
+ }
+ }
+
+ /* Allocate dma memory and load. */
+ err = bus_dmamem_alloc(sc->dma_tag, &dma_mem, BUS_DMA_NOWAIT,
+ &sc->dma_map);
+ if (err != 0) {
+ DEVCFG_SC_UNLOCK(sc);
+ return (err);
+ }
+ err = bus_dmamap_load(sc->dma_tag, sc->dma_map, dma_mem, PAGE_SIZE,
+ zy7_dma_cb2, &dma_physaddr, 0);
+ if (err != 0) {
+ bus_dmamem_free(sc->dma_tag, dma_mem, sc->dma_map);
+ DEVCFG_SC_UNLOCK(sc);
+ return (err);
+ }
+
+ while (uio->uio_resid > 0) {
+ /* If DONE signal has been set, we shouldn't write anymore. */
+ if ((RD4(sc, ZY7_DEVCFG_INT_STATUS) &
+ ZY7_DEVCFG_INT_PCFG_DONE) != 0) {
+ err = EIO;
+ break;
+ }
+
+ /* uiomove the data from user buffer to our dma map. */
+ segsz = MIN(PAGE_SIZE, uio->uio_resid);
+ DEVCFG_SC_UNLOCK(sc);
+ err = uiomove(dma_mem, segsz, uio);
+ DEVCFG_SC_LOCK(sc);
+ if (err != 0)
+ break;
+
+ /* Flush the cache to memory. */
+ bus_dmamap_sync(sc->dma_tag, sc->dma_map,
+ BUS_DMASYNC_PREWRITE);
+
+ /* Program devcfg's DMA engine. The ordering of these
+ * register writes is critical.
+ */
+ if (uio->uio_resid > segsz)
+ WR4(sc, ZY7_DEVCFG_DMA_SRC_ADDR,
+ (uint32_t) dma_physaddr);
+ else
+ WR4(sc, ZY7_DEVCFG_DMA_SRC_ADDR,
+ (uint32_t) dma_physaddr |
+ ZY7_DEVCFG_DMA_ADDR_WAIT_PCAP);
+ WR4(sc, ZY7_DEVCFG_DMA_DST_ADDR, ZY7_DEVCFG_DMA_ADDR_ILLEGAL);
+ WR4(sc, ZY7_DEVCFG_DMA_SRC_LEN, (segsz+3)/4);
+ WR4(sc, ZY7_DEVCFG_DMA_DST_LEN, 0);
+
+ /* Now clear done bit and set up DMA done interrupt. */
+ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL);
+ WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_DMA_DONE);
+
+ /* Wait for DMA done interrupt. */
+ err = mtx_sleep(sc->dma_map, &sc->sc_mtx, PCATCH,
+ "zy7dma", hz);
+ if (err != 0)
+ break;
+
+ bus_dmamap_sync(sc->dma_tag, sc->dma_map,
+ BUS_DMASYNC_POSTWRITE);
+
+ /* Check DONE signal. */
+ if ((RD4(sc, ZY7_DEVCFG_INT_STATUS) &
+ ZY7_DEVCFG_INT_PCFG_DONE) != 0)
+ zy7_slcr_postload_pl(zy7_en_level_shifters);
+ }
+
+ bus_dmamap_unload(sc->dma_tag, sc->dma_map);
+ bus_dmamem_free(sc->dma_tag, dma_mem, sc->dma_map);
+ DEVCFG_SC_UNLOCK(sc);
+ return (err);
+}
+
+static int
+zy7_devcfg_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
+{
+ struct zy7_devcfg_softc *sc = dev->si_drv1;
+
+ DEVCFG_SC_LOCK(sc);
+ sc->is_open = 0;
+ bus_dma_tag_destroy(sc->dma_tag);
+ DEVCFG_SC_UNLOCK(sc);
+
+ return (0);
+}
+
+
+static void
+zy7_devcfg_intr(void *arg)
+{
+ struct zy7_devcfg_softc *sc = (struct zy7_devcfg_softc *)arg;
+ uint32_t istatus, imask;
+
+ DEVCFG_SC_LOCK(sc);
+
+ istatus = RD4(sc, ZY7_DEVCFG_INT_STATUS);
+ imask = ~RD4(sc, ZY7_DEVCFG_INT_MASK);
+
+ /* Turn interrupt off. */
+ WR4(sc, ZY7_DEVCFG_INT_MASK, ~0);
+
+ if ((istatus & imask) == 0) {
+ DEVCFG_SC_UNLOCK(sc);
+ return;
+ }
+
+ /* DMA done? */
+ if ((istatus & ZY7_DEVCFG_INT_DMA_DONE) != 0)
+ wakeup(sc->dma_map);
+
+ /* INIT_B positive edge? */
+ if ((istatus & ZY7_DEVCFG_INT_PCFG_INIT_PE) != 0)
+ wakeup(sc);
+
+ DEVCFG_SC_UNLOCK(sc);
+}
+
+/* zy7_devcfg_sysctl_pl_done() returns status of the PL_DONE signal.
+ */
+static int
+zy7_devcfg_sysctl_pl_done(SYSCTL_HANDLER_ARGS)
+{
+ struct zy7_devcfg_softc *sc = zy7_devcfg_softc_p;
+ int pl_done = 0;
+
+ if (sc) {
+ DEVCFG_SC_LOCK(sc);
+
+ /* PCFG_DONE bit is sticky. Clear it before checking it. */
+ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_PCFG_DONE);
+ pl_done = ((RD4(sc, ZY7_DEVCFG_INT_STATUS) &
+ ZY7_DEVCFG_INT_PCFG_DONE) != 0);
+
+ DEVCFG_SC_UNLOCK(sc);
+ }
+ return (sysctl_handle_int(oidp, &pl_done, 0, req));
+}
+
+static int
+zy7_devcfg_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "xlnx,zy7_devcfg"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Zynq devcfg block");
+ return (0);
+}
+
+static int zy7_devcfg_detach(device_t dev);
+
+static int
+zy7_devcfg_attach(device_t dev)
+{
+ struct zy7_devcfg_softc *sc = device_get_softc(dev);
+ int rid, err;
+
+ /* Allow only one attach. */
+ if (zy7_devcfg_softc_p != NULL)
+ return (ENXIO);
+
+ sc->dev = dev;
+
+ DEVCFG_SC_LOCK_INIT(sc);
+
+ /* Get memory resource. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resources.\n");
+ zy7_devcfg_detach(dev);
+ return (ENOMEM);
+ }
+
+ /* Allocate IRQ. */
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "cannot allocate IRQ\n");
+ zy7_devcfg_detach(dev);
+ return (ENOMEM);
+ }
+
+ /* Activate the interrupt. */
+ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, zy7_devcfg_intr, sc, &sc->intrhandle);
+ if (err) {
+ device_printf(dev, "cannot setup IRQ\n");
+ zy7_devcfg_detach(dev);
+ return (err);
+ }
+
+ /* Create /dev/devcfg */
+ sc->sc_ctl_dev = make_dev(&zy7_devcfg_cdevsw, 0,
+ UID_ROOT, GID_WHEEL, 0600, "devcfg");
+ if (sc->sc_ctl_dev == NULL) {
+ device_printf(dev, "failed to create /dev/devcfg");
+ zy7_devcfg_detach(dev);
+ return (ENXIO);
+ }
+ sc->sc_ctl_dev->si_drv1 = sc;
+
+ zy7_devcfg_softc_p = sc;
+
+ /* Unlock devcfg registers. */
+ WR4(sc, ZY7_DEVCFG_UNLOCK, ZY7_DEVCFG_UNLOCK_MAGIC);
+
+ /* Make sure interrupts are completely disabled. */
+ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL);
+ WR4(sc, ZY7_DEVCFG_INT_MASK, 0xffffffff);
+
+ /* Get PS_VERS for SYSCTL. */
+ zy7_ps_vers = (RD4(sc, ZY7_DEVCFG_MCTRL) &
+ ZY7_DEVCFG_MCTRL_PS_VERS_MASK) >>
+ ZY7_DEVCFG_MCTRL_PS_VERS_SHIFT;
+
+ return (0);
+}
+
+static int
+zy7_devcfg_detach(device_t dev)
+{
+ struct zy7_devcfg_softc *sc = device_get_softc(dev);
+
+ if (device_is_attached(dev))
+ bus_generic_detach(dev);
+
+ /* Get rid of /dev/devcfg0. */
+ if (sc->sc_ctl_dev != NULL)
+ destroy_dev(sc->sc_ctl_dev);
+
+ /* Teardown and release interrupt. */
+ if (sc->irq_res != NULL) {
+ if (sc->intrhandle)
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhandle);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->irq_res), sc->irq_res);
+ }
+
+ /* Release memory resource. */
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+
+ zy7_devcfg_softc_p = NULL;
+
+ DEVCFG_SC_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static device_method_t zy7_devcfg_methods[] = {
+ /* device_if */
+ DEVMETHOD(device_probe, zy7_devcfg_probe),
+ DEVMETHOD(device_attach, zy7_devcfg_attach),
+ DEVMETHOD(device_detach, zy7_devcfg_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t zy7_devcfg_driver = {
+ "zy7_devcfg",
+ zy7_devcfg_methods,
+ sizeof(struct zy7_devcfg_softc),
+};
+static devclass_t zy7_devcfg_devclass;
+
+DRIVER_MODULE(zy7_devcfg, simplebus, zy7_devcfg_driver, zy7_devcfg_devclass, \
+ 0, 0);
+MODULE_DEPEND(zy7_devcfg, zy7_slcr, 1, 1, 1);
Property changes on: trunk/sys/arm/xilinx/zy7_devcfg.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_ehci.c
===================================================================
--- trunk/sys/arm/xilinx/zy7_ehci.c (rev 0)
+++ trunk/sys/arm/xilinx/zy7_ehci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,364 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012-2013 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xilinx/zy7_ehci.c 308402 2016-11-07 09:19:04Z hselasky $
+ */
+
+/*
+ * A host-controller driver for Zynq-7000's USB OTG controller.
+ *
+ * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
+ * (v1.4) November 16, 2012. Xilinx doc UG585. Ch. 15 covers the USB
+ * controller and register definitions are in appendix B.34.
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/zy7_ehci.c 308402 2016-11-07 09:19:04Z hselasky $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/stdarg.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+
+/* Register definitions. */
+#define ZY7_USB_ID 0x0000
+#define ZY7_USB_HWGENERAL 0x0004
+#define ZY7_USB_HWHOST 0x0008
+#define ZY7_USB_HWDEVICE 0x000c
+#define ZY7_USB_HWTXBUF 0x0010
+#define ZY7_USB_HWRXBUF 0x0014
+#define ZY7_USB_GPTIMER0LD 0x0080
+#define ZY7_USB_GPTIMER0CTRL 0x0084
+#define ZY7_USB_GPTIMER1LD 0x0088
+#define ZY7_USB_GPTIMER1CTRL 0x008c
+#define ZY7_USB_SBUSCFG 0x0090
+#define ZY7_USB_CAPLENGTH_HCIVERSION 0x0100
+#define ZY7_USB_HCSPARAMS 0x0104
+#define ZY7_USB_HCCPARAMS 0x0108
+#define ZY7_USB_DCIVERSION 0x0120
+#define ZY7_USB_DCCPARAMS 0x0124
+#define ZY7_USB_USBCMD 0x0140
+#define ZY7_USB_USBSTS 0x0144
+#define ZY7_USB_USBINTR 0x0148
+#define ZY7_USB_FRINDEX 0x014c
+#define ZY7_USB_PERIODICLISTBASE_DEICEADDR 0x0154
+#define ZY7_USB_ASYNCLISTADDR_ENDPOINTLISTADDR 0x0158
+#define ZY7_USB_TTCTRL 0x015c
+#define ZY7_USB_BURSTSIZE 0x0160
+#define ZY7_USB_TXFILLTUNING 0x0164
+#define ZY7_USB_TXFILLTUNING_TXFIFOTHRES_SHFT 16
+#define ZY7_USB_TXFILLTUNING_TXFIFOTHRES_MASK (0x3f<<16)
+#define ZY7_USB_TXTFILLTUNING 0x0168
+#define ZY7_USB_IC_USB 0x016c
+#define ZY7_USB_ULPI_VIEWPORT 0x0170
+#define ZY7_USB_ULPI_VIEWPORT_WU (1<<31)
+#define ZY7_USB_ULPI_VIEWPORT_RUN (1<<30)
+#define ZY7_USB_ULPI_VIEWPORT_RW (1<<29)
+#define ZY7_USB_ULPI_VIEWPORT_SS (1<<27)
+#define ZY7_USB_ULPI_VIEWPORT_PORT_MASK (7<<24)
+#define ZY7_USB_ULPI_VIEWPORT_PORT_SHIFT 24
+#define ZY7_USB_ULPI_VIEWPORT_ADDR_MASK (0xff<<16)
+#define ZY7_USB_ULPI_VIEWPORT_ADDR_SHIFT 16
+#define ZY7_USB_ULPI_VIEWPORT_DATARD_MASK (0xff<<8)
+#define ZY7_USB_ULPI_VIEWPORT_DATARD_SHIFT 8
+#define ZY7_USB_ULPI_VIEWPORT_DATAWR_MASK (0xff<<0)
+#define ZY7_USB_ULPI_VIEWPORT_DATAWR_SHIFT 0
+#define ZY7_USB_ENDPTNAK 0x0178
+#define ZY7_USB_ENDPTNAKEN 0x017c
+#define ZY7_USB_CONFIGFLAG 0x0180
+#define ZY7_USB_PORTSC(n) (0x0180+4*(n))
+#define ZY7_USB_PORTSC_PTS_MASK (3<<30)
+#define ZY7_USB_PORTSC_PTS_SHIFT 30
+#define ZY7_USB_PORTSC_PTS_UTMI (0<<30)
+#define ZY7_USB_PORTSC_PTS_ULPI (2<<30)
+#define ZY7_USB_PORTSC_PTS_SERIAL (3<<30)
+#define ZY7_USB_PORTSC_PTW (1<<28)
+#define ZY7_USB_PORTSC_PTS2 (1<<25)
+#define ZY7_USB_OTGSC 0x01a4
+#define ZY7_USB_USBMODE 0x01a8
+#define ZY7_USB_ENDPTSETUPSTAT 0x01ac
+#define ZY7_USB_ENDPTPRIME 0x01b0
+#define ZY7_USB_ENDPTFLUSH 0x01b4
+#define ZY7_USB_ENDPTSTAT 0x01b8
+#define ZY7_USB_ENDPTCOMPLETE 0x01bc
+#define ZY7_USB_ENDPTCTRL(n) (0x01c0+4*(n))
+
+#define EHCI_REG_OFFSET ZY7_USB_CAPLENGTH_HCIVERSION
+#define EHCI_REG_SIZE 0x100
+
+static int
+zy7_phy_config(device_t dev, bus_space_tag_t io_tag, bus_space_handle_t bsh)
+{
+ phandle_t node;
+ char buf[64];
+ uint32_t portsc;
+ int tries;
+
+ node = ofw_bus_get_node(dev);
+
+ if (OF_getprop(node, "phy_type", buf, sizeof(buf)) > 0) {
+ portsc = bus_space_read_4(io_tag, bsh, ZY7_USB_PORTSC(1));
+ portsc &= ~(ZY7_USB_PORTSC_PTS_MASK | ZY7_USB_PORTSC_PTW |
+ ZY7_USB_PORTSC_PTS2);
+
+ if (strcmp(buf,"ulpi") == 0)
+ portsc |= ZY7_USB_PORTSC_PTS_ULPI;
+ else if (strcmp(buf,"utmi") == 0)
+ portsc |= ZY7_USB_PORTSC_PTS_UTMI;
+ else if (strcmp(buf,"utmi-wide") == 0)
+ portsc |= (ZY7_USB_PORTSC_PTS_UTMI |
+ ZY7_USB_PORTSC_PTW);
+ else if (strcmp(buf, "serial") == 0)
+ portsc |= ZY7_USB_PORTSC_PTS_SERIAL;
+
+ bus_space_write_4(io_tag, bsh, ZY7_USB_PORTSC(1), portsc);
+ }
+
+ if (OF_getprop(node, "phy_vbus_ext", buf, sizeof(buf)) >= 0) {
+
+ /* Tell PHY that VBUS is supplied externally. */
+ bus_space_write_4(io_tag, bsh, ZY7_USB_ULPI_VIEWPORT,
+ ZY7_USB_ULPI_VIEWPORT_RUN |
+ ZY7_USB_ULPI_VIEWPORT_RW |
+ (0 << ZY7_USB_ULPI_VIEWPORT_PORT_SHIFT) |
+ (0x0b << ZY7_USB_ULPI_VIEWPORT_ADDR_SHIFT) |
+ (0x60 << ZY7_USB_ULPI_VIEWPORT_DATAWR_SHIFT)
+ );
+
+ tries = 100;
+ while ((bus_space_read_4(io_tag, bsh, ZY7_USB_ULPI_VIEWPORT) &
+ ZY7_USB_ULPI_VIEWPORT_RUN) != 0) {
+ if (--tries < 0)
+ return (-1);
+ DELAY(1);
+ }
+ }
+
+ return (0);
+}
+
+static int
+zy7_ehci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "xlnx,zy7_ehci"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Zynq-7000 EHCI USB 2.0 controller");
+ return (0);
+}
+
+static int zy7_ehci_detach(device_t dev);
+
+static int
+zy7_ehci_attach(device_t dev)
+{
+ ehci_softc_t *sc = device_get_softc(dev);
+ bus_space_handle_t bsh;
+ int err, rid;
+
+ /* initialize some bus fields */
+ sc->sc_bus.parent = dev;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus,
+ USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc))
+ return (ENOMEM);
+
+ /* Allocate memory. */
+ rid = 0;
+ sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE);
+ if (sc->sc_io_res == NULL) {
+ device_printf(dev, "Can't allocate memory");
+ zy7_ehci_detach(dev);
+ return (ENOMEM);
+ }
+
+ sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+ bsh = rman_get_bushandle(sc->sc_io_res);
+ sc->sc_io_size = EHCI_REG_SIZE;
+
+ if (bus_space_subregion(sc->sc_io_tag, bsh, EHCI_REG_OFFSET,
+ sc->sc_io_size, &sc->sc_io_hdl) != 0)
+ panic("%s: unable to subregion USB host registers",
+ device_get_name(dev));
+
+ /* Allocate IRQ. */
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(dev, "Can't allocate IRQ\n");
+ zy7_ehci_detach(dev);
+ return (ENOMEM);
+ }
+
+ /* Add USB device */
+ sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(dev, "Could not add USB device\n");
+ zy7_ehci_detach(dev);
+ return (ENXIO);
+ }
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+ device_set_desc(sc->sc_bus.bdev, "Zynq-7000 ehci USB 2.0 controller");
+
+ strcpy(sc->sc_vendor, "Xilinx"); /* or IP vendor? */
+
+ /* Activate the interrupt */
+ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)ehci_interrupt, sc,
+ &sc->sc_intr_hdl);
+ if (err) {
+ device_printf(dev, "Cannot setup IRQ\n");
+ zy7_ehci_detach(dev);
+ return (err);
+ }
+
+ /* Customization. */
+ sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_TT |
+ EHCI_SCFLG_NORESTERM;
+
+ /* Modify FIFO burst threshold from 2 to 8. */
+ bus_space_write_4(sc->sc_io_tag, bsh,
+ ZY7_USB_TXFILLTUNING,
+ 8 << ZY7_USB_TXFILLTUNING_TXFIFOTHRES_SHFT);
+
+ /* Handle PHY options. */
+ if (zy7_phy_config(dev, sc->sc_io_tag, bsh) < 0) {
+ device_printf(dev, "Cannot config phy!\n");
+ zy7_ehci_detach(dev);
+ return (EIO);
+ }
+
+ /* Init ehci. */
+ err = ehci_init(sc);
+ if (!err) {
+ sc->sc_flags |= EHCI_SCFLG_DONEINIT;
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ }
+ if (err) {
+ device_printf(dev, "USB init failed err=%d\n", err);
+ zy7_ehci_detach(dev);
+ return (err);
+ }
+
+ return (0);
+}
+
+static int
+zy7_ehci_detach(device_t dev)
+{
+ ehci_softc_t *sc = device_get_softc(dev);
+
+ /* during module unload there are lots of children leftover */
+ device_delete_children(dev);
+
+ sc->sc_flags &= ~EHCI_SCFLG_DONEINIT;
+
+ if (sc->sc_irq_res && sc->sc_intr_hdl)
+ /* call ehci_detach() after ehci_init() called after
+ * successful bus_setup_intr().
+ */
+ ehci_detach(sc);
+
+ if (sc->sc_irq_res) {
+ if (sc->sc_intr_hdl != NULL)
+ bus_teardown_intr(dev, sc->sc_irq_res,
+ sc->sc_intr_hdl);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
+ }
+
+ if (sc->sc_io_res)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->sc_io_res), sc->sc_io_res);
+ usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
+
+ return (0);
+}
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, zy7_ehci_probe),
+ DEVMETHOD(device_attach, zy7_ehci_attach),
+ DEVMETHOD(device_detach, zy7_ehci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+ DEVMETHOD_END
+};
+
+static driver_t ehci_driver = {
+ "ehci",
+ ehci_methods,
+ sizeof(struct ehci_softc),
+};
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, NULL, NULL);
+MODULE_DEPEND(ehci, usb, 1, 1, 1);
Property changes on: trunk/sys/arm/xilinx/zy7_ehci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_gpio.c
===================================================================
--- trunk/sys/arm/xilinx/zy7_gpio.c (rev 0)
+++ trunk/sys/arm/xilinx/zy7_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,389 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xilinx/zy7_gpio.c 278782 2015-02-14 20:37:33Z loos $
+ */
+
+/*
+ * A GPIO driver for Xilinx Zynq-7000.
+ *
+ * The GPIO peripheral on Zynq allows controlling 114 general purpose I/Os.
+ *
+ * Pins 53-0 are sent to the MIO. Any MIO pins not used by a PS peripheral are
+ * available as a GPIO pin. Pins 64-127 are sent to the PL (FPGA) section of
+ * Zynq as EMIO signals.
+ *
+ * The hardware provides a way to use IOs as interrupt sources but the
+ * gpio framework doesn't seem to have hooks for this.
+ *
+ * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
+ * (v1.4) November 16, 2012. Xilinx doc UG585. GPIO is covered in
+ * chater 14. Register definitions are in appendix B.19.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/zy7_gpio.c 278782 2015-02-14 20:37:33Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/stdarg.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "gpio_if.h"
+
+#define NUMBANKS 4
+#define MAXPIN (32*NUMBANKS)
+
+#define MIO_PIN 0 /* pins 0-53 go to MIO */
+#define NUM_MIO_PINS 54
+#define EMIO_PIN 64 /* pins 64-127 go to PL */
+#define NUM_EMIO_PINS 64
+
+#define VALID_PIN(u) (((u) >= MIO_PIN && (u) < MIO_PIN + NUM_MIO_PINS) || \
+ ((u) >= EMIO_PIN && (u) < EMIO_PIN + NUM_EMIO_PINS))
+
+#define ZGPIO_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define ZGPIO_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define ZGPIO_LOCK_INIT(sc) \
+ mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \
+ "gpio", MTX_DEF)
+#define ZGPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+
+struct zy7_gpio_softc {
+ device_t dev;
+ struct mtx sc_mtx;
+ struct resource *mem_res; /* Memory resource */
+};
+
+#define WR4(sc, off, val) bus_write_4((sc)->mem_res, (off), (val))
+#define RD4(sc, off) bus_read_4((sc)->mem_res, (off))
+
+
+/* Xilinx Zynq-7000 GPIO register definitions:
+ */
+#define ZY7_GPIO_MASK_DATA_LSW(b) (0x0000+8*(b)) /* maskable wr lo */
+#define ZY7_GPIO_MASK_DATA_MSW(b) (0x0004+8*(b)) /* maskable wr hi */
+#define ZY7_GPIO_DATA(b) (0x0040+4*(b)) /* in/out data */
+#define ZY7_GPIO_DATA_RO(b) (0x0060+4*(b)) /* input data */
+
+#define ZY7_GPIO_DIRM(b) (0x0204+0x40*(b)) /* direction mode */
+#define ZY7_GPIO_OEN(b) (0x0208+0x40*(b)) /* output enable */
+#define ZY7_GPIO_INT_MASK(b) (0x020c+0x40*(b)) /* int mask */
+#define ZY7_GPIO_INT_EN(b) (0x0210+0x40*(b)) /* int enable */
+#define ZY7_GPIO_INT_DIS(b) (0x0214+0x40*(b)) /* int disable */
+#define ZY7_GPIO_INT_STAT(b) (0x0218+0x40*(b)) /* int status */
+#define ZY7_GPIO_INT_TYPE(b) (0x021c+0x40*(b)) /* int type */
+#define ZY7_GPIO_INT_POLARITY(b) (0x0220+0x40*(b)) /* int polarity */
+#define ZY7_GPIO_INT_ANY(b) (0x0224+0x40*(b)) /* any edge */
+
+
+static int
+zy7_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = MAXPIN;
+ return (0);
+}
+
+/* Get a specific pin's capabilities. */
+static int
+zy7_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+
+ if (!VALID_PIN(pin))
+ return (EINVAL);
+
+ *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
+
+ return (0);
+}
+
+/* Get a specific pin's name. */
+static int
+zy7_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+
+ if (!VALID_PIN(pin))
+ return (EINVAL);
+
+ if (pin < NUM_MIO_PINS) {
+ snprintf(name, GPIOMAXNAME, "MIO_%d", pin);
+ name[GPIOMAXNAME - 1] = '\0';
+ } else {
+ snprintf(name, GPIOMAXNAME, "EMIO_%d", pin - EMIO_PIN);
+ name[GPIOMAXNAME - 1] = '\0';
+ }
+
+ return (0);
+}
+
+/* Get a specific pin's current in/out/tri state. */
+static int
+zy7_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct zy7_gpio_softc *sc = device_get_softc(dev);
+
+ if (!VALID_PIN(pin))
+ return (EINVAL);
+
+ ZGPIO_LOCK(sc);
+
+ if ((RD4(sc, ZY7_GPIO_DIRM(pin >> 5)) & (1 << (pin & 31))) != 0) {
+ /* output */
+ if ((RD4(sc, ZY7_GPIO_OEN(pin >> 5)) & (1 << (pin & 31))) == 0)
+ *flags = (GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
+ else
+ *flags = GPIO_PIN_OUTPUT;
+ } else
+ /* input */
+ *flags = GPIO_PIN_INPUT;
+
+ ZGPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/* Set a specific pin's in/out/tri state. */
+static int
+zy7_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct zy7_gpio_softc *sc = device_get_softc(dev);
+
+ if (!VALID_PIN(pin))
+ return (EINVAL);
+
+ ZGPIO_LOCK(sc);
+
+ if ((flags & GPIO_PIN_OUTPUT) != 0) {
+ /* Output. Set or reset OEN too. */
+ WR4(sc, ZY7_GPIO_DIRM(pin >> 5),
+ RD4(sc, ZY7_GPIO_DIRM(pin >> 5)) | (1 << (pin & 31)));
+
+ if ((flags & GPIO_PIN_TRISTATE) != 0)
+ WR4(sc, ZY7_GPIO_OEN(pin >> 5),
+ RD4(sc, ZY7_GPIO_OEN(pin >> 5)) &
+ ~(1 << (pin & 31)));
+ else
+ WR4(sc, ZY7_GPIO_OEN(pin >> 5),
+ RD4(sc, ZY7_GPIO_OEN(pin >> 5)) |
+ (1 << (pin & 31)));
+ } else {
+ /* Input. Turn off OEN. */
+ WR4(sc, ZY7_GPIO_DIRM(pin >> 5),
+ RD4(sc, ZY7_GPIO_DIRM(pin >> 5)) & ~(1 << (pin & 31)));
+ WR4(sc, ZY7_GPIO_OEN(pin >> 5),
+ RD4(sc, ZY7_GPIO_OEN(pin >> 5)) & ~(1 << (pin & 31)));
+ }
+
+ ZGPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+/* Set a specific output pin's value. */
+static int
+zy7_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct zy7_gpio_softc *sc = device_get_softc(dev);
+
+ if (!VALID_PIN(pin) || value > 1)
+ return (EINVAL);
+
+ /* Fancy register tricks allow atomic set or reset. */
+ if ((pin & 16) != 0)
+ WR4(sc, ZY7_GPIO_MASK_DATA_MSW(pin >> 5),
+ (0xffff0000 ^ (0x10000 << (pin & 15))) |
+ (value << (pin & 15)));
+ else
+ WR4(sc, ZY7_GPIO_MASK_DATA_LSW(pin >> 5),
+ (0xffff0000 ^ (0x10000 << (pin & 15))) |
+ (value << (pin & 15)));
+
+ return (0);
+}
+
+/* Get a specific pin's input value. */
+static int
+zy7_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
+{
+ struct zy7_gpio_softc *sc = device_get_softc(dev);
+
+ if (!VALID_PIN(pin))
+ return (EINVAL);
+
+ *value = (RD4(sc, ZY7_GPIO_DATA_RO(pin >> 5)) >> (pin & 31)) & 1;
+
+ return (0);
+}
+
+/* Toggle a pin's output value. */
+static int
+zy7_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct zy7_gpio_softc *sc = device_get_softc(dev);
+
+ if (!VALID_PIN(pin))
+ return (EINVAL);
+
+ ZGPIO_LOCK(sc);
+
+ WR4(sc, ZY7_GPIO_DATA(pin >> 5),
+ RD4(sc, ZY7_GPIO_DATA(pin >> 5)) ^ (1 << (pin & 31)));
+
+ ZGPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+zy7_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "xlnx,zy7_gpio"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Zynq-7000 GPIO driver");
+ return (0);
+}
+
+static void
+zy7_gpio_hw_reset(struct zy7_gpio_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < NUMBANKS; i++) {
+ WR4(sc, ZY7_GPIO_DATA(i), 0);
+ WR4(sc, ZY7_GPIO_DIRM(i), 0);
+ WR4(sc, ZY7_GPIO_OEN(i), 0);
+ WR4(sc, ZY7_GPIO_INT_DIS(i), 0xffffffff);
+ WR4(sc, ZY7_GPIO_INT_POLARITY(i), 0);
+ WR4(sc, ZY7_GPIO_INT_TYPE(i),
+ i == 1 ? 0x003fffff : 0xffffffff);
+ WR4(sc, ZY7_GPIO_INT_ANY(i), 0);
+ WR4(sc, ZY7_GPIO_INT_STAT(i), 0xffffffff);
+ }
+}
+
+static int zy7_gpio_detach(device_t dev);
+
+static int
+zy7_gpio_attach(device_t dev)
+{
+ struct zy7_gpio_softc *sc = device_get_softc(dev);
+ int rid;
+
+ sc->dev = dev;
+
+ ZGPIO_LOCK_INIT(sc);
+
+ /* Allocate memory. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev,
+ SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Can't allocate memory for device");
+ zy7_gpio_detach(dev);
+ return (ENOMEM);
+ }
+
+ /* Completely reset. */
+ zy7_gpio_hw_reset(sc);
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+zy7_gpio_detach(device_t dev)
+{
+ struct zy7_gpio_softc *sc = device_get_softc(dev);
+
+ bus_generic_detach(dev);
+
+ if (sc->mem_res != NULL) {
+ /* Release memory resource. */
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+ }
+
+ ZGPIO_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static device_method_t zy7_gpio_methods[] = {
+ /* device_if */
+ DEVMETHOD(device_probe, zy7_gpio_probe),
+ DEVMETHOD(device_attach, zy7_gpio_attach),
+ DEVMETHOD(device_detach, zy7_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, zy7_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, zy7_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, zy7_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, zy7_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, zy7_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, zy7_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, zy7_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, zy7_gpio_pin_toggle),
+
+ DEVMETHOD_END
+};
+
+static driver_t zy7_gpio_driver = {
+ "zy7_gpio",
+ zy7_gpio_methods,
+ sizeof(struct zy7_gpio_softc),
+};
+static devclass_t zy7_gpio_devclass;
+
+extern devclass_t gpiobus_devclass, gpioc_devclass;
+extern driver_t gpiobus_driver, gpioc_driver;
+
+DRIVER_MODULE(zy7_gpio, simplebus, zy7_gpio_driver, zy7_gpio_devclass, \
+ NULL, NULL);
+DRIVER_MODULE(gpiobus, zy7_gpio, gpiobus_driver, gpiobus_devclass, 0, 0);
+DRIVER_MODULE(gpioc, zy7_gpio, gpioc_driver, gpioc_devclass, 0, 0);
Property changes on: trunk/sys/arm/xilinx/zy7_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_l2cache.c
===================================================================
--- trunk/sys/arm/xilinx/zy7_l2cache.c (rev 0)
+++ trunk/sys/arm/xilinx/zy7_l2cache.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,61 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xilinx/zy7_l2cache.c 250015 2013-04-28 07:00:36Z wkoszek $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/zy7_l2cache.c 250015 2013-04-28 07:00:36Z wkoszek $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/pl310.h>
+
+void
+platform_pl310_init(struct pl310_softc *softc)
+{
+}
+
+void
+platform_pl310_write_ctrl(struct pl310_softc *sc, uint32_t val)
+{
+
+ pl310_write4(sc, PL310_CTRL, val);
+}
+
+void
+platform_pl310_write_debug(struct pl310_softc *sc, uint32_t val)
+{
+
+ pl310_write4(sc, PL310_DEBUG_CTRL, val);
+}
Property changes on: trunk/sys/arm/xilinx/zy7_l2cache.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_machdep.c
===================================================================
--- trunk/sys/arm/xilinx/zy7_machdep.c (rev 0)
+++ trunk/sys/arm/xilinx/zy7_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,147 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xilinx/zy7_machdep.c 266379 2014-05-17 23:25:20Z ian $
+ */
+
+/*
+ * Machine dependent code for Xilinx Zynq-7000 Soc.
+ *
+ * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
+ * (v1.4) November 16, 2012. Xilinx doc UG585.
+ */
+
+#include "opt_global.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/zy7_machdep.c 266379 2014-05-17 23:25:20Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/machdep.h>
+
+#include <arm/xilinx/zy7_reg.h>
+
+void (*zynq7_cpu_reset)(void);
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+void
+initarm_early_init(void)
+{
+
+}
+
+void
+initarm_gpio_init(void)
+{
+}
+
+void
+initarm_late_init(void)
+{
+}
+
+/*
+ * Set up static device mappings. Not strictly necessary -- simplebus will
+ * dynamically establish mappings as needed -- but doing it this way gets us
+ * nice efficient 1MB section mappings.
+ */
+int
+initarm_devmap_init(void)
+{
+
+ arm_devmap_add_entry(ZYNQ7_PSIO_HWBASE, ZYNQ7_PSIO_SIZE);
+ arm_devmap_add_entry(ZYNQ7_PSCTL_HWBASE, ZYNQ7_PSCTL_SIZE);
+
+ return (0);
+}
+
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_gic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+
+ if (!fdt_is_compatible(node, "arm,gic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_gic_decode_ic,
+ NULL
+};
+
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+void
+cpu_reset()
+{
+ if (zynq7_cpu_reset != NULL)
+ (*zynq7_cpu_reset)();
+
+ printf("cpu_reset: no platform cpu_reset. hanging.\n");
+ for (;;)
+ ;
+}
Property changes on: trunk/sys/arm/xilinx/zy7_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_mp.c
===================================================================
--- trunk/sys/arm/xilinx/zy7_mp.c (rev 0)
+++ trunk/sys/arm/xilinx/zy7_mp.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,117 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Thomas Skibo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/zy7_mp.c 278701 2015-02-13 20:21:13Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <arm/xilinx/zy7_reg.h>
+
+#define ZYNQ7_CPU1_ENTRY 0xfffffff0
+
+#define SCU_CONTROL_REG 0xf8f00000
+#define SCU_CONTROL_ENABLE (1 << 0)
+
+void
+platform_mp_init_secondary(void)
+{
+
+ gic_init_secondary();
+}
+
+void
+platform_mp_setmaxid(void)
+{
+
+ mp_maxid = 1;
+}
+
+int
+platform_mp_probe(void)
+{
+
+ mp_ncpus = 2;
+ return (1);
+}
+
+void
+platform_mp_start_ap(void)
+{
+ bus_space_handle_t scu_handle;
+ bus_space_handle_t ocm_handle;
+ uint32_t scu_ctrl;
+
+ /* Map in SCU control register. */
+ if (bus_space_map(fdtbus_bs_tag, SCU_CONTROL_REG, 4,
+ 0, &scu_handle) != 0)
+ panic("platform_mp_start_ap: Couldn't map SCU config reg\n");
+
+ /* Set SCU enable bit. */
+ scu_ctrl = bus_space_read_4(fdtbus_bs_tag, scu_handle, 0);
+ scu_ctrl |= SCU_CONTROL_ENABLE;
+ bus_space_write_4(fdtbus_bs_tag, scu_handle, 0, scu_ctrl);
+
+ bus_space_unmap(fdtbus_bs_tag, scu_handle, 4);
+
+ /* Map in magic location to give entry address to CPU1. */
+ if (bus_space_map(fdtbus_bs_tag, ZYNQ7_CPU1_ENTRY, 4,
+ 0, &ocm_handle) != 0)
+ panic("platform_mp_start_ap: Couldn't map OCM\n");
+
+ /* Write start address for CPU1. */
+ bus_space_write_4(fdtbus_bs_tag, ocm_handle, 0,
+ pmap_kextract((vm_offset_t)mpentry));
+
+ bus_space_unmap(fdtbus_bs_tag, ocm_handle, 4);
+
+ /*
+ * The SCU is enabled above but I think the second CPU doesn't
+ * turn on filtering until after the wake-up below. I think that's why
+ * things don't work if I don't put these cache ops here. Also, the
+ * magic location, 0xfffffff0, isn't in the SCU's filtering range so it
+ * needs a write-back too.
+ */
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+
+ /* Wake up CPU1. */
+ armv7_sev();
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+
+ pic_ipi_send(cpus, ipi);
+}
Property changes on: trunk/sys/arm/xilinx/zy7_mp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_reg.h
===================================================================
--- trunk/sys/arm/xilinx/zy7_reg.h (rev 0)
+++ trunk/sys/arm/xilinx/zy7_reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,73 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012-2013 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xilinx/zy7_reg.h 266379 2014-05-17 23:25:20Z ian $
+ */
+
+/*
+ * Address regions of Zynq-7000.
+ * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
+ * (v1.4) November 16, 2012. Xilinx doc UG585.
+ */
+
+#ifndef _ZY7_REG_H_
+#define _ZY7_REG_H_
+
+/* PL AXI buses: General Purpose Port #0, M_AXI_GP0. */
+#define ZYNQ7_PLGP0_HWBASE 0x40000000
+#define ZYNQ7_PLGP0_SIZE 0x40000000
+
+/* PL AXI buses: General Purpose Port #1, M_AXI_GP1. */
+#define ZYNQ7_PLGP1_HWBASE 0x80000000
+#define ZYNQ7_PLGP1_SIZE 0x40000000
+
+/* I/O Peripheral registers. */
+#define ZYNQ7_PSIO_HWBASE 0xE0000000
+#define ZYNQ7_PSIO_SIZE 0x00300000
+
+/* UART0 and UART1 */
+#define ZYNQ7_UART0_HWBASE (ZYNQ7_PSIO_HWBASE)
+#define ZYNQ7_UART0_SIZE 0x1000
+
+#define ZYNQ7_UART1_HWBASE (ZYNQ7_PSIO_HWBASE+0x1000)
+#define ZYNQ7_UART1_SIZE 0x1000
+
+
+/* SMC Memories not mapped for now. */
+#define ZYNQ7_SMC_HWBASE 0xE1000000
+#define ZYNQ7_SMC_SIZE 0x05000000
+
+/* SLCR, PS system, and CPU private registers combined in this region. */
+#define ZYNQ7_PSCTL_HWBASE 0xF8000000
+#define ZYNQ7_PSCTL_SIZE 0x01000000
+
+#define ZYNQ7_SLCR_HWBASE (ZYNQ7_PSCTL_HWBASE)
+#define ZYNQ7_SLCR_SIZE 0x1000
+
+#define ZYNQ7_DEVCFG_HWBASE (ZYNQ7_PSCTL_HWBASE+0x7000)
+#define ZYNQ7_DEVCFG_SIZE 0x1000
+
+#endif /* _ZY7_REG_H_ */
Property changes on: trunk/sys/arm/xilinx/zy7_reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_slcr.c
===================================================================
--- trunk/sys/arm/xilinx/zy7_slcr.c (rev 0)
+++ trunk/sys/arm/xilinx/zy7_slcr.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,425 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xilinx/zy7_slcr.c 273645 2014-10-25 20:34:10Z ian $
+ */
+
+/*
+ * Zynq-700 SLCR driver. Provides hooks for cpu_reset and PL control stuff.
+ * In the future, maybe MIO control, clock control, etc. could go here.
+ *
+ * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
+ * (v1.4) November 16, 2012. Xilinx doc UG585.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/zy7_slcr.c 273645 2014-10-25 20:34:10Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/stdarg.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/xilinx/zy7_slcr.h>
+
+struct zy7_slcr_softc {
+ device_t dev;
+ struct mtx sc_mtx;
+ struct resource *mem_res;
+};
+
+static struct zy7_slcr_softc *zy7_slcr_softc_p;
+extern void (*zynq7_cpu_reset);
+
+#define ZSLCR_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define ZSLCR_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define ZSLCR_LOCK_INIT(sc) \
+ mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \
+ "zy7_slcr", MTX_DEF)
+#define ZSLCR_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+
+#define RD4(sc, off) (bus_read_4((sc)->mem_res, (off)))
+#define WR4(sc, off, val) (bus_write_4((sc)->mem_res, (off), (val)))
+
+#define ZYNQ_DEFAULT_PS_CLK_FREQUENCY 33333333 /* 33.3 Mhz */
+
+
+SYSCTL_NODE(_hw, OID_AUTO, zynq, CTLFLAG_RD, 0, "Xilinx Zynq-7000");
+
+static char zynq_bootmode[64];
+SYSCTL_STRING(_hw_zynq, OID_AUTO, bootmode, CTLFLAG_RD, zynq_bootmode, 0,
+ "Zynq boot mode");
+
+static char zynq_pssid[100];
+SYSCTL_STRING(_hw_zynq, OID_AUTO, pssid, CTLFLAG_RD, zynq_pssid, 0,
+ "Zynq PSS IDCODE");
+
+static uint32_t zynq_reboot_status;
+SYSCTL_INT(_hw_zynq, OID_AUTO, reboot_status, CTLFLAG_RD, &zynq_reboot_status,
+ 0, "Zynq REBOOT_STATUS register");
+
+static int ps_clk_frequency;
+SYSCTL_INT(_hw_zynq, OID_AUTO, ps_clk_frequency, CTLFLAG_RD, &ps_clk_frequency,
+ 0, "Zynq PS_CLK Frequency");
+
+static int io_pll_frequency;
+SYSCTL_INT(_hw_zynq, OID_AUTO, io_pll_frequency, CTLFLAG_RD, &io_pll_frequency,
+ 0, "Zynq IO PLL Frequency");
+
+static int arm_pll_frequency;
+SYSCTL_INT(_hw_zynq, OID_AUTO, arm_pll_frequency, CTLFLAG_RD,
+ &arm_pll_frequency, 0, "Zynq ARM PLL Frequency");
+
+static int ddr_pll_frequency;
+SYSCTL_INT(_hw_zynq, OID_AUTO, ddr_pll_frequency, CTLFLAG_RD,
+ &ddr_pll_frequency, 0, "Zynq DDR PLL Frequency");
+
+static void
+zy7_slcr_unlock(struct zy7_slcr_softc *sc)
+{
+
+ /* Unlock SLCR with magic number. */
+ WR4(sc, ZY7_SLCR_UNLOCK, ZY7_SLCR_UNLOCK_MAGIC);
+}
+
+static void
+zy7_slcr_lock(struct zy7_slcr_softc *sc)
+{
+
+ /* Lock SLCR with magic number. */
+ WR4(sc, ZY7_SLCR_LOCK, ZY7_SLCR_LOCK_MAGIC);
+}
+
+
+static void
+zy7_slcr_cpu_reset(void)
+{
+ struct zy7_slcr_softc *sc = zy7_slcr_softc_p;
+
+ /* Unlock SLCR registers. */
+ zy7_slcr_unlock(sc);
+
+ /* This has something to do with a work-around so the fsbl will load
+ * the bitstream after soft-reboot. It's very important.
+ */
+ WR4(sc, ZY7_SLCR_REBOOT_STAT,
+ RD4(sc, ZY7_SLCR_REBOOT_STAT) & 0xf0ffffff);
+
+ /* Soft reset */
+ WR4(sc, ZY7_SLCR_PSS_RST_CTRL, ZY7_SLCR_PSS_RST_CTRL_SOFT_RESET);
+
+ for (;;)
+ ;
+}
+
+/* Assert PL resets and disable level shifters in preparation of programming
+ * the PL (FPGA) section. Called from zy7_devcfg.c.
+ */
+void
+zy7_slcr_preload_pl(void)
+{
+ struct zy7_slcr_softc *sc = zy7_slcr_softc_p;
+
+ if (!sc)
+ return;
+
+ ZSLCR_LOCK(sc);
+
+ /* Unlock SLCR registers. */
+ zy7_slcr_unlock(sc);
+
+ /* Assert top level output resets. */
+ WR4(sc, ZY7_SLCR_FPGA_RST_CTRL, ZY7_SLCR_FPGA_RST_CTRL_RST_ALL);
+
+ /* Disable all level shifters. */
+ WR4(sc, ZY7_SLCR_LVL_SHFTR_EN, 0);
+
+ /* Lock SLCR registers. */
+ zy7_slcr_lock(sc);
+
+ ZSLCR_UNLOCK(sc);
+}
+
+/* After PL configuration, enable level shifters and deassert top-level
+ * PL resets. Called from zy7_devcfg.c. Optionally, the level shifters
+ * can be left disabled but that's rare of an FPGA application. That option
+ * is controled by a sysctl in the devcfg driver.
+ */
+void
+zy7_slcr_postload_pl(int en_level_shifters)
+{
+ struct zy7_slcr_softc *sc = zy7_slcr_softc_p;
+
+ if (!sc)
+ return;
+
+ ZSLCR_LOCK(sc);
+
+ /* Unlock SLCR registers. */
+ zy7_slcr_unlock(sc);
+
+ if (en_level_shifters)
+ /* Enable level shifters. */
+ WR4(sc, ZY7_SLCR_LVL_SHFTR_EN, ZY7_SLCR_LVL_SHFTR_EN_ALL);
+
+ /* Deassert top level output resets. */
+ WR4(sc, ZY7_SLCR_FPGA_RST_CTRL, 0);
+
+ /* Lock SLCR registers. */
+ zy7_slcr_lock(sc);
+
+ ZSLCR_UNLOCK(sc);
+}
+
+/* Override cgem_set_refclk() in gigabit ethernet driver
+ * (sys/dev/cadence/if_cgem.c). This function is called to
+ * request a change in the gem's reference clock speed.
+ */
+int
+cgem_set_ref_clk(int unit, int frequency)
+{
+ struct zy7_slcr_softc *sc = zy7_slcr_softc_p;
+ int div0, div1;
+
+ if (!sc)
+ return (-1);
+
+ /* Find suitable divisor pairs. Round result to nearest khz
+ * to test for match.
+ */
+ for (div1 = 1; div1 <= ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MAX; div1++) {
+ div0 = (io_pll_frequency + div1 * frequency / 2) /
+ div1 / frequency;
+ if (div0 > 0 && div0 <= ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_MAX &&
+ ((io_pll_frequency / div0 / div1) + 500) / 1000 ==
+ (frequency + 500) / 1000)
+ break;
+ }
+
+ if (div1 > ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MAX)
+ return (-1);
+
+ ZSLCR_LOCK(sc);
+
+ /* Unlock SLCR registers. */
+ zy7_slcr_unlock(sc);
+
+ /* Modify GEM reference clock. */
+ WR4(sc, unit ? ZY7_SLCR_GEM1_CLK_CTRL : ZY7_SLCR_GEM0_CLK_CTRL,
+ (div1 << ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_SHIFT) |
+ (div0 << ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_SHIFT) |
+ ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_IO_PLL |
+ ZY7_SLCR_GEM_CLK_CTRL_CLKACT);
+
+ /* Lock SLCR registers. */
+ zy7_slcr_lock(sc);
+
+ ZSLCR_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+zy7_slcr_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "xlnx,zy7_slcr"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Zynq-7000 slcr block");
+ return (0);
+}
+
+static int
+zy7_slcr_attach(device_t dev)
+{
+ struct zy7_slcr_softc *sc = device_get_softc(dev);
+ int rid;
+ phandle_t node;
+ pcell_t cell;
+ uint32_t bootmode;
+ uint32_t pss_idcode;
+ uint32_t arm_pll_ctrl;
+ uint32_t ddr_pll_ctrl;
+ uint32_t io_pll_ctrl;
+ static char *bootdev_names[] = {
+ "JTAG", "Quad-SPI", "NOR", "(3?)",
+ "NAND", "SD Card", "(6?)", "(7?)"
+ };
+
+ /* Allow only one attach. */
+ if (zy7_slcr_softc_p != NULL)
+ return (ENXIO);
+
+ sc->dev = dev;
+
+ ZSLCR_LOCK_INIT(sc);
+
+ /* Get memory resource. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resources.\n");
+ return (ENOMEM);
+ }
+
+ /* Hook up cpu_reset. */
+ zy7_slcr_softc_p = sc;
+ zynq7_cpu_reset = zy7_slcr_cpu_reset;
+
+ /* Read info and set sysctls. */
+ bootmode = RD4(sc, ZY7_SLCR_BOOT_MODE);
+ snprintf(zynq_bootmode, sizeof(zynq_bootmode),
+ "0x%x: boot device: %s", bootmode,
+ bootdev_names[bootmode & ZY7_SLCR_BOOT_MODE_BOOTDEV_MASK]);
+
+ pss_idcode = RD4(sc, ZY7_SLCR_PSS_IDCODE);
+ snprintf(zynq_pssid, sizeof(zynq_pssid),
+ "0x%x: manufacturer: 0x%x device: 0x%x "
+ "family: 0x%x sub-family: 0x%x rev: 0x%x",
+ pss_idcode,
+ (pss_idcode & ZY7_SLCR_PSS_IDCODE_MNFR_ID_MASK) >>
+ ZY7_SLCR_PSS_IDCODE_MNFR_ID_SHIFT,
+ (pss_idcode & ZY7_SLCR_PSS_IDCODE_DEVICE_MASK) >>
+ ZY7_SLCR_PSS_IDCODE_DEVICE_SHIFT,
+ (pss_idcode & ZY7_SLCR_PSS_IDCODE_FAMILY_MASK) >>
+ ZY7_SLCR_PSS_IDCODE_FAMILY_SHIFT,
+ (pss_idcode & ZY7_SLCR_PSS_IDCODE_SUB_FAMILY_MASK) >>
+ ZY7_SLCR_PSS_IDCODE_SUB_FAMILY_SHIFT,
+ (pss_idcode & ZY7_SLCR_PSS_IDCODE_REVISION_MASK) >>
+ ZY7_SLCR_PSS_IDCODE_REVISION_SHIFT);
+
+ zynq_reboot_status = RD4(sc, ZY7_SLCR_REBOOT_STAT);
+
+ /* Derive PLL frequencies from PS_CLK. */
+ node = ofw_bus_get_node(dev);
+ if (OF_getprop(node, "clock-frequency", &cell, sizeof(cell)) > 0)
+ ps_clk_frequency = fdt32_to_cpu(cell);
+ else
+ ps_clk_frequency = ZYNQ_DEFAULT_PS_CLK_FREQUENCY;
+
+ arm_pll_ctrl = RD4(sc, ZY7_SLCR_ARM_PLL_CTRL);
+ ddr_pll_ctrl = RD4(sc, ZY7_SLCR_DDR_PLL_CTRL);
+ io_pll_ctrl = RD4(sc, ZY7_SLCR_IO_PLL_CTRL);
+
+ /* Determine ARM PLL frequency. */
+ if (((arm_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_QUAL) == 0 &&
+ (arm_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_FORCE) != 0) ||
+ ((arm_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_QUAL) != 0 &&
+ (bootmode & ZY7_SLCR_BOOT_MODE_PLL_BYPASS) != 0))
+ /* PLL is bypassed. */
+ arm_pll_frequency = ps_clk_frequency;
+ else
+ arm_pll_frequency = ps_clk_frequency *
+ ((arm_pll_ctrl & ZY7_SLCR_PLL_CTRL_FDIV_MASK) >>
+ ZY7_SLCR_PLL_CTRL_FDIV_SHIFT);
+
+ /* Determine DDR PLL frequency. */
+ if (((ddr_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_QUAL) == 0 &&
+ (ddr_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_FORCE) != 0) ||
+ ((ddr_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_QUAL) != 0 &&
+ (bootmode & ZY7_SLCR_BOOT_MODE_PLL_BYPASS) != 0))
+ /* PLL is bypassed. */
+ ddr_pll_frequency = ps_clk_frequency;
+ else
+ ddr_pll_frequency = ps_clk_frequency *
+ ((ddr_pll_ctrl & ZY7_SLCR_PLL_CTRL_FDIV_MASK) >>
+ ZY7_SLCR_PLL_CTRL_FDIV_SHIFT);
+
+ /* Determine IO PLL frequency. */
+ if (((io_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_QUAL) == 0 &&
+ (io_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_FORCE) != 0) ||
+ ((io_pll_ctrl & ZY7_SLCR_PLL_CTRL_BYPASS_QUAL) != 0 &&
+ (bootmode & ZY7_SLCR_BOOT_MODE_PLL_BYPASS) != 0))
+ /* PLL is bypassed. */
+ io_pll_frequency = ps_clk_frequency;
+ else
+ io_pll_frequency = ps_clk_frequency *
+ ((io_pll_ctrl & ZY7_SLCR_PLL_CTRL_FDIV_MASK) >>
+ ZY7_SLCR_PLL_CTRL_FDIV_SHIFT);
+
+ /* Lock SLCR registers. */
+ zy7_slcr_lock(sc);
+
+ return (0);
+}
+
+static int
+zy7_slcr_detach(device_t dev)
+{
+ struct zy7_slcr_softc *sc = device_get_softc(dev);
+
+ bus_generic_detach(dev);
+
+ /* Release memory resource. */
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res), sc->mem_res);
+
+ zy7_slcr_softc_p = NULL;
+ zynq7_cpu_reset = NULL;
+
+ ZSLCR_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static device_method_t zy7_slcr_methods[] = {
+ /* device_if */
+ DEVMETHOD(device_probe, zy7_slcr_probe),
+ DEVMETHOD(device_attach, zy7_slcr_attach),
+ DEVMETHOD(device_detach, zy7_slcr_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t zy7_slcr_driver = {
+ "zy7_slcr",
+ zy7_slcr_methods,
+ sizeof(struct zy7_slcr_softc),
+};
+static devclass_t zy7_slcr_devclass;
+
+DRIVER_MODULE(zy7_slcr, simplebus, zy7_slcr_driver, zy7_slcr_devclass, 0, 0);
+MODULE_VERSION(zy7_slcr, 1);
Property changes on: trunk/sys/arm/xilinx/zy7_slcr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xilinx/zy7_slcr.h
===================================================================
--- trunk/sys/arm/xilinx/zy7_slcr.h (rev 0)
+++ trunk/sys/arm/xilinx/zy7_slcr.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,293 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Thomas Skibo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xilinx/zy7_slcr.h 273645 2014-10-25 20:34:10Z ian $
+ */
+
+/*
+ * Defines for Zynq-7000 SLCR registers.
+ *
+ * Most of these registers are initialized by the First Stage Boot
+ * Loader and are not modified by the kernel.
+ *
+ * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
+ * (v1.4) November 16, 2012. Xilinx doc UG585. SLCR register definitions
+ * are in appendix B.28.
+ */
+
+
+#ifndef _ZY7_SLCR_H_
+#define _ZY7_SLCR_H_
+
+#define ZY7_SCLR_SCL 0x0000
+#define ZY7_SLCR_LOCK 0x0004
+#define ZY7_SLCR_LOCK_MAGIC 0x767b
+#define ZY7_SLCR_UNLOCK 0x0008
+#define ZY7_SLCR_UNLOCK_MAGIC 0xdf0d
+#define ZY7_SLCR_LOCKSTA 0x000c
+
+/* PLL controls. */
+#define ZY7_SLCR_ARM_PLL_CTRL 0x0100
+#define ZY7_SLCR_DDR_PLL_CTRL 0x0104
+#define ZY7_SLCR_IO_PLL_CTRL 0x0108
+#define ZY7_SLCR_PLL_CTRL_RESET (1<<0)
+#define ZY7_SLCR_PLL_CTRL_PWRDWN (1<<1)
+#define ZY7_SLCR_PLL_CTRL_BYPASS_QUAL (1<<3)
+#define ZY7_SLCR_PLL_CTRL_BYPASS_FORCE (1<<4)
+#define ZY7_SLCR_PLL_CTRL_FDIV_SHIFT 12
+#define ZY7_SLCR_PLL_CTRL_FDIV_MASK (0x7f<<12)
+#define ZY7_SLCR_PLL_STATUS 0x010c
+#define ZY7_SLCR_PLL_STAT_ARM_PLL_LOCK (1<<0)
+#define ZY7_SLCR_PLL_STAT_DDR_PLL_LOCK (1<<1)
+#define ZY7_SLCR_PLL_STAT_IO_PLL_LOCK (1<<2)
+#define ZY7_SLCR_PLL_STAT_ARM_PLL_STABLE (1<<3)
+#define ZY7_SLCR_PLL_STAT_DDR_PLL_STABLE (1<<4)
+#define ZY7_SLCR_PLL_STAT_IO_PLL_STABLE (1<<5)
+#define ZY7_SLCR_ARM_PLL_CFG 0x0110
+#define ZY7_SLCR_DDR_PLL_CFG 0x0114
+#define ZY7_SLCR_IO_PLL_CFG 0x0118
+#define ZY7_SLCR_PLL_CFG_RES_SHIFT 4
+#define ZY7_SLCR_PLL_CFG_RES_MASK (0xf<<4)
+#define ZY7_SLCR_PLL_CFG_PLL_CP_SHIFT 8
+#define ZY7_SLCR_PLL_CFG_PLL_CP_MASK (0xf<<8)
+#define ZY7_SLCR_PLL_CFG_LOCK_CNT_SHIFT 12
+#define ZY7_SLCR_PLL_CFG_LOCK_CNT_MASK (0x3ff<<12)
+
+/* Clock controls. */
+#define ZY7_SLCR_ARM_CLK_CTRL 0x0120
+#define ZY7_SLCR_ARM_CLK_CTRL_CPU_PERI_CLKACT (1<<28)
+#define ZY7_SLCR_ARM_CLK_CTRL_CPU_1XCLKACT (1<<27)
+#define ZY7_SLCR_ARM_CLK_CTRL_CPU_2XCLKACT (1<<26)
+#define ZY7_SLCR_ARM_CLK_CTRL_CPU_3OR2XCLKACT (1<<25)
+#define ZY7_SLCR_ARM_CLK_CTRL_CPU_6OR4XCLKACT (1<<24)
+#define ZY7_SLCR_ARM_CLK_CTRL_SRCSEL_MASK (3<<4)
+#define ZY7_SLCR_ARM_CLK_CTRL_SRCSEL_ARM_PLL (0<<4)
+#define ZY7_SLCR_ARM_CLK_CTRL_SRCSEL_DDR_PLL (2<<4)
+#define ZY7_SLCR_ARM_CLK_CTRL_SRCSEL_IO_PLL (3<<4)
+#define ZY7_SLCR_ARM_CLK_CTRL_DIVISOR_SHIFT 8
+#define ZY7_SLCR_ARM_CLK_CTRL_DIVISOR_MASK (0x3f<<8)
+#define ZY7_SLCR_DDR_CLK_CTRL 0x0124
+#define ZY7_SLCR_DDR_CLK_CTRL_2XCLK_DIV_SHIFT 26
+#define ZY7_SLCR_DDR_CLK_CTRL_2XCLK_DIV_MASK (0x3f<<26)
+#define ZY7_SLCR_DDR_CLK_CTRL_3XCLK_DIV_SHIFT 20
+#define ZY7_SLCR_DDR_CLK_CTRL_3XCLK_DIV_MASK (0x3f<<20)
+#define ZY7_SLCR_DDR_CLK_CTRL_2XCLKACT (1<<1)
+#define ZY7_SLCR_DDR_CLK_CTRL_3XCLKACT (1<<0)
+#define ZY7_SLCR_DCI_CLK_CTRL 0x0128
+#define ZY7_SLCR_DCI_CLK_CTRL_DIVISOR1_SHIFT 20
+#define ZY7_SLCR_DCI_CLK_CTRL_DIVISOR1_MASK (0x3f<<20)
+#define ZY7_SLCR_DCI_CLK_CTRL_DIVISOR0_SHIFT 8
+#define ZY7_SLCR_DCI_CLK_CTRL_DIVISOR0_MASK (0x3f<<8)
+#define ZY7_SLCR_DCI_CLK_CTRL_CLKACT (1<<0)
+#define ZY7_SLCR_APER_CLK_CTRL 0x012c /* amba periph clk ctrl */
+#define ZY7_SLCR_APER_CLK_CTRL_SMC_CPU_1XCLKACT (1<<24)
+#define ZY7_SLCR_APER_CLK_CTRL_LQSPI_CPU_1XCLKACT (1<<23)
+#define ZY7_SLCR_APER_CLK_CTRL_GPIO_CPU_1XCLKACT (1<<22)
+#define ZY7_SLCR_APER_CLK_CTRL_UART1_CPU_1XCLKACT (1<<21)
+#define ZY7_SLCR_APER_CLK_CTRL_UART0_CPU_1XCLKACT (1<<20)
+#define ZY7_SLCR_APER_CLK_CTRL_I2C1_CPU_1XCLKACT (1<<19)
+#define ZY7_SLCR_APER_CLK_CTRL_I2C0_CPU_1XCLKACT (1<<18)
+#define ZY7_SLCR_APER_CLK_CTRL_CAN1_CPU_1XCLKACT (1<<17)
+#define ZY7_SLCR_APER_CLK_CTRL_CAN0_CPU_1XCLKACT (1<<16)
+#define ZY7_SLCR_APER_CLK_CTRL_SPI1_CPU_1XCLKACT (1<<15)
+#define ZY7_SLCR_APER_CLK_CTRL_SPI0_CPU_1XCLKACT (1<<14)
+#define ZY7_SLCR_APER_CLK_CTRL_SDI1_CPU_1XCLKACT (1<<11)
+#define ZY7_SLCR_APER_CLK_CTRL_SDI0_CPU_1XCLKACT (1<<10)
+#define ZY7_SLCR_APER_CLK_CTRL_GEM1_CPU_1XCLKACT (1<<7)
+#define ZY7_SLCR_APER_CLK_CTRL_GEM0_CPU_1XCLKACT (1<<6)
+#define ZY7_SLCR_APER_CLK_CTRL_USB1_CPU_1XCLKACT (1<<3)
+#define ZY7_SLCR_APER_CLK_CTRL_USB0_CPU_1XCLKACT (1<<2)
+#define ZY7_SLCR_APER_CLK_CTRL_DMA_CPU_1XCLKACT (1<<0)
+#define ZY7_SLCR_USB0_CLK_CTRL 0x0130
+#define ZY7_SLCR_USB1_CLK_CTRL 0x0134
+#define ZY7_SLCR_GEM0_RCLK_CTRL 0x0138
+#define ZY7_SLCR_GEM1_RCLK_CTRL 0x013c
+#define ZY7_SLCR_GEM0_CLK_CTRL 0x0140
+#define ZY7_SLCR_GEM1_CLK_CTRL 0x0144
+#define ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MASK (0x3f<<20)
+#define ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_SHIFT 20
+#define ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MAX 0x3f
+#define ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_MASK (0x3f<<8)
+#define ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_SHIFT 8
+#define ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_MAX 0x3f
+#define ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_MASK (7<<4)
+#define ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_IO_PLL (0<<4)
+#define ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_ARM_PLL (2<<4)
+#define ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_DDR_PLL (3<<4)
+#define ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_EMIO_CLK (4<<4)
+#define ZY7_SLCR_GEM_CLK_CTRL_CLKACT 1
+#define ZY7_SLCR_SMC_CLK_CTRL 0x0148
+#define ZY7_SLCR_LQSPI_CLK_CTRL 0x014c
+#define ZY7_SLCR_SDIO_CLK_CTRL 0x0150
+#define ZY7_SLCR_UART_CLK_CTRL 0x0154
+#define ZY7_SLCR_SPI_CLK_CTRL 0x0158
+#define ZY7_SLCR_CAN_CLK_CTRL 0x015c
+#define ZY7_SLCR_CAN_MIOCLK_CTRL 0x0160
+#define ZY7_SLCR_DBG_CLK_CTRL 0x0164
+#define ZY7_SLCR_PCAP_CLK_CTRL 0x0168
+#define ZY7_SLCR_TOPSW_CLK_CTRL 0x016c /* central intercnn clk ctrl */
+#define ZY7_SLCR_FPGA0_CLK_CTRL 0x0170
+#define ZY7_SLCR_FPGA1_CLK_CTRL 0x0180
+#define ZY7_SLCR_FPGA2_CLK_CTRL 0x0190
+#define ZY7_SLCR_FPGA3_CLK_CTRL 0x01a0
+#define ZY7_SLCR_CLK_621_TRUE 0x01c4 /* cpu clock ratio mode */
+
+/* Reset controls. */
+#define ZY7_SLCR_PSS_RST_CTRL 0x0200
+#define ZY7_SLCR_PSS_RST_CTRL_SOFT_RESET (1<<0)
+#define ZY7_SLCR_DDR_RST_CTRL 0x0204
+#define ZY7_SLCR_TOPSW_RST_CTRL 0x0208
+#define ZY7_SLCR_DMAC_RST_CTRL 0x020c
+#define ZY7_SLCR_USB_RST_CTRL 0x0210
+#define ZY7_SLCR_GEM_RST_CTRL 0x0214
+#define ZY7_SLCR_SDIO_RST_CTRL 0x0218
+#define ZY7_SLCR_SPI_RST_CTRL 0x021c
+#define ZY7_SLCR_CAN_RST_CTRL 0x0220
+#define ZY7_SLCR_I2C_RST_CTRL 0x0224
+#define ZY7_SLCR_UART_RST_CTRL 0x0228
+#define ZY7_SLCR_GPIO_RST_CTRL 0x022c
+#define ZY7_SLCR_LQSPI_RST_CTRL 0x0230
+#define ZY7_SLCR_SMC_RST_CTRL 0x0234
+#define ZY7_SLCR_OCM_RST_CTRL 0x0238
+#define ZY7_SLCR_DEVCI_RST_CTRL 0x023c
+#define ZY7_SLCR_FPGA_RST_CTRL 0x0240
+#define ZY7_SLCR_FPGA_RST_CTRL_FPGA3_OUT_RST (1<<3)
+#define ZY7_SLCR_FPGA_RST_CTRL_FPGA2_OUT_RST (1<<2)
+#define ZY7_SLCR_FPGA_RST_CTRL_FPGA1_OUT_RST (1<<1)
+#define ZY7_SLCR_FPGA_RST_CTRL_FPGA0_OUT_RST (1<<0)
+#define ZY7_SLCR_FPGA_RST_CTRL_RST_ALL 0xf
+#define ZY7_SLCR_A9_CPU_RST_CTRL 0x0244
+#define ZY7_SLCR_RS_AWDT_CTRL 0x024c
+
+#define ZY7_SLCR_REBOOT_STAT 0x0258
+#define ZY7_SLCR_REBOOT_STAT_STATE_MASK (0xff<<24)
+#define ZY7_SLCR_REBOOT_STAT_POR (1<<22)
+#define ZY7_SLCR_REBOOT_STAT_SRST_B (1<<21)
+#define ZY7_SLCR_REBOOT_STAT_DBG_RST (1<<20)
+#define ZY7_SLCR_REBOOT_STAT_SLC_RST (1<<19)
+#define ZY7_SLCR_REBOOT_STAT_AWDT1_RST (1<<18)
+#define ZY7_SLCR_REBOOT_STAT_AWDT0_RST (1<<17)
+#define ZY7_SLCR_REBOOT_STAT_SWDT_RST (1<<16)
+#define ZY7_SLCR_REBOOT_STAT_BOOTROM_ERR_CODE_MASK (0xffff)
+#define ZY7_SLCR_BOOT_MODE 0x025c
+#define ZY7_SLCR_BOOT_MODE_PLL_BYPASS (1<<4)
+#define ZY7_SLCR_BOOT_MODE_JTAG_INDEP (1<<3)
+#define ZY7_SLCR_BOOT_MODE_BOOTDEV_MASK 7
+#define ZY7_SLCR_BOOT_MODE_BOOTDEV_JTAG 0
+#define ZY7_SLCR_BOOT_MODE_BOOTDEV_QUAD_SPI 1
+#define ZY7_SLCR_BOOT_MODE_BOOTDEV_NOR 2
+#define ZY7_SLCR_BOOT_MODE_BOOTDEV_NAND 4
+#define ZY7_SLCR_BOOT_MODE_BOOTDEV_SD_CARD 5
+#define ZY7_SLCR_APU_CTRL 0x0300
+#define ZY7_SLCR_WDT_CLK_SEL 0x0304
+
+#define ZY7_SLCR_PSS_IDCODE 0x0530
+#define ZY7_SLCR_PSS_IDCODE_REVISION_MASK (0xf<<28)
+#define ZY7_SLCR_PSS_IDCODE_REVISION_SHIFT 28
+#define ZY7_SLCR_PSS_IDCODE_FAMILY_MASK (0x7f<<21)
+#define ZY7_SLCR_PSS_IDCODE_FAMILY_SHIFT 21
+#define ZY7_SLCR_PSS_IDCODE_SUB_FAMILY_MASK (0xf<<17)
+#define ZY7_SLCR_PSS_IDCODE_SUB_FAMILY_SHIFT 17
+#define ZY7_SLCR_PSS_IDCODE_DEVICE_MASK (0x1f<<12)
+#define ZY7_SLCR_PSS_IDCODE_DEVICE_SHIFT 12
+#define ZY7_SLCR_PSS_IDCODE_MNFR_ID_MASK (0x7ff<<1)
+#define ZY7_SLCR_PSS_IDCODE_MNFR_ID_SHIFT 1
+
+#define ZY7_SLCR_DDR_URGENT 0x0600
+#define ZY7_SLCR_DDR_CAL_START 0x060c
+#define ZY7_SLCR_DDR_REF_START 0x0614
+#define ZY7_SLCR_DDR_CMD_STA 0x0618
+#define ZY7_SLCR_DDR_URGENT_SEL 0x061c
+#define ZY7_SLCR_DDR_DFI_STATUS 0x0620
+
+/* MIO Pin controls */
+#define ZY7_SLCR_MIO_PIN(n) (0x0700+(n)*4) /* 0-53 */
+#define ZY7_SLCR_MIO_PIN_RCVR_DIS (1<<13)
+#define ZY7_SLCR_MIO_PIN_PULLUP_EN (1<<12)
+#define ZY7_SLCR_MIO_PIN_IO_TYPE_MASK (7<<9)
+#define ZY7_SLCR_MIO_PIN_IO_TYPE_LVTTL (0<<9)
+#define ZY7_SLCR_MIO_PIN_IO_TYPE_LVCMOS18 (1<<9)
+#define ZY7_SLCR_MIO_PIN_IO_TYPE_LVCMOS25 (2<<9)
+#define ZY7_SLCR_MIO_PIN_IO_TYPE_LVCMOS33 (3<<9)
+#define ZY7_SLCR_MIO_PIN_IO_TYPE_HSTL (4<<9)
+#define ZY7_SLCR_MIO_PIN_L2_SEL_MASK (3<<3)
+#define ZY7_SLCR_MIO_PIN_L2_SEL_L3_MUX (0<<3)
+#define ZY7_SLCR_MIO_PIN_L2_SEL_SRAM_NOR_CS0 (1<<3)
+#define ZY7_SLCR_MIO_PIN_L2_SEL_NAND_CS (2<<3)
+#define ZY7_SLCR_MIO_PIN_L2_SEL_SDIO0_PC (3<<3)
+#define ZY7_SLCR_MIO_PIN_L1_SEL (1<<2)
+#define ZY7_SLCR_MIO_PIN_L0_SEL (1<<1)
+#define ZY7_SLCR_MIO_PIN_TRI_EN (1<<0)
+
+#define ZY7_SLCR_MIO_LOOPBACK 0x0804
+#define ZY7_SLCR_MIO_LOOPBACK_I2C0_I2C1 (1<<3)
+#define ZY7_SLCR_MIO_LOOPBACK_CAN0_CAN1 (1<<2)
+#define ZY7_SLCR_MIO_LOOPBACK_UA0_UA1 (1<<1)
+#define ZY7_SLCR_MIO_LOOPBACK_SPI0_SPI1 (1<<0)
+#define ZY7_SLCR_MIO_MST_TRI0 0x080c
+#define ZY7_SLCR_MIO_MST_TRI1 0x0810
+#define ZY7_SLCR_SD0_WP_CD_SEL 0x0830
+#define ZY7_SLCR_SD1_WP_CD_SEL 0x0834
+
+/* PS-PL level shifter control. */
+#define ZY7_SLCR_LVL_SHFTR_EN 0x900
+#define ZY7_SLCR_LVL_SHFTR_EN_USER_LVL_IN_EN_0 (1<<3) /* PL to PS */
+#define ZY7_SLCR_LVL_SHFTR_EN_USER_LVL_OUT_EN_0 (1<<2) /* PS to PL */
+#define ZY7_SLCR_LVL_SHFTR_EN_USER_LVL_IN_EN_1 (1<<1) /* PL to PS */
+#define ZY7_SLCR_LVL_SHFTR_EN_USER_LVL_OUT_EN_1 (1<<0) /* PS to PL */
+#define ZY7_SLCR_LVL_SHFTR_EN_ALL 0xf
+
+#define ZY7_SLCR_OCM_CFG 0x0910
+
+#define ZY7_SLCR_GPIOB_CTRL 0x0b00
+#define ZY7_SLCR_GPIOB_CFG_CMOS18 0x0b04
+#define ZY7_SLCR_GPIOB_CFG_CMOS25 0x0b08
+#define ZY7_SLCR_GPIOB_CFG_CMOS33 0x0b0c
+#define ZY7_SLCR_GPIOB_CFG_LVTTL 0x0b10
+#define ZY7_SLCR_GPIOB_CFG_HSTL 0x0b14
+#define ZY7_SLCR_GPIOB_DRVR_BIAS_CTRL 0x0b18
+
+#define ZY7_SLCR_DDRIOB_ADDR0 0x0b40
+#define ZY7_SLCR_DDRIOB_ADDR1 0x0b44
+#define ZY7_SLCR_DDRIOB_DATA0 0x0b48
+#define ZY7_SLCR_DDRIOB_DATA1 0x0b4c
+#define ZY7_SLCR_DDRIOB_DIFF0 0x0b50
+#define ZY7_SLCR_DDRIOB_DIFF1 0x0b54
+#define ZY7_SLCR_DDRIOB_CLK 0x0b58
+#define ZY7_SLCR_DDRIOB_DRIVE_SLEW_ADDR 0x0b5c
+#define ZY7_SLCR_DDRIOB_DRIVE_SLEW_DATA 0x0b60
+#define ZY7_SLCR_DDRIOB_DRIVE_SLEW_DIFF 0x0b64
+#define ZY7_SLCR_DDRIOB_DRIVE_SLEW_CLK 0x0b68
+#define ZY7_SLCR_DDRIOB_DDR_CTRL 0x0b6c
+#define ZY7_SLCR_DDRIOB_DCI_CTRL 0x0b70
+#define ZY7_SLCR_DDRIOB_DCI_STATUS 0x0b74
+
+#ifdef _KERNEL
+extern void zy7_slcr_preload_pl(void);
+extern void zy7_slcr_postload_pl(int en_level_shifters);
+extern int cgem_set_ref_clk(int unit, int frequency);
+#endif
+#endif /* _ZY7_SLCR_H_ */
Property changes on: trunk/sys/arm/xilinx/zy7_slcr.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/ep80219_machdep.c
===================================================================
--- trunk/sys/arm/xscale/i80321/ep80219_machdep.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/ep80219_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,397 @@
+/* $MidnightBSD$ */
+/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
+
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work.
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/ep80219_machdep.c 278727 2015-02-13 22:32:02Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/cons.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/kdb.h>
+#include <sys/msgbuf.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <machine/devmap.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/physmem.h>
+#include <sys/reboot.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i80321/iq80321reg.h>
+#include <arm/xscale/i80321/obiovar.h>
+
+#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
+#define KERNEL_PT_IOPXS 1
+#define KERNEL_PT_BEFOREKERN 2
+#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */
+#define KERNEL_PT_AFKERNEL_NUM 9
+
+/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
+#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
+
+struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
+
+/* Physical and virtual addresses for some global pages */
+
+struct pv_addr systempage;
+struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+struct pv_addr kernelstack;
+struct pv_addr minidataclean;
+
+
+/* #define IQ80321_OBIO_BASE 0xfe800000UL */
+/* #define IQ80321_OBIO_SIZE 0x00100000UL */
+
+/* Static device mappings. */
+static const struct arm_devmap_entry ep80219_devmap[] = {
+ /*
+ * Map the on-board devices VA == PA so that we can access them
+ * with the MMU on or off.
+ */
+ {
+ IQ80321_OBIO_BASE,
+ IQ80321_OBIO_BASE,
+ IQ80321_OBIO_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ IQ80321_IOW_VBASE,
+ VERDE_OUT_XLATE_IO_WIN0_BASE,
+ VERDE_OUT_XLATE_IO_WIN_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ IQ80321_80321_VBASE,
+ VERDE_PMMR_BASE,
+ VERDE_PMMR_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ }
+};
+
+extern vm_offset_t xscale_cache_clean_addr;
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+ struct pv_addr kernel_l1pt;
+ struct pv_addr dpcpu;
+ int loop, i;
+ u_int l1pagetable;
+ vm_offset_t freemempos;
+ vm_offset_t freemem_pt;
+ vm_offset_t afterkern;
+ vm_offset_t freemem_after;
+ vm_offset_t lastaddr;
+ uint32_t memsize, memstart;
+
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+ set_cpufuncs();
+ pcpu_init(pcpup, 0, sizeof(struct pcpu));
+ PCPU_SET(curthread, &thread0);
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+ freemempos = 0xa0200000;
+ /* Define a macro to simplify memory allocation */
+#define valloc_pages(var, np) \
+ alloc_pages((var).pv_pa, (np)); \
+ (var).pv_va = (var).pv_pa + 0x20000000;
+
+#define alloc_pages(var, np) \
+ freemempos -= (np * PAGE_SIZE); \
+ (var) = freemempos; \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos -= PAGE_SIZE;
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[loop],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ } else {
+ kernel_pt_table[loop].pv_pa = freemempos +
+ (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
+ L2_TABLE_SIZE_REAL;
+ kernel_pt_table[loop].pv_va =
+ kernel_pt_table[loop].pv_pa + 0x20000000;
+ }
+ }
+ freemem_pt = freemempos;
+ freemempos = 0xa0100000;
+ /*
+ * Allocate a page for the system page mapped to V0x00000000
+ * This page will just contain the system vectors and can be
+ * shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate dynamic per-cpu area. */
+ valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
+ dpcpu_init((void *)dpcpu.pv_va, 0);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE);
+ valloc_pages(abtstack, ABT_STACK_SIZE);
+ valloc_pages(undstack, UND_STACK_SIZE);
+ valloc_pages(kernelstack, KSTACK_PAGES);
+ alloc_pages(minidataclean.pv_pa, 1);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+ /*
+ * Allocate memory for the l1 and l2 page tables. The scheme to avoid
+ * wasting memory by allocating the l1pt on the first 16k memory was
+ * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for
+ * this to work (which is supposed to be the case).
+ */
+
+ /*
+ * Now we start construction of the L1 page table
+ * We start by mapping the L2 page tables into the L1.
+ * This means that we can replace L1 mappings later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /* Map the L2 pages tables in the L1 page table */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1),
+ &kernel_pt_table[KERNEL_PT_SYS]);
+ pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE,
+ &kernel_pt_table[KERNEL_PT_IOPXS]);
+ pmap_link_l2pt(l1pagetable, KERNBASE,
+ &kernel_pt_table[KERNEL_PT_BEFOREKERN]);
+ pmap_map_chunk(l1pagetable, KERNBASE, IQ80321_SDRAM_START, 0x100000,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, IQ80321_SDRAM_START + 0x100000,
+ 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, IQ80321_SDRAM_START + 0x200000,
+ (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1),
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1);
+ afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE
+ - 1));
+ for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
+ pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
+ &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
+ }
+ pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+
+ /* Map the Mini-Data cache clean area. */
+ xscale_setup_minidata(l1pagetable, afterkern,
+ minidataclean.pv_pa);
+
+ /* Map the vector page. */
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ arm_devmap_bootstrap(l1pagetable, ep80219_devmap);
+ /*
+ * Give the XScale global cache clean code an appropriately
+ * sized chunk of unmapped VA space starting at 0xff000000
+ * (our device mappings end before this address).
+ */
+ xscale_cache_clean_addr = 0xff000000U;
+
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+ cpu_setup("");
+
+ /*
+ * Fetch the SDRAM start/size from the i80321 SDRAM configration
+ * registers.
+ */
+ i80321_calibrate_delay();
+ i80321_sdram_bounds(obio_bs_tag, IQ80321_80321_VBASE + VERDE_MCU_BASE,
+ &memstart, &memsize);
+ physmem = memsize / PAGE_SIZE;
+ cninit();
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ /* Enable MMU, I-cache, D-cache, write buffer. */
+
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+ vm_max_kernel_address = 0xd0000000;
+ pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
+ msgbufp = (void*)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+
+ /*
+ * Add the physical ram we have available.
+ *
+ * Exclude the kernel (and all the things we allocated which immediately
+ * follow the kernel) from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ arm_physmem_hardware_region(IQ80321_SDRAM_START, memsize);
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+}
+
+extern int
+machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin)
+{
+ int bus;
+ int device;
+ int func;
+ uint32_t busno;
+ struct i80321_pci_softc *sc = device_get_softc(pcib);
+ bus = pci_get_bus(dev);
+ device = pci_get_slot(dev);
+ func = pci_get_function(dev);
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
+ busno = PCIXSR_BUSNO(busno);
+ if (busno == 0xff)
+ busno = 0;
+ if (bus != busno)
+ goto no_mapping;
+ switch (device) {
+ /* EP80219 PCI */
+ case 1: /* Ethernet i82555 10/100 */
+ printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(0));
+ return (ICU_INT_XINT(0));
+ case 2: /* UART */
+ printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(1));
+ return (ICU_INT_XINT(1));
+ case 3:
+ /*
+ * The S-ATA chips are behind the bridge, and all of
+ * the S-ATA interrupts are wired together.
+ */
+ printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(2));
+ return (ICU_INT_XINT(2));
+ case 4: /* MINI-PIC_INT */
+ printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(3));
+ return( ICU_INT_XINT(3));
+ default:
+no_mapping:
+ printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin);
+
+ }
+ return (0);
+
+}
Property changes on: trunk/sys/arm/xscale/i80321/ep80219_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/files.ep80219
===================================================================
--- trunk/sys/arm/xscale/i80321/files.ep80219 (rev 0)
+++ trunk/sys/arm/xscale/i80321/files.ep80219 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,11 @@
+#$FreeBSD: stable/10/sys/arm/xscale/i80321/files.ep80219 278727 2015-02-13 22:32:02Z ian $
+#
+#
+# EP80219 Board Specific
+#
+arm/xscale/i80321/iq80321.c standard
+arm/xscale/i80321/ep80219_machdep.c standard
+arm/xscale/i80321/obio.c standard
+arm/xscale/i80321/uart_cpu_i80321.c optional uart
+arm/xscale/i80321/uart_bus_i80321.c optional uart
+dev/uart/uart_dev_ns8250.c optional uart
Property changes on: trunk/sys/arm/xscale/i80321/files.ep80219
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/files.i80219
===================================================================
--- trunk/sys/arm/xscale/i80321/files.i80219 (rev 0)
+++ trunk/sys/arm/xscale/i80321/files.i80219 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,14 @@
+#$FreeBSD: stable/10/sys/arm/xscale/i80321/files.i80219 278727 2015-02-13 22:32:02Z ian $
+#
+# IOP Specific
+#
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_xscale.S standard
+arm/xscale/i80321/i80321.c standard
+arm/xscale/i80321/i80321_dma.c optional dma
+arm/xscale/i80321/i80321_mcu.c standard
+arm/xscale/i80321/i80321_pci.c optional pci
+arm/xscale/i80321/i80321_space.c standard
+arm/xscale/i80321/i80321_timer.c standard
+arm/xscale/i80321/i80321_wdog.c optional iopwdog
Property changes on: trunk/sys/arm/xscale/i80321/files.i80219
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/files.i80321
===================================================================
--- trunk/sys/arm/xscale/i80321/files.i80321 (rev 0)
+++ trunk/sys/arm/xscale/i80321/files.i80321 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,12 @@
+#$FreeBSD: stable/10/sys/arm/xscale/i80321/files.i80321 278727 2015-02-13 22:32:02Z ian $
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_xscale.S standard
+arm/xscale/i80321/i80321.c standard
+arm/xscale/i80321/i80321_aau.c optional aau
+arm/xscale/i80321/i80321_dma.c optional dma
+arm/xscale/i80321/i80321_mcu.c standard
+arm/xscale/i80321/i80321_pci.c optional pci
+arm/xscale/i80321/i80321_space.c standard
+arm/xscale/i80321/i80321_timer.c standard
+arm/xscale/i80321/i80321_wdog.c optional iopwdog
Property changes on: trunk/sys/arm/xscale/i80321/files.i80321
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/files.iq31244
===================================================================
--- trunk/sys/arm/xscale/i80321/files.iq31244 (rev 0)
+++ trunk/sys/arm/xscale/i80321/files.iq31244 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,8 @@
+#$FreeBSD: stable/10/sys/arm/xscale/i80321/files.iq31244 278727 2015-02-13 22:32:02Z ian $
+arm/xscale/i80321/iq80321.c standard
+arm/xscale/i80321/iq31244_machdep.c standard
+arm/xscale/i80321/iq31244_7seg.c optional iq31244_7seg
+arm/xscale/i80321/obio.c standard
+arm/xscale/i80321/uart_cpu_i80321.c optional uart
+arm/xscale/i80321/uart_bus_i80321.c optional uart
+dev/uart/uart_dev_ns8250.c optional uart
Property changes on: trunk/sys/arm/xscale/i80321/files.iq31244
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321.c
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,251 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321.c,v 1.15 2003/10/06 16:06:05 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Autoconfiguration support for the Intel i80321 I/O Processor.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/i80321.c 236987 2012-06-13 04:38:09Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i80321/i80321_intr.h>
+
+#include <dev/pci/pcireg.h>
+
+volatile uint32_t intr_enabled;
+uint32_t intr_steer = 0;
+/*
+ * Statically-allocated bus_space stucture used to access the
+ * i80321's own registers.
+ */
+struct bus_space i80321_bs_tag;
+
+/*
+ * There can be only one i80321, so we keep a global pointer to
+ * the softc, so board-specific code can use features of the
+ * i80321 without having to have a handle on the softc itself.
+ */
+struct i80321_softc *i80321_softc;
+
+#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
+/*
+ * i80321_attach:
+ *
+ * Board-independent attach routine for the i80321.
+ */
+void
+i80321_attach(struct i80321_softc *sc)
+{
+
+ i80321_softc = sc;
+ uint32_t preg;
+
+ /* We expect the Memory Controller to be already sliced off. */
+
+ /*
+ * Program the Inbound windows.
+ */
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0,
+ (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0,
+ sc->sc_iwin[0].iwin_xlate);
+ if (sc->sc_is_host) {
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ PCIR_BARS, sc->sc_iwin[0].iwin_base_lo);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ PCIR_BARS + 0x04, sc->sc_iwin[0].iwin_base_hi);
+ } else {
+ sc->sc_iwin[0].iwin_base_lo = bus_space_read_4(sc->sc_st,
+ sc->sc_atu_sh, PCIR_BARS);
+ sc->sc_iwin[0].iwin_base_hi = bus_space_read_4(sc->sc_st,
+ sc->sc_atu_sh, PCIR_BARS + 0x04);
+ sc->sc_iwin[0].iwin_base_lo =
+ PCI_MAPREG_MEM_ADDR(sc->sc_iwin[0].iwin_base_lo);
+ }
+
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1,
+ (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0);
+
+ /* no xlate for window 1 */
+ if (sc->sc_is_host) {
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ PCIR_BARS + 0x08, sc->sc_iwin[1].iwin_base_lo);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ PCIR_BARS + 0x0c, sc->sc_iwin[1].iwin_base_hi);
+ } else {
+ sc->sc_iwin[1].iwin_base_lo = bus_space_read_4(sc->sc_st,
+ sc->sc_atu_sh, PCIR_BARS + 0x08);
+ sc->sc_iwin[1].iwin_base_hi = bus_space_read_4(sc->sc_st,
+ sc->sc_atu_sh, PCIR_BARS + 0x0c);
+ sc->sc_iwin[1].iwin_base_lo =
+ PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
+ }
+
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2,
+ (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2,
+ sc->sc_iwin[2].iwin_xlate);
+
+ if (sc->sc_is_host) {
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ PCIR_BARS + 0x10, sc->sc_iwin[2].iwin_base_lo);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ PCIR_BARS + 0x14, sc->sc_iwin[2].iwin_base_hi);
+ } else {
+ sc->sc_iwin[2].iwin_base_lo = bus_space_read_4(sc->sc_st,
+ sc->sc_atu_sh, PCIR_BARS + 0x10);
+ sc->sc_iwin[2].iwin_base_hi = bus_space_read_4(sc->sc_st,
+ sc->sc_atu_sh, PCIR_BARS + 0x14);
+ sc->sc_iwin[2].iwin_base_lo =
+ PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
+ }
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3,
+ (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3,
+ sc->sc_iwin[3].iwin_xlate);
+
+ if (sc->sc_is_host) {
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi);
+ } else {
+ sc->sc_iwin[3].iwin_base_lo = bus_space_read_4(sc->sc_st,
+ sc->sc_atu_sh, ATU_IABAR3);
+ sc->sc_iwin[3].iwin_base_hi = bus_space_read_4(sc->sc_st,
+ sc->sc_atu_sh, ATU_IAUBAR3);
+ sc->sc_iwin[3].iwin_base_lo =
+ PCI_MAPREG_MEM_ADDR(sc->sc_iwin[3].iwin_base_lo);
+ }
+ /*
+ * Mask (disable) the ATU interrupt sources.
+ * XXX May want to revisit this if we encounter
+ * XXX an application that wants it.
+ */
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ ATU_ATUIMR,
+ ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST|
+ ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM|
+ ATUIMR_PTAT|ATUIMR_PMPE);
+
+ /*
+ * Program the outbound windows.
+ */
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ ATU_OIOWTVR, sc->sc_ioout_xlate);
+
+ if (!sc->sc_is_host) {
+ sc->sc_owin[0].owin_xlate_lo = sc->sc_iwin[1].iwin_base_lo;
+ sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
+ }
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi);
+
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi);
+
+ /*
+ * Set up the ATU configuration register. All we do
+ * right now is enable Outbound Windows.
+ */
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR,
+ ATUCR_OUT_EN);
+
+ /*
+ * Enable bus mastering, memory access, SERR, and parity
+ * checking on the ATU.
+ */
+ if (sc->sc_is_host) {
+ preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh,
+ PCIR_COMMAND);
+ preg |= PCIM_CMD_MEMEN |
+ PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN |
+ PCIM_CMD_SERRESPEN;
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
+ PCIR_COMMAND, preg);
+ }
+ /* Initialize the bus space tags. */
+ i80321_io_bs_init(&sc->sc_pci_iot, sc);
+ i80321_mem_bs_init(&sc->sc_pci_memt, sc);
+ intr_enabled = 0;
+ i80321_set_intrmask();
+ i80321_set_intrsteer();
+}
+
+
+static __inline uint32_t
+i80321_iintsrc_read(void)
+{
+ uint32_t iintsrc;
+
+ __asm __volatile("mrc p6, 0, %0, c8, c0, 0"
+ : "=r" (iintsrc));
+
+ /*
+ * The IINTSRC register shows bits that are active even
+ * if they are masked in INTCTL, so we have to mask them
+ * off with the interrupts we consider enabled.
+ */
+ return (iintsrc & intr_enabled);
+}
+
+int
+arm_get_next_irq(int last __unused)
+{
+ int irq;
+
+ if ((irq = i80321_iintsrc_read()))
+ return (ffs(irq) - 1);
+ return (-1);
+}
Property changes on: trunk/sys/arm/xscale/i80321/i80321.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321_aau.c
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321_aau.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321_aau.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,293 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/i80321_aau.c 236987 2012-06-13 04:38:09Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i80321/iq80321reg.h>
+#include <arm/xscale/i80321/iq80321var.h>
+#include <arm/xscale/i80321/i80321_intr.h>
+
+typedef struct i80321_aaudesc_s {
+ vm_paddr_t next_desc;
+ uint32_t sar[4];
+ vm_paddr_t local_addr;
+ vm_size_t count;
+ uint32_t descr_ctrl;
+} __packed i80321_aaudesc_t;
+
+typedef struct i80321_aauring_s {
+ i80321_aaudesc_t *desc;
+ vm_paddr_t phys_addr;
+ bus_dmamap_t map;
+} i80321_aauring_t;
+
+#define AAU_RING_SIZE 64
+
+struct i80321_aau_softc {
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_aau_sh;
+ bus_dma_tag_t dmatag;
+ i80321_aauring_t aauring[AAU_RING_SIZE];
+ int flags;
+#define BUSY 0x1
+ int unit;
+ struct mtx mtx;
+};
+
+static int
+i80321_aau_probe(device_t dev)
+{
+ device_set_desc(dev, "I80321 AAU");
+ return (0);
+}
+
+static struct i80321_aau_softc *aau_softc;
+
+static void
+i80321_mapphys(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ vm_paddr_t *addr = (vm_paddr_t *)arg;
+
+ *addr = segs->ds_addr;
+}
+
+#define AAU_REG_WRITE(softc, reg, val) \
+ bus_space_write_4((softc)->sc_st, (softc)->sc_aau_sh, \
+ (reg), (val))
+#define AAU_REG_READ(softc, reg) \
+ bus_space_read_4((softc)->sc_st, (softc)->sc_aau_sh, \
+ (reg))
+
+static int aau_bzero(void *, int, int);
+
+static int
+i80321_aau_attach(device_t dev)
+{
+ struct i80321_aau_softc *softc = device_get_softc(dev);
+ struct i80321_softc *sc = device_get_softc(device_get_parent(dev));
+ struct i80321_aaudesc_s *aaudescs;
+
+ mtx_init(&softc->mtx, "AAU mtx", NULL, MTX_SPIN);
+ softc->sc_st = sc->sc_st;
+ if (bus_space_subregion(softc->sc_st, sc->sc_sh, VERDE_AAU_BASE,
+ VERDE_AAU_SIZE, &softc->sc_aau_sh) != 0)
+ panic("%s: unable to subregion AAU registers",
+ device_get_name(dev));
+ if (bus_dma_tag_create(NULL, sizeof(i80321_aaudesc_t), 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ AAU_RING_SIZE * sizeof(i80321_aaudesc_t),
+ 1, sizeof(i80321_aaudesc_t), BUS_DMA_ALLOCNOW, busdma_lock_mutex,
+ &Giant, &softc->dmatag))
+ panic("Couldn't create a dma tag");
+ if (bus_dmamem_alloc(softc->dmatag, (void **)&aaudescs,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &softc->aauring[0].map))
+ panic("Couldn't alloc dma memory");
+
+ for (int i = 0; i < AAU_RING_SIZE; i++) {
+ if (i > 0)
+ if (bus_dmamap_create(softc->dmatag, 0,
+ &softc->aauring[i].map))
+ panic("Couldn't create dma map");
+ softc->aauring[i].desc = &aaudescs[i];
+ bus_dmamap_load(softc->dmatag, softc->aauring[i].map,
+ softc->aauring[i].desc, sizeof(i80321_aaudesc_t),
+ i80321_mapphys, &softc->aauring[i].phys_addr, 0);
+ bzero(softc->aauring[i].desc, sizeof(i80321_aaudesc_t));
+ }
+ aau_softc = softc;
+ _arm_bzero = aau_bzero;
+ _min_bzero_size = 1024;
+ return (0);
+}
+
+static __inline void
+test_virt_addr(void *addr, int len)
+{
+ int to_nextpage;
+
+ while (len > 0) {
+ *(char *)addr = 0;
+ to_nextpage = ((vm_offset_t)addr & ~PAGE_MASK) +
+ PAGE_SIZE - (vm_offset_t)addr;
+ if (to_nextpage >= len)
+ break;
+ len -= to_nextpage;
+ addr = (void *)((vm_offset_t)addr + to_nextpage);
+ }
+}
+
+static int
+aau_bzero(void *dst, int len, int flags)
+{
+ struct i80321_aau_softc *sc = aau_softc;
+ i80321_aaudesc_t *desc;
+ int ret;
+ int csr;
+ int descnb = 0;
+ int tmplen = len;
+ int to_nextpagedst;
+ int min_hop;
+ vm_paddr_t pa, tmppa;
+
+ if (!sc)
+ return (-1);
+ mtx_lock_spin(&sc->mtx);
+ if (sc->flags & BUSY) {
+ mtx_unlock_spin(&sc->mtx);
+ return (-1);
+ }
+ sc->flags |= BUSY;
+ mtx_unlock_spin(&sc->mtx);
+ desc = sc->aauring[0].desc;
+ if (flags & IS_PHYSICAL) {
+ desc->local_addr = (vm_paddr_t)dst;
+ desc->next_desc = 0;
+ desc->count = len;
+ desc->descr_ctrl = 2 << 1 | 1 << 31; /* Fill, enable dest write */
+ bus_dmamap_sync(sc->dmatag, sc->aauring[0].map,
+ BUS_DMASYNC_PREWRITE);
+ } else {
+ test_virt_addr(dst, len);
+ if ((vm_offset_t)dst & (31))
+ cpu_dcache_wb_range((vm_offset_t)dst & ~31, 32);
+ if (((vm_offset_t)dst + len) & 31)
+ cpu_dcache_wb_range(((vm_offset_t)dst + len) & ~31,
+ 32);
+ cpu_dcache_inv_range((vm_offset_t)dst, len);
+ while (tmplen > 0) {
+ pa = vtophys(dst);
+ to_nextpagedst = ((vm_offset_t)dst & ~PAGE_MASK) +
+ PAGE_SIZE - (vm_offset_t)dst;
+ while (to_nextpagedst < tmplen) {
+ tmppa = vtophys((vm_offset_t)dst +
+ to_nextpagedst);
+ if (tmppa != pa + to_nextpagedst)
+ break;
+ to_nextpagedst += PAGE_SIZE;
+ }
+ min_hop = to_nextpagedst;
+ if (min_hop < 64) {
+ tmplen -= min_hop;
+ bzero(dst, min_hop);
+ cpu_dcache_wbinv_range((vm_offset_t)dst,
+ min_hop);
+
+ dst = (void *)((vm_offset_t)dst + min_hop);
+ if (tmplen <= 0 && descnb > 0) {
+ sc->aauring[descnb - 1].desc->next_desc
+ = 0;
+ bus_dmamap_sync(sc->dmatag,
+ sc->aauring[descnb - 1].map,
+ BUS_DMASYNC_PREWRITE);
+ }
+ continue;
+ }
+ desc->local_addr = pa;
+ desc->count = tmplen > min_hop ? min_hop : tmplen;
+ desc->descr_ctrl = 2 << 1 | 1 << 31; /* Fill, enable dest write */;
+ if (min_hop < tmplen) {
+ tmplen -= min_hop;
+ dst = (void *)((vm_offset_t)dst + min_hop);
+ } else
+ tmplen = 0;
+ if (descnb + 1 >= AAU_RING_SIZE) {
+ mtx_lock_spin(&sc->mtx);
+ sc->flags &= ~BUSY;
+ mtx_unlock_spin(&sc->mtx);
+ return (-1);
+ }
+ if (tmplen > 0) {
+ desc->next_desc = sc->aauring[descnb + 1].
+ phys_addr;
+ bus_dmamap_sync(sc->dmatag,
+ sc->aauring[descnb].map,
+ BUS_DMASYNC_PREWRITE);
+ desc = sc->aauring[descnb + 1].desc;
+ descnb++;
+ } else {
+ desc->next_desc = 0;
+ bus_dmamap_sync(sc->dmatag,
+ sc->aauring[descnb].map,
+ BUS_DMASYNC_PREWRITE);
+ }
+
+ }
+
+ }
+ AAU_REG_WRITE(sc, 0x0c /* Descriptor addr */,
+ sc->aauring[0].phys_addr);
+ AAU_REG_WRITE(sc, 0 /* Control register */, 1 << 0/* Start transfer */);
+ while ((csr = AAU_REG_READ(sc, 0x4)) & (1 << 10));
+ /* Wait until it's done. */
+ if (csr & (1 << 5)) /* error */
+ ret = -1;
+ else
+ ret = 0;
+ /* Clear the interrupt. */
+ AAU_REG_WRITE(sc, 0x4, csr);
+ /* Stop the AAU. */
+ AAU_REG_WRITE(sc, 0, 0);
+ mtx_lock_spin(&sc->mtx);
+ sc->flags &= ~BUSY;
+ mtx_unlock_spin(&sc->mtx);
+ return (ret);
+}
+
+static device_method_t i80321_aau_methods[] = {
+ DEVMETHOD(device_probe, i80321_aau_probe),
+ DEVMETHOD(device_attach, i80321_aau_attach),
+ {0, 0},
+};
+
+static driver_t i80321_aau_driver = {
+ "i80321_aau",
+ i80321_aau_methods,
+ sizeof(struct i80321_aau_softc),
+};
+
+static devclass_t i80321_aau_devclass;
+
+DRIVER_MODULE(i80321_aau, iq, i80321_aau_driver, i80321_aau_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i80321/i80321_aau.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321_dma.c
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321_dma.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321_dma.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,352 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/i80321_dma.c 236987 2012-06-13 04:38:09Z imp $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i80321/iq80321reg.h>
+#include <arm/xscale/i80321/iq80321var.h>
+#include <arm/xscale/i80321/i80321_intr.h>
+
+typedef struct i80321_dmadesc_s {
+ vm_paddr_t next_desc;
+ vm_paddr_t low_pciaddr;
+ vm_paddr_t high_pciaddr;
+ vm_paddr_t local_addr;
+ vm_size_t count;
+ uint32_t descr_ctrl;
+ uint64_t unused;
+} __packed i80321_dmadesc_t;
+
+typedef struct i80321_dmaring_s {
+ i80321_dmadesc_t *desc;
+ vm_paddr_t phys_addr;
+ bus_dmamap_t map;
+} i80321_dmaring_t;
+
+#define DMA_RING_SIZE 64
+
+struct i80321_dma_softc {
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_dma_sh;
+ bus_dma_tag_t dmatag;
+ i80321_dmaring_t dmaring[DMA_RING_SIZE];
+ int flags;
+#define BUSY 0x1
+ int unit;
+ struct mtx mtx;
+};
+
+static int
+i80321_dma_probe(device_t dev)
+{
+ device_set_desc(dev, "I80321 DMA Unit");
+ return (0);
+}
+
+static struct i80321_dma_softc *softcs[2]; /* XXX */
+
+static void
+i80321_mapphys(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ vm_paddr_t *addr = (vm_paddr_t *)arg;
+
+ *addr = segs->ds_addr;
+}
+
+#define DMA_REG_WRITE(softc, reg, val) \
+ bus_space_write_4((softc)->sc_st, (softc)->sc_dma_sh, \
+ (reg), (val))
+#define DMA_REG_READ(softc, reg) \
+ bus_space_read_4((softc)->sc_st, (softc)->sc_dma_sh, \
+ (reg))
+
+#define DMA_CLEAN_MASK (0x2|0x4|0x8|0x20|0x100|0x200)
+static int dma_memcpy(void *, void *, int, int);
+
+static int
+i80321_dma_attach(device_t dev)
+{
+ struct i80321_dma_softc *softc = device_get_softc(dev);
+ struct i80321_softc *sc = device_get_softc(device_get_parent(dev));
+ int unit = device_get_unit(dev);
+ i80321_dmadesc_t *dmadescs;
+
+ mtx_init(&softc->mtx, "DMA engine mtx", NULL, MTX_SPIN);
+ softc->sc_st = sc->sc_st;
+ if (bus_space_subregion(softc->sc_st, sc->sc_sh, unit == 0 ?
+ VERDE_DMA_BASE0 : VERDE_DMA_BASE1, VERDE_DMA_SIZE,
+ &softc->sc_dma_sh) != 0)
+ panic("%s: unable to subregion DMA registers",
+ device_get_name(dev));
+ if (bus_dma_tag_create(NULL, sizeof(i80321_dmadesc_t),
+ 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ DMA_RING_SIZE * sizeof(i80321_dmadesc_t), 1,
+ sizeof(i80321_dmadesc_t), BUS_DMA_ALLOCNOW, busdma_lock_mutex,
+ &Giant, &softc->dmatag))
+ panic("Couldn't create a dma tag");
+ DMA_REG_WRITE(softc, 0, 0);
+ if (bus_dmamem_alloc(softc->dmatag, (void **)&dmadescs,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &softc->dmaring[0].map))
+ panic("Couldn't alloc dma memory");
+ for (int i = 0; i < DMA_RING_SIZE; i++) {
+ if (i > 0)
+ if (bus_dmamap_create(softc->dmatag, 0,
+ &softc->dmaring[i].map))
+ panic("Couldn't alloc dmamap");
+ softc->dmaring[i].desc = &dmadescs[i];
+ bus_dmamap_load(softc->dmatag, softc->dmaring[i].map,
+ softc->dmaring[i].desc, sizeof(i80321_dmadesc_t),
+ i80321_mapphys, &softc->dmaring[i].phys_addr, 0);
+ }
+ softc->unit = unit;
+ softcs[unit] = softc;
+ _arm_memcpy = dma_memcpy;
+ _min_memcpy_size = 1024;
+ return (0);
+}
+
+static __inline int
+virt_addr_is_valid(void *addr, int len, int write, int is_kernel)
+{
+ int to_nextpage;
+ char tmp = 0;
+
+ while (len > 0) {
+ if (write) {
+ if (is_kernel)
+ *(char *)addr = 0;
+ else if (subyte(addr, 0) != 0) {
+ return (0);
+ }
+ } else {
+ if (is_kernel)
+ badaddr_read(addr, 1, &tmp);
+ else if (fubyte(addr) == -1) {
+ return (0);
+ }
+ }
+ to_nextpage = ((vm_offset_t)addr & ~PAGE_MASK) +
+ PAGE_SIZE - (vm_offset_t)addr;
+ if (to_nextpage >= len)
+ break;
+ len -= to_nextpage;
+ addr = (void *)((vm_offset_t)addr + to_nextpage);
+ }
+ return (1);
+}
+
+static int
+dma_memcpy(void *dst, void *src, int len, int flags)
+{
+ struct i80321_dma_softc *sc;
+ i80321_dmadesc_t *desc;
+ int ret;
+ int csr;
+ int descnb = 0;
+ int tmplen = len;
+ int to_nextpagesrc, to_nextpagedst;
+ int min_hop;
+ vm_paddr_t pa, pa2, tmppa;
+ pmap_t pmap = vmspace_pmap(curthread->td_proc->p_vmspace);
+
+ if (!softcs[0] || !softcs[1])
+ return (-1);
+ mtx_lock_spin(&softcs[0]->mtx);
+ if (softcs[0]->flags & BUSY) {
+ mtx_unlock_spin(&softcs[0]->mtx);
+ mtx_lock_spin(&softcs[1]->mtx);
+ if (softcs[1]->flags & BUSY) {
+ mtx_unlock(&softcs[1]->mtx);
+ return (-1);
+ }
+ sc = softcs[1];
+ } else
+ sc = softcs[0];
+ sc->flags |= BUSY;
+ mtx_unlock_spin(&sc->mtx);
+ desc = sc->dmaring[0].desc;
+ if (flags & IS_PHYSICAL) {
+ desc->next_desc = 0;
+ desc->low_pciaddr = (vm_paddr_t)src;
+ desc->high_pciaddr = 0;
+ desc->local_addr = (vm_paddr_t)dst;
+ desc->count = len;
+ desc->descr_ctrl = 1 << 6; /* Local memory to local memory. */
+ bus_dmamap_sync(sc->dmatag,
+ sc->dmaring[0].map,
+ BUS_DMASYNC_PREWRITE);
+ } else {
+ if (!virt_addr_is_valid(dst, len, 1, !(flags & DST_IS_USER)) ||
+ !virt_addr_is_valid(src, len, 0, !(flags & SRC_IS_USER))) {
+ mtx_lock_spin(&sc->mtx);
+ sc->flags &= ~BUSY;
+ mtx_unlock_spin(&sc->mtx);
+ return (-1);
+ }
+ cpu_dcache_wb_range((vm_offset_t)src, len);
+ if ((vm_offset_t)dst & (31))
+ cpu_dcache_wb_range((vm_offset_t)dst & ~31, 32);
+ if (((vm_offset_t)dst + len) & 31)
+ cpu_dcache_wb_range(((vm_offset_t)dst + len) & ~31,
+ 32);
+ cpu_dcache_inv_range((vm_offset_t)dst, len);
+ while (tmplen > 0) {
+ pa = (flags & SRC_IS_USER) ?
+ pmap_extract(pmap, (vm_offset_t)src) :
+ vtophys(src);
+ pa2 = (flags & DST_IS_USER) ?
+ pmap_extract(pmap, (vm_offset_t)dst) :
+ vtophys(dst);
+ to_nextpagesrc = ((vm_offset_t)src & ~PAGE_MASK) +
+ PAGE_SIZE - (vm_offset_t)src;
+ to_nextpagedst = ((vm_offset_t)dst & ~PAGE_MASK) +
+ PAGE_SIZE - (vm_offset_t)dst;
+ while (to_nextpagesrc < tmplen) {
+ tmppa = (flags & SRC_IS_USER) ?
+ pmap_extract(pmap, (vm_offset_t)src +
+ to_nextpagesrc) :
+ vtophys((vm_offset_t)src +
+ to_nextpagesrc);
+ if (tmppa != pa + to_nextpagesrc)
+ break;
+ to_nextpagesrc += PAGE_SIZE;
+ }
+ while (to_nextpagedst < tmplen) {
+ tmppa = (flags & DST_IS_USER) ?
+ pmap_extract(pmap, (vm_offset_t)dst +
+ to_nextpagedst) :
+ vtophys((vm_offset_t)dst +
+ to_nextpagedst);
+ if (tmppa != pa2 + to_nextpagedst)
+ break;
+ to_nextpagedst += PAGE_SIZE;
+ }
+ min_hop = to_nextpagedst > to_nextpagesrc ?
+ to_nextpagesrc : to_nextpagedst;
+ if (min_hop < 64) {
+ tmplen -= min_hop;
+ memcpy(dst, src, min_hop);
+ cpu_dcache_wbinv_range((vm_offset_t)dst,
+ min_hop);
+
+ src = (void *)((vm_offset_t)src + min_hop);
+ dst = (void *)((vm_offset_t)dst + min_hop);
+ if (tmplen <= 0 && descnb > 0) {
+ sc->dmaring[descnb - 1].desc->next_desc
+ = 0;
+ bus_dmamap_sync(sc->dmatag,
+ sc->dmaring[descnb - 1].map,
+ BUS_DMASYNC_PREWRITE);
+ }
+ continue;
+ }
+ desc->low_pciaddr = pa;
+ desc->high_pciaddr = 0;
+ desc->local_addr = pa2;
+ desc->count = tmplen > min_hop ? min_hop : tmplen;
+ desc->descr_ctrl = 1 << 6;
+ if (min_hop < tmplen) {
+ tmplen -= min_hop;
+ src = (void *)((vm_offset_t)src + min_hop);
+ dst = (void *)((vm_offset_t)dst + min_hop);
+ } else
+ tmplen = 0;
+ if (descnb + 1 >= DMA_RING_SIZE) {
+ mtx_lock_spin(&sc->mtx);
+ sc->flags &= ~BUSY;
+ mtx_unlock_spin(&sc->mtx);
+ return (-1);
+ }
+ if (tmplen > 0) {
+ desc->next_desc = sc->dmaring[descnb + 1].
+ phys_addr;
+ bus_dmamap_sync(sc->dmatag,
+ sc->dmaring[descnb].map,
+ BUS_DMASYNC_PREWRITE);
+ desc = sc->dmaring[descnb + 1].desc;
+ descnb++;
+ } else {
+ desc->next_desc = 0;
+ bus_dmamap_sync(sc->dmatag,
+ sc->dmaring[descnb].map,
+ BUS_DMASYNC_PREWRITE);
+ }
+
+ }
+
+ }
+ DMA_REG_WRITE(sc, 4 /* Status register */,
+ DMA_REG_READ(sc, 4) | DMA_CLEAN_MASK);
+ DMA_REG_WRITE(sc, 0x10 /* Descriptor addr */,
+ sc->dmaring[0].phys_addr);
+ DMA_REG_WRITE(sc, 0 /* Control register */, 1 | 2/* Start transfer */);
+ while ((csr = DMA_REG_READ(sc, 0x4)) & (1 << 10));
+ /* Wait until it's done. */
+ if (csr & 0x2e) /* error */
+ ret = -1;
+ else
+ ret = 0;
+ DMA_REG_WRITE(sc, 0, 0);
+ mtx_lock_spin(&sc->mtx);
+ sc->flags &= ~BUSY;
+ mtx_unlock_spin(&sc->mtx);
+ return (ret);
+}
+
+static device_method_t i80321_dma_methods[] = {
+ DEVMETHOD(device_probe, i80321_dma_probe),
+ DEVMETHOD(device_attach, i80321_dma_attach),
+ {0, 0},
+};
+
+static driver_t i80321_dma_driver = {
+ "i80321_dma",
+ i80321_dma_methods,
+ sizeof(struct i80321_dma_softc),
+};
+
+static devclass_t i80321_dma_devclass;
+
+DRIVER_MODULE(i80321_dma, iq, i80321_dma_driver, i80321_dma_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i80321/i80321_dma.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321_intr.h
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321_intr.h (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321_intr.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,166 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321_intr.h,v 1.5 2004/01/12 10:25:06 scw Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/i80321/i80321_intr.h 278613 2015-02-12 03:50:33Z ian $
+ *
+ */
+
+#ifndef _I80321_INTR_H_
+#define _I80321_INTR_H_
+
+#define ARM_IRQ_HANDLER _C_LABEL(i80321_intr_dispatch)
+
+#ifndef _LOCORE
+
+#include <machine/armreg.h>
+#include <machine/cpufunc.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+
+void i80321_do_pending(void);
+
+extern __volatile uint32_t intr_enabled;
+extern uint32_t intr_steer;
+
+static __inline void __attribute__((__unused__))
+i80321_set_intrmask(void)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c0, c0, 0"
+ :
+ : "r" (intr_enabled & ICU_INT_HWMASK));
+}
+
+static __inline void
+i80321_set_intrsteer(void)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c4, c0, 0"
+ :
+ : "r" (intr_steer & ICU_INT_HWMASK));
+}
+
+#if defined ( CPU_XSCALE_80219 )
+#define INT_SWMASK \
+ ((1U << ICU_INT_bit26) | \
+ (1U << ICU_INT_bit25) | \
+ (1U << ICU_INT_bit23) | \
+ (1U << ICU_INT_bit22) | \
+ (1U << ICU_INT_bit7) | \
+ (1U << ICU_INT_bit6) | \
+ (1U << ICU_INT_bit5) | \
+ (1U << ICU_INT_bit4))
+#else
+#define INT_SWMASK \
+ ((1U << ICU_INT_bit26) | (1U << ICU_INT_bit22) | \
+ (1U << ICU_INT_bit5) | (1U << ICU_INT_bit4))
+#endif
+
+#if 0
+static __inline void __attribute__((__unused__))
+i80321_splx(int new)
+{
+ extern __volatile uint32_t intr_enabled;
+ extern __volatile int current_spl_level;
+ extern __volatile int i80321_ipending;
+ extern void i80321_do_pending(void);
+ int oldirqstate, hwpend;
+
+ /* Don't let the compiler re-order this code with preceding code */
+ __insn_barrier();
+
+ current_spl_level = new;
+
+ hwpend = (i80321_ipending & ICU_INT_HWMASK) & ~new;
+ if (hwpend != 0) {
+ oldirqstate = disable_interrupts(PSR_I);
+ intr_enabled |= hwpend;
+ i80321_set_intrmask();
+ restore_interrupts(oldirqstate);
+ }
+
+ if ((i80321_ipending & INT_SWMASK) & ~new)
+ i80321_do_pending();
+}
+
+static __inline int __attribute__((__unused__))
+i80321_splraise(int ipl)
+{
+ extern __volatile int current_spl_level;
+ extern int i80321_imask[];
+ int old;
+
+ old = current_spl_level;
+ current_spl_level |= i80321_imask[ipl];
+
+ /* Don't let the compiler re-order this code with subsequent code */
+ __insn_barrier();
+
+ return (old);
+}
+
+static __inline int __attribute__((__unused__))
+i80321_spllower(int ipl)
+{
+ extern __volatile int current_spl_level;
+ extern int i80321_imask[];
+ int old = current_spl_level;
+
+ i80321_splx(i80321_imask[ipl]);
+ return(old);
+}
+
+#endif
+#if !defined(EVBARM_SPL_NOINLINE)
+
+#define splx(new) i80321_splx(new)
+#define _spllower(ipl) i80321_spllower(ipl)
+#define _splraise(ipl) i80321_splraise(ipl)
+void _setsoftintr(int);
+
+#else
+
+int _splraise(int);
+int _spllower(int);
+void splx(int);
+void _setsoftintr(int);
+
+#endif /* ! EVBARM_SPL_NOINLINE */
+
+#endif /* _LOCORE */
+
+#endif /* _I80321_INTR_H_ */
Property changes on: trunk/sys/arm/xscale/i80321/i80321_intr.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321_mcu.c
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321_mcu.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321_mcu.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,91 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321_mcu.c,v 1.2 2003/07/15 00:24:54 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Intel i80321 I/O Processor memory controller support.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/i80321_mcu.c 139735 2005-01-05 21:58:49Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+
+/*
+ * i80321_sdram_bounds:
+ *
+ * Retrieve the start and size of SDRAM.
+ */
+void
+i80321_sdram_bounds(bus_space_tag_t st, bus_space_handle_t sh,
+ vm_paddr_t *start, vm_size_t *size)
+{
+ uint32_t sdbr, sbr0, sbr1;
+ uint32_t bank0, bank1;
+
+ sdbr = bus_space_read_4(st, sh, MCU_SDBR);
+ sbr0 = bus_space_read_4(st, sh, MCU_SBR0);
+ sbr1 = bus_space_read_4(st, sh, MCU_SBR1);
+
+#ifdef VERBOSE_INIT_ARM
+ printf("i80321: SBDR = 0x%08x SBR0 = 0x%08x SBR1 = 0x%08x\n",
+ sdbr, sbr0, sbr1);
+#endif
+
+ *start = sdbr;
+
+ sdbr = (sdbr >> 25) & 0x1f;
+
+ sbr0 &= 0x3f;
+ sbr1 &= 0x3f;
+
+ bank0 = (sbr0 - sdbr) << 25;
+ bank1 = (sbr1 - sbr0) << 25;
+
+#ifdef VERBOSE_INIT_ARM
+ printf("i80321: BANK0 = 0x%08x BANK1 = 0x%08x\n", bank0, bank1);
+#endif
+
+ *size = bank0 + bank1;
+}
Property changes on: trunk/sys/arm/xscale/i80321/i80321_mcu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321_pci.c
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321_pci.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321_pci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,402 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321_pci.c,v 1.4 2003/07/15 00:24:54 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * PCI configuration support for i80321 I/O Processor chip.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/i80321_pci.c 259329 2013-12-13 20:43:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/pcb.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i80321/i80321_intr.h>
+
+#include <dev/pci/pcib_private.h>
+#include "pcib_if.h"
+
+#include <dev/pci/pcireg.h>
+extern struct i80321_softc *i80321_softc;
+
+static int
+i80321_pci_probe(device_t dev)
+{
+ device_set_desc(dev, "i80321 PCI bus");
+ return (0);
+}
+
+static int
+i80321_pci_attach(device_t dev)
+{
+
+ uint32_t busno;
+ struct i80321_pci_softc *sc = device_get_softc(dev);
+
+ sc->sc_st = i80321_softc->sc_st;
+ sc->sc_atu_sh = i80321_softc->sc_atu_sh;
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
+ busno = PCIXSR_BUSNO(busno);
+ if (busno == 0xff)
+ busno = 0;
+ sc->sc_dev = dev;
+ sc->sc_busno = busno;
+ sc->sc_pciio = &i80321_softc->sc_pci_iot;
+ sc->sc_pcimem = &i80321_softc->sc_pci_memt;
+ sc->sc_mem = i80321_softc->sc_owin[0].owin_xlate_lo +
+ VERDE_OUT_XLATE_MEM_WIN_SIZE;
+
+ sc->sc_io = i80321_softc->sc_iow_vaddr;
+ /* Initialize memory and i/o rmans. */
+ sc->sc_io_rman.rm_type = RMAN_ARRAY;
+ sc->sc_io_rman.rm_descr = "I80321 PCI I/O Ports";
+ if (rman_init(&sc->sc_io_rman) != 0 ||
+ rman_manage_region(&sc->sc_io_rman,
+ sc->sc_io,
+ sc->sc_io +
+ VERDE_OUT_XLATE_IO_WIN_SIZE) != 0) {
+ panic("i80321_pci_probe: failed to set up I/O rman");
+ }
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "I80321 PCI Memory";
+ if (rman_init(&sc->sc_mem_rman) != 0 ||
+ rman_manage_region(&sc->sc_mem_rman,
+ 0, VERDE_OUT_XLATE_MEM_WIN_SIZE) != 0) {
+ panic("i80321_pci_probe: failed to set up memory rman");
+ }
+ sc->sc_irq_rman.rm_type = RMAN_ARRAY;
+ sc->sc_irq_rman.rm_descr = "i80321 PCI IRQs";
+ if (rman_init(&sc->sc_irq_rman) != 0 ||
+ rman_manage_region(&sc->sc_irq_rman, 26, 32) != 0)
+ panic("i80321_pci_probe: failed to set up IRQ rman");
+ device_add_child(dev, "pci",busno);
+ return (bus_generic_attach(dev));
+}
+
+static int
+i80321_pci_maxslots(device_t dev)
+{
+ return (PCI_SLOTMAX);
+}
+
+
+
+static int
+i80321_pci_conf_setup(struct i80321_pci_softc *sc, int bus, int slot, int func,
+ int reg, uint32_t *addr)
+{
+ uint32_t busno;
+
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
+ busno = PCIXSR_BUSNO(busno);
+ if (busno == 0xff)
+ busno = 0;
+
+ /*
+ * If the bus # is the same as our own, then use Type 0 cycles,
+ * else use Type 1.
+ *
+ * XXX We should filter out all non-private devices here!
+ * XXX How does private space interact with PCI-PCI bridges?
+ */
+ if (bus == busno) {
+ if (slot > (31 - 16))
+ return (1);
+ /*
+ * NOTE: PCI-X requires that that devices updated their
+ * PCIXSR on every config write with the device number
+ * specified in AD[15:11]. If we don't set this field,
+ * each device could end of thinking it is at device 0,
+ * which can cause a number of problems. Doing this
+ * unconditionally should be OK when only PCI devices
+ * are present.
+ */
+ bus &= 0xff;
+ slot &= 0x1f;
+ func &= 0x07;
+
+ *addr = (1U << (slot + 16)) |
+ (slot << 11) | (func << 8) | reg;
+ } else {
+ *addr = (bus << 16) | (slot << 11) | (func << 8) | reg | 1;
+ }
+
+ return (0);
+}
+
+static u_int32_t
+i80321_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, int bytes)
+{
+ struct i80321_pci_softc *sc = device_get_softc(dev);
+ uint32_t isr;
+ uint32_t addr;
+ u_int32_t ret = 0;
+ vm_offset_t va;
+ int err = 0;
+ if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr))
+ return (-1);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR,
+ addr);
+
+ va = sc->sc_atu_sh;
+ switch (bytes) {
+ case 1:
+ err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 1, &ret);
+ break;
+ case 2:
+ err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 2, &ret);
+ break;
+ case 4:
+ err = badaddr_read((void *)(va + ATU_OCCDR), 4, &ret);
+ break;
+ default:
+ printf("i80321_read_config: invalid size %d\n", bytes);
+ ret = -1;
+ }
+ if (err) {
+
+ isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR,
+ isr & (ATUISR_P_SERR_DET|ATUISR_PMA|ATUISR_PTAM|
+ ATUISR_PTAT|ATUISR_PMPE));
+ return (-1);
+ }
+ return (ret);
+}
+
+static void
+i80321_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, u_int32_t data, int bytes)
+{
+ struct i80321_pci_softc *sc = device_get_softc(dev);
+ uint32_t addr;
+
+ if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr))
+ return;
+
+
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR,
+ addr);
+ switch (bytes) {
+ case 1:
+ bus_space_write_1(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR +
+ (reg & 3), data);
+ break;
+ case 2:
+ bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR +
+ (reg & 3), data);
+ break;
+ case 4:
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR, data);
+ break;
+ default:
+ printf("i80321_pci_write_config: Invalid size : %d\n", bytes);
+ }
+
+}
+
+static int
+i80321_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct i80321_pci_softc *sc = device_get_softc(dev);
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = 0;
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_busno;
+ return (0);
+
+ }
+ return (ENOENT);
+}
+
+static int
+i80321_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
+{
+ struct i80321_pci_softc * sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ return (EINVAL);
+ case PCIB_IVAR_BUS:
+ sc->sc_busno = result;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+static struct resource *
+i80321_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct i80321_pci_softc *sc = device_get_softc(bus);
+ struct resource *rv;
+ struct rman *rm;
+ bus_space_tag_t bt = NULL;
+ bus_space_handle_t bh = 0;
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ rm = &sc->sc_irq_rman;
+ break;
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_mem_rman;
+ bt = sc->sc_pcimem;
+ bh = (start >= 0x80000000 && start < 0x84000000) ? 0x80000000 :
+ sc->sc_mem;
+ start &= (0x1000000 - 1);
+ end &= (0x1000000 - 1);
+ break;
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io_rman;
+ bt = sc->sc_pciio;
+ bh = sc->sc_io;
+ if (start < sc->sc_io) {
+ start = start - 0x90000000 + sc->sc_io;
+ end = end - 0x90000000 + sc->sc_io;
+ }
+ break;
+ default:
+ return (NULL);
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == NULL)
+ return (NULL);
+ rman_set_rid(rv, *rid);
+ if (type != SYS_RES_IRQ) {
+ if (type == SYS_RES_MEMORY)
+ bh += (rman_get_start(rv));
+ rman_set_bustag(rv, bt);
+ rman_set_bushandle(rv, bh);
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+ }
+ return (rv);
+}
+
+static int
+i80321_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ u_long p;
+ int error;
+
+ if (type == SYS_RES_MEMORY) {
+ error = bus_space_map(rman_get_bustag(r),
+ rman_get_bushandle(r), rman_get_size(r), 0, &p);
+ if (error)
+ return (error);
+ rman_set_bushandle(r, p);
+
+ }
+ return (rman_activate_resource(r));
+}
+
+static int
+i80321_pci_setup_intr(device_t dev, device_t child,
+ struct resource *ires, int flags, driver_filter_t *filt,
+ driver_intr_t *intr, void *arg, void **cookiep)
+{
+ return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ filt, intr, arg, cookiep));
+}
+
+static int
+i80321_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
+static device_method_t i80321_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, i80321_pci_probe),
+ DEVMETHOD(device_attach, i80321_pci_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, i80321_read_ivar),
+ DEVMETHOD(bus_write_ivar, i80321_write_ivar),
+ DEVMETHOD(bus_alloc_resource, i80321_pci_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, i80321_pci_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, i80321_pci_setup_intr),
+ DEVMETHOD(bus_teardown_intr, i80321_pci_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, i80321_pci_maxslots),
+ DEVMETHOD(pcib_read_config, i80321_pci_read_config),
+ DEVMETHOD(pcib_write_config, i80321_pci_write_config),
+ DEVMETHOD(pcib_route_interrupt, machdep_pci_route_interrupt),
+
+ DEVMETHOD_END
+};
+
+static driver_t i80321_pci_driver = {
+ "pcib",
+ i80321_pci_methods,
+ sizeof(struct i80321_pci_softc),
+};
+
+static devclass_t i80321_pci_devclass;
+
+DRIVER_MODULE(ipci, iq, i80321_pci_driver, i80321_pci_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i80321/i80321_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321_space.c
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321_space.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321_space.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,210 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321_space.c,v 1.6 2003/10/06 15:43:35 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * bus_space functions for i80321 I/O Processor.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/i80321_space.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/pcb.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(i80321);
+bs_protos(i80321_io);
+bs_protos(i80321_mem);
+
+void
+i80321_bs_init(bus_space_tag_t bs, void *cookie)
+{
+
+ *bs = *arm_base_bs_tag;
+ bs->bs_privdata = cookie;
+}
+
+void
+i80321_io_bs_init(bus_space_tag_t bs, void *cookie)
+{
+
+ *bs = *arm_base_bs_tag;
+ bs->bs_privdata = cookie;
+
+ bs->bs_map = i80321_io_bs_map;
+ bs->bs_unmap = i80321_io_bs_unmap;
+ bs->bs_alloc = i80321_io_bs_alloc;
+ bs->bs_free = i80321_io_bs_free;
+
+}
+
+void
+i80321_mem_bs_init(bus_space_tag_t bs, void *cookie)
+{
+
+ *bs = *arm_base_bs_tag;
+ bs->bs_privdata = cookie;
+
+ bs->bs_map = i80321_mem_bs_map;
+ bs->bs_unmap = i80321_mem_bs_unmap;
+ bs->bs_alloc = i80321_mem_bs_alloc;
+ bs->bs_free = i80321_mem_bs_free;
+
+}
+
+/* *** Routines shared by i80321, PCI IO, and PCI MEM. *** */
+
+int
+i80321_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t size, bus_space_handle_t *nbshp)
+{
+
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+void
+i80321_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t len, int flags)
+{
+
+ /* Nothing to do. */
+}
+
+/* *** Routines for PCI IO. *** */
+
+extern struct i80321_softc *i80321_softc;
+int
+i80321_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ struct i80321_softc *sc = i80321_softc;
+ vm_offset_t winvaddr;
+ uint32_t busbase;
+
+ if (bpa >= sc->sc_ioout_xlate &&
+ bpa < (sc->sc_ioout_xlate + VERDE_OUT_XLATE_IO_WIN_SIZE)) {
+ busbase = sc->sc_ioout_xlate;
+ winvaddr = sc->sc_iow_vaddr;
+ } else
+ return (EINVAL);
+
+ if ((bpa + size) >= (busbase + VERDE_OUT_XLATE_IO_WIN_SIZE))
+ return (EINVAL);
+
+ /*
+ * Found the window -- PCI I/O space is mapped at a fixed
+ * virtual address by board-specific code. Translate the
+ * bus address to the virtual address.
+ */
+ *bshp = winvaddr + (bpa - busbase);
+
+ return (0);
+}
+
+void
+i80321_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
+{
+
+ /* Nothing to do. */
+}
+
+int
+i80321_io_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
+ bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+
+ panic("i80321_io_bs_alloc(): not implemented");
+}
+
+void
+i80321_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
+{
+
+ panic("i80321_io_bs_free(): not implemented");
+}
+
+
+/* *** Routines for PCI MEM. *** */
+extern int badaddr_read(void *, int, void *);
+int
+i80321_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+
+ *bshp = (vm_offset_t)pmap_mapdev(bpa, size);
+ return (0);
+}
+
+void
+i80321_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
+{
+
+ pmap_unmapdev((vm_offset_t)h, size);
+}
+
+int
+i80321_mem_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
+ bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+
+ panic("i80321_mem_bs_alloc(): not implemented");
+}
+
+void
+i80321_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
+{
+
+ panic("i80321_mem_bs_free(): not implemented");
+}
Property changes on: trunk/sys/arm/xscale/i80321/i80321_space.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321_timer.c
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321_timer.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321_timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,486 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321_timer.c,v 1.7 2003/07/27 04:52:28 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Timer/clock support for the Intel i80321 I/O processor.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/i80321_timer.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+
+#ifdef CPU_XSCALE_81342
+#define ICU_INT_TIMER0 (8) /* XXX: Can't include i81342reg.h because
+ definitions overrides the ones from i80321reg.h
+ */
+#endif
+#include "opt_timer.h"
+
+void (*i80321_hardclock_hook)(void) = NULL;
+struct i80321_timer_softc {
+ device_t dev;
+} timer_softc;
+
+
+static unsigned i80321_timer_get_timecount(struct timecounter *tc);
+
+
+static uint32_t counts_per_hz;
+
+#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342)
+static uint32_t offset;
+static uint32_t last = -1;
+#endif
+
+static int ticked = 0;
+
+#ifndef COUNTS_PER_SEC
+#define COUNTS_PER_SEC 200000000 /* 200MHz */
+#endif
+
+#define COUNTS_PER_USEC (COUNTS_PER_SEC / 1000000)
+
+static struct timecounter i80321_timer_timecounter = {
+ i80321_timer_get_timecount, /* get_timecount */
+ NULL, /* no poll_pps */
+ ~0u, /* counter_mask */
+#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342)
+ COUNTS_PER_SEC,
+#else
+ COUNTS_PER_SEC * 3, /* frequency */
+#endif
+ "i80321 timer", /* name */
+ 1000 /* quality */
+};
+
+static int
+i80321_timer_probe(device_t dev)
+{
+
+ device_set_desc(dev, "i80321 timer");
+ return (0);
+}
+
+static int
+i80321_timer_attach(device_t dev)
+{
+ timer_softc.dev = dev;
+
+ return (0);
+}
+
+static device_method_t i80321_timer_methods[] = {
+ DEVMETHOD(device_probe, i80321_timer_probe),
+ DEVMETHOD(device_attach, i80321_timer_attach),
+ {0, 0},
+};
+
+static driver_t i80321_timer_driver = {
+ "itimer",
+ i80321_timer_methods,
+ sizeof(struct i80321_timer_softc),
+};
+static devclass_t i80321_timer_devclass;
+
+DRIVER_MODULE(itimer, iq, i80321_timer_driver, i80321_timer_devclass, 0, 0);
+
+int clockhandler(void *);
+
+
+static __inline uint32_t
+tmr1_read(void)
+{
+ uint32_t rv;
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mrc p6, 0, %0, c1, c9, 0"
+#else
+ __asm __volatile("mrc p6, 0, %0, c1, c1, 0"
+#endif
+ : "=r" (rv));
+ return (rv);
+}
+
+static __inline void
+tmr1_write(uint32_t val)
+{
+
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mcr p6, 0, %0, c1, c9, 0"
+#else
+ __asm __volatile("mcr p6, 0, %0, c1, c1, 0"
+#endif
+ :
+ : "r" (val));
+}
+
+static __inline uint32_t
+tcr1_read(void)
+{
+ uint32_t rv;
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mrc p6, 0, %0, c3, c9, 0"
+#else
+ __asm __volatile("mrc p6, 0, %0, c3, c1, 0"
+#endif
+ : "=r" (rv));
+ return (rv);
+}
+static __inline void
+tcr1_write(uint32_t val)
+{
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mcr p6, 0, %0, c3, c9, 0"
+#else
+ __asm __volatile("mcr p6, 0, %0, c3, c1, 0"
+#endif
+ :
+ : "r" (val));
+}
+
+static __inline void
+trr1_write(uint32_t val)
+{
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mcr p6, 0, %0, c5, c9, 0"
+#else
+ __asm __volatile("mcr p6, 0, %0, c5, c1, 0"
+#endif
+ :
+ : "r" (val));
+}
+
+static __inline uint32_t
+tmr0_read(void)
+{
+ uint32_t rv;
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mrc p6, 0, %0, c0, c9, 0"
+#else
+ __asm __volatile("mrc p6, 0, %0, c0, c1, 0"
+#endif
+ : "=r" (rv));
+ return (rv);
+}
+
+static __inline void
+tmr0_write(uint32_t val)
+{
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mcr p6, 0, %0, c0, c9, 0"
+#else
+ __asm __volatile("mcr p6, 0, %0, c0, c1, 0"
+#endif
+ :
+ : "r" (val));
+}
+
+static __inline uint32_t
+tcr0_read(void)
+{
+ uint32_t rv;
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mrc p6, 0, %0, c2, c9, 0"
+#else
+ __asm __volatile("mrc p6, 0, %0, c2, c1, 0"
+#endif
+ : "=r" (rv));
+ return (rv);
+}
+static __inline void
+tcr0_write(uint32_t val)
+{
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mcr p6, 0, %0, c2, c9, 0"
+#else
+ __asm __volatile("mcr p6, 0, %0, c2, c1, 0"
+#endif
+ :
+ : "r" (val));
+}
+
+static __inline void
+trr0_write(uint32_t val)
+{
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mcr p6, 0, %0, c4, c9, 0"
+#else
+ __asm __volatile("mcr p6, 0, %0, c4, c1, 0"
+#endif
+ :
+ : "r" (val));
+}
+
+static __inline void
+tisr_write(uint32_t val)
+{
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mcr p6, 0, %0, c6, c9, 0"
+#else
+ __asm __volatile("mcr p6, 0, %0, c6, c1, 0"
+#endif
+ :
+ : "r" (val));
+}
+
+static __inline uint32_t
+tisr_read(void)
+{
+ int ret;
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mrc p6, 0, %0, c6, c9, 0" : "=r" (ret));
+#else
+ __asm __volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (ret));
+#endif
+ return (ret);
+}
+
+static unsigned
+i80321_timer_get_timecount(struct timecounter *tc)
+{
+#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342)
+ uint32_t cur = tcr0_read();
+
+ if (cur > last && last != -1) {
+ offset += counts_per_hz;
+ if (ticked > 0)
+ ticked--;
+ }
+ if (ticked) {
+ offset += ticked * counts_per_hz;
+ ticked = 0;
+ }
+ return (counts_per_hz - cur + offset);
+#else
+ uint32_t ret;
+
+ __asm __volatile("mrc p14, 0, %0, c1, c0, 0\n"
+ : "=r" (ret));
+ return (ret);
+#endif
+}
+
+/*
+ * i80321_calibrate_delay:
+ *
+ * Calibrate the delay loop.
+ */
+void
+i80321_calibrate_delay(void)
+{
+
+ /*
+ * Just use hz=100 for now -- we'll adjust it, if necessary,
+ * in cpu_initclocks().
+ */
+ counts_per_hz = COUNTS_PER_SEC / 100;
+
+ tmr0_write(0); /* stop timer */
+ tisr_write(TISR_TMR0); /* clear interrupt */
+ trr0_write(counts_per_hz); /* reload value */
+ tcr0_write(counts_per_hz); /* current value */
+
+ tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE);
+}
+
+/*
+ * cpu_initclocks:
+ *
+ * Initialize the clock and get them going.
+ */
+void
+cpu_initclocks(void)
+{
+ u_int oldirqstate;
+ struct resource *irq;
+ int rid = 0;
+ void *ihl;
+ device_t dev = timer_softc.dev;
+
+ if (hz < 50 || COUNTS_PER_SEC % hz) {
+ printf("Cannot get %d Hz clock; using 100 Hz\n", hz);
+ hz = 100;
+ }
+ tick = 1000000 / hz; /* number of microseconds between interrupts */
+
+ /*
+ * We only have one timer available; stathz and profhz are
+ * always left as 0 (the upper-layer clock code deals with
+ * this situation).
+ */
+ if (stathz != 0)
+ printf("Cannot get %d Hz statclock\n", stathz);
+ stathz = 0;
+
+ if (profhz != 0)
+ printf("Cannot get %d Hz profclock\n", profhz);
+ profhz = 0;
+
+ /* Report the clock frequency. */
+
+ oldirqstate = disable_interrupts(PSR_I);
+
+ irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+#ifdef CPU_XSCALE_81342
+ ICU_INT_TIMER0, ICU_INT_TIMER0,
+#else
+ ICU_INT_TMR0, ICU_INT_TMR0,
+#endif
+ 1, RF_ACTIVE);
+ if (!irq)
+ panic("Unable to setup the clock irq handler.\n");
+ else
+ bus_setup_intr(dev, irq, INTR_TYPE_CLK, clockhandler, NULL,
+ NULL, &ihl);
+ tmr0_write(0); /* stop timer */
+ tisr_write(TISR_TMR0); /* clear interrupt */
+
+ counts_per_hz = COUNTS_PER_SEC / hz;
+
+ trr0_write(counts_per_hz); /* reload value */
+ tcr0_write(counts_per_hz); /* current value */
+ tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE);
+
+ tc_init(&i80321_timer_timecounter);
+ restore_interrupts(oldirqstate);
+ rid = 0;
+#if !defined(XSCALE_DISABLE_CCNT) && !defined(CPU_XSCALE_81342)
+ /* Enable the clock count register. */
+ __asm __volatile("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (rid));
+ rid &= ~(1 << 3);
+ rid |= (1 << 2) | 1;
+ __asm __volatile("mcr p14, 0, %0, c0, c0, 0\n"
+ : : "r" (rid));
+#endif
+}
+
+
+/*
+ * DELAY:
+ *
+ * Delay for at least N microseconds.
+ */
+void
+DELAY(int n)
+{
+ uint32_t cur, last, delta, usecs;
+
+ /*
+ * This works by polling the timer and counting the
+ * number of microseconds that go by.
+ */
+ last = tcr0_read();
+ delta = usecs = 0;
+
+ while (n > usecs) {
+ cur = tcr0_read();
+
+ /* Check to see if the timer has wrapped around. */
+ if (last < cur)
+ delta += (last + (counts_per_hz - cur));
+ else
+ delta += (last - cur);
+
+ last = cur;
+
+ if (delta >= COUNTS_PER_USEC) {
+ usecs += delta / COUNTS_PER_USEC;
+ delta %= COUNTS_PER_USEC;
+ }
+ }
+}
+
+/*
+ * clockhandler:
+ *
+ * Handle the hardclock interrupt.
+ */
+int
+clockhandler(void *arg)
+{
+ struct trapframe *frame = arg;
+
+ ticked++;
+ tisr_write(TISR_TMR0);
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+
+ if (i80321_hardclock_hook != NULL)
+ (*i80321_hardclock_hook)();
+ return (FILTER_HANDLED);
+}
+
+void
+cpu_startprofclock(void)
+{
+}
+
+void
+cpu_stopprofclock(void)
+{
+
+}
Property changes on: trunk/sys/arm/xscale/i80321/i80321_timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321_wdog.c
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321_wdog.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321_wdog.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,155 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321_wdog.c,v 1.6 2003/07/15 00:24:54 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2005 Olivier Houchard
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Watchdog timer support for the Intel i80321 I/O processor.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/i80321_wdog.c 171627 2007-07-27 14:52:04Z cognet $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/watchdog.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <machine/machdep.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+
+
+struct iopwdog_softc {
+ device_t dev;
+ int armed;
+ int wdog_period;
+};
+
+static __inline void
+wdtcr_write(uint32_t val)
+{
+
+#ifdef CPU_XSCALE_81342
+ __asm __volatile("mcr p6, 0, %0, c7, c9, 0"
+#else
+ __asm __volatile("mcr p6, 0, %0, c7, c1, 0"
+#endif
+ :
+ : "r" (val));
+}
+
+static void
+iopwdog_tickle(void *arg)
+{
+ struct iopwdog_softc *sc = arg;
+
+ if (!sc->armed)
+ return;
+ wdtcr_write(WDTCR_ENABLE1);
+ wdtcr_write(WDTCR_ENABLE2);
+}
+
+static int
+iopwdog_probe(device_t dev)
+{
+ struct iopwdog_softc *sc = device_get_softc(dev);
+ char buf[128];
+
+ /*
+ * XXX Should compute the period based on processor speed.
+ * For a 600MHz XScale core, the wdog must be tickled approx.
+ * every 7 seconds.
+ */
+
+ sc->wdog_period = 7;
+ sprintf(buf, "i80321 Watchdog, must be tickled every %d seconds",
+ sc->wdog_period);
+ device_set_desc_copy(dev, buf);
+
+ return (0);
+}
+
+static void
+iopwdog_watchdog_fn(void *private, u_int cmd, int *error)
+{
+ struct iopwdog_softc *sc = private;
+
+ cmd &= WD_INTERVAL;
+ if (cmd > 0 && cmd <= 63
+ && (uint64_t)1<<cmd <= (uint64_t)sc->wdog_period * 1000000000) {
+ /* Valid value -> Enable watchdog */
+ iopwdog_tickle(sc);
+ sc->armed = 1;
+ *error = 0;
+ } else {
+ /* Can't disable this watchdog! */
+ if (sc->armed)
+ *error = EOPNOTSUPP;
+ }
+}
+
+static int
+iopwdog_attach(device_t dev)
+{
+ struct iopwdog_softc *sc = device_get_softc(dev);
+
+ sc->dev = dev;
+ sc->armed = 0;
+ EVENTHANDLER_REGISTER(watchdog_list, iopwdog_watchdog_fn, sc, 0);
+ return (0);
+}
+
+static device_method_t iopwdog_methods[] = {
+ DEVMETHOD(device_probe, iopwdog_probe),
+ DEVMETHOD(device_attach, iopwdog_attach),
+ {0, 0},
+};
+
+static driver_t iopwdog_driver = {
+ "iopwdog",
+ iopwdog_methods,
+ sizeof(struct iopwdog_softc),
+};
+static devclass_t iopwdog_devclass;
+
+DRIVER_MODULE(iopwdog, iq, iopwdog_driver, iopwdog_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i80321/i80321_wdog.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321reg.h
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321reg.h (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,548 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321reg.h,v 1.14 2003/12/19 10:08:11 gavan Exp $ */
+
+/*-
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/i80321/i80321reg.h 236987 2012-06-13 04:38:09Z imp $
+ *
+ */
+
+#ifndef _ARM_XSCALE_I80321REG_H_
+#define _ARM_XSCALE_I80321REG_H_
+
+/*
+ * Register definitions for the Intel 80321 (``Verde'') I/O processor,
+ * based on the XScale core.
+ */
+
+/*
+ * Base i80321 memory map:
+ *
+ * 0x0000.0000 - 0x7fff.ffff ATU Outbound Direct Addressing Window
+ * 0x8000.0000 - 0x9001.ffff ATU Outbound Translation Windows
+ * 0x9002.0000 - 0xffff.dfff External Memory
+ * 0xffff.e000 - 0xffff.e8ff Peripheral Memory Mapped Registers
+ * 0xffff.e900 - 0xffff.ffff Reserved
+ */
+
+#define VERDE_OUT_DIRECT_WIN_BASE 0x00000000UL
+#define VERDE_OUT_DIRECT_WIN_SIZE 0x80000000UL
+
+#define VERDE_OUT_XLATE_MEM_WIN_SIZE 0x04000000UL
+#define VERDE_OUT_XLATE_IO_WIN_SIZE 0x00010000UL
+
+#define VERDE_OUT_XLATE_MEM_WIN0_BASE 0x80000000UL
+#define VERDE_OUT_XLATE_MEM_WIN1_BASE 0x84000000UL
+
+#define VERDE_OUT_XLATE_IO_WIN0_BASE 0x90000000UL
+
+#define VERDE_EXTMEM_BASE 0x90020000UL
+
+#define VERDE_PMMR_BASE 0xffffe000UL
+#define VERDE_PMMR_SIZE 0x00001700UL
+
+/*
+ * Peripheral Memory Mapped Registers. Defined as offsets
+ * from the VERDE_PMMR_BASE.
+ */
+#define VERDE_ATU_BASE 0x0100
+#define VERDE_ATU_SIZE 0x0100
+
+#define VERDE_MU_BASE 0x0300
+#define VERDE_MU_SIZE 0x0100
+
+#define VERDE_DMA_BASE 0x0400
+#define VERDE_DMA_BASE0 (VERDE_DMA_BASE + 0x00)
+#define VERDE_DMA_BASE1 (VERDE_DMA_BASE + 0x40)
+#define VERDE_DMA_SIZE 0x0100
+#define VERDE_DMA_CHSIZE 0x0040
+
+#define VERDE_MCU_BASE 0x0500
+#define VERDE_MCU_SIZE 0x0100
+
+#if defined(CPU_XSCALE_80321)
+#define VERDE_SSP_BASE 0x0600
+#define VERDE_SSP_SIZE 0x0080
+#endif
+
+#define VERDE_PBIU_BASE 0x0680
+#define VERDE_PBIU_SIZE 0x0080
+
+#if defined(CPU_XSCALE_80321)
+#define VERDE_AAU_BASE 0x0800
+#define VERDE_AAU_SIZE 0x0100
+#endif
+
+#define VERDE_I2C_BASE 0x1680
+#define VERDE_I2C_BASE0 (VERDE_I2C_BASE + 0x00)
+#define VERDE_I2C_BASE1 (VERDE_I2C_BASE + 0x20)
+#define VERDE_I2C_SIZE 0x0080
+#define VERDE_I2C_CHSIZE 0x0020
+
+/*
+ * Address Translation Unit
+ */
+ /* 0x00 - 0x38 -- PCI configuration space header */
+#define ATU_IALR0 0x40 /* Inbound ATU Limit 0 */
+#define ATU_IATVR0 0x44 /* Inbound ATU Xlate Value 0 */
+#define ATU_ERLR 0x48 /* Expansion ROM Limit */
+#define ATU_ERTVR 0x4c /* Expansion ROM Xlate Value */
+#define ATU_IALR1 0x50 /* Inbound ATU Limit 1 */
+#define ATU_IALR2 0x54 /* Inbound ATU Limit 2 */
+#define ATU_IATVR2 0x58 /* Inbound ATU Xlate Value 2 */
+#define ATU_OIOWTVR 0x5c /* Outbound I/O Window Xlate Value */
+#define ATU_OMWTVR0 0x60 /* Outbound Mem Window Xlate Value 0 */
+#define ATU_OUMWTVR0 0x64 /* Outbound Mem Window Xlate Value 0 Upper */
+#define ATU_OMWTVR1 0x68 /* Outbound Mem Window Xlate Value 1 */
+#define ATU_OUMWTVR1 0x6c /* Outbound Mem Window Xlate Value 1 Upper */
+#define ATU_OUDWTVR 0x78 /* Outbound Mem Direct Xlate Value Upper */
+#define ATU_ATUCR 0x80 /* ATU Configuration */
+#define ATU_PCSR 0x84 /* PCI Configuration and Status */
+#define ATU_ATUISR 0x88 /* ATU Interrupt Status */
+#define ATU_ATUIMR 0x8c /* ATU Interrupt Mask */
+#define ATU_IABAR3 0x90 /* Inbound ATU Base Address 3 */
+#define ATU_IAUBAR3 0x94 /* Inbound ATU Base Address 3 Upper */
+#define ATU_IALR3 0x98 /* Inbound ATU Limit 3 */
+#define ATU_IATVR3 0x9c /* Inbound ATU Xlate Value 3 */
+#define ATU_OCCAR 0xa4 /* Outbound Configuration Cycle Address */
+#define ATU_OCCDR 0xac /* Outbound Configuration Cycle Data */
+#define ATU_MSI_PORT 0xb4 /* MSI port */
+#define ATU_PDSCR 0xbc /* PCI Bus Drive Strength Control */
+#define ATU_PCI_X_CAP_ID 0xe0 /* (1) */
+#define ATU_PCI_X_NEXT 0xe1 /* (1) */
+#define ATU_PCIXCMD 0xe2 /* PCI-X Command Register (2) */
+#define ATU_PCIXSR 0xe4 /* PCI-X Status Register */
+
+#define ATUCR_DRC_ALIAS (1U << 19)
+#define ATUCR_DAU2GXEN (1U << 18)
+#define ATUCR_P_SERR_MA (1U << 16)
+#define ATUCR_DTS (1U << 15)
+#define ATUCR_P_SERR_DIE (1U << 9)
+#define ATUCR_DAE (1U << 8)
+#define ATUCR_BIST_IE (1U << 3)
+#define ATUCR_OUT_EN (1U << 1)
+
+#define PCSR_DAAAPE (1U << 18)
+#define PCSR_PCI_X_CAP (3U << 16)
+#define PCSR_PCI_X_CAP_BORING (0 << 16)
+#define PCSR_PCI_X_CAP_66 (1U << 16)
+#define PCSR_PCI_X_CAP_100 (2U << 16)
+#define PCSR_PCI_X_CAP_133 (3U << 16)
+#define PCSR_OTQB (1U << 15)
+#define PCSR_IRTQB (1U << 14)
+#define PCSR_DTV (1U << 12)
+#define PCSR_BUS66 (1U << 10)
+#define PCSR_BUS64 (1U << 8)
+#define PCSR_RIB (1U << 5)
+#define PCSR_RPB (1U << 4)
+#define PCSR_CCR (1U << 2)
+#define PCSR_CPR (1U << 1)
+
+#define ATUISR_IMW1BU (1U << 14)
+#define ATUISR_ISCEM (1U << 13)
+#define ATUISR_RSCEM (1U << 12)
+#define ATUISR_PST (1U << 11)
+#define ATUISR_P_SERR_ASRT (1U << 10)
+#define ATUISR_DPE (1U << 9)
+#define ATUISR_BIST (1U << 8)
+#define ATUISR_IBMA (1U << 7)
+#define ATUISR_P_SERR_DET (1U << 4)
+#define ATUISR_PMA (1U << 3)
+#define ATUISR_PTAM (1U << 2)
+#define ATUISR_PTAT (1U << 1)
+#define ATUISR_PMPE (1U << 0)
+
+#define ATUIMR_IMW1BU (1U << 11)
+#define ATUIMR_ISCEM (1U << 10)
+#define ATUIMR_RSCEM (1U << 9)
+#define ATUIMR_PST (1U << 8)
+#define ATUIMR_DPE (1U << 7)
+#define ATUIMR_P_SERR_ASRT (1U << 6)
+#define ATUIMR_PMA (1U << 5)
+#define ATUIMR_PTAM (1U << 4)
+#define ATUIMR_PTAT (1U << 3)
+#define ATUIMR_PMPE (1U << 2)
+#define ATUIMR_IE_SERR_EN (1U << 1)
+#define ATUIMR_ECC_TAE (1U << 0)
+
+#define PCIXCMD_MOST_1 (0 << 4)
+#define PCIXCMD_MOST_2 (1 << 4)
+#define PCIXCMD_MOST_3 (2 << 4)
+#define PCIXCMD_MOST_4 (3 << 4)
+#define PCIXCMD_MOST_8 (4 << 4)
+#define PCIXCMD_MOST_12 (5 << 4)
+#define PCIXCMD_MOST_16 (6 << 4)
+#define PCIXCMD_MOST_32 (7 << 4)
+#define PCIXCMD_MOST_MASK (7 << 4)
+#define PCIXCMD_MMRBC_512 (0 << 2)
+#define PCIXCMD_MMRBC_1024 (1 << 2)
+#define PCIXCMD_MMRBC_2048 (2 << 2)
+#define PCIXCMD_MMRBC_4096 (3 << 2)
+#define PCIXCMD_MMRBC_MASK (3 << 2)
+#define PCIXCMD_ERO (1U << 1)
+#define PCIXCMD_DPERE (1U << 0)
+
+#define PCIXSR_RSCEM (1U << 29)
+#define PCIXSR_DMCRS_MASK (7 << 26)
+#define PCIXSR_DMOST_MASK (7 << 23)
+#define PCIXSR_COMPLEX (1U << 20)
+#define PCIXSR_USC (1U << 19)
+#define PCIXSR_SCD (1U << 18)
+#define PCIXSR_133_CAP (1U << 17)
+#define PCIXSR_32PCI (1U << 16) /* 0 = 32, 1 = 64 */
+#define PCIXSR_BUSNO(x) (((x) & 0xff00) >> 8)
+#define PCIXSR_DEVNO(x) (((x) & 0xf8) >> 3)
+#define PCIXSR_FUNCNO(x) ((x) & 0x7)
+
+/*
+ * Memory Controller Unit
+ */
+#define MCU_SDIR 0x00 /* DDR SDRAM Init. Register */
+#define MCU_SDCR 0x04 /* DDR SDRAM Control Register */
+#define MCU_SDBR 0x08 /* SDRAM Base Register */
+#define MCU_SBR0 0x0c /* SDRAM Boundary 0 */
+#define MCU_SBR1 0x10 /* SDRAM Boundary 1 */
+#define MCU_ECCR 0x34 /* ECC Control Register */
+#define MCU_ELOG0 0x38 /* ECC Log 0 */
+#define MCU_ELOG1 0x3c /* ECC Log 1 */
+#define MCU_ECAR0 0x40 /* ECC address 0 */
+#define MCU_ECAR1 0x44 /* ECC address 1 */
+#define MCU_ECTST 0x48 /* ECC test register */
+#define MCU_MCISR 0x4c /* MCU Interrupt Status Register */
+#define MCU_RFR 0x50 /* Refresh Frequency Register */
+#define MCU_DBUDSR 0x54 /* Data Bus Pull-up Drive Strength */
+#define MCU_DBDDSR 0x58 /* Data Bus Pull-down Drive Strength */
+#define MCU_CUDSR 0x5c /* Clock Pull-up Drive Strength */
+#define MCU_CDDSR 0x60 /* Clock Pull-down Drive Strength */
+#define MCU_CEUDSR 0x64 /* Clock En Pull-up Drive Strength */
+#define MCU_CEDDSR 0x68 /* Clock En Pull-down Drive Strength */
+#define MCU_CSUDSR 0x6c /* Chip Sel Pull-up Drive Strength */
+#define MCU_CSDDSR 0x70 /* Chip Sel Pull-down Drive Strength */
+#define MCU_REUDSR 0x74 /* Rx En Pull-up Drive Strength */
+#define MCU_REDDSR 0x78 /* Rx En Pull-down Drive Strength */
+#define MCU_ABUDSR 0x7c /* Addr Bus Pull-up Drive Strength */
+#define MCU_ABDDSR 0x80 /* Addr Bus Pull-down Drive Strength */
+#define MCU_DSDR 0x84 /* Data Strobe Delay Register */
+#define MCU_REDR 0x88 /* Rx Enable Delay Register */
+
+#define SDCR_DIMMTYPE (1U << 1) /* 0 = unbuf, 1 = reg */
+#define SDCR_BUSWIDTH (1U << 2) /* 0 = 64, 1 = 32 */
+
+#define SBRx_TECH (1U << 31)
+#define SBRx_BOUND 0x0000003f
+
+#define ECCR_SBERE (1U << 0)
+#define ECCR_MBERE (1U << 1)
+#define ECCR_SBECE (1U << 2)
+#define ECCR_ECCEN (1U << 3)
+
+#define ELOGx_SYNDROME 0x000000ff
+#define ELOGx_ERRTYPE (1U << 8) /* 1 = multi-bit */
+#define ELOGx_RW (1U << 12) /* 1 = write error */
+ /*
+ * Dev ID Func Requester
+ * 2 0 XScale core
+ * 2 1 ATU
+ * 13 0 DMA channel 0
+ * 13 1 DMA channel 1
+ * 26 0 ATU
+ */
+#define ELOGx_REQ_DEV(x) (((x) >> 19) & 0x1f)
+#define ELOGx_REQ_FUNC(x) (((x) >> 16) & 0x3)
+
+#define MCISR_ECC_ERR0 (1U << 0)
+#define MCISR_ECC_ERR1 (1U << 1)
+#define MCISR_ECC_ERRN (1U << 2)
+
+/*
+ * Timers
+ *
+ * The i80321 timer registers are available in both memory-mapped
+ * and coprocessor spaces. Most of the registers are read-only
+ * if memory-mapped, so we access them via coprocessor space.
+ *
+ * TMR0 cp6 c0,1 0xffffe7e0
+ * TMR1 cp6 c1,1 0xffffe7e4
+ * TCR0 cp6 c2,1 0xffffe7e8
+ * TCR1 cp6 c3,1 0xffffe7ec
+ * TRR0 cp6 c4,1 0xffffe7f0
+ * TRR1 cp6 c5,1 0xffffe7f4
+ * TISR cp6 c6,1 0xffffe7f8
+ * WDTCR cp6 c7,1 0xffffe7fc
+ */
+
+#define TMRx_TC (1U << 0)
+#define TMRx_ENABLE (1U << 1)
+#define TMRx_RELOAD (1U << 2)
+#define TMRx_CSEL_CORE (0 << 4)
+#define TMRx_CSEL_CORE_div4 (1 << 4)
+#define TMRx_CSEL_CORE_div8 (2 << 4)
+#define TMRx_CSEL_CORE_div16 (3 << 4)
+
+#define TISR_TMR0 (1U << 0)
+#define TISR_TMR1 (1U << 1)
+
+#define WDTCR_ENABLE1 0x1e1e1e1e
+#define WDTCR_ENABLE2 0xe1e1e1e1
+
+/*
+ * Interrupt Controller Unit.
+ *
+ * INTCTL cp6 c0,0 0xffffe7d0
+ * INTSTR cp6 c4,0 0xffffe7d4
+ * IINTSRC cp6 c8,0 0xffffe7d8
+ * FINTSRC cp6 c9,0 0xffffe7dc
+ * PIRSR 0xffffe1ec
+ */
+
+#define ICU_PIRSR 0x01ec
+#define ICU_GPOE 0x07c4
+#define ICU_GPID 0x07c8
+#define ICU_GPOD 0x07cc
+
+/*
+ * NOTE: WE USE THE `bitXX' BITS TO INDICATE PENDING SOFTWARE
+ * INTERRUPTS. See i80321_icu.c
+ */
+#define ICU_INT_HPI 31 /* high priority interrupt */
+#define ICU_INT_XINT0 27 /* external interrupts */
+#define ICU_INT_XINT(x) ((x) + ICU_INT_XINT0)
+#define ICU_INT_bit26 26
+
+#if defined (CPU_XSCALE_80219)
+#define ICU_INT_bit25 25 /* reserved */
+#else
+/* CPU_XSCALE_80321 */
+#define ICU_INT_SSP 25 /* SSP serial port */
+#endif
+
+#define ICU_INT_MUE 24 /* msg unit error */
+
+#if defined (CPU_XSCALE_80219)
+#define ICU_INT_bit23 23 /* reserved */
+#else
+/* CPU_XSCALE_80321 */
+#define ICU_INT_AAUE 23 /* AAU error */
+#endif
+
+#define ICU_INT_bit22 22
+#define ICU_INT_DMA1E 21 /* DMA Ch 1 error */
+#define ICU_INT_DMA0E 20 /* DMA Ch 0 error */
+#define ICU_INT_MCUE 19 /* memory controller error */
+#define ICU_INT_ATUE 18 /* ATU error */
+#define ICU_INT_BIUE 17 /* bus interface unit error */
+#define ICU_INT_PMU 16 /* XScale PMU */
+#define ICU_INT_PPM 15 /* peripheral PMU */
+#define ICU_INT_BIST 14 /* ATU Start BIST */
+#define ICU_INT_MU 13 /* messaging unit */
+#define ICU_INT_I2C1 12 /* i2c unit 1 */
+#define ICU_INT_I2C0 11 /* i2c unit 0 */
+#define ICU_INT_TMR1 10 /* timer 1 */
+#define ICU_INT_TMR0 9 /* timer 0 */
+#define ICU_INT_CPPM 8 /* core processor PMU */
+
+#if defined(CPU_XSCALE_80219)
+#define ICU_INT_bit7 7 /* reserved */
+#define ICU_INT_bit6 6 /* reserved */
+#else
+/* CPU_XSCALE_80321 */
+#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */
+#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */
+#endif
+
+#define ICU_INT_bit5 5
+#define ICU_INT_bit4 4
+#define ICU_INT_DMA1_EOC 3 /* DMA1 end-of-chain */
+#define ICU_INT_DMA1_EOT 2 /* DMA1 end-of-transfer */
+#define ICU_INT_DMA0_EOC 1 /* DMA0 end-of-chain */
+#define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */
+
+#if defined (CPU_XSCALE_80219)
+#define ICU_INT_HWMASK (0xffffffff & \
+ ~((1 << ICU_INT_bit26) | \
+ (1 << ICU_INT_bit25) | \
+ (1 << ICU_INT_bit23) | \
+ (1 << ICU_INT_bit22) | \
+ (1 << ICU_INT_bit7) | \
+ (1 << ICU_INT_bit6) | \
+ (1 << ICU_INT_bit5) | \
+ (1 << ICU_INT_bit4)))
+
+#else
+/* CPU_XSCALE_80321 */
+#define ICU_INT_HWMASK (0xffffffff & \
+ ~((1 << ICU_INT_bit26) | \
+ (1 << ICU_INT_bit22) | \
+ (1 << ICU_INT_bit5) | \
+ (1 << ICU_INT_bit4)))
+#endif
+
+/*
+ * SSP Serial Port
+ */
+#if defined (CPU_XSCALE_80321)
+
+#define SSP_SSCR0 0x00 /* SSC control 0 */
+#define SSP_SSCR1 0x04 /* SSC control 1 */
+#define SSP_SSSR 0x08 /* SSP status */
+#define SSP_SSITR 0x0c /* SSP interrupt test */
+#define SSP_SSDR 0x10 /* SSP data */
+
+#define SSP_SSCR0_DSIZE(x) ((x) - 1)/* data size: 4..16 */
+#define SSP_SSCR0_FRF_SPI (0 << 4) /* Motorola Serial Periph Iface */
+#define SSP_SSCR0_FRF_SSP (1U << 4)/* TI Sync. Serial Protocol */
+#define SSP_SSCR0_FRF_UWIRE (2U << 4)/* NatSemi Microwire */
+#define SSP_SSCR0_FRF_rsvd (3U << 4)/* reserved */
+#define SSP_SSCR0_ECS (1U << 6)/* external clock select */
+#define SSP_SSCR0_SSE (1U << 7)/* sync. serial port enable */
+#define SSP_SSCR0_SCR(x) ((x) << 8)/* serial clock rate */
+ /* bit rate = 3.6864 * 10e6 /
+ (2 * (SCR + 1)) */
+
+#define SSP_SSCR1_RIE (1U << 0)/* Rx FIFO interrupt enable */
+#define SSP_SSCR1_TIE (1U << 1)/* Tx FIFO interrupt enable */
+#define SSP_SSCR1_LBM (1U << 2)/* loopback mode enable */
+#define SSP_SSCR1_SPO (1U << 3)/* Moto SPI SSCLK pol. (1 = high) */
+#define SSP_SSCR1_SPH (1U << 4)/* Moto SPI SSCLK phase:
+ 0 = inactive full at start,
+ 1/2 at end of frame
+ 1 = inactive 1/2 at start,
+ full at end of frame */
+#define SSP_SSCR1_MWDS (1U << 5)/* Microwire data size:
+ 0 = 8 bit
+ 1 = 16 bit */
+#define SSP_SSCR1_TFT (((x) - 1) << 6) /* Tx FIFO threshold */
+#define SSP_SSCR1_RFT (((x) - 1) << 10)/* Rx FIFO threshold */
+#define SSP_SSCR1_EFWR (1U << 14)/* enab. FIFO write/read */
+#define SSP_SSCR1_STRF (1U << 15)/* FIFO write/read FIFO select:
+ 0 = Tx FIFO
+ 1 = Rx FIFO */
+
+#define SSP_SSSR_TNF (1U << 2)/* Tx FIFO not full */
+#define SSP_SSSR_RNE (1U << 3)/* Rx FIFO not empty */
+#define SSP_SSSR_BSY (1U << 4)/* SSP is busy */
+#define SSP_SSSR_TFS (1U << 5)/* Tx FIFO service request */
+#define SSP_SSSR_RFS (1U << 6)/* Rx FIFO service request */
+#define SSP_SSSR_ROR (1U << 7)/* Rx FIFO overrun */
+#define SSP_SSSR_TFL(x) (((x) >> 8) & 0xf) /* Tx FIFO level */
+#define SSP_SSSR_RFL(x) (((x) >> 12) & 0xf)/* Rx FIFO level */
+
+#define SSP_SSITR_TTFS (1U << 5)/* Test Tx FIFO service */
+#define SSP_SSITR_TRFS (1U << 6)/* Test Rx FIFO service */
+#define SSP_SSITR_TROR (1U << 7)/* Test Rx overrun */
+
+#endif /* CPU_XSCALE_80321 */
+
+/*
+ * Peripheral Bus Interface Unit
+ */
+
+#define PBIU_PBCR 0x00 /* PBIU Control Register */
+#define PBIU_PBBAR0 0x08 /* PBIU Base Address Register 0 */
+#define PBIU_PBLR0 0x0c /* PBIU Limit Register 0 */
+#define PBIU_PBBAR1 0x10 /* PBIU Base Address Register 1 */
+#define PBIU_PBLR1 0x14 /* PBIU Limit Register 1 */
+#define PBIU_PBBAR2 0x18 /* PBIU Base Address Register 2 */
+#define PBIU_PBLR2 0x1c /* PBIU Limit Register 2 */
+#define PBIU_PBBAR3 0x20 /* PBIU Base Address Register 3 */
+#define PBIU_PBLR3 0x24 /* PBIU Limit Register 3 */
+#define PBIU_PBBAR4 0x28 /* PBIU Base Address Register 4 */
+#define PBIU_PBLR4 0x2c /* PBIU Limit Register 4 */
+#define PBIU_PBBAR5 0x30 /* PBIU Base Address Register 5 */
+#define PBIU_PBLR5 0x34 /* PBIU Limit Register 5 */
+#define PBIU_DSCR 0x38 /* PBIU Drive Strength Control Reg. */
+#define PBIU_MBR0 0x40 /* PBIU Memory-less Boot Reg. 0 */
+#define PBIU_MBR1 0x60 /* PBIU Memory-less Boot Reg. 1 */
+#define PBIU_MBR2 0x64 /* PBIU Memory-less Boot Reg. 2 */
+
+#define PBIU_PBCR_PBIEN (1 << 0)
+#define PBIU_PBCR_PBI100 (1 << 1)
+#define PBIU_PBCR_PBI66 (2 << 1)
+#define PBIU_PBCR_PBI33 (3 << 1)
+#define PBIU_PBCR_PBBEN (1 << 3)
+
+#define PBIU_PBARx_WIDTH8 (0 << 0)
+#define PBIU_PBARx_WIDTH16 (1 << 0)
+#define PBIU_PBARx_WIDTH32 (2 << 0)
+#define PBIU_PBARx_ADWAIT4 (0 << 2)
+#define PBIU_PBARx_ADWAIT8 (1 << 2)
+#define PBIU_PBARx_ADWAIT12 (2 << 2)
+#define PBIU_PBARx_ADWAIT16 (3 << 2)
+#define PBIU_PBARx_ADWAIT20 (4 << 2)
+#define PBIU_PBARx_RCWAIT1 (0 << 6)
+#define PBIU_PBARx_RCWAIT4 (1 << 6)
+#define PBIU_PBARx_RCWAIT8 (2 << 6)
+#define PBIU_PBARx_RCWAIT12 (3 << 6)
+#define PBIU_PBARx_RCWAIT16 (4 << 6)
+#define PBIU_PBARx_RCWAIT20 (5 << 6)
+#define PBIU_PBARx_FWE (1 << 9)
+#define PBIU_BASE_MASK 0xfffff000U
+
+#define PBIU_PBLRx_SIZE(x) (~((x) - 1))
+
+/*
+ * Messaging Unit
+ */
+#define MU_IMR0 0x0010 /* MU Inbound Message Register 0 */
+#define MU_IMR1 0x0014 /* MU Inbound Message Register 1 */
+#define MU_OMR0 0x0018 /* MU Outbound Message Register 0 */
+#define MU_OMR1 0x001c /* MU Outbound Message Register 1 */
+#define MU_IDR 0x0020 /* MU Inbound Doorbell Register */
+#define MU_IISR 0x0024 /* MU Inbound Interrupt Status Reg */
+#define MU_IIMR 0x0028 /* MU Inbound Interrupt Mask Reg */
+#define MU_ODR 0x002c /* MU Outbound Doorbell Register */
+#define MU_OISR 0x0030 /* MU Outbound Interrupt Status Reg */
+#define MU_OIMR 0x0034 /* MU Outbound Interrupt Mask Reg */
+#define MU_MUCR 0x0050 /* MU Configuration Register */
+#define MU_QBAR 0x0054 /* MU Queue Base Address Register */
+#define MU_IFHPR 0x0060 /* MU Inbound Free Head Pointer Reg */
+#define MU_IFTPR 0x0064 /* MU Inbound Free Tail Pointer Reg */
+#define MU_IPHPR 0x0068 /* MU Inbound Post Head Pointer Reg */
+#define MU_IPTPR 0x006c /* MU Inbound Post Tail Pointer Reg */
+#define MU_OFHPR 0x0070 /* MU Outbound Free Head Pointer Reg */
+#define MU_OFTPR 0x0074 /* MU Outbound Free Tail Pointer Reg */
+#define MU_OPHPR 0x0078 /* MU Outbound Post Head Pointer Reg */
+#define MU_OPTPR 0x007c /* MU Outbound Post Tail Pointer Reg */
+#define MU_IAR 0x0080 /* MU Index Address Register */
+
+#define MU_IIMR_IRI (1 << 6) /* Index Register Interrupt */
+#define MU_IIMR_OFQFI (1 << 5) /* Outbound Free Queue Full Int. */
+#define MU_IIMR_IPQI (1 << 4) /* Inbound Post Queue Interrupt */
+#define MU_IIMR_EDI (1 << 3) /* Error Doorbell Interrupt */
+#define MU_IIMR_IDI (1 << 2) /* Inbound Doorbell Interrupt */
+#define MU_IIMR_IM1I (1 << 1) /* Inbound Message 1 Interrupt */
+#define MU_IIMR_IM0I (1 << 0) /* Inbound Message 0 Interrupt */
+
+#endif /* _ARM_XSCALE_I80321REG_H_ */
Property changes on: trunk/sys/arm/xscale/i80321/i80321reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/i80321var.h
===================================================================
--- trunk/sys/arm/xscale/i80321/i80321var.h (rev 0)
+++ trunk/sys/arm/xscale/i80321/i80321var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,138 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321var.h,v 1.8 2003/10/06 16:06:06 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/i80321/i80321var.h 171628 2007-07-27 14:53:06Z cognet $
+ *
+ */
+
+#ifndef _ARM_XSCALE_I80321VAR_H_
+#define _ARM_XSCALE_I80321VAR_H_
+
+#include <sys/queue.h>
+#include <dev/pci/pcivar.h>
+#include <sys/rman.h>
+
+extern struct bus_space i80321_bs_tag;
+
+struct i80321_softc {
+ device_t dev;
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_sh;
+ /* Handles for the various subregions. */
+ bus_space_handle_t sc_atu_sh;
+ bus_space_handle_t sc_mcu_sh;
+ int sc_is_host;
+
+ /*
+ * We expect the board-specific front-end to have already mapped
+ * the PCI I/O space .. it is only 64K, and I/O mappings tend to
+ * be smaller than a page size, so it's generally more efficient
+ * to map them all into virtual space in one fell swoop.
+ */
+ vm_offset_t sc_iow_vaddr; /* I/O window vaddr */
+
+ /*
+ * Variables that define the Inbound windows. The base address of
+ * 0-2 are configured by a host via BARs. The xlate variable
+ * defines the start of the local address space that it maps to.
+ * The size variable defines the byte size.
+ *
+ * The first 3 windows are for incoming PCI memory read/write
+ * cycles from a host. The 4th window, not configured by the
+ * host (as it outside the normal BAR range) is the inbound
+ * window for PCI devices controlled by the i80321.
+ */
+ struct {
+ uint32_t iwin_base_hi;
+ uint32_t iwin_base_lo;
+ uint32_t iwin_xlate;
+ uint32_t iwin_size;
+ } sc_iwin[4];
+
+ /*
+ * Variables that define the Outbound windows.
+ */
+ struct {
+ uint32_t owin_xlate_lo;
+ uint32_t owin_xlate_hi;
+ } sc_owin[2];
+
+ /*
+ * This is the PCI address that the Outbound I/O
+ * window maps to.
+ */
+ uint32_t sc_ioout_xlate;
+
+ /* Bus space, DMA, and PCI tags for the PCI bus (private devices). */
+ struct bus_space sc_pci_iot;
+ struct bus_space sc_pci_memt;
+
+ /* GPIO state */
+ uint8_t sc_gpio_dir; /* GPIO pin direction (1 == output) */
+ uint8_t sc_gpio_val; /* GPIO output pin value */
+ struct rman sc_irq_rman;
+
+};
+
+
+struct i80321_pci_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_atu_sh;
+ bus_space_tag_t sc_pciio;
+ bus_space_tag_t sc_pcimem;
+ int sc_busno;
+ struct rman sc_mem_rman;
+ struct rman sc_io_rman;
+ struct rman sc_irq_rman;
+ uint32_t sc_mem;
+ uint32_t sc_io;
+};
+
+void i80321_sdram_bounds(bus_space_tag_t, bus_space_handle_t,
+ vm_paddr_t *, vm_size_t *);
+
+void i80321_attach(struct i80321_softc *);
+void i80321_calibrate_delay(void);
+
+void i80321_bs_init(bus_space_tag_t, void *);
+void i80321_io_bs_init(bus_space_tag_t, void *);
+void i80321_mem_bs_init(bus_space_tag_t, void *);
+extern int machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin);
+
+
+#endif /* _ARM_XSCALE_I80321VAR_H_ */
Property changes on: trunk/sys/arm/xscale/i80321/i80321var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/iq31244_7seg.c
===================================================================
--- trunk/sys/arm/xscale/i80321/iq31244_7seg.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/iq31244_7seg.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,391 @@
+/* $MidnightBSD$ */
+/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Support for the 7-segment display on the Intel IQ31244.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/iq31244_7seg.c 236987 2012-06-13 04:38:09Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/i80321/iq80321reg.h>
+#include <arm/xscale/i80321/iq80321var.h>
+
+#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v)
+
+static int snakestate;
+
+/*
+ * The 7-segment display looks like so:
+ *
+ * A
+ * +-----+
+ * | |
+ * F | | B
+ * | G |
+ * +-----+
+ * | |
+ * E | | C
+ * | D |
+ * +-----+ o DP
+ *
+ * Setting a bit clears the corresponding segment on the
+ * display.
+ */
+#define SEG_A (1 << 0)
+#define SEG_B (1 << 1)
+#define SEG_C (1 << 2)
+#define SEG_D (1 << 3)
+#define SEG_E (1 << 4)
+#define SEG_F (1 << 5)
+#define SEG_G (1 << 6)
+#define SEG_DP (1 << 7)
+
+static const uint8_t digitmap[] = {
+/* +#####+
+ * # #
+ * # #
+ * # #
+ * +-----+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ */
+ SEG_G,
+
+/* +-----+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ */
+ SEG_A|SEG_D|SEG_E|SEG_F|SEG_G,
+
+/* +#####+
+ * | #
+ * | #
+ * | #
+ * +#####+
+ * # |
+ * # |
+ * # |
+ * +#####+
+ */
+ SEG_C|SEG_F,
+
+/* +#####+
+ * | #
+ * | #
+ * | #
+ * +#####+
+ * | #
+ * | #
+ * | #
+ * +#####+
+ */
+ SEG_E|SEG_F,
+
+/* +-----+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ */
+ SEG_A|SEG_D|SEG_E,
+
+/* +#####+
+ * # |
+ * # |
+ * # |
+ * +#####+
+ * | #
+ * | #
+ * | #
+ * +#####+
+ */
+ SEG_B|SEG_E,
+
+/* +#####+
+ * # |
+ * # |
+ * # |
+ * +#####+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ */
+ SEG_B,
+
+/* +#####+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ */
+ SEG_D|SEG_E|SEG_F,
+
+/* +#####+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ */
+ 0,
+
+/* +#####+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ */
+ SEG_D|SEG_E,
+};
+
+static uint8_t
+iq80321_7seg_xlate(char c)
+{
+ uint8_t rv;
+
+ if (c >= '0' && c <= '9')
+ rv = digitmap[c - '0'];
+ else if (c == '.')
+ rv = (uint8_t) ~SEG_DP;
+ else
+ rv = 0xff;
+
+ return (rv);
+}
+
+void
+iq80321_7seg(char a, char b)
+{
+ uint8_t msb, lsb;
+
+ msb = iq80321_7seg_xlate(a);
+ lsb = iq80321_7seg_xlate(b);
+
+ snakestate = 0;
+
+ WRITE(IQ80321_7SEG_MSB, msb);
+ WRITE(IQ80321_7SEG_LSB, lsb);
+}
+
+static const uint8_t snakemap[][2] = {
+
+/* +#####+ +#####+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { ~SEG_A, ~SEG_A },
+
+/* +-----+ +-----+
+ * # | | #
+ * # | | #
+ * # | | #
+ * +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { ~SEG_F, ~SEG_B },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +#####+ +#####+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { ~SEG_G, ~SEG_G },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ * | # # |
+ * | # # |
+ * | # # |
+ * +-----+ +-----+
+ */
+ { ~SEG_C, ~SEG_E },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +#####+ +#####+
+ */
+ { ~SEG_D, ~SEG_D },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ * # | | #
+ * # | | #
+ * # | | #
+ * +-----+ +-----+
+ */
+ { ~SEG_E, ~SEG_C },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +#####+ +#####+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { ~SEG_G, ~SEG_G },
+
+/* +-----+ +-----+
+ * | # # |
+ * | # # |
+ * | # # |
+ * +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { ~SEG_B, ~SEG_F },
+};
+
+static SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg");
+static int freq = 20;
+SYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0,
+ "7 Seg update frequency");
+static void
+iq31244_7seg_snake(void)
+{
+ static int snakefreq;
+ int cur = snakestate;
+
+ snakefreq++;
+ if ((snakefreq % freq))
+ return;
+ WRITE(IQ80321_7SEG_MSB, snakemap[cur][0]);
+ WRITE(IQ80321_7SEG_LSB, snakemap[cur][1]);
+
+ snakestate = (cur + 1) & 7;
+}
+
+struct iq31244_7seg_softc {
+ device_t dev;
+};
+
+static int
+iq31244_7seg_probe(device_t dev)
+{
+
+ device_set_desc(dev, "IQ31244 7seg");
+ return (0);
+}
+
+extern void (*i80321_hardclock_hook)(void);
+static int
+iq31244_7seg_attach(device_t dev)
+{
+
+ i80321_hardclock_hook = iq31244_7seg_snake;
+ return (0);
+}
+
+static device_method_t iq31244_7seg_methods[] = {
+ DEVMETHOD(device_probe, iq31244_7seg_probe),
+ DEVMETHOD(device_attach, iq31244_7seg_attach),
+ {0, 0},
+};
+
+static driver_t iq31244_7seg_driver = {
+ "iqseg",
+ iq31244_7seg_methods,
+ sizeof(struct iq31244_7seg_softc),
+};
+static devclass_t iq31244_7seg_devclass;
+
+DRIVER_MODULE(iqseg, iq, iq31244_7seg_driver, iq31244_7seg_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i80321/iq31244_7seg.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/iq31244_machdep.c
===================================================================
--- trunk/sys/arm/xscale/i80321/iq31244_machdep.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/iq31244_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,411 @@
+/* $MidnightBSD$ */
+/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
+
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work.
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/iq31244_machdep.c 278727 2015-02-13 22:32:02Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/cons.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/kdb.h>
+#include <sys/msgbuf.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+#include <machine/physmem.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <machine/devmap.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <sys/reboot.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i80321/iq80321reg.h>
+#include <arm/xscale/i80321/obiovar.h>
+
+#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
+#define KERNEL_PT_IOPXS 1
+#define KERNEL_PT_BEFOREKERN 2
+#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */
+#define KERNEL_PT_AFKERNEL_NUM 9
+
+/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
+#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
+
+struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
+
+/* Physical and virtual addresses for some global pages */
+
+struct pv_addr systempage;
+struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+struct pv_addr kernelstack;
+struct pv_addr minidataclean;
+
+#define IQ80321_OBIO_BASE 0xfe800000UL
+#define IQ80321_OBIO_SIZE 0x00100000UL
+/* Static device mappings. */
+static const struct arm_devmap_entry iq80321_devmap[] = {
+ /*
+ * Map the on-board devices VA == PA so that we can access them
+ * with the MMU on or off.
+ */
+ {
+ IQ80321_OBIO_BASE,
+ IQ80321_OBIO_BASE,
+ IQ80321_OBIO_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ IQ80321_IOW_VBASE,
+ VERDE_OUT_XLATE_IO_WIN0_BASE,
+ VERDE_OUT_XLATE_IO_WIN_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+
+ {
+ IQ80321_80321_VBASE,
+ VERDE_PMMR_BASE,
+ VERDE_PMMR_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ }
+};
+
+#define SDRAM_START 0xa0000000
+
+extern vm_offset_t xscale_cache_clean_addr;
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+ struct pv_addr kernel_l1pt;
+ struct pv_addr dpcpu;
+ int loop, i;
+ u_int l1pagetable;
+ vm_offset_t freemempos;
+ vm_offset_t freemem_pt;
+ vm_offset_t afterkern;
+ vm_offset_t freemem_after;
+ vm_offset_t lastaddr;
+ uint32_t memsize, memstart;
+
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+ set_cpufuncs();
+ pcpu_init(pcpup, 0, sizeof(struct pcpu));
+ PCPU_SET(curthread, &thread0);
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+ freemempos = 0xa0200000;
+ /* Define a macro to simplify memory allocation */
+#define valloc_pages(var, np) \
+ alloc_pages((var).pv_pa, (np)); \
+ (var).pv_va = (var).pv_pa + 0x20000000;
+
+#define alloc_pages(var, np) \
+ freemempos -= (np * PAGE_SIZE); \
+ (var) = freemempos; \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos -= PAGE_SIZE;
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[loop],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ } else {
+ kernel_pt_table[loop].pv_pa = freemempos +
+ (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
+ L2_TABLE_SIZE_REAL;
+ kernel_pt_table[loop].pv_va =
+ kernel_pt_table[loop].pv_pa + 0x20000000;
+ }
+ }
+ freemem_pt = freemempos;
+ freemempos = 0xa0100000;
+ /*
+ * Allocate a page for the system page mapped to V0x00000000
+ * This page will just contain the system vectors and can be
+ * shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate dynamic per-cpu area. */
+ valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
+ dpcpu_init((void *)dpcpu.pv_va, 0);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE);
+ valloc_pages(abtstack, ABT_STACK_SIZE);
+ valloc_pages(undstack, UND_STACK_SIZE);
+ valloc_pages(kernelstack, KSTACK_PAGES);
+ alloc_pages(minidataclean.pv_pa, 1);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+ /*
+ * Allocate memory for the l1 and l2 page tables. The scheme to avoid
+ * wasting memory by allocating the l1pt on the first 16k memory was
+ * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for
+ * this to work (which is supposed to be the case).
+ */
+
+ /*
+ * Now we start construction of the L1 page table
+ * We start by mapping the L2 page tables into the L1.
+ * This means that we can replace L1 mappings later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /* Map the L2 pages tables in the L1 page table */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1),
+ &kernel_pt_table[KERNEL_PT_SYS]);
+ pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE,
+ &kernel_pt_table[KERNEL_PT_IOPXS]);
+ pmap_link_l2pt(l1pagetable, KERNBASE,
+ &kernel_pt_table[KERNEL_PT_BEFOREKERN]);
+ pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000,
+ 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000,
+ (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1),
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1);
+ afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE
+ - 1));
+ for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
+ pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
+ &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
+ }
+ pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+
+ /* Map the Mini-Data cache clean area. */
+ xscale_setup_minidata(l1pagetable, afterkern,
+ minidataclean.pv_pa);
+
+ /* Map the vector page. */
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ arm_devmap_bootstrap(l1pagetable, iq80321_devmap);
+ /*
+ * Give the XScale global cache clean code an appropriately
+ * sized chunk of unmapped VA space starting at 0xff000000
+ * (our device mappings end before this address).
+ */
+ xscale_cache_clean_addr = 0xff000000U;
+
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+ cpu_setup("");
+
+ /*
+ * Fetch the SDRAM start/size from the i80321 SDRAM configration
+ * registers.
+ */
+ i80321_calibrate_delay();
+ i80321_sdram_bounds(obio_bs_tag, IQ80321_80321_VBASE + VERDE_MCU_BASE,
+ &memstart, &memsize);
+ physmem = memsize / PAGE_SIZE;
+ cninit();
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ /* Enable MMU, I-cache, D-cache, write buffer. */
+
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+ pmap_curmaxkvaddr = afterkern + PAGE_SIZE;
+ vm_max_kernel_address = 0xd0000000;
+ pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
+ msgbufp = (void*)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+
+ /*
+ * Add the physical ram we have available.
+ *
+ * Exclude the kernel (and all the things we allocated which immediately
+ * follow the kernel) from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ arm_physmem_hardware_region(SDRAM_START, memsize);
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+}
+
+extern int
+machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin)
+{
+ int bus;
+ int device;
+ int func;
+ uint32_t busno;
+ struct i80321_pci_softc *sc = device_get_softc(pcib);
+ bus = pci_get_bus(dev);
+ device = pci_get_slot(dev);
+ func = pci_get_function(dev);
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
+ busno = PCIXSR_BUSNO(busno);
+ if (busno == 0xff)
+ busno = 0;
+ if (bus != busno)
+ goto no_mapping;
+ switch (device) {
+ /* IQ31244 PCI */
+ case 1: /* PCIX-PCIX bridge */
+ /*
+ * The S-ATA chips are behind the bridge, and all of
+ * the S-ATA interrupts are wired together.
+ */
+ return (ICU_INT_XINT(2));
+ case 2: /* PCI slot */
+ /* All pins are wired together. */
+ return (ICU_INT_XINT(3));
+ case 3: /* i82546 dual Gig-E */
+ if (pin == 1 || pin == 2)
+ return (ICU_INT_XINT(0));
+ goto no_mapping;
+ /* IQ80321 PCI */
+ case 4: /* i82544 Gig-E */
+ case 8: /*
+ * Apparently you can set the device for the ethernet adapter
+ * to 8 with a jumper, so handle that as well
+ */
+ if (pin == 1)
+ return (ICU_INT_XINT(0));
+ goto no_mapping;
+ case 6: /* S-PCI-X slot */
+ if (pin == 1)
+ return (ICU_INT_XINT(2));
+ if (pin == 2)
+ return (ICU_INT_XINT(3));
+ goto no_mapping;
+ default:
+no_mapping:
+ printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin);
+
+ }
+ return (0);
+
+}
Property changes on: trunk/sys/arm/xscale/i80321/iq31244_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/iq80321.c
===================================================================
--- trunk/sys/arm/xscale/i80321/iq80321.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/iq80321.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,395 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321_mainbus.c,v 1.13 2003/12/17 22:03:24 abs Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * IQ80321 front-end for the i80321 I/O Processor. We take care
+ * of setting up the i80321 memory map, PCI interrupt routing, etc.,
+ * which are all specific to the board the i80321 is wired up to.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/iq80321.c 278613 2015-02-12 03:50:33Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i80321/iq80321reg.h>
+#include <arm/xscale/i80321/iq80321var.h>
+#include <arm/xscale/i80321/i80321_intr.h>
+
+#include <dev/pci/pcireg.h>
+
+
+int iq80321_probe(device_t);
+void iq80321_identify(driver_t *, device_t);
+int iq80321_attach(device_t);
+
+int
+iq80321_probe(device_t dev)
+{
+ device_set_desc(dev, "Intel 80321");
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+void
+iq80321_identify(driver_t *driver, device_t parent)
+{
+
+ BUS_ADD_CHILD(parent, 0, "iq", 0);
+}
+
+static struct arm32_dma_range i80321_dr;
+static int dma_range_init = 0;
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+ if (dma_range_init == 0)
+ return (NULL);
+ return (&i80321_dr);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+ if (dma_range_init == 0)
+ return (0);
+ return (1);
+}
+
+#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
+#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
+
+int
+iq80321_attach(device_t dev)
+{
+ struct i80321_softc *sc = device_get_softc(dev);
+ int b0u, b0l, b1u, b1l;
+ vm_paddr_t memstart = 0;
+ vm_size_t memsize = 0;
+ int busno;
+
+ /*
+ * Fill in the space tag for the i80321's own devices,
+ * and hand-craft the space handle for it (the device
+ * was mapped during early bootstrap).
+ */
+ i80321_bs_init(&i80321_bs_tag, sc);
+ sc->sc_st = &i80321_bs_tag;
+ sc->sc_sh = IQ80321_80321_VBASE;
+ sc->dev = dev;
+ sc->sc_is_host = 1;
+
+ /*
+ * Slice off a subregion for the Memory Controller -- we need it
+ * here in order read the memory size.
+ */
+ if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
+ VERDE_MCU_SIZE, &sc->sc_mcu_sh))
+ panic("%s: unable to subregion MCU registers",
+ device_get_name(dev));
+
+ if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
+ VERDE_ATU_SIZE, &sc->sc_atu_sh))
+ panic("%s: unable to subregion ATU registers",
+ device_get_name(dev));
+
+ /*
+ * We have mapped the PCI I/O windows in the early
+ * bootstrap phase.
+ */
+ sc->sc_iow_vaddr = IQ80321_IOW_VBASE;
+
+ /*
+ * Check the configuration of the ATU to see if another BIOS
+ * has configured us. If a PC BIOS didn't configure us, then:
+ * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
+ * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
+ * If a BIOS has configured us, at least one of those should be
+ * different. This is pretty fragile, but it's not clear what
+ * would work better.
+ */
+ b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0);
+ b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4);
+ b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8);
+ b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc);
+
+#ifdef VERBOSE_INIT_ARM
+ printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
+ b0l,b0u, b1l, b1u );
+#endif
+
+#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0
+ b0l &= PCI_MAPREG_MEM_ADDR_MASK;
+ b0u &= PCI_MAPREG_MEM_ADDR_MASK;
+ b1l &= PCI_MAPREG_MEM_ADDR_MASK;
+ b1u &= PCI_MAPREG_MEM_ADDR_MASK;
+
+#ifdef VERBOSE_INIT_ARM
+ printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
+ b0l,b0u, b1l, b1u );
+#endif
+
+ if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
+ sc->sc_is_host = 0;
+ else
+ sc->sc_is_host = 1;
+
+ /* FIXME: i force it's */
+
+#ifdef CPU_XSCALE_80219
+ sc->sc_is_host = 1;
+#endif
+
+ i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
+ /*
+ * We set up the Inbound Windows as follows:
+ *
+ * 0 Access to i80321 PMMRs
+ *
+ * 1 Reserve space for private devices
+ *
+ * 2 RAM access
+ *
+ * 3 Unused.
+ *
+ * This chunk needs to be customized for each IOP321 application.
+ */
+#if 0
+ sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
+ sc->sc_iwin[0].iwin_base_hi = 0;
+ sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
+ sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
+#endif
+ if (sc->sc_is_host) {
+
+ /* Map PCI:Local 1:1. */
+ sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
+ PCI_MAPREG_MEM_PREFETCHABLE_MASK |
+ PCI_MAPREG_MEM_TYPE_64BIT;
+ sc->sc_iwin[1].iwin_base_hi = 0;
+ } else {
+
+ sc->sc_iwin[1].iwin_base_lo = 0;
+ sc->sc_iwin[1].iwin_base_hi = 0;
+ }
+ sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
+ sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
+
+ if (sc->sc_is_host) {
+ sc->sc_iwin[2].iwin_base_lo = memstart |
+ PCI_MAPREG_MEM_PREFETCHABLE_MASK |
+ PCI_MAPREG_MEM_TYPE_64BIT;
+ sc->sc_iwin[2].iwin_base_hi = 0;
+ } else {
+ sc->sc_iwin[2].iwin_base_lo = 0;
+ sc->sc_iwin[2].iwin_base_hi = 0;
+ }
+ sc->sc_iwin[2].iwin_xlate = memstart;
+ sc->sc_iwin[2].iwin_size = memsize;
+
+ if (sc->sc_is_host) {
+ sc->sc_iwin[3].iwin_base_lo = 0 |
+ PCI_MAPREG_MEM_PREFETCHABLE_MASK |
+ PCI_MAPREG_MEM_TYPE_64BIT;
+ } else {
+ sc->sc_iwin[3].iwin_base_lo = 0;
+ }
+ sc->sc_iwin[3].iwin_base_hi = 0;
+ sc->sc_iwin[3].iwin_xlate = 0;
+ sc->sc_iwin[3].iwin_size = 0;
+
+#ifdef VERBOSE_INIT_ARM
+ printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
+ sc->sc_iwin[1].iwin_base_hi,
+ sc->sc_iwin[1].iwin_base_lo,
+ sc->sc_iwin[1].iwin_xlate,
+ sc->sc_iwin[1].iwin_size
+ );
+ printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
+ sc->sc_iwin[2].iwin_base_hi,
+ sc->sc_iwin[2].iwin_base_lo,
+ sc->sc_iwin[2].iwin_xlate,
+ sc->sc_iwin[2].iwin_size
+ );
+#endif
+
+ /*
+ * We set up the Outbound Windows as follows:
+ *
+ * 0 Access to private PCI space.
+ *
+ * 1 Unused.
+ */
+#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
+ sc->sc_owin[0].owin_xlate_lo =
+ PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
+ sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
+ /*
+ * Set the Secondary Outbound I/O window to map
+ * to PCI address 0 for all 64K of the I/O space.
+ */
+ sc->sc_ioout_xlate = 0;
+ i80321_attach(sc);
+ i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate;
+ i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
+ i80321_dr.dr_len = sc->sc_iwin[2].iwin_size;
+ dma_range_init = 1;
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
+ busno = PCIXSR_BUSNO(busno);
+ if (busno == 0xff)
+ busno = 0;
+ sc->sc_irq_rman.rm_type = RMAN_ARRAY;
+ sc->sc_irq_rman.rm_descr = "i80321 IRQs";
+ if (rman_init(&sc->sc_irq_rman) != 0 ||
+ rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0)
+ panic("i80321_attach: failed to set up IRQ rman");
+
+ device_add_child(dev, "obio", 0);
+ device_add_child(dev, "itimer", 0);
+ device_add_child(dev, "iopwdog", 0);
+#ifndef CPU_XSCALE_80219
+ device_add_child(dev, "iqseg", 0);
+#endif
+ device_add_child(dev, "pcib", busno);
+ device_add_child(dev, "i80321_dma", 0);
+ device_add_child(dev, "i80321_dma", 1);
+#ifndef CPU_XSCALE_80219
+ device_add_child(dev, "i80321_aau", 0);
+#endif
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ intr_enabled &= ~(1 << nb);
+ i80321_set_intrmask();
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ intr_enabled |= (1 << nb);
+ i80321_set_intrmask();
+}
+
+
+void
+cpu_reset()
+{
+ (void) disable_interrupts(PSR_I|PSR_F);
+ *(__volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE +
+ ATU_PCSR) = PCSR_RIB | PCSR_RPB;
+ printf("Reset failed!\n");
+ for(;;);
+}
+
+static struct resource *
+iq80321_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct i80321_softc *sc = device_get_softc(dev);
+ struct resource *rv;
+
+ if (type == SYS_RES_IRQ) {
+ rv = rman_reserve_resource(&sc->sc_irq_rman,
+ start, end, count, flags, child);
+ if (rv != NULL)
+ rman_set_rid(rv, *rid);
+ return (rv);
+ }
+ return (NULL);
+}
+
+static int
+iq80321_setup_intr(device_t dev, device_t child,
+ struct resource *ires, int flags, driver_filter_t *filt,
+ driver_intr_t *intr, void *arg, void **cookiep)
+{
+ int error;
+
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ filt, intr, arg, cookiep);
+ if (error)
+ return (error);
+ intr_enabled |= 1 << rman_get_start(ires);
+ i80321_set_intrmask();
+
+ return (0);
+}
+
+static int
+iq80321_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
+static device_method_t iq80321_methods[] = {
+ DEVMETHOD(device_probe, iq80321_probe),
+ DEVMETHOD(device_attach, iq80321_attach),
+ DEVMETHOD(device_identify, iq80321_identify),
+ DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource),
+ DEVMETHOD(bus_setup_intr, iq80321_setup_intr),
+ DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr),
+ {0, 0},
+};
+
+static driver_t iq80321_driver = {
+ "iq",
+ iq80321_methods,
+ sizeof(struct i80321_softc),
+};
+static devclass_t iq80321_devclass;
+
+DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i80321/iq80321.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/iq80321reg.h
===================================================================
--- trunk/sys/arm/xscale/i80321/iq80321reg.h (rev 0)
+++ trunk/sys/arm/xscale/i80321/iq80321reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,112 @@
+/* $MidnightBSD$ */
+/* $NetBSD: iq80321reg.h,v 1.4 2003/05/14 19:46:39 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/i80321/iq80321reg.h 161592 2006-08-24 23:51:28Z cognet $
+ *
+ */
+
+#ifndef _IQ80321REG_H_
+#define _IQ80321REG_H_
+
+/*
+ * Memory map and register definitions for the Intel IQ80321
+ * Evaluation Board.
+ */
+
+/*
+ * The memory map of the IQ80321 looks like so:
+ *
+ * ------------------------------
+ * Intel 80321 IOP Reserved
+ * FFFF E900 ------------------------------
+ * Peripheral Memory Mapped
+ * Registers
+ * FFFF E000 ------------------------------
+ * On-board devices
+ * FE80 0000 ------------------------------
+ * SDRAM
+ * A000 0000 ------------------------------
+ * Reserved
+ * 9100 0000 ------------------------------
+ * Flash
+ * 9080 0000 ------------------------------
+ * Reserved
+ * 9002 0000 ------------------------------
+ * ATU Outbound Transaction
+ * Windows
+ * 8000 0000 ------------------------------
+ * ATU Outbound Direct
+ * Addressing Windows
+ * 0000 1000 ------------------------------
+ * Initialization Boot Code
+ * from Flash
+ * 0000 0000 ------------------------------
+ */
+
+/*
+ * We allocate a page table for VA 0xfe400000 (4MB) and map the
+ * PCI I/O space (64K) and i80321 memory-mapped registers (4K) there.
+ */
+#define IQ80321_IOPXS_VBASE 0xfe400000UL
+#define IQ80321_IOW_VBASE IQ80321_IOPXS_VBASE
+#define IQ80321_80321_VBASE (IQ80321_IOW_VBASE + \
+ VERDE_OUT_XLATE_IO_WIN_SIZE)
+
+#define IQ80321_SDRAM_START 0xa0000000
+/*
+ * The IQ80321 on-board devices are mapped VA==PA during bootstrap.
+ * Conveniently, the size of the on-board register space is 1 section
+ * mapping.
+ */
+#define IQ80321_OBIO_BASE 0xfe800000UL
+#define IQ80321_OBIO_SIZE 0x00100000UL /* 1MB */
+
+#define IQ80321_UART1 0xfe800000UL /* TI 16550 */
+
+#if defined( CPU_XSCALE_80321 )
+#define IQ80321_7SEG_MSB 0xfe840000UL
+#define IQ80321_7SEG_LSB 0xfe850000UL
+
+#define IQ80321_ROT_SWITCH 0xfe8d0000UL
+
+#define IQ80321_BATTERY_STAT 0xfe8f0000UL
+#define BATTERY_STAT_PRES (1U << 0)
+#define BATTERY_STAT_CHRG (1U << 1)
+#define BATTERY_STAT_DISCHRG (1U << 2)
+#endif /* CPU_XSCALE_80321 */
+
+#endif /* _IQ80321REG_H_ */
Property changes on: trunk/sys/arm/xscale/i80321/iq80321reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/iq80321var.h
===================================================================
--- trunk/sys/arm/xscale/i80321/iq80321var.h (rev 0)
+++ trunk/sys/arm/xscale/i80321/iq80321var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,54 @@
+/* $MidnightBSD$ */
+/* $NetBSD: iq80321var.h,v 1.1 2002/03/27 21:51:30 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/i80321/iq80321var.h 139735 2005-01-05 21:58:49Z imp $
+ *
+ */
+
+#ifndef _IQ80321_IQ80321VAR_H_
+#define _IQ80321_IQ80321VAR_H_
+
+#include <dev/pci/pcivar.h>
+
+void iq80321_7seg(char, char);
+void iq80321_7seg_snake(void);
+
+#if 0
+void iq80321_pci_init(pci_chipset_tag_t, void *);
+#endif
+
+#endif /* _IQ80321_IQ80321VAR_H_ */
Property changes on: trunk/sys/arm/xscale/i80321/iq80321var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/obio.c
===================================================================
--- trunk/sys/arm/xscale/i80321/obio.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/obio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,164 @@
+/* $MidnightBSD$ */
+/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * On-board device autoconfiguration support for Intel IQ80321
+ * evaluation boards.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/obio.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/i80321/i80321reg.h>
+
+#include <arm/xscale/i80321/iq80321reg.h>
+#include <arm/xscale/i80321/obiovar.h>
+
+bus_space_tag_t obio_bs_tag;
+
+int obio_probe(device_t);
+int obio_attach(device_t);
+
+int
+obio_probe(device_t dev)
+{
+ return (0);
+}
+
+int
+obio_attach(device_t dev)
+{
+ struct obio_softc *sc = device_get_softc(dev);
+
+ obio_bs_tag = arm_base_bs_tag;
+ sc->oba_st = obio_bs_tag;
+ sc->oba_addr = IQ80321_OBIO_BASE;
+ sc->oba_size = IQ80321_OBIO_SIZE;
+ sc->oba_rman.rm_type = RMAN_ARRAY;
+ sc->oba_rman.rm_descr = "OBIO I/O";
+ if (rman_init(&sc->oba_rman) != 0 ||
+ rman_manage_region(&sc->oba_rman,
+ sc->oba_addr, sc->oba_addr + sc->oba_size) != 0)
+ panic("obio_attach: failed to set up I/O rman");
+ sc->oba_irq_rman.rm_type = RMAN_ARRAY;
+ sc->oba_irq_rman.rm_descr = "OBIO IRQ";
+ if (rman_init(&sc->oba_irq_rman) != 0 ||
+ rman_manage_region(&sc->oba_irq_rman, 28, 28) != 0)
+ panic("obio_attach: failed to set up IRQ rman");
+ device_add_child(dev, "uart", 0);
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+ return (0);
+}
+
+static struct resource *
+obio_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct resource *rv;
+ struct rman *rm;
+ bus_space_tag_t bt = NULL;
+ bus_space_handle_t bh = 0;
+ struct obio_softc *sc = device_get_softc(bus);
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ rm = &sc->oba_irq_rman;
+ break;
+ case SYS_RES_MEMORY:
+ return (NULL);
+ case SYS_RES_IOPORT:
+ rm = &sc->oba_rman;
+ bt = sc->oba_st;
+ bh = sc->oba_addr;
+ start = bh;
+ break;
+ default:
+ return (NULL);
+ }
+
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == NULL)
+ return (NULL);
+ if (type == SYS_RES_IRQ)
+ return (rv);
+ rman_set_rid(rv, *rid);
+ rman_set_bustag(rv, bt);
+ rman_set_bushandle(rv, bh);
+
+ return (rv);
+
+}
+
+static int
+obio_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ return (0);
+}
+static device_method_t obio_methods[] = {
+ DEVMETHOD(device_probe, obio_probe),
+ DEVMETHOD(device_attach, obio_attach),
+
+ DEVMETHOD(bus_alloc_resource, obio_alloc_resource),
+ DEVMETHOD(bus_activate_resource, obio_activate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ {0, 0},
+};
+
+static driver_t obio_driver = {
+ "obio",
+ obio_methods,
+ sizeof(struct obio_softc),
+};
+static devclass_t obio_devclass;
+
+DRIVER_MODULE(obio, iq, obio_driver, obio_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i80321/obio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/obiovar.h
===================================================================
--- trunk/sys/arm/xscale/i80321/obiovar.h (rev 0)
+++ trunk/sys/arm/xscale/i80321/obiovar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,59 @@
+/* $MidnightBSD$ */
+/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/i80321/obiovar.h 278727 2015-02-13 22:32:02Z ian $
+ *
+ */
+
+#ifndef _IQ80321_OBIOVAR_H_
+#define _IQ80321_OBIOVAR_H_
+
+#include <sys/rman.h>
+
+struct obio_softc {
+ bus_space_tag_t oba_st; /* bus space tag */
+ bus_addr_t oba_addr; /* address of device */
+ bus_size_t oba_size; /* size of device */
+ int oba_width; /* bus width */
+ int oba_irq; /* XINT interrupt bit # */
+ struct rman oba_rman;
+ struct rman oba_irq_rman;
+
+};
+extern bus_space_tag_t obio_bs_tag;
+
+#endif /* _IQ80321_OBIOVAR_H_ */
Property changes on: trunk/sys/arm/xscale/i80321/obiovar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/std.ep80219
===================================================================
--- trunk/sys/arm/xscale/i80321/std.ep80219 (rev 0)
+++ trunk/sys/arm/xscale/i80321/std.ep80219 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,7 @@
+#EP80219 board configuration
+#$FreeBSD: stable/10/sys/arm/xscale/i80321/std.ep80219 161592 2006-08-24 23:51:28Z cognet $
+include "../xscale/i80321/std.i80219"
+files "../xscale/i80321/files.ep80219"
+makeoptions KERNPHYSADDR=0xa0200000
+makeoptions KERNVIRTADDR=0xc0200000
+options COUNTS_PER_SEC=198000000
Property changes on: trunk/sys/arm/xscale/i80321/std.ep80219
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/std.i80219
===================================================================
--- trunk/sys/arm/xscale/i80321/std.i80219 (rev 0)
+++ trunk/sys/arm/xscale/i80321/std.i80219 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+#XScale i80219 generic configuration
+#$FreeBSD: stable/10/sys/arm/xscale/i80321/std.i80219 239362 2012-08-18 05:48:19Z andrew $
+files "../xscale/i80321/files.i80219"
+include "../xscale/std.xscale-be"
+cpu CPU_XSCALE_80219
Property changes on: trunk/sys/arm/xscale/i80321/std.i80219
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/std.i80321
===================================================================
--- trunk/sys/arm/xscale/i80321/std.i80321 (rev 0)
+++ trunk/sys/arm/xscale/i80321/std.i80321 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+#XScale i80321 generic configuration
+#$FreeBSD: stable/10/sys/arm/xscale/i80321/std.i80321 239362 2012-08-18 05:48:19Z andrew $
+files "../xscale/i80321/files.i80321"
+include "../xscale/std.xscale-be"
+cpu CPU_XSCALE_80321
Property changes on: trunk/sys/arm/xscale/i80321/std.i80321
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/std.iq31244
===================================================================
--- trunk/sys/arm/xscale/i80321/std.iq31244 (rev 0)
+++ trunk/sys/arm/xscale/i80321/std.iq31244 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,7 @@
+#IQ31244 board configuration
+#$FreeBSD: stable/10/sys/arm/xscale/i80321/std.iq31244 153277 2005-12-09 23:52:51Z cognet $
+include "../xscale/i80321/std.i80321"
+files "../xscale/i80321/files.iq31244"
+makeoptions KERNPHYSADDR=0xa0200000
+makeoptions KERNVIRTADDR=0xc0200000
+options COUNTS_PER_SEC=198000000
Property changes on: trunk/sys/arm/xscale/i80321/std.iq31244
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/uart_bus_i80321.c
===================================================================
--- trunk/sys/arm/xscale/i80321/uart_bus_i80321.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/uart_bus_i80321.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,77 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/uart_bus_i80321.c 139735 2005-01-05 21:58:49Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include "uart_if.h"
+
+static int uart_i80321_probe(device_t dev);
+
+static device_method_t uart_i80321_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uart_i80321_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, uart_bus_detach),
+ { 0, 0 }
+};
+
+static driver_t uart_i80321_driver = {
+ uart_driver_name,
+ uart_i80321_methods,
+ sizeof(struct uart_softc),
+};
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+static int
+uart_i80321_probe(device_t dev)
+{
+ struct uart_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
+ sc->sc_class = &uart_ns8250_class;
+ bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
+ return(uart_bus_probe(dev, 0, 0, 0, 0));
+}
+
+
+DRIVER_MODULE(uart, obio, uart_i80321_driver, uart_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i80321/uart_bus_i80321.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i80321/uart_cpu_i80321.c
===================================================================
--- trunk/sys/arm/xscale/i80321/uart_cpu_i80321.c (rev 0)
+++ trunk/sys/arm/xscale/i80321/uart_cpu_i80321.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,68 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i80321/uart_cpu_i80321.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i80321/obiovar.h>
+
+bus_space_tag_t uart_bus_space_io;
+bus_space_tag_t uart_bus_space_mem;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+ return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+ di->ops = uart_getops(&uart_ns8250_class);
+ di->bas.chan = 0;
+ di->bas.bst = obio_bs_tag;
+ di->bas.regshft = 0;
+ di->bas.rclk = 0;
+ di->baudrate = 115200;
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ uart_bus_space_io = obio_bs_tag;
+ uart_bus_space_mem = NULL;
+ di->bas.bsh = 0xfe800000;
+ return (0);
+}
Property changes on: trunk/sys/arm/xscale/i80321/uart_cpu_i80321.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/crb_machdep.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/crb_machdep.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/crb_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,335 @@
+/* $MidnightBSD$ */
+/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
+
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work.
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/crb_machdep.c 278727 2015-02-13 22:32:02Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/cons.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/kdb.h>
+#include <sys/msgbuf.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <machine/devmap.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/physmem.h>
+#include <sys/reboot.h>
+
+
+#include <arm/xscale/i80321/i80321var.h> /* For i80321_calibrate_delay() */
+
+#include <arm/xscale/i8134x/i81342reg.h>
+#include <arm/xscale/i8134x/i81342var.h>
+#include <arm/xscale/i8134x/obiovar.h>
+
+
+#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
+#define KERNEL_PT_IOPXS 1
+#define KERNEL_PT_BEFOREKERN 2
+#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */
+#define KERNEL_PT_AFKERNEL_NUM 9
+
+/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
+#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
+
+struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
+
+/* Physical and virtual addresses for some global pages */
+
+struct pv_addr systempage;
+struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+struct pv_addr kernelstack;
+
+/* Static device mappings. */
+static const struct arm_devmap_entry iq81342_devmap[] = {
+ {
+ IOP34X_VADDR,
+ IOP34X_HWADDR,
+ IOP34X_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ /*
+ * Cheat and map a whole section, this will bring
+ * both PCI-X and PCI-E outbound I/O
+ */
+ IOP34X_PCIX_OIOBAR_VADDR &~ (0x100000 - 1),
+ IOP34X_PCIX_OIOBAR &~ (0x100000 - 1),
+ 0x100000,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ IOP34X_PCE1_VADDR,
+ IOP34X_PCE1,
+ IOP34X_PCE1_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ }
+};
+
+#define SDRAM_START 0x00000000
+
+extern vm_offset_t xscale_cache_clean_addr;
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+ struct pv_addr kernel_l1pt;
+ struct pv_addr dpcpu;
+ int loop, i;
+ u_int l1pagetable;
+ vm_offset_t freemempos;
+ vm_offset_t freemem_pt;
+ vm_offset_t afterkern;
+ vm_offset_t freemem_after;
+ vm_offset_t lastaddr;
+ uint32_t memsize, memstart;
+
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+ set_cpufuncs();
+ pcpu_init(pcpup, 0, sizeof(struct pcpu));
+ PCPU_SET(curthread, &thread0);
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+ freemempos = 0x00200000;
+ /* Define a macro to simplify memory allocation */
+#define valloc_pages(var, np) \
+ alloc_pages((var).pv_pa, (np)); \
+ (var).pv_va = (var).pv_pa + 0xc0000000;
+
+#define alloc_pages(var, np) \
+ freemempos -= (np * PAGE_SIZE); \
+ (var) = freemempos; \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos -= PAGE_SIZE;
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[loop],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ } else {
+ kernel_pt_table[loop].pv_pa = freemempos +
+ (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
+ L2_TABLE_SIZE_REAL;
+ kernel_pt_table[loop].pv_va =
+ kernel_pt_table[loop].pv_pa + 0xc0000000;
+ }
+ }
+ freemem_pt = freemempos;
+ freemempos = 0x00100000;
+ /*
+ * Allocate a page for the system page mapped to V0x00000000
+ * This page will just contain the system vectors and can be
+ * shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate dynamic per-cpu area. */
+ valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
+ dpcpu_init((void *)dpcpu.pv_va, 0);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE);
+ valloc_pages(abtstack, ABT_STACK_SIZE);
+ valloc_pages(undstack, UND_STACK_SIZE);
+ valloc_pages(kernelstack, KSTACK_PAGES);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+ /*
+ * Now we start construction of the L1 page table
+ * We start by mapping the L2 page tables into the L1.
+ * This means that we can replace L1 mappings later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /* Map the L2 pages tables in the L1 page table */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1),
+ &kernel_pt_table[KERNEL_PT_SYS]);
+ pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000,
+ 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000,
+ (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1),
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1);
+ afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE
+ - 1));
+ for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
+ pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
+ &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
+ }
+
+
+ /* Map the vector page. */
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ arm_devmap_bootstrap(l1pagetable, iq81342_devmap);
+ /*
+ * Give the XScale global cache clean code an appropriately
+ * sized chunk of unmapped VA space starting at 0xff000000
+ * (our device mappings end before this address).
+ */
+ xscale_cache_clean_addr = 0xff000000U;
+
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+ cpu_setup("");
+
+ i80321_calibrate_delay();
+ i81342_sdram_bounds(obio_bs_tag, IOP34X_VADDR, &memstart, &memsize);
+ physmem = memsize / PAGE_SIZE;
+ cninit();
+ /* Set stack for exception handlers */
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+
+ pmap_curmaxkvaddr = afterkern + PAGE_SIZE;
+
+ vm_max_kernel_address = 0xd0000000;
+ pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
+ msgbufp = (void*)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+
+ /*
+ * Add the physical ram we have available.
+ *
+ * Exclude the kernel (and all the things we allocated which immediately
+ * follow the kernel) from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ arm_physmem_hardware_region(SDRAM_START, memsize);
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+}
Property changes on: trunk/sys/arm/xscale/i8134x/crb_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/files.crb
===================================================================
--- trunk/sys/arm/xscale/i8134x/files.crb (rev 0)
+++ trunk/sys/arm/xscale/i8134x/files.crb 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,3 @@
+# $FreeBSD: stable/10/sys/arm/xscale/i8134x/files.crb 172297 2007-09-22 16:25:43Z cognet $
+arm/xscale/i8134x/crb_machdep.c standard
+arm/xscale/i8134x/iq81342_7seg.c optional 7seg
Property changes on: trunk/sys/arm/xscale/i8134x/files.crb
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/files.i81342
===================================================================
--- trunk/sys/arm/xscale/i8134x/files.i81342 (rev 0)
+++ trunk/sys/arm/xscale/i8134x/files.i81342 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,15 @@
+# $FreeBSD: stable/10/sys/arm/xscale/i8134x/files.i81342 278727 2015-02-13 22:32:02Z ian $
+arm/arm/bus_space_base.c standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_xscale.S standard
+arm/arm/cpufunc_asm_xscale_c3.S standard
+arm/xscale/i80321/i80321_timer.c standard
+arm/xscale/i80321/i80321_wdog.c optional iopwdog
+arm/xscale/i8134x/i81342.c standard
+arm/xscale/i8134x/i81342_mcu.c standard
+arm/xscale/i8134x/i81342_pci.c optional pci
+arm/xscale/i8134x/i81342_space.c standard
+arm/xscale/i8134x/obio.c standard
+arm/xscale/i8134x/uart_bus_i81342.c optional uart
+arm/xscale/i8134x/uart_cpu_i81342.c optional uart
+dev/uart/uart_dev_ns8250.c optional uart
Property changes on: trunk/sys/arm/xscale/i8134x/files.i81342
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/i81342.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/i81342.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/i81342.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,467 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/i81342.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/i8134x/i81342reg.h>
+#include <arm/xscale/i8134x/i81342var.h>
+
+#define WDTCR_ENABLE1 0x1e1e1e1e
+#define WDTCR_ENABLE2 0xe1e1e1e1
+
+static volatile int intr_enabled0;
+static volatile int intr_enabled1;
+static volatile int intr_enabled2;
+static volatile int intr_enabled3;
+
+struct bus_space i81342_bs_tag;
+
+/* Read the interrupt pending register */
+
+static __inline
+uint32_t intpnd0_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c0, c3, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intpnd1_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c1, c3, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intpnd2_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c2, c3, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intpnd3_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c3, c3, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+/* Read the interrupt control register */
+/* 0 masked, 1 unmasked */
+static __inline
+uint32_t intctl0_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c0, c4, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intctl1_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c1, c4, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intctl2_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c2, c4, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intctl3_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c3, c4, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+/* Write the interrupt control register */
+
+static __inline
+void intctl0_write(uint32_t val)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c0, c4, 0"
+ : : "r" (val));
+}
+
+static __inline
+void intctl1_write(uint32_t val)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c1, c4, 0"
+ : : "r" (val));
+}
+
+static __inline
+void intctl2_write(uint32_t val)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c2, c4, 0"
+ : : "r" (val));
+}
+
+static __inline
+void intctl3_write(uint32_t val)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c3, c4, 0"
+ : : "r" (val));
+}
+
+/* Read the interrupt steering register */
+/* 0 IRQ 1 FIQ */
+static __inline
+uint32_t intstr0_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c0, c5, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intstr1_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c1, c5, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intstr2_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c2, c5, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+static __inline
+uint32_t intstr3_read(void)
+{
+ uint32_t ret;
+
+ __asm __volatile("mrc p6, 0, %0, c3, c5, 0"
+ : "=r" (ret));
+ return (ret);
+}
+
+/* Write the interrupt steering register */
+
+static __inline
+void intstr0_write(uint32_t val)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c0, c5, 0"
+ : : "r" (val));
+}
+
+static __inline
+void intstr1_write(uint32_t val)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c1, c5, 0"
+ : : "r" (val));
+}
+
+static __inline
+void intstr2_write(uint32_t val)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c2, c5, 0"
+ : : "r" (val));
+}
+
+static __inline
+void intstr3_write(uint32_t val)
+{
+
+ __asm __volatile("mcr p6, 0, %0, c3, c5, 0"
+ : : "r" (val));
+}
+
+void
+cpu_reset(void)
+{
+
+ disable_interrupts(PSR_I);
+ /* XXX: Use the watchdog to reset for now */
+ __asm __volatile("mcr p6, 0, %0, c8, c9, 0\n"
+ "mcr p6, 0, %1, c7, c9, 0\n"
+ "mcr p6, 0, %2, c7, c9, 0\n"
+ : : "r" (1), "r" (WDTCR_ENABLE1), "r" (WDTCR_ENABLE2));
+ while (1);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+
+ if (nb < 32) {
+ intr_enabled0 &= ~(1 << nb);
+ intctl0_write(intr_enabled0);
+ } else if (nb < 64) {
+ intr_enabled1 &= ~(1 << (nb - 32));
+ intctl1_write(intr_enabled1);
+ } else if (nb < 96) {
+ intr_enabled2 &= ~(1 << (nb - 64));
+ intctl2_write(intr_enabled2);
+ } else {
+ intr_enabled3 &= ~(1 << (nb - 96));
+ intctl3_write(intr_enabled3);
+ }
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ if (nb < 32) {
+ intr_enabled0 |= (1 << nb);
+ intctl0_write(intr_enabled0);
+ } else if (nb < 64) {
+ intr_enabled1 |= (1 << (nb - 32));
+ intctl1_write(intr_enabled1);
+ } else if (nb < 96) {
+ intr_enabled2 |= (1 << (nb - 64));
+ intctl2_write(intr_enabled2);
+ } else {
+ intr_enabled3 |= (1 << (nb - 96));
+ intctl3_write(intr_enabled3);
+ }
+}
+
+int
+arm_get_next_irq(int last __unused)
+{
+ uint32_t val;
+ val = intpnd0_read() & intr_enabled0;
+ if (val)
+ return (ffs(val) - 1);
+ val = intpnd1_read() & intr_enabled1;
+ if (val)
+ return (32 + ffs(val) - 1);
+ val = intpnd2_read() & intr_enabled2;
+ if (val)
+ return (64 + ffs(val) - 1);
+ val = intpnd3_read() & intr_enabled3;
+ if (val)
+ return (96 + ffs(val) - 1);
+ return (-1);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+ return (NULL);
+}
+
+static int
+i81342_probe(device_t dev)
+{
+ unsigned int freq;
+
+ freq = *(volatile unsigned int *)(IOP34X_VADDR + IOP34X_PFR);
+
+ switch (freq & IOP34X_FREQ_MASK) {
+ case IOP34X_FREQ_600:
+ device_set_desc(dev, "Intel 81342 600MHz");
+ break;
+ case IOP34X_FREQ_667:
+ device_set_desc(dev, "Intel 81342 667MHz");
+ break;
+ case IOP34X_FREQ_800:
+ device_set_desc(dev, "Intel 81342 800MHz");
+ break;
+ case IOP34X_FREQ_833:
+ device_set_desc(dev, "Intel 81342 833MHz");
+ break;
+ case IOP34X_FREQ_1000:
+ device_set_desc(dev, "Intel 81342 1000MHz");
+ break;
+ case IOP34X_FREQ_1200:
+ device_set_desc(dev, "Intel 81342 1200MHz");
+ break;
+ default:
+ device_set_desc(dev, "Intel 81342 unknown frequency");
+ break;
+ }
+ return (0);
+}
+
+static void
+i81342_identify(driver_t *driver, device_t parent)
+{
+
+ BUS_ADD_CHILD(parent, 0, "iq", 0);
+}
+
+static int
+i81342_attach(device_t dev)
+{
+ struct i81342_softc *sc = device_get_softc(dev);
+ uint32_t esstrsr;
+
+ i81342_bs_init(&i81342_bs_tag, sc);
+ sc->sc_st = &i81342_bs_tag;
+ sc->sc_sh = IOP34X_VADDR;
+ esstrsr = bus_space_read_4(sc->sc_st, sc->sc_sh, IOP34X_ESSTSR0);
+ sc->sc_atux_sh = IOP34X_ATUX_ADDR(esstrsr) - IOP34X_HWADDR +
+ IOP34X_VADDR;
+ sc->sc_atue_sh = IOP34X_ATUE_ADDR(esstrsr) - IOP34X_HWADDR +
+ IOP34X_VADDR;
+ /* Disable all interrupts. */
+ intctl0_write(0);
+ intctl1_write(0);
+ intctl2_write(0);
+ intctl3_write(0);
+ /* Defaults to IRQ */
+ intstr0_write(0);
+ intstr1_write(0);
+ intstr2_write(0);
+ intstr3_write(0);
+ sc->sc_irq_rman.rm_type = RMAN_ARRAY;
+ sc->sc_irq_rman.rm_descr = "i81342 IRQs";
+ if (rman_init(&sc->sc_irq_rman) != 0 ||
+ rman_manage_region(&sc->sc_irq_rman, 0, 127) != 0)
+ panic("i81342_attach: failed to set up IRQ rman");
+
+ device_add_child(dev, "obio", 0);
+ device_add_child(dev, "itimer", 0);
+ device_add_child(dev, "iopwdog", 0);
+ device_add_child(dev, "pcib", 0);
+ device_add_child(dev, "pcib", 1);
+ device_add_child(dev, "iqseg", 0);
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+ return (0);
+}
+
+static struct resource *
+i81342_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct i81342_softc *sc = device_get_softc(dev);
+ struct resource *rv;
+
+ if (type == SYS_RES_IRQ) {
+ rv = rman_reserve_resource(&sc->sc_irq_rman,
+ start, end, count, flags, child);
+ if (rv != NULL)
+ rman_set_rid(rv, *rid);
+ return (rv);
+ }
+
+ return (NULL);
+}
+
+static int
+i81342_setup_intr(device_t dev, device_t child, struct resource *ires,
+ int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
+ void **cookiep)
+{
+ int error;
+
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ filt, intr, arg, cookiep);
+ if (error)
+ return (error);
+ return (0);
+}
+
+static int
+i81342_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
+static device_method_t i81342_methods[] = {
+ DEVMETHOD(device_probe, i81342_probe),
+ DEVMETHOD(device_attach, i81342_attach),
+ DEVMETHOD(device_identify, i81342_identify),
+ DEVMETHOD(bus_alloc_resource, i81342_alloc_resource),
+ DEVMETHOD(bus_setup_intr, i81342_setup_intr),
+ DEVMETHOD(bus_teardown_intr, i81342_teardown_intr),
+ {0, 0},
+};
+
+static driver_t i81342_driver = {
+ "iq",
+ i81342_methods,
+ sizeof(struct i81342_softc),
+};
+static devclass_t i81342_devclass;
+
+DRIVER_MODULE(iq, nexus, i81342_driver, i81342_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i8134x/i81342.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/i81342_mcu.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/i81342_mcu.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/i81342_mcu.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,57 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/i81342_mcu.c 236987 2012-06-13 04:38:09Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <arm/xscale/i8134x/i81342reg.h>
+#include <arm/xscale/i8134x/i81342var.h>
+
+void
+i81342_sdram_bounds(bus_space_tag_t bt, bus_space_handle_t bh,
+ vm_paddr_t *start, vm_size_t *size)
+{
+ uint32_t reg;
+ int bank_nb;
+
+ reg = bus_space_read_4(bt, bh, SMC_SDBR);
+ *start = (reg & SMC_SDBR_BASEADDR_MASK);
+ reg = bus_space_read_4(bt, bh, SMC_SBSR);
+ if (reg & SMC_SBSR_BANK_NB)
+ bank_nb = 1;
+ else
+ bank_nb = 2;
+
+ *size = (reg & SMC_SBSR_BANK_SZ_MASK) * bank_nb;
+}
Property changes on: trunk/sys/arm/xscale/i8134x/i81342_mcu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/i81342_pci.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/i81342_pci.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/i81342_pci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,545 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/i81342_pci.c 259329 2013-12-13 20:43:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/types.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/pcb.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <arm/xscale/i8134x/i81342reg.h>
+#include <arm/xscale/i8134x/i81342var.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcib_private.h>
+#include "pcib_if.h"
+
+#include <dev/pci/pcireg.h>
+
+static pcib_read_config_t i81342_pci_read_config;
+static pcib_write_config_t i81342_pci_write_config;
+
+static int
+i81342_pci_probe(device_t dev)
+{
+ struct i81342_pci_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (device_get_unit(dev) == 0) {
+ device_set_desc(dev, "i81342 PCI-X bus");
+ sc->sc_is_atux = 1;
+ } else {
+ device_set_desc(dev, "i81342 PCIe bus");
+ sc->sc_is_atux = 0;
+ }
+ return (0);
+}
+
+#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
+#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
+
+static int
+i81342_pci_attach(device_t dev)
+{
+ struct i81342_softc *parent_sc;
+ struct i81342_pci_softc *sc;
+ uint32_t memsize, memstart;
+ uint32_t reg;
+ int func;
+ uint32_t busno;
+
+ sc = device_get_softc(dev);
+ parent_sc = device_get_softc(device_get_parent(dev));
+ sc->sc_atu_sh = sc->sc_is_atux ? parent_sc->sc_atux_sh :
+ parent_sc->sc_atue_sh;
+ sc->sc_st = parent_sc->sc_st;
+ if (bus_space_read_4(sc->sc_st, parent_sc->sc_sh, IOP34X_ESSTSR0)
+ & IOP34X_INT_SEL_PCIX) {
+ if (sc->sc_is_atux)
+ func = 5;
+ else
+ func = 0;
+ } else {
+ if (sc->sc_is_atux)
+ func = 0;
+ else
+ func = 5;
+ }
+ i81342_io_bs_init(&sc->sc_pciio, sc);
+ i81342_mem_bs_init(&sc->sc_pcimem, sc);
+ i81342_sdram_bounds(sc->sc_st, IOP34X_VADDR, &memstart, &memsize);
+ if (sc->sc_is_atux) {
+ reg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
+ if (reg & ATUX_P_RSTOUT) {
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR,
+ reg &~ ATUX_P_RSTOUT);
+ DELAY(200);
+ }
+ }
+ /* Setup the Inbound windows. */
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR0, 0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR0, 0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, 0);
+
+ /* Set the mapping Physical address <=> PCI address */
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR1,
+ memstart | PCI_MAPREG_MEM_PREFETCHABLE_MASK |
+ PCI_MAPREG_MEM_TYPE_64BIT);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR1, 0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, ~(memsize - 1)
+ &~(0xfff));
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR1, memstart);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUTVR1, 0);
+
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR2, 0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR2, 0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, 0);
+
+ /* Setup the Outbound IO Bar */
+ if (sc->sc_is_atux)
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOBAR,
+ (IOP34X_PCIX_OIOBAR >> 4) | func);
+ else
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOBAR,
+ (IOP34X_PCIE_OIOBAR >> 4) | func);
+
+ /* Setup the Outbound windows */
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR0, 0);
+ if (sc->sc_is_atux)
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR1,
+ (IOP34X_PCIX_OMBAR >> 32) | (func << ATU_OUMBAR_FUNC) |
+ ATU_OUMBAR_EN);
+ else
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR1,
+ (IOP34X_PCIE_OMBAR >> 32) | (func << ATU_OUMBAR_FUNC) |
+ ATU_OUMBAR_EN);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMWTVR1, 0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR2, 0);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR3, 0);
+
+ /* Enable the outbound windows. */
+ reg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_CR);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_CR,
+ reg | ATU_CR_OUT_EN);
+
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR,
+ bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR) & ATUX_ISR_ERRMSK);
+ /*
+ * Enable bus mastering, memory access, SERR, and parity
+ * checking on the ATU.
+ */
+ if (sc->sc_is_atux) {
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
+ busno = PCIXSR_BUSNO(busno);
+ } else {
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
+ busno = PCIE_BUSNO(busno);
+ }
+ reg = bus_space_read_2(sc->sc_st, sc->sc_atu_sh, ATU_CMD);
+ reg |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN |
+ PCIM_CMD_SERRESPEN;
+ bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_CMD, reg);
+ sc->sc_busno = busno;
+ /* Initialize memory and i/o rmans. */
+ sc->sc_io_rman.rm_type = RMAN_ARRAY;
+ sc->sc_io_rman.rm_descr = "I81342 PCI I/O Ports";
+ if (rman_init(&sc->sc_io_rman) != 0 ||
+ rman_manage_region(&sc->sc_io_rman,
+ sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
+ IOP34X_PCIE_OIOBAR_VADDR,
+ (sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
+ IOP34X_PCIE_OIOBAR_VADDR) + IOP34X_OIOBAR_SIZE) != 0) {
+ panic("i81342_pci_probe: failed to set up I/O rman");
+ }
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "I81342 PCI Memory";
+ if (rman_init(&sc->sc_mem_rman) != 0 ||
+ rman_manage_region(&sc->sc_mem_rman,
+ 0, 0xffffffff) != 0) {
+ panic("i81342_pci_attach: failed to set up memory rman");
+ }
+ sc->sc_irq_rman.rm_type = RMAN_ARRAY;
+ sc->sc_irq_rman.rm_descr = "i81342 PCI IRQs";
+ if (sc->sc_is_atux) {
+ if (rman_init(&sc->sc_irq_rman) != 0 ||
+ rman_manage_region(&sc->sc_irq_rman, ICU_INT_XINT0,
+ ICU_INT_XINT3) != 0)
+ panic("i83142_pci_attach: failed to set up IRQ rman");
+ } else {
+ if (rman_init(&sc->sc_irq_rman) != 0 ||
+ rman_manage_region(&sc->sc_irq_rman, ICU_INT_ATUE_MA,
+ ICU_INT_ATUE_MD) != 0)
+ panic("i81342_pci_attach: failed to set up IRQ rman");
+
+ }
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR,
+ bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR) & ATUX_ISR_ERRMSK);
+ device_add_child(dev, "pci", busno);
+ return (bus_generic_attach(dev));
+}
+
+static int
+i81342_pci_maxslots(device_t dev)
+{
+
+ return (PCI_SLOTMAX);
+}
+
+static void
+i81342_pci_conf_setup(struct i81342_pci_softc *sc, int bus, int slot, int func,
+ int reg, uint32_t *addr)
+{
+ uint32_t busno;
+
+ if (sc->sc_is_atux) {
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
+ busno = PCIXSR_BUSNO(busno);
+ } else {
+ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
+ busno = PCIE_BUSNO(busno);
+ }
+ bus &= 0xff;
+ slot &= 0x1f;
+ func &= 0x7;
+ if (sc->sc_is_atux) {
+ if (busno == bus)
+ *addr = (1 << (slot + 16)) | (slot << 11) |
+ (func << 8) | reg;
+ else
+ *addr = (bus << 16) | (slot << 11) | (func << 11) |
+ reg | 1;
+ } else {
+ *addr = (bus << 24) | (slot << 19) | (func << 16) | reg;
+ if (bus != busno)
+ *addr |= 1;
+ }
+}
+
+static u_int32_t
+i81342_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, int bytes)
+{
+ struct i81342_pci_softc *sc = device_get_softc(dev);
+ uint32_t addr;
+ uint32_t ret = 0;
+ uint32_t isr;
+ int err = 0;
+ vm_offset_t va;
+
+ i81342_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, sc->sc_is_atux ?
+ ATUX_OCCAR : ATUE_OCCAR, addr);
+ if (sc->sc_is_atux)
+ va = sc->sc_atu_sh + ATUX_OCCDR;
+ else
+ va = sc->sc_atu_sh + ATUE_OCCDR;
+ switch (bytes) {
+ case 1:
+ err = badaddr_read((void*)(va + (reg & 3)), 1, &ret);
+ break;
+ case 2:
+ err = badaddr_read((void*)(va + (reg & 3)), 2, &ret);
+ break;
+ case 4:
+ err = badaddr_read((void *)(va) , 4, &ret);
+ break;
+ default:
+ printf("i81342_read_config: invalid size %d\n", bytes);
+ ret = -1;
+ }
+ if (err) {
+ isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR);
+ if (sc->sc_is_atux)
+ isr &= ATUX_ISR_ERRMSK;
+ else
+ isr &= ATUE_ISR_ERRMSK;
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR, isr);
+ ret = -1;
+ }
+
+ return (ret);
+}
+
+static void
+i81342_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, u_int32_t data, int bytes)
+{
+ struct i81342_pci_softc *sc = device_get_softc(dev);
+ uint32_t addr;
+ vm_offset_t va;
+
+ i81342_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr);
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, sc->sc_is_atux ?
+ ATUX_OCCAR : ATUE_OCCAR, addr);
+ va = sc->sc_is_atux ? ATUX_OCCDR : ATUE_OCCDR;
+ switch (bytes) {
+ case 1:
+ bus_space_write_1(sc->sc_st, sc->sc_atu_sh, va + (reg & 3)
+ , data);
+ break;
+ case 2:
+ bus_space_write_2(sc->sc_st, sc->sc_atu_sh, va + (reg & 3)
+ , data);
+ break;
+ case 4:
+ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, va, data);
+ break;
+ default:
+ printf("i81342_pci_write_config: Invalid size : %d\n", bytes);
+ }
+
+
+}
+
+static struct resource *
+i81342_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct i81342_pci_softc *sc = device_get_softc(bus);
+ struct resource *rv;
+ struct rman *rm;
+ bus_space_tag_t bt = NULL;
+ bus_space_handle_t bh = 0;
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ rm = &sc->sc_irq_rman;
+ break;
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_mem_rman;
+ bt = &sc->sc_pcimem;
+ bh = 0;
+ break;
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io_rman;
+ bt = &sc->sc_pciio;
+ bh = sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
+ IOP34X_PCIE_OIOBAR_VADDR;
+ start += bh;
+ end += bh;
+ break;
+ default:
+ return (NULL);
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == NULL)
+ return (NULL);
+ rman_set_rid(rv, *rid);
+ if (type != SYS_RES_IRQ) {
+ if (type == SYS_RES_MEMORY)
+ bh += (rman_get_start(rv));
+ rman_set_bustag(rv, bt);
+ rman_set_bushandle(rv, bh);
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+ }
+ return (rv);
+
+
+ return (NULL);
+}
+
+static int
+i81342_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ u_long p;
+ int error;
+
+ if (type == SYS_RES_MEMORY) {
+ error = bus_space_map(rman_get_bustag(r),
+ rman_get_bushandle(r), rman_get_size(r), 0, &p);
+ if (error)
+ return (error);
+ rman_set_bushandle(r, p);
+
+ }
+ return (rman_activate_resource(r));
+}
+
+static int
+i81342_pci_setup_intr(device_t dev, device_t child, struct resource *ires,
+ int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
+ void **cookiep)
+{
+
+ return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ filt, intr, arg, cookiep));
+}
+
+
+
+static int
+i81342_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
+static int
+i81342_pci_route_interrupt(device_t pcib, device_t dev, int pin)
+{
+ struct i81342_pci_softc *sc;
+ int device;
+
+ device = pci_get_slot(dev);
+ sc = device_get_softc(pcib);
+ /* XXX: Is board specific */
+ if (sc->sc_is_atux) {
+ /* PCI-X */
+ switch(device) {
+ case 1:
+ switch (pin) {
+ case 1:
+ return (ICU_INT_XINT1);
+ case 2:
+ return (ICU_INT_XINT2);
+ case 3:
+ return (ICU_INT_XINT3);
+ case 4:
+ return (ICU_INT_XINT0);
+ default:
+ break;
+ }
+ case 2:
+ switch (pin) {
+ case 1:
+ return (ICU_INT_XINT2);
+ case 2:
+ return (ICU_INT_XINT3);
+ case 3:
+ return (ICU_INT_XINT2);
+ case 4:
+ return (ICU_INT_XINT3);
+ default:
+ break;
+ }
+ }
+
+ } else {
+ switch (pin) {
+ case 1:
+ return (ICU_INT_ATUE_MA);
+ case 2:
+ return (ICU_INT_ATUE_MB);
+ case 3:
+ return (ICU_INT_ATUE_MC);
+ case 4:
+ return (ICU_INT_ATUE_MD);
+ default:
+ break;
+ }
+ }
+ printf("Warning: couldn't map %s IRQ for device %d pin %d\n",
+ sc->sc_is_atux ? "PCI-X" : "PCIe", device, pin);
+ return (-1);
+}
+
+static int
+i81342_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct i81342_pci_softc *sc = device_get_softc(dev);
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = 0;
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_busno;
+ return (0);
+
+ }
+ return (ENOENT);
+}
+
+static int
+i81342_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
+{
+ struct i81342_pci_softc * sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ return (EINVAL);
+ case PCIB_IVAR_BUS:
+ sc->sc_busno = result;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+static device_method_t i81342_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, i81342_pci_probe),
+ DEVMETHOD(device_attach, i81342_pci_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, i81342_read_ivar),
+ DEVMETHOD(bus_write_ivar, i81342_write_ivar),
+ DEVMETHOD(bus_alloc_resource, i81342_pci_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, i81342_pci_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, i81342_pci_setup_intr),
+ DEVMETHOD(bus_teardown_intr, i81342_pci_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, i81342_pci_maxslots),
+ DEVMETHOD(pcib_read_config, i81342_pci_read_config),
+ DEVMETHOD(pcib_write_config, i81342_pci_write_config),
+ DEVMETHOD(pcib_route_interrupt, i81342_pci_route_interrupt),
+
+ DEVMETHOD_END
+};
+
+static driver_t i81342_pci_driver = {
+ "pcib",
+ i81342_pci_methods,
+ sizeof(struct i81342_pci_softc),
+};
+
+static devclass_t i81342_pci_devclass;
+
+DRIVER_MODULE(ipci, iq, i81342_pci_driver, i81342_pci_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i8134x/i81342_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/i81342_space.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/i81342_space.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/i81342_space.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,233 @@
+/* $MidnightBSD$ */
+/* $NetBSD: i80321_space.c,v 1.6 2003/10/06 15:43:35 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * bus_space functions for i81342 I/O Processor.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/i81342_space.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
+#include <machine/pcb.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/i8134x/i81342reg.h>
+#include <arm/xscale/i8134x/i81342var.h>
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(i81342);
+bs_protos(i81342_io);
+bs_protos(i81342_mem);
+
+void
+i81342_bs_init(bus_space_tag_t bs, void *cookie)
+{
+
+ *bs = *arm_base_bs_tag;
+ bs->bs_privdata = cookie;
+}
+
+void
+i81342_io_bs_init(bus_space_tag_t bs, void *cookie)
+{
+
+ *bs = *arm_base_bs_tag;
+ bs->bs_privdata = cookie;
+
+ bs->bs_map = i81342_io_bs_map;
+ bs->bs_unmap = i81342_io_bs_unmap;
+ bs->bs_alloc = i81342_io_bs_alloc;
+ bs->bs_free = i81342_io_bs_free;
+
+}
+
+void
+i81342_mem_bs_init(bus_space_tag_t bs, void *cookie)
+{
+
+ *bs = *arm_base_bs_tag;
+ bs->bs_privdata = cookie;
+
+ bs->bs_map = i81342_mem_bs_map;
+ bs->bs_unmap = i81342_mem_bs_unmap;
+ bs->bs_alloc = i81342_mem_bs_alloc;
+ bs->bs_free = i81342_mem_bs_free;
+
+}
+
+/* *** Routines shared by i81342, PCI IO, and PCI MEM. *** */
+
+int
+i81342_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t size, bus_space_handle_t *nbshp)
+{
+
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+void
+i81342_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t len, int flags)
+{
+
+ /* Nothing to do. */
+}
+
+/* *** Routines for PCI IO. *** */
+
+int
+i81342_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+
+ *bshp = bpa;
+ return (0);
+}
+
+void
+i81342_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
+{
+
+ /* Nothing to do. */
+}
+
+int
+i81342_io_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
+ bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+
+ panic("i81342_io_bs_alloc(): not implemented");
+}
+
+void
+i81342_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
+{
+
+ panic("i81342_io_bs_free(): not implemented");
+}
+
+
+/* *** Routines for PCI MEM. *** */
+extern int badaddr_read(void *, int, void *);
+static vm_offset_t allocable = 0xe1000000;
+int
+i81342_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ struct i81342_pci_softc *sc = (struct i81342_pci_softc *)tag->bs_privdata;
+ struct i81342_pci_map *tmp;
+ vm_offset_t addr, endaddr;
+ vm_paddr_t paddr;
+
+ /* Lookup to see if we already have a mapping at this address. */
+ tmp = sc->sc_pci_mappings;
+ while (tmp) {
+ if (tmp->paddr <= bpa && tmp->paddr + tmp->size >
+ bpa + size) {
+ *bshp = bpa - tmp->paddr + tmp->vaddr;
+ return (0);
+ }
+ tmp = tmp->next;
+ }
+ addr = allocable;
+ endaddr = ((addr + size) &~ (0x1000000 - 1)) + 0x1000000;
+ if (endaddr >= IOP34X_VADDR)
+ panic("PCI virtual memory exhausted");
+ allocable = endaddr;
+ tmp = malloc(sizeof(*tmp), M_DEVBUF, M_WAITOK);
+ tmp->next = NULL;
+ paddr = bpa &~ (0x100000 - 1);
+ tmp->paddr = paddr;
+ tmp->vaddr = addr;
+ tmp->size = 0;
+ while (addr < endaddr) {
+ pmap_kenter_supersection(addr, paddr + (sc->sc_is_atux ?
+ IOP34X_PCIX_OMBAR : IOP34X_PCIE_OMBAR), 0);
+ addr += 0x1000000;
+ paddr += 0x1000000;
+ tmp->size += 0x1000000;
+ }
+ tmp->next = sc->sc_pci_mappings;
+ sc->sc_pci_mappings = tmp;
+ *bshp = bpa - tmp->paddr + tmp->vaddr;
+ return (0);
+}
+
+void
+i81342_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
+{
+#if 0
+ vm_offset_t va, endva;
+
+ va = trunc_page((vm_offset_t)h);
+ endva = va + round_page(size);
+
+ /* Free the kernel virtual mapping. */
+ kva_free(va, endva - va);
+#endif
+}
+
+int
+i81342_mem_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
+ bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+
+ panic("i81342_mem_bs_alloc(): not implemented");
+}
+
+void
+i81342_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
+{
+
+ panic("i81342_mem_bs_free(): not implemented");
+}
Property changes on: trunk/sys/arm/xscale/i8134x/i81342_space.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/i81342reg.h
===================================================================
--- trunk/sys/arm/xscale/i8134x/i81342reg.h (rev 0)
+++ trunk/sys/arm/xscale/i8134x/i81342reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,349 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/xscale/i8134x/i81342reg.h 261455 2014-02-04 03:36:42Z eadler $ */
+
+#ifndef I83142_REG_H_
+#define I83142_REG_H_
+/* Physical Memory Map */
+/*
+ * 0x000000000 - 0x07FFFFFFF SDRAM
+ * 0x090100000 - 0x0901FFFFF ATUe Outbound IO Window
+ * 0x0F0000000 - 0x0F1FFFFFF Flash
+ * 0x0F2000000 - 0x0F20FFFFF PCE1
+ * 0x0F3000000 - 0x0FFCFFFFF Compact Flash
+ * 0x0FFD00000 - 0x0FFDFFFFF MMR
+ * 0x0FFFB0000 - 0x0FFFBFFFF ATU-X Outbound I/O Window
+ * 0x0FFFD0000 - 0x0FFFDFFFF ATUe Outbound I/O Window
+ * 0x100000000 - 0x1FFFFFFFF ATU-X outbound Memory Translation Window
+ * 0x2FF000000 - 0x2FFFFFFFF ATUe Outbound Memory Translation Window
+ */
+
+#define IOP34X_VADDR 0xf0000000
+#define IOP34X_HWADDR 0xffd00000
+#define IOP34X_SIZE 0x100000
+
+#define IOP34X_ADMA0_OFFSET 0x00080000
+#define IOP34X_ADMA1_OFFSET 0x00080200
+#define IOP34X_ADMA2_OFFSET 0x00080400
+#define IOP34X_ADMA_SIZE 0x200
+
+
+/* ADMA Registers */
+#define IOP34X_ADMA_CCR 0x0000 /* Channel Control Register */
+#define IOP34X_ADMA_CSR 0x0004 /* Channel Status Register */
+#define IOP34X_ADMA_DAR 0x0008 /* Descriptor Address Register */
+#define IOP34X_ADMA_IPCR 0x0018 /* Internal Interface Parity Ctrl Reg */
+#define IOP34X_ADMA_NDAR 0x0024 /* Next Descriptor Register */
+#define IOP34X_ADMA_DCR 0x0028 /* Descriptor Control Register */
+
+#define IOP34X_ADMA_IE (1 << 0) /* Interrupt enable */
+#define IOP34X_ADMA_TR (1 << 1) /* Transfert Direction */
+/*
+ * Source Destination
+ * 00 Host I/O Interface Local Memory
+ * 01 Local Memory Host I/O Interface
+ * 10 Internal Bus Local Memory
+ * 11 Local Memory Internal Bus
+ */
+#define IOP34X_ADMA_SS (1 << 3) /* Source selection */
+/* 0000: Data Transfer / CRC / Memory Block Fill */
+#define IOP34X_ADMA_ZRBCE (1 << 7) /* Zero Result Buffer Check Enable */
+#define IOP34X_ADMA_MBFE (1 << 8) /* Memory Block Fill Enable */
+#define IOP34X_ADMA_CGE (1 << 9) /* CRC Generation enable */
+#define IOP34X_ADMA_CTD (1 << 10) /* CRC Transfer disable */
+#define IOP34X_ADMA_CSFD (1 << 11) /* CRC Seed fetch disable */
+#define IOP34X_ADMA_SWBE (1 << 12) /* Status write back enable */
+#define IOP34X_ADMA_ESE (1 << 13) /* Endian swap enable */
+#define IOP34X_ADMA_PQUTE (1 << 16) /* P+Q Update Transfer Enable */
+#define IOP34X_ADMA_DXE (1 << 17) /* Dual XOR Enable */
+#define IOP34X_ADMA_PQTE (1 << 18) /* P+Q Transfer Enable */
+#define IOP34X_ADMA_PTD (1 << 19) /* P Transfer Disable */
+#define IOP34X_ADMA_ROE (1 << 30) /* Relaxed Ordering Enable */
+#define IOP34X_ADMA_NSE (1U << 31) /* No Snoop Enable */
+
+#define IOP34X_PBBAR0 0x81588 /* PBI Base Address Register 0 */
+#define IOP34X_PBBAR0_ADDRMASK 0xfffff000
+#define IOP34X_PBBAR1 0x81590
+#define IOP34X_PCE1 0xF2000000
+#define IOP34X_PCE1_SIZE 0x00100000
+#define IOP34X_PCE1_VADDR 0xF1000000
+#define IOP34X_ESSTSR0 0x82188
+#define IOP34X_CONTROLLER_ONLY (1 << 14)
+#define IOP34X_INT_SEL_PCIX (1 << 15)
+#define IOP34X_PFR 0x82180 /* Processor Frequency Register */
+#define IOP34X_FREQ_MASK ((1 << 16) | (1 << 17) | (1 << 18))
+#define IOP34X_FREQ_600 (0)
+#define IOP34X_FREQ_667 (1 << 16)
+#define IOP34X_FREQ_800 (1 << 17)
+#define IOP34X_FREQ_833 ((1 << 17) | (1 << 16))
+#define IOP34X_FREQ_1000 (1 << 18)
+#define IOP34X_FREQ_1200 ((1 << 16) | (1 << 18))
+
+#define IOP34X_UART0_VADDR IOP34X_VADDR + 0x82300
+#define IOP34X_UART0_HWADDR IOP34X_HWADDR + 0x82300
+#define IOP34X_UART1_VADDR IOP34X_VADDR + 0x82340
+#define IOP34X_UART1_HWADDR IOP34X_HWADDR + 0x82340
+#define IOP34X_PBI_HWADDR 0xffd81580
+
+/* SDRAM Memory Controller */
+#define SMC_SDBR 0x8180c /* Base Register */
+#define SMC_SDBR_BASEADDR (1 << 27)
+#define SMC_SDBR_BASEADDR_MASK ((1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) \
+ | (1U << 31))
+#define SMC_SDUBR 0x81810 /* Upper Base Register */
+#define SMC_SBSR 0x81814 /* SDRAM Bank Size Register */
+#define SMC_SBSR_BANK_NB (1 << 2) /* Number of DDR Banks
+ 0 => 2 Banks
+ 1 => 1 Bank
+ */
+#define SMC_SBSR_BANK_SZ (1 << 27) /* SDRAM Bank Size :
+ 0x00000 Empty
+ 0x00001 128MB
+ 0x00010 256MB
+ 0x00100 512MB
+ 0x01000 1GB
+ */
+#define SMC_SBSR_BANK_SZ_MASK ((1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) \
+ | (1U << 31))
+
+
+/* Two possible addresses for ATUe depending on configuration. */
+#define IOP34X_ATUE_ADDR(esstrsr) ((((esstrsr) & (IOP34X_CONTROLLER_ONLY | \
+ IOP34X_INT_SEL_PCIX)) == (IOP34X_CONTROLLER_ONLY | IOP34X_INT_SEL_PCIX)) ? \
+ 0xffdc8000 : 0xffdcd000)
+
+/* Three possible addresses for ATU-X depending on configuration. */
+#define IOP34X_ATUX_ADDR(esstrsr) (!((esstrsr) & IOP34X_CONTROLLER_ONLY) ? \
+ 0xffdcc000 : !((esstrsr) & IOP34X_INT_SEL_PCIX) ? 0xffdc8000 : 0xffdcd000)
+
+#define IOP34X_OIOBAR_SIZE 0x10000
+#define IOP34X_PCIX_OIOBAR 0xfffb0000
+#define IOP34X_PCIX_OIOBAR_VADDR 0xf01b0000
+#define IOP34X_PCIX_OMBAR 0x100000000
+#define IOP34X_PCIE_OIOBAR 0xfffd0000
+#define IOP34X_PCIE_OIOBAR_VADDR 0xf01d0000
+#define IOP34X_PCIE_OMBAR 0x200000000
+
+/* ATU Registers */
+/* Common for ATU-X and ATUe */
+#define ATU_VID 0x0000 /* ATU Vendor ID */
+#define ATU_DID 0x0002 /* ATU Device ID */
+#define ATU_CMD 0x0004 /* ATU Command Register */
+#define ATU_SR 0x0006 /* ATU Status Register */
+#define ATU_RID 0x0008 /* ATU Revision ID */
+#define ATU_CCR 0x0009 /* ATU Class Code */
+#define ATU_CLSR 0x000c /* ATU Cacheline Size */
+#define ATU_LT 0x000d /* ATU Latency Timer */
+#define ATU_HTR 0x000e /* ATU Header Type */
+#define ATU_BISTR 0x000f /* ATU BIST Register */
+#define ATU_IABAR0 0x0010 /* Inbound ATU Base Address register 0 */
+#define ATU_IAUBAR0 0x0014 /* Inbound ATU Upper Base Address Register 0 */
+#define ATU_IABAR1 0x0018 /* Inbound ATU Base Address Register 1 */
+#define ATU_IAUBAR1 0x001c /* Inbound ATU Upper Base Address Register 1 */
+#define ATU_IABAR2 0x0020 /* Inbound ATU Base Address Register 2 */
+#define ATU_IAUBAR2 0x0024 /* Inbound ATU Upper Base Address Register 2 */
+#define ATU_VSIR 0x002c /* ATU Subsystem Vendor ID Register */
+#define ATU_SIR 0x002e /* ATU Subsystem ID Register */
+#define ATU_ERBAR 0x0030 /* Expansion ROM Base Address Register */
+#define ATU_CAPPTR 0x0034 /* ATU Capabilities Pointer Register */
+#define ATU_ILR 0x003c /* ATU Interrupt Line Register */
+#define ATU_IPR 0x003d /* ATU Interrupt Pin Register */
+#define ATU_MGNT 0x003e /* ATU Minimum Grand Register */
+#define ATU_MLAT 0x003f /* ATU Maximum Latency Register */
+#define ATU_IALR0 0x0040 /* Inbound ATU Limit Register 0 */
+#define ATU_IATVR0 0x0044 /* Inbound ATU Translate Value Register 0 */
+#define ATU_IAUTVR0 0x0048 /* Inbound ATU Upper Translate Value Register 0*/
+#define ATU_IALR1 0x004c /* Inbound ATU Limit Register 1 */
+#define ATU_IATVR1 0x0050 /* Inbound ATU Translate Value Register 1 */
+#define ATU_IAUTVR1 0x0054 /* Inbound ATU Upper Translate Value Register 1*/
+#define ATU_IALR2 0x0058 /* Inbound ATU Limit Register 2 */
+#define ATU_IATVR2 0x005c /* Inbound ATU Translate Value Register 2 */
+#define ATU_IAUTVR2 0x0060 /* Inbound ATU Upper Translate Value Register 2*/
+#define ATU_ERLR 0x0064 /* Expansion ROM Limit Register */
+#define ATU_ERTVR 0x0068 /* Expansion ROM Translater Value Register */
+#define ATU_ERUTVR 0x006c /* Expansion ROM Upper Translate Value Register*/
+#define ATU_CR 0x0070 /* ATU Configuration Register */
+#define ATU_CR_OUT_EN (1 << 1)
+#define ATU_PCSR 0x0074 /* PCI Configuration and Status Register */
+#define PCIE_BUSNO(x) ((x & 0xff000000) >> 24)
+#define ATUX_CORE_RST ((1 << 30) | (1U << 31)) /* Core Processor Reset */
+#define ATUX_P_RSTOUT (1 << 21) /* Central Resource PCI Bus Reset */
+#define ATUE_CORE_RST ((1 << 9) | (1 << 8)) /* Core Processor Reset */
+#define ATU_ISR 0x0078 /* ATU Interrupt Status Register */
+#define ATUX_ISR_PIE (1 << 18) /* PCI Interface error */
+#define ATUX_ISR_IBPR (1 << 16) /* Internal Bus Parity Error */
+#define ATUX_ISR_DCE (1 << 14) /* Detected Correctable error */
+#define ATUX_ISR_ISCE (1 << 13) /* Initiated Split Completion Error Msg */
+#define ATUX_ISR_RSCE (1 << 12) /* Received Split Completion Error Msg */
+#define ATUX_ISR_DPE (1 << 9) /* Detected Parity Error */
+#define ATUX_ISR_IBMA (1 << 7) /* Internal Bus Master Abort */
+#define ATUX_ISR_PMA (1 << 3) /* PCI Master Abort */
+#define ATUX_ISR_PTAM (1 << 2) /* PCI Target Abort (Master) */
+#define ATUX_ISR_PTAT (1 << 1) /* PCI Target Abort (Target) */
+#define ATUX_ISR_PMPE (1 << 0) /* PCI Master Parity Error */
+#define ATUX_ISR_ERRMSK (ATUX_ISR_PIE | ATUX_ISR_IBPR | ATUX_ISR_DCE | \
+ ATUX_ISR_ISCE | ATUX_ISR_RSCE | ATUX_ISR_DPE | ATUX_ISR_IBMA | ATUX_ISR_PMA\
+ | ATUX_ISR_PTAM | ATUX_ISR_PTAT | ATUX_ISR_PMPE)
+#define ATUE_ISR_HON (1 << 13) /* Halt on Error Interrupt */
+#define ATUE_ISR_RSE (1 << 12) /* Root System Error Message */
+#define ATUE_ISR_REM (1 << 11) /* Root Error Message */
+#define ATUE_ISR_PIE (1 << 10) /* PCI Interface error */
+#define ATUE_ISR_CEM (1 << 9) /* Correctable Error Message */
+#define ATUE_ISR_UEM (1 << 8) /* Uncorrectable error message */
+#define ATUE_ISR_CRS (1 << 7) /* Received Configuration Retry Status */
+#define ATUE_ISR_IBMA (1 << 5) /* Internal Bus Master Abort */
+#define ATUE_ISR_DPE (1 << 4) /* Detected Parity Error Interrupt */
+#define ATUE_ISR_MAI (1 << 3) /* Received Master Abort Interrupt */
+#define ATUE_ISR_STAI (1 << 2) /* Signaled Target Abort Interrupt */
+#define ATUE_ISR_TAI (1 << 1) /* Received Target Abort Interrupt */
+#define ATUE_ISR_MDPE (1 << 0) /* Master Data Parity Error Interrupt */
+#define ATUE_ISR_ERRMSK (ATUE_ISR_HON | ATUE_ISR_RSE | ATUE_ISR_REM | \
+ ATUE_ISR_PIE | ATUE_ISR_CEM | ATUE_ISR_UEM | ATUE_ISR_CRS | ATUE_ISR_IBMA |\
+ ATUE_ISR_DPE | ATUE_ISR_MAI | ATUE_ISR_STAI | ATUE_ISR_TAI | ATUE_ISR_MDPE)
+#define ATU_IMR 0x007c /* ATU Interrupt Mask Register */
+/* 0x0080 - 0x008f reserved */
+#define ATU_VPDCID 0x0090 /* VPD Capability Identifier Register */
+#define ATU_VPDNIP 0x0091 /* VPD Next Item Pointer Register */
+#define ATU_VPDAR 0x0092 /* VPD Address Register */
+#define ATU_VPDDR 0x0094 /* VPD Data Register */
+#define ATU_PMCID 0x0098 /* PM Capability Identifier Register */
+#define ATU_PMNIPR 0x0099 /* PM Next Item Pointer Register */
+#define ATU_PMCR 0x009a /* ATU Power Management Capabilities Register */
+#define ATU_PMCSR 0x009c /* ATU Power Management Control/Status Register*/
+#define ATU_MSICIR 0x00a0 /* MSI Capability Identifier Register */
+#define ATU_MSINIPR 0x00a1 /* MSI Next Item Pointer Register */
+#define ATU_MCR 0x00a2 /* Message Control Register */
+#define ATU_MAR 0x00a4 /* Message Address Register */
+#define ATU_MUAR 0x00a8 /* Message Upper Address Register */
+#define ATU_MDR 0x00ac /* Message Data Register */
+#define ATU_PCIXSR 0x00d4 /* PCI-X Status Register */
+#define PCIXSR_BUSNO(x) (((x) & 0xff00) >> 8)
+#define ATU_IABAR3 0x0200 /* Inbound ATU Base Address Register 3 */
+#define ATU_IAUBAR3 0x0204 /* Inbound ATU Upper Base Address Register 3 */
+#define ATU_IALR3 0x0208 /* Inbound ATU Limit Register 3 */
+#define ATU_ITVR3 0x020c /* Inbound ATU Upper Translate Value Reg 3 */
+#define ATU_OIOBAR 0x0300 /* Outbound I/O Base Address Register */
+#define ATU_OIOWTVR 0x0304 /* Outbound I/O Window Translate Value Reg */
+#define ATU_OUMBAR0 0x0308 /* Outbound Upper Memory Window base addr reg 0*/
+#define ATU_OUMBAR_FUNC (28)
+#define ATU_OUMBAR_EN (1U << 31)
+#define ATU_OUMWTVR0 0x030c /* Outbound Upper 32bit Memory Window Translate Value Register 0 */
+#define ATU_OUMBAR1 0x0310 /* Outbound Upper Memory Window base addr reg1*/
+#define ATU_OUMWTVR1 0x0314 /* Outbound Upper 32bit Memory Window Translate Value Register 1 */
+#define ATU_OUMBAR2 0x0318 /* Outbound Upper Memory Window base addr reg2*/
+#define ATU_OUMWTVR2 0x031c /* Outbount Upper 32bit Memory Window Translate Value Register 2 */
+#define ATU_OUMBAR3 0x0320 /* Outbound Upper Memory Window base addr reg3*/
+#define ATU_OUMWTVR3 0x0324 /* Outbound Upper 32bit Memory Window Translate Value Register 3 */
+
+/* ATU-X specific */
+#define ATUX_OCCAR 0x0330 /* Outbound Configuration Cycle Address Reg */
+#define ATUX_OCCDR 0x0334 /* Outbound Configuration Cycle Data Reg */
+#define ATUX_OCCFN 0x0338 /* Outbound Configuration Cycle Function Number*/
+/* ATUe specific */
+#define ATUE_OCCAR 0x032c /* Outbound Configuration Cycle Address Reg */
+#define ATUE_OCCDR 0x0330 /* Outbound Configuration Cycle Data Reg */
+#define ATUE_OCCFN 0x0334 /* Outbound Configuration Cycle Function Number*/
+/* Interrupts */
+
+/* IINTRSRC0 */
+#define ICU_INT_ADMA0_EOT (0) /* ADMA 0 End of transfer */
+#define ICU_INT_ADMA0_EOC (1) /* ADMA 0 End of Chain */
+#define ICU_INT_ADMA1_EOT (2) /* ADMA 1 End of transfer */
+#define ICU_INT_ADMA1_EOC (3) /* ADMA 1 End of chain */
+#define ICU_INT_ADMA2_EOT (4) /* ADMA 2 End of transfer */
+#define ICU_INT_ADMA2_EOC (5) /* ADMA 2 end of chain */
+#define ICU_INT_WDOG (6) /* Watchdog timer */
+/* 7 Reserved */
+#define ICU_INT_TIMER0 (8) /* Timer 0 */
+#define ICU_INT_TIMER1 (9) /* Timer 1 */
+#define ICU_INT_I2C0 (10) /* I2C bus interface 0 */
+#define ICU_INT_I2C1 (11) /* I2C bus interface 1 */
+#define ICU_INT_MU (12) /* Message Unit */
+#define ICU_INT_MU_IPQ (13) /* Message unit inbound post queue */
+#define ICU_INT_ATUE_IM (14) /* ATU-E inbound message */
+#define ICU_INT_ATU_BIST (15) /* ATU/Start BIST */
+#define ICU_INT_PMC (16) /* PMC */
+#define ICU_INT_PMU (17) /* PMU */
+#define ICU_INT_PC (18) /* Processor cache */
+/* 19-23 Reserved */
+#define ICU_INT_XINT0 (24)
+#define ICU_INT_XINT1 (25)
+#define ICU_INT_XINT2 (26)
+#define ICU_INT_XINT3 (27)
+#define ICU_INT_XINT4 (28)
+#define ICU_INT_XINT5 (29)
+#define ICU_INT_XINT6 (30)
+#define ICU_INT_XINT7 (31)
+/* IINTSRC1 */
+#define ICU_INT_XINT8 (32)
+#define ICU_INT_XINT9 (33)
+#define ICU_INT_XINT10 (34)
+#define ICU_INT_XINT11 (35)
+#define ICU_INT_XINT12 (36)
+#define ICU_INT_XINT13 (37)
+#define ICU_INT_XINT14 (38)
+#define ICU_INT_XINT15 (39)
+/* 40-50 reserved */
+#define ICU_INT_UART0 (51) /* UART 0 */
+#define ICU_INT_UART1 (52) /* UART 1 */
+#define ICU_INT_PBIUE (53) /* Peripheral bus interface unit error */
+#define ICU_INT_ATUCRW (54) /* ATU Configuration register write */
+#define ICU_INT_ATUE (55) /* ATU error */
+#define ICU_INT_MCUE (56) /* Memory controller unit error */
+#define ICU_INT_ADMA0E (57) /* ADMA Channel 0 error */
+#define ICU_INT_ADMA1E (58) /* ADMA Channel 1 error */
+#define ICU_INT_ADMA2E (59) /* ADMA Channel 2 error */
+/* 60-61 reserved */
+#define ICU_INT_MUE (62) /* Messaging Unit Error */
+/* 63 reserved */
+
+/* IINTSRC2 */
+#define ICU_INT_IP (64) /* Inter-processor */
+/* 65-93 reserved */
+#define ICU_INT_SIBBE (94) /* South internal bus bridge error */
+/* 95 reserved */
+
+/* IINTSRC3 */
+#define ICU_INT_I2C2 (96) /* I2C bus interface 2 */
+#define ICU_INT_ATUE_BIST (97) /* ATU-E/Start BIST */
+#define ICU_INT_ATUE_CRW (98) /* ATU-E Configuration register write */
+#define ICU_INT_ATUEE (99) /* ATU-E Error */
+#define ICU_INT_IMU (100) /* IMU */
+/* 101-106 reserved */
+#define ICU_INT_ATUE_MA (107) /* ATUE Interrupt message A */
+#define ICU_INT_ATUE_MB (108) /* ATUE Interrupt message B */
+#define ICU_INT_ATUE_MC (109) /* ATUE Interrupt message C */
+#define ICU_INT_ATUE_MD (110) /* ATUE Interrupt message D */
+#define ICU_INT_MU_MSIX_TW (111) /* MU MSI-X Table write */
+/* 112 reserved */
+#define ICU_INT_IMSI (113) /* Inbound MSI */
+/* 114-126 reserved */
+#define ICU_INT_HPI (127) /* HPI */
+
+
+#endif /* I81342_REG_H_ */
Property changes on: trunk/sys/arm/xscale/i8134x/i81342reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/i81342var.h
===================================================================
--- trunk/sys/arm/xscale/i8134x/i81342var.h (rev 0)
+++ trunk/sys/arm/xscale/i8134x/i81342var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,71 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/xscale/i8134x/i81342var.h 171626 2007-07-27 14:50:57Z cognet $ */
+#ifndef I81342VAR_H_
+#define I81342VAR_H_
+
+#include <sys/rman.h>
+
+struct i81342_softc {
+ device_t dev;
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_sh;
+ bus_space_handle_t sc_atux_sh;
+ bus_space_handle_t sc_atue_sh;
+ bus_space_tag_t sc_pciio;
+ bus_space_tag_t sc_pcimem;
+ struct rman sc_irq_rman;
+};
+
+struct i81342_pci_map {
+ vm_offset_t vaddr;
+ vm_paddr_t paddr;
+ vm_size_t size;
+ struct i81342_pci_map *next;
+};
+
+struct i81342_pci_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_atu_sh;
+ struct bus_space sc_pciio;
+ struct bus_space sc_pcimem;
+ struct rman sc_mem_rman;
+ struct rman sc_io_rman;
+ struct rman sc_irq_rman;
+ char sc_is_atux;
+ int sc_busno;
+ struct i81342_pci_map *sc_pci_mappings;
+};
+
+void i81342_bs_init(bus_space_tag_t, void *);
+void i81342_io_bs_init(bus_space_tag_t, void *);
+void i81342_mem_bs_init(bus_space_tag_t, void *);
+void i81342_sdram_bounds(bus_space_tag_t, bus_space_handle_t, vm_paddr_t *,
+ vm_size_t *);
+#endif /*I81342VAR_H_ */
Property changes on: trunk/sys/arm/xscale/i8134x/i81342var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/iq81342_7seg.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/iq81342_7seg.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/iq81342_7seg.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,392 @@
+/* $MidnightBSD$ */
+/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Support for the 7-segment display on the Intel IQ81342.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/iq81342_7seg.c 236987 2012-06-13 04:38:09Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/i8134x/i81342reg.h>
+#include <arm/xscale/i8134x/iq81342reg.h>
+#include <arm/xscale/i8134x/iq81342var.h>
+
+#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v)
+
+static int snakestate;
+
+/*
+ * The 7-segment display looks like so:
+ *
+ * A
+ * +-----+
+ * | |
+ * F | | B
+ * | G |
+ * +-----+
+ * | |
+ * E | | C
+ * | D |
+ * +-----+ o DP
+ *
+ * Setting a bit clears the corresponding segment on the
+ * display.
+ */
+#define SEG_A (1 << 1)
+#define SEG_B (1 << 2)
+#define SEG_C (1 << 3)
+#define SEG_D (1 << 4)
+#define SEG_E (1 << 5)
+#define SEG_F (1 << 6)
+#define SEG_G (1 << 7)
+#define SEG_DP (1 << 0)
+
+static const uint8_t digitmap[] = {
+/* +#####+
+ * # #
+ * # #
+ * # #
+ * +-----+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ */
+ (unsigned char)~SEG_G,
+
+/* +-----+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ */
+ SEG_B|SEG_C,
+
+/* +#####+
+ * | #
+ * | #
+ * | #
+ * +#####+
+ * # |
+ * # |
+ * # |
+ * +#####+
+ */
+ ~(SEG_C|SEG_F),
+
+/* +#####+
+ * | #
+ * | #
+ * | #
+ * +#####+
+ * | #
+ * | #
+ * | #
+ * +#####+
+ */
+ ~(SEG_E|SEG_F),
+
+/* +-----+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ */
+ ~(SEG_A|SEG_D|SEG_E),
+
+/* +#####+
+ * # |
+ * # |
+ * # |
+ * +#####+
+ * | #
+ * | #
+ * | #
+ * +#####+
+ */
+ ~(SEG_B|SEG_E),
+
+/* +#####+
+ * # |
+ * # |
+ * # |
+ * +#####+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ */
+ ~(SEG_B),
+
+/* +#####+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ */
+ ~(SEG_D|SEG_E|SEG_F),
+
+/* +#####+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ */
+ ~0,
+
+/* +#####+
+ * # #
+ * # #
+ * # #
+ * +#####+
+ * | #
+ * | #
+ * | #
+ * +-----+
+ */
+ ~(SEG_D|SEG_E),
+};
+
+static uint8_t
+iq81342_7seg_xlate(char c)
+{
+ uint8_t rv;
+
+ if (c >= '0' && c <= '9')
+ rv = digitmap[c - '0'];
+ else if (c == '.')
+ rv = (uint8_t) ~SEG_DP;
+ else
+ rv = 0xff;
+
+ return (rv);
+}
+
+void
+iq81342_7seg(char a, char b)
+{
+ uint8_t msb, lsb;
+
+ msb = iq81342_7seg_xlate(a);
+ lsb = iq81342_7seg_xlate(b);
+
+ snakestate = 0;
+
+ WRITE(IQ8134X_7SEG_MSB, msb);
+ WRITE(IQ8134X_7SEG_LSB, lsb);
+}
+
+static const uint8_t snakemap[][2] = {
+
+/* +#####+ +#####+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { SEG_A, SEG_A },
+
+/* +-----+ +-----+
+ * # | | #
+ * # | | #
+ * # | | #
+ * +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { SEG_F, SEG_B },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +#####+ +#####+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { SEG_G, SEG_G },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ * | # # |
+ * | # # |
+ * | # # |
+ * +-----+ +-----+
+ */
+ { SEG_C, SEG_E },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +#####+ +#####+
+ */
+ { SEG_D, SEG_D },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ * # | | #
+ * # | | #
+ * # | | #
+ * +-----+ +-----+
+ */
+ { SEG_E, SEG_C },
+
+/* +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +#####+ +#####+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { SEG_G, SEG_G },
+
+/* +-----+ +-----+
+ * | # # |
+ * | # # |
+ * | # # |
+ * +-----+ +-----+
+ * | | | |
+ * | | | |
+ * | | | |
+ * +-----+ +-----+
+ */
+ { SEG_B, SEG_F },
+};
+
+static SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg");
+static int freq = 20;
+SYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0,
+ "7 Seg update frequency");
+static void
+iq81342_7seg_snake(void)
+{
+ static int snakefreq;
+ int cur = snakestate;
+
+ snakefreq++;
+ if ((snakefreq % freq))
+ return;
+ WRITE(IQ8134X_7SEG_MSB, snakemap[cur][0]);
+ WRITE(IQ8134X_7SEG_LSB, snakemap[cur][1]);
+
+ snakestate = (cur + 1) & 7;
+}
+
+struct iq81342_7seg_softc {
+ device_t dev;
+};
+
+static int
+iq81342_7seg_probe(device_t dev)
+{
+
+ device_set_desc(dev, "IQ81342 7seg");
+ return (0);
+}
+
+extern void (*i80321_hardclock_hook)(void);
+static int
+iq81342_7seg_attach(device_t dev)
+{
+
+ i80321_hardclock_hook = iq81342_7seg_snake;
+ return (0);
+}
+
+static device_method_t iq81342_7seg_methods[] = {
+ DEVMETHOD(device_probe, iq81342_7seg_probe),
+ DEVMETHOD(device_attach, iq81342_7seg_attach),
+ {0, 0},
+};
+
+static driver_t iq81342_7seg_driver = {
+ "iqseg",
+ iq81342_7seg_methods,
+ sizeof(struct iq81342_7seg_softc),
+};
+static devclass_t iq81342_7seg_devclass;
+
+DRIVER_MODULE(iqseg, iq, iq81342_7seg_driver, iq81342_7seg_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i8134x/iq81342_7seg.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/iq81342reg.h
===================================================================
--- trunk/sys/arm/xscale/i8134x/iq81342reg.h (rev 0)
+++ trunk/sys/arm/xscale/i8134x/iq81342reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,34 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/xscale/i8134x/iq81342reg.h 172297 2007-09-22 16:25:43Z cognet $ */
+
+#ifndef _IQ81342REG_H_
+#define _IQ81342REG_H_
+#define IQ8134X_7SEG_MSB IOP34X_PCE1_VADDR + 0x40000
+#define IQ8134X_7SEG_LSB IOP34X_PCE1_VADDR + 0x50000
+#endif /* _IQ81342REG_H_ */
Property changes on: trunk/sys/arm/xscale/i8134x/iq81342reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/iq81342var.h
===================================================================
--- trunk/sys/arm/xscale/i8134x/iq81342var.h (rev 0)
+++ trunk/sys/arm/xscale/i8134x/iq81342var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,33 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/xscale/i8134x/iq81342var.h 172297 2007-09-22 16:25:43Z cognet $ */
+
+#ifndef _IQ81342VAR_H_
+#define _IQ81342VAR_H_
+void iq81342_7seg(char, char);
+#endif /* _I8Q1342VAR_H_ */
Property changes on: trunk/sys/arm/xscale/i8134x/iq81342var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/obio.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/obio.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/obio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,170 @@
+/* $MidnightBSD$ */
+/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * On-board device autoconfiguration support for Intel IQ80321
+ * evaluation boards.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/obio.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/i8134x/i81342reg.h>
+#include <arm/xscale/i8134x/obiovar.h>
+
+bus_space_tag_t obio_bs_tag;
+
+static int
+obio_probe(device_t dev)
+{
+ return (0);
+}
+
+static int
+obio_attach(device_t dev)
+{
+ struct obio_softc *sc = device_get_softc(dev);
+
+ obio_bs_tag = arm_base_bs_tag;
+ sc->oba_st = obio_bs_tag;
+ sc->oba_rman.rm_type = RMAN_ARRAY;
+ sc->oba_rman.rm_descr = "OBIO I/O";
+ if (rman_init(&sc->oba_rman) != 0 ||
+ rman_manage_region(&sc->oba_rman,
+ IOP34X_UART0_VADDR, IOP34X_UART1_VADDR + 0x40) != 0)
+ panic("obio_attach: failed to set up I/O rman");
+ sc->oba_irq_rman.rm_type = RMAN_ARRAY;
+ sc->oba_irq_rman.rm_descr = "OBIO IRQ";
+ if (rman_init(&sc->oba_irq_rman) != 0 ||
+ rman_manage_region(&sc->oba_irq_rman, ICU_INT_UART0, ICU_INT_UART1) != 0)
+ panic("obio_attach: failed to set up IRQ rman");
+ device_add_child(dev, "uart", 0);
+ device_add_child(dev, "uart", 1);
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+ return (0);
+}
+
+static struct resource *
+obio_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct resource *rv;
+ struct rman *rm;
+ bus_space_tag_t bt = NULL;
+ bus_space_handle_t bh = 0;
+ struct obio_softc *sc = device_get_softc(bus);
+ int unit = device_get_unit(child);
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ rm = &sc->oba_irq_rman;
+ if (unit == 0)
+ start = end = ICU_INT_UART0;
+ else
+ start = end = ICU_INT_UART1;
+ break;
+ case SYS_RES_MEMORY:
+ return (NULL);
+ case SYS_RES_IOPORT:
+ rm = &sc->oba_rman;
+ bt = sc->oba_st;
+ if (unit == 0) {
+ bh = IOP34X_UART0_VADDR;
+ start = bh;
+ end = IOP34X_UART1_VADDR;
+ } else {
+ bh = IOP34X_UART1_VADDR;
+ start = bh;
+ end = start + 0x40;
+ }
+ break;
+ default:
+ return (NULL);
+ }
+
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == NULL)
+ return (NULL);
+ if (type == SYS_RES_IRQ)
+ return (rv);
+ rman_set_rid(rv, *rid);
+ rman_set_bustag(rv, bt);
+ rman_set_bushandle(rv, bh);
+
+ return (rv);
+
+}
+
+static int
+obio_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ return (0);
+}
+static device_method_t obio_methods[] = {
+ DEVMETHOD(device_probe, obio_probe),
+ DEVMETHOD(device_attach, obio_attach),
+
+ DEVMETHOD(bus_alloc_resource, obio_alloc_resource),
+ DEVMETHOD(bus_activate_resource, obio_activate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ {0, 0},
+};
+
+static driver_t obio_driver = {
+ "obio",
+ obio_methods,
+ sizeof(struct obio_softc),
+};
+static devclass_t obio_devclass;
+
+DRIVER_MODULE(obio, iq, obio_driver, obio_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i8134x/obio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/obiovar.h
===================================================================
--- trunk/sys/arm/xscale/i8134x/obiovar.h (rev 0)
+++ trunk/sys/arm/xscale/i8134x/obiovar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,56 @@
+/* $MidnightBSD$ */
+/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/i8134x/obiovar.h 278727 2015-02-13 22:32:02Z ian $
+ *
+ */
+
+#ifndef _IQ81342_OBIOVAR_H_
+#define _IQ81342_OBIOVAR_H_
+
+#include <sys/rman.h>
+
+struct obio_softc {
+ bus_space_tag_t oba_st; /* bus space tag */
+ int oba_irq; /* XINT interrupt bit # */
+ struct rman oba_rman;
+ struct rman oba_irq_rman;
+
+};
+extern bus_space_tag_t obio_bs_tag;
+
+#endif /* _IQ80321_OBIOVAR_H_ */
Property changes on: trunk/sys/arm/xscale/i8134x/obiovar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/std.crb
===================================================================
--- trunk/sys/arm/xscale/i8134x/std.crb (rev 0)
+++ trunk/sys/arm/xscale/i8134x/std.crb 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,6 @@
+#CRB board configuration
+#$FreeBSD: stable/10/sys/arm/xscale/i8134x/std.crb 171626 2007-07-27 14:50:57Z cognet $
+include "../xscale/i8134x/std.i81342"
+files "../xscale/i8134x/files.crb"
+makeoptions KERNPHYSADDR=0x00200000
+makeoptions KERNVIRTADDR=0xc0200000
Property changes on: trunk/sys/arm/xscale/i8134x/std.crb
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/std.i81342
===================================================================
--- trunk/sys/arm/xscale/i8134x/std.i81342 (rev 0)
+++ trunk/sys/arm/xscale/i8134x/std.i81342 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+#XScale i81342 generic configuration
+#$FreeBSD: stable/10/sys/arm/xscale/i8134x/std.i81342 239362 2012-08-18 05:48:19Z andrew $
+files "../xscale/i8134x/files.i81342"
+include "../xscale/std.xscale-be"
+cpu CPU_XSCALE_81342
Property changes on: trunk/sys/arm/xscale/i8134x/std.i81342
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/uart_bus_i81342.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/uart_bus_i81342.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/uart_bus_i81342.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,93 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Olivier Houchard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/uart_bus_i81342.c 171626 2007-07-27 14:50:57Z cognet $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <dev/ic/ns16550.h>
+
+#include "uart_if.h"
+
+static int uart_i81342_probe(device_t dev);
+
+static device_method_t uart_i81342_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uart_i81342_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, uart_bus_detach),
+ { 0, 0 }
+};
+
+static driver_t uart_i81342_driver = {
+ uart_driver_name,
+ uart_i81342_methods,
+ sizeof(struct uart_softc),
+};
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+static int
+uart_i81342_probe(device_t dev)
+{
+ struct uart_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->sc_class = &uart_ns8250_class;
+ if (device_get_unit(dev) == 0) {
+ sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
+ bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
+ }
+ sc->sc_rres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_rrid,
+ 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE);
+
+ sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
+ sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
+ bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh, REG_IER << 2,
+ 0x40 | 0x10);
+ bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
+
+ err = uart_bus_probe(dev, 2, 33334000, 0, device_get_unit(dev));
+ sc->sc_rxfifosz = sc->sc_txfifosz = 1;
+ return (err);
+}
+
+
+DRIVER_MODULE(uart, obio, uart_i81342_driver, uart_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/i8134x/uart_bus_i81342.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/i8134x/uart_cpu_i81342.c
===================================================================
--- trunk/sys/arm/xscale/i8134x/uart_cpu_i81342.c (rev 0)
+++ trunk/sys/arm/xscale/i8134x/uart_cpu_i81342.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,69 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/i8134x/uart_cpu_i81342.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/xscale/i8134x/i81342reg.h>
+#include <arm/xscale/i8134x/obiovar.h>
+
+bus_space_tag_t uart_bus_space_io;
+bus_space_tag_t uart_bus_space_mem;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+ return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+
+ di->ops = uart_getops(&uart_ns8250_class);
+ di->bas.chan = 0;
+ di->bas.bst = obio_bs_tag;
+ di->bas.regshft = 2;
+ di->bas.rclk = 33334000;
+ di->baudrate = 115200;
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ uart_bus_space_io = obio_bs_tag;
+ uart_bus_space_mem = NULL;
+ di->bas.bsh = IOP34X_UART0_VADDR;
+ return (0);
+}
Property changes on: trunk/sys/arm/xscale/i8134x/uart_cpu_i81342.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/avila_ata.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/avila_ata.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/avila_ata.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,554 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/avila_ata.c 305615 2016-09-08 15:06:28Z pfg $");
+
+/*
+ * Compact Flash Support for the Avila Gateworks XScale boards.
+ * The CF slot is operated in "True IDE" mode. Registers are on
+ * the Expansion Bus connected to CS1 and CS2. Interrupts are
+ * tied to GPIO pin 12. No DMA, just PIO.
+ *
+ * The ADI Pronghorn Metro is very similar. It use CS3 and CS4 and
+ * GPIO pin 0 for interrupts.
+ *
+ * See also http://www.intel.com/design/network/applnots/302456.htm.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/endian.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#include <sys/ata.h>
+#include <sys/sema.h>
+#include <sys/taskqueue.h>
+#include <vm/uma.h>
+#include <dev/ata/ata-all.h>
+#include <ata_if.h>
+
+#define AVILA_IDE_CTRL 0x06
+
+struct ata_config {
+ const char *desc; /* description for probe */
+ uint8_t gpin; /* GPIO pin */
+ uint8_t irq; /* IRQ */
+ uint32_t base16; /* CS base addr for 16-bit */
+ uint32_t size16; /* CS size for 16-bit */
+ uint32_t off16; /* CS offset for 16-bit */
+ uint32_t basealt; /* CS base addr for alt */
+ uint32_t sizealt; /* CS size for alt */
+ uint32_t offalt; /* CS offset for alt */
+};
+
+static const struct ata_config *
+ata_getconfig(struct ixp425_softc *sa)
+{
+ static const struct ata_config configs[] = {
+ { .desc = "Gateworks Avila IDE/CF Controller",
+ .gpin = 12,
+ .irq = IXP425_INT_GPIO_12,
+ .base16 = IXP425_EXP_BUS_CS1_HWBASE,
+ .size16 = IXP425_EXP_BUS_CS1_SIZE,
+ .off16 = EXP_TIMING_CS1_OFFSET,
+ .basealt = IXP425_EXP_BUS_CS2_HWBASE,
+ .sizealt = IXP425_EXP_BUS_CS2_SIZE,
+ .offalt = EXP_TIMING_CS2_OFFSET,
+ },
+ { .desc = "Gateworks Cambria IDE/CF Controller",
+ .gpin = 12,
+ .irq = IXP425_INT_GPIO_12,
+ .base16 = CAMBRIA_CFSEL0_HWBASE,
+ .size16 = CAMBRIA_CFSEL0_SIZE,
+ .off16 = EXP_TIMING_CS3_OFFSET,
+ .basealt = CAMBRIA_CFSEL1_HWBASE,
+ .sizealt = CAMBRIA_CFSEL1_SIZE,
+ .offalt = EXP_TIMING_CS4_OFFSET,
+ },
+ { .desc = "ADI Pronghorn Metro IDE/CF Controller",
+ .gpin = 0,
+ .irq = IXP425_INT_GPIO_0,
+ .base16 = IXP425_EXP_BUS_CS3_HWBASE,
+ .size16 = IXP425_EXP_BUS_CS3_SIZE,
+ .off16 = EXP_TIMING_CS3_OFFSET,
+ .basealt = IXP425_EXP_BUS_CS4_HWBASE,
+ .sizealt = IXP425_EXP_BUS_CS4_SIZE,
+ .offalt = EXP_TIMING_CS4_OFFSET,
+ },
+ };
+
+ /* XXX honor hint? (but then no multi-board support) */
+ /* XXX total hack */
+ if (cpu_is_ixp43x())
+ return &configs[1]; /* Cambria */
+ if (EXP_BUS_READ_4(sa, EXP_TIMING_CS2_OFFSET) != 0)
+ return &configs[0]; /* Avila */
+ return &configs[2]; /* Pronghorn */
+}
+
+struct ata_avila_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_exp_ioh; /* Exp Bus config registers */
+ bus_space_handle_t sc_ioh; /* CS1/3 data registers */
+ bus_space_handle_t sc_alt_ioh; /* CS2/4 data registers */
+ struct bus_space sc_expbus_tag;
+ struct resource sc_ata; /* hand-crafted for ATA */
+ struct resource sc_alt_ata; /* hand-crafted for ATA */
+ u_int32_t sc_16bit_off; /* EXP_TIMING_CSx_OFFSET */
+ int sc_rid; /* rid for IRQ */
+ struct resource *sc_irq; /* IRQ resource */
+ void *sc_ih; /* interrupt handler */
+ struct {
+ void (*cb)(void *);
+ void *arg;
+ } sc_intr[1]; /* NB: 1/channel */
+};
+
+static void ata_avila_intr(void *);
+bs_protos(ata);
+static void ata_bs_rm_2_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t,
+ u_int16_t *, bus_size_t);
+static void ata_bs_wm_2_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t,
+ const u_int16_t *, bus_size_t);
+
+static int
+ata_avila_probe(device_t dev)
+{
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+ const struct ata_config *config;
+
+ config = ata_getconfig(sa);
+ if (config != NULL) {
+ device_set_desc_copy(dev, config->desc);
+ return 0;
+ }
+ return ENXIO;
+}
+
+static int
+ata_avila_attach(device_t dev)
+{
+ struct ata_avila_softc *sc = device_get_softc(dev);
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+ const struct ata_config *config;
+
+ config = ata_getconfig(sa);
+ KASSERT(config != NULL, ("no board config"));
+
+ sc->sc_dev = dev;
+ /* NB: borrow from parent */
+ sc->sc_iot = sa->sc_iot;
+ sc->sc_exp_ioh = sa->sc_exp_ioh;
+
+ if (bus_space_map(sc->sc_iot, config->base16, config->size16,
+ 0, &sc->sc_ioh))
+ panic("%s: cannot map 16-bit window (0x%x/0x%x)",
+ __func__, config->base16, config->size16);
+ if (bus_space_map(sc->sc_iot, config->basealt, config->sizealt,
+ 0, &sc->sc_alt_ioh))
+ panic("%s: cannot map alt window (0x%x/0x%x)",
+ __func__, config->basealt, config->sizealt);
+ sc->sc_16bit_off = config->off16;
+
+ if (config->base16 != CAMBRIA_CFSEL0_HWBASE) {
+ /*
+ * Craft special resource for ATA bus space ops
+ * that go through the expansion bus and require
+ * special hackery to ena/dis 16-bit operations.
+ *
+ * XXX probably should just make this generic for
+ * accessing the expansion bus.
+ */
+ sc->sc_expbus_tag.bs_privdata = sc; /* NB: backpointer */
+ /* read single */
+ sc->sc_expbus_tag.bs_r_1 = ata_bs_r_1;
+ sc->sc_expbus_tag.bs_r_2 = ata_bs_r_2;
+ /* read multiple */
+ sc->sc_expbus_tag.bs_rm_2 = ata_bs_rm_2;
+ sc->sc_expbus_tag.bs_rm_2_s = ata_bs_rm_2_s;
+ /* write (single) */
+ sc->sc_expbus_tag.bs_w_1 = ata_bs_w_1;
+ sc->sc_expbus_tag.bs_w_2 = ata_bs_w_2;
+ /* write multiple */
+ sc->sc_expbus_tag.bs_wm_2 = ata_bs_wm_2;
+ sc->sc_expbus_tag.bs_wm_2_s = ata_bs_wm_2_s;
+
+ rman_set_bustag(&sc->sc_ata, &sc->sc_expbus_tag);
+ rman_set_bustag(&sc->sc_alt_ata, &sc->sc_expbus_tag);
+ } else {
+ /*
+ * On Cambria use the shared CS3 expansion bus tag
+ * that handles interlock for sharing access with the
+ * optional UART's.
+ */
+ rman_set_bustag(&sc->sc_ata, &cambria_exp_bs_tag);
+ rman_set_bustag(&sc->sc_alt_ata, &cambria_exp_bs_tag);
+ }
+ rman_set_bushandle(&sc->sc_ata, sc->sc_ioh);
+ rman_set_bushandle(&sc->sc_alt_ata, sc->sc_alt_ioh);
+
+ ixp425_set_gpio(sa, config->gpin, GPIO_TYPE_EDG_RISING);
+
+ /* configure CS1/3 window, leaving timing unchanged */
+ EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
+ EXP_BUS_READ_4(sc, sc->sc_16bit_off) |
+ EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
+ /* configure CS2/4 window, leaving timing unchanged */
+ EXP_BUS_WRITE_4(sc, config->offalt,
+ EXP_BUS_READ_4(sc, config->offalt) |
+ EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
+
+ /* setup interrupt */
+ sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid,
+ config->irq, config->irq, 1, RF_ACTIVE);
+ if (!sc->sc_irq)
+ panic("Unable to allocate irq %u.\n", config->irq);
+ bus_setup_intr(dev, sc->sc_irq,
+ INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
+ NULL, ata_avila_intr, sc, &sc->sc_ih);
+
+ /* attach channel on this controller */
+ device_add_child(dev, "ata", -1);
+ bus_generic_attach(dev);
+
+ return 0;
+}
+
+static int
+ata_avila_detach(device_t dev)
+{
+ struct ata_avila_softc *sc = device_get_softc(dev);
+
+ /* XXX quiesce gpio? */
+
+ /* detach & delete all children */
+ device_delete_children(dev);
+
+ bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_irq);
+
+ return 0;
+}
+
+static void
+ata_avila_intr(void *xsc)
+{
+ struct ata_avila_softc *sc = xsc;
+
+ if (sc->sc_intr[0].cb != NULL)
+ sc->sc_intr[0].cb(sc->sc_intr[0].arg);
+}
+
+static struct resource *
+ata_avila_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct ata_avila_softc *sc = device_get_softc(dev);
+
+ KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID,
+ ("type %u rid %u start %lu end %lu count %lu flags %u",
+ type, *rid, start, end, count, flags));
+
+ /* doesn't matter what we return so reuse the real thing */
+ return sc->sc_irq;
+}
+
+static int
+ata_avila_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID,
+ ("type %u rid %u", type, rid));
+ return 0;
+}
+
+static int
+ata_avila_setup_intr(device_t dev, device_t child, struct resource *irq,
+ int flags, driver_filter_t *filt,
+ driver_intr_t *function, void *argument, void **cookiep)
+{
+ struct ata_avila_softc *sc = device_get_softc(dev);
+ int unit = ((struct ata_channel *)device_get_softc(child))->unit;
+
+ KASSERT(unit == 0, ("unit %d", unit));
+ sc->sc_intr[unit].cb = function;
+ sc->sc_intr[unit].arg = argument;
+ *cookiep = sc;
+ return 0;
+}
+
+static int
+ata_avila_teardown_intr(device_t dev, device_t child, struct resource *irq,
+ void *cookie)
+{
+ struct ata_avila_softc *sc = device_get_softc(dev);
+ int unit = ((struct ata_channel *)device_get_softc(child))->unit;
+
+ KASSERT(unit == 0, ("unit %d", unit));
+ sc->sc_intr[unit].cb = NULL;
+ sc->sc_intr[unit].arg = NULL;
+ return 0;
+}
+
+/*
+ * Bus space accessors for CF-IDE PIO operations.
+ */
+
+/*
+ * Enable/disable 16-bit ops on the expansion bus.
+ */
+static __inline void
+enable_16(struct ata_avila_softc *sc)
+{
+ EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
+ EXP_BUS_READ_4(sc, sc->sc_16bit_off) &~ EXP_BYTE_EN);
+ DELAY(100); /* XXX? */
+}
+
+static __inline void
+disable_16(struct ata_avila_softc *sc)
+{
+ DELAY(100); /* XXX? */
+ EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
+ EXP_BUS_READ_4(sc, sc->sc_16bit_off) | EXP_BYTE_EN);
+}
+
+uint8_t
+ata_bs_r_1(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o)
+{
+ struct ata_avila_softc *sc = tag->bs_privdata;
+
+ return bus_space_read_1(sc->sc_iot, h, o);
+}
+
+void
+ata_bs_w_1(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o, u_int8_t v)
+{
+ struct ata_avila_softc *sc = tag->bs_privdata;
+
+ bus_space_write_1(sc->sc_iot, h, o, v);
+}
+
+uint16_t
+ata_bs_r_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o)
+{
+ struct ata_avila_softc *sc = tag->bs_privdata;
+ uint16_t v;
+
+ enable_16(sc);
+ v = bus_space_read_2(sc->sc_iot, h, o);
+ disable_16(sc);
+ return v;
+}
+
+void
+ata_bs_w_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o, uint16_t v)
+{
+ struct ata_avila_softc *sc = tag->bs_privdata;
+
+ enable_16(sc);
+ bus_space_write_2(sc->sc_iot, h, o, v);
+ disable_16(sc);
+}
+
+void
+ata_bs_rm_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
+ u_int16_t *d, bus_size_t c)
+{
+ struct ata_avila_softc *sc = tag->bs_privdata;
+
+ enable_16(sc);
+ bus_space_read_multi_2(sc->sc_iot, h, o, d, c);
+ disable_16(sc);
+}
+
+void
+ata_bs_wm_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
+ const u_int16_t *d, bus_size_t c)
+{
+ struct ata_avila_softc *sc = tag->bs_privdata;
+
+ enable_16(sc);
+ bus_space_write_multi_2(sc->sc_iot, h, o, d, c);
+ disable_16(sc);
+}
+
+/* XXX workaround ata driver by (incorrectly) byte swapping stream cases */
+
+void
+ata_bs_rm_2_s(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
+ u_int16_t *d, bus_size_t c)
+{
+ struct ata_avila_softc *sc = tag->bs_privdata;
+ uint16_t v;
+ bus_size_t i;
+
+ enable_16(sc);
+#if 1
+ for (i = 0; i < c; i++) {
+ v = bus_space_read_2(sc->sc_iot, h, o);
+ d[i] = bswap16(v);
+ }
+#else
+ bus_space_read_multi_stream_2(sc->sc_iot, h, o, d, c);
+#endif
+ disable_16(sc);
+}
+
+void
+ata_bs_wm_2_s(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
+ const u_int16_t *d, bus_size_t c)
+{
+ struct ata_avila_softc *sc = tag->bs_privdata;
+ bus_size_t i;
+
+ enable_16(sc);
+#if 1
+ for (i = 0; i < c; i++)
+ bus_space_write_2(sc->sc_iot, h, o, bswap16(d[i]));
+#else
+ bus_space_write_multi_stream_2(sc->sc_iot, h, o, d, c);
+#endif
+ disable_16(sc);
+}
+
+static device_method_t ata_avila_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ata_avila_probe),
+ DEVMETHOD(device_attach, ata_avila_attach),
+ DEVMETHOD(device_detach, ata_avila_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* bus methods */
+ DEVMETHOD(bus_alloc_resource, ata_avila_alloc_resource),
+ DEVMETHOD(bus_release_resource, ata_avila_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, ata_avila_setup_intr),
+ DEVMETHOD(bus_teardown_intr, ata_avila_teardown_intr),
+
+ { 0, 0 }
+};
+
+devclass_t ata_avila_devclass;
+
+static driver_t ata_avila_driver = {
+ "ata_avila",
+ ata_avila_methods,
+ sizeof(struct ata_avila_softc),
+};
+
+DRIVER_MODULE(ata_avila, ixp, ata_avila_driver, ata_avila_devclass, 0, 0);
+MODULE_VERSION(ata_avila, 1);
+MODULE_DEPEND(ata_avila, ata, 1, 1, 1);
+
+static int
+avila_channel_probe(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ ch->unit = 0;
+ ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE;
+ device_set_desc_copy(dev, "ATA channel 0");
+
+ return ata_probe(dev);
+}
+
+static int
+avila_channel_attach(device_t dev)
+{
+ struct ata_avila_softc *sc = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < ATA_MAX_RES; i++)
+ ch->r_io[i].res = &sc->sc_ata;
+
+ ch->r_io[ATA_DATA].offset = ATA_DATA;
+ ch->r_io[ATA_FEATURE].offset = ATA_FEATURE;
+ ch->r_io[ATA_COUNT].offset = ATA_COUNT;
+ ch->r_io[ATA_SECTOR].offset = ATA_SECTOR;
+ ch->r_io[ATA_CYL_LSB].offset = ATA_CYL_LSB;
+ ch->r_io[ATA_CYL_MSB].offset = ATA_CYL_MSB;
+ ch->r_io[ATA_DRIVE].offset = ATA_DRIVE;
+ ch->r_io[ATA_COMMAND].offset = ATA_COMMAND;
+ ch->r_io[ATA_ERROR].offset = ATA_FEATURE;
+ /* NB: should be used only for ATAPI devices */
+ ch->r_io[ATA_IREASON].offset = ATA_COUNT;
+ ch->r_io[ATA_STATUS].offset = ATA_COMMAND;
+
+ /* NB: the control and alt status registers are special */
+ ch->r_io[ATA_ALTSTAT].res = &sc->sc_alt_ata;
+ ch->r_io[ATA_ALTSTAT].offset = AVILA_IDE_CTRL;
+ ch->r_io[ATA_CONTROL].res = &sc->sc_alt_ata;
+ ch->r_io[ATA_CONTROL].offset = AVILA_IDE_CTRL;
+
+ /* NB: by convention this points at the base of registers */
+ ch->r_io[ATA_IDX_ADDR].offset = 0;
+
+ ata_generic_hw(dev);
+ return ata_attach(dev);
+}
+
+static device_method_t avila_channel_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, avila_channel_probe),
+ DEVMETHOD(device_attach, avila_channel_attach),
+ DEVMETHOD(device_detach, ata_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, ata_suspend),
+ DEVMETHOD(device_resume, ata_resume),
+
+ { 0, 0 }
+};
+
+driver_t avila_channel_driver = {
+ "ata",
+ avila_channel_methods,
+ sizeof(struct ata_channel),
+};
+DRIVER_MODULE(ata, ata_avila, avila_channel_driver, ata_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/ixp425/avila_ata.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/avila_gpio.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/avila_gpio.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/avila_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,359 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo at FreeBSD.org>
+ * Copyright (c) 2009, Luiz Otavio O Souza.
+ * Copyright (c) 2010, Andrew Thompson <thompsa at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * GPIO driver for Gateworks Avilia
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/avila_gpio.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#include "gpio_if.h"
+
+#define GPIO_SET_BITS(sc, reg, bits) \
+ GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, (reg)) | (bits))
+
+#define GPIO_CLEAR_BITS(sc, reg, bits) \
+ GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, (reg)) & ~(bits))
+
+struct avila_gpio_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_gpio_ioh;
+ uint32_t sc_valid;
+ struct gpio_pin sc_pins[IXP4XX_GPIO_PINS];
+};
+
+struct avila_gpio_pin {
+ const char *name;
+ int pin;
+ int caps;
+};
+
+#define GPIO_PIN_IO (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)
+static struct avila_gpio_pin avila_gpio_pins[] = {
+ { "GPIO0", 0, GPIO_PIN_IO },
+ { "GPIO1", 1, GPIO_PIN_IO },
+ { "GPIO2", 2, GPIO_PIN_IO },
+ { "GPIO3", 3, GPIO_PIN_IO },
+ { "GPIO4", 4, GPIO_PIN_IO },
+ /*
+ * The following pins are connected to system devices and should not
+ * really be frobbed.
+ */
+#if 0
+ { "SER_ENA", 5, GPIO_PIN_IO },
+ { "I2C_SCL", 6, GPIO_PIN_IO },
+ { "I2C_SDA", 7, GPIO_PIN_IO },
+ { "PCI_INTD", 8, GPIO_PIN_IO },
+ { "PCI_INTC", 9, GPIO_PIN_IO },
+ { "PCI_INTB", 10, GPIO_PIN_IO },
+ { "PCI_INTA", 11, GPIO_PIN_IO },
+ { "ATA_INT", 12, GPIO_PIN_IO },
+ { "PCI_RST", 13, GPIO_PIN_IO },
+ { "PCI_CLK", 14, GPIO_PIN_OUTPUT },
+ { "EX_CLK", 15, GPIO_PIN_OUTPUT },
+#endif
+};
+#undef GPIO_PIN_IO
+
+/*
+ * Helpers
+ */
+static void avila_gpio_pin_configure(struct avila_gpio_softc *sc,
+ struct gpio_pin *pin, uint32_t flags);
+static int avila_gpio_pin_flags(struct avila_gpio_softc *sc, uint32_t pin);
+
+/*
+ * Driver stuff
+ */
+static int avila_gpio_probe(device_t dev);
+static int avila_gpio_attach(device_t dev);
+static int avila_gpio_detach(device_t dev);
+
+/*
+ * GPIO interface
+ */
+static int avila_gpio_pin_max(device_t dev, int *maxpin);
+static int avila_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
+static int avila_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
+ *flags);
+static int avila_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
+static int avila_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
+static int avila_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
+static int avila_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
+static int avila_gpio_pin_toggle(device_t dev, uint32_t pin);
+
+static int
+avila_gpio_pin_flags(struct avila_gpio_softc *sc, uint32_t pin)
+{
+ uint32_t v;
+
+ v = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR) & (1 << pin);
+
+ return (v ? GPIO_PIN_INPUT : GPIO_PIN_OUTPUT);
+}
+
+static void
+avila_gpio_pin_configure(struct avila_gpio_softc *sc, struct gpio_pin *pin,
+ unsigned int flags)
+{
+ uint32_t mask;
+
+ mask = 1 << pin->gp_pin;
+
+ /*
+ * Manage input/output
+ */
+ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
+ IXP4XX_GPIO_LOCK();
+ pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
+ if (flags & GPIO_PIN_OUTPUT) {
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+ GPIO_CLEAR_BITS(sc, IXP425_GPIO_GPOER, mask);
+ }
+ else {
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ GPIO_SET_BITS(sc, IXP425_GPIO_GPOER, mask);
+ }
+ IXP4XX_GPIO_UNLOCK();
+ }
+}
+
+static int
+avila_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = IXP4XX_GPIO_PINS - 1;
+ return (0);
+}
+
+static int
+avila_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct avila_gpio_softc *sc = device_get_softc(dev);
+
+ if (pin >= IXP4XX_GPIO_PINS || !(sc->sc_valid & (1 << pin)))
+ return (EINVAL);
+
+ *caps = sc->sc_pins[pin].gp_caps;
+ return (0);
+}
+
+static int
+avila_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct avila_gpio_softc *sc = device_get_softc(dev);
+
+ if (pin >= IXP4XX_GPIO_PINS || !(sc->sc_valid & (1 << pin)))
+ return (EINVAL);
+
+ IXP4XX_GPIO_LOCK();
+ /* refresh since we do not own all the pins */
+ sc->sc_pins[pin].gp_flags = avila_gpio_pin_flags(sc, pin);
+ *flags = sc->sc_pins[pin].gp_flags;
+ IXP4XX_GPIO_UNLOCK();
+
+ return (0);
+}
+
+static int
+avila_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct avila_gpio_softc *sc = device_get_softc(dev);
+
+ if (pin >= IXP4XX_GPIO_PINS || !(sc->sc_valid & (1 << pin)))
+ return (EINVAL);
+
+ memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
+ return (0);
+}
+
+static int
+avila_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct avila_gpio_softc *sc = device_get_softc(dev);
+ uint32_t mask = 1 << pin;
+
+ if (pin >= IXP4XX_GPIO_PINS || !(sc->sc_valid & mask))
+ return (EINVAL);
+
+ avila_gpio_pin_configure(sc, &sc->sc_pins[pin], flags);
+
+ return (0);
+}
+
+static int
+avila_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct avila_gpio_softc *sc = device_get_softc(dev);
+ uint32_t mask = 1 << pin;
+
+ if (pin >= IXP4XX_GPIO_PINS || !(sc->sc_valid & mask))
+ return (EINVAL);
+
+ IXP4XX_GPIO_LOCK();
+ if (value)
+ GPIO_SET_BITS(sc, IXP425_GPIO_GPOUTR, mask);
+ else
+ GPIO_CLEAR_BITS(sc, IXP425_GPIO_GPOUTR, mask);
+ IXP4XX_GPIO_UNLOCK();
+
+ return (0);
+}
+
+static int
+avila_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct avila_gpio_softc *sc = device_get_softc(dev);
+
+ if (pin >= IXP4XX_GPIO_PINS || !(sc->sc_valid & (1 << pin)))
+ return (EINVAL);
+
+ IXP4XX_GPIO_LOCK();
+ *val = (GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR) & (1 << pin)) ? 1 : 0;
+ IXP4XX_GPIO_UNLOCK();
+
+ return (0);
+}
+
+static int
+avila_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct avila_gpio_softc *sc = device_get_softc(dev);
+ uint32_t mask = 1 << pin;
+ int res;
+
+ if (pin >= IXP4XX_GPIO_PINS || !(sc->sc_valid & mask))
+ return (EINVAL);
+
+ IXP4XX_GPIO_LOCK();
+ res = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR) & mask;
+ if (res)
+ GPIO_CLEAR_BITS(sc, IXP425_GPIO_GPOUTR, mask);
+ else
+ GPIO_SET_BITS(sc, IXP425_GPIO_GPOUTR, mask);
+ IXP4XX_GPIO_UNLOCK();
+
+ return (0);
+}
+
+static int
+avila_gpio_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Gateworks Avila GPIO driver");
+ return (0);
+}
+
+static int
+avila_gpio_attach(device_t dev)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ struct avila_gpio_softc *sc = device_get_softc(dev);
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+ int i;
+
+ sc->sc_dev = dev;
+ sc->sc_iot = sa->sc_iot;
+ sc->sc_gpio_ioh = sa->sc_gpio_ioh;
+
+ for (i = 0; i < N(avila_gpio_pins); i++) {
+ struct avila_gpio_pin *p = &avila_gpio_pins[i];
+
+ strncpy(sc->sc_pins[p->pin].gp_name, p->name, GPIOMAXNAME);
+ sc->sc_pins[p->pin].gp_pin = p->pin;
+ sc->sc_pins[p->pin].gp_caps = p->caps;
+ sc->sc_pins[p->pin].gp_flags = avila_gpio_pin_flags(sc, p->pin);
+ sc->sc_valid |= 1 << p->pin;
+ }
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+#undef N
+}
+
+static int
+avila_gpio_detach(device_t dev)
+{
+
+ bus_generic_detach(dev);
+
+ return(0);
+}
+
+static device_method_t gpio_avila_methods[] = {
+ DEVMETHOD(device_probe, avila_gpio_probe),
+ DEVMETHOD(device_attach, avila_gpio_attach),
+ DEVMETHOD(device_detach, avila_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, avila_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, avila_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, avila_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, avila_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, avila_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, avila_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, avila_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, avila_gpio_pin_toggle),
+ {0, 0},
+};
+
+static driver_t gpio_avila_driver = {
+ "gpio_avila",
+ gpio_avila_methods,
+ sizeof(struct avila_gpio_softc),
+};
+static devclass_t gpio_avila_devclass;
+extern devclass_t gpiobus_devclass, gpioc_devclass;
+extern driver_t gpiobus_driver, gpioc_driver;
+
+DRIVER_MODULE(gpio_avila, ixp, gpio_avila_driver, gpio_avila_devclass, 0, 0);
+DRIVER_MODULE(gpiobus, gpio_avila, gpiobus_driver, gpiobus_devclass, 0, 0);
+DRIVER_MODULE(gpioc, gpio_avila, gpioc_driver, gpioc_devclass, 0, 0);
+MODULE_VERSION(gpio_avila, 1);
Property changes on: trunk/sys/arm/xscale/ixp425/avila_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/avila_led.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/avila_led.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/avila_led.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,119 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Kevin Lo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/avila_led.c 215319 2010-11-14 20:41:22Z thompsa $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#include <dev/led/led.h>
+
+#define GPIO_LED_STATUS 3
+#define GPIO_LED_STATUS_BIT (1U << GPIO_LED_STATUS)
+
+struct led_avila_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_gpio_ioh;
+ struct cdev *sc_led;
+};
+
+static void
+led_func(void *arg, int onoff)
+{
+ struct led_avila_softc *sc = arg;
+ uint32_t reg;
+
+ IXP4XX_GPIO_LOCK();
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
+ if (onoff)
+ reg &= ~GPIO_LED_STATUS_BIT;
+ else
+ reg |= GPIO_LED_STATUS_BIT;
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
+ IXP4XX_GPIO_UNLOCK();
+}
+
+static int
+led_avila_probe(device_t dev)
+{
+ device_set_desc(dev, "Gateworks Avila Front Panel LED");
+ return (0);
+}
+
+static int
+led_avila_attach(device_t dev)
+{
+ struct led_avila_softc *sc = device_get_softc(dev);
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+
+ sc->sc_dev = dev;
+ sc->sc_iot = sa->sc_iot;
+ sc->sc_gpio_ioh = sa->sc_gpio_ioh;
+
+ /* Configure LED GPIO pin as output */
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER,
+ GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER) &~ GPIO_LED_STATUS_BIT);
+
+ sc->sc_led = led_create(led_func, sc, "gpioled");
+
+ led_func(sc, 1); /* Turn on LED */
+
+ return (0);
+}
+
+static int
+led_avila_detach(device_t dev)
+{
+ struct led_avila_softc *sc = device_get_softc(dev);
+
+ if (sc->sc_led != NULL)
+ led_destroy(sc->sc_led);
+ return (0);
+}
+
+static device_method_t led_avila_methods[] = {
+ DEVMETHOD(device_probe, led_avila_probe),
+ DEVMETHOD(device_attach, led_avila_attach),
+ DEVMETHOD(device_detach, led_avila_detach),
+
+ {0, 0},
+};
+
+static driver_t led_avila_driver = {
+ "led_avila",
+ led_avila_methods,
+ sizeof(struct led_avila_softc),
+};
+static devclass_t led_avila_devclass;
+
+DRIVER_MODULE(led_avila, ixp, led_avila_driver, led_avila_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/ixp425/avila_led.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/avila_machdep.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/avila_machdep.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/avila_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,428 @@
+/* $MidnightBSD$ */
+/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
+
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work.
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/avila_machdep.c 294683 2016-01-24 21:04:06Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/cons.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/kdb.h>
+#include <sys/msgbuf.h>
+#include <machine/physmem.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <machine/devmap.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <sys/reboot.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
+#define KERNEL_PT_IO 1
+#define KERNEL_PT_IO_NUM 3
+#define KERNEL_PT_BEFOREKERN KERNEL_PT_IO + KERNEL_PT_IO_NUM
+#define KERNEL_PT_AFKERNEL KERNEL_PT_BEFOREKERN + 1 /* L2 table for mapping after kernel */
+#define KERNEL_PT_AFKERNEL_NUM 9
+
+/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
+#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
+
+struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
+
+/* Physical and virtual addresses for some global pages */
+
+struct pv_addr systempage;
+struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+struct pv_addr kernelstack;
+struct pv_addr minidataclean;
+
+/* Static device mappings. */
+static const struct arm_devmap_entry ixp425_devmap[] = {
+ /* Physical/Virtual address for I/O space */
+ { IXP425_IO_VBASE, IXP425_IO_HWBASE, IXP425_IO_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* Expansion Bus */
+ { IXP425_EXP_VBASE, IXP425_EXP_HWBASE, IXP425_EXP_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* CFI Flash on the Expansion Bus */
+ { IXP425_EXP_BUS_CS0_VBASE, IXP425_EXP_BUS_CS0_HWBASE,
+ IXP425_EXP_BUS_CS0_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* IXP425 PCI Configuration */
+ { IXP425_PCI_VBASE, IXP425_PCI_HWBASE, IXP425_PCI_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* SDRAM Controller */
+ { IXP425_MCU_VBASE, IXP425_MCU_HWBASE, IXP425_MCU_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* PCI Memory Space */
+ { IXP425_PCI_MEM_VBASE, IXP425_PCI_MEM_HWBASE, IXP425_PCI_MEM_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* Q-Mgr Memory Space */
+ { IXP425_QMGR_VBASE, IXP425_QMGR_HWBASE, IXP425_QMGR_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ { 0 },
+};
+
+/* Static device mappings. */
+static const struct arm_devmap_entry ixp435_devmap[] = {
+ /* Physical/Virtual address for I/O space */
+ { IXP425_IO_VBASE, IXP425_IO_HWBASE, IXP425_IO_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ { IXP425_EXP_VBASE, IXP425_EXP_HWBASE, IXP425_EXP_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* IXP425 PCI Configuration */
+ { IXP425_PCI_VBASE, IXP425_PCI_HWBASE, IXP425_PCI_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* DDRII Controller NB: mapped same place as IXP425 */
+ { IXP425_MCU_VBASE, IXP435_MCU_HWBASE, IXP425_MCU_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* PCI Memory Space */
+ { IXP425_PCI_MEM_VBASE, IXP425_PCI_MEM_HWBASE, IXP425_PCI_MEM_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* Q-Mgr Memory Space */
+ { IXP425_QMGR_VBASE, IXP425_QMGR_HWBASE, IXP425_QMGR_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* CFI Flash on the Expansion Bus */
+ { IXP425_EXP_BUS_CS0_VBASE, IXP425_EXP_BUS_CS0_HWBASE,
+ IXP425_EXP_BUS_CS0_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* USB1 Memory Space */
+ { IXP435_USB1_VBASE, IXP435_USB1_HWBASE, IXP435_USB1_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+ /* USB2 Memory Space */
+ { IXP435_USB2_VBASE, IXP435_USB2_HWBASE, IXP435_USB2_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* GPS Memory Space */
+ { CAMBRIA_GPS_VBASE, CAMBRIA_GPS_HWBASE, CAMBRIA_GPS_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ /* RS485 Memory Space */
+ { CAMBRIA_RS485_VBASE, CAMBRIA_RS485_HWBASE, CAMBRIA_RS485_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, },
+
+ { 0 }
+};
+
+extern vm_offset_t xscale_cache_clean_addr;
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+#define next_chunk2(a,b) (((a) + (b)) &~ ((b)-1))
+#define next_page(a) next_chunk2(a,PAGE_SIZE)
+ struct pv_addr kernel_l1pt;
+ struct pv_addr dpcpu;
+ int loop, i;
+ u_int l1pagetable;
+ vm_offset_t freemempos;
+ vm_offset_t freemem_pt;
+ vm_offset_t afterkern;
+ vm_offset_t freemem_after;
+ vm_offset_t lastaddr;
+ uint32_t memsize;
+
+ /* kernel text starts where we were loaded at boot */
+#define KERNEL_TEXT_OFF (abp->abp_physaddr - PHYSADDR)
+#define KERNEL_TEXT_BASE (KERNBASE + KERNEL_TEXT_OFF)
+#define KERNEL_TEXT_PHYS (PHYSADDR + KERNEL_TEXT_OFF)
+
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+ set_cpufuncs(); /* NB: sets cputype */
+ pcpu_init(pcpup, 0, sizeof(struct pcpu));
+ PCPU_SET(curthread, &thread0);
+
+ init_static_kenv(NULL, 0);
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+ /*
+ * We allocate memory downwards from where we were loaded
+ * by RedBoot; first the L1 page table, then NUM_KERNEL_PTS
+ * entries in the L2 page table. Past that we re-align the
+ * allocation boundary so later data structures (stacks, etc)
+ * can be mapped with different attributes (write-back vs
+ * write-through). Note this leaves a gap for expansion
+ * (or might be repurposed).
+ */
+ freemempos = abp->abp_physaddr;
+
+ /* macros to simplify initial memory allocation */
+#define alloc_pages(var, np) do { \
+ freemempos -= (np * PAGE_SIZE); \
+ (var) = freemempos; \
+ /* NB: this works because locore maps PA=VA */ \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE)); \
+} while (0)
+#define valloc_pages(var, np) do { \
+ alloc_pages((var).pv_pa, (np)); \
+ (var).pv_va = (var).pv_pa + (KERNVIRTADDR - abp->abp_physaddr); \
+} while (0)
+
+ /* force L1 page table alignment */
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos -= PAGE_SIZE;
+ /* allocate contiguous L1 page table */
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+ /* now allocate L2 page tables; they are linked to L1 below */
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[loop],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ } else {
+ kernel_pt_table[loop].pv_pa = freemempos +
+ (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
+ L2_TABLE_SIZE_REAL;
+ kernel_pt_table[loop].pv_va =
+ kernel_pt_table[loop].pv_pa +
+ (KERNVIRTADDR - abp->abp_physaddr);
+ }
+ }
+ freemem_pt = freemempos; /* base of allocated pt's */
+
+ /*
+ * Re-align allocation boundary so we can map the area
+ * write-back instead of write-through for the stacks and
+ * related structures allocated below.
+ */
+ freemempos = PHYSADDR + 0x100000;
+ /*
+ * Allocate a page for the system page mapped to V0x00000000
+ * This page will just contain the system vectors and can be
+ * shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate dynamic per-cpu area. */
+ valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
+ dpcpu_init((void *)dpcpu.pv_va, 0);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE);
+ valloc_pages(abtstack, ABT_STACK_SIZE);
+ valloc_pages(undstack, UND_STACK_SIZE);
+ valloc_pages(kernelstack, KSTACK_PAGES);
+ alloc_pages(minidataclean.pv_pa, 1);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+
+ /*
+ * Now construct the L1 page table. First map the L2
+ * page tables into the L1 so we can replace L1 mappings
+ * later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /* Map the L2 pages tables in the L1 page table */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1),
+ &kernel_pt_table[KERNEL_PT_SYS]);
+ pmap_link_l2pt(l1pagetable, IXP425_IO_VBASE,
+ &kernel_pt_table[KERNEL_PT_IO]);
+ pmap_link_l2pt(l1pagetable, IXP425_MCU_VBASE,
+ &kernel_pt_table[KERNEL_PT_IO + 1]);
+ pmap_link_l2pt(l1pagetable, IXP425_PCI_MEM_VBASE,
+ &kernel_pt_table[KERNEL_PT_IO + 2]);
+ pmap_link_l2pt(l1pagetable, KERNBASE,
+ &kernel_pt_table[KERNEL_PT_BEFOREKERN]);
+ pmap_map_chunk(l1pagetable, KERNBASE, PHYSADDR, 0x100000,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, PHYSADDR + 0x100000,
+ 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ pmap_map_chunk(l1pagetable, KERNEL_TEXT_BASE, KERNEL_TEXT_PHYS,
+ next_chunk2(((uint32_t)lastaddr) - KERNEL_TEXT_BASE, L1_S_SIZE),
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ freemem_after = next_page((int)lastaddr);
+ afterkern = round_page(next_chunk2((vm_offset_t)lastaddr, L1_S_SIZE));
+ for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
+ pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
+ &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
+ }
+ pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+
+ /* Map the Mini-Data cache clean area. */
+ xscale_setup_minidata(l1pagetable, afterkern,
+ minidataclean.pv_pa);
+
+ /* Map the vector page. */
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ if (cpu_is_ixp43x())
+ arm_devmap_bootstrap(l1pagetable, ixp435_devmap);
+ else
+ arm_devmap_bootstrap(l1pagetable, ixp425_devmap);
+ /*
+ * Give the XScale global cache clean code an appropriately
+ * sized chunk of unmapped VA space starting at 0xff000000
+ * (our device mappings end before this address).
+ */
+ xscale_cache_clean_addr = 0xff000000U;
+
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
+
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+ cpu_setup("");
+
+ /* ready to setup the console (XXX move earlier if possible) */
+ cninit();
+ /*
+ * Fetch the RAM size from the MCU registers. The
+ * expansion bus was mapped above so we can now read 'em.
+ */
+ if (cpu_is_ixp43x())
+ memsize = ixp435_ddram_size();
+ else
+ memsize = ixp425_sdram_size();
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+
+ pmap_curmaxkvaddr = afterkern + PAGE_SIZE;
+ vm_max_kernel_address = 0xd0000000;
+ pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
+ msgbufp = (void*)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+
+ /*
+ * Add the physical ram we have available.
+ *
+ * Exclude the kernel, and all the things we allocated which immediately
+ * follow the kernel, from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ arm_physmem_hardware_region(PHYSADDR, memsize);
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+#undef next_page
+#undef next_chunk2
+}
Property changes on: trunk/sys/arm/xscale/ixp425/avila_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/cambria_exp_space.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/cambria_exp_space.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/cambria_exp_space.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,259 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Sam Leffler. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Bus space tag for devices on the Cambria expansion bus.
+ * This interlocks accesses to allow the optional GPS+RS485 UART's
+ * to share access with the CF-IDE adapter. Note this does not
+ * slow the timing UART r/w ops because the lock operation does
+ * this implicitly for us. Also note we do not DELAY after byte/word
+ * chip select changes; this doesn't seem necessary (as required
+ * for IXP425/Avila boards).
+ *
+ * XXX should make this generic so all expansion bus devices can
+ * use it but probably not until we eliminate the ATA hacks
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/cambria_exp_space.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(exp);
+bs_protos(generic);
+
+struct expbus_softc {
+ struct ixp425_softc *sc; /* bus space tag */
+ struct mtx lock; /* i/o interlock */
+ bus_size_t csoff; /* CS offset for 8/16 enable */
+};
+#define EXP_LOCK_INIT(exp) \
+ mtx_init(&(exp)->lock, "ExpBus", NULL, MTX_SPIN)
+#define EXP_LOCK_DESTROY(exp) \
+ mtx_destroy(&(exp)->lock)
+#define EXP_LOCK(exp) mtx_lock_spin(&(exp)->lock)
+#define EXP_UNLOCK(exp) mtx_unlock_spin(&(exp)->lock)
+
+/*
+ * Enable/disable 16-bit ops on the expansion bus.
+ */
+static __inline void
+enable_16(struct ixp425_softc *sc, bus_size_t cs)
+{
+ EXP_BUS_WRITE_4(sc, cs, EXP_BUS_READ_4(sc, cs) &~ EXP_BYTE_EN);
+}
+
+static __inline void
+disable_16(struct ixp425_softc *sc, bus_size_t cs)
+{
+ EXP_BUS_WRITE_4(sc, cs, EXP_BUS_READ_4(sc, cs) | EXP_BYTE_EN);
+}
+
+static uint8_t
+cambria_bs_r_1(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o)
+{
+ struct expbus_softc *exp = tag->bs_privdata;
+ struct ixp425_softc *sc = exp->sc;
+ uint8_t v;
+
+ EXP_LOCK(exp);
+ v = bus_space_read_1(sc->sc_iot, h, o);
+ EXP_UNLOCK(exp);
+ return v;
+}
+
+static void
+cambria_bs_w_1(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o, u_int8_t v)
+{
+ struct expbus_softc *exp = tag->bs_privdata;
+ struct ixp425_softc *sc = exp->sc;
+
+ EXP_LOCK(exp);
+ bus_space_write_1(sc->sc_iot, h, o, v);
+ EXP_UNLOCK(exp);
+}
+
+static uint16_t
+cambria_bs_r_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o)
+{
+ struct expbus_softc *exp = tag->bs_privdata;
+ struct ixp425_softc *sc = exp->sc;
+ uint16_t v;
+
+ EXP_LOCK(exp);
+ enable_16(sc, exp->csoff);
+ v = bus_space_read_2(sc->sc_iot, h, o);
+ disable_16(sc, exp->csoff);
+ EXP_UNLOCK(exp);
+ return v;
+}
+
+static void
+cambria_bs_w_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o, uint16_t v)
+{
+ struct expbus_softc *exp = tag->bs_privdata;
+ struct ixp425_softc *sc = exp->sc;
+
+ EXP_LOCK(exp);
+ enable_16(sc, exp->csoff);
+ bus_space_write_2(sc->sc_iot, h, o, v);
+ disable_16(sc, exp->csoff);
+ EXP_UNLOCK(exp);
+}
+
+static void
+cambria_bs_rm_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
+ u_int16_t *d, bus_size_t c)
+{
+ struct expbus_softc *exp = tag->bs_privdata;
+ struct ixp425_softc *sc = exp->sc;
+
+ EXP_LOCK(exp);
+ enable_16(sc, exp->csoff);
+ bus_space_read_multi_2(sc->sc_iot, h, o, d, c);
+ disable_16(sc, exp->csoff);
+ EXP_UNLOCK(exp);
+}
+
+static void
+cambria_bs_wm_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
+ const u_int16_t *d, bus_size_t c)
+{
+ struct expbus_softc *exp = tag->bs_privdata;
+ struct ixp425_softc *sc = exp->sc;
+
+ EXP_LOCK(exp);
+ enable_16(sc, exp->csoff);
+ bus_space_write_multi_2(sc->sc_iot, h, o, d, c);
+ disable_16(sc, exp->csoff);
+ EXP_UNLOCK(exp);
+}
+
+/* XXX workaround ata driver by (incorrectly) byte swapping stream cases */
+
+static void
+cambria_bs_rm_2_s(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
+ u_int16_t *d, bus_size_t c)
+{
+ struct expbus_softc *exp = tag->bs_privdata;
+ struct ixp425_softc *sc = exp->sc;
+ uint16_t v;
+ bus_size_t i;
+
+ EXP_LOCK(exp);
+ enable_16(sc, exp->csoff);
+#if 1
+ for (i = 0; i < c; i++) {
+ v = bus_space_read_2(sc->sc_iot, h, o);
+ d[i] = bswap16(v);
+ }
+#else
+ bus_space_read_multi_stream_2(sc->sc_iot, h, o, d, c);
+#endif
+ disable_16(sc, exp->csoff);
+ EXP_UNLOCK(exp);
+}
+
+static void
+cambria_bs_wm_2_s(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
+ const u_int16_t *d, bus_size_t c)
+{
+ struct expbus_softc *exp = tag->bs_privdata;
+ struct ixp425_softc *sc = exp->sc;
+ bus_size_t i;
+
+ EXP_LOCK(exp);
+ enable_16(sc, exp->csoff);
+#if 1
+ for (i = 0; i < c; i++)
+ bus_space_write_2(sc->sc_iot, h, o, bswap16(d[i]));
+#else
+ bus_space_write_multi_stream_2(sc->sc_iot, h, o, d, c);
+#endif
+ disable_16(sc, exp->csoff);
+ EXP_UNLOCK(exp);
+}
+
+/* NB: we only define what's needed by ata+uart */
+struct bus_space cambria_exp_bs_tag = {
+ /* mapping/unmapping */
+ .bs_map = generic_bs_map,
+ .bs_unmap = generic_bs_unmap,
+
+ /* barrier */
+ .bs_barrier = generic_bs_barrier,
+
+ /* read (single) */
+ .bs_r_1 = cambria_bs_r_1,
+ .bs_r_2 = cambria_bs_r_2,
+
+ /* write (single) */
+ .bs_w_1 = cambria_bs_w_1,
+ .bs_w_2 = cambria_bs_w_2,
+
+ /* read multiple */
+ .bs_rm_2 = cambria_bs_rm_2,
+ .bs_rm_2_s = cambria_bs_rm_2_s,
+
+ /* write multiple */
+ .bs_wm_2 = cambria_bs_wm_2,
+ .bs_wm_2_s = cambria_bs_wm_2_s,
+};
+
+void
+cambria_exp_bus_init(struct ixp425_softc *sc)
+{
+ static struct expbus_softc c3; /* NB: no need to malloc */
+ uint32_t cs3;
+
+ KASSERT(cpu_is_ixp43x(), ("wrong cpu type"));
+
+ c3.sc = sc;
+ c3.csoff = EXP_TIMING_CS3_OFFSET;
+ EXP_LOCK_INIT(&c3);
+ cambria_exp_bs_tag.bs_privdata = &c3;
+
+ cs3 = EXP_BUS_READ_4(sc, EXP_TIMING_CS3_OFFSET);
+ /* XXX force slowest possible timings and byte mode */
+ EXP_BUS_WRITE_4(sc, EXP_TIMING_CS3_OFFSET,
+ cs3 | (EXP_T1|EXP_T2|EXP_T3|EXP_T4|EXP_T5) |
+ EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
+
+ /* XXX force GPIO 3+4 for GPS+RS485 uarts */
+ ixp425_set_gpio(sc, 3, GPIO_TYPE_EDG_RISING);
+ ixp425_set_gpio(sc, 4, GPIO_TYPE_EDG_RISING);
+}
Property changes on: trunk/sys/arm/xscale/ixp425/cambria_exp_space.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/cambria_fled.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/cambria_fled.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/cambria_fled.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,111 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Sam Leffler. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/cambria_fled.c 205705 2010-03-26 18:49:43Z rpaulo $");
+/*
+ * Cambria Front Panel LED sitting on the I2C bus.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/led/led.h>
+
+#include "iicbus_if.h"
+
+#define IIC_M_WR 0 /* write operation */
+#define LED_ADDR 0xae /* slave address */
+
+struct fled_softc {
+ struct cdev *sc_led;
+};
+
+static int
+fled_probe(device_t dev)
+{
+ device_set_desc(dev, "Gateworks Cambria Front Panel LED");
+ return 0;
+}
+
+static void
+fled_cb(void *arg, int onoff)
+{
+ uint8_t data[1];
+ struct iic_msg msgs[1] = {
+ { LED_ADDR, IIC_M_WR, 1, data },
+ };
+ device_t dev = arg;
+
+ data[0] = (onoff == 0); /* NB: low true */
+ (void) iicbus_transfer(dev, msgs, 1);
+}
+
+static int
+fled_attach(device_t dev)
+{
+ struct fled_softc *sc = device_get_softc(dev);
+
+ sc->sc_led = led_create(fled_cb, dev, "front");
+
+ fled_cb(dev, 1); /* Turn on LED */
+
+ return 0;
+}
+
+static int
+fled_detach(device_t dev)
+{
+ struct fled_softc *sc = device_get_softc(dev);
+
+ if (sc->sc_led != NULL)
+ led_destroy(sc->sc_led);
+
+ return 0;
+}
+
+static device_method_t fled_methods[] = {
+ DEVMETHOD(device_probe, fled_probe),
+ DEVMETHOD(device_attach, fled_attach),
+ DEVMETHOD(device_detach, fled_detach),
+
+ {0, 0},
+};
+
+static driver_t fled_driver = {
+ "fled",
+ fled_methods,
+ sizeof(struct fled_softc),
+};
+static devclass_t fled_devclass;
+
+DRIVER_MODULE(fled, iicbus, fled_driver, fled_devclass, 0, 0);
+MODULE_VERSION(fled, 1);
+MODULE_DEPEND(fled, iicbus, 1, 1, 1);
Property changes on: trunk/sys/arm/xscale/ixp425/cambria_fled.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/cambria_gpio.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/cambria_gpio.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/cambria_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,492 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010, Andrew Thompson <thompsa at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * GPIO driver for Gateworks Cambria
+ *
+ * Note:
+ * The Cambria PLD does not set the i2c ack bit after each write, if we used the
+ * regular iicbus interface it would abort the xfer after the address byte
+ * times out and not write our latch. To get around this we grab the iicbus and
+ * then do our own bit banging. This is a comprimise to changing all the iicbb
+ * device methods to allow a flag to be passed down and is similir to how Linux
+ * does it.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/cambria_gpio.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+#include <arm/xscale/ixp425/ixdp425reg.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include "iicbb_if.h"
+#include "gpio_if.h"
+
+#define IIC_M_WR 0 /* write operation */
+#define PLD_ADDR 0xac /* slave address */
+
+#define I2C_DELAY 10
+
+#define GPIO_CONF_CLR(sc, reg, mask) \
+ GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) &~ (mask))
+#define GPIO_CONF_SET(sc, reg, mask) \
+ GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) | (mask))
+
+#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define GPIO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
+
+#define GPIO_PINS 5
+struct cambria_gpio_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_gpio_ioh;
+ struct mtx sc_mtx;
+ struct gpio_pin sc_pins[GPIO_PINS];
+ uint8_t sc_latch;
+ uint8_t sc_val;
+};
+
+struct cambria_gpio_pin {
+ const char *name;
+ int pin;
+ int flags;
+};
+
+extern struct ixp425_softc *ixp425_softc;
+
+static struct cambria_gpio_pin cambria_gpio_pins[GPIO_PINS] = {
+ { "PLD0", 0, GPIO_PIN_OUTPUT },
+ { "PLD1", 1, GPIO_PIN_OUTPUT },
+ { "PLD2", 2, GPIO_PIN_OUTPUT },
+ { "PLD3", 3, GPIO_PIN_OUTPUT },
+ { "PLD4", 4, GPIO_PIN_OUTPUT },
+};
+
+/*
+ * Helpers
+ */
+static int cambria_gpio_read(struct cambria_gpio_softc *, uint32_t, unsigned int *);
+static int cambria_gpio_write(struct cambria_gpio_softc *);
+
+/*
+ * Driver stuff
+ */
+static int cambria_gpio_probe(device_t dev);
+static int cambria_gpio_attach(device_t dev);
+static int cambria_gpio_detach(device_t dev);
+
+/*
+ * GPIO interface
+ */
+static int cambria_gpio_pin_max(device_t dev, int *maxpin);
+static int cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
+static int cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
+ *flags);
+static int cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
+static int cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
+static int cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
+static int cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
+static int cambria_gpio_pin_toggle(device_t dev, uint32_t pin);
+
+static int
+i2c_getsda(struct cambria_gpio_softc *sc)
+{
+ uint32_t reg;
+
+ IXP4XX_GPIO_LOCK();
+ GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
+ IXP4XX_GPIO_UNLOCK();
+ return (reg & GPIO_I2C_SDA_BIT);
+}
+
+static void
+i2c_setsda(struct cambria_gpio_softc *sc, int val)
+{
+
+ IXP4XX_GPIO_LOCK();
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT);
+ if (val)
+ GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+ else
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+ IXP4XX_GPIO_UNLOCK();
+ DELAY(I2C_DELAY);
+}
+
+static void
+i2c_setscl(struct cambria_gpio_softc *sc, int val)
+{
+
+ IXP4XX_GPIO_LOCK();
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT);
+ if (val)
+ GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
+ else
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
+ IXP4XX_GPIO_UNLOCK();
+ DELAY(I2C_DELAY);
+}
+
+static void
+i2c_sendstart(struct cambria_gpio_softc *sc)
+{
+ i2c_setsda(sc, 1);
+ i2c_setscl(sc, 1);
+ i2c_setsda(sc, 0);
+ i2c_setscl(sc, 0);
+}
+
+static void
+i2c_sendstop(struct cambria_gpio_softc *sc)
+{
+ i2c_setscl(sc, 1);
+ i2c_setsda(sc, 1);
+ i2c_setscl(sc, 0);
+ i2c_setsda(sc, 0);
+}
+
+static void
+i2c_sendbyte(struct cambria_gpio_softc *sc, u_char data)
+{
+ int i;
+
+ for (i=7; i>=0; i--) {
+ i2c_setsda(sc, data & (1<<i));
+ i2c_setscl(sc, 1);
+ i2c_setscl(sc, 0);
+ }
+ i2c_setscl(sc, 1);
+ i2c_getsda(sc);
+ i2c_setscl(sc, 0);
+}
+
+static u_char
+i2c_readbyte(struct cambria_gpio_softc *sc)
+{
+ int i;
+ unsigned char data=0;
+
+ for (i=7; i>=0; i--)
+ {
+ i2c_setscl(sc, 1);
+ if (i2c_getsda(sc))
+ data |= (1<<i);
+ i2c_setscl(sc, 0);
+ }
+ return data;
+}
+
+static int
+cambria_gpio_read(struct cambria_gpio_softc *sc, uint32_t pin, unsigned int *val)
+{
+ device_t dev = sc->sc_dev;
+ int error;
+
+ error = iicbus_request_bus(device_get_parent(dev), dev,
+ IIC_DONTWAIT);
+ if (error)
+ return (error);
+
+ i2c_sendstart(sc);
+ i2c_sendbyte(sc, PLD_ADDR | LSB);
+ *val = (i2c_readbyte(sc) & (1 << pin)) != 0;
+ i2c_sendstop(sc);
+
+ iicbus_release_bus(device_get_parent(dev), dev);
+
+ return (0);
+}
+
+static int
+cambria_gpio_write(struct cambria_gpio_softc *sc)
+{
+ device_t dev = sc->sc_dev;
+ int error;
+
+ error = iicbus_request_bus(device_get_parent(dev), dev,
+ IIC_DONTWAIT);
+ if (error)
+ return (error);
+
+ i2c_sendstart(sc);
+ i2c_sendbyte(sc, PLD_ADDR & ~LSB);
+ i2c_sendbyte(sc, sc->sc_latch);
+ i2c_sendstop(sc);
+
+ iicbus_release_bus(device_get_parent(dev), dev);
+
+ return (0);
+}
+
+static int
+cambria_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = GPIO_PINS - 1;
+ return (0);
+}
+
+static int
+cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+
+ if (pin >= GPIO_PINS)
+ return (EINVAL);
+
+ *caps = sc->sc_pins[pin].gp_caps;
+ return (0);
+}
+
+static int
+cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+
+ if (pin >= GPIO_PINS)
+ return (EINVAL);
+
+ *flags = sc->sc_pins[pin].gp_flags;
+ return (0);
+}
+
+static int
+cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+
+ if (pin >= GPIO_PINS)
+ return (EINVAL);
+
+ memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
+ return (0);
+}
+
+static int
+cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+ int error;
+ uint8_t mask;
+
+ mask = 1 << pin;
+
+ if (pin >= GPIO_PINS)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ sc->sc_pins[pin].gp_flags = flags;
+
+ /*
+ * Writing a logical one sets the signal high and writing a logical
+ * zero sets the signal low. To configure a digital I/O signal as an
+ * input, a logical one must first be written to the data bit to
+ * three-state the associated output.
+ */
+ if (flags & GPIO_PIN_INPUT || sc->sc_val & mask)
+ sc->sc_latch |= mask; /* input or output & high */
+ else
+ sc->sc_latch &= ~mask;
+ error = cambria_gpio_write(sc);
+ GPIO_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+ int error;
+ uint8_t mask;
+
+ mask = 1 << pin;
+
+ if (pin >= GPIO_PINS)
+ return (EINVAL);
+ GPIO_LOCK(sc);
+ if (value)
+ sc->sc_val |= mask;
+ else
+ sc->sc_val &= ~mask;
+
+ if (sc->sc_pins[pin].gp_flags != GPIO_PIN_OUTPUT) {
+ /* just save, altering the latch will disable input */
+ GPIO_UNLOCK(sc);
+ return (0);
+ }
+
+ if (value)
+ sc->sc_latch |= mask;
+ else
+ sc->sc_latch &= ~mask;
+ error = cambria_gpio_write(sc);
+ GPIO_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+ int error = 0;
+
+ if (pin >= GPIO_PINS)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT)
+ *val = (sc->sc_latch & (1 << pin)) ? 1 : 0;
+ else
+ error = cambria_gpio_read(sc, pin, val);
+ GPIO_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+cambria_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+ int error = 0;
+
+ if (pin >= GPIO_PINS)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ sc->sc_val ^= (1 << pin);
+ if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT) {
+ sc->sc_latch ^= (1 << pin);
+ error = cambria_gpio_write(sc);
+ }
+ GPIO_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+cambria_gpio_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Gateworks Cambria GPIO driver");
+ return (0);
+}
+
+static int
+cambria_gpio_attach(device_t dev)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+ int pin;
+
+ sc->sc_dev = dev;
+ sc->sc_iot = ixp425_softc->sc_iot;
+ sc->sc_gpio_ioh = ixp425_softc->sc_gpio_ioh;
+
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ for (pin = 0; pin < GPIO_PINS; pin++) {
+ struct cambria_gpio_pin *p = &cambria_gpio_pins[pin];
+
+ strncpy(sc->sc_pins[pin].gp_name, p->name, GPIOMAXNAME);
+ sc->sc_pins[pin].gp_pin = pin;
+ sc->sc_pins[pin].gp_caps = GPIO_PIN_INPUT|GPIO_PIN_OUTPUT;
+ sc->sc_pins[pin].gp_flags = 0;
+ cambria_gpio_pin_setflags(dev, pin, p->flags);
+ }
+
+ device_add_child(dev, "gpioc", -1);
+ device_add_child(dev, "gpiobus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+cambria_gpio_detach(device_t dev)
+{
+ struct cambria_gpio_softc *sc = device_get_softc(dev);
+
+ KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
+
+ bus_generic_detach(dev);
+
+ mtx_destroy(&sc->sc_mtx);
+
+ return(0);
+}
+
+static device_method_t cambria_gpio_methods[] = {
+ DEVMETHOD(device_probe, cambria_gpio_probe),
+ DEVMETHOD(device_attach, cambria_gpio_attach),
+ DEVMETHOD(device_detach, cambria_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_pin_max, cambria_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, cambria_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, cambria_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, cambria_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, cambria_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, cambria_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, cambria_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, cambria_gpio_pin_toggle),
+ {0, 0},
+};
+
+static driver_t cambria_gpio_driver = {
+ "gpio_cambria",
+ cambria_gpio_methods,
+ sizeof(struct cambria_gpio_softc),
+};
+static devclass_t cambria_gpio_devclass;
+extern devclass_t gpiobus_devclass, gpioc_devclass;
+extern driver_t gpiobus_driver, gpioc_driver;
+
+DRIVER_MODULE(gpio_cambria, iicbus, cambria_gpio_driver, cambria_gpio_devclass, 0, 0);
+DRIVER_MODULE(gpiobus, gpio_cambria, gpiobus_driver, gpiobus_devclass, 0, 0);
+DRIVER_MODULE(gpioc, gpio_cambria, gpioc_driver, gpioc_devclass, 0, 0);
+MODULE_VERSION(gpio_cambria, 1);
+MODULE_DEPEND(gpio_cambria, iicbus, 1, 1, 1);
Property changes on: trunk/sys/arm/xscale/ixp425/cambria_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/cambria_led.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/cambria_led.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/cambria_led.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,134 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Sam Leffler. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/cambria_led.c 194015 2009-06-11 17:05:13Z avg $");
+
+/*
+ * Gateworks Cambria Octal LED Latch driver.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <machine/armreg.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#include <dev/led/led.h>
+
+struct led_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ struct cdev *sc_leds[8];
+ uint8_t sc_latch;
+};
+
+static void
+update_latch(struct led_softc *sc, int bit, int onoff)
+{
+ if (onoff)
+ sc->sc_latch &= ~bit;
+ else
+ sc->sc_latch |= bit;
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0, sc->sc_latch);
+}
+static void led_A(void *arg, int onoff) { update_latch(arg, 1<<0, onoff); }
+static void led_B(void *arg, int onoff) { update_latch(arg, 1<<1, onoff); }
+static void led_C(void *arg, int onoff) { update_latch(arg, 1<<2, onoff); }
+static void led_D(void *arg, int onoff) { update_latch(arg, 1<<3, onoff); }
+static void led_E(void *arg, int onoff) { update_latch(arg, 1<<4, onoff); }
+static void led_F(void *arg, int onoff) { update_latch(arg, 1<<5, onoff); }
+static void led_G(void *arg, int onoff) { update_latch(arg, 1<<6, onoff); }
+static void led_H(void *arg, int onoff) { update_latch(arg, 1<<7, onoff); }
+
+static int
+led_probe(device_t dev)
+{
+ device_set_desc(dev, "Gateworks Octal LED Latch");
+ return (0);
+}
+
+static int
+led_attach(device_t dev)
+{
+ struct led_softc *sc = device_get_softc(dev);
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+
+ sc->sc_dev = dev;
+ sc->sc_iot = sa->sc_iot;
+ /* NB: write anywhere works, use first location */
+ if (bus_space_map(sc->sc_iot, CAMBRIA_OCTAL_LED_HWBASE, sizeof(uint8_t),
+ 0, &sc->sc_ioh)) {
+ device_printf(dev, "cannot map LED latch (0x%lx)",
+ CAMBRIA_OCTAL_LED_HWBASE);
+ return ENXIO;
+ }
+
+ sc->sc_leds[0] = led_create(led_A, sc, "A");
+ sc->sc_leds[1] = led_create(led_B, sc, "B");
+ sc->sc_leds[2] = led_create(led_C, sc, "C");
+ sc->sc_leds[3] = led_create(led_D, sc, "D");
+ sc->sc_leds[4] = led_create(led_E, sc, "E");
+ sc->sc_leds[5] = led_create(led_F, sc, "F");
+ sc->sc_leds[6] = led_create(led_G, sc, "G");
+ sc->sc_leds[7] = led_create(led_H, sc, "H");
+
+ return 0;
+}
+
+static int
+led_detach(device_t dev)
+{
+ struct led_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ struct cdev *led = sc->sc_leds[i];
+ if (led != NULL)
+ led_destroy(led);
+ }
+ return (0);
+}
+
+static device_method_t led_methods[] = {
+ DEVMETHOD(device_probe, led_probe),
+ DEVMETHOD(device_attach, led_attach),
+ DEVMETHOD(device_detach, led_detach),
+
+ {0, 0},
+};
+
+static driver_t led_driver = {
+ "led_cambria",
+ led_methods,
+ sizeof(struct led_softc),
+};
+static devclass_t led_devclass;
+DRIVER_MODULE(led_cambria, ixp, led_driver, led_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/ixp425/cambria_led.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/files.avila
===================================================================
--- trunk/sys/arm/xscale/ixp425/files.avila (rev 0)
+++ trunk/sys/arm/xscale/ixp425/files.avila 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,10 @@
+#$FreeBSD: stable/10/sys/arm/xscale/ixp425/files.avila 215142 2010-11-11 20:18:33Z thompsa $
+arm/xscale/ixp425/avila_machdep.c standard
+arm/xscale/ixp425/avila_ata.c optional avila_ata
+arm/xscale/ixp425/avila_led.c optional avila_led
+arm/xscale/ixp425/avila_gpio.c optional avila_gpio
+arm/xscale/ixp425/cambria_exp_space.c standard
+arm/xscale/ixp425/cambria_fled.c optional cambria_fled
+arm/xscale/ixp425/cambria_led.c optional cambria_led
+arm/xscale/ixp425/cambria_gpio.c optional cambria_gpio
+arm/xscale/ixp425/ixdp425_pci.c optional pci
Property changes on: trunk/sys/arm/xscale/ixp425/files.avila
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/files.ixp425
===================================================================
--- trunk/sys/arm/xscale/ixp425/files.ixp425 (rev 0)
+++ trunk/sys/arm/xscale/ixp425/files.ixp425 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,49 @@
+#$FreeBSD: stable/10/sys/arm/xscale/ixp425/files.ixp425 266311 2014-05-17 13:53:38Z ian $
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_xscale.S standard
+arm/xscale/ixp425/ixp425.c standard
+arm/xscale/ixp425/ixp425_mem.c standard
+arm/xscale/ixp425/ixp425_space.c standard
+arm/xscale/ixp425/ixp425_timer.c standard
+arm/xscale/ixp425/ixp425_wdog.c optional ixpwdog
+arm/xscale/ixp425/ixp425_iic.c optional ixpiic
+arm/xscale/ixp425/ixp425_pci.c optional pci
+arm/xscale/ixp425/ixp425_pci_asm.S optional pci
+arm/xscale/ixp425/ixp425_pci_space.c optional pci
+arm/xscale/ixp425/uart_cpu_ixp425.c optional uart
+arm/xscale/ixp425/uart_bus_ixp425.c optional uart
+arm/xscale/ixp425/ixp425_a4x_space.c optional uart
+arm/xscale/ixp425/ixp425_a4x_io.S optional uart
+dev/cfi/cfi_bus_ixp4xx.c optional cfi
+dev/hwpmc/hwpmc_xscale.c optional hwpmc
+dev/uart/uart_dev_ns8250.c optional uart
+#
+# NPE-based Ethernet support (requires qmgr also).
+#
+arm/xscale/ixp425/if_npe.c optional npe
+arm/xscale/ixp425/ixp425_npe.c optional npe
+ixp425_npe_fw.c optional npe_fw \
+ compile-with "${AWK} -f $S/tools/fw_stub.awk IxNpeMicrocode.dat:npe_fw -mnpe -c${.TARGET}" \
+ no-implicit-rule before-depend local \
+ clean "ixp425_npe_fw.c"
+#
+# NB: ld encodes the path in the binary symbols generated for the
+# firmware image so link the file to the object directory to
+# get known values for reference in the _fw.c file.
+#
+IxNpeMicrocode.fwo optional npe_fw \
+ dependency "IxNpeMicrocode.dat" \
+ compile-with "${LD} -b binary -d -warn-common -r -d -o ${.TARGET} IxNpeMicrocode.dat" \
+ no-implicit-rule \
+ clean "IxNpeMicrocode.fwo"
+IxNpeMicrocode.dat optional npe_fw \
+ dependency "$S/contrib/dev/npe/IxNpeMicrocode.dat.uu" \
+ compile-with "uudecode < $S/contrib/dev/npe/IxNpeMicrocode.dat.uu" \
+ no-obj no-implicit-rule \
+ clean "IxNpeMicrocode.dat"
+#
+# Q-Manager support
+#
+arm/xscale/ixp425/ixp425_qmgr.c optional qmgr
+#
+dev/usb/controller/ehci_ixp4xx.c optional ehci usb
Property changes on: trunk/sys/arm/xscale/ixp425/files.ixp425
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/if_npe.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/if_npe.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/if_npe.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1784 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006-2008 Sam Leffler. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/if_npe.c 266406 2014-05-18 16:07:35Z ian $");
+
+/*
+ * Intel XScale NPE Ethernet driver.
+ *
+ * This driver handles the two ports present on the IXP425.
+ * Packet processing is done by the Network Processing Engines
+ * (NPE's) that work together with a MAC and PHY. The MAC
+ * is also mapped to the XScale cpu; the PHY is accessed via
+ * the MAC. NPE-XScale communication happens through h/w
+ * queues managed by the Q Manager block.
+ *
+ * The code here replaces the ethAcc, ethMii, and ethDB classes
+ * in the Intel Access Library (IAL) and the OS-specific driver.
+ *
+ * XXX add vlan support
+ */
+#ifdef HAVE_KERNEL_OPTION_HEADERS
+#include "opt_device_polling.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/endian.h>
+#include <machine/bus.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_mib.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+#include <arm/xscale/ixp425/ixp425_qmgr.h>
+#include <arm/xscale/ixp425/ixp425_npevar.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <arm/xscale/ixp425/if_npereg.h>
+
+#include <machine/armreg.h>
+
+#include "miibus_if.h"
+
+/*
+ * XXX: For the main bus dma tag. Can go away if the new method to get the
+ * dma tag from the parent got MFC'd into RELENG_6.
+ */
+extern struct ixp425_softc *ixp425_softc;
+
+struct npebuf {
+ struct npebuf *ix_next; /* chain to next buffer */
+ void *ix_m; /* backpointer to mbuf */
+ bus_dmamap_t ix_map; /* bus dma map for associated data */
+ struct npehwbuf *ix_hw; /* associated h/w block */
+ uint32_t ix_neaddr; /* phys address of ix_hw */
+};
+
+struct npedma {
+ const char* name;
+ int nbuf; /* # npebuf's allocated */
+ bus_dma_tag_t mtag; /* bus dma tag for mbuf data */
+ struct npehwbuf *hwbuf; /* NPE h/w buffers */
+ bus_dma_tag_t buf_tag; /* tag+map for NPE buffers */
+ bus_dmamap_t buf_map;
+ bus_addr_t buf_phys; /* phys addr of buffers */
+ struct npebuf *buf; /* s/w buffers (1-1 w/ h/w) */
+};
+
+struct npe_softc {
+ /* XXX mii requires this be first; do not move! */
+ struct ifnet *sc_ifp; /* ifnet pointer */
+ struct mtx sc_mtx; /* basically a perimeter lock */
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh; /* MAC register window */
+ device_t sc_mii; /* child miibus */
+ bus_space_handle_t sc_miih; /* MII register window */
+ int sc_npeid;
+ struct ixpnpe_softc *sc_npe; /* NPE support */
+ int sc_debug; /* DPRINTF* control */
+ int sc_tickinterval;
+ struct callout tick_ch; /* Tick callout */
+ int npe_watchdog_timer;
+ struct npedma txdma;
+ struct npebuf *tx_free; /* list of free tx buffers */
+ struct npedma rxdma;
+ bus_addr_t buf_phys; /* XXX for returning a value */
+ int rx_qid; /* rx qid */
+ int rx_freeqid; /* rx free buffers qid */
+ int tx_qid; /* tx qid */
+ int tx_doneqid; /* tx completed qid */
+ struct ifmib_iso_8802_3 mibdata;
+ bus_dma_tag_t sc_stats_tag; /* bus dma tag for stats block */
+ struct npestats *sc_stats;
+ bus_dmamap_t sc_stats_map;
+ bus_addr_t sc_stats_phys; /* phys addr of sc_stats */
+ struct npestats sc_totals; /* accumulated sc_stats */
+};
+
+/*
+ * Static configuration for IXP425. The tx and
+ * rx free Q id's are fixed by the NPE microcode. The
+ * rx Q id's are programmed to be separate to simplify
+ * multi-port processing. It may be better to handle
+ * all traffic through one Q (as done by the Intel drivers).
+ *
+ * Note that the PHY's are accessible only from MAC B on the
+ * IXP425 and from MAC C on other devices. This and other
+ * platform-specific assumptions are handled with hints.
+ */
+static const struct {
+ uint32_t macbase;
+ uint32_t miibase;
+ int phy; /* phy id */
+ uint8_t rx_qid;
+ uint8_t rx_freeqid;
+ uint8_t tx_qid;
+ uint8_t tx_doneqid;
+} npeconfig[NPE_MAX] = {
+ [NPE_A] = {
+ .macbase = IXP435_MAC_A_HWBASE,
+ .miibase = IXP425_MAC_C_HWBASE,
+ .phy = 2,
+ .rx_qid = 4,
+ .rx_freeqid = 26,
+ .tx_qid = 23,
+ .tx_doneqid = 31
+ },
+ [NPE_B] = {
+ .macbase = IXP425_MAC_B_HWBASE,
+ .miibase = IXP425_MAC_B_HWBASE,
+ .phy = 0,
+ .rx_qid = 4,
+ .rx_freeqid = 27,
+ .tx_qid = 24,
+ .tx_doneqid = 31
+ },
+ [NPE_C] = {
+ .macbase = IXP425_MAC_C_HWBASE,
+ .miibase = IXP425_MAC_B_HWBASE,
+ .phy = 1,
+ .rx_qid = 12,
+ .rx_freeqid = 28,
+ .tx_qid = 25,
+ .tx_doneqid = 31
+ },
+};
+static struct npe_softc *npes[NPE_MAX]; /* NB: indexed by npeid */
+
+static __inline uint32_t
+RD4(struct npe_softc *sc, bus_size_t off)
+{
+ return bus_space_read_4(sc->sc_iot, sc->sc_ioh, off);
+}
+
+static __inline void
+WR4(struct npe_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val);
+}
+
+#define NPE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define NPE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define NPE_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ MTX_NETWORK_LOCK, MTX_DEF)
+#define NPE_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define NPE_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define NPE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+static devclass_t npe_devclass;
+
+static int override_npeid(device_t, const char *resname, int *val);
+static int npe_activate(device_t dev);
+static void npe_deactivate(device_t dev);
+static int npe_ifmedia_update(struct ifnet *ifp);
+static void npe_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr);
+static void npe_setmac(struct npe_softc *sc, u_char *eaddr);
+static void npe_getmac(struct npe_softc *sc, u_char *eaddr);
+static void npe_txdone(int qid, void *arg);
+static int npe_rxbuf_init(struct npe_softc *, struct npebuf *,
+ struct mbuf *);
+static int npe_rxdone(int qid, void *arg);
+static void npeinit(void *);
+static void npestart_locked(struct ifnet *);
+static void npestart(struct ifnet *);
+static void npestop(struct npe_softc *);
+static void npewatchdog(struct npe_softc *);
+static int npeioctl(struct ifnet * ifp, u_long, caddr_t);
+
+static int npe_setrxqosentry(struct npe_softc *, int classix,
+ int trafclass, int qid);
+static int npe_setportaddress(struct npe_softc *, const uint8_t mac[]);
+static int npe_setfirewallmode(struct npe_softc *, int onoff);
+static int npe_updatestats(struct npe_softc *);
+#if 0
+static int npe_getstats(struct npe_softc *);
+static uint32_t npe_getimageid(struct npe_softc *);
+static int npe_setloopback(struct npe_softc *, int ena);
+#endif
+
+/* NB: all tx done processing goes through one queue */
+static int tx_doneqid = -1;
+
+static SYSCTL_NODE(_hw, OID_AUTO, npe, CTLFLAG_RD, 0,
+ "IXP4XX NPE driver parameters");
+
+static int npe_debug = 0;
+SYSCTL_INT(_hw_npe, OID_AUTO, debug, CTLFLAG_RW, &npe_debug,
+ 0, "IXP4XX NPE network interface debug msgs");
+TUNABLE_INT("hw.npe.debug", &npe_debug);
+#define DPRINTF(sc, fmt, ...) do { \
+ if (sc->sc_debug) device_printf(sc->sc_dev, fmt, __VA_ARGS__); \
+} while (0)
+#define DPRINTFn(n, sc, fmt, ...) do { \
+ if (sc->sc_debug >= n) device_printf(sc->sc_dev, fmt, __VA_ARGS__);\
+} while (0)
+static int npe_tickinterval = 3; /* npe_tick frequency (secs) */
+SYSCTL_INT(_hw_npe, OID_AUTO, tickinterval, CTLFLAG_RD, &npe_tickinterval,
+ 0, "periodic work interval (secs)");
+TUNABLE_INT("hw.npe.tickinterval", &npe_tickinterval);
+
+static int npe_rxbuf = 64; /* # rx buffers to allocate */
+SYSCTL_INT(_hw_npe, OID_AUTO, rxbuf, CTLFLAG_RD, &npe_rxbuf,
+ 0, "rx buffers allocated");
+TUNABLE_INT("hw.npe.rxbuf", &npe_rxbuf);
+static int npe_txbuf = 128; /* # tx buffers to allocate */
+SYSCTL_INT(_hw_npe, OID_AUTO, txbuf, CTLFLAG_RD, &npe_txbuf,
+ 0, "tx buffers allocated");
+TUNABLE_INT("hw.npe.txbuf", &npe_txbuf);
+
+static int
+unit2npeid(int unit)
+{
+ static const int npeidmap[2][3] = {
+ /* on 425 A is for HSS, B & C are for Ethernet */
+ { NPE_B, NPE_C, -1 }, /* IXP425 */
+ /* 435 only has A & C, order C then A */
+ { NPE_C, NPE_A, -1 }, /* IXP435 */
+ };
+ /* XXX check feature register instead */
+ return (unit < 3 ? npeidmap[
+ (cpu_id() & CPU_ID_CPU_MASK) == CPU_ID_IXP435][unit] : -1);
+}
+
+static int
+npe_probe(device_t dev)
+{
+ static const char *desc[NPE_MAX] = {
+ [NPE_A] = "IXP NPE-A",
+ [NPE_B] = "IXP NPE-B",
+ [NPE_C] = "IXP NPE-C"
+ };
+ int unit = device_get_unit(dev);
+ int npeid;
+
+ if (unit > 2 ||
+ (ixp4xx_read_feature_bits() &
+ (unit == 0 ? EXP_FCTRL_ETH0 : EXP_FCTRL_ETH1)) == 0)
+ return EINVAL;
+
+ npeid = -1;
+ if (!override_npeid(dev, "npeid", &npeid))
+ npeid = unit2npeid(unit);
+ if (npeid == -1) {
+ device_printf(dev, "unit %d not supported\n", unit);
+ return EINVAL;
+ }
+ device_set_desc(dev, desc[npeid]);
+ return 0;
+}
+
+static int
+npe_attach(device_t dev)
+{
+ struct npe_softc *sc = device_get_softc(dev);
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
+ struct sysctl_oid *tree = device_get_sysctl_tree(dev);
+ struct ifnet *ifp;
+ int error;
+ u_char eaddr[6];
+
+ sc->sc_dev = dev;
+ sc->sc_iot = sa->sc_iot;
+ NPE_LOCK_INIT(sc);
+ callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
+ sc->sc_debug = npe_debug;
+ sc->sc_tickinterval = npe_tickinterval;
+
+ ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "cannot allocate ifnet\n");
+ error = EIO; /* XXX */
+ goto out;
+ }
+ /* NB: must be setup prior to invoking mii code */
+ sc->sc_ifp = ifp;
+
+ error = npe_activate(dev);
+ if (error) {
+ device_printf(dev, "cannot activate npe\n");
+ goto out;
+ }
+
+ npe_getmac(sc, eaddr);
+
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = npestart;
+ ifp->if_ioctl = npeioctl;
+ ifp->if_init = npeinit;
+ IFQ_SET_MAXLEN(&ifp->if_snd, sc->txdma.nbuf - 1);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_linkmib = &sc->mibdata;
+ ifp->if_linkmiblen = sizeof(sc->mibdata);
+ sc->mibdata.dot3Compliance = DOT3COMPLIANCE_STATS;
+ /* device supports oversided vlan frames */
+ ifp->if_capabilities |= IFCAP_VLAN_MTU;
+ ifp->if_capenable = ifp->if_capabilities;
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
+
+ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "debug",
+ CTLFLAG_RW, &sc->sc_debug, 0, "control debugging printfs");
+ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tickinterval",
+ CTLFLAG_RW, &sc->sc_tickinterval, 0, "periodic work frequency");
+ SYSCTL_ADD_STRUCT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "stats",
+ CTLFLAG_RD, &sc->sc_totals, npestats, "onboard stats");
+
+ ether_ifattach(ifp, eaddr);
+ return 0;
+out:
+ if (ifp != NULL)
+ if_free(ifp);
+ NPE_LOCK_DESTROY(sc);
+ npe_deactivate(dev);
+ return error;
+}
+
+static int
+npe_detach(device_t dev)
+{
+ struct npe_softc *sc = device_get_softc(dev);
+ struct ifnet *ifp = sc->sc_ifp;
+
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(ifp);
+#endif
+ npestop(sc);
+ if (ifp != NULL) {
+ ether_ifdetach(ifp);
+ if_free(ifp);
+ }
+ NPE_LOCK_DESTROY(sc);
+ npe_deactivate(dev);
+ return 0;
+}
+
+/*
+ * Compute and install the multicast filter.
+ */
+static void
+npe_setmcast(struct npe_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ uint8_t mask[ETHER_ADDR_LEN], addr[ETHER_ADDR_LEN];
+ int i;
+
+ if (ifp->if_flags & IFF_PROMISC) {
+ memset(mask, 0, ETHER_ADDR_LEN);
+ memset(addr, 0, ETHER_ADDR_LEN);
+ } else if (ifp->if_flags & IFF_ALLMULTI) {
+ static const uint8_t allmulti[ETHER_ADDR_LEN] =
+ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ memcpy(mask, allmulti, ETHER_ADDR_LEN);
+ memcpy(addr, allmulti, ETHER_ADDR_LEN);
+ } else {
+ uint8_t clr[ETHER_ADDR_LEN], set[ETHER_ADDR_LEN];
+ struct ifmultiaddr *ifma;
+ const uint8_t *mac;
+
+ memset(clr, 0, ETHER_ADDR_LEN);
+ memset(set, 0xff, ETHER_ADDR_LEN);
+
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ mac = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ clr[i] |= mac[i];
+ set[i] &= mac[i];
+ }
+ }
+ if_maddr_runlock(ifp);
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ mask[i] = set[i] | ~clr[i];
+ addr[i] = set[i];
+ }
+ }
+
+ /*
+ * Write the mask and address registers.
+ */
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ WR4(sc, NPE_MAC_ADDR_MASK(i), mask[i]);
+ WR4(sc, NPE_MAC_ADDR(i), addr[i]);
+ }
+}
+
+static void
+npe_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct npe_softc *sc;
+
+ if (error != 0)
+ return;
+ sc = (struct npe_softc *)arg;
+ sc->buf_phys = segs[0].ds_addr;
+}
+
+static int
+npe_dma_setup(struct npe_softc *sc, struct npedma *dma,
+ const char *name, int nbuf, int maxseg)
+{
+ int error, i;
+
+ memset(dma, 0, sizeof(*dma));
+
+ dma->name = name;
+ dma->nbuf = nbuf;
+
+ /* DMA tag for mapped mbufs */
+ error = bus_dma_tag_create(ixp425_softc->sc_dmat, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ MCLBYTES, maxseg, MCLBYTES, 0,
+ busdma_lock_mutex, &sc->sc_mtx, &dma->mtag);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "unable to create %s mbuf dma tag, "
+ "error %u\n", dma->name, error);
+ return error;
+ }
+
+ /* DMA tag and map for the NPE buffers */
+ error = bus_dma_tag_create(ixp425_softc->sc_dmat, sizeof(uint32_t), 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ nbuf * sizeof(struct npehwbuf), 1,
+ nbuf * sizeof(struct npehwbuf), 0,
+ busdma_lock_mutex, &sc->sc_mtx, &dma->buf_tag);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "unable to create %s npebuf dma tag, error %u\n",
+ dma->name, error);
+ return error;
+ }
+ if (bus_dmamem_alloc(dma->buf_tag, (void **)&dma->hwbuf,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
+ &dma->buf_map) != 0) {
+ device_printf(sc->sc_dev,
+ "unable to allocate memory for %s h/w buffers, error %u\n",
+ dma->name, error);
+ return error;
+ }
+ /* XXX M_TEMP */
+ dma->buf = malloc(nbuf * sizeof(struct npebuf), M_TEMP, M_NOWAIT | M_ZERO);
+ if (dma->buf == NULL) {
+ device_printf(sc->sc_dev,
+ "unable to allocate memory for %s s/w buffers\n",
+ dma->name);
+ return error;
+ }
+ if (bus_dmamap_load(dma->buf_tag, dma->buf_map,
+ dma->hwbuf, nbuf*sizeof(struct npehwbuf), npe_getaddr, sc, 0) != 0) {
+ device_printf(sc->sc_dev,
+ "unable to map memory for %s h/w buffers, error %u\n",
+ dma->name, error);
+ return error;
+ }
+ dma->buf_phys = sc->buf_phys;
+ for (i = 0; i < dma->nbuf; i++) {
+ struct npebuf *npe = &dma->buf[i];
+ struct npehwbuf *hw = &dma->hwbuf[i];
+
+ /* calculate offset to shared area */
+ npe->ix_neaddr = dma->buf_phys +
+ ((uintptr_t)hw - (uintptr_t)dma->hwbuf);
+ KASSERT((npe->ix_neaddr & 0x1f) == 0,
+ ("ixpbuf misaligned, PA 0x%x", npe->ix_neaddr));
+ error = bus_dmamap_create(dma->mtag, BUS_DMA_NOWAIT,
+ &npe->ix_map);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "unable to create dmamap for %s buffer %u, "
+ "error %u\n", dma->name, i, error);
+ return error;
+ }
+ npe->ix_hw = hw;
+ }
+ bus_dmamap_sync(dma->buf_tag, dma->buf_map, BUS_DMASYNC_PREWRITE);
+ return 0;
+}
+
+static void
+npe_dma_destroy(struct npe_softc *sc, struct npedma *dma)
+{
+ int i;
+
+ if (dma->hwbuf != NULL) {
+ for (i = 0; i < dma->nbuf; i++) {
+ struct npebuf *npe = &dma->buf[i];
+ bus_dmamap_destroy(dma->mtag, npe->ix_map);
+ }
+ bus_dmamap_unload(dma->buf_tag, dma->buf_map);
+ bus_dmamem_free(dma->buf_tag, dma->hwbuf, dma->buf_map);
+ }
+ if (dma->buf != NULL)
+ free(dma->buf, M_TEMP);
+ if (dma->buf_tag)
+ bus_dma_tag_destroy(dma->buf_tag);
+ if (dma->mtag)
+ bus_dma_tag_destroy(dma->mtag);
+ memset(dma, 0, sizeof(*dma));
+}
+
+static int
+override_addr(device_t dev, const char *resname, int *base)
+{
+ int unit = device_get_unit(dev);
+ const char *resval;
+
+ /* XXX warn for wrong hint type */
+ if (resource_string_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ switch (resval[0]) {
+ case 'A':
+ *base = IXP435_MAC_A_HWBASE;
+ break;
+ case 'B':
+ *base = IXP425_MAC_B_HWBASE;
+ break;
+ case 'C':
+ *base = IXP425_MAC_C_HWBASE;
+ break;
+ default:
+ device_printf(dev, "Warning, bad value %s for "
+ "npe.%d.%s ignored\n", resval, unit, resname);
+ return 0;
+ }
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=%s override\n",
+ unit, resname, resval);
+ return 1;
+}
+
+static int
+override_npeid(device_t dev, const char *resname, int *npeid)
+{
+ int unit = device_get_unit(dev);
+ const char *resval;
+
+ /* XXX warn for wrong hint type */
+ if (resource_string_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ switch (resval[0]) {
+ case 'A': *npeid = NPE_A; break;
+ case 'B': *npeid = NPE_B; break;
+ case 'C': *npeid = NPE_C; break;
+ default:
+ device_printf(dev, "Warning, bad value %s for "
+ "npe.%d.%s ignored\n", resval, unit, resname);
+ return 0;
+ }
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=%s override\n",
+ unit, resname, resval);
+ return 1;
+}
+
+static int
+override_unit(device_t dev, const char *resname, int *val, int min, int max)
+{
+ int unit = device_get_unit(dev);
+ int resval;
+
+ if (resource_int_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ if (!(min <= resval && resval <= max)) {
+ device_printf(dev, "Warning, bad value %d for npe.%d.%s "
+ "ignored (value must be [%d-%d])\n", resval, unit,
+ resname, min, max);
+ return 0;
+ }
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=%d override\n",
+ unit, resname, resval);
+ *val = resval;
+ return 1;
+}
+
+static void
+npe_mac_reset(struct npe_softc *sc)
+{
+ /*
+ * Reset MAC core.
+ */
+ WR4(sc, NPE_MAC_CORE_CNTRL, NPE_CORE_RESET);
+ DELAY(NPE_MAC_RESET_DELAY);
+ /* configure MAC to generate MDC clock */
+ WR4(sc, NPE_MAC_CORE_CNTRL, NPE_CORE_MDC_EN);
+}
+
+static int
+npe_activate(device_t dev)
+{
+ struct npe_softc *sc = device_get_softc(dev);
+ int error, i, macbase, miibase, phy;
+
+ /*
+ * Setup NEP ID, MAC, and MII bindings. We allow override
+ * via hints to handle unexpected board configs.
+ */
+ if (!override_npeid(dev, "npeid", &sc->sc_npeid))
+ sc->sc_npeid = unit2npeid(device_get_unit(dev));
+ sc->sc_npe = ixpnpe_attach(dev, sc->sc_npeid);
+ if (sc->sc_npe == NULL) {
+ device_printf(dev, "cannot attach ixpnpe\n");
+ return EIO; /* XXX */
+ }
+
+ /* MAC */
+ if (!override_addr(dev, "mac", &macbase))
+ macbase = npeconfig[sc->sc_npeid].macbase;
+ device_printf(sc->sc_dev, "MAC at 0x%x\n", macbase);
+ if (bus_space_map(sc->sc_iot, macbase, IXP425_REG_SIZE, 0, &sc->sc_ioh)) {
+ device_printf(dev, "cannot map mac registers 0x%x:0x%x\n",
+ macbase, IXP425_REG_SIZE);
+ return ENOMEM;
+ }
+
+ /* PHY */
+ if (!override_unit(dev, "phy", &phy, 0, MII_NPHY - 1))
+ phy = npeconfig[sc->sc_npeid].phy;
+ if (!override_addr(dev, "mii", &miibase))
+ miibase = npeconfig[sc->sc_npeid].miibase;
+ device_printf(sc->sc_dev, "MII at 0x%x\n", miibase);
+ if (miibase != macbase) {
+ /*
+ * PHY is mapped through a different MAC, setup an
+ * additional mapping for frobbing the PHY registers.
+ */
+ if (bus_space_map(sc->sc_iot, miibase, IXP425_REG_SIZE, 0, &sc->sc_miih)) {
+ device_printf(dev,
+ "cannot map MII registers 0x%x:0x%x\n",
+ miibase, IXP425_REG_SIZE);
+ return ENOMEM;
+ }
+ } else
+ sc->sc_miih = sc->sc_ioh;
+
+ /*
+ * Load NPE firmware and start it running.
+ */
+ error = ixpnpe_init(sc->sc_npe);
+ if (error != 0) {
+ device_printf(dev, "cannot init NPE (error %d)\n", error);
+ return error;
+ }
+
+ /* attach PHY */
+ error = mii_attach(dev, &sc->sc_mii, sc->sc_ifp, npe_ifmedia_update,
+ npe_ifmedia_status, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
+ if (error != 0) {
+ device_printf(dev, "attaching PHYs failed\n");
+ return error;
+ }
+
+ error = npe_dma_setup(sc, &sc->txdma, "tx", npe_txbuf, NPE_MAXSEG);
+ if (error != 0)
+ return error;
+ error = npe_dma_setup(sc, &sc->rxdma, "rx", npe_rxbuf, 1);
+ if (error != 0)
+ return error;
+
+ /* setup statistics block */
+ error = bus_dma_tag_create(ixp425_softc->sc_dmat, sizeof(uint32_t), 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ sizeof(struct npestats), 1, sizeof(struct npestats), 0,
+ busdma_lock_mutex, &sc->sc_mtx, &sc->sc_stats_tag);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "unable to create stats tag, "
+ "error %u\n", error);
+ return error;
+ }
+ if (bus_dmamem_alloc(sc->sc_stats_tag, (void **)&sc->sc_stats,
+ BUS_DMA_NOWAIT, &sc->sc_stats_map) != 0) {
+ device_printf(sc->sc_dev,
+ "unable to allocate memory for stats block, error %u\n",
+ error);
+ return error;
+ }
+ if (bus_dmamap_load(sc->sc_stats_tag, sc->sc_stats_map,
+ sc->sc_stats, sizeof(struct npestats), npe_getaddr, sc, 0) != 0) {
+ device_printf(sc->sc_dev,
+ "unable to load memory for stats block, error %u\n",
+ error);
+ return error;
+ }
+ sc->sc_stats_phys = sc->buf_phys;
+
+ /*
+ * Setup h/w rx/tx queues. There are four q's:
+ * rx inbound q of rx'd frames
+ * rx_free pool of ixpbuf's for receiving frames
+ * tx outbound q of frames to send
+ * tx_done q of tx frames that have been processed
+ *
+ * The NPE handles the actual tx/rx process and the q manager
+ * handles the queues. The driver just writes entries to the
+ * q manager mailbox's and gets callbacks when there are rx'd
+ * frames to process or tx'd frames to reap. These callbacks
+ * are controlled by the q configurations; e.g. we get a
+ * callback when tx_done has 2 or more frames to process and
+ * when the rx q has at least one frame. These setings can
+ * changed at the time the q is configured.
+ */
+ sc->rx_qid = npeconfig[sc->sc_npeid].rx_qid;
+ ixpqmgr_qconfig(sc->rx_qid, npe_rxbuf, 0, 1,
+ IX_QMGR_Q_SOURCE_ID_NOT_E, (qconfig_hand_t *)npe_rxdone, sc);
+ sc->rx_freeqid = npeconfig[sc->sc_npeid].rx_freeqid;
+ ixpqmgr_qconfig(sc->rx_freeqid, npe_rxbuf, 0, npe_rxbuf/2, 0, NULL, sc);
+ /*
+ * Setup the NPE to direct all traffic to rx_qid.
+ * When QoS is enabled in the firmware there are
+ * 8 traffic classes; otherwise just 4.
+ */
+ for (i = 0; i < 8; i++)
+ npe_setrxqosentry(sc, i, 0, sc->rx_qid);
+
+ /* disable firewall mode just in case (should be off) */
+ npe_setfirewallmode(sc, 0);
+
+ sc->tx_qid = npeconfig[sc->sc_npeid].tx_qid;
+ sc->tx_doneqid = npeconfig[sc->sc_npeid].tx_doneqid;
+ ixpqmgr_qconfig(sc->tx_qid, npe_txbuf, 0, npe_txbuf, 0, NULL, sc);
+ if (tx_doneqid == -1) {
+ ixpqmgr_qconfig(sc->tx_doneqid, npe_txbuf, 0, 2,
+ IX_QMGR_Q_SOURCE_ID_NOT_E, npe_txdone, sc);
+ tx_doneqid = sc->tx_doneqid;
+ }
+
+ KASSERT(npes[sc->sc_npeid] == NULL,
+ ("npe %u already setup", sc->sc_npeid));
+ npes[sc->sc_npeid] = sc;
+
+ return 0;
+}
+
+static void
+npe_deactivate(device_t dev)
+{
+ struct npe_softc *sc = device_get_softc(dev);
+
+ npes[sc->sc_npeid] = NULL;
+
+ /* XXX disable q's */
+ if (sc->sc_npe != NULL) {
+ ixpnpe_stop(sc->sc_npe);
+ ixpnpe_detach(sc->sc_npe);
+ }
+ if (sc->sc_stats != NULL) {
+ bus_dmamap_unload(sc->sc_stats_tag, sc->sc_stats_map);
+ bus_dmamem_free(sc->sc_stats_tag, sc->sc_stats,
+ sc->sc_stats_map);
+ }
+ if (sc->sc_stats_tag != NULL)
+ bus_dma_tag_destroy(sc->sc_stats_tag);
+ npe_dma_destroy(sc, &sc->txdma);
+ npe_dma_destroy(sc, &sc->rxdma);
+ bus_generic_detach(sc->sc_dev);
+ if (sc->sc_mii != NULL)
+ device_delete_child(sc->sc_dev, sc->sc_mii);
+}
+
+/*
+ * Change media according to request.
+ */
+static int
+npe_ifmedia_update(struct ifnet *ifp)
+{
+ struct npe_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+
+ mii = device_get_softc(sc->sc_mii);
+ NPE_LOCK(sc);
+ mii_mediachg(mii);
+ /* XXX push state ourself? */
+ NPE_UNLOCK(sc);
+ return (0);
+}
+
+/*
+ * Notify the world which media we're using.
+ */
+static void
+npe_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct npe_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+
+ mii = device_get_softc(sc->sc_mii);
+ NPE_LOCK(sc);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ NPE_UNLOCK(sc);
+}
+
+static void
+npe_addstats(struct npe_softc *sc)
+{
+#define NPEADD(x) sc->sc_totals.x += be32toh(ns->x)
+#define MIBADD(x) do { sc->mibdata.x += be32toh(ns->x); NPEADD(x); } while (0)
+ struct ifnet *ifp = sc->sc_ifp;
+ struct npestats *ns = sc->sc_stats;
+
+ MIBADD(dot3StatsAlignmentErrors);
+ MIBADD(dot3StatsFCSErrors);
+ MIBADD(dot3StatsInternalMacReceiveErrors);
+ NPEADD(RxOverrunDiscards);
+ NPEADD(RxLearnedEntryDiscards);
+ NPEADD(RxLargeFramesDiscards);
+ NPEADD(RxSTPBlockedDiscards);
+ NPEADD(RxVLANTypeFilterDiscards);
+ NPEADD(RxVLANIdFilterDiscards);
+ NPEADD(RxInvalidSourceDiscards);
+ NPEADD(RxBlackListDiscards);
+ NPEADD(RxWhiteListDiscards);
+ NPEADD(RxUnderflowEntryDiscards);
+ MIBADD(dot3StatsSingleCollisionFrames);
+ MIBADD(dot3StatsMultipleCollisionFrames);
+ MIBADD(dot3StatsDeferredTransmissions);
+ MIBADD(dot3StatsLateCollisions);
+ MIBADD(dot3StatsExcessiveCollisions);
+ MIBADD(dot3StatsInternalMacTransmitErrors);
+ MIBADD(dot3StatsCarrierSenseErrors);
+ NPEADD(TxLargeFrameDiscards);
+ NPEADD(TxVLANIdFilterDiscards);
+
+ sc->mibdata.dot3StatsFrameTooLongs +=
+ be32toh(ns->RxLargeFramesDiscards)
+ + be32toh(ns->TxLargeFrameDiscards);
+ sc->mibdata.dot3StatsMissedFrames +=
+ be32toh(ns->RxOverrunDiscards)
+ + be32toh(ns->RxUnderflowEntryDiscards);
+
+ ifp->if_oerrors +=
+ be32toh(ns->dot3StatsInternalMacTransmitErrors)
+ + be32toh(ns->dot3StatsCarrierSenseErrors)
+ + be32toh(ns->TxVLANIdFilterDiscards)
+ ;
+ ifp->if_ierrors += be32toh(ns->dot3StatsFCSErrors)
+ + be32toh(ns->dot3StatsInternalMacReceiveErrors)
+ + be32toh(ns->RxOverrunDiscards)
+ + be32toh(ns->RxUnderflowEntryDiscards)
+ ;
+ ifp->if_collisions +=
+ be32toh(ns->dot3StatsSingleCollisionFrames)
+ + be32toh(ns->dot3StatsMultipleCollisionFrames)
+ ;
+#undef NPEADD
+#undef MIBADD
+}
+
+static void
+npe_tick(void *xsc)
+{
+#define ACK (NPE_RESETSTATS << NPE_MAC_MSGID_SHL)
+ struct npe_softc *sc = xsc;
+ struct mii_data *mii = device_get_softc(sc->sc_mii);
+ uint32_t msg[2];
+
+ NPE_ASSERT_LOCKED(sc);
+
+ /*
+ * NB: to avoid sleeping with the softc lock held we
+ * split the NPE msg processing into two parts. The
+ * request for statistics is sent w/o waiting for a
+ * reply and then on the next tick we retrieve the
+ * results. This works because npe_tick is the only
+ * code that talks via the mailbox's (except at setup).
+ * This likely can be handled better.
+ */
+ if (ixpnpe_recvmsg_async(sc->sc_npe, msg) == 0 && msg[0] == ACK) {
+ bus_dmamap_sync(sc->sc_stats_tag, sc->sc_stats_map,
+ BUS_DMASYNC_POSTREAD);
+ npe_addstats(sc);
+ }
+ npe_updatestats(sc);
+ mii_tick(mii);
+
+ npewatchdog(sc);
+
+ /* schedule next poll */
+ callout_reset(&sc->tick_ch, sc->sc_tickinterval * hz, npe_tick, sc);
+#undef ACK
+}
+
+static void
+npe_setmac(struct npe_softc *sc, u_char *eaddr)
+{
+ WR4(sc, NPE_MAC_UNI_ADDR_1, eaddr[0]);
+ WR4(sc, NPE_MAC_UNI_ADDR_2, eaddr[1]);
+ WR4(sc, NPE_MAC_UNI_ADDR_3, eaddr[2]);
+ WR4(sc, NPE_MAC_UNI_ADDR_4, eaddr[3]);
+ WR4(sc, NPE_MAC_UNI_ADDR_5, eaddr[4]);
+ WR4(sc, NPE_MAC_UNI_ADDR_6, eaddr[5]);
+}
+
+static void
+npe_getmac(struct npe_softc *sc, u_char *eaddr)
+{
+ /* NB: the unicast address appears to be loaded from EEPROM on reset */
+ eaddr[0] = RD4(sc, NPE_MAC_UNI_ADDR_1) & 0xff;
+ eaddr[1] = RD4(sc, NPE_MAC_UNI_ADDR_2) & 0xff;
+ eaddr[2] = RD4(sc, NPE_MAC_UNI_ADDR_3) & 0xff;
+ eaddr[3] = RD4(sc, NPE_MAC_UNI_ADDR_4) & 0xff;
+ eaddr[4] = RD4(sc, NPE_MAC_UNI_ADDR_5) & 0xff;
+ eaddr[5] = RD4(sc, NPE_MAC_UNI_ADDR_6) & 0xff;
+}
+
+struct txdone {
+ struct npebuf *head;
+ struct npebuf **tail;
+ int count;
+};
+
+static __inline void
+npe_txdone_finish(struct npe_softc *sc, const struct txdone *td)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+
+ NPE_LOCK(sc);
+ *td->tail = sc->tx_free;
+ sc->tx_free = td->head;
+ /*
+ * We're no longer busy, so clear the busy flag and call the
+ * start routine to xmit more packets.
+ */
+ ifp->if_opackets += td->count;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ sc->npe_watchdog_timer = 0;
+ npestart_locked(ifp);
+ NPE_UNLOCK(sc);
+}
+
+/*
+ * Q manager callback on tx done queue. Reap mbufs
+ * and return tx buffers to the free list. Finally
+ * restart output. Note the microcode has only one
+ * txdone q wired into it so we must use the NPE ID
+ * returned with each npehwbuf to decide where to
+ * send buffers.
+ */
+static void
+npe_txdone(int qid, void *arg)
+{
+#define P2V(a, dma) \
+ &(dma)->buf[((a) - (dma)->buf_phys) / sizeof(struct npehwbuf)]
+ struct npe_softc *sc0 = arg;
+ struct npe_softc *sc;
+ struct npebuf *npe;
+ struct txdone *td, q[NPE_MAX];
+ uint32_t entry;
+
+ q[NPE_A].tail = &q[NPE_A].head; q[NPE_A].count = 0;
+ q[NPE_B].tail = &q[NPE_B].head; q[NPE_B].count = 0;
+ q[NPE_C].tail = &q[NPE_C].head; q[NPE_C].count = 0;
+ /* XXX max # at a time? */
+ while (ixpqmgr_qread(qid, &entry) == 0) {
+ DPRINTF(sc0, "%s: entry 0x%x NPE %u port %u\n",
+ __func__, entry, NPE_QM_Q_NPE(entry), NPE_QM_Q_PORT(entry));
+
+ sc = npes[NPE_QM_Q_NPE(entry)];
+ npe = P2V(NPE_QM_Q_ADDR(entry), &sc->txdma);
+ m_freem(npe->ix_m);
+ npe->ix_m = NULL;
+
+ td = &q[NPE_QM_Q_NPE(entry)];
+ *td->tail = npe;
+ td->tail = &npe->ix_next;
+ td->count++;
+ }
+
+ if (q[NPE_A].count)
+ npe_txdone_finish(npes[NPE_A], &q[NPE_A]);
+ if (q[NPE_B].count)
+ npe_txdone_finish(npes[NPE_B], &q[NPE_B]);
+ if (q[NPE_C].count)
+ npe_txdone_finish(npes[NPE_C], &q[NPE_C]);
+#undef P2V
+}
+
+static int
+npe_rxbuf_init(struct npe_softc *sc, struct npebuf *npe, struct mbuf *m)
+{
+ bus_dma_segment_t segs[1];
+ struct npedma *dma = &sc->rxdma;
+ struct npehwbuf *hw;
+ int error, nseg;
+
+ if (m == NULL) {
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL)
+ return ENOBUFS;
+ }
+ KASSERT(m->m_ext.ext_size >= 1536 + ETHER_ALIGN,
+ ("ext_size %d", m->m_ext.ext_size));
+ m->m_pkthdr.len = m->m_len = 1536;
+ /* backload payload and align ip hdr */
+ m->m_data = m->m_ext.ext_buf + (m->m_ext.ext_size - (1536+ETHER_ALIGN));
+ bus_dmamap_unload(dma->mtag, npe->ix_map);
+ error = bus_dmamap_load_mbuf_sg(dma->mtag, npe->ix_map, m,
+ segs, &nseg, 0);
+ if (error != 0) {
+ m_freem(m);
+ return error;
+ }
+ hw = npe->ix_hw;
+ hw->ix_ne[0].data = htobe32(segs[0].ds_addr);
+ /* NB: NPE requires length be a multiple of 64 */
+ /* NB: buffer length is shifted in word */
+ hw->ix_ne[0].len = htobe32(segs[0].ds_len << 16);
+ hw->ix_ne[0].next = 0;
+ bus_dmamap_sync(dma->buf_tag, dma->buf_map,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+ npe->ix_m = m;
+ /* Flush the memory in the mbuf */
+ bus_dmamap_sync(dma->mtag, npe->ix_map, BUS_DMASYNC_PREREAD);
+ return 0;
+}
+
+/*
+ * RX q processing for a specific NPE. Claim entries
+ * from the hardware queue and pass the frames up the
+ * stack. Pass the rx buffers to the free list.
+ */
+static int
+npe_rxdone(int qid, void *arg)
+{
+#define P2V(a, dma) \
+ &(dma)->buf[((a) - (dma)->buf_phys) / sizeof(struct npehwbuf)]
+ struct npe_softc *sc = arg;
+ struct npedma *dma = &sc->rxdma;
+ uint32_t entry;
+ int rx_npkts = 0;
+
+ while (ixpqmgr_qread(qid, &entry) == 0) {
+ struct npebuf *npe = P2V(NPE_QM_Q_ADDR(entry), dma);
+ struct mbuf *m;
+
+ bus_dmamap_sync(dma->buf_tag, dma->buf_map,
+ BUS_DMASYNC_POSTREAD);
+ DPRINTF(sc, "%s: entry 0x%x neaddr 0x%x ne_len 0x%x\n",
+ __func__, entry, npe->ix_neaddr, npe->ix_hw->ix_ne[0].len);
+ /*
+ * Allocate a new mbuf to replenish the rx buffer.
+ * If doing so fails we drop the rx'd frame so we
+ * can reuse the previous mbuf. When we're able to
+ * allocate a new mbuf dispatch the mbuf w/ rx'd
+ * data up the stack and replace it with the newly
+ * allocated one.
+ */
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (m != NULL) {
+ struct mbuf *mrx = npe->ix_m;
+ struct npehwbuf *hw = npe->ix_hw;
+ struct ifnet *ifp = sc->sc_ifp;
+
+ /* Flush mbuf memory for rx'd data */
+ bus_dmamap_sync(dma->mtag, npe->ix_map,
+ BUS_DMASYNC_POSTREAD);
+
+ /* set m_len etc. per rx frame size */
+ mrx->m_len = be32toh(hw->ix_ne[0].len) & 0xffff;
+ mrx->m_pkthdr.len = mrx->m_len;
+ mrx->m_pkthdr.rcvif = ifp;
+
+ ifp->if_ipackets++;
+ ifp->if_input(ifp, mrx);
+ rx_npkts++;
+ } else {
+ /* discard frame and re-use mbuf */
+ m = npe->ix_m;
+ }
+ if (npe_rxbuf_init(sc, npe, m) == 0) {
+ /* return npe buf to rx free list */
+ ixpqmgr_qwrite(sc->rx_freeqid, npe->ix_neaddr);
+ } else {
+ /* XXX should not happen */
+ }
+ }
+ return rx_npkts;
+#undef P2V
+}
+
+#ifdef DEVICE_POLLING
+static int
+npe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+ struct npe_softc *sc = ifp->if_softc;
+ int rx_npkts = 0;
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ rx_npkts = npe_rxdone(sc->rx_qid, sc);
+ npe_txdone(sc->tx_doneqid, sc); /* XXX polls both NPE's */
+ }
+ return rx_npkts;
+}
+#endif /* DEVICE_POLLING */
+
+static void
+npe_startxmit(struct npe_softc *sc)
+{
+ struct npedma *dma = &sc->txdma;
+ int i;
+
+ NPE_ASSERT_LOCKED(sc);
+ sc->tx_free = NULL;
+ for (i = 0; i < dma->nbuf; i++) {
+ struct npebuf *npe = &dma->buf[i];
+ if (npe->ix_m != NULL) {
+ /* NB: should not happen */
+ device_printf(sc->sc_dev,
+ "%s: free mbuf at entry %u\n", __func__, i);
+ m_freem(npe->ix_m);
+ }
+ npe->ix_m = NULL;
+ npe->ix_next = sc->tx_free;
+ sc->tx_free = npe;
+ }
+}
+
+static void
+npe_startrecv(struct npe_softc *sc)
+{
+ struct npedma *dma = &sc->rxdma;
+ struct npebuf *npe;
+ int i;
+
+ NPE_ASSERT_LOCKED(sc);
+ for (i = 0; i < dma->nbuf; i++) {
+ npe = &dma->buf[i];
+ npe_rxbuf_init(sc, npe, npe->ix_m);
+ /* set npe buf on rx free list */
+ ixpqmgr_qwrite(sc->rx_freeqid, npe->ix_neaddr);
+ }
+}
+
+/*
+ * Reset and initialize the chip
+ */
+static void
+npeinit_locked(void *xsc)
+{
+ struct npe_softc *sc = xsc;
+ struct ifnet *ifp = sc->sc_ifp;
+
+ NPE_ASSERT_LOCKED(sc);
+if (ifp->if_drv_flags & IFF_DRV_RUNNING) return;/*XXX*/
+
+ /*
+ * Reset MAC core.
+ */
+ npe_mac_reset(sc);
+
+ /* disable transmitter and reciver in the MAC */
+ WR4(sc, NPE_MAC_RX_CNTRL1,
+ RD4(sc, NPE_MAC_RX_CNTRL1) &~ NPE_RX_CNTRL1_RX_EN);
+ WR4(sc, NPE_MAC_TX_CNTRL1,
+ RD4(sc, NPE_MAC_TX_CNTRL1) &~ NPE_TX_CNTRL1_TX_EN);
+
+ /*
+ * Set the MAC core registers.
+ */
+ WR4(sc, NPE_MAC_INT_CLK_THRESH, 0x1); /* clock ratio: for ipx4xx */
+ WR4(sc, NPE_MAC_TX_CNTRL2, 0xf); /* max retries */
+ WR4(sc, NPE_MAC_RANDOM_SEED, 0x8); /* LFSR back-off seed */
+ /* thresholds determined by NPE firmware FS */
+ WR4(sc, NPE_MAC_THRESH_P_EMPTY, 0x12);
+ WR4(sc, NPE_MAC_THRESH_P_FULL, 0x30);
+ WR4(sc, NPE_MAC_BUF_SIZE_TX, 0x8); /* tx fifo threshold (bytes) */
+ WR4(sc, NPE_MAC_TX_DEFER, 0x15); /* for single deferral */
+ WR4(sc, NPE_MAC_RX_DEFER, 0x16); /* deferral on inter-frame gap*/
+ WR4(sc, NPE_MAC_TX_TWO_DEFER_1, 0x8); /* for 2-part deferral */
+ WR4(sc, NPE_MAC_TX_TWO_DEFER_2, 0x7); /* for 2-part deferral */
+ WR4(sc, NPE_MAC_SLOT_TIME, 0x80); /* assumes MII mode */
+
+ WR4(sc, NPE_MAC_TX_CNTRL1,
+ NPE_TX_CNTRL1_RETRY /* retry failed xmits */
+ | NPE_TX_CNTRL1_FCS_EN /* append FCS */
+ | NPE_TX_CNTRL1_2DEFER /* 2-part deferal */
+ | NPE_TX_CNTRL1_PAD_EN); /* pad runt frames */
+ /* XXX pad strip? */
+ /* ena pause frame handling */
+ WR4(sc, NPE_MAC_RX_CNTRL1, NPE_RX_CNTRL1_PAUSE_EN);
+ WR4(sc, NPE_MAC_RX_CNTRL2, 0);
+
+ npe_setmac(sc, IF_LLADDR(ifp));
+ npe_setportaddress(sc, IF_LLADDR(ifp));
+ npe_setmcast(sc);
+
+ npe_startxmit(sc);
+ npe_startrecv(sc);
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ sc->npe_watchdog_timer = 0; /* just in case */
+
+ /* enable transmitter and reciver in the MAC */
+ WR4(sc, NPE_MAC_RX_CNTRL1,
+ RD4(sc, NPE_MAC_RX_CNTRL1) | NPE_RX_CNTRL1_RX_EN);
+ WR4(sc, NPE_MAC_TX_CNTRL1,
+ RD4(sc, NPE_MAC_TX_CNTRL1) | NPE_TX_CNTRL1_TX_EN);
+
+ callout_reset(&sc->tick_ch, sc->sc_tickinterval * hz, npe_tick, sc);
+}
+
+static void
+npeinit(void *xsc)
+{
+ struct npe_softc *sc = xsc;
+ NPE_LOCK(sc);
+ npeinit_locked(sc);
+ NPE_UNLOCK(sc);
+}
+
+/*
+ * Dequeue packets and place on the h/w transmit queue.
+ */
+static void
+npestart_locked(struct ifnet *ifp)
+{
+ struct npe_softc *sc = ifp->if_softc;
+ struct npebuf *npe;
+ struct npehwbuf *hw;
+ struct mbuf *m, *n;
+ struct npedma *dma = &sc->txdma;
+ bus_dma_segment_t segs[NPE_MAXSEG];
+ int nseg, len, error, i;
+ uint32_t next;
+
+ NPE_ASSERT_LOCKED(sc);
+ /* XXX can this happen? */
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
+ return;
+
+ while (sc->tx_free != NULL) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL) {
+ /* XXX? */
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ return;
+ }
+ npe = sc->tx_free;
+ bus_dmamap_unload(dma->mtag, npe->ix_map);
+ error = bus_dmamap_load_mbuf_sg(dma->mtag, npe->ix_map,
+ m, segs, &nseg, 0);
+ if (error == EFBIG) {
+ n = m_collapse(m, M_NOWAIT, NPE_MAXSEG);
+ if (n == NULL) {
+ if_printf(ifp, "%s: too many fragments %u\n",
+ __func__, nseg);
+ m_freem(m);
+ return; /* XXX? */
+ }
+ m = n;
+ error = bus_dmamap_load_mbuf_sg(dma->mtag, npe->ix_map,
+ m, segs, &nseg, 0);
+ }
+ if (error != 0 || nseg == 0) {
+ if_printf(ifp, "%s: error %u nseg %u\n",
+ __func__, error, nseg);
+ m_freem(m);
+ return; /* XXX? */
+ }
+ sc->tx_free = npe->ix_next;
+
+ bus_dmamap_sync(dma->mtag, npe->ix_map, BUS_DMASYNC_PREWRITE);
+
+ /*
+ * Tap off here if there is a bpf listener.
+ */
+ BPF_MTAP(ifp, m);
+
+ npe->ix_m = m;
+ hw = npe->ix_hw;
+ len = m->m_pkthdr.len;
+ next = npe->ix_neaddr + sizeof(hw->ix_ne[0]);
+ for (i = 0; i < nseg; i++) {
+ hw->ix_ne[i].data = htobe32(segs[i].ds_addr);
+ hw->ix_ne[i].len = htobe32((segs[i].ds_len<<16) | len);
+ hw->ix_ne[i].next = htobe32(next);
+
+ len = 0; /* zero for segments > 1 */
+ next += sizeof(hw->ix_ne[0]);
+ }
+ hw->ix_ne[i-1].next = 0; /* zero last in chain */
+ bus_dmamap_sync(dma->buf_tag, dma->buf_map,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+
+ DPRINTF(sc, "%s: qwrite(%u, 0x%x) ne_data %x ne_len 0x%x\n",
+ __func__, sc->tx_qid, npe->ix_neaddr,
+ hw->ix_ne[0].data, hw->ix_ne[0].len);
+ /* stick it on the tx q */
+ /* XXX add vlan priority */
+ ixpqmgr_qwrite(sc->tx_qid, npe->ix_neaddr);
+
+ sc->npe_watchdog_timer = 5;
+ }
+ if (sc->tx_free == NULL)
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+}
+
+void
+npestart(struct ifnet *ifp)
+{
+ struct npe_softc *sc = ifp->if_softc;
+ NPE_LOCK(sc);
+ npestart_locked(ifp);
+ NPE_UNLOCK(sc);
+}
+
+static void
+npe_stopxmit(struct npe_softc *sc)
+{
+ struct npedma *dma = &sc->txdma;
+ int i;
+
+ NPE_ASSERT_LOCKED(sc);
+
+ /* XXX qmgr */
+ for (i = 0; i < dma->nbuf; i++) {
+ struct npebuf *npe = &dma->buf[i];
+
+ if (npe->ix_m != NULL) {
+ bus_dmamap_unload(dma->mtag, npe->ix_map);
+ m_freem(npe->ix_m);
+ npe->ix_m = NULL;
+ }
+ }
+}
+
+static void
+npe_stoprecv(struct npe_softc *sc)
+{
+ struct npedma *dma = &sc->rxdma;
+ int i;
+
+ NPE_ASSERT_LOCKED(sc);
+
+ /* XXX qmgr */
+ for (i = 0; i < dma->nbuf; i++) {
+ struct npebuf *npe = &dma->buf[i];
+
+ if (npe->ix_m != NULL) {
+ bus_dmamap_unload(dma->mtag, npe->ix_map);
+ m_freem(npe->ix_m);
+ npe->ix_m = NULL;
+ }
+ }
+}
+
+/*
+ * Turn off interrupts, and stop the nic.
+ */
+void
+npestop(struct npe_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+
+ /* disable transmitter and reciver in the MAC */
+ WR4(sc, NPE_MAC_RX_CNTRL1,
+ RD4(sc, NPE_MAC_RX_CNTRL1) &~ NPE_RX_CNTRL1_RX_EN);
+ WR4(sc, NPE_MAC_TX_CNTRL1,
+ RD4(sc, NPE_MAC_TX_CNTRL1) &~ NPE_TX_CNTRL1_TX_EN);
+
+ sc->npe_watchdog_timer = 0;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+
+ callout_stop(&sc->tick_ch);
+
+ npe_stopxmit(sc);
+ npe_stoprecv(sc);
+ /* XXX go into loopback & drain q's? */
+ /* XXX but beware of disabling tx above */
+
+ /*
+ * The MAC core rx/tx disable may leave the MAC hardware in an
+ * unpredictable state. A hw reset is executed before resetting
+ * all the MAC parameters to a known value.
+ */
+ WR4(sc, NPE_MAC_CORE_CNTRL, NPE_CORE_RESET);
+ DELAY(NPE_MAC_RESET_DELAY);
+ WR4(sc, NPE_MAC_INT_CLK_THRESH, NPE_MAC_INT_CLK_THRESH_DEFAULT);
+ WR4(sc, NPE_MAC_CORE_CNTRL, NPE_CORE_MDC_EN);
+}
+
+void
+npewatchdog(struct npe_softc *sc)
+{
+ NPE_ASSERT_LOCKED(sc);
+
+ if (sc->npe_watchdog_timer == 0 || --sc->npe_watchdog_timer != 0)
+ return;
+
+ device_printf(sc->sc_dev, "watchdog timeout\n");
+ sc->sc_ifp->if_oerrors++;
+
+ npeinit_locked(sc);
+}
+
+static int
+npeioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct npe_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int error = 0;
+#ifdef DEVICE_POLLING
+ int mask;
+#endif
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ NPE_LOCK(sc);
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ npestop(sc);
+ } else {
+ /* reinitialize card on any parameter change */
+ npeinit_locked(sc);
+ }
+ NPE_UNLOCK(sc);
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ /* update multicast filter list. */
+ NPE_LOCK(sc);
+ npe_setmcast(sc);
+ NPE_UNLOCK(sc);
+ error = 0;
+ break;
+
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ mii = device_get_softc(sc->sc_mii);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ break;
+
+#ifdef DEVICE_POLLING
+ case SIOCSIFCAP:
+ mask = ifp->if_capenable ^ ifr->ifr_reqcap;
+ if (mask & IFCAP_POLLING) {
+ if (ifr->ifr_reqcap & IFCAP_POLLING) {
+ error = ether_poll_register(npe_poll, ifp);
+ if (error)
+ return error;
+ NPE_LOCK(sc);
+ /* disable callbacks XXX txdone is shared */
+ ixpqmgr_notify_disable(sc->rx_qid);
+ ixpqmgr_notify_disable(sc->tx_doneqid);
+ ifp->if_capenable |= IFCAP_POLLING;
+ NPE_UNLOCK(sc);
+ } else {
+ error = ether_poll_deregister(ifp);
+ /* NB: always enable qmgr callbacks */
+ NPE_LOCK(sc);
+ /* enable qmgr callbacks */
+ ixpqmgr_notify_enable(sc->rx_qid,
+ IX_QMGR_Q_SOURCE_ID_NOT_E);
+ ixpqmgr_notify_enable(sc->tx_doneqid,
+ IX_QMGR_Q_SOURCE_ID_NOT_E);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ NPE_UNLOCK(sc);
+ }
+ }
+ break;
+#endif
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ }
+ return error;
+}
+
+/*
+ * Setup a traffic class -> rx queue mapping.
+ */
+static int
+npe_setrxqosentry(struct npe_softc *sc, int classix, int trafclass, int qid)
+{
+ uint32_t msg[2];
+
+ msg[0] = (NPE_SETRXQOSENTRY << 24) | (sc->sc_npeid << 20) | classix;
+ msg[1] = (trafclass << 24) | (1 << 23) | (qid << 16) | (qid << 4);
+ return ixpnpe_sendandrecvmsg_sync(sc->sc_npe, msg, msg);
+}
+
+static int
+npe_setportaddress(struct npe_softc *sc, const uint8_t mac[ETHER_ADDR_LEN])
+{
+ uint32_t msg[2];
+
+ msg[0] = (NPE_SETPORTADDRESS << 24)
+ | (sc->sc_npeid << 20)
+ | (mac[0] << 8)
+ | (mac[1] << 0);
+ msg[1] = (mac[2] << 24)
+ | (mac[3] << 16)
+ | (mac[4] << 8)
+ | (mac[5] << 0);
+ return ixpnpe_sendandrecvmsg_sync(sc->sc_npe, msg, msg);
+}
+
+static int
+npe_setfirewallmode(struct npe_softc *sc, int onoff)
+{
+ uint32_t msg[2];
+
+ /* XXX honor onoff */
+ msg[0] = (NPE_SETFIREWALLMODE << 24) | (sc->sc_npeid << 20);
+ msg[1] = 0;
+ return ixpnpe_sendandrecvmsg_sync(sc->sc_npe, msg, msg);
+}
+
+/*
+ * Update and reset the statistics in the NPE.
+ */
+static int
+npe_updatestats(struct npe_softc *sc)
+{
+ uint32_t msg[2];
+
+ msg[0] = NPE_RESETSTATS << NPE_MAC_MSGID_SHL;
+ msg[1] = sc->sc_stats_phys; /* physical address of stat block */
+ return ixpnpe_sendmsg_async(sc->sc_npe, msg);
+}
+
+#if 0
+/*
+ * Get the current statistics block.
+ */
+static int
+npe_getstats(struct npe_softc *sc)
+{
+ uint32_t msg[2];
+
+ msg[0] = NPE_GETSTATS << NPE_MAC_MSGID_SHL;
+ msg[1] = sc->sc_stats_phys; /* physical address of stat block */
+ return ixpnpe_sendandrecvmsg(sc->sc_npe, msg, msg);
+}
+
+/*
+ * Query the image id of the loaded firmware.
+ */
+static uint32_t
+npe_getimageid(struct npe_softc *sc)
+{
+ uint32_t msg[2];
+
+ msg[0] = NPE_GETSTATUS << NPE_MAC_MSGID_SHL;
+ msg[1] = 0;
+ return ixpnpe_sendandrecvmsg_sync(sc->sc_npe, msg, msg) == 0 ? msg[1] : 0;
+}
+
+/*
+ * Enable/disable loopback.
+ */
+static int
+npe_setloopback(struct npe_softc *sc, int ena)
+{
+ uint32_t msg[2];
+
+ msg[0] = (NPE_SETLOOPBACK << NPE_MAC_MSGID_SHL) | (ena != 0);
+ msg[1] = 0;
+ return ixpnpe_sendandrecvmsg_sync(sc->sc_npe, msg, msg);
+}
+#endif
+
+static void
+npe_child_detached(device_t dev, device_t child)
+{
+ struct npe_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (child == sc->sc_mii)
+ sc->sc_mii = NULL;
+}
+
+/*
+ * MII bus support routines.
+ */
+#define MII_RD4(sc, reg) bus_space_read_4(sc->sc_iot, sc->sc_miih, reg)
+#define MII_WR4(sc, reg, v) \
+ bus_space_write_4(sc->sc_iot, sc->sc_miih, reg, v)
+
+static uint32_t
+npe_mii_mdio_read(struct npe_softc *sc, int reg)
+{
+ uint32_t v;
+
+ /* NB: registers are known to be sequential */
+ v = (MII_RD4(sc, reg+0) & 0xff) << 0;
+ v |= (MII_RD4(sc, reg+4) & 0xff) << 8;
+ v |= (MII_RD4(sc, reg+8) & 0xff) << 16;
+ v |= (MII_RD4(sc, reg+12) & 0xff) << 24;
+ return v;
+}
+
+static void
+npe_mii_mdio_write(struct npe_softc *sc, int reg, uint32_t cmd)
+{
+ /* NB: registers are known to be sequential */
+ MII_WR4(sc, reg+0, cmd & 0xff);
+ MII_WR4(sc, reg+4, (cmd >> 8) & 0xff);
+ MII_WR4(sc, reg+8, (cmd >> 16) & 0xff);
+ MII_WR4(sc, reg+12, (cmd >> 24) & 0xff);
+}
+
+static int
+npe_mii_mdio_wait(struct npe_softc *sc)
+{
+ uint32_t v;
+ int i;
+
+ /* NB: typically this takes 25-30 trips */
+ for (i = 0; i < 1000; i++) {
+ v = npe_mii_mdio_read(sc, NPE_MAC_MDIO_CMD);
+ if ((v & NPE_MII_GO) == 0)
+ return 1;
+ DELAY(1);
+ }
+ device_printf(sc->sc_dev, "%s: timeout after ~1ms, cmd 0x%x\n",
+ __func__, v);
+ return 0; /* NB: timeout */
+}
+
+static int
+npe_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct npe_softc *sc = device_get_softc(dev);
+ uint32_t v;
+
+ v = (phy << NPE_MII_ADDR_SHL) | (reg << NPE_MII_REG_SHL) | NPE_MII_GO;
+ npe_mii_mdio_write(sc, NPE_MAC_MDIO_CMD, v);
+ if (npe_mii_mdio_wait(sc))
+ v = npe_mii_mdio_read(sc, NPE_MAC_MDIO_STS);
+ else
+ v = 0xffff | NPE_MII_READ_FAIL;
+ return (v & NPE_MII_READ_FAIL) ? 0xffff : (v & 0xffff);
+}
+
+static int
+npe_miibus_writereg(device_t dev, int phy, int reg, int data)
+{
+ struct npe_softc *sc = device_get_softc(dev);
+ uint32_t v;
+
+ v = (phy << NPE_MII_ADDR_SHL) | (reg << NPE_MII_REG_SHL)
+ | data | NPE_MII_WRITE
+ | NPE_MII_GO;
+ npe_mii_mdio_write(sc, NPE_MAC_MDIO_CMD, v);
+ /* XXX complain about timeout */
+ (void) npe_mii_mdio_wait(sc);
+ return (0);
+}
+
+static void
+npe_miibus_statchg(device_t dev)
+{
+ struct npe_softc *sc = device_get_softc(dev);
+ struct mii_data *mii = device_get_softc(sc->sc_mii);
+ uint32_t tx1, rx1;
+
+ /* sync MAC duplex state */
+ tx1 = RD4(sc, NPE_MAC_TX_CNTRL1);
+ rx1 = RD4(sc, NPE_MAC_RX_CNTRL1);
+ if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
+ tx1 &= ~NPE_TX_CNTRL1_DUPLEX;
+ rx1 |= NPE_RX_CNTRL1_PAUSE_EN;
+ } else {
+ tx1 |= NPE_TX_CNTRL1_DUPLEX;
+ rx1 &= ~NPE_RX_CNTRL1_PAUSE_EN;
+ }
+ WR4(sc, NPE_MAC_RX_CNTRL1, rx1);
+ WR4(sc, NPE_MAC_TX_CNTRL1, tx1);
+}
+
+static device_method_t npe_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, npe_probe),
+ DEVMETHOD(device_attach, npe_attach),
+ DEVMETHOD(device_detach, npe_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_child_detached, npe_child_detached),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, npe_miibus_readreg),
+ DEVMETHOD(miibus_writereg, npe_miibus_writereg),
+ DEVMETHOD(miibus_statchg, npe_miibus_statchg),
+
+ { 0, 0 }
+};
+
+static driver_t npe_driver = {
+ "npe",
+ npe_methods,
+ sizeof(struct npe_softc),
+};
+
+DRIVER_MODULE(npe, ixp, npe_driver, npe_devclass, 0, 0);
+DRIVER_MODULE(miibus, npe, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(npe, ixpqmgr, 1, 1, 1);
+MODULE_DEPEND(npe, miibus, 1, 1, 1);
+MODULE_DEPEND(npe, ether, 1, 1, 1);
Property changes on: trunk/sys/arm/xscale/ixp425/if_npe.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/if_npereg.h
===================================================================
--- trunk/sys/arm/xscale/ixp425/if_npereg.h (rev 0)
+++ trunk/sys/arm/xscale/ixp425/if_npereg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,282 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/ixp425/if_npereg.h 236987 2012-06-13 04:38:09Z imp $
+ */
+
+/*
+ * Copyright (c) 2001-2005, Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ARM_XSCALE_IF_NPEREG_H
+#define ARM_XSCALE_IF_NPEREG_H
+
+/*
+ * NPE/NPE tx/rx descriptor format. This is just the area
+ * shared with ucode running in the NPE; the driver-specific
+ * state is defined in the driver. The shared area must be
+ * cacheline-aligned. We allocate NPE_MAXSEG "descriptors"
+ * per buffer; this allows us to do minimal s/g. The number
+ * of descriptors can be expanded but doing so uses memory
+ * so should be done with care.
+ *
+ * The driver sets up buffers in uncached memory.
+ */
+#define NPE_MAXSEG 3 /* empirically selected */
+
+struct npehwbuf {
+ struct { /* NPE shared area, cacheline aligned */
+ uint32_t next; /* phys addr of next segment */
+ uint32_t len; /* buffer/segment length (bytes) */
+ uint32_t data; /* phys addr of data segment */
+ uint32_t pad[5]; /* pad to cacheline */
+ } ix_ne[NPE_MAXSEG];
+};
+
+#define NPE_FRAME_SIZE_DEFAULT 1536
+#define NPE_FRAME_SIZE_MAX (65536-64)
+#define NPE_FRAME_SIZE_MIN 64
+
+/*
+ * Queue Manager-related definitions.
+ *
+ * These define the layout of 32-bit Q entries passed
+ * between the host cpu and the NPE's.
+ */
+#define NPE_QM_Q_NPE(e) (((e)>>0)&0x3) /* NPE ID */
+#define NPE_QM_Q_PORT(e) (((e)>>3)&0x1) /* Port ID */
+#define NPE_QM_Q_PRIO(e) (((e)>>0)&0x3) /* 802.1d priority */
+#define NPE_QM_Q_ADDR(e) ((e)&0xfffffffe0) /* phys address */
+
+/*
+ * Host->NPE requests written to the shared mailbox.
+ * The NPE writes the same value back as an ACK.
+ */
+#define NPE_GETSTATUS 0x00 /* get firmware revision */
+#define NPE_SETPORTADDRESS 0x01 /* set port id and mac address */
+#define NPE_GETMACADDRDB 0x02 /* upload filter database */
+#define NPE_SETMACADDRDB 0x03 /* download filter database */
+#define NPE_GETSTATS 0x04 /* get statistics */
+#define NPE_RESETSTATS 0x05 /* reset stats + return result */
+#define NPE_SETMAXFRAME 0x06 /* configure max tx/rx frame lengths */
+#define NPE_SETRXTAGMODE 0x07 /* configure VLAN rx operating mode */
+#define NPE_SETDEFRXVID 0x08 /* set def VLAN tag + traffic class */
+#define NPE_SETRXQOSENTRY 0x0b /* map user pri -> QoS class+rx qid */
+#define NPE_SETFIREWALLMODE 0x0e /* config firewall services */
+#define NPE_SETLOOPBACK 0x12 /* enable/disable loopback */
+/* ... XXX more */
+
+#define NPE_MAC_MSGID_SHL 24
+#define NPE_MAC_PORTID_SHL 16
+
+/*
+ * MAC register definitions; see section
+ * 15.2 of the Intel Developers Manual.
+ */
+#define NPE_MAC_TX_CNTRL1 0x000
+#define NPE_MAC_TX_CNTRL2 0x004
+#define NPE_MAC_RX_CNTRL1 0x010
+#define NPE_MAC_RX_CNTRL2 0x014
+#define NPE_MAC_RANDOM_SEED 0x020
+#define NPE_MAC_THRESH_P_EMPTY 0x030
+#define NPE_MAC_THRESH_P_FULL 0x038
+#define NPE_MAC_BUF_SIZE_TX 0x040
+#define NPE_MAC_TX_DEFER 0x050
+#define NPE_MAC_RX_DEFER 0x054
+#define NPE_MAC_TX_TWO_DEFER_1 0x060
+#define NPE_MAC_TX_TWO_DEFER_2 0x064
+#define NPE_MAC_SLOT_TIME 0x070
+#define NPE_MAC_MDIO_CMD_1 0x080
+#define NPE_MAC_MDIO_CMD_2 0x084
+#define NPE_MAC_MDIO_CMD_3 0x088
+#define NPE_MAC_MDIO_CMD_4 0x08c
+#define NPE_MAC_MDIO_STS_1 0x090
+#define NPE_MAC_MDIO_STS_2 0x094
+#define NPE_MAC_MDIO_STS_3 0x098
+#define NPE_MAC_MDIO_STS_4 0x09c
+#define NPE_MAC_ADDR_MASK_1 0x0A0
+#define NPE_MAC_ADDR_MASK_2 0x0A4
+#define NPE_MAC_ADDR_MASK_3 0x0A8
+#define NPE_MAC_ADDR_MASK_4 0x0AC
+#define NPE_MAC_ADDR_MASK_5 0x0B0
+#define NPE_MAC_ADDR_MASK_6 0x0B4
+#define NPE_MAC_ADDR_1 0x0C0
+#define NPE_MAC_ADDR_2 0x0C4
+#define NPE_MAC_ADDR_3 0x0C8
+#define NPE_MAC_ADDR_4 0x0CC
+#define NPE_MAC_ADDR_5 0x0D0
+#define NPE_MAC_ADDR_6 0x0D4
+#define NPE_MAC_INT_CLK_THRESH 0x0E0
+#define NPE_MAC_UNI_ADDR_1 0x0F0
+#define NPE_MAC_UNI_ADDR_2 0x0F4
+#define NPE_MAC_UNI_ADDR_3 0x0F8
+#define NPE_MAC_UNI_ADDR_4 0x0FC
+#define NPE_MAC_UNI_ADDR_5 0x100
+#define NPE_MAC_UNI_ADDR_6 0x104
+#define NPE_MAC_CORE_CNTRL 0x1FC
+
+#define NPE_MAC_ADDR_MASK(i) (NPE_MAC_ADDR_MASK_1 + ((i)<<2))
+#define NPE_MAC_ADDR(i) (NPE_MAC_ADDR_1 + ((i)<<2))
+#define NPE_MAC_UNI_ADDR(i) (NPE_MAC_UNI_ADDR_1 + ((i)<<2))
+
+/*
+ * Bit definitions
+ */
+
+/* TX Control Register 1*/
+#define NPE_TX_CNTRL1_TX_EN 0x01 /* enable TX engine */
+#define NPE_TX_CNTRL1_DUPLEX 0x02 /* select half duplex */
+#define NPE_TX_CNTRL1_RETRY 0x04 /* auto-retry on collision */
+#define NPE_TX_CNTRL1_PAD_EN 0x08 /* pad frames <64 bytes */
+#define NPE_TX_CNTRL1_FCS_EN 0x10 /* append FCS */
+#define NPE_TX_CNTRL1_2DEFER 0x20 /* select 2-part deferral */
+#define NPE_TX_CNTRL1_RMII 0x40
+
+/* TX Control Register 2 */
+#define NPE_TX_CNTRL2_RETRIES_MASK 0xf /* max retry count */
+
+/* RX Control Register 1 */
+#define NPE_RX_CNTRL1_RX_EN 0x01 /* enable RX engine */
+#define NPE_RX_CNTRL1_PADSTRIP_EN 0x02 /* strip frame padding */
+#define NPE_RX_CNTRL1_CRC_EN 0x04 /* include CRC in RX frame */
+#define NPE_RX_CNTRL1_PAUSE_EN 0x08 /* detect Pause frames */
+#define NPE_RX_CNTRL1_LOOP_EN 0x10 /* loopback tx/rx */
+#define NPE_RX_CNTRL1_ADDR_FLTR_EN 0x20 /* enable address filtering */
+#define NPE_RX_CNTRL1_RX_RUNT_EN 0x40 /* enable RX of runt frames */
+#define NPE_RX_CNTRL1_BCAST_DIS 0x80 /* discard broadcast frames */
+
+/* RX Control Register 2 */
+#define NPE_RX_CNTRL2_DEFER_EN 0x01
+
+/* Core Control Register */
+#define NPE_CORE_RESET 0x01 /* MAC reset state */
+#define NPE_CORE_RX_FIFO_FLUSH 0x02 /* flush RX FIFO */
+#define NPE_CORE_TX_FIFO_FLUSH 0x04 /* flush TX FIFO */
+#define NPE_CORE_SEND_JAM 0x08 /* send JAM on packet RX */
+#define NPE_CORE_MDC_EN 0x10 /* IXP42X drives MDC clock */
+
+/*
+ * Stat block returned by NPE with NPE_GETSTATS msg.
+ */
+struct npestats {
+ uint32_t dot3StatsAlignmentErrors;
+ uint32_t dot3StatsFCSErrors;
+ uint32_t dot3StatsInternalMacReceiveErrors;
+ uint32_t RxOverrunDiscards;
+ uint32_t RxLearnedEntryDiscards;
+ uint32_t RxLargeFramesDiscards;
+ uint32_t RxSTPBlockedDiscards;
+ uint32_t RxVLANTypeFilterDiscards;
+ uint32_t RxVLANIdFilterDiscards;
+ uint32_t RxInvalidSourceDiscards;
+ uint32_t RxBlackListDiscards;
+ uint32_t RxWhiteListDiscards;
+ uint32_t RxUnderflowEntryDiscards;
+ uint32_t dot3StatsSingleCollisionFrames;
+ uint32_t dot3StatsMultipleCollisionFrames;
+ uint32_t dot3StatsDeferredTransmissions;
+ uint32_t dot3StatsLateCollisions;
+ uint32_t dot3StatsExcessiveCollisions;
+ uint32_t dot3StatsInternalMacTransmitErrors;
+ uint32_t dot3StatsCarrierSenseErrors;
+ uint32_t TxLargeFrameDiscards;
+ uint32_t TxVLANIdFilterDiscards;
+};
+
+/*
+ * Default values
+ */
+#define NPE_MAC_INT_CLK_THRESH_DEFAULT 0x1
+
+#define NPE_MAC_RESET_DELAY 1
+
+/* This value applies to RMII */
+#define NPE_MAC_SLOT_TIME_RMII_DEFAULT 0xFF
+
+/*
+ * MII definitions - these have been verified against the LXT971 and LXT972 PHYs
+ */
+#define NPE_MII_REG_SHL 16
+#define NPE_MII_ADDR_SHL 21
+
+/* NB: shorthands for mii bus mdio routines */
+#define NPE_MAC_MDIO_CMD NPE_MAC_MDIO_CMD_1
+#define NPE_MAC_MDIO_STS NPE_MAC_MDIO_STS_1
+
+#define NPE_MII_GO (1<<31)
+#define NPE_MII_WRITE (1<<26)
+#define NPE_MII_TIMEOUT_10TH_SECS 5
+#define NPE_MII_10TH_SEC_IN_MILLIS 100
+#define NPE_MII_READ_FAIL (1<<31)
+
+#define NPE_MII_PHY_DEF_DELAY 300 /* max delay before link up, etc. */
+#define NPE_MII_PHY_NO_DELAY 0x0 /* do not delay */
+#define NPE_MII_PHY_NULL 0xff /* PHY is not present */
+#define NPE_MII_PHY_DEF_ADDR 0x0 /* default PHY's logical address */
+
+/* Register definition */
+#define NPE_MII_CTRL_REG 0x0 /* Control Register */
+#define NPE_MII_STAT_REG 0x1 /* Status Register */
+#define NPE_MII_PHY_ID1_REG 0x2 /* PHY identifier 1 Register */
+#define NPE_MII_PHY_ID2_REG 0x3 /* PHY identifier 2 Register */
+#define NPE_MII_AN_ADS_REG 0x4 /* Auto-Negotiation */
+ /* Advertisement Register */
+#define NPE_MII_AN_PRTN_REG 0x5 /* Auto-Negotiation */
+ /* partner ability Register */
+#define NPE_MII_AN_EXP_REG 0x6 /* Auto-Negotiation */
+ /* Expansion Register */
+#define NPE_MII_AN_NEXT_REG 0x7 /* Auto-Negotiation */
+ /* next-page transmit Register */
+#endif /* ARM_XSCALE_IF_NPEREG_H */
Property changes on: trunk/sys/arm/xscale/ixp425/if_npereg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixdp425_pci.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixdp425_pci.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixdp425_pci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,174 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixdp425_pci.c,v 1.5 2005/12/11 12:17:09 christos Exp $ */
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixdp425_pci.c 229125 2011-12-31 15:53:34Z marius $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+#include <arm/xscale/ixp425/ixp425_intr.h>
+#include <arm/xscale/ixp425/ixdp425reg.h>
+
+void
+ixp425_md_attach(device_t dev)
+{
+ struct ixp425_softc *sc = device_get_softc(device_get_parent(dev));
+ struct ixppcib_softc *pci_sc = device_get_softc(dev);
+ uint32_t reg;
+
+
+ /* PCI Reset Assert */
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
+ reg &= ~(1U << GPIO_PCI_RESET);
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
+
+ /* PCI Clock Disable */
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
+ reg &= ~GPCLKR_MUX14;
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
+
+ /*
+ * set GPIO Direction
+ * Output: PCI_CLK, PCI_RESET
+ * Input: PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD
+ */
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER);
+ reg &= ~(1U << GPIO_PCI_CLK);
+ reg &= ~(1U << GPIO_PCI_RESET);
+ reg |= ((1U << GPIO_PCI_INTA) | (1U << GPIO_PCI_INTB) |
+ (1U << GPIO_PCI_INTC) | (1U << GPIO_PCI_INTD));
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER, reg);
+
+ /*
+ * Set GPIO interrupt type
+ * PCI_INT_A, PCI_INTB, PCI_INT_C, PCI_INT_D: Active Low
+ */
+ reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA));
+ reg &= ~GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_MASK);
+ reg |= GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_ACT_LOW);
+ GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA), reg);
+
+ reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB));
+ reg &= ~GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_MASK);
+ reg |= GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_ACT_LOW);
+ GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB), reg);
+
+ reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC));
+ reg &= ~GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_MASK);
+ reg |= GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_ACT_LOW);
+ GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC), reg);
+
+ reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTD));
+ reg &= ~GPIO_TYPE(GPIO_PCI_INTD, GPIO_TYPE_MASK);
+ reg |= GPIO_TYPE(GPIO_PCI_INTD, GPIO_TYPE_ACT_LOW);
+ GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTD), reg);
+
+ /* clear ISR */
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPISR,
+ (1U << GPIO_PCI_INTA) | (1U << GPIO_PCI_INTB) |
+ (1U << GPIO_PCI_INTC) | (1U << GPIO_PCI_INTD));
+
+ /* wait 1ms to satisfy "minimum reset assertion time" of the PCI spec */
+ DELAY(1000);
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg |
+ (0xf << GPCLKR_CLK0DC_SHIFT) | (0xf << GPCLKR_CLK0TC_SHIFT));
+
+ /* PCI Clock Enable */
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
+ reg |= GPCLKR_MUX14;
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg | GPCLKR_MUX14);
+
+ /*
+ * wait 100us to satisfy "minimum reset assertion time from clock stable
+ * requirement of the PCI spec
+ */
+ DELAY(100);
+ /* PCI Reset deassert */
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
+ reg |= 1U << GPIO_PCI_RESET;
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg | (1U << GPIO_PCI_RESET));
+ pci_sc->sc_irq_rman.rm_type = RMAN_ARRAY;
+ pci_sc->sc_irq_rman.rm_descr = "IXP425 PCI IRQs";
+ CTASSERT(PCI_INT_D < PCI_INT_A);
+ /* XXX this overlaps the irq's setup in ixp425_attach */
+ if (rman_init(&pci_sc->sc_irq_rman) != 0 ||
+ rman_manage_region(&pci_sc->sc_irq_rman, PCI_INT_D, PCI_INT_A) != 0)
+ panic("ixp425_md_attach: failed to set up IRQ rman");
+}
+
+#define IXP425_MAX_DEV 5
+#define IXP425_MAX_LINE 4
+
+int
+ixp425_md_route_interrupt(device_t bridge, device_t device, int pin)
+{
+ static int ixp425_pci_table[IXP425_MAX_DEV][IXP425_MAX_LINE] = {
+ {PCI_INT_A, PCI_INT_B, PCI_INT_C, PCI_INT_D},
+ {PCI_INT_B, PCI_INT_C, PCI_INT_D, PCI_INT_A},
+ {PCI_INT_C, PCI_INT_D, PCI_INT_A, PCI_INT_B},
+ {PCI_INT_D, PCI_INT_A, PCI_INT_B, PCI_INT_C},
+ /* NB: for optional USB controller on Gateworks Avila */
+ {PCI_INT_A, PCI_INT_B, PCI_INT_C, PCI_INT_D},
+ };
+ int dev;
+
+ dev = pci_get_slot(device);
+ if (bootverbose)
+ device_printf(bridge, "routing pin %d for %s\n", pin,
+ device_get_nameunit(device));
+ if (pin >= 1 && pin <= IXP425_MAX_LINE &&
+ dev >= 1 && dev <= IXP425_MAX_DEV) {
+ return (ixp425_pci_table[dev - 1][pin - 1]);
+ } else
+ printf("ixppcib: no mapping for %d/%d/%d\n",
+ pci_get_bus(device), dev, pci_get_function(device));
+
+ return (-1);
+}
Property changes on: trunk/sys/arm/xscale/ixp425/ixdp425_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixdp425reg.h
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixdp425reg.h (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixdp425reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,55 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixdp425reg.h,v 1.6 2005/12/11 12:17:09 christos Exp $ */
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $FreeBSD: stable/10/sys/arm/xscale/ixp425/ixdp425reg.h 164763 2006-11-30 06:30:01Z kevlo $ */
+#ifndef _IXDP425REG_H_
+#define _IXDP425REG_H_
+/* GPIOs */
+#define GPIO_PCI_CLK 14
+#define GPIO_PCI_RESET 13
+#define GPIO_PCI_INTA 11
+#define GPIO_PCI_INTB 10
+#define GPIO_PCI_INTC 9
+#define GPIO_PCI_INTD 8
+#define GPIO_I2C_SDA 7
+#define GPIO_I2C_SDA_BIT (1U << GPIO_I2C_SDA)
+#define GPIO_I2C_SCL 6
+#define GPIO_I2C_SCL_BIT (1U << GPIO_I2C_SCL)
+/* Interrupt */
+#define PCI_INT_A IXP425_INT_GPIO_11
+#define PCI_INT_B IXP425_INT_GPIO_10
+#define PCI_INT_C IXP425_INT_GPIO_9
+#define PCI_INT_D IXP425_INT_GPIO_8
+#endif /* _IXDP425REG_H_ */
Property changes on: trunk/sys/arm/xscale/ixp425/ixdp425reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,697 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425.c,v 1.10 2005/12/11 12:16:51 christos Exp $ */
+
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include "opt_ddb.h"
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+#include <arm/xscale/ixp425/ixp425_intr.h>
+
+#include <dev/pci/pcireg.h>
+
+volatile uint32_t intr_enabled;
+uint32_t intr_steer = 0;
+
+/* ixp43x et. al have +32 IRQ's */
+volatile uint32_t intr_enabled2;
+uint32_t intr_steer2 = 0;
+
+struct ixp425_softc *ixp425_softc = NULL;
+
+struct mtx ixp425_gpio_mtx;
+
+static int ixp425_probe(device_t);
+static void ixp425_identify(driver_t *, device_t);
+static int ixp425_attach(device_t);
+
+/*
+ * Return a mask of the "fuse" bits that identify
+ * which h/w features are present.
+ * NB: assumes the expansion bus is mapped.
+ */
+uint32_t
+ixp4xx_read_feature_bits(void)
+{
+ uint32_t bits = ~IXPREG(IXP425_EXP_VBASE + EXP_FCTRL_OFFSET);
+ bits &= ~EXP_FCTRL_RESVD;
+ if (!cpu_is_ixp46x())
+ bits &= ~EXP_FCTRL_IXP46X_ONLY;
+ return bits;
+}
+
+void
+ixp4xx_write_feature_bits(uint32_t v)
+{
+ IXPREG(IXP425_EXP_VBASE + EXP_FCTRL_OFFSET) = ~v;
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+ return (0);
+}
+
+static const uint8_t int2gpio[32] __attribute__ ((aligned(32))) = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#0 -> INT#5 */
+ 0x00, 0x01, /* GPIO#0 -> GPIO#1 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#8 -> INT#13 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#14 -> INT#18 */
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* GPIO#2 -> GPIO#7 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, /* GPIO#8 -> GPIO#12 */
+ 0xff, 0xff /* INT#30 -> INT#31 */
+};
+
+static __inline uint32_t
+ixp425_irq2gpio_bit(int irq)
+{
+ return (1U << int2gpio[irq]);
+}
+
+#ifdef DDB
+#include <ddb/ddb.h>
+
+DB_SHOW_COMMAND(gpio, db_show_gpio)
+{
+ static const char *itype[8] = {
+ [GPIO_TYPE_ACT_HIGH] = "act-high",
+ [GPIO_TYPE_ACT_LOW] = "act-low",
+ [GPIO_TYPE_EDG_RISING] = "edge-rising",
+ [GPIO_TYPE_EDG_FALLING] = "edge-falling",
+ [GPIO_TYPE_TRANSITIONAL]= "transitional",
+ [5] = "type-5", [6] = "type-6", [7] = "type-7"
+ };
+ uint32_t gpoutr = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOUTR);
+ uint32_t gpoer = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOER);
+ uint32_t gpinr = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPINR);
+ uint32_t gpit1r = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPIT1R);
+ uint32_t gpit2r = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPIT2R);
+ int i, j;
+
+ db_printf("GPOUTR %08x GPINR %08x GPOER %08x GPISR %08x\n",
+ gpoutr, gpinr, gpoer,
+ GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPISR));
+ db_printf("GPIT1R %08x GPIT2R %08x GPCLKR %08x\n",
+ gpit1r, gpit2r, GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPCLKR));
+ for (i = 0; i < 16; i++) {
+ db_printf("[%2d] out %u in %u %-3s", i,
+ (gpoutr>>i)&1, (gpinr>>i)&1, (gpoer>>i)&1 ? "in" : "out");
+ for (j = 0; j < 32; j++)
+ if (int2gpio[j] == i) {
+ db_printf(" irq %2u %s", j, itype[
+ (((i & 8) ? gpit2r : gpit1r) >> (3*(i&7)))
+ & 7]);
+ break;
+ }
+ db_printf("\n");
+ }
+}
+#endif
+
+void
+ixp425_set_gpio(struct ixp425_softc *sc, int pin, int type)
+{
+ uint32_t gpiotr = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(pin));
+
+ IXP4XX_GPIO_LOCK();
+ /* clear interrupt type */
+ GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(pin),
+ gpiotr &~ GPIO_TYPE(pin, GPIO_TYPE_MASK));
+ /* clear any pending interrupt */
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPISR, (1<<pin));
+ /* set new interrupt type */
+ GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(pin),
+ gpiotr | GPIO_TYPE(pin, type));
+
+ /* configure gpio line as an input */
+ GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER,
+ GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER) | (1<<pin));
+ IXP4XX_GPIO_UNLOCK();
+}
+
+static __inline void
+ixp425_gpio_ack(int irq)
+{
+ if (irq < 32 && ((1 << irq) & IXP425_INT_GPIOMASK))
+ IXPREG(IXP425_GPIO_VBASE + IXP425_GPIO_GPISR) =
+ ixp425_irq2gpio_bit(irq);
+}
+
+static void
+ixp425_post_filter(void *arg)
+{
+ uintptr_t irq = (uintptr_t) arg;
+ ixp425_gpio_ack(irq);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ int i;
+
+ i = disable_interrupts(PSR_I);
+ if (nb < 32) {
+ intr_enabled &= ~(1 << nb);
+ ixp425_set_intrmask();
+ } else {
+ intr_enabled2 &= ~(1 << (nb - 32));
+ ixp435_set_intrmask();
+ }
+ restore_interrupts(i);
+ /*XXX; If it's a GPIO interrupt, ACK it know. Can it be a problem ?*/
+ ixp425_gpio_ack(nb);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ int i;
+
+ i = disable_interrupts(PSR_I);
+ if (nb < 32) {
+ intr_enabled |= (1 << nb);
+ ixp425_set_intrmask();
+ } else {
+ intr_enabled2 |= (1 << (nb - 32));
+ ixp435_set_intrmask();
+ }
+ restore_interrupts(i);
+}
+
+static __inline uint32_t
+ixp425_irq_read(void)
+{
+ return IXPREG(IXP425_INT_STATUS) & intr_enabled;
+}
+
+static __inline uint32_t
+ixp435_irq_read(void)
+{
+ return IXPREG(IXP435_INT_STATUS2) & intr_enabled2;
+}
+
+int
+arm_get_next_irq(int last)
+{
+ uint32_t mask;
+
+ last += 1; /* always advance fwd, NB: handles -1 */
+ if (last < 32) {
+ mask = ixp425_irq_read() >> last;
+ for (; mask != 0; mask >>= 1, last++) {
+ if (mask & 1)
+ return last;
+ }
+ last = 32;
+ }
+ if (cpu_is_ixp43x()) {
+ mask = ixp435_irq_read() >> (32-last);
+ for (; mask != 0; mask >>= 1, last++) {
+ if (mask & 1)
+ return last;
+ }
+ }
+ return -1;
+}
+
+void
+cpu_reset(void)
+{
+
+ bus_space_write_4(&ixp425_bs_tag, IXP425_TIMER_VBASE,
+ IXP425_OST_WDOG_KEY, OST_WDOG_KEY_MAJICK);
+ bus_space_write_4(&ixp425_bs_tag, IXP425_TIMER_VBASE,
+ IXP425_OST_WDOG, 0);
+ bus_space_write_4(&ixp425_bs_tag, IXP425_TIMER_VBASE,
+ IXP425_OST_WDOG_ENAB, OST_WDOG_ENAB_RST_ENA |
+ OST_WDOG_ENAB_CNT_ENA);
+ printf("Reset failed!\n");
+ for(;;);
+}
+
+static void
+ixp425_identify(driver_t *driver, device_t parent)
+{
+ BUS_ADD_CHILD(parent, 0, "ixp", 0);
+}
+
+static int
+ixp425_probe(device_t dev)
+{
+ device_set_desc(dev, "Intel IXP4XX");
+ return (0);
+}
+
+static int
+ixp425_attach(device_t dev)
+{
+ struct ixp425_softc *sc;
+
+ device_printf(dev, "%b\n", ixp4xx_read_feature_bits(), EXP_FCTRL_BITS);
+
+ sc = device_get_softc(dev);
+ sc->sc_iot = &ixp425_bs_tag;
+ KASSERT(ixp425_softc == NULL, ("%s called twice?", __func__));
+ ixp425_softc = sc;
+
+ intr_enabled = 0;
+ ixp425_set_intrmask();
+ ixp425_set_intrsteer();
+ if (cpu_is_ixp43x()) {
+ intr_enabled2 = 0;
+ ixp435_set_intrmask();
+ ixp435_set_intrsteer();
+ }
+ arm_post_filter = ixp425_post_filter;
+
+ mtx_init(&ixp425_gpio_mtx, "gpio", NULL, MTX_DEF);
+ if (bus_space_map(sc->sc_iot, IXP425_GPIO_HWBASE, IXP425_GPIO_SIZE,
+ 0, &sc->sc_gpio_ioh))
+ panic("%s: unable to map GPIO registers", __func__);
+ if (bus_space_map(sc->sc_iot, IXP425_EXP_HWBASE, IXP425_EXP_SIZE,
+ 0, &sc->sc_exp_ioh))
+ panic("%s: unable to map Expansion Bus registers", __func__);
+
+ /* XXX belongs in platform init */
+ if (cpu_is_ixp43x())
+ cambria_exp_bus_init(sc);
+
+ if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR, NULL, NULL, 0xffffffff, 0xff, 0xffffffff, 0,
+ NULL, NULL, &sc->sc_dmat))
+ panic("%s: failed to create dma tag", __func__);
+
+ sc->sc_irq_rman.rm_type = RMAN_ARRAY;
+ sc->sc_irq_rman.rm_descr = "IXP4XX IRQs";
+ if (rman_init(&sc->sc_irq_rman) != 0 ||
+ rman_manage_region(&sc->sc_irq_rman, 0, cpu_is_ixp43x() ? 63 : 31) != 0)
+ panic("%s: failed to set up IRQ rman", __func__);
+
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "IXP4XX Memory";
+ if (rman_init(&sc->sc_mem_rman) != 0 ||
+ rman_manage_region(&sc->sc_mem_rman, 0, ~0) != 0)
+ panic("%s: failed to set up memory rman", __func__);
+
+ BUS_ADD_CHILD(dev, 0, "pcib", 0);
+ BUS_ADD_CHILD(dev, 0, "ixpclk", 0);
+ BUS_ADD_CHILD(dev, 0, "ixpiic", 0);
+ /* XXX move to hints? */
+ BUS_ADD_CHILD(dev, 0, "ixpwdog", 0);
+
+ /* attach wired devices via hints */
+ bus_enumerate_hinted_children(dev);
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static void
+ixp425_hinted_child(device_t bus, const char *dname, int dunit)
+{
+ device_t child;
+ struct ixp425_ivar *ivar;
+
+ child = BUS_ADD_CHILD(bus, 0, dname, dunit);
+ ivar = IXP425_IVAR(child);
+ resource_int_value(dname, dunit, "addr", &ivar->addr);
+ resource_int_value(dname, dunit, "irq", &ivar->irq);
+}
+
+static device_t
+ixp425_add_child(device_t dev, u_int order, const char *name, int unit)
+{
+ device_t child;
+ struct ixp425_ivar *ivar;
+
+ child = device_add_child_ordered(dev, order, name, unit);
+ if (child == NULL)
+ return NULL;
+ ivar = malloc(sizeof(struct ixp425_ivar), M_DEVBUF, M_NOWAIT);
+ if (ivar == NULL) {
+ device_delete_child(dev, child);
+ return NULL;
+ }
+ ivar->addr = 0;
+ ivar->irq = -1;
+ device_set_ivars(child, ivar);
+ return child;
+}
+
+static int
+ixp425_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
+{
+ struct ixp425_ivar *ivar = IXP425_IVAR(child);
+
+ switch (which) {
+ case IXP425_IVAR_ADDR:
+ if (ivar->addr != 0) {
+ *(uint32_t *)result = ivar->addr;
+ return 0;
+ }
+ break;
+ case IXP425_IVAR_IRQ:
+ if (ivar->irq != -1) {
+ *(int *)result = ivar->irq;
+ return 0;
+ }
+ break;
+ }
+ return EINVAL;
+}
+
+/*
+ * NB: This table handles P->V translations for regions setup with
+ * static mappings in initarm. This is used solely for calls to
+ * bus_alloc_resource_any; anything done with bus_space_map is
+ * handled elsewhere and does not require an entry here.
+ *
+ * XXX this table is also used by uart_cpu_getdev via getvbase
+ * (hence the public api)
+ */
+struct hwvtrans {
+ uint32_t hwbase;
+ uint32_t size;
+ uint32_t vbase;
+ int isa4x; /* XXX needs special bus space tag */
+ int isslow; /* XXX needs special bus space tag */
+};
+
+static const struct hwvtrans *
+gethwvtrans(uint32_t hwbase, uint32_t size)
+{
+ static const struct hwvtrans hwvtrans[] = {
+ /* NB: needed only for uart_cpu_getdev */
+ { .hwbase = IXP425_UART0_HWBASE,
+ .size = IXP425_REG_SIZE,
+ .vbase = IXP425_UART0_VBASE,
+ .isa4x = 1 },
+ { .hwbase = IXP425_UART1_HWBASE,
+ .size = IXP425_REG_SIZE,
+ .vbase = IXP425_UART1_VBASE,
+ .isa4x = 1 },
+ { .hwbase = IXP425_PCI_HWBASE,
+ .size = IXP425_PCI_SIZE,
+ .vbase = IXP425_PCI_VBASE },
+ { .hwbase = IXP425_PCI_MEM_HWBASE,
+ .size = IXP425_PCI_MEM_SIZE,
+ .vbase = IXP425_PCI_MEM_VBASE },
+ { .hwbase = IXP425_EXP_BUS_CS0_HWBASE,
+ .size = IXP425_EXP_BUS_CS0_SIZE,
+ .vbase = IXP425_EXP_BUS_CS0_VBASE },
+ /* NB: needed for ixp435 ehci controllers */
+ { .hwbase = IXP435_USB1_HWBASE,
+ .size = IXP435_USB1_SIZE,
+ .vbase = IXP435_USB1_VBASE },
+ { .hwbase = IXP435_USB2_HWBASE,
+ .size = IXP435_USB2_SIZE,
+ .vbase = IXP435_USB2_VBASE },
+ { .hwbase = CAMBRIA_GPS_HWBASE,
+ .size = CAMBRIA_GPS_SIZE,
+ .vbase = CAMBRIA_GPS_VBASE,
+ .isslow = 1 },
+ { .hwbase = CAMBRIA_RS485_HWBASE,
+ .size = CAMBRIA_RS485_SIZE,
+ .vbase = CAMBRIA_RS485_VBASE,
+ .isslow = 1 },
+ };
+ int i;
+
+ for (i = 0; i < sizeof hwvtrans / sizeof *hwvtrans; i++) {
+ if (hwbase >= hwvtrans[i].hwbase &&
+ hwbase + size <= hwvtrans[i].hwbase + hwvtrans[i].size)
+ return &hwvtrans[i];
+ }
+ return NULL;
+}
+
+/* XXX for uart_cpu_getdev */
+int
+getvbase(uint32_t hwbase, uint32_t size, uint32_t *vbase)
+{
+ const struct hwvtrans *hw;
+
+ hw = gethwvtrans(hwbase, size);
+ if (hw == NULL)
+ return (ENOENT);
+ *vbase = hwbase - hw->hwbase + hw->vbase;
+ return (0);
+}
+
+static struct resource *
+ixp425_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct ixp425_softc *sc = device_get_softc(dev);
+ const struct hwvtrans *vtrans;
+ struct resource *rv;
+ uint32_t addr;
+ int needactivate = flags & RF_ACTIVE;
+ int irq;
+
+ flags &= ~RF_ACTIVE;
+ switch (type) {
+ case SYS_RES_IRQ:
+ /* override per hints */
+ if (BUS_READ_IVAR(dev, child, IXP425_IVAR_IRQ, &irq) == 0)
+ start = end = irq;
+ rv = rman_reserve_resource(&sc->sc_irq_rman, start, end, count,
+ flags, child);
+ if (rv != NULL)
+ rman_set_rid(rv, *rid);
+ break;
+
+ case SYS_RES_MEMORY:
+ /* override per hints */
+ if (BUS_READ_IVAR(dev, child, IXP425_IVAR_ADDR, &addr) == 0) {
+ start = addr;
+ /* XXX use nominal window to check for mapping */
+ vtrans = gethwvtrans(start, 0x1000);
+ if (vtrans != NULL) {
+ /*
+ * Assign the entire mapped region; this may
+ * not be correct but without more info from
+ * the caller we cannot tell.
+ */
+ end = start + vtrans->size -
+ (start - vtrans->hwbase);
+ if (bootverbose)
+ device_printf(child,
+ "%s: assign 0x%lx:0x%lx%s\n",
+ __func__, start, end - start,
+ vtrans->isa4x ? " A4X" :
+ vtrans->isslow ? " SLOW" : "");
+ }
+ } else
+ vtrans = gethwvtrans(start, end - start);
+ if (vtrans == NULL) {
+ /* likely means above table needs to be updated */
+ device_printf(child, "%s: no mapping for 0x%lx:0x%lx\n",
+ __func__, start, end - start);
+ return NULL;
+ }
+ rv = rman_reserve_resource(&sc->sc_mem_rman, start, end,
+ end - start, flags, child);
+ if (rv == NULL) {
+ device_printf(child, "%s: cannot reserve 0x%lx:0x%lx\n",
+ __func__, start, end - start);
+ return NULL;
+ }
+ rman_set_rid(rv, *rid);
+ break;
+ default:
+ rv = NULL;
+ break;
+ }
+ if (rv != NULL && needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+ return (rv);
+}
+
+static int
+ixp425_release_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ /* NB: no private resources, just release */
+ return rman_release_resource(r);
+}
+
+static int
+ixp425_activate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct ixp425_softc *sc = device_get_softc(dev);
+ const struct hwvtrans *vtrans;
+
+ if (type == SYS_RES_MEMORY) {
+ vtrans = gethwvtrans(rman_get_start(r), rman_get_size(r));
+ if (vtrans == NULL) { /* NB: should not happen */
+ device_printf(child, "%s: no mapping for 0x%lx:0x%lx\n",
+ __func__, rman_get_start(r), rman_get_size(r));
+ return (ENOENT);
+ }
+ if (vtrans->isa4x)
+ rman_set_bustag(r, &ixp425_a4x_bs_tag);
+ else if (vtrans->isslow)
+ rman_set_bustag(r, &cambria_exp_bs_tag);
+ else
+ rman_set_bustag(r, sc->sc_iot);
+ rman_set_bushandle(r, vtrans->vbase);
+ }
+ return (rman_activate_resource(r));
+}
+
+static int
+ixp425_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ /* NB: no private resources, just deactive */
+ return (rman_deactivate_resource(r));
+}
+
+static __inline void
+get_masks(struct resource *res, uint32_t *mask, uint32_t *mask2)
+{
+ int i;
+
+ *mask = 0;
+ for (i = rman_get_start(res); i < 32 && i <= rman_get_end(res); i++)
+ *mask |= 1 << i;
+ *mask2 = 0;
+ for (; i <= rman_get_end(res); i++)
+ *mask2 |= 1 << (i - 32);
+}
+
+static __inline void
+update_masks(uint32_t mask, uint32_t mask2)
+{
+
+ intr_enabled = mask;
+ ixp425_set_intrmask();
+ if (cpu_is_ixp43x()) {
+ intr_enabled2 = mask2;
+ ixp435_set_intrmask();
+ }
+}
+
+static int
+ixp425_setup_intr(device_t dev, device_t child,
+ struct resource *res, int flags, driver_filter_t *filt,
+ driver_intr_t *intr, void *arg, void **cookiep)
+{
+ uint32_t mask, mask2;
+ int error;
+
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, res, flags,
+ filt, intr, arg, cookiep);
+ if (error)
+ return (error);
+
+ get_masks(res, &mask, &mask2);
+ update_masks(intr_enabled | mask, intr_enabled2 | mask2);
+
+ return (0);
+}
+
+static int
+ixp425_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ uint32_t mask, mask2;
+
+ get_masks(res, &mask, &mask2);
+ update_masks(intr_enabled &~ mask, intr_enabled2 &~ mask2);
+
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
+static device_method_t ixp425_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ixp425_probe),
+ DEVMETHOD(device_attach, ixp425_attach),
+ DEVMETHOD(device_identify, ixp425_identify),
+
+ /* Bus interface */
+ DEVMETHOD(bus_add_child, ixp425_add_child),
+ DEVMETHOD(bus_hinted_child, ixp425_hinted_child),
+ DEVMETHOD(bus_read_ivar, ixp425_read_ivar),
+
+ DEVMETHOD(bus_alloc_resource, ixp425_alloc_resource),
+ DEVMETHOD(bus_release_resource, ixp425_release_resource),
+ DEVMETHOD(bus_activate_resource, ixp425_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, ixp425_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, ixp425_setup_intr),
+ DEVMETHOD(bus_teardown_intr, ixp425_teardown_intr),
+
+ {0, 0},
+};
+
+static driver_t ixp425_driver = {
+ "ixp",
+ ixp425_methods,
+ sizeof(struct ixp425_softc),
+};
+static devclass_t ixp425_devclass;
+
+DRIVER_MODULE(ixp, nexus, ixp425_driver, ixp425_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_a4x_io.S
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_a4x_io.S (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_a4x_io.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,153 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_a4x_io.S,v 1.2 2005/12/11 12:16:51 christos Exp $ */
+
+/*
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * There are simple bus space functions for IO registers mapped at
+ * 32-bit aligned positions. offset is multiplied by 4.
+ *
+ * Based loosely on pxa2x0_a2x_io.S
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_a4x_io.S 275767 2014-12-14 16:28:53Z andrew $");
+
+/*
+ * bus_space I/O functions with offset*4
+ */
+
+/*
+ * Read single
+ */
+ENTRY(a4x_bs_r_1)
+ ldr r0, [r1, r2, LSL #2]
+ and r0, r0, #0xff
+ mov pc, lr
+END(a4x_bs_r_1)
+
+ENTRY(a4x_bs_r_2)
+ ldr r0, [r1, r2, LSL #2]
+ mov r1, #0xff
+ orr r1, r1, r1, lsl #8
+ and r0, r0, r1
+ mov pc, lr
+END(a4x_bs_r_2)
+
+ENTRY(a4x_bs_r_4)
+ ldr r0, [r1, r2, LSL #2]
+ mov pc, lr
+END(a4x_bs_r_4)
+
+/*
+ * Write single
+ */
+ENTRY(a4x_bs_w_1)
+ and r3, r3, #0xff
+ str r3, [r1, r2, LSL #2]
+ mov pc, lr
+END(a4x_bs_w_1)
+
+ENTRY(a4x_bs_w_2)
+ mov r0, #0xff
+ orr r0, r0, r0, lsl #8
+ and r3, r3, r0
+ str r3, [r1, r2, LSL #2]
+ mov pc, lr
+END(a4x_bs_w_2)
+
+ENTRY(a4x_bs_w_4)
+ str r3, [r1, r2, LSL #2]
+ mov pc, lr
+END(a4x_bs_w_4)
+
+/*
+ * Read multiple
+ */
+ENTRY(a4x_bs_rm_1)
+ add r0, r1, r2, lsl #2
+ ldr r2, [sp, #0]
+ mov r1, r3
+ teq r2, #0
+ moveq pc, lr
+1: ldr r3, [r0]
+ subs r2, r2, #1
+ strb r3, [r1], #1
+ bne 1b
+ mov pc, lr
+END(a4x_bs_rm_1)
+
+ENTRY(a4x_bs_rm_2)
+ add r0, r1, r2, lsl #2
+ ldr r2, [sp, #0]
+ mov r1, r3
+ teq r2, #0
+ moveq pc, lr
+1: ldr r3, [r0]
+ subs r2, r2, #1
+ strh r3, [r1], #2
+ bne 1b
+ mov pc, lr
+END(a4x_bs_rm_2)
+
+/*
+ * Write multiple
+ */
+ENTRY(a4x_bs_wm_1)
+ add r0, r1, r2, lsl #2
+ ldr r2, [sp, #0]
+ mov r1, r3
+ teq r2, #0
+ moveq pc, lr
+1: ldrb r3, [r1], #1
+ subs r2, r2, #1
+ str r3, [r0]
+ bne 1b
+ mov pc, lr
+END(a4x_bs_wm_1)
+
+ENTRY(a4x_bs_wm_2)
+ add r0, r1, r2, lsl #2
+ ldr r2, [sp, #0]
+ mov r1, r3
+ teq r2, #0
+ moveq pc, lr
+1: ldrh r3, [r1], #2
+ subs r2, r2, #1
+ str r3, [r0]
+ bne 1b
+ mov pc, lr
+END(a4x_bs_wm_2)
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_a4x_io.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_a4x_space.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_a4x_space.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_a4x_space.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,115 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_a4x_space.c,v 1.2 2005/12/11 12:16:51 christos Exp $ */
+
+/*
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Bus space tag for 8/16-bit devices on 32-bit bus.
+ * all registers are located at the address of multiple of 4.
+ *
+ * Based on pxa2x0_a4x_space.c
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_a4x_space.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/pcb.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(a4x);
+bs_protos(generic);
+
+struct bus_space ixp425_a4x_bs_tag = {
+ /* cookie */
+ .bs_privdata = (void *) 0,
+
+ /* mapping/unmapping */
+ .bs_map = generic_bs_map,
+ .bs_unmap = generic_bs_unmap,
+ .bs_subregion = generic_bs_subregion,
+
+ /* allocation/deallocation */
+ .bs_alloc = generic_bs_alloc, /* XXX not implemented */
+ .bs_free = generic_bs_free, /* XXX not implemented */
+
+ /* barrier */
+ .bs_barrier = generic_bs_barrier,
+
+ /* read (single) */
+ .bs_r_1 = a4x_bs_r_1,
+ .bs_r_2 = a4x_bs_r_2,
+ .bs_r_4 = a4x_bs_r_4,
+
+ /* read multiple */
+ .bs_rm_1 = a4x_bs_rm_1,
+ .bs_rm_2 = a4x_bs_rm_2,
+
+ /* read region */
+ /* XXX not implemented */
+
+ /* write (single) */
+ .bs_w_1 = a4x_bs_w_1,
+ .bs_w_2 = a4x_bs_w_2,
+ .bs_w_4 = a4x_bs_w_4,
+
+ /* write multiple */
+ .bs_wm_1 = a4x_bs_wm_1,
+ .bs_wm_2 = a4x_bs_wm_2,
+
+ /* write region */
+ /* XXX not implemented */
+
+ /* set multiple */
+ /* XXX not implemented */
+
+ /* set region */
+ /* XXX not implemented */
+
+ /* copy */
+ /* XXX not implemented */
+};
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_a4x_space.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_iic.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_iic.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_iic.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,196 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (c) 2006 Kevin Lo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_iic.c 236987 2012-06-13 04:38:09Z imp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/uio.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+#include <arm/xscale/ixp425/ixdp425reg.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include "iicbb_if.h"
+
+#define I2C_DELAY 10
+
+/* bit clr/set shorthands */
+#define GPIO_CONF_CLR(sc, reg, mask) \
+ GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) &~ (mask))
+#define GPIO_CONF_SET(sc, reg, mask) \
+ GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) | (mask))
+
+struct ixpiic_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_gpio_ioh;
+
+ device_t iicbb;
+};
+
+static struct ixpiic_softc *ixpiic_sc = NULL;
+
+static int
+ixpiic_probe(device_t dev)
+{
+ device_set_desc(dev, "IXP4XX GPIO-Based I2C Interface");
+ return (0);
+}
+
+static int
+ixpiic_attach(device_t dev)
+{
+ struct ixpiic_softc *sc = device_get_softc(dev);
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+
+ ixpiic_sc = sc;
+
+ sc->sc_dev = dev;
+ sc->sc_iot = sa->sc_iot;
+ sc->sc_gpio_ioh = sa->sc_gpio_ioh;
+
+ GPIO_CONF_SET(sc, IXP425_GPIO_GPOER,
+ GPIO_I2C_SCL_BIT | GPIO_I2C_SDA_BIT);
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR,
+ GPIO_I2C_SCL_BIT | GPIO_I2C_SDA_BIT);
+
+ /* add generic bit-banging code */
+ if ((sc->iicbb = device_add_child(dev, "iicbb", -1)) == NULL)
+ device_printf(dev, "could not add iicbb\n");
+
+ /* probe and attach the bit-banging code */
+ device_probe_and_attach(sc->iicbb);
+
+ return (0);
+}
+
+static int
+ixpiic_callback(device_t dev, int index, caddr_t data)
+{
+ return (0);
+}
+
+static int
+ixpiic_getscl(device_t dev)
+{
+ struct ixpiic_softc *sc = ixpiic_sc;
+ uint32_t reg;
+
+ IXP4XX_GPIO_LOCK();
+ GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
+
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
+ IXP4XX_GPIO_UNLOCK();
+ return (reg & GPIO_I2C_SCL_BIT);
+}
+
+static int
+ixpiic_getsda(device_t dev)
+{
+ struct ixpiic_softc *sc = ixpiic_sc;
+ uint32_t reg;
+
+ IXP4XX_GPIO_LOCK();
+ GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+
+ reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
+ IXP4XX_GPIO_UNLOCK();
+ return (reg & GPIO_I2C_SDA_BIT);
+}
+
+static void
+ixpiic_setsda(device_t dev, int val)
+{
+ struct ixpiic_softc *sc = ixpiic_sc;
+
+ IXP4XX_GPIO_LOCK();
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT);
+ if (val)
+ GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+ else
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+ IXP4XX_GPIO_UNLOCK();
+ DELAY(I2C_DELAY);
+}
+
+static void
+ixpiic_setscl(device_t dev, int val)
+{
+ struct ixpiic_softc *sc = ixpiic_sc;
+
+ IXP4XX_GPIO_LOCK();
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT);
+ if (val)
+ GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
+ else
+ GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
+ IXP4XX_GPIO_UNLOCK();
+ DELAY(I2C_DELAY);
+}
+
+static int
+ixpiic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+ /* reset bus */
+ ixpiic_setsda(dev, 1);
+ ixpiic_setscl(dev, 1);
+
+ return (IIC_ENOADDR);
+}
+
+static device_method_t ixpiic_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ixpiic_probe),
+ DEVMETHOD(device_attach, ixpiic_attach),
+
+ /* iicbb interface */
+ DEVMETHOD(iicbb_callback, ixpiic_callback),
+ DEVMETHOD(iicbb_setsda, ixpiic_setsda),
+ DEVMETHOD(iicbb_setscl, ixpiic_setscl),
+ DEVMETHOD(iicbb_getsda, ixpiic_getsda),
+ DEVMETHOD(iicbb_getscl, ixpiic_getscl),
+ DEVMETHOD(iicbb_reset, ixpiic_reset),
+
+ { 0, 0 }
+};
+
+static driver_t ixpiic_driver = {
+ "ixpiic",
+ ixpiic_methods,
+ sizeof(struct ixpiic_softc),
+};
+static devclass_t ixpiic_devclass;
+
+DRIVER_MODULE(ixpiic, ixp, ixpiic_driver, ixpiic_devclass, 0, 0);
+DRIVER_MODULE(iicbb, ixpiic, iicbb_driver, iicbb_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_iic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_intr.h
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_intr.h (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_intr.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,90 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_intr.h,v 1.6 2005/12/24 20:06:52 perry Exp $ */
+
+/*
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_intr.h 186352 2008-12-20 03:26:09Z sam $
+ *
+ */
+
+#ifndef _IXP425_INTR_H_
+#define _IXP425_INTR_H_
+
+#define ARM_IRQ_HANDLER _C_LABEL(ixp425_intr_dispatch)
+
+#ifndef _LOCORE
+
+#include <machine/armreg.h>
+#include <machine/cpufunc.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+
+#define IXPREG(reg) *((__volatile u_int32_t*) (reg))
+
+void ixp425_do_pending(void);
+
+extern __volatile uint32_t intr_enabled;
+extern uint32_t intr_steer;
+
+static __inline void __attribute__((__unused__))
+ixp425_set_intrmask(void)
+{
+ IXPREG(IXP425_INT_ENABLE) = intr_enabled & IXP425_INT_HWMASK;
+}
+
+static __inline void
+ixp425_set_intrsteer(void)
+{
+ IXPREG(IXP425_INT_SELECT) = intr_steer & IXP425_INT_HWMASK;
+}
+
+extern __volatile uint32_t intr_enabled2;
+extern uint32_t intr_steer2;
+
+static __inline void __attribute__((__unused__))
+ixp435_set_intrmask(void)
+{
+ IXPREG(IXP435_INT_ENABLE2) = intr_enabled2 & IXP435_INT_HWMASK;
+}
+
+static __inline void
+ixp435_set_intrsteer(void)
+{
+ IXPREG(IXP435_INT_SELECT2) = intr_steer2 & IXP435_INT_HWMASK;
+}
+
+#endif /* _LOCORE */
+
+#endif /* _IXP425_INTR_H_ */
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_intr.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_mem.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_mem.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_mem.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,103 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_mem.c,v 1.2 2005/12/11 12:16:51 christos Exp $ */
+
+/*
+ * Copyright (c) 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_mem.c 266406 2014-05-18 16:07:35Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+static uint32_t sdram_64bit[] = {
+ 0x00800000, /* 8M: One 2M x 32 chip */
+ 0x01000000, /* 16M: Two 2M x 32 chips */
+ 0x01000000, /* 16M: Two 4M x 16 chips */
+ 0x02000000, /* 32M: Four 4M x 32 chips */
+ 0, 0, 0, 0
+};
+
+static uint32_t sdram_other[] = {
+ 0x02000000, /* 32M: Two 8M x 16 chips */
+ 0x04000000, /* 64M: Four 8M x 16 chips */
+ 0x04000000, /* 64M: Two 16M x 16 chips */
+ 0x08000000, /* 128M: Four 16M x 16 chips */
+ 0x08000000, /* 128M: Two 32M x 16 chips */
+ 0x10000000, /* 256M: Four 32M x 16 chips */
+ 0, 0
+};
+
+uint32_t
+ixp425_sdram_size(void)
+{
+#define MCU_REG_READ(x) (*(volatile uint32_t *)(IXP425_MCU_VBASE + (x)))
+ uint32_t size, sdr_config;
+
+ sdr_config = MCU_REG_READ(MCU_SDR_CONFIG);
+
+ if (sdr_config & MCU_SDR_CONFIG_64MBIT)
+ size = sdram_64bit[MCU_SDR_CONFIG_MCONF(sdr_config)];
+ else
+ size = sdram_other[MCU_SDR_CONFIG_MCONF(sdr_config)];
+
+ if (size == 0) {
+ printf("** SDR_CONFIG returns unknown value, using 32M\n");
+ size = 32 * 1024 * 1024;
+ }
+
+ return (size);
+#undef MCU_REG_READ
+}
+
+uint32_t
+ixp435_ddram_size(void)
+{
+#define MCU_REG_READ(x) (*(volatile uint32_t *)(IXP425_MCU_VBASE + (x)))
+ uint32_t sbr0;
+
+ /*
+ * Table 198, page 516 shows DDR-I/II SDRAM bank sizes
+ * for SBR0 and SBR1. The manual states both banks must
+ * be programmed to be the same size. We just assume
+ * it's done right and calculate 2x for the memory size.
+ */
+ sbr0 = MCU_REG_READ(MCU_DDR_SBR0);
+ return 2 * 16*(sbr0 & 0x7f) * 1024 * 1024;
+#undef MCU_REG_READ
+}
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_mem.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_npe.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_npe.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_npe.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1576 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006-2008 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*-
+ * Copyright (c) 2001-2005, Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_npe.c 249582 2013-04-17 11:40:10Z gabor $");
+
+/*
+ * Intel XScale Network Processing Engine (NPE) support.
+ *
+ * Each NPE has an ixpnpeX device associated with it that is
+ * attached at boot. Depending on the microcode loaded into
+ * an NPE there may be an Ethernet interface (npeX) or some
+ * other network interface (e.g. for ATM). This file has support
+ * for loading microcode images and the associated NPE CPU
+ * manipulations (start, stop, reset).
+ *
+ * The code here basically replaces the npeDl and npeMh classes
+ * in the Intel Access Library (IAL).
+ *
+ * NB: Microcode images are loaded with firmware(9). To
+ * include microcode in a static kernel include the
+ * ixpnpe_fw device. Otherwise the firmware will be
+ * automatically loaded from the filesystem.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <sys/linker.h>
+#include <sys/firmware.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#include <arm/xscale/ixp425/ixp425_npereg.h>
+#include <arm/xscale/ixp425/ixp425_npevar.h>
+
+struct ixpnpe_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_size_t sc_size; /* size of mapped register window */
+ struct resource *sc_irq; /* IRQ resource */
+ void *sc_ih; /* interrupt handler */
+ struct mtx sc_mtx; /* mailbox lock */
+ uint32_t sc_msg[2]; /* reply msg collected in ixpnpe_intr */
+ int sc_msgwaiting; /* sc_msg holds valid data */
+ int sc_npeid;
+ int sc_nrefs; /* # of references */
+
+ int validImage; /* valid ucode image loaded */
+ int started; /* NPE is started */
+ uint8_t functionalityId;/* ucode functionality ID */
+ int insMemSize; /* size of instruction memory */
+ int dataMemSize; /* size of data memory */
+ uint32_t savedExecCount;
+ uint32_t savedEcsDbgCtxtReg2;
+};
+static struct ixpnpe_softc *npes[NPE_MAX];
+
+#define IX_NPEDL_NPEIMAGE_FIELD_MASK 0xff
+
+/* used to read download map from version in microcode image */
+#define IX_NPEDL_BLOCK_TYPE_INSTRUCTION 0x00000000
+#define IX_NPEDL_BLOCK_TYPE_DATA 0x00000001
+#define IX_NPEDL_BLOCK_TYPE_STATE 0x00000002
+#define IX_NPEDL_END_OF_DOWNLOAD_MAP 0x0000000F
+
+/*
+ * masks used to extract address info from State information context
+ * register addresses as read from microcode image
+ */
+#define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG 0x0000000F
+#define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM 0x000000F0
+
+/* LSB offset of Context Number field in State-Info Context Address */
+#define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM 4
+
+/* size (in words) of single State Information entry (ctxt reg address|data) */
+#define IX_NPEDL_STATE_INFO_ENTRY_SIZE 2
+
+typedef struct {
+ uint32_t type;
+ uint32_t offset;
+} IxNpeDlNpeMgrDownloadMapBlockEntry;
+
+typedef union {
+ IxNpeDlNpeMgrDownloadMapBlockEntry block;
+ uint32_t eodmMarker;
+} IxNpeDlNpeMgrDownloadMapEntry;
+
+typedef struct {
+ /* 1st entry in the download map (there may be more than one) */
+ IxNpeDlNpeMgrDownloadMapEntry entry[1];
+} IxNpeDlNpeMgrDownloadMap;
+
+/* used to access an instruction or data block in a microcode image */
+typedef struct {
+ uint32_t npeMemAddress;
+ uint32_t size;
+ uint32_t data[1];
+} IxNpeDlNpeMgrCodeBlock;
+
+/* used to access each Context Reg entry state-information block */
+typedef struct {
+ uint32_t addressInfo;
+ uint32_t value;
+} IxNpeDlNpeMgrStateInfoCtxtRegEntry;
+
+/* used to access a state-information block in a microcode image */
+typedef struct {
+ uint32_t size;
+ IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1];
+} IxNpeDlNpeMgrStateInfoBlock;
+
+static int npe_debug = 0;
+SYSCTL_INT(_debug, OID_AUTO, ixp425npe, CTLFLAG_RW, &npe_debug,
+ 0, "IXP4XX NPE debug msgs");
+TUNABLE_INT("debug.ixp425npe", &npe_debug);
+#define DPRINTF(dev, fmt, ...) do { \
+ if (npe_debug) device_printf(dev, fmt, __VA_ARGS__); \
+} while (0)
+#define DPRINTFn(n, dev, fmt, ...) do { \
+ if (npe_debug >= n) printf(fmt, __VA_ARGS__); \
+} while (0)
+
+static int npe_checkbits(struct ixpnpe_softc *, uint32_t reg, uint32_t);
+static int npe_isstopped(struct ixpnpe_softc *);
+static int npe_load_ins(struct ixpnpe_softc *,
+ const IxNpeDlNpeMgrCodeBlock *bp, int verify);
+static int npe_load_data(struct ixpnpe_softc *,
+ const IxNpeDlNpeMgrCodeBlock *bp, int verify);
+static int npe_load_stateinfo(struct ixpnpe_softc *,
+ const IxNpeDlNpeMgrStateInfoBlock *bp, int verify);
+static int npe_load_image(struct ixpnpe_softc *,
+ const uint32_t *imageCodePtr, int verify);
+static int npe_cpu_reset(struct ixpnpe_softc *);
+static int npe_cpu_start(struct ixpnpe_softc *);
+static int npe_cpu_stop(struct ixpnpe_softc *);
+static void npe_cmd_issue_write(struct ixpnpe_softc *,
+ uint32_t cmd, uint32_t addr, uint32_t data);
+static uint32_t npe_cmd_issue_read(struct ixpnpe_softc *,
+ uint32_t cmd, uint32_t addr);
+static int npe_ins_write(struct ixpnpe_softc *,
+ uint32_t addr, uint32_t data, int verify);
+static int npe_data_write(struct ixpnpe_softc *,
+ uint32_t addr, uint32_t data, int verify);
+static void npe_ecs_reg_write(struct ixpnpe_softc *,
+ uint32_t reg, uint32_t data);
+static uint32_t npe_ecs_reg_read(struct ixpnpe_softc *, uint32_t reg);
+static void npe_issue_cmd(struct ixpnpe_softc *, uint32_t command);
+static void npe_cpu_step_save(struct ixpnpe_softc *);
+static int npe_cpu_step(struct ixpnpe_softc *, uint32_t npeInstruction,
+ uint32_t ctxtNum, uint32_t ldur);
+static void npe_cpu_step_restore(struct ixpnpe_softc *);
+static int npe_logical_reg_read(struct ixpnpe_softc *,
+ uint32_t regAddr, uint32_t regSize,
+ uint32_t ctxtNum, uint32_t *regVal);
+static int npe_logical_reg_write(struct ixpnpe_softc *,
+ uint32_t regAddr, uint32_t regVal,
+ uint32_t regSize, uint32_t ctxtNum, int verify);
+static int npe_physical_reg_write(struct ixpnpe_softc *,
+ uint32_t regAddr, uint32_t regValue, int verify);
+static int npe_ctx_reg_write(struct ixpnpe_softc *, uint32_t ctxtNum,
+ uint32_t ctxtReg, uint32_t ctxtRegVal, int verify);
+
+static void ixpnpe_intr(void *arg);
+
+static uint32_t
+npe_reg_read(struct ixpnpe_softc *sc, bus_size_t off)
+{
+ uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off);
+ DPRINTFn(9, sc->sc_dev, "%s(0x%lx) => 0x%x\n", __func__, off, v);
+ return v;
+}
+
+static void
+npe_reg_write(struct ixpnpe_softc *sc, bus_size_t off, uint32_t val)
+{
+ DPRINTFn(9, sc->sc_dev, "%s(0x%lx, 0x%x)\n", __func__, off, val);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val);
+}
+
+struct ixpnpe_softc *
+ixpnpe_attach(device_t dev, int npeid)
+{
+ struct npeconfig {
+ uint32_t base;
+ uint32_t size;
+ int irq;
+ uint32_t ins_memsize;
+ uint32_t data_memsize;
+ };
+ static const struct npeconfig npeconfigs[NPE_MAX] = {
+ [NPE_A] = {
+ .base = IXP425_NPE_A_HWBASE,
+ .size = IXP425_NPE_A_SIZE,
+ .irq = IXP425_INT_NPE_A,
+ .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEA,
+ .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA
+ },
+ [NPE_B] = {
+ .base = IXP425_NPE_B_HWBASE,
+ .size = IXP425_NPE_B_SIZE,
+ .irq = IXP425_INT_NPE_B,
+ .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB,
+ .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB
+ },
+ [NPE_C] = {
+ .base = IXP425_NPE_C_HWBASE,
+ .size = IXP425_NPE_C_SIZE,
+ .irq = IXP425_INT_NPE_C,
+ .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC,
+ .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC
+ },
+ };
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+ struct ixpnpe_softc *sc;
+ const struct npeconfig *config;
+ int rid;
+
+ if (npeid >= NPE_MAX) {
+ device_printf(dev, "%s: bad npeid %d\n", __func__, npeid);
+ return NULL;
+ }
+ sc = npes[npeid];
+ if (sc != NULL) {
+ sc->sc_nrefs++;
+ return sc;
+ }
+ config = &npeconfigs[npeid];
+
+ /* XXX M_BUS */
+ sc = malloc(sizeof(struct ixpnpe_softc), M_TEMP, M_WAITOK | M_ZERO);
+ sc->sc_dev = dev;
+ sc->sc_iot = sa->sc_iot;
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "npe driver", MTX_DEF);
+ sc->sc_npeid = npeid;
+ sc->sc_nrefs = 1;
+
+ sc->sc_size = config->size;
+ if (cpu_is_ixp42x()) {
+ /* NB: instruction/data memory sizes are NPE-dependent */
+ sc->insMemSize = config->ins_memsize;
+ sc->dataMemSize = config->data_memsize;
+ } else {
+ sc->insMemSize = IXP46X_NPEDL_INS_MEMSIZE_WORDS;
+ sc->dataMemSize = IXP46X_NPEDL_DATA_MEMSIZE_WORDS;
+ }
+
+ if (bus_space_map(sc->sc_iot, config->base, sc->sc_size, 0, &sc->sc_ioh))
+ panic("%s: Cannot map registers", device_get_name(dev));
+
+ /*
+ * Setup IRQ and handler for NPE message support.
+ */
+ rid = 0;
+ sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+ config->irq, config->irq, 1, RF_ACTIVE);
+ if (sc->sc_irq == NULL)
+ panic("%s: Unable to allocate irq %u", device_get_name(dev),
+ config->irq);
+ /* XXX could be a source of entropy */
+ bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, ixpnpe_intr, sc, &sc->sc_ih);
+ /*
+ * Enable output fifo interrupts (NB: must also set OFIFO Write Enable)
+ */
+ npe_reg_write(sc, IX_NPECTL,
+ npe_reg_read(sc, IX_NPECTL) | (IX_NPECTL_OFE | IX_NPECTL_OFWE));
+
+ npes[npeid] = sc;
+
+ return sc;
+}
+
+void
+ixpnpe_detach(struct ixpnpe_softc *sc)
+{
+ if (--sc->sc_nrefs == 0) {
+ npes[sc->sc_npeid] = NULL;
+
+ /* disable output fifo interrupts */
+ npe_reg_write(sc, IX_NPECTL,
+ npe_reg_read(sc, IX_NPECTL) &~ (IX_NPECTL_OFE | IX_NPECTL_OFWE));
+
+ bus_teardown_intr(sc->sc_dev, sc->sc_irq, sc->sc_ih);
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
+ mtx_destroy(&sc->sc_mtx);
+ free(sc, M_TEMP);
+ }
+}
+
+int
+ixpnpe_stopandreset(struct ixpnpe_softc *sc)
+{
+ int error;
+
+ mtx_lock(&sc->sc_mtx);
+ error = npe_cpu_stop(sc); /* stop NPE */
+ if (error == 0)
+ error = npe_cpu_reset(sc); /* reset it */
+ if (error == 0)
+ sc->started = 0; /* mark stopped */
+ mtx_unlock(&sc->sc_mtx);
+
+ DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
+ return error;
+}
+
+static int
+ixpnpe_start_locked(struct ixpnpe_softc *sc)
+{
+ int error;
+
+ if (!sc->started) {
+ error = npe_cpu_start(sc);
+ if (error == 0)
+ sc->started = 1;
+ } else
+ error = 0;
+
+ DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
+ return error;
+}
+
+int
+ixpnpe_start(struct ixpnpe_softc *sc)
+{
+ int ret;
+
+ mtx_lock(&sc->sc_mtx);
+ ret = ixpnpe_start_locked(sc);
+ mtx_unlock(&sc->sc_mtx);
+ return (ret);
+}
+
+int
+ixpnpe_stop(struct ixpnpe_softc *sc)
+{
+ int error;
+
+ mtx_lock(&sc->sc_mtx);
+ error = npe_cpu_stop(sc);
+ if (error == 0)
+ sc->started = 0;
+ mtx_unlock(&sc->sc_mtx);
+
+ DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
+ return error;
+}
+
+/*
+ * Indicates the start of an NPE Image, in new NPE Image Library format.
+ * 2 consecutive occurrences indicates the end of the NPE Image Library
+ */
+#define NPE_IMAGE_MARKER 0xfeedf00d
+
+/*
+ * NPE Image Header definition, used in new NPE Image Library format
+ */
+typedef struct {
+ uint32_t marker;
+ uint32_t id;
+ uint32_t size;
+} IxNpeDlImageMgrImageHeader;
+
+static int
+npe_findimage(struct ixpnpe_softc *sc,
+ const uint32_t *imageLibrary, uint32_t imageId,
+ const uint32_t **imagePtr, uint32_t *imageSize)
+{
+ const IxNpeDlImageMgrImageHeader *image;
+ uint32_t offset = 0;
+
+ while (imageLibrary[offset] == NPE_IMAGE_MARKER) {
+ image = (const IxNpeDlImageMgrImageHeader *)
+ &imageLibrary[offset];
+ offset += sizeof(IxNpeDlImageMgrImageHeader)/sizeof(uint32_t);
+
+ DPRINTF(sc->sc_dev, "%s: off %u mark 0x%x id 0x%x size %u\n",
+ __func__, offset, image->marker, image->id, image->size);
+ if (image->id == imageId) {
+ *imagePtr = imageLibrary + offset;
+ *imageSize = image->size;
+ return 0;
+ }
+ /* 2 consecutive NPE_IMAGE_MARKER's indicates end of library */
+ if (image->id == NPE_IMAGE_MARKER) {
+ DPRINTF(sc->sc_dev, "imageId 0x%08x not found in "
+ "image library header\n", imageId);
+ /* reached end of library, image not found */
+ return ESRCH;
+ }
+ offset += image->size;
+ }
+ return ESRCH;
+}
+
+static int
+ixpnpe_load_firmware(struct ixpnpe_softc *sc, const char *imageName,
+ uint32_t imageId)
+{
+ static const char *devname[4] =
+ { "IXP425", "IXP435/IXP465", "DeviceID#2", "DeviceID#3" };
+ uint32_t imageSize;
+ const uint32_t *imageCodePtr;
+ const struct firmware *fw;
+ int error;
+
+ DPRINTF(sc->sc_dev, "load %s, imageId 0x%08x\n", imageName, imageId);
+
+#if 0
+ IxFeatureCtrlDeviceId devid = IX_NPEDL_DEVICEID_FROM_IMAGEID_GET(imageId);
+ /*
+ * Checking if image being loaded is meant for device that is running.
+ * Image is forward compatible. i.e Image built for IXP42X should run
+ * on IXP46X but not vice versa.
+ */
+ if (devid > (ixFeatureCtrlDeviceRead() & IX_FEATURE_CTRL_DEVICE_TYPE_MASK))
+ return EINVAL;
+#endif
+ error = ixpnpe_stopandreset(sc); /* stop and reset the NPE */
+ if (error != 0)
+ return error;
+
+ fw = firmware_get(imageName);
+ if (fw == NULL)
+ return ENOENT;
+
+ /* Locate desired image in files w/ combined images */
+ error = npe_findimage(sc, fw->data, imageId, &imageCodePtr, &imageSize);
+ if (error != 0)
+ goto done;
+
+ device_printf(sc->sc_dev,
+ "load fw image %s.NPE-%c Func 0x%x Rev %u.%u\n",
+ devname[NPEIMAGE_DEVID(imageId)], 'A' + NPEIMAGE_NPEID(imageId),
+ NPEIMAGE_FUNCID(imageId), NPEIMAGE_MAJOR(imageId),
+ NPEIMAGE_MINOR(imageId));
+
+ /*
+ * If download was successful, store image Id in list of
+ * currently loaded images. If a critical error occured
+ * during download, record that the NPE has an invalid image
+ */
+ mtx_lock(&sc->sc_mtx);
+ error = npe_load_image(sc, imageCodePtr, 1 /*VERIFY*/);
+ if (error == 0) {
+ sc->validImage = 1;
+ error = ixpnpe_start_locked(sc);
+ } else {
+ sc->validImage = 0;
+ }
+ sc->functionalityId = IX_NPEDL_FUNCTIONID_FROM_IMAGEID_GET(imageId);
+ mtx_unlock(&sc->sc_mtx);
+done:
+ firmware_put(fw, FIRMWARE_UNLOAD);
+ DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
+ return error;
+}
+
+static int
+override_imageid(device_t dev, const char *resname, uint32_t *val)
+{
+ int unit = device_get_unit(dev);
+ int resval;
+
+ if (resource_int_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ /* XXX validate */
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=0x%x override\n",
+ unit, resname, resval);
+ *val = resval;
+ return 1;
+}
+
+int
+ixpnpe_init(struct ixpnpe_softc *sc)
+{
+ static const uint32_t npeconfig[NPE_MAX] = {
+ [NPE_A] = IXP425_NPE_A_IMAGEID,
+ [NPE_B] = IXP425_NPE_B_IMAGEID,
+ [NPE_C] = IXP425_NPE_C_IMAGEID,
+ };
+ uint32_t imageid, msg[2];
+ int error;
+
+ if (sc->started)
+ return 0;
+ /*
+ * Load NPE firmware and start it running. We assume
+ * that minor version bumps remain compatible so probe
+ * the firmware image starting with the expected version
+ * and then bump the minor version up to the max.
+ */
+ if (!override_imageid(sc->sc_dev, "imageid", &imageid))
+ imageid = npeconfig[sc->sc_npeid];
+ for (;;) {
+ error = ixpnpe_load_firmware(sc, "npe_fw", imageid);
+ if (error == 0)
+ break;
+ /*
+ * ESRCH is returned when the requested image
+ * is not present
+ */
+ if (error != ESRCH) {
+ device_printf(sc->sc_dev,
+ "cannot init NPE (error %d)\n", error);
+ return error;
+ }
+ /* bump the minor version up to the max possible */
+ if (NPEIMAGE_MINOR(imageid) == 0xff) {
+ device_printf(sc->sc_dev, "cannot locate firmware "
+ "(imageid 0x%08x)\n", imageid);
+ return error;
+ }
+ imageid++;
+ }
+ /* NB: firmware should respond with a status msg */
+ if (ixpnpe_recvmsg_sync(sc, msg) != 0) {
+ device_printf(sc->sc_dev,
+ "firmware did not respond as expected\n");
+ return EIO;
+ }
+ return 0;
+}
+
+int
+ixpnpe_getfunctionality(struct ixpnpe_softc *sc)
+{
+ return (sc->validImage ? sc->functionalityId : 0);
+}
+
+static int
+npe_checkbits(struct ixpnpe_softc *sc, uint32_t reg, uint32_t expectedBitsSet)
+{
+ uint32_t val;
+
+ val = npe_reg_read(sc, reg);
+ DPRINTFn(5, sc->sc_dev, "%s(0x%x, 0x%x) => 0x%x (%u)\n",
+ __func__, reg, expectedBitsSet, val,
+ (val & expectedBitsSet) == expectedBitsSet);
+ return ((val & expectedBitsSet) == expectedBitsSet);
+}
+
+static int
+npe_isstopped(struct ixpnpe_softc *sc)
+{
+ return npe_checkbits(sc,
+ IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP);
+}
+
+static int
+npe_load_ins(struct ixpnpe_softc *sc,
+ const IxNpeDlNpeMgrCodeBlock *bp, int verify)
+{
+ uint32_t npeMemAddress;
+ int i, blockSize;
+
+ npeMemAddress = bp->npeMemAddress;
+ blockSize = bp->size; /* NB: instruction/data count */
+ if (npeMemAddress + blockSize > sc->insMemSize) {
+ device_printf(sc->sc_dev,
+ "Block size %u too big for NPE memory\n", blockSize);
+ return EINVAL; /* XXX */
+ }
+ for (i = 0; i < blockSize; i++, npeMemAddress++) {
+ if (npe_ins_write(sc, npeMemAddress, bp->data[i], verify) != 0) {
+ device_printf(sc->sc_dev,
+ "NPE instruction write failed");
+ return EIO;
+ }
+ }
+ return 0;
+}
+
+static int
+npe_load_data(struct ixpnpe_softc *sc,
+ const IxNpeDlNpeMgrCodeBlock *bp, int verify)
+{
+ uint32_t npeMemAddress;
+ int i, blockSize;
+
+ npeMemAddress = bp->npeMemAddress;
+ blockSize = bp->size; /* NB: instruction/data count */
+ if (npeMemAddress + blockSize > sc->dataMemSize) {
+ device_printf(sc->sc_dev,
+ "Block size %u too big for NPE memory\n", blockSize);
+ return EINVAL;
+ }
+ for (i = 0; i < blockSize; i++, npeMemAddress++) {
+ if (npe_data_write(sc, npeMemAddress, bp->data[i], verify) != 0) {
+ device_printf(sc->sc_dev, "NPE data write failed\n");
+ return EIO;
+ }
+ }
+ return 0;
+}
+
+static int
+npe_load_stateinfo(struct ixpnpe_softc *sc,
+ const IxNpeDlNpeMgrStateInfoBlock *bp, int verify)
+{
+ int i, nentries, error;
+
+ npe_cpu_step_save(sc);
+
+ /* for each state-info context register entry in block */
+ nentries = bp->size / IX_NPEDL_STATE_INFO_ENTRY_SIZE;
+ error = 0;
+ for (i = 0; i < nentries; i++) {
+ /* each state-info entry is 2 words (address, value) */
+ uint32_t regVal = bp->ctxtRegEntry[i].value;
+ uint32_t addrInfo = bp->ctxtRegEntry[i].addressInfo;
+
+ uint32_t reg = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG);
+ uint32_t cNum = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >>
+ IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM;
+
+ /* error-check Context Register No. and Context Number values */
+ if (!(0 <= reg && reg < IX_NPEDL_CTXT_REG_MAX)) {
+ device_printf(sc->sc_dev,
+ "invalid Context Register %u\n", reg);
+ error = EINVAL;
+ break;
+ }
+ if (!(0 <= cNum && cNum < IX_NPEDL_CTXT_NUM_MAX)) {
+ device_printf(sc->sc_dev,
+ "invalid Context Number %u\n", cNum);
+ error = EINVAL;
+ break;
+ }
+ /* NOTE that there is no STEVT register for Context 0 */
+ if (cNum == 0 && reg == IX_NPEDL_CTXT_REG_STEVT) {
+ device_printf(sc->sc_dev,
+ "no STEVT for Context 0\n");
+ error = EINVAL;
+ break;
+ }
+
+ if (npe_ctx_reg_write(sc, cNum, reg, regVal, verify) != 0) {
+ device_printf(sc->sc_dev,
+ "write of state-info to NPE failed\n");
+ error = EIO;
+ break;
+ }
+ }
+
+ npe_cpu_step_restore(sc);
+ return error;
+}
+
+static int
+npe_load_image(struct ixpnpe_softc *sc,
+ const uint32_t *imageCodePtr, int verify)
+{
+#define EOM(marker) ((marker) == IX_NPEDL_END_OF_DOWNLOAD_MAP)
+ const IxNpeDlNpeMgrDownloadMap *downloadMap;
+ int i, error;
+
+ if (!npe_isstopped(sc)) { /* verify NPE is stopped */
+ device_printf(sc->sc_dev,
+ "cannot load image, NPE not stopped\n");
+ return EIO;
+ }
+
+ /*
+ * Read Download Map, checking each block type and calling
+ * appropriate function to perform download
+ */
+ error = 0;
+ downloadMap = (const IxNpeDlNpeMgrDownloadMap *) imageCodePtr;
+ for (i = 0; !EOM(downloadMap->entry[i].eodmMarker); i++) {
+ /* calculate pointer to block to be downloaded */
+ const uint32_t *bp = imageCodePtr +
+ downloadMap->entry[i].block.offset;
+ switch (downloadMap->entry[i].block.type) {
+ case IX_NPEDL_BLOCK_TYPE_INSTRUCTION:
+ error = npe_load_ins(sc,
+ (const IxNpeDlNpeMgrCodeBlock *) bp, verify);
+ DPRINTF(sc->sc_dev, "%s: inst, error %d\n",
+ __func__, error);
+ break;
+ case IX_NPEDL_BLOCK_TYPE_DATA:
+ error = npe_load_data(sc,
+ (const IxNpeDlNpeMgrCodeBlock *) bp, verify);
+ DPRINTF(sc->sc_dev, "%s: data, error %d\n",
+ __func__, error);
+ break;
+ case IX_NPEDL_BLOCK_TYPE_STATE:
+ error = npe_load_stateinfo(sc,
+ (const IxNpeDlNpeMgrStateInfoBlock *) bp, verify);
+ DPRINTF(sc->sc_dev, "%s: state, error %d\n",
+ __func__, error);
+ break;
+ default:
+ device_printf(sc->sc_dev,
+ "unknown block type 0x%x in download map\n",
+ downloadMap->entry[i].block.type);
+ error = EIO; /* XXX */
+ break;
+ }
+ if (error != 0)
+ break;
+ }
+ return error;
+#undef EOM
+}
+
+/* contains Reset values for Context Store Registers */
+static const struct {
+ uint32_t regAddr;
+ uint32_t regResetVal;
+} ixNpeDlEcsRegResetValues[] = {
+ { IX_NPEDL_ECS_BG_CTXT_REG_0, IX_NPEDL_ECS_BG_CTXT_REG_0_RESET },
+ { IX_NPEDL_ECS_BG_CTXT_REG_1, IX_NPEDL_ECS_BG_CTXT_REG_1_RESET },
+ { IX_NPEDL_ECS_BG_CTXT_REG_2, IX_NPEDL_ECS_BG_CTXT_REG_2_RESET },
+ { IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET },
+ { IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET },
+ { IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET },
+ { IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET },
+ { IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET },
+ { IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET },
+ { IX_NPEDL_ECS_DBG_CTXT_REG_0, IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET },
+ { IX_NPEDL_ECS_DBG_CTXT_REG_1, IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET },
+ { IX_NPEDL_ECS_DBG_CTXT_REG_2, IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET },
+ { IX_NPEDL_ECS_INSTRUCT_REG, IX_NPEDL_ECS_INSTRUCT_REG_RESET }
+};
+
+/* contains Reset values for Context Store Registers */
+static const uint32_t ixNpeDlCtxtRegResetValues[] = {
+ IX_NPEDL_CTXT_REG_RESET_STEVT,
+ IX_NPEDL_CTXT_REG_RESET_STARTPC,
+ IX_NPEDL_CTXT_REG_RESET_REGMAP,
+ IX_NPEDL_CTXT_REG_RESET_CINDEX,
+};
+
+#define IX_NPEDL_PARITY_BIT_MASK 0x3F00FFFF
+#define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF
+
+#if 0
+/*
+ * Reset the NPE and its coprocessor using the
+ * fuse bits in the feature control register.
+ */
+static void
+npe_reset(int npeid)
+{
+ uint32_t mask = EXP_FCTRL_NPEA << npeid;
+ uint32_t v;
+
+ v = ixp4xx_read_feature_bits();
+ ixp4xx_write_feature_bits(v &~ mask);
+ /* un-fuse and un-reset the NPE & coprocessor */
+ ixp4xx_write_feature_bits(v | mask);
+}
+#endif
+
+static int
+npe_cpu_reset(struct ixpnpe_softc *sc)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ uint32_t ctxtReg; /* identifies Context Store reg (0-3) */
+ uint32_t regAddr;
+ uint32_t regVal;
+ uint32_t ixNpeConfigCtrlRegVal;
+ int i, error = 0;
+
+ /* pre-store the NPE Config Control Register Value */
+ ixNpeConfigCtrlRegVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL);
+ ixNpeConfigCtrlRegVal |= 0x3F000000;
+
+ /* disable the parity interrupt */
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,
+ (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK));
+ DPRINTFn(2, sc->sc_dev, "%s: dis parity int, CTL => 0x%x\n",
+ __func__, ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK);
+
+ npe_cpu_step_save(sc);
+
+ /*
+ * Clear the FIFOs.
+ */
+ while (npe_checkbits(sc,
+ IX_NPEDL_REG_OFFSET_WFIFO, IX_NPEDL_MASK_WFIFO_VALID)) {
+ /* read from the Watch-point FIFO until empty */
+ (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WFIFO);
+ }
+
+ while (npe_checkbits(sc,
+ IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_OFNE)) {
+ /* read from the outFIFO until empty */
+ (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_FIFO);
+ }
+
+ while (npe_checkbits(sc,
+ IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_IFNE)) {
+ /*
+ * Step execution of the NPE intruction to read inFIFO using
+ * the Debug Executing Context stack.
+ */
+ error = npe_cpu_step(sc, IX_NPEDL_INSTR_RD_FIFO, 0, 0);
+ if (error != 0) {
+ DPRINTF(sc->sc_dev, "%s: cannot step (1), error %u\n",
+ __func__, error);
+ npe_cpu_step_restore(sc);
+ return error;
+ }
+ }
+
+ /*
+ * Reset the mailbox reg
+ */
+ /* ...from XScale side */
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_MBST, IX_NPEDL_REG_RESET_MBST);
+ /* ...from NPE side */
+ error = npe_cpu_step(sc, IX_NPEDL_INSTR_RESET_MBOX, 0, 0);
+ if (error != 0) {
+ DPRINTF(sc->sc_dev, "%s: cannot step (2), error %u\n",
+ __func__, error);
+ npe_cpu_step_restore(sc);
+ return error;
+ }
+
+ /*
+ * Reset the physical registers in the NPE register file:
+ * Note: no need to save/restore REGMAP for Context 0 here
+ * since all Context Store regs are reset in subsequent code.
+ */
+ for (regAddr = 0;
+ regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG && error == 0;
+ regAddr++) {
+ /* for each physical register in the NPE reg file, write 0 : */
+ error = npe_physical_reg_write(sc, regAddr, 0, TRUE);
+ if (error != 0) {
+ DPRINTF(sc->sc_dev, "%s: cannot write phy reg,"
+ "error %u\n", __func__, error);
+ npe_cpu_step_restore(sc);
+ return error; /* abort reset */
+ }
+ }
+
+ /*
+ * Reset the context store:
+ */
+ for (i = IX_NPEDL_CTXT_NUM_MIN; i <= IX_NPEDL_CTXT_NUM_MAX; i++) {
+ /* set each context's Context Store registers to reset values */
+ for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++) {
+ /* NOTE that there is no STEVT register for Context 0 */
+ if (i == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STEVT)
+ continue;
+ regVal = ixNpeDlCtxtRegResetValues[ctxtReg];
+ error = npe_ctx_reg_write(sc, i, ctxtReg,
+ regVal, TRUE);
+ if (error != 0) {
+ DPRINTF(sc->sc_dev, "%s: cannot write ctx reg,"
+ "error %u\n", __func__, error);
+ npe_cpu_step_restore(sc);
+ return error; /* abort reset */
+ }
+ }
+ }
+
+ npe_cpu_step_restore(sc);
+
+ /* write Reset values to Execution Context Stack registers */
+ for (i = 0; i < N(ixNpeDlEcsRegResetValues); i++)
+ npe_ecs_reg_write(sc,
+ ixNpeDlEcsRegResetValues[i].regAddr,
+ ixNpeDlEcsRegResetValues[i].regResetVal);
+
+ /* clear the profile counter */
+ npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT);
+
+ /* clear registers EXCT, AP0, AP1, AP2 and AP3 */
+ for (regAddr = IX_NPEDL_REG_OFFSET_EXCT;
+ regAddr <= IX_NPEDL_REG_OFFSET_AP3;
+ regAddr += sizeof(uint32_t))
+ npe_reg_write(sc, regAddr, 0);
+
+ /* Reset the Watch-count register */
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_WC, 0);
+#if 0
+ /*
+ * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation
+ * XXX Removed because it breaks IXP435 operation; e.g. on Gateworks
+ * XXX 2358 boards reseting NPE-A after NPE-C is running causes both
+ * XXX npe's to stop working
+ */
+ npe_reset(sc->sc_npeid);
+#endif
+ /*
+ * Call NpeMgr function to stop the NPE again after the Feature Control
+ * has unfused and Un-Reset the NPE and its associated Coprocessors.
+ */
+ error = npe_cpu_stop(sc);
+
+ /* restore NPE configuration bus Control Register - Parity Settings */
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,
+ (ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK));
+ DPRINTFn(2, sc->sc_dev, "%s: restore CTL => 0x%x\n",
+ __func__, npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL));
+
+ return error;
+#undef N
+}
+
+static int
+npe_cpu_start(struct ixpnpe_softc *sc)
+{
+ uint32_t ecsRegVal;
+
+ /*
+ * Ensure only Background Context Stack Level is Active by turning off
+ * the Active bit in each of the other Executing Context Stack levels.
+ */
+ ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0);
+ ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0, ecsRegVal);
+
+ ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0);
+ ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0, ecsRegVal);
+
+ ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0);
+ ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsRegVal);
+
+ /* clear the pipeline */
+ npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
+
+ /* start NPE execution by issuing cmd through EXCTL register on NPE */
+ npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_START);
+
+ /*
+ * Check execution status of NPE to verify operation was successful.
+ */
+ return npe_checkbits(sc,
+ IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_RUN) ? 0 : EIO;
+}
+
+static int
+npe_cpu_stop(struct ixpnpe_softc *sc)
+{
+ /* stop NPE execution by issuing cmd through EXCTL register on NPE */
+ npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STOP);
+
+ /* verify that NPE Stop was successful */
+ return npe_checkbits(sc,
+ IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP) ? 0 : EIO;
+}
+
+#define IX_NPEDL_REG_SIZE_BYTE 8
+#define IX_NPEDL_REG_SIZE_SHORT 16
+#define IX_NPEDL_REG_SIZE_WORD 32
+
+/*
+ * Introduce extra read cycles after issuing read command to NPE
+ * so that we read the register after the NPE has updated it
+ * This is to overcome race condition between XScale and NPE
+ */
+#define IX_NPEDL_DELAY_READ_CYCLES 2
+/*
+ * To mask top three MSBs of 32bit word to download into NPE IMEM
+ */
+#define IX_NPEDL_MASK_UNUSED_IMEM_BITS 0x1FFFFFFF;
+
+static void
+npe_cmd_issue_write(struct ixpnpe_softc *sc,
+ uint32_t cmd, uint32_t addr, uint32_t data)
+{
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, data);
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr);
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
+}
+
+static uint32_t
+npe_cmd_issue_read(struct ixpnpe_softc *sc, uint32_t cmd, uint32_t addr)
+{
+ uint32_t data;
+ int i;
+
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr);
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
+ for (i = 0; i <= IX_NPEDL_DELAY_READ_CYCLES; i++)
+ data = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA);
+ return data;
+}
+
+static int
+npe_ins_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify)
+{
+ DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data);
+ npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_INS_MEM, addr, data);
+ if (verify) {
+ uint32_t rdata;
+
+ /*
+ * Write invalid data to this reg, so we can see if we're
+ * reading the EXDATA register too early.
+ */
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data);
+
+ /*
+ * Disabled since top 3 MSB are not used for Azusa
+ * hardware Refer WR:IXA00053900
+ */
+ data &= IX_NPEDL_MASK_UNUSED_IMEM_BITS;
+
+ rdata = npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_INS_MEM,
+ addr);
+ rdata &= IX_NPEDL_MASK_UNUSED_IMEM_BITS;
+
+ if (data != rdata)
+ return EIO;
+ }
+ return 0;
+}
+
+static int
+npe_data_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify)
+{
+ DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data);
+ npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_DATA_MEM, addr, data);
+ if (verify) {
+ /*
+ * Write invalid data to this reg, so we can see if we're
+ * reading the EXDATA register too early.
+ */
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data);
+ if (data != npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_DATA_MEM, addr))
+ return EIO;
+ }
+ return 0;
+}
+
+static void
+npe_ecs_reg_write(struct ixpnpe_softc *sc, uint32_t reg, uint32_t data)
+{
+ npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_ECS_REG, reg, data);
+}
+
+static uint32_t
+npe_ecs_reg_read(struct ixpnpe_softc *sc, uint32_t reg)
+{
+ return npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_ECS_REG, reg);
+}
+
+static void
+npe_issue_cmd(struct ixpnpe_softc *sc, uint32_t command)
+{
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, command);
+}
+
+static void
+npe_cpu_step_save(struct ixpnpe_softc *sc)
+{
+ /* turn off the halt bit by clearing Execution Count register. */
+ /* save reg contents 1st and restore later */
+ sc->savedExecCount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXCT);
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, 0);
+
+ /* ensure that IF and IE are on (temporarily), so that we don't end up
+ * stepping forever */
+ sc->savedEcsDbgCtxtReg2 = npe_ecs_reg_read(sc,
+ IX_NPEDL_ECS_DBG_CTXT_REG_2);
+
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2,
+ (sc->savedEcsDbgCtxtReg2 | IX_NPEDL_MASK_ECS_DBG_REG_2_IF |
+ IX_NPEDL_MASK_ECS_DBG_REG_2_IE));
+}
+
+static int
+npe_cpu_step(struct ixpnpe_softc *sc, uint32_t npeInstruction,
+ uint32_t ctxtNum, uint32_t ldur)
+{
+#define IX_NPE_DL_MAX_NUM_OF_RETRIES 1000000
+ uint32_t ecsDbgRegVal;
+ uint32_t oldWatchcount, newWatchcount;
+ int tries;
+
+ /* set the Active bit, and the LDUR, in the debug level */
+ ecsDbgRegVal = IX_NPEDL_MASK_ECS_REG_0_ACTIVE |
+ (ldur << IX_NPEDL_OFFSET_ECS_REG_0_LDUR);
+
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsDbgRegVal);
+
+ /*
+ * Set CCTXT at ECS DEBUG L3 to specify in which context to execute the
+ * instruction, and set SELCTXT at ECS DEBUG Level to specify which
+ * context store to access.
+ * Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
+ */
+ ecsDbgRegVal = (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_CCTXT) |
+ (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT);
+
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_1, ecsDbgRegVal);
+
+ /* clear the pipeline */
+ npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
+
+ /* load NPE instruction into the instruction register */
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_INSTRUCT_REG, npeInstruction);
+
+ /* need this value later to wait for completion of NPE execution step */
+ oldWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
+
+ /* issue a Step One command via the Execution Control register */
+ npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STEP);
+
+ /*
+ * Force the XScale to wait until the NPE has finished execution step
+ * NOTE that this delay will be very small, just long enough to allow a
+ * single NPE instruction to complete execution; if instruction
+ * execution is not completed before timeout retries, exit the while
+ * loop.
+ */
+ newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
+ for (tries = 0; tries < IX_NPE_DL_MAX_NUM_OF_RETRIES &&
+ newWatchcount == oldWatchcount; tries++) {
+ /* Watch Count register incr's when NPE completes an inst */
+ newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
+ }
+ return (tries < IX_NPE_DL_MAX_NUM_OF_RETRIES) ? 0 : EIO;
+#undef IX_NPE_DL_MAX_NUM_OF_RETRIES
+}
+
+static void
+npe_cpu_step_restore(struct ixpnpe_softc *sc)
+{
+ /* clear active bit in debug level */
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, 0);
+
+ /* clear the pipeline */
+ npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
+
+ /* restore Execution Count register contents. */
+ npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, sc->savedExecCount);
+
+ /* restore IF and IE bits to original values */
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2, sc->savedEcsDbgCtxtReg2);
+}
+
+static int
+npe_logical_reg_read(struct ixpnpe_softc *sc,
+ uint32_t regAddr, uint32_t regSize,
+ uint32_t ctxtNum, uint32_t *regVal)
+{
+ uint32_t npeInstruction, mask;
+ int error;
+
+ switch (regSize) {
+ case IX_NPEDL_REG_SIZE_BYTE:
+ npeInstruction = IX_NPEDL_INSTR_RD_REG_BYTE;
+ mask = 0xff;
+ break;
+ case IX_NPEDL_REG_SIZE_SHORT:
+ npeInstruction = IX_NPEDL_INSTR_RD_REG_SHORT;
+ mask = 0xffff;
+ break;
+ case IX_NPEDL_REG_SIZE_WORD:
+ npeInstruction = IX_NPEDL_INSTR_RD_REG_WORD;
+ mask = 0xffffffff;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ /* make regAddr be the SRC and DEST operands (e.g. movX d0, d0) */
+ npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_SRC) |
+ (regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
+
+ /* step execution of NPE inst using Debug Executing Context stack */
+ error = npe_cpu_step(sc, npeInstruction, ctxtNum,
+ IX_NPEDL_RD_INSTR_LDUR);
+ if (error != 0) {
+ DPRINTF(sc->sc_dev, "%s(0x%x, %u, %u), cannot step, error %d\n",
+ __func__, regAddr, regSize, ctxtNum, error);
+ return error;
+ }
+ /* read value of register from Execution Data register */
+ *regVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA);
+
+ /* align value from left to right */
+ *regVal = (*regVal >> (IX_NPEDL_REG_SIZE_WORD - regSize)) & mask;
+
+ return 0;
+}
+
+static int
+npe_logical_reg_write(struct ixpnpe_softc *sc, uint32_t regAddr, uint32_t regVal,
+ uint32_t regSize, uint32_t ctxtNum, int verify)
+{
+ int error;
+
+ DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x, %u, %u)\n",
+ __func__, regAddr, regVal, regSize, ctxtNum);
+ if (regSize == IX_NPEDL_REG_SIZE_WORD) {
+ /*
+ * NPE register addressing is left-to-right: e.g. |d0|d1|d2|d3|
+ * Write upper half-word (short) to |d0|d1|
+ */
+ error = npe_logical_reg_write(sc, regAddr,
+ regVal >> IX_NPEDL_REG_SIZE_SHORT,
+ IX_NPEDL_REG_SIZE_SHORT, ctxtNum, verify);
+ if (error != 0)
+ return error;
+
+ /* Write lower half-word (short) to |d2|d3| */
+ error = npe_logical_reg_write(sc,
+ regAddr + sizeof(uint16_t),
+ regVal & 0xffff,
+ IX_NPEDL_REG_SIZE_SHORT, ctxtNum, verify);
+ } else {
+ uint32_t npeInstruction;
+
+ switch (regSize) {
+ case IX_NPEDL_REG_SIZE_BYTE:
+ npeInstruction = IX_NPEDL_INSTR_WR_REG_BYTE;
+ regVal &= 0xff;
+ break;
+ case IX_NPEDL_REG_SIZE_SHORT:
+ npeInstruction = IX_NPEDL_INSTR_WR_REG_SHORT;
+ regVal &= 0xffff;
+ break;
+ default:
+ return EINVAL;
+ }
+ /* fill dest operand field of inst with dest reg addr */
+ npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
+
+ /* fill src operand field of inst with least-sig 5 bits of val*/
+ npeInstruction |=
+ ((regVal & IX_NPEDL_MASK_IMMED_INSTR_SRC_DATA) <<
+ IX_NPEDL_OFFSET_INSTR_SRC);
+
+ /* fill coprocessor field of inst with most-sig 11 bits of val*/
+ npeInstruction |=
+ ((regVal & IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA) <<
+ IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA);
+
+ /* step execution of NPE intruction using Debug ECS */
+ error = npe_cpu_step(sc, npeInstruction,
+ ctxtNum, IX_NPEDL_WR_INSTR_LDUR);
+ }
+ if (error != 0) {
+ DPRINTF(sc->sc_dev, "%s(0x%x, 0x%x, %u, %u), error %u "
+ "writing reg\n", __func__, regAddr, regVal, regSize,
+ ctxtNum, error);
+ return error;
+ }
+ if (verify) {
+ uint32_t retRegVal;
+
+ error = npe_logical_reg_read(sc, regAddr, regSize, ctxtNum,
+ &retRegVal);
+ if (error == 0 && regVal != retRegVal)
+ error = EIO; /* XXX ambiguous */
+ }
+ return error;
+}
+
+/*
+ * There are 32 physical registers used in an NPE. These are
+ * treated as 16 pairs of 32-bit registers. To write one of the pair,
+ * write the pair number (0-16) to the REGMAP for Context 0. Then write
+ * the value to register 0 or 4 in the regfile, depending on which
+ * register of the pair is to be written
+ */
+static int
+npe_physical_reg_write(struct ixpnpe_softc *sc,
+ uint32_t regAddr, uint32_t regValue, int verify)
+{
+ int error;
+
+ /*
+ * Set REGMAP for context 0 to (regAddr >> 1) to choose which pair
+ * (0-16) of physical registers to write .
+ */
+ error = npe_logical_reg_write(sc, IX_NPEDL_CTXT_REG_ADDR_REGMAP,
+ (regAddr >> IX_NPEDL_OFFSET_PHYS_REG_ADDR_REGMAP),
+ IX_NPEDL_REG_SIZE_SHORT, 0, verify);
+ if (error == 0) {
+ /* regAddr = 0 or 4 */
+ regAddr = (regAddr & IX_NPEDL_MASK_PHYS_REG_ADDR_LOGICAL_ADDR) *
+ sizeof(uint32_t);
+ error = npe_logical_reg_write(sc, regAddr, regValue,
+ IX_NPEDL_REG_SIZE_WORD, 0, verify);
+ }
+ return error;
+}
+
+static int
+npe_ctx_reg_write(struct ixpnpe_softc *sc, uint32_t ctxtNum,
+ uint32_t ctxtReg, uint32_t ctxtRegVal, int verify)
+{
+ DPRINTFn(4, sc->sc_dev, "%s(%u, %u, %u)\n",
+ __func__, ctxtNum, ctxtReg, ctxtRegVal);
+ /*
+ * Context 0 has no STARTPC. Instead, this value is used to set
+ * NextPC for Background ECS, to set where NPE starts executing code
+ */
+ if (ctxtNum == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STARTPC) {
+ /* read BG_CTXT_REG_0, update NEXTPC bits, & write back to reg*/
+ uint32_t v = npe_ecs_reg_read(sc, IX_NPEDL_ECS_BG_CTXT_REG_0);
+ v &= ~IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
+ v |= (ctxtRegVal << IX_NPEDL_OFFSET_ECS_REG_0_NEXTPC) &
+ IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
+
+ npe_ecs_reg_write(sc, IX_NPEDL_ECS_BG_CTXT_REG_0, v);
+ return 0;
+ } else {
+ static const struct {
+ uint32_t regAddress;
+ uint32_t regSize;
+ } regAccInfo[IX_NPEDL_CTXT_REG_MAX] = {
+ { IX_NPEDL_CTXT_REG_ADDR_STEVT,
+ IX_NPEDL_REG_SIZE_BYTE },
+ { IX_NPEDL_CTXT_REG_ADDR_STARTPC,
+ IX_NPEDL_REG_SIZE_SHORT },
+ { IX_NPEDL_CTXT_REG_ADDR_REGMAP,
+ IX_NPEDL_REG_SIZE_SHORT },
+ { IX_NPEDL_CTXT_REG_ADDR_CINDEX,
+ IX_NPEDL_REG_SIZE_BYTE }
+ };
+ return npe_logical_reg_write(sc, regAccInfo[ctxtReg].regAddress,
+ ctxtRegVal, regAccInfo[ctxtReg].regSize, ctxtNum, verify);
+ }
+}
+
+/*
+ * NPE Mailbox support.
+ */
+#define IX_NPEMH_MAXTRIES 100000
+
+static int
+ofifo_wait(struct ixpnpe_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < IX_NPEMH_MAXTRIES; i++) {
+ if (npe_reg_read(sc, IX_NPESTAT) & IX_NPESTAT_OFNE)
+ return 1;
+ DELAY(10);
+ }
+ device_printf(sc->sc_dev, "%s: timeout, last status 0x%x\n",
+ __func__, npe_reg_read(sc, IX_NPESTAT));
+ return 0;
+}
+
+static int
+getmsg(struct ixpnpe_softc *sc, uint32_t msg[2])
+{
+ mtx_assert(&sc->sc_mtx, MA_OWNED);
+
+ if (!ofifo_wait(sc))
+ return EAGAIN;
+ msg[0] = npe_reg_read(sc, IX_NPEFIFO);
+ DPRINTF(sc->sc_dev, "%s: msg0 0x%x\n", __func__, msg[0]);
+ if (!ofifo_wait(sc))
+ return EAGAIN;
+ msg[1] = npe_reg_read(sc, IX_NPEFIFO);
+ DPRINTF(sc->sc_dev, "%s: msg1 0x%x\n", __func__, msg[1]);
+ return 0;
+}
+
+static void
+ixpnpe_intr(void *arg)
+{
+ struct ixpnpe_softc *sc = arg;
+ uint32_t status;
+
+ mtx_lock(&sc->sc_mtx);
+ status = npe_reg_read(sc, IX_NPESTAT);
+ DPRINTF(sc->sc_dev, "%s: status 0x%x\n", __func__, status);
+ if ((status & IX_NPESTAT_OFINT) == 0) {
+ /* NB: should not happen */
+ device_printf(sc->sc_dev, "%s: status 0x%x\n",
+ __func__, status);
+ /* XXX must silence interrupt? */
+ mtx_unlock(&sc->sc_mtx);
+ return;
+ }
+ /*
+ * A message is waiting in the output FIFO, copy it so
+ * the interrupt will be silenced.
+ */
+ if (getmsg(sc, sc->sc_msg) == 0)
+ sc->sc_msgwaiting = 1;
+ mtx_unlock(&sc->sc_mtx);
+}
+
+static int
+ififo_wait(struct ixpnpe_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < IX_NPEMH_MAXTRIES; i++) {
+ if (npe_reg_read(sc, IX_NPESTAT) & IX_NPESTAT_IFNF)
+ return 1;
+ DELAY(10);
+ }
+ device_printf(sc->sc_dev, "%s: timeout, last status 0x%x\n",
+ __func__, npe_reg_read(sc, IX_NPESTAT));
+ return 0;
+}
+
+static int
+putmsg(struct ixpnpe_softc *sc, const uint32_t msg[2])
+{
+ mtx_assert(&sc->sc_mtx, MA_OWNED);
+
+ DPRINTF(sc->sc_dev, "%s: msg 0x%x:0x%x\n", __func__, msg[0], msg[1]);
+ if (!ififo_wait(sc))
+ return EIO;
+ npe_reg_write(sc, IX_NPEFIFO, msg[0]);
+ if (!ififo_wait(sc))
+ return EIO;
+ npe_reg_write(sc, IX_NPEFIFO, msg[1]);
+
+ return 0;
+}
+
+/*
+ * Send a msg to the NPE and wait for a reply. We spin as
+ * we may be called early with interrupts not properly setup.
+ */
+int
+ixpnpe_sendandrecvmsg_sync(struct ixpnpe_softc *sc,
+ const uint32_t send[2], uint32_t recv[2])
+{
+ int error;
+
+ mtx_lock(&sc->sc_mtx);
+ error = putmsg(sc, send);
+ if (error == 0)
+ error = getmsg(sc, recv);
+ mtx_unlock(&sc->sc_mtx);
+
+ return error;
+}
+
+/*
+ * Send a msg to the NPE w/o waiting for a reply.
+ */
+int
+ixpnpe_sendmsg_async(struct ixpnpe_softc *sc, const uint32_t msg[2])
+{
+ int error;
+
+ mtx_lock(&sc->sc_mtx);
+ error = putmsg(sc, msg);
+ mtx_unlock(&sc->sc_mtx);
+
+ return error;
+}
+
+static int
+recvmsg_locked(struct ixpnpe_softc *sc, uint32_t msg[2])
+{
+ mtx_assert(&sc->sc_mtx, MA_OWNED);
+
+ DPRINTF(sc->sc_dev, "%s: msgwaiting %d\n", __func__, sc->sc_msgwaiting);
+ if (sc->sc_msgwaiting) {
+ msg[0] = sc->sc_msg[0];
+ msg[1] = sc->sc_msg[1];
+ sc->sc_msgwaiting = 0;
+ return 0;
+ }
+ return EAGAIN;
+}
+
+/*
+ * Receive any msg previously received from the NPE. If nothing
+ * is available we return EAGAIN and the caller is required to
+ * do a synchronous receive or try again later.
+ */
+int
+ixpnpe_recvmsg_async(struct ixpnpe_softc *sc, uint32_t msg[2])
+{
+ int error;
+
+ mtx_lock(&sc->sc_mtx);
+ error = recvmsg_locked(sc, msg);
+ mtx_unlock(&sc->sc_mtx);
+
+ return error;
+}
+
+/*
+ * Receive a msg from the NPE. If one was received asynchronously
+ * then it's returned; otherwise we poll synchronously.
+ */
+int
+ixpnpe_recvmsg_sync(struct ixpnpe_softc *sc, uint32_t msg[2])
+{
+ int error;
+
+ mtx_lock(&sc->sc_mtx);
+ error = recvmsg_locked(sc, msg);
+ if (error == EAGAIN)
+ error = getmsg(sc, msg);
+ mtx_unlock(&sc->sc_mtx);
+
+ return error;
+}
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_npe.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_npereg.h
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_npereg.h (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_npereg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,428 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_npereg.h 236987 2012-06-13 04:38:09Z imp $
+ */
+
+/*-
+ * Copyright (c) 2001-2005, Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+*/
+
+#ifndef _IXP425_NPEREG_H_
+#define _IXP425_NPEREG_H_
+
+/* signature found as 1st word in a microcode image library */
+#define IX_NPEDL_IMAGEMGR_SIGNATURE 0xDEADBEEF
+/* marks end of header in a microcode image library */
+#define IX_NPEDL_IMAGEMGR_END_OF_HEADER 0xFFFFFFFF
+
+/*
+ * Intel (R) IXP400 Software NPE Image ID Definition
+ *
+ * Definition of NPE Image ID to be passed to ixNpeDlNpeInitAndStart()
+ * as input of type uint32_t which has the following fields format:
+ *
+ * Field [Bit Location]
+ * -----------------------------------
+ * Device ID [31 - 28]
+ * NPE ID [27 - 24]
+ * NPE Functionality ID [23 - 16]
+ * Major Release Number [15 - 8]
+ * Minor Release Number [7 - 0]
+ */
+#define IX_NPEDL_NPEID_FROM_IMAGEID_GET(imageId) \
+ (((imageId) >> 24) & 0xf)
+#define IX_NPEDL_DEVICEID_FROM_IMAGEID_GET(imageId) \
+ (((imageId) >> 28) & 0xf)
+#define IX_NPEDL_FUNCTIONID_FROM_IMAGEID_GET(imageId) \
+ (((imageId) >> 16) & 0xff)
+#define IX_NPEDL_MAJOR_FROM_IMAGEID_GET(imageId) \
+ (((imageId) >> 8) & 0xff)
+#define IX_NPEDL_MINOR_FROM_IMAGEID_GET(imageId) \
+ (((imageId) >> 0) & 0xff)
+
+/*
+ * Instruction and Data Memory Size (in words) for each NPE
+ */
+#define IX_NPEDL_INS_MEMSIZE_WORDS_NPEA 4096
+#define IX_NPEDL_INS_MEMSIZE_WORDS_NPEB 2048
+#define IX_NPEDL_INS_MEMSIZE_WORDS_NPEC 2048
+
+#define IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA 2048
+#define IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB 2048
+#define IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC 2048
+
+#define IXP46X_NPEDL_INS_MEMSIZE_WORDS 4096
+#define IXP46X_NPEDL_DATA_MEMSIZE_WORDS 4096
+
+/* BAR offsets */
+#define IX_NPEDL_REG_OFFSET_EXAD 0x00000000 /* Execution Address */
+#define IX_NPEDL_REG_OFFSET_EXDATA 0x00000004 /* Execution Data */
+#define IX_NPEDL_REG_OFFSET_EXCTL 0x00000008 /* Execution Control */
+#define IX_NPEDL_REG_OFFSET_EXCT 0x0000000C /* Execution Count */
+#define IX_NPEDL_REG_OFFSET_AP0 0x00000010 /* Action Point 0 */
+#define IX_NPEDL_REG_OFFSET_AP1 0x00000014 /* Action Point 1 */
+#define IX_NPEDL_REG_OFFSET_AP2 0x00000018 /* Action Point 2 */
+#define IX_NPEDL_REG_OFFSET_AP3 0x0000001C /* Action Point 3 */
+#define IX_NPEDL_REG_OFFSET_WFIFO 0x00000020 /* Watchpoint FIFO */
+#define IX_NPEDL_REG_OFFSET_WC 0x00000024 /* Watch Count */
+#define IX_NPEDL_REG_OFFSET_PROFCT 0x00000028 /* Profile Count */
+#define IX_NPEDL_REG_OFFSET_STAT 0x0000002C /* Messaging Status */
+#define IX_NPEDL_REG_OFFSET_CTL 0x00000030 /* Messaging Control */
+#define IX_NPEDL_REG_OFFSET_MBST 0x00000034 /* Mailbox Status */
+#define IX_NPEDL_REG_OFFSET_FIFO 0x00000038 /* Message FIFO */
+
+/*
+ * Reset value for Mailbox (MBST) register
+ * NOTE that if used, it should be complemented with an NPE intruction
+ * to clear the Mailbox at the NPE side as well
+ */
+#define IX_NPEDL_REG_RESET_MBST 0x0000F0F0
+
+#define IX_NPEDL_MASK_WFIFO_VALID 0x80000000 /* VALID bit */
+#define IX_NPEDL_MASK_STAT_OFNE 0x00010000 /* OFNE bit */
+#define IX_NPEDL_MASK_STAT_IFNE 0x00080000 /* IFNE bit */
+
+/*
+ * EXCTL (Execution Control) Register commands
+*/
+#define IX_NPEDL_EXCTL_CMD_NPE_STEP 0x01 /* Step 1 instruction */
+#define IX_NPEDL_EXCTL_CMD_NPE_START 0x02 /* Start execution */
+#define IX_NPEDL_EXCTL_CMD_NPE_STOP 0x03 /* Stop execution */
+#define IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE 0x04 /* Clear ins pipeline */
+
+/*
+ * Read/write operations use address in EXAD and data in EXDATA.
+ */
+#define IX_NPEDL_EXCTL_CMD_RD_INS_MEM 0x10 /* Read ins memory */
+#define IX_NPEDL_EXCTL_CMD_WR_INS_MEM 0x11 /* Write ins memory */
+#define IX_NPEDL_EXCTL_CMD_RD_DATA_MEM 0x12 /* Read data memory */
+#define IX_NPEDL_EXCTL_CMD_WR_DATA_MEM 0x13 /* Write data memory */
+#define IX_NPEDL_EXCTL_CMD_RD_ECS_REG 0x14 /* Read ECS register */
+#define IX_NPEDL_EXCTL_CMD_WR_ECS_REG 0x15 /* Write ECS register */
+
+#define IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT 0x0C /* Clear Profile Count register */
+
+
+/*
+ * EXCTL (Execution Control) Register status bit masks
+ */
+#define IX_NPEDL_EXCTL_STATUS_RUN 0x80000000
+#define IX_NPEDL_EXCTL_STATUS_STOP 0x40000000
+#define IX_NPEDL_EXCTL_STATUS_CLEAR 0x20000000
+#define IX_NPEDL_EXCTL_STATUS_ECS_K 0x00800000 /* pipeline Klean */
+
+/*
+ * Executing Context Stack (ECS) level registers
+ */
+#define IX_NPEDL_ECS_BG_CTXT_REG_0 0x00 /* reg 0 @ bg ctx */
+#define IX_NPEDL_ECS_BG_CTXT_REG_1 0x01 /* reg 1 @ bg ctx */
+#define IX_NPEDL_ECS_BG_CTXT_REG_2 0x02 /* reg 2 @ bg ctx */
+
+#define IX_NPEDL_ECS_PRI_1_CTXT_REG_0 0x04 /* reg 0 @ pri 1 ctx */
+#define IX_NPEDL_ECS_PRI_1_CTXT_REG_1 0x05 /* reg 1 @ pri 1 ctx */
+#define IX_NPEDL_ECS_PRI_1_CTXT_REG_2 0x06 /* reg 2 @ pri 1 ctx */
+
+#define IX_NPEDL_ECS_PRI_2_CTXT_REG_0 0x08 /* reg 0 @ pri 2 ctx */
+#define IX_NPEDL_ECS_PRI_2_CTXT_REG_1 0x09 /* reg 1 @ pri 2 ctx */
+#define IX_NPEDL_ECS_PRI_2_CTXT_REG_2 0x0A /* reg 2 @ pri 2 ctx */
+
+#define IX_NPEDL_ECS_DBG_CTXT_REG_0 0x0C /* reg 0 @ debug ctx */
+#define IX_NPEDL_ECS_DBG_CTXT_REG_1 0x0D /* reg 1 @ debug ctx */
+#define IX_NPEDL_ECS_DBG_CTXT_REG_2 0x0E /* reg 2 @ debug ctx */
+
+#define IX_NPEDL_ECS_INSTRUCT_REG 0x11 /* Instruction reg */
+
+/*
+ * Execution Access register reset values
+ */
+#define IX_NPEDL_ECS_BG_CTXT_REG_0_RESET 0xA0000000
+#define IX_NPEDL_ECS_BG_CTXT_REG_1_RESET 0x01000000
+#define IX_NPEDL_ECS_BG_CTXT_REG_2_RESET 0x00008000
+#define IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET 0x20000080
+#define IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET 0x01000000
+#define IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET 0x00008000
+#define IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET 0x20000080
+#define IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET 0x01000000
+#define IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET 0x00008000
+#define IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET 0x20000000
+#define IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET 0x00000000
+#define IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET 0x001E0000
+#define IX_NPEDL_ECS_INSTRUCT_REG_RESET 0x1003C00F
+
+/*
+ * Masks used to read/write particular bits in Execution Access registers
+ */
+
+#define IX_NPEDL_MASK_ECS_REG_0_ACTIVE 0x80000000 /* Active bit */
+#define IX_NPEDL_MASK_ECS_REG_0_NEXTPC 0x1FFF0000 /* NextPC bits */
+#define IX_NPEDL_MASK_ECS_REG_0_LDUR 0x00000700 /* LDUR bits */
+
+#define IX_NPEDL_MASK_ECS_REG_1_CCTXT 0x000F0000 /* NextPC bits */
+#define IX_NPEDL_MASK_ECS_REG_1_SELCTXT 0x0000000F
+
+#define IX_NPEDL_MASK_ECS_DBG_REG_2_IF 0x00100000 /* IF bit */
+#define IX_NPEDL_MASK_ECS_DBG_REG_2_IE 0x00080000 /* IE bit */
+
+
+/*
+ * Bit-Offsets from LSB of particular bit-fields in Execution Access registers.
+ */
+
+#define IX_NPEDL_OFFSET_ECS_REG_0_NEXTPC 16
+#define IX_NPEDL_OFFSET_ECS_REG_0_LDUR 8
+
+#define IX_NPEDL_OFFSET_ECS_REG_1_CCTXT 16
+#define IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT 0
+
+/*
+ * NPE core & co-processor instruction templates to load into NPE Instruction
+ * Register, for read/write of NPE register file registers.
+ */
+
+/*
+ * Read an 8-bit NPE internal logical register
+ * and return the value in the EXDATA register (aligned to MSB).
+ * NPE Assembler instruction: "mov8 d0, d0 &&& DBG_WrExec"
+ */
+#define IX_NPEDL_INSTR_RD_REG_BYTE 0x0FC00000
+
+/*
+ * Read a 16-bit NPE internal logical register
+ * and return the value in the EXDATA register (aligned to MSB).
+ * NPE Assembler instruction: "mov16 d0, d0 &&& DBG_WrExec"
+ */
+#define IX_NPEDL_INSTR_RD_REG_SHORT 0x0FC08010
+
+/*
+ * Read a 16-bit NPE internal logical register
+ * and return the value in the EXDATA register.
+ * NPE Assembler instruction: "mov32 d0, d0 &&& DBG_WrExec"
+ */
+#define IX_NPEDL_INSTR_RD_REG_WORD 0x0FC08210
+
+/*
+ * Write an 8-bit NPE internal logical register.
+ * NPE Assembler instruction: "mov8 d0, #0"
+ */
+#define IX_NPEDL_INSTR_WR_REG_BYTE 0x00004000
+
+/*
+ * Write a 16-bit NPE internal logical register.
+ * NPE Assembler instruction: "mov16 d0, #0"
+ */
+#define IX_NPEDL_INSTR_WR_REG_SHORT 0x0000C000
+
+/*
+ * Write a 16-bit NPE internal logical register.
+ * NPE Assembler instruction: "cprd32 d0 &&& DBG_RdInFIFO"
+ */
+#define IX_NPEDL_INSTR_RD_FIFO 0x0F888220
+
+/*
+ * Reset Mailbox (MBST) register
+ * NPE Assembler instruction: "mov32 d0, d0 &&& DBG_ClearM"
+ */
+#define IX_NPEDL_INSTR_RESET_MBOX 0x0FAC8210
+
+
+/*
+ * Bit-offsets from LSB, of particular bit-fields in an NPE instruction
+ */
+#define IX_NPEDL_OFFSET_INSTR_SRC 4 /* src operand */
+#define IX_NPEDL_OFFSET_INSTR_DEST 9 /* dest operand */
+#define IX_NPEDL_OFFSET_INSTR_COPROC 18 /* coprocessor ins */
+
+/*
+ * Masks used to read/write particular bits of an NPE Instruction
+ */
+
+/**
+ * Mask the bits of 16-bit data value (least-sig 5 bits) to be used in
+ * SRC field of immediate-mode NPE instruction
+ */
+#define IX_NPEDL_MASK_IMMED_INSTR_SRC_DATA 0x1F
+
+/**
+ * Mask the bits of 16-bit data value (most-sig 11 bits) to be used in
+ * COPROC field of immediate-mode NPE instruction
+ */
+#define IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA 0xFFE0
+
+/**
+ * LSB offset of the bit-field of 16-bit data value (most-sig 11 bits)
+ * to be used in COPROC field of immediate-mode NPE instruction
+ */
+#define IX_NPEDL_OFFSET_IMMED_INSTR_COPROC_DATA 5
+
+/**
+ * Number of left-shifts required to align most-sig 11 bits of 16-bit
+ * data value into COPROC field of immediate-mode NPE instruction
+ */
+#define IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA \
+ (IX_NPEDL_OFFSET_INSTR_COPROC - IX_NPEDL_OFFSET_IMMED_INSTR_COPROC_DATA)
+
+/**
+ * LDUR value used with immediate-mode NPE Instructions by the NpeDl
+ * for writing to NPE internal logical registers
+ */
+#define IX_NPEDL_WR_INSTR_LDUR 1
+
+/**
+ * LDUR value used with NON-immediate-mode NPE Instructions by the NpeDl
+ * for reading from NPE internal logical registers
+ */
+#define IX_NPEDL_RD_INSTR_LDUR 0
+
+
+/**
+ * NPE internal Context Store registers.
+ */
+typedef enum
+{
+ IX_NPEDL_CTXT_REG_STEVT = 0, /**< identifies STEVT */
+ IX_NPEDL_CTXT_REG_STARTPC, /**< identifies STARTPC */
+ IX_NPEDL_CTXT_REG_REGMAP, /**< identifies REGMAP */
+ IX_NPEDL_CTXT_REG_CINDEX, /**< identifies CINDEX */
+ IX_NPEDL_CTXT_REG_MAX /**< Total number of Context Store registers */
+} IxNpeDlCtxtRegNum;
+
+
+/*
+ * NPE Context Store register logical addresses
+ */
+#define IX_NPEDL_CTXT_REG_ADDR_STEVT 0x0000001B
+#define IX_NPEDL_CTXT_REG_ADDR_STARTPC 0x0000001C
+#define IX_NPEDL_CTXT_REG_ADDR_REGMAP 0x0000001E
+#define IX_NPEDL_CTXT_REG_ADDR_CINDEX 0x0000001F
+
+/*
+ * NPE Context Store register reset values
+ */
+
+/**
+ * Reset value of STEVT NPE internal Context Store register
+ * (STEVT = off, 0x80)
+ */
+#define IX_NPEDL_CTXT_REG_RESET_STEVT 0x80
+
+/**
+ * Reset value of STARTPC NPE internal Context Store register
+ * (STARTPC = 0x0000)
+ */
+#define IX_NPEDL_CTXT_REG_RESET_STARTPC 0x0000
+
+/**
+ * Reset value of REGMAP NPE internal Context Store register
+ * (REGMAP = d0->p0, d8->p2, d16->p4)
+ */
+#define IX_NPEDL_CTXT_REG_RESET_REGMAP 0x0820
+
+/**
+ * Reset value of CINDEX NPE internal Context Store register
+ * (CINDEX = 0)
+ */
+#define IX_NPEDL_CTXT_REG_RESET_CINDEX 0x00
+
+
+/*
+ * Numeric range of context levels available on an NPE
+ */
+#define IX_NPEDL_CTXT_NUM_MIN 0
+#define IX_NPEDL_CTXT_NUM_MAX 15
+
+
+/**
+ * Number of Physical registers currently supported
+ * Initial NPE implementations will have a 32-word register file.
+ * Later implementations may have a 64-word register file.
+ */
+#define IX_NPEDL_TOTAL_NUM_PHYS_REG 32
+
+/**
+ * LSB-offset of Regmap number in Physical NPE register address, used
+ * for Physical To Logical register address mapping in the NPE
+ */
+#define IX_NPEDL_OFFSET_PHYS_REG_ADDR_REGMAP 1
+
+/**
+ * Mask to extract a logical NPE register address from a physical
+ * register address, used for Physical To Logical address mapping
+ */
+#define IX_NPEDL_MASK_PHYS_REG_ADDR_LOGICAL_ADDR 0x1
+
+/*
+ * NPE Message/Mailbox interface.
+ */
+#define IX_NPESTAT IX_NPEDL_REG_OFFSET_STAT /* status register */
+#define IX_NPECTL IX_NPEDL_REG_OFFSET_CTL /* control register */
+#define IX_NPEFIFO IX_NPEDL_REG_OFFSET_FIFO /* FIFO register */
+
+/* control register */
+#define IX_NPECTL_OFE 0x00010000 /* output fifo enable */
+#define IX_NPECTL_IFE 0x00020000 /* input fifo enable */
+#define IX_NPECTL_OFWE 0x01000000 /* output fifo write enable */
+#define IX_NPECTL_IFWE 0x02000000 /* input fifo write enable */
+
+/* status register */
+#define IX_NPESTAT_OFNE 0x00010000 /* output fifo not empty */
+#define IX_NPESTAT_IFNF 0x00020000 /* input fifo not full */
+#define IX_NPESTAT_OFNF 0x00040000 /* output fifo not full */
+#define IX_NPESTAT_IFNE 0x00080000 /* input fifo not empty */
+#define IX_NPESTAT_MBINT 0x00100000 /* Mailbox interrupt */
+#define IX_NPESTAT_IFINT 0x00200000 /* input fifo interrupt */
+#define IX_NPESTAT_OFINT 0x00400000 /* output fifo interrupt */
+#define IX_NPESTAT_WFINT 0x00800000 /* watch fifo interrupt */
+#endif /* _IXP425_NPEREG_H_ */
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_npereg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_npevar.h
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_npevar.h (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_npevar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,123 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Sam Leffler. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_npevar.h 186420 2008-12-23 04:51:46Z sam $
+ */
+
+#ifndef _IXP425_NPEVAR_H_
+#define _IXP425_NPEVAR_H_
+
+/*
+ * Intel (R) IXP400 Software NPE Image ID Definition
+ *
+ * Firmware Id's for current firmware image. These are typed by
+ * NPE ID and the feature set. Not all features are available
+ * on all NPE's. The Image ID has the following structure:
+ *
+ * Field [Bit Location]
+ * -----------------------------------
+ * Device ID [28..31]
+ * NPE ID [24..27]
+ * NPE Functionality ID [16..23]
+ * Major Release Number [8..15]
+ * Minor Release Number [0..7]
+ *
+ * The following "feature sets" are known to exist:
+ *
+ * HSS-0: supports 32 channelized and 4 packetized.
+ * HSS-0 + ATM + SPHY:
+ * For HSS, 16/32 channelized and 4/0 packetized.
+ * For ATM, AAL5, AAL0 and OAM for UTOPIA SPHY, 1 logical port, 32 VCs.
+ * Fast Path support.
+ * HSS-0 + ATM + MPHY:
+ * For HSS, 16/32 channelized and 4/0 packetized.
+ * For ATM, AAL5, AAL0 and OAM for UTOPIA MPHY, 1 logical port, 32 VCs.
+ * Fast Path support.
+ * ATM-Only:
+ * AAL5, AAL0 and OAM for UTOPIA MPHY, 12 logical ports, 32 VCs.
+ * Fast Path support.
+ * HSS-2:
+ * HSS-0 and HSS-1.
+ * Each HSS port supports 32 channelized and 4 packetized.
+ * ETH: Ethernet Rx/Tx which includes:
+ * MAC_FILTERING, MAC_LEARNING, SPANNING_TREE, FIREWALL
+ * ETH+VLAN Ethernet Rx/Tx which includes:
+ * MAC_FILTERING, MAC_LEARNING, SPANNING_TREE, FIREWALL, VLAN_QOS
+ * ETH+VLAN+HDR: Ethernet Rx/Tx which includes:
+ * SPANNING_TREE, FIREWALL, VLAN_QOS, HEADER_CONVERSION
+ */
+#define NPEIMAGE_DEVID(id) (((id) >> 28) & 0xf)
+#define NPEIMAGE_NPEID(id) (((id) >> 24) & 0xf)
+#define NPEIMAGE_FUNCID(id) (((id) >> 16) & 0xff)
+#define NPEIMAGE_MAJOR(id) (((id) >> 8) & 0xff)
+#define NPEIMAGE_MINOR(id) (((id) >> 0) & 0xff)
+#define NPEIMAGE_MAKEID(dev, npe, func, maj, min) \
+ ((((dev) & 0xf) << 28) | (((npe) & 0xf) << 24) | \
+ (((func) & 0xff) << 16) (((maj) & 0xff) << 8) | (((min) & 0xff) << 0))
+
+/* XXX not right, revise */
+/* NPE A Firmware Image Id's */
+#define NPEFW_A_HSS0 0x00010000 /* HSS-0: 32 chan+4 packet */
+#define NPEFW_A_HSS0_ATM_S_1 0x00020000 /* HSS-0+ATM UTOPIA SPHY (1 port) */
+#define NPEFW_A_HSS0_ATM_M_1 0x00020000 /* HSS-0+ATM UTOPIA MPHY (1 port) */
+#define NPEFW_A_ATM_M_12 0x00040000 /* ATM UTOPIA MPHY (12 ports) */
+#define NPEFW_A_DMA 0x00150100 /* DMA only */
+#define NPEFW_A_HSS2 0x00090000 /* HSS-0 + HSS-1 */
+#define NPEFW_A_ETH 0x10800200 /* Basic Ethernet */
+#define NPEFW_A_ETH_VLAN 0x10810200 /* NPEFW_A_ETH + VLAN QoS */
+#define NPEFW_A_ETH_VLAN_HDR 0x10820200 /* NPEFW_A_ETH_VLAN + Hdr conv */
+/* XXX ... more not included */
+
+/* NPE B Firmware Image Id's */
+#define NPEFW_B_ETH 0x01000200 /* Basic Ethernet */
+#define NPEFW_B_ETH_VLAN 0x01010200 /* NPEFW_B_ETH + VLAN QoS */
+#define NPEFW_B_ETH_VLAN_HDR 0x01020201 /* NPEFW_B_ETH_VLAN + Hdr conv */
+#define NPEFW_B_DMA 0x01020100 /* DMA only */
+/* XXX ... more not include */
+
+/* NPE ID's */
+#define NPE_A 0
+#define NPE_B 1
+#define NPE_C 2
+#define NPE_MAX (NPE_C+1)
+
+#define IXP425_NPE_A_IMAGEID 0x10820200
+#define IXP425_NPE_B_IMAGEID 0x01020201
+#define IXP425_NPE_C_IMAGEID 0x02050201
+
+struct ixpnpe_softc;
+struct ixpnpe_softc *ixpnpe_attach(device_t, int npeid);
+void ixpnpe_detach(struct ixpnpe_softc *);
+int ixpnpe_stopandreset(struct ixpnpe_softc *);
+int ixpnpe_start(struct ixpnpe_softc *);
+int ixpnpe_stop(struct ixpnpe_softc *);
+int ixpnpe_init(struct ixpnpe_softc *);
+int ixpnpe_getfunctionality(struct ixpnpe_softc *sc);
+
+int ixpnpe_sendmsg_async(struct ixpnpe_softc *, const uint32_t msg[2]);
+int ixpnpe_recvmsg_async(struct ixpnpe_softc *, uint32_t msg[2]);
+int ixpnpe_sendandrecvmsg_sync(struct ixpnpe_softc *,
+ const uint32_t send[2], uint32_t recv[2]);
+int ixpnpe_recvmsg_sync(struct ixpnpe_softc *, uint32_t msg[2]);
+#endif /* _IXP425_NPEVAR_H_ */
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_npevar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_pci.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_pci.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_pci.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,478 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_pci.c,v 1.5 2006/04/10 03:36:03 simonb Exp $ */
+
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_pci.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/pcb.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#include <dev/pci/pcib_private.h>
+#include "pcib_if.h"
+
+#include <dev/pci/pcireg.h>
+extern struct ixp425_softc *ixp425_softc;
+
+#define PCI_CSR_WRITE_4(sc, reg, data) \
+ bus_write_4(sc->sc_csr, reg, data)
+
+#define PCI_CSR_READ_4(sc, reg) \
+ bus_read_4(sc->sc_csr, reg)
+
+#define PCI_CONF_LOCK(s) (s) = disable_interrupts(PSR_I)
+#define PCI_CONF_UNLOCK(s) restore_interrupts((s))
+
+static device_probe_t ixppcib_probe;
+static device_attach_t ixppcib_attach;
+static bus_read_ivar_t ixppcib_read_ivar;
+static bus_write_ivar_t ixppcib_write_ivar;
+static bus_setup_intr_t ixppcib_setup_intr;
+static bus_teardown_intr_t ixppcib_teardown_intr;
+static bus_alloc_resource_t ixppcib_alloc_resource;
+static bus_activate_resource_t ixppcib_activate_resource;
+static bus_deactivate_resource_t ixppcib_deactivate_resource;
+static bus_release_resource_t ixppcib_release_resource;
+static pcib_maxslots_t ixppcib_maxslots;
+static pcib_read_config_t ixppcib_read_config;
+static pcib_write_config_t ixppcib_write_config;
+static pcib_route_interrupt_t ixppcib_route_interrupt;
+
+static int
+ixppcib_probe(device_t dev)
+{
+ device_set_desc(dev, "IXP4XX PCI Bus");
+ return (0);
+}
+
+static void
+ixp425_pci_conf_reg_write(struct ixppcib_softc *sc, uint32_t reg,
+ uint32_t data)
+{
+ PCI_CSR_WRITE_4(sc, PCI_CRP_AD_CBE, ((reg & ~3) | COMMAND_CRP_WRITE));
+ PCI_CSR_WRITE_4(sc, PCI_CRP_AD_WDATA, data);
+}
+
+static int
+ixppcib_attach(device_t dev)
+{
+ int rid;
+ struct ixppcib_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ rid = 0;
+ sc->sc_csr = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ IXP425_PCI_HWBASE, IXP425_PCI_HWBASE + IXP425_PCI_SIZE,
+ IXP425_PCI_SIZE, RF_ACTIVE);
+ if (sc->sc_csr == NULL)
+ panic("cannot allocate PCI CSR registers");
+
+ ixp425_md_attach(dev);
+ /* always setup the base, incase another OS messes w/ it */
+ PCI_CSR_WRITE_4(sc, PCI_PCIMEMBASE, 0x48494a4b);
+
+ rid = 0;
+ sc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ IXP425_PCI_MEM_HWBASE, IXP425_PCI_MEM_HWBASE + IXP425_PCI_MEM_SIZE,
+ IXP425_PCI_MEM_SIZE, RF_ACTIVE);
+ if (sc->sc_mem == NULL)
+ panic("cannot allocate PCI MEM space");
+
+ /* NB: PCI dma window is 64M so anything above must be bounced */
+ if (bus_dma_tag_create(NULL, 1, 0, IXP425_AHB_OFFSET + 64 * 1024 * 1024,
+ BUS_SPACE_MAXADDR, NULL, NULL, 0xffffffff, 0xff, 0xffffffff, 0,
+ NULL, NULL, &sc->sc_dmat))
+ panic("couldn't create the PCI dma tag !");
+ /*
+ * The PCI bus can only address 64MB. However, due to the way our
+ * implementation of busdma works, busdma can't tell if a device
+ * is a PCI device or not. So defaults to the PCI dma tag, which
+ * restrict the DMA'able memory to the first 64MB, and explicitely
+ * create less restrictive tags for non-PCI devices.
+ */
+ arm_root_dma_tag = sc->sc_dmat;
+ /*
+ * Initialize the bus space tags.
+ */
+ ixp425_io_bs_init(&sc->sc_pci_iot, sc);
+ ixp425_mem_bs_init(&sc->sc_pci_memt, sc);
+
+ sc->sc_dev = dev;
+
+ /* Initialize memory and i/o rmans. */
+ sc->sc_io_rman.rm_type = RMAN_ARRAY;
+ sc->sc_io_rman.rm_descr = "IXP4XX PCI I/O Ports";
+ if (rman_init(&sc->sc_io_rman) != 0 ||
+ rman_manage_region(&sc->sc_io_rman, 0,
+ IXP425_PCI_IO_SIZE) != 0) {
+ panic("ixppcib_probe: failed to set up I/O rman");
+ }
+
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "IXP4XX PCI Memory";
+ if (rman_init(&sc->sc_mem_rman) != 0 ||
+ rman_manage_region(&sc->sc_mem_rman, IXP425_PCI_MEM_HWBASE,
+ IXP425_PCI_MEM_HWBASE + IXP425_PCI_MEM_SIZE) != 0) {
+ panic("ixppcib_probe: failed to set up memory rman");
+ }
+
+ /*
+ * PCI->AHB address translation
+ * begin at the physical memory start + OFFSET
+ */
+ PCI_CSR_WRITE_4(sc, PCI_AHBMEMBASE,
+ (IXP425_AHB_OFFSET & 0xFF000000) +
+ ((IXP425_AHB_OFFSET & 0xFF000000) >> 8) +
+ ((IXP425_AHB_OFFSET & 0xFF000000) >> 16) +
+ ((IXP425_AHB_OFFSET & 0xFF000000) >> 24) +
+ 0x00010203);
+
+#define IXPPCIB_WRITE_CONF(sc, reg, val) \
+ ixp425_pci_conf_reg_write(sc, reg, val)
+ /* Write Mapping registers PCI Configuration Registers */
+ /* Base Address 0 - 3 */
+ IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR0, IXP425_AHB_OFFSET + 0x00000000);
+ IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR1, IXP425_AHB_OFFSET + 0x01000000);
+ IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR2, IXP425_AHB_OFFSET + 0x02000000);
+ IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR3, IXP425_AHB_OFFSET + 0x03000000);
+
+ /* Base Address 4 */
+ IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR4, 0xffffffff);
+
+ /* Base Address 5 */
+ IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR5, 0x00000000);
+
+ /* Assert some PCI errors */
+ PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_AHBE | ISR_PPE | ISR_PFE | ISR_PSE);
+
+#ifdef __ARMEB__
+ /*
+ * Set up byte lane swapping between little-endian PCI
+ * and the big-endian AHB bus
+ */
+ PCI_CSR_WRITE_4(sc, PCI_CSR, CSR_IC | CSR_ABE | CSR_PDS);
+#else
+ PCI_CSR_WRITE_4(sc, PCI_CSR, CSR_IC | CSR_ABE);
+#endif
+
+ /*
+ * Enable bus mastering and I/O,memory access
+ */
+ IXPPCIB_WRITE_CONF(sc, PCIR_COMMAND,
+ PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
+
+ /*
+ * Wait some more to ensure PCI devices have stabilised.
+ */
+ DELAY(50000);
+
+ device_add_child(dev, "pci", -1);
+ return (bus_generic_attach(dev));
+}
+
+static int
+ixppcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct ixppcib_softc *sc;
+
+ sc = device_get_softc(dev);
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = 0;
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_bus;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+ixppcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct ixppcib_softc *sc;
+
+ sc = device_get_softc(dev);
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ return (EINVAL);
+ case PCIB_IVAR_BUS:
+ sc->sc_bus = value;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+ixppcib_setup_intr(device_t dev, device_t child, struct resource *ires,
+ int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
+ void **cookiep)
+{
+
+ return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ filt, intr, arg, cookiep));
+}
+
+static int
+ixppcib_teardown_intr(device_t dev, device_t child, struct resource *vec,
+ void *cookie)
+{
+
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, vec, cookie));
+}
+
+static struct resource *
+ixppcib_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct ixppcib_softc *sc = device_get_softc(bus);
+ struct rman *rmanp;
+ struct resource *rv;
+
+ rv = NULL;
+ switch (type) {
+ case SYS_RES_IRQ:
+ rmanp = &sc->sc_irq_rman;
+ break;
+
+ case SYS_RES_IOPORT:
+ rmanp = &sc->sc_io_rman;
+ break;
+
+ case SYS_RES_MEMORY:
+ rmanp = &sc->sc_mem_rman;
+ break;
+
+ default:
+ return (rv);
+ }
+
+ rv = rman_reserve_resource(rmanp, start, end, count, flags & ~RF_ACTIVE,
+ child);
+ if (rv == NULL)
+ return (NULL);
+ rman_set_rid(rv, *rid);
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+
+ return (rv);
+}
+
+static int
+ixppcib_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ struct ixppcib_softc *sc = device_get_softc(bus);
+
+ switch (type) {
+ case SYS_RES_IOPORT:
+ rman_set_bustag(r, &sc->sc_pci_iot);
+ rman_set_bushandle(r, rman_get_start(r));
+ break;
+ case SYS_RES_MEMORY:
+ rman_set_bustag(r, &sc->sc_pci_memt);
+ rman_set_bushandle(r, rman_get_bushandle(sc->sc_mem) +
+ (rman_get_start(r) - IXP425_PCI_MEM_HWBASE));
+ break;
+ }
+
+ return (rman_activate_resource(r));
+}
+
+static int
+ixppcib_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ device_printf(bus, "%s called deactivate_resource (unexpected)\n",
+ device_get_nameunit(child));
+ return (ENXIO);
+}
+
+static int
+ixppcib_release_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ device_printf(bus, "%s called release_resource (unexpected)\n",
+ device_get_nameunit(child));
+ return (ENXIO);
+}
+
+static void
+ixppcib_conf_setup(struct ixppcib_softc *sc, int bus, int slot, int func,
+ int reg)
+{
+ if (bus == 0) {
+ /* configuration type 0 */
+ PCI_CSR_WRITE_4(sc, PCI_NP_AD,
+ (1U << (32 - (slot & 0x1f))) |
+ ((func & 0x7) << 8) | (reg & ~3));
+ } else {
+ /* configuration type 1 */
+ PCI_CSR_WRITE_4(sc, PCI_NP_AD,
+ (bus << 16) | (slot << 11) |
+ (func << 8) | (reg & ~3) | 1);
+ }
+
+}
+
+static int
+ixppcib_maxslots(device_t dev)
+{
+
+ return (PCI_SLOTMAX);
+}
+
+static u_int32_t
+ixppcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+ int bytes)
+{
+ struct ixppcib_softc *sc = device_get_softc(dev);
+ u_int32_t data, ret;
+
+ ixppcib_conf_setup(sc, bus, slot, func, reg & ~3);
+
+ PCI_CSR_WRITE_4(sc, PCI_NP_CBE, COMMAND_NP_CONF_READ);
+ ret = PCI_CSR_READ_4(sc, PCI_NP_RDATA);
+ ret >>= (reg & 3) * 8;
+ ret &= 0xffffffff >> ((4 - bytes) * 8);
+#if 0
+ device_printf(dev, "%s: %u:%u:%u %#x(%d) = %#x\n",
+ __func__, bus, slot, func, reg, bytes, ret);
+#endif
+ /* check & clear PCI abort */
+ data = PCI_CSR_READ_4(sc, PCI_ISR);
+ if (data & ISR_PFE) {
+ PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_PFE);
+ return (-1);
+ }
+ return (ret);
+}
+
+static const int byteenables[] = { 0, 0x10, 0x30, 0x70, 0xf0 };
+
+static void
+ixppcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+ u_int32_t val, int bytes)
+{
+ struct ixppcib_softc *sc = device_get_softc(dev);
+ u_int32_t data;
+
+#if 0
+ device_printf(dev, "%s: %u:%u:%u %#x(%d) = %#x\n",
+ __func__, bus, slot, func, reg, bytes, val);
+#endif
+ ixppcib_conf_setup(sc, bus, slot, func, reg & ~3);
+
+ /* Byte enables are active low, so not them first */
+ PCI_CSR_WRITE_4(sc, PCI_NP_CBE, COMMAND_NP_CONF_WRITE |
+ (~(byteenables[bytes] << (reg & 3)) & 0xf0));
+ PCI_CSR_WRITE_4(sc, PCI_NP_WDATA, val << ((reg & 3) * 8));
+
+ /* check & clear PCI abort */
+ data = PCI_CSR_READ_4(sc, PCI_ISR);
+ if (data & ISR_PFE)
+ PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_PFE);
+}
+
+static int
+ixppcib_route_interrupt(device_t bridge, device_t device, int pin)
+{
+
+ return (ixp425_md_route_interrupt(bridge, device, pin));
+}
+
+static device_method_t ixppcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ixppcib_probe),
+ DEVMETHOD(device_attach, ixppcib_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, ixppcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, ixppcib_write_ivar),
+ DEVMETHOD(bus_setup_intr, ixppcib_setup_intr),
+ DEVMETHOD(bus_teardown_intr, ixppcib_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, ixppcib_alloc_resource),
+ DEVMETHOD(bus_activate_resource, ixppcib_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, ixppcib_deactivate_resource),
+ DEVMETHOD(bus_release_resource, ixppcib_release_resource),
+ /* DEVMETHOD(bus_get_dma_tag, ixppcib_get_dma_tag), */
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, ixppcib_maxslots),
+ DEVMETHOD(pcib_read_config, ixppcib_read_config),
+ DEVMETHOD(pcib_write_config, ixppcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, ixppcib_route_interrupt),
+
+ DEVMETHOD_END
+};
+
+static driver_t ixppcib_driver = {
+ "pcib",
+ ixppcib_methods,
+ sizeof(struct ixppcib_softc),
+};
+static devclass_t ixppcib_devclass;
+
+DRIVER_MODULE(ixppcib, ixp, ixppcib_driver, ixppcib_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_pci_asm.S
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_pci_asm.S (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_pci_asm.S 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,109 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_pci_asm.S,v 1.2 2005/12/11 12:16:51 christos Exp $ */
+
+/*
+ * Copyright (c) 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_pci_asm.S 275767 2014-12-14 16:28:53Z andrew $
+ *
+ */
+
+#include <machine/asm.h>
+
+/*
+ * Bus space functions for IXP425 PCI space access. We have to swizzle
+ * the address for 1 and 2 byte accesses when in big-endian mode.
+ */
+
+/*
+ * read single
+ */
+
+ENTRY(ixp425_pci_mem_bs_r_1)
+#ifdef __ARMEB__
+ add r1, r1, r2
+ eor r1, r1, #0x3
+ ldrb r0, [r1]
+#else
+ ldrb r0, [r1, r2]
+#endif /* __ARMEB__ */
+ mov pc, lr
+END(ixp425_pci_mem_bs_r_1)
+
+ENTRY(ixp425_pci_mem_bs_r_2)
+#ifdef __ARMEB__
+ add r1, r1, r2
+ eor r1, r1, #0x2
+ ldrh r0, [r1]
+#else
+ ldrh r0, [r1, r2]
+#endif /* __ARMEB__ */
+ mov pc, lr
+END(ixp425_pci_mem_bs_r_2)
+
+ENTRY(ixp425_pci_mem_bs_r_4)
+ ldr r0, [r1, r2]
+ mov pc, lr
+END(ixp425_pci_mem_bs_r_4)
+
+/*
+ * write single
+ */
+
+ENTRY(ixp425_pci_mem_bs_w_1)
+#ifdef __ARMEB__
+ add r1, r1, r2
+ eor r1, r1, #0x3
+ strb r3, [r1]
+#else
+ strb r3, [r1, r2]
+#endif /* __ARMEB__ */
+ mov pc, lr
+END(ixp425_pci_mem_bs_w_1)
+
+ENTRY(ixp425_pci_mem_bs_w_2)
+#ifdef __ARMEB__
+ add r1, r1, r2
+ eor r1, r1, #0x2
+ strh r3, [r1]
+#else
+ strh r3, [r1, r2]
+#endif /* __ARMEB__ */
+ mov pc, lr
+END(ixp425_pci_mem_bs_w_2)
+
+ENTRY(ixp425_pci_mem_bs_w_4)
+ str r3, [r1, r2]
+ mov pc, lr
+END(ixp425_pci_mem_bs_w_4)
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_pci_asm.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_pci_space.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_pci_space.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_pci_space.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,486 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_pci_space.c,v 1.6 2006/04/10 03:36:03 simonb Exp $ */
+
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_pci_space.c 278727 2015-02-13 22:32:02Z ian $");
+
+/*
+ * bus_space PCI functions for ixp425
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+
+#include <machine/pcb.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+/*
+ * Macros to read/write registers
+*/
+#define CSR_READ_4(x) *(volatile uint32_t *) \
+ (IXP425_PCI_CSR_BASE + (x))
+#define CSR_WRITE_4(x, v) *(volatile uint32_t *) \
+ (IXP425_PCI_CSR_BASE + (x)) = (v)
+
+/* Proto types for all the bus_space structure functions */
+bs_protos(ixp425_pci);
+bs_protos(ixp425_pci_io);
+bs_protos(ixp425_pci_mem);
+
+/* special I/O functions */
+static u_int8_t _pci_io_bs_r_1(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+static u_int16_t _pci_io_bs_r_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+static u_int32_t _pci_io_bs_r_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+
+static void _pci_io_bs_w_1(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int8_t);
+static void _pci_io_bs_w_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int16_t);
+static void _pci_io_bs_w_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int32_t);
+
+#ifdef __ARMEB__
+static u_int8_t _pci_io_bs_r_1_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+static u_int16_t _pci_io_bs_r_2_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+static u_int32_t _pci_io_bs_r_4_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+
+static void _pci_io_bs_w_1_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int8_t);
+static void _pci_io_bs_w_2_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int16_t);
+static void _pci_io_bs_w_4_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int32_t);
+
+static u_int8_t _pci_mem_bs_r_1(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+static u_int16_t _pci_mem_bs_r_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+static u_int32_t _pci_mem_bs_r_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
+
+static void _pci_mem_bs_w_1(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int8_t);
+static void _pci_mem_bs_w_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int16_t);
+static void _pci_mem_bs_w_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int32_t);
+#endif
+
+struct bus_space ixp425_pci_io_bs_tag_template = {
+ /* mapping/unmapping */
+ .bs_map = ixp425_pci_io_bs_map,
+ .bs_unmap = ixp425_pci_io_bs_unmap,
+ .bs_subregion = ixp425_pci_bs_subregion,
+
+ .bs_alloc = ixp425_pci_io_bs_alloc,
+ .bs_free = ixp425_pci_io_bs_free,
+
+ /* barrier */
+ .bs_barrier = ixp425_pci_bs_barrier,
+
+ /*
+ * IXP425 processor does not have PCI I/O windows
+ */
+ /* read (single) */
+ .bs_r_1 = _pci_io_bs_r_1,
+ .bs_r_2 = _pci_io_bs_r_2,
+ .bs_r_4 = _pci_io_bs_r_4,
+
+ /* write (single) */
+ .bs_w_1 = _pci_io_bs_w_1,
+ .bs_w_2 = _pci_io_bs_w_2,
+ .bs_w_4 = _pci_io_bs_w_4,
+
+#ifdef __ARMEB__
+ .bs_r_1_s = _pci_io_bs_r_1_s,
+ .bs_r_2_s = _pci_io_bs_r_2_s,
+ .bs_r_4_s = _pci_io_bs_r_4_s,
+
+ .bs_w_1_s = _pci_io_bs_w_1_s,
+ .bs_w_2_s = _pci_io_bs_w_2_s,
+ .bs_w_4_s = _pci_io_bs_w_4_s,
+#else
+ .bs_r_1_s = _pci_io_bs_r_1,
+ .bs_r_2_s = _pci_io_bs_r_2,
+ .bs_r_4_s = _pci_io_bs_r_4,
+
+ .bs_w_1_s = _pci_io_bs_w_1,
+ .bs_w_2_s = _pci_io_bs_w_2,
+ .bs_w_4_s = _pci_io_bs_w_4,
+#endif
+};
+
+void
+ixp425_io_bs_init(bus_space_tag_t bs, void *cookie)
+{
+ *bs = ixp425_pci_io_bs_tag_template;
+ bs->bs_privdata = cookie;
+}
+
+struct bus_space ixp425_pci_mem_bs_tag_template = {
+ /* mapping/unmapping */
+ .bs_map = ixp425_pci_mem_bs_map,
+ .bs_unmap = ixp425_pci_mem_bs_unmap,
+ .bs_subregion = ixp425_pci_bs_subregion,
+
+ .bs_alloc = ixp425_pci_mem_bs_alloc,
+ .bs_free = ixp425_pci_mem_bs_free,
+
+ /* barrier */
+ .bs_barrier = ixp425_pci_bs_barrier,
+
+#ifdef __ARMEB__
+ /* read (single) */
+ .bs_r_1_s = _pci_mem_bs_r_1,
+ .bs_r_2_s = _pci_mem_bs_r_2,
+ .bs_r_4_s = _pci_mem_bs_r_4,
+
+ .bs_r_1 = ixp425_pci_mem_bs_r_1,
+ .bs_r_2 = ixp425_pci_mem_bs_r_2,
+ .bs_r_4 = ixp425_pci_mem_bs_r_4,
+
+ /* write (single) */
+ .bs_w_1_s = _pci_mem_bs_w_1,
+ .bs_w_2_s = _pci_mem_bs_w_2,
+ .bs_w_4_s = _pci_mem_bs_w_4,
+
+ .bs_w_1 = ixp425_pci_mem_bs_w_1,
+ .bs_w_2 = ixp425_pci_mem_bs_w_2,
+ .bs_w_4 = ixp425_pci_mem_bs_w_4,
+#else
+ /* read (single) */
+ .bs_r_1 = ixp425_pci_mem_bs_r_1,
+ .bs_r_2 = ixp425_pci_mem_bs_r_2,
+ .bs_r_4 = ixp425_pci_mem_bs_r_4,
+ .bs_r_1_s = ixp425_pci_mem_bs_r_1,
+ .bs_r_2_s = ixp425_pci_mem_bs_r_2,
+ .bs_r_4_s = ixp425_pci_mem_bs_r_4,
+
+ /* write (single) */
+ .bs_w_1 = ixp425_pci_mem_bs_w_1,
+ .bs_w_2 = ixp425_pci_mem_bs_w_2,
+ .bs_w_4 = ixp425_pci_mem_bs_w_4,
+ .bs_w_1_s = ixp425_pci_mem_bs_w_1,
+ .bs_w_2_s = ixp425_pci_mem_bs_w_2,
+ .bs_w_4_s = ixp425_pci_mem_bs_w_4,
+#endif
+};
+
+void
+ixp425_mem_bs_init(bus_space_tag_t bs, void *cookie)
+{
+ *bs = ixp425_pci_mem_bs_tag_template;
+ bs->bs_privdata = cookie;
+}
+
+/* common routine */
+int
+ixp425_pci_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t size, bus_space_handle_t *nbshp)
+{
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+void
+ixp425_pci_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t len, int flags)
+{
+ /* NULL */
+}
+
+/* io bs */
+int
+ixp425_pci_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size,
+ int cacheable, bus_space_handle_t *bshp)
+{
+ *bshp = bpa;
+ return (0);
+}
+
+void
+ixp425_pci_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
+{
+ /* Nothing to do. */
+}
+
+int
+ixp425_pci_io_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable,
+ bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+ panic("ixp425_pci_io_bs_alloc(): not implemented\n");
+}
+
+void
+ixp425_pci_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
+{
+ panic("ixp425_pci_io_bs_free(): not implemented\n");
+}
+
+/* special I/O functions */
+static __inline u_int32_t
+_bs_r(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off, u_int32_t be)
+{
+ u_int32_t data;
+
+ CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
+ CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_READ);
+ data = CSR_READ_4(PCI_NP_RDATA);
+ if (CSR_READ_4(PCI_ISR) & ISR_PFE)
+ CSR_WRITE_4(PCI_ISR, ISR_PFE);
+
+ return data;
+}
+
+static u_int8_t
+_pci_io_bs_r_1(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ u_int32_t data, n, be;
+
+ n = (ioh + off) % 4;
+ be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
+ data = _bs_r(tag, ioh, off, be);
+
+ return data >> (8 * n);
+}
+
+static u_int16_t
+_pci_io_bs_r_2(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ u_int32_t data, n, be;
+
+ n = (ioh + off) % 4;
+ be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
+ data = _bs_r(tag, ioh, off, be);
+
+ return data >> (8 * n);
+}
+
+static u_int32_t
+_pci_io_bs_r_4(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ u_int32_t data;
+
+ data = _bs_r(tag, ioh, off, 0);
+ return data;
+}
+
+#ifdef __ARMEB__
+static u_int8_t
+_pci_io_bs_r_1_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ u_int32_t data, n, be;
+
+ n = (ioh + off) % 4;
+ be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
+ data = _bs_r(tag, ioh, off, be);
+
+ return data >> (8 * n);
+}
+
+static u_int16_t
+_pci_io_bs_r_2_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ u_int32_t data, n, be;
+
+ n = (ioh + off) % 4;
+ be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
+ data = _bs_r(tag, ioh, off, be);
+
+ return data >> (8 * n);
+}
+
+static u_int32_t
+_pci_io_bs_r_4_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ u_int32_t data;
+
+ data = _bs_r(tag, ioh, off, 0);
+ return le32toh(data);
+}
+#endif /* __ARMEB__ */
+
+static __inline void
+_bs_w(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int32_t be, u_int32_t data)
+{
+ CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
+ CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_WRITE);
+ CSR_WRITE_4(PCI_NP_WDATA, data);
+ if (CSR_READ_4(PCI_ISR) & ISR_PFE)
+ CSR_WRITE_4(PCI_ISR, ISR_PFE);
+}
+
+static void
+_pci_io_bs_w_1(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int8_t val)
+{
+ u_int32_t data, n, be;
+
+ n = (ioh + off) % 4;
+ be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
+ data = val << (8 * n);
+ _bs_w(tag, ioh, off, be, data);
+}
+
+static void
+_pci_io_bs_w_2(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int16_t val)
+{
+ u_int32_t data, n, be;
+
+ n = (ioh + off) % 4;
+ be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
+ data = val << (8 * n);
+ _bs_w(tag, ioh, off, be, data);
+}
+
+static void
+_pci_io_bs_w_4(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int32_t val)
+{
+ _bs_w(tag, ioh, off, 0, val);
+}
+
+#ifdef __ARMEB__
+static void
+_pci_io_bs_w_1_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int8_t val)
+{
+ u_int32_t data, n, be;
+
+ n = (ioh + off) % 4;
+ be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
+ data = val << (8 * n);
+ _bs_w(tag, ioh, off, be, data);
+}
+
+static void
+_pci_io_bs_w_2_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int16_t val)
+{
+ u_int32_t data, n, be;
+
+ n = (ioh + off) % 4;
+ be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
+ data = val << (8 * n);
+ _bs_w(tag, ioh, off, be, data);
+}
+
+static void
+_pci_io_bs_w_4_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int32_t val)
+{
+ _bs_w(tag, ioh, off, 0, htole32(val));
+}
+#endif /* __ARMEB__ */
+
+/* mem bs */
+int
+ixp425_pci_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size,
+ int cacheable, bus_space_handle_t *bshp)
+{
+ *bshp = (vm_offset_t)pmap_mapdev(bpa, size);
+ return (0);
+}
+
+void
+ixp425_pci_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
+{
+
+ pmap_unmapdev((vm_offset_t)h, size);
+}
+
+int
+ixp425_pci_mem_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable,
+ bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+ panic("ixp425_mem_bs_alloc(): not implemented\n");
+}
+
+void
+ixp425_pci_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
+{
+ panic("ixp425_mem_bs_free(): not implemented\n");
+}
+
+#ifdef __ARMEB__
+static u_int8_t
+_pci_mem_bs_r_1(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ return ixp425_pci_mem_bs_r_1(tag, ioh, off);
+}
+
+static u_int16_t
+_pci_mem_bs_r_2(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ return (ixp425_pci_mem_bs_r_2(tag, ioh, off));
+}
+
+static u_int32_t
+_pci_mem_bs_r_4(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
+{
+ u_int32_t data;
+
+ data = ixp425_pci_mem_bs_r_4(tag, ioh, off);
+ return (le32toh(data));
+}
+
+static void
+_pci_mem_bs_w_1(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int8_t val)
+{
+ ixp425_pci_mem_bs_w_1(tag, ioh, off, val);
+}
+
+static void
+_pci_mem_bs_w_2(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int16_t val)
+{
+ ixp425_pci_mem_bs_w_2(tag, ioh, off, val);
+}
+
+static void
+_pci_mem_bs_w_4(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
+ u_int32_t val)
+{
+ ixp425_pci_mem_bs_w_4(tag, ioh, off, htole32(val));
+}
+#endif /* __ARMEB__ */
+
+/* End of ixp425_pci_space.c */
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_pci_space.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_qmgr.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_qmgr.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_qmgr.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,1106 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*-
+ * Copyright (c) 2001-2005, Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_qmgr.c 236987 2012-06-13 04:38:09Z imp $");
+
+/*
+ * Intel XScale Queue Manager support.
+ *
+ * Each IXP4XXX device has a hardware block that implements a priority
+ * queue manager that is shared between the XScale cpu and the backend
+ * devices (such as the NPE). Queues are accessed by reading/writing
+ * special memory locations. The queue contents are mapped into a shared
+ * SRAM region with entries managed in a circular buffer. The XScale
+ * processor can receive interrupts based on queue contents (a condition
+ * code determines when interrupts should be delivered).
+ *
+ * The code here basically replaces the qmgr class in the Intel Access
+ * Library (IAL).
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#include <arm/xscale/ixp425/ixp425_qmgr.h>
+
+/*
+ * State per AQM hw queue.
+ * This structure holds q configuration and dispatch state.
+ */
+struct qmgrInfo {
+ int qSizeInWords; /* queue size in words */
+
+ uint32_t qOflowStatBitMask; /* overflow status mask */
+ int qWriteCount; /* queue write count */
+
+ bus_size_t qAccRegAddr; /* access register */
+ bus_size_t qUOStatRegAddr; /* status register */
+ bus_size_t qConfigRegAddr; /* config register */
+ int qSizeInEntries; /* queue size in entries */
+
+ uint32_t qUflowStatBitMask; /* underflow status mask */
+ int qReadCount; /* queue read count */
+
+ /* XXX union */
+ uint32_t qStatRegAddr;
+ uint32_t qStatBitsOffset;
+ uint32_t qStat0BitMask;
+ uint32_t qStat1BitMask;
+
+ uint32_t intRegCheckMask; /* interrupt reg check mask */
+ void (*cb)(int, void *); /* callback function */
+ void *cbarg; /* callback argument */
+ int priority; /* dispatch priority */
+#if 0
+ /* NB: needed only for A0 parts */
+ u_int statusWordOffset; /* status word offset */
+ uint32_t statusMask; /* status mask */
+ uint32_t statusCheckValue; /* status check value */
+#endif
+};
+
+struct ixpqmgr_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ struct resource *sc_irq1; /* IRQ resource */
+ void *sc_ih1; /* interrupt handler */
+ int sc_rid1; /* resource id for irq */
+
+ struct resource *sc_irq2;
+ void *sc_ih2;
+ int sc_rid2;
+
+ struct qmgrInfo qinfo[IX_QMGR_MAX_NUM_QUEUES];
+ /*
+ * This array contains a list of queue identifiers ordered by
+ * priority. The table is split logically between queue
+ * identifiers 0-31 and 32-63. To optimize lookups bit masks
+ * are kept for the first-32 and last-32 q's. When the
+ * table needs to be rebuilt mark rebuildTable and it'll
+ * happen after the next interrupt.
+ */
+ int priorityTable[IX_QMGR_MAX_NUM_QUEUES];
+ uint32_t lowPriorityTableFirstHalfMask;
+ uint32_t uppPriorityTableFirstHalfMask;
+ int rebuildTable; /* rebuild priorityTable */
+
+ uint32_t aqmFreeSramAddress; /* SRAM free space */
+};
+
+static int qmgr_debug = 0;
+SYSCTL_INT(_debug, OID_AUTO, qmgr, CTLFLAG_RW, &qmgr_debug,
+ 0, "IXP4XX Q-Manager debug msgs");
+TUNABLE_INT("debug.qmgr", &qmgr_debug);
+#define DPRINTF(dev, fmt, ...) do { \
+ if (qmgr_debug) printf(fmt, __VA_ARGS__); \
+} while (0)
+#define DPRINTFn(n, dev, fmt, ...) do { \
+ if (qmgr_debug >= n) printf(fmt, __VA_ARGS__); \
+} while (0)
+
+static struct ixpqmgr_softc *ixpqmgr_sc = NULL;
+
+static void ixpqmgr_rebuild(struct ixpqmgr_softc *);
+static void ixpqmgr_intr(void *);
+
+static void aqm_int_enable(struct ixpqmgr_softc *sc, int qId);
+static void aqm_int_disable(struct ixpqmgr_softc *sc, int qId);
+static void aqm_qcfg(struct ixpqmgr_softc *sc, int qId, u_int ne, u_int nf);
+static void aqm_srcsel_write(struct ixpqmgr_softc *sc, int qId, int sourceId);
+static void aqm_reset(struct ixpqmgr_softc *sc);
+
+static void
+dummyCallback(int qId, void *arg)
+{
+ /* XXX complain */
+}
+
+static uint32_t
+aqm_reg_read(struct ixpqmgr_softc *sc, bus_size_t off)
+{
+ DPRINTFn(9, sc->sc_dev, "%s(0x%x)\n", __func__, (int)off);
+ return bus_space_read_4(sc->sc_iot, sc->sc_ioh, off);
+}
+
+static void
+aqm_reg_write(struct ixpqmgr_softc *sc, bus_size_t off, uint32_t val)
+{
+ DPRINTFn(9, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, (int)off, val);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val);
+}
+
+static int
+ixpqmgr_probe(device_t dev)
+{
+ device_set_desc(dev, "IXP4XX Q-Manager");
+ return 0;
+}
+
+static int
+ixpqmgr_attach(device_t dev)
+{
+ struct ixpqmgr_softc *sc = device_get_softc(dev);
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+ int i, err;
+
+ ixpqmgr_sc = sc;
+
+ sc->sc_dev = dev;
+ sc->sc_iot = sa->sc_iot;
+ if (bus_space_map(sc->sc_iot, IXP425_QMGR_HWBASE, IXP425_QMGR_SIZE,
+ 0, &sc->sc_ioh))
+ panic("%s: Cannot map registers", device_get_name(dev));
+
+ /* NB: we only use the lower 32 q's */
+
+ /* Set up QMGR interrupts */
+ sc->sc_rid1 = 0;
+ sc->sc_irq1 = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid1,
+ IXP425_INT_QUE1_32, IXP425_INT_QUE1_32, 1, RF_ACTIVE);
+ sc->sc_rid2 = 1;
+ sc->sc_irq2 = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid2,
+ IXP425_INT_QUE33_64, IXP425_INT_QUE33_64, 1, RF_ACTIVE);
+
+ if (sc->sc_irq1 == NULL || sc->sc_irq2 == NULL)
+ panic("Unable to allocate the qmgr irqs.\n");
+
+ err = bus_setup_intr(dev, sc->sc_irq1, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, ixpqmgr_intr, NULL, &sc->sc_ih1);
+ if (err) {
+ device_printf(dev, "failed to set up qmgr irq=%d\n",
+ IXP425_INT_QUE1_32);
+ return (ENXIO);
+ }
+ err = bus_setup_intr(dev, sc->sc_irq2, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, ixpqmgr_intr, NULL, &sc->sc_ih2);
+ if (err) {
+ device_printf(dev, "failed to set up qmgr irq=%d\n",
+ IXP425_INT_QUE33_64);
+ return (ENXIO);
+ }
+
+ /* NB: softc is pre-zero'd */
+ for (i = 0; i < IX_QMGR_MAX_NUM_QUEUES; i++) {
+ struct qmgrInfo *qi = &sc->qinfo[i];
+
+ qi->cb = dummyCallback;
+ qi->priority = IX_QMGR_Q_PRIORITY_0; /* default priority */
+ /*
+ * There are two interrupt registers, 32 bits each. One
+ * for the lower queues(0-31) and one for the upper
+ * queues(32-63). Therefore need to mod by 32 i.e the
+ * min upper queue identifier.
+ */
+ qi->intRegCheckMask = (1<<(i%(IX_QMGR_MIN_QUEUPP_QID)));
+
+ /*
+ * Register addresses and bit masks are calculated and
+ * stored here to optimize QRead, QWrite and QStatusGet
+ * functions.
+ */
+
+ /* AQM Queue access reg addresses, per queue */
+ qi->qAccRegAddr = IX_QMGR_Q_ACCESS_ADDR_GET(i);
+ qi->qAccRegAddr = IX_QMGR_Q_ACCESS_ADDR_GET(i);
+ qi->qConfigRegAddr = IX_QMGR_Q_CONFIG_ADDR_GET(i);
+
+ /* AQM Queue lower-group (0-31), only */
+ if (i < IX_QMGR_MIN_QUEUPP_QID) {
+ /* AQM Q underflow/overflow status reg address, per queue */
+ qi->qUOStatRegAddr = IX_QMGR_QUEUOSTAT0_OFFSET +
+ ((i / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD) *
+ sizeof(uint32_t));
+
+ /* AQM Q underflow status bit masks for status reg per queue */
+ qi->qUflowStatBitMask =
+ (IX_QMGR_UNDERFLOW_BIT_OFFSET + 1) <<
+ ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) *
+ (32 / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD));
+
+ /* AQM Q overflow status bit masks for status reg, per queue */
+ qi->qOflowStatBitMask =
+ (IX_QMGR_OVERFLOW_BIT_OFFSET + 1) <<
+ ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) *
+ (32 / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD));
+
+ /* AQM Q lower-group (0-31) status reg addresses, per queue */
+ qi->qStatRegAddr = IX_QMGR_QUELOWSTAT0_OFFSET +
+ ((i / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) *
+ sizeof(uint32_t));
+
+ /* AQM Q lower-group (0-31) status register bit offset */
+ qi->qStatBitsOffset =
+ (i & (IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD - 1)) *
+ (32 / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD);
+ } else { /* AQM Q upper-group (32-63), only */
+ qi->qUOStatRegAddr = 0; /* XXX */
+
+ /* AQM Q upper-group (32-63) Nearly Empty status reg bitmasks */
+ qi->qStat0BitMask = (1 << (i - IX_QMGR_MIN_QUEUPP_QID));
+
+ /* AQM Q upper-group (32-63) Full status register bitmasks */
+ qi->qStat1BitMask = (1 << (i - IX_QMGR_MIN_QUEUPP_QID));
+ }
+ }
+
+ sc->aqmFreeSramAddress = 0x100; /* Q buffer space starts at 0x2100 */
+
+ ixpqmgr_rebuild(sc); /* build initial priority table */
+ aqm_reset(sc); /* reset h/w */
+ return (0);
+}
+
+static int
+ixpqmgr_detach(device_t dev)
+{
+ struct ixpqmgr_softc *sc = device_get_softc(dev);
+
+ aqm_reset(sc); /* disable interrupts */
+ bus_teardown_intr(dev, sc->sc_irq1, sc->sc_ih1);
+ bus_teardown_intr(dev, sc->sc_irq2, sc->sc_ih2);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid1, sc->sc_irq1);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid2, sc->sc_irq2);
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, IXP425_QMGR_SIZE);
+ return (0);
+}
+
+int
+ixpqmgr_qconfig(int qId, int qEntries, int ne, int nf, int srcSel,
+ qconfig_hand_t *cb, void *cbarg)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+ struct qmgrInfo *qi = &sc->qinfo[qId];
+
+ DPRINTF(sc->sc_dev, "%s(%u, %u, %u, %u, %u, %p, %p)\n",
+ __func__, qId, qEntries, ne, nf, srcSel, cb, cbarg);
+
+ /* NB: entry size is always 1 */
+ qi->qSizeInWords = qEntries;
+
+ qi->qReadCount = 0;
+ qi->qWriteCount = 0;
+ qi->qSizeInEntries = qEntries; /* XXX kept for code clarity */
+
+ if (cb == NULL) {
+ /* Reset to dummy callback */
+ qi->cb = dummyCallback;
+ qi->cbarg = 0;
+ } else {
+ qi->cb = cb;
+ qi->cbarg = cbarg;
+ }
+
+ /* Write the config register; NB must be AFTER qinfo setup */
+ aqm_qcfg(sc, qId, ne, nf);
+ /*
+ * Account for space just allocated to queue.
+ */
+ sc->aqmFreeSramAddress += (qi->qSizeInWords * sizeof(uint32_t));
+
+ /* Set the interrupt source if this queue is in the range 0-31 */
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ aqm_srcsel_write(sc, qId, srcSel);
+
+ if (cb != NULL) /* Enable the interrupt */
+ aqm_int_enable(sc, qId);
+
+ sc->rebuildTable = TRUE;
+
+ return 0; /* XXX */
+}
+
+int
+ixpqmgr_qwrite(int qId, uint32_t entry)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+ struct qmgrInfo *qi = &sc->qinfo[qId];
+
+ DPRINTFn(3, sc->sc_dev, "%s(%u, 0x%x) writeCount %u size %u\n",
+ __func__, qId, entry, qi->qWriteCount, qi->qSizeInEntries);
+
+ /* write the entry */
+ aqm_reg_write(sc, qi->qAccRegAddr, entry);
+
+ /* NB: overflow is available for lower queues only */
+ if (qId < IX_QMGR_MIN_QUEUPP_QID) {
+ int qSize = qi->qSizeInEntries;
+ /*
+ * Increment the current number of entries in the queue
+ * and check for overflow .
+ */
+ if (qi->qWriteCount++ == qSize) { /* check for overflow */
+ uint32_t status = aqm_reg_read(sc, qi->qUOStatRegAddr);
+ int qPtrs;
+
+ /*
+ * Read the status twice because the status may
+ * not be immediately ready after the write operation
+ */
+ if ((status & qi->qOflowStatBitMask) ||
+ ((status = aqm_reg_read(sc, qi->qUOStatRegAddr)) & qi->qOflowStatBitMask)) {
+ /*
+ * The queue is full, clear the overflow status bit if set.
+ */
+ aqm_reg_write(sc, qi->qUOStatRegAddr,
+ status & ~qi->qOflowStatBitMask);
+ qi->qWriteCount = qSize;
+ DPRINTFn(5, sc->sc_dev,
+ "%s(%u, 0x%x) Q full, overflow status cleared\n",
+ __func__, qId, entry);
+ return ENOSPC;
+ }
+ /*
+ * No overflow occured : someone is draining the queue
+ * and the current counter needs to be
+ * updated from the current number of entries in the queue
+ */
+
+ /* calculate number of words in q */
+ qPtrs = aqm_reg_read(sc, qi->qConfigRegAddr);
+ DPRINTFn(2, sc->sc_dev,
+ "%s(%u, 0x%x) Q full, no overflow status, qConfig 0x%x\n",
+ __func__, qId, entry, qPtrs);
+ qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
+
+ if (qPtrs == 0) {
+ /*
+ * The queue may be full at the time of the
+ * snapshot. Next access will check
+ * the overflow status again.
+ */
+ qi->qWriteCount = qSize;
+ } else {
+ /* convert the number of words to a number of entries */
+ qi->qWriteCount = qPtrs & (qSize - 1);
+ }
+ }
+ }
+ return 0;
+}
+
+int
+ixpqmgr_qread(int qId, uint32_t *entry)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+ struct qmgrInfo *qi = &sc->qinfo[qId];
+ bus_size_t off = qi->qAccRegAddr;
+
+ *entry = aqm_reg_read(sc, off);
+
+ /*
+ * Reset the current read count : next access to the read function
+ * will force a underflow status check.
+ */
+ qi->qReadCount = 0;
+
+ /* Check if underflow occurred on the read */
+ if (*entry == 0 && qId < IX_QMGR_MIN_QUEUPP_QID) {
+ /* get the queue status */
+ uint32_t status = aqm_reg_read(sc, qi->qUOStatRegAddr);
+
+ if (status & qi->qUflowStatBitMask) { /* clear underflow status */
+ aqm_reg_write(sc, qi->qUOStatRegAddr,
+ status &~ qi->qUflowStatBitMask);
+ return ENOSPC;
+ }
+ }
+ return 0;
+}
+
+int
+ixpqmgr_qreadm(int qId, uint32_t n, uint32_t *p)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+ struct qmgrInfo *qi = &sc->qinfo[qId];
+ uint32_t entry;
+ bus_size_t off = qi->qAccRegAddr;
+
+ entry = aqm_reg_read(sc, off);
+ while (--n) {
+ if (entry == 0) {
+ /* if we read a NULL entry, stop. We have underflowed */
+ break;
+ }
+ *p++ = entry; /* store */
+ entry = aqm_reg_read(sc, off);
+ }
+ *p = entry;
+
+ /*
+ * Reset the current read count : next access to the read function
+ * will force a underflow status check.
+ */
+ qi->qReadCount = 0;
+
+ /* Check if underflow occurred on the read */
+ if (entry == 0 && qId < IX_QMGR_MIN_QUEUPP_QID) {
+ /* get the queue status */
+ uint32_t status = aqm_reg_read(sc, qi->qUOStatRegAddr);
+
+ if (status & qi->qUflowStatBitMask) { /* clear underflow status */
+ aqm_reg_write(sc, qi->qUOStatRegAddr,
+ status &~ qi->qUflowStatBitMask);
+ return ENOSPC;
+ }
+ }
+ return 0;
+}
+
+uint32_t
+ixpqmgr_getqstatus(int qId)
+{
+#define QLOWSTATMASK \
+ ((1 << (32 / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)) - 1)
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+ const struct qmgrInfo *qi = &sc->qinfo[qId];
+ uint32_t status;
+
+ if (qId < IX_QMGR_MIN_QUEUPP_QID) {
+ /* read the status of a queue in the range 0-31 */
+ status = aqm_reg_read(sc, qi->qStatRegAddr);
+
+ /* mask out the status bits relevant only to this queue */
+ status = (status >> qi->qStatBitsOffset) & QLOWSTATMASK;
+ } else { /* read status of a queue in the range 32-63 */
+ status = 0;
+ if (aqm_reg_read(sc, IX_QMGR_QUEUPPSTAT0_OFFSET)&qi->qStat0BitMask)
+ status |= IX_QMGR_Q_STATUS_NE_BIT_MASK; /* nearly empty */
+ if (aqm_reg_read(sc, IX_QMGR_QUEUPPSTAT1_OFFSET)&qi->qStat1BitMask)
+ status |= IX_QMGR_Q_STATUS_F_BIT_MASK; /* full */
+ }
+ return status;
+#undef QLOWSTATMASK
+}
+
+uint32_t
+ixpqmgr_getqconfig(int qId)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+
+ return aqm_reg_read(sc, IX_QMGR_Q_CONFIG_ADDR_GET(qId));
+}
+
+void
+ixpqmgr_dump(void)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+ int i, a;
+
+ /* status registers */
+ printf("0x%04x: %08x %08x %08x %08x\n"
+ , 0x400
+ , aqm_reg_read(sc, 0x400)
+ , aqm_reg_read(sc, 0x400+4)
+ , aqm_reg_read(sc, 0x400+8)
+ , aqm_reg_read(sc, 0x400+12)
+ );
+ printf("0x%04x: %08x %08x %08x %08x\n"
+ , 0x410
+ , aqm_reg_read(sc, 0x410)
+ , aqm_reg_read(sc, 0x410+4)
+ , aqm_reg_read(sc, 0x410+8)
+ , aqm_reg_read(sc, 0x410+12)
+ );
+ printf("0x%04x: %08x %08x %08x %08x\n"
+ , 0x420
+ , aqm_reg_read(sc, 0x420)
+ , aqm_reg_read(sc, 0x420+4)
+ , aqm_reg_read(sc, 0x420+8)
+ , aqm_reg_read(sc, 0x420+12)
+ );
+ printf("0x%04x: %08x %08x %08x %08x\n"
+ , 0x430
+ , aqm_reg_read(sc, 0x430)
+ , aqm_reg_read(sc, 0x430+4)
+ , aqm_reg_read(sc, 0x430+8)
+ , aqm_reg_read(sc, 0x430+12)
+ );
+ /* q configuration registers */
+ for (a = 0x2000; a < 0x20ff; a += 32)
+ printf("0x%04x: %08x %08x %08x %08x %08x %08x %08x %08x\n"
+ , a
+ , aqm_reg_read(sc, a)
+ , aqm_reg_read(sc, a+4)
+ , aqm_reg_read(sc, a+8)
+ , aqm_reg_read(sc, a+12)
+ , aqm_reg_read(sc, a+16)
+ , aqm_reg_read(sc, a+20)
+ , aqm_reg_read(sc, a+24)
+ , aqm_reg_read(sc, a+28)
+ );
+ /* allocated SRAM */
+ for (i = 0x100; i < sc->aqmFreeSramAddress; i += 32) {
+ a = 0x2000 + i;
+ printf("0x%04x: %08x %08x %08x %08x %08x %08x %08x %08x\n"
+ , a
+ , aqm_reg_read(sc, a)
+ , aqm_reg_read(sc, a+4)
+ , aqm_reg_read(sc, a+8)
+ , aqm_reg_read(sc, a+12)
+ , aqm_reg_read(sc, a+16)
+ , aqm_reg_read(sc, a+20)
+ , aqm_reg_read(sc, a+24)
+ , aqm_reg_read(sc, a+28)
+ );
+ }
+ for (i = 0; i < 16; i++) {
+ printf("Q[%2d] config 0x%08x status 0x%02x "
+ "Q[%2d] config 0x%08x status 0x%02x\n"
+ , i, ixpqmgr_getqconfig(i), ixpqmgr_getqstatus(i)
+ , i+16, ixpqmgr_getqconfig(i+16), ixpqmgr_getqstatus(i+16)
+ );
+ }
+}
+
+void
+ixpqmgr_notify_enable(int qId, int srcSel)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+#if 0
+ /* Calculate the checkMask and checkValue for this q */
+ aqm_calc_statuscheck(sc, qId, srcSel);
+#endif
+ /* Set the interrupt source if this queue is in the range 0-31 */
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ aqm_srcsel_write(sc, qId, srcSel);
+
+ /* Enable the interrupt */
+ aqm_int_enable(sc, qId);
+}
+
+void
+ixpqmgr_notify_disable(int qId)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+
+ aqm_int_disable(sc, qId);
+}
+
+/*
+ * Rebuild the priority table used by the dispatcher.
+ */
+static void
+ixpqmgr_rebuild(struct ixpqmgr_softc *sc)
+{
+ int q, pri;
+ int lowQuePriorityTableIndex, uppQuePriorityTableIndex;
+ struct qmgrInfo *qi;
+
+ sc->lowPriorityTableFirstHalfMask = 0;
+ sc->uppPriorityTableFirstHalfMask = 0;
+
+ lowQuePriorityTableIndex = 0;
+ uppQuePriorityTableIndex = 32;
+ for (pri = 0; pri < IX_QMGR_NUM_PRIORITY_LEVELS; pri++) {
+ /* low priority q's */
+ for (q = 0; q < IX_QMGR_MIN_QUEUPP_QID; q++) {
+ qi = &sc->qinfo[q];
+ if (qi->priority == pri) {
+ /*
+ * Build the priority table bitmask which match the
+ * queues of the first half of the priority table.
+ */
+ if (lowQuePriorityTableIndex < 16) {
+ sc->lowPriorityTableFirstHalfMask |=
+ qi->intRegCheckMask;
+ }
+ sc->priorityTable[lowQuePriorityTableIndex++] = q;
+ }
+ }
+ /* high priority q's */
+ for (; q < IX_QMGR_MAX_NUM_QUEUES; q++) {
+ qi = &sc->qinfo[q];
+ if (qi->priority == pri) {
+ /*
+ * Build the priority table bitmask which match the
+ * queues of the first half of the priority table .
+ */
+ if (uppQuePriorityTableIndex < 48) {
+ sc->uppPriorityTableFirstHalfMask |=
+ qi->intRegCheckMask;
+ }
+ sc->priorityTable[uppQuePriorityTableIndex++] = q;
+ }
+ }
+ }
+ sc->rebuildTable = FALSE;
+}
+
+/*
+ * Count the number of leading zero bits in a word,
+ * and return the same value than the CLZ instruction.
+ * Note this is similar to the standard ffs function but
+ * it counts zero's from the MSB instead of the LSB.
+ *
+ * word (in) return value (out)
+ * 0x80000000 0
+ * 0x40000000 1
+ * ,,, ,,,
+ * 0x00000002 30
+ * 0x00000001 31
+ * 0x00000000 32
+ *
+ * The C version of this function is used as a replacement
+ * for system not providing the equivalent of the CLZ
+ * assembly language instruction.
+ *
+ * Note that this version is big-endian
+ */
+static unsigned int
+_lzcount(uint32_t word)
+{
+ unsigned int lzcount = 0;
+
+ if (word == 0)
+ return 32;
+ while ((word & 0x80000000) == 0) {
+ word <<= 1;
+ lzcount++;
+ }
+ return lzcount;
+}
+
+static void
+ixpqmgr_intr(void *arg)
+{
+ struct ixpqmgr_softc *sc = ixpqmgr_sc;
+ uint32_t intRegVal; /* Interrupt reg val */
+ struct qmgrInfo *qi;
+ int priorityTableIndex; /* Priority table index */
+ int qIndex; /* Current queue being processed */
+
+ /* Read the interrupt register */
+ intRegVal = aqm_reg_read(sc, IX_QMGR_QINTREG0_OFFSET);
+ /* Write back to clear interrupt */
+ aqm_reg_write(sc, IX_QMGR_QINTREG0_OFFSET, intRegVal);
+
+ DPRINTFn(5, sc->sc_dev, "%s: ISR0 0x%x ISR1 0x%x\n",
+ __func__, intRegVal, aqm_reg_read(sc, IX_QMGR_QINTREG1_OFFSET));
+
+ /* No queue has interrupt register set */
+ if (intRegVal != 0) {
+ /* get the first queue Id from the interrupt register value */
+ qIndex = (32 - 1) - _lzcount(intRegVal);
+
+ DPRINTFn(2, sc->sc_dev, "%s: ISR0 0x%x qIndex %u\n",
+ __func__, intRegVal, qIndex);
+
+ /*
+ * Optimize for single callback case.
+ */
+ qi = &sc->qinfo[qIndex];
+ if (intRegVal == qi->intRegCheckMask) {
+ /*
+ * Only 1 queue event triggered a notification.
+ * Call the callback function for this queue
+ */
+ qi->cb(qIndex, qi->cbarg);
+ } else {
+ /*
+ * The event is triggered by more than 1 queue,
+ * the queue search will start from the beginning
+ * or the middle of the priority table.
+ *
+ * The search will end when all the bits of the interrupt
+ * register are cleared. There is no need to maintain
+ * a separate value and test it at each iteration.
+ */
+ if (intRegVal & sc->lowPriorityTableFirstHalfMask) {
+ priorityTableIndex = 0;
+ } else {
+ priorityTableIndex = 16;
+ }
+ /*
+ * Iterate over the priority table until all the bits
+ * of the interrupt register are cleared.
+ */
+ do {
+ qIndex = sc->priorityTable[priorityTableIndex++];
+ qi = &sc->qinfo[qIndex];
+
+ /* If this queue caused this interrupt to be raised */
+ if (intRegVal & qi->intRegCheckMask) {
+ /* Call the callback function for this queue */
+ qi->cb(qIndex, qi->cbarg);
+ /* Clear the interrupt register bit */
+ intRegVal &= ~qi->intRegCheckMask;
+ }
+ } while (intRegVal);
+ }
+ }
+
+ /* Rebuild the priority table if needed */
+ if (sc->rebuildTable)
+ ixpqmgr_rebuild(sc);
+}
+
+#if 0
+/*
+ * Generate the parameters used to check if a Q's status matches
+ * the specified source select. We calculate which status word
+ * to check (statusWordOffset), the value to check the status
+ * against (statusCheckValue) and the mask (statusMask) to mask
+ * out all but the bits to check in the status word.
+ */
+static void
+aqm_calc_statuscheck(int qId, IxQMgrSourceId srcSel)
+{
+ struct qmgrInfo *qi = &qinfo[qId];
+ uint32_t shiftVal;
+
+ if (qId < IX_QMGR_MIN_QUEUPP_QID) {
+ switch (srcSel) {
+ case IX_QMGR_Q_SOURCE_ID_E:
+ qi->statusCheckValue = IX_QMGR_Q_STATUS_E_BIT_MASK;
+ qi->statusMask = IX_QMGR_Q_STATUS_E_BIT_MASK;
+ break;
+ case IX_QMGR_Q_SOURCE_ID_NE:
+ qi->statusCheckValue = IX_QMGR_Q_STATUS_NE_BIT_MASK;
+ qi->statusMask = IX_QMGR_Q_STATUS_NE_BIT_MASK;
+ break;
+ case IX_QMGR_Q_SOURCE_ID_NF:
+ qi->statusCheckValue = IX_QMGR_Q_STATUS_NF_BIT_MASK;
+ qi->statusMask = IX_QMGR_Q_STATUS_NF_BIT_MASK;
+ break;
+ case IX_QMGR_Q_SOURCE_ID_F:
+ qi->statusCheckValue = IX_QMGR_Q_STATUS_F_BIT_MASK;
+ qi->statusMask = IX_QMGR_Q_STATUS_F_BIT_MASK;
+ break;
+ case IX_QMGR_Q_SOURCE_ID_NOT_E:
+ qi->statusCheckValue = 0;
+ qi->statusMask = IX_QMGR_Q_STATUS_E_BIT_MASK;
+ break;
+ case IX_QMGR_Q_SOURCE_ID_NOT_NE:
+ qi->statusCheckValue = 0;
+ qi->statusMask = IX_QMGR_Q_STATUS_NE_BIT_MASK;
+ break;
+ case IX_QMGR_Q_SOURCE_ID_NOT_NF:
+ qi->statusCheckValue = 0;
+ qi->statusMask = IX_QMGR_Q_STATUS_NF_BIT_MASK;
+ break;
+ case IX_QMGR_Q_SOURCE_ID_NOT_F:
+ qi->statusCheckValue = 0;
+ qi->statusMask = IX_QMGR_Q_STATUS_F_BIT_MASK;
+ break;
+ default:
+ /* Should never hit */
+ IX_OSAL_ASSERT(0);
+ break;
+ }
+
+ /* One nibble of status per queue so need to shift the
+ * check value and mask out to the correct position.
+ */
+ shiftVal = (qId % IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) *
+ IX_QMGR_QUELOWSTAT_BITS_PER_Q;
+
+ /* Calculate the which status word to check from the qId,
+ * 8 Qs status per word
+ */
+ qi->statusWordOffset = qId / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD;
+
+ qi->statusCheckValue <<= shiftVal;
+ qi->statusMask <<= shiftVal;
+ } else {
+ /* One status word */
+ qi->statusWordOffset = 0;
+ /* Single bits per queue and int source bit hardwired NE,
+ * Qs start at 32.
+ */
+ qi->statusMask = 1 << (qId - IX_QMGR_MIN_QUEUPP_QID);
+ qi->statusCheckValue = qi->statusMask;
+ }
+}
+#endif
+
+static void
+aqm_int_enable(struct ixpqmgr_softc *sc, int qId)
+{
+ bus_size_t reg;
+ uint32_t v;
+
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ reg = IX_QMGR_QUEIEREG0_OFFSET;
+ else
+ reg = IX_QMGR_QUEIEREG1_OFFSET;
+ v = aqm_reg_read(sc, reg);
+ aqm_reg_write(sc, reg, v | (1 << (qId % IX_QMGR_MIN_QUEUPP_QID)));
+
+ DPRINTF(sc->sc_dev, "%s(%u) 0x%lx: 0x%x => 0x%x\n",
+ __func__, qId, reg, v, aqm_reg_read(sc, reg));
+}
+
+static void
+aqm_int_disable(struct ixpqmgr_softc *sc, int qId)
+{
+ bus_size_t reg;
+ uint32_t v;
+
+ if (qId < IX_QMGR_MIN_QUEUPP_QID)
+ reg = IX_QMGR_QUEIEREG0_OFFSET;
+ else
+ reg = IX_QMGR_QUEIEREG1_OFFSET;
+ v = aqm_reg_read(sc, reg);
+ aqm_reg_write(sc, reg, v &~ (1 << (qId % IX_QMGR_MIN_QUEUPP_QID)));
+
+ DPRINTF(sc->sc_dev, "%s(%u) 0x%lx: 0x%x => 0x%x\n",
+ __func__, qId, reg, v, aqm_reg_read(sc, reg));
+}
+
+static unsigned
+log2(unsigned n)
+{
+ unsigned count;
+ /*
+ * N.B. this function will return 0 if supplied 0.
+ */
+ for (count = 0; n/2; count++)
+ n /= 2;
+ return count;
+}
+
+static __inline unsigned
+toAqmEntrySize(int entrySize)
+{
+ /* entrySize 1("00"),2("01"),4("10") */
+ return log2(entrySize);
+}
+
+static __inline unsigned
+toAqmBufferSize(unsigned bufferSizeInWords)
+{
+ /* bufferSize 16("00"),32("01),64("10"),128("11") */
+ return log2(bufferSizeInWords / IX_QMGR_MIN_BUFFER_SIZE);
+}
+
+static __inline unsigned
+toAqmWatermark(int watermark)
+{
+ /*
+ * Watermarks 0("000"),1("001"),2("010"),4("011"),
+ * 8("100"),16("101"),32("110"),64("111")
+ */
+ return log2(2 * watermark);
+}
+
+static void
+aqm_qcfg(struct ixpqmgr_softc *sc, int qId, u_int ne, u_int nf)
+{
+ const struct qmgrInfo *qi = &sc->qinfo[qId];
+ uint32_t qCfg;
+ uint32_t baseAddress;
+
+ /* Build config register */
+ qCfg = ((toAqmEntrySize(1) & IX_QMGR_ENTRY_SIZE_MASK) <<
+ IX_QMGR_Q_CONFIG_ESIZE_OFFSET)
+ | ((toAqmBufferSize(qi->qSizeInWords) & IX_QMGR_SIZE_MASK) <<
+ IX_QMGR_Q_CONFIG_BSIZE_OFFSET);
+
+ /* baseAddress, calculated relative to start address */
+ baseAddress = sc->aqmFreeSramAddress;
+
+ /* base address must be word-aligned */
+ KASSERT((baseAddress % IX_QMGR_BASE_ADDR_16_WORD_ALIGN) == 0,
+ ("address not word-aligned"));
+
+ /* Now convert to a 16 word pointer as required by QUECONFIG register */
+ baseAddress >>= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
+ qCfg |= baseAddress << IX_QMGR_Q_CONFIG_BADDR_OFFSET;
+
+ /* set watermarks */
+ qCfg |= (toAqmWatermark(ne) << IX_QMGR_Q_CONFIG_NE_OFFSET)
+ | (toAqmWatermark(nf) << IX_QMGR_Q_CONFIG_NF_OFFSET);
+
+ DPRINTF(sc->sc_dev, "%s(%u, %u, %u) 0x%x => 0x%x @ 0x%x\n",
+ __func__, qId, ne, nf,
+ aqm_reg_read(sc, IX_QMGR_Q_CONFIG_ADDR_GET(qId)),
+ qCfg, IX_QMGR_Q_CONFIG_ADDR_GET(qId));
+
+ aqm_reg_write(sc, IX_QMGR_Q_CONFIG_ADDR_GET(qId), qCfg);
+}
+
+static void
+aqm_srcsel_write(struct ixpqmgr_softc *sc, int qId, int sourceId)
+{
+ bus_size_t off;
+ uint32_t v;
+
+ /*
+ * Calculate the register offset; multiple queues split across registers
+ */
+ off = IX_QMGR_INT0SRCSELREG0_OFFSET +
+ ((qId / IX_QMGR_INTSRC_NUM_QUE_PER_WORD) * sizeof(uint32_t));
+
+ v = aqm_reg_read(sc, off);
+ if (off == IX_QMGR_INT0SRCSELREG0_OFFSET && qId == 0) {
+ /* Queue 0 at INT0SRCSELREG should not corrupt the value bit-3 */
+ v |= 0x7;
+ } else {
+ const uint32_t bpq = 32 / IX_QMGR_INTSRC_NUM_QUE_PER_WORD;
+ uint32_t mask;
+ int qshift;
+
+ qshift = (qId & (IX_QMGR_INTSRC_NUM_QUE_PER_WORD-1)) * bpq;
+ mask = ((1 << bpq) - 1) << qshift; /* q's status mask */
+
+ /* merge sourceId */
+ v = (v &~ mask) | ((sourceId << qshift) & mask);
+ }
+
+ DPRINTF(sc->sc_dev, "%s(%u, %u) 0x%x => 0x%x @ 0x%lx\n",
+ __func__, qId, sourceId, aqm_reg_read(sc, off), v, off);
+ aqm_reg_write(sc, off, v);
+}
+
+/*
+ * Reset AQM registers to default values.
+ */
+static void
+aqm_reset(struct ixpqmgr_softc *sc)
+{
+ int i;
+
+ /* Reset queues 0..31 status registers 0..3 */
+ aqm_reg_write(sc, IX_QMGR_QUELOWSTAT0_OFFSET,
+ IX_QMGR_QUELOWSTAT_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_QUELOWSTAT1_OFFSET,
+ IX_QMGR_QUELOWSTAT_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_QUELOWSTAT2_OFFSET,
+ IX_QMGR_QUELOWSTAT_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_QUELOWSTAT3_OFFSET,
+ IX_QMGR_QUELOWSTAT_RESET_VALUE);
+
+ /* Reset underflow/overflow status registers 0..1 */
+ aqm_reg_write(sc, IX_QMGR_QUEUOSTAT0_OFFSET,
+ IX_QMGR_QUEUOSTAT_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_QUEUOSTAT1_OFFSET,
+ IX_QMGR_QUEUOSTAT_RESET_VALUE);
+
+ /* Reset queues 32..63 nearly empty status registers */
+ aqm_reg_write(sc, IX_QMGR_QUEUPPSTAT0_OFFSET,
+ IX_QMGR_QUEUPPSTAT0_RESET_VALUE);
+
+ /* Reset queues 32..63 full status registers */
+ aqm_reg_write(sc, IX_QMGR_QUEUPPSTAT1_OFFSET,
+ IX_QMGR_QUEUPPSTAT1_RESET_VALUE);
+
+ /* Reset int0 status flag source select registers 0..3 */
+ aqm_reg_write(sc, IX_QMGR_INT0SRCSELREG0_OFFSET,
+ IX_QMGR_INT0SRCSELREG_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_INT0SRCSELREG1_OFFSET,
+ IX_QMGR_INT0SRCSELREG_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_INT0SRCSELREG2_OFFSET,
+ IX_QMGR_INT0SRCSELREG_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_INT0SRCSELREG3_OFFSET,
+ IX_QMGR_INT0SRCSELREG_RESET_VALUE);
+
+ /* Reset queue interrupt enable register 0..1 */
+ aqm_reg_write(sc, IX_QMGR_QUEIEREG0_OFFSET,
+ IX_QMGR_QUEIEREG_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_QUEIEREG1_OFFSET,
+ IX_QMGR_QUEIEREG_RESET_VALUE);
+
+ /* Reset queue interrupt register 0..1 */
+ aqm_reg_write(sc, IX_QMGR_QINTREG0_OFFSET, IX_QMGR_QINTREG_RESET_VALUE);
+ aqm_reg_write(sc, IX_QMGR_QINTREG1_OFFSET, IX_QMGR_QINTREG_RESET_VALUE);
+
+ /* Reset queue configuration words 0..63 */
+ for (i = 0; i < IX_QMGR_MAX_NUM_QUEUES; i++)
+ aqm_reg_write(sc, sc->qinfo[i].qConfigRegAddr,
+ IX_QMGR_QUECONFIG_RESET_VALUE);
+
+ /* XXX zero SRAM to simplify debugging */
+ for (i = IX_QMGR_QUEBUFFER_SPACE_OFFSET;
+ i < IX_QMGR_AQM_SRAM_SIZE_IN_BYTES; i += sizeof(uint32_t))
+ aqm_reg_write(sc, i, 0);
+}
+
+static device_method_t ixpqmgr_methods[] = {
+ DEVMETHOD(device_probe, ixpqmgr_probe),
+ DEVMETHOD(device_attach, ixpqmgr_attach),
+ DEVMETHOD(device_detach, ixpqmgr_detach),
+
+ { 0, 0 }
+};
+
+static driver_t ixpqmgr_driver = {
+ "ixpqmgr",
+ ixpqmgr_methods,
+ sizeof(struct ixpqmgr_softc),
+};
+static devclass_t ixpqmgr_devclass;
+
+DRIVER_MODULE(ixpqmgr, ixp, ixpqmgr_driver, ixpqmgr_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_qmgr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_qmgr.h
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_qmgr.h (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_qmgr.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,246 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_qmgr.h 236987 2012-06-13 04:38:09Z imp $
+ */
+
+/*-
+ * Copyright (c) 2001-2005, Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+*/
+
+#ifndef ARM_XSCALE_IXP425_QMGR_H
+#define ARM_XSCALE_IXP425_QMGR_H
+
+#define IX_QMGR_MAX_NUM_QUEUES 64
+#define IX_QMGR_MIN_QUEUPP_QID 32
+
+#define IX_QMGR_MIN_ENTRY_SIZE_IN_WORDS 16
+
+/* Total size of SRAM */
+#define IX_QMGR_AQM_SRAM_SIZE_IN_BYTES 0x4000
+
+#define IX_QMGR_Q_PRIORITY_0 0
+#define IX_QMGR_Q_PRIORITY_1 1
+#define IX_QMGR_Q_PRIORITY_2 2
+#define IX_QMGR_NUM_PRIORITY_LEVELS 3 /* number of priority levels */
+
+#define IX_QMGR_Q_STATUS_E_BIT_MASK 0x1 /* Empty */
+#define IX_QMGR_Q_STATUS_NE_BIT_MASK 0x2 /* Nearly Empty */
+#define IX_QMGR_Q_STATUS_NF_BIT_MASK 0x4 /* Nearly Full */
+#define IX_QMGR_Q_STATUS_F_BIT_MASK 0x8 /* Full */
+#define IX_QMGR_Q_STATUS_UF_BIT_MASK 0x10 /* Underflow */
+#define IX_QMGR_Q_STATUS_OF_BIT_MASK 0x20 /* Overflow */
+
+#define IX_QMGR_Q_SOURCE_ID_E 0 /* Q Empty after last read */
+#define IX_QMGR_Q_SOURCE_ID_NE 1 /* Q Nearly Empty after last read */
+#define IX_QMGR_Q_SOURCE_ID_NF 2 /* Q Nearly Full after last write */
+#define IX_QMGR_Q_SOURCE_ID_F 3 /* Q Full after last write */
+#define IX_QMGR_Q_SOURCE_ID_NOT_E 4 /* Q !Empty after last write */
+#define IX_QMGR_Q_SOURCE_ID_NOT_NE 5 /* Q !Nearly Empty after last write */
+#define IX_QMGR_Q_SOURCE_ID_NOT_NF 6 /* Q !Nearly Full after last read */
+#define IX_QMGR_Q_SOURCE_ID_NOT_F 7 /* Q !Full after last read */
+
+#define IX_QMGR_UNDERFLOW_BIT_OFFSET 0x0 /* underflow bit mask */
+#define IX_QMGR_OVERFLOW_BIT_OFFSET 0x1 /* overflow bit mask */
+
+#define IX_QMGR_QUEACC0_OFFSET 0x0000 /* q 0 access register */
+#define IX_QMGR_QUEACC_SIZE 0x4/*words*/
+
+#define IX_QMGR_QUELOWSTAT0_OFFSET 0x400 /* Q status, q's 0-7 */
+#define IX_QMGR_QUELOWSTAT1_OFFSET 0x404 /* Q status, q's 8-15 */
+#define IX_QMGR_QUELOWSTAT2_OFFSET 0x408 /* Q status, q's 16-23 */
+#define IX_QMGR_QUELOWSTAT3_OFFSET 0x40c /* Q status, q's 24-31 */
+
+/* Queue status register Q status bits mask */
+#define IX_QMGR_QUELOWSTAT_QUE_STS_BITS_MASK 0xF
+/* Size of queue 0-31 status register */
+#define IX_QMGR_QUELOWSTAT_SIZE 0x4 /*words*/
+#define IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD 8 /* # status/word */
+
+#define IX_QMGR_QUEUOSTAT0_OFFSET 0x410 /* Q UF/OF status, q's 0-15 */
+#define IX_QMGR_QUEUOSTAT1_OFFSET 0x414 /* Q UF/OF status, q's 16-31 */
+
+#define IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD 16 /* # UF/OF status/word */
+
+#define IX_QMGR_QUEUPPSTAT0_OFFSET 0x418 /* NE status, q's 32-63 */
+#define IX_QMGR_QUEUPPSTAT1_OFFSET 0x41c /* F status, q's 32-63 */
+
+#define IX_QMGR_INT0SRCSELREG0_OFFSET 0x420 /* INT src select, q's 0-7 */
+#define IX_QMGR_INT0SRCSELREG1_OFFSET 0x424 /* INT src select, q's 8-15 */
+#define IX_QMGR_INT0SRCSELREG2_OFFSET 0x428 /* INT src select, q's 16-23 */
+#define IX_QMGR_INT0SRCSELREG3_OFFSET 0x42c /* INT src select, q's 24-31 */
+
+#define IX_QMGR_INTSRC_NUM_QUE_PER_WORD 8 /* # INT src select/word */
+
+#define IX_QMGR_QUEIEREG0_OFFSET 0x430 /* INT enable, q's 0-31 */
+#define IX_QMGR_QUEIEREG1_OFFSET 0x434 /* INT enable, q's 32-63 */
+#define IX_QMGR_QINTREG0_OFFSET 0x438 /* INT status, q's 0-31 */
+#define IX_QMGR_QINTREG1_OFFSET 0x43c /* INT status, q's 32-63 */
+
+#define IX_QMGR_QUECONFIG_BASE_OFFSET 0x2000 /* Q config register, q 0 */
+
+#define IX_QMGR_QUECONFIG_SIZE 0x100 /* total size of Q config regs*/
+
+#define IX_QMGR_QUEBUFFER_SPACE_OFFSET 0x2100 /* start of SRAM */
+
+/* Total bits in a word */
+#define BITS_PER_WORD 32
+
+/* Size of queue buffer space */
+#define IX_QMGR_QUE_BUFFER_SPACE_SIZE 0x1F00
+
+/*
+ * This macro will return the address of the access register for the
+ * queue specified by qId
+ */
+#define IX_QMGR_Q_ACCESS_ADDR_GET(qId)\
+ (((qId) * (IX_QMGR_QUEACC_SIZE * sizeof(uint32_t)))\
+ + IX_QMGR_QUEACC0_OFFSET)
+
+/*
+ * Bit location of bit-3 of INT0SRCSELREG0 register to enabled
+ * sticky interrupt register.
+ */
+#define IX_QMGR_INT0SRCSELREG0_BIT3 3
+
+/*
+ * These defines are the bit offsets of the various fields of
+ * the queue configuration register.
+ */
+#if 0
+#define IX_QMGR_Q_CONFIG_WRPTR_OFFSET 0x00
+#define IX_QMGR_Q_CONFIG_RDPTR_OFFSET 0x07
+#define IX_QMGR_Q_CONFIG_BADDR_OFFSET 0x0E
+#define IX_QMGR_Q_CONFIG_ESIZE_OFFSET 0x16
+#define IX_QMGR_Q_CONFIG_BSIZE_OFFSET 0x18
+#define IX_QMGR_Q_CONFIG_NE_OFFSET 0x1A
+#define IX_QMGR_Q_CONFIG_NF_OFFSET 0x1D
+
+#define IX_QMGR_NE_NF_CLEAR_MASK 0x03FFFFFF
+#define IX_QMGR_NE_MASK 0x7
+#define IX_QMGR_NF_MASK 0x7
+#define IX_QMGR_SIZE_MASK 0x3
+#define IX_QMGR_ENTRY_SIZE_MASK 0x3
+#define IX_QMGR_BADDR_MASK 0x003FC000
+#define IX_QMGR_RDPTR_MASK 0x7F
+#define IX_QMGR_WRPTR_MASK 0x7F
+#define IX_QMGR_RDWRPTR_MASK 0x00003FFF
+#else
+#define IX_QMGR_Q_CONFIG_WRPTR_OFFSET 0
+#define IX_QMGR_WRPTR_MASK 0x7F
+#define IX_QMGR_Q_CONFIG_RDPTR_OFFSET 7
+#define IX_QMGR_RDPTR_MASK 0x7F
+#define IX_QMGR_Q_CONFIG_BADDR_OFFSET 14
+#define IX_QMGR_BADDR_MASK 0x3FC000 /* XXX not used */
+#define IX_QMGR_Q_CONFIG_ESIZE_OFFSET 22
+#define IX_QMGR_ENTRY_SIZE_MASK 0x3
+#define IX_QMGR_Q_CONFIG_BSIZE_OFFSET 24
+#define IX_QMGR_SIZE_MASK 0x3
+#define IX_QMGR_Q_CONFIG_NE_OFFSET 26
+#define IX_QMGR_NE_MASK 0x7
+#define IX_QMGR_Q_CONFIG_NF_OFFSET 29
+#define IX_QMGR_NF_MASK 0x7
+
+#define IX_QMGR_RDWRPTR_MASK 0x00003FFF
+#define IX_QMGR_NE_NF_CLEAR_MASK 0x03FFFFFF
+#endif
+
+#define IX_QMGR_BASE_ADDR_16_WORD_ALIGN 64
+#define IX_QMGR_BASE_ADDR_16_WORD_SHIFT 6
+
+#define IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS 0x1000
+
+/* Base address of AQM SRAM */
+#define IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET \
+((IX_QMGR_QUECONFIG_BASE_OFFSET) + (IX_QMGR_QUECONFIG_SIZE))
+
+/* Min buffer size used for generating buffer size in QUECONFIG */
+#define IX_QMGR_MIN_BUFFER_SIZE 16
+
+/* Reset values of QMgr hardware registers */
+#define IX_QMGR_QUELOWSTAT_RESET_VALUE 0x33333333
+#define IX_QMGR_QUEUOSTAT_RESET_VALUE 0x00000000
+#define IX_QMGR_QUEUPPSTAT0_RESET_VALUE 0xFFFFFFFF
+#define IX_QMGR_QUEUPPSTAT1_RESET_VALUE 0x00000000
+#define IX_QMGR_INT0SRCSELREG_RESET_VALUE 0x00000000
+#define IX_QMGR_QUEIEREG_RESET_VALUE 0x00000000
+#define IX_QMGR_QINTREG_RESET_VALUE 0xFFFFFFFF
+#define IX_QMGR_QUECONFIG_RESET_VALUE 0x00000000
+
+#define IX_QMGR_QUELOWSTAT_BITS_PER_Q \
+ (BITS_PER_WORD/IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)
+
+#define IX_QMGR_QUELOWSTAT_QID_MASK 0x7
+#define IX_QMGR_Q_CONFIG_ADDR_GET(qId)\
+ (((qId) * sizeof(uint32_t)) + IX_QMGR_QUECONFIG_BASE_OFFSET)
+
+#define IX_QMGR_ENTRY1_OFFSET 0
+#define IX_QMGR_ENTRY2_OFFSET 1
+#define IX_QMGR_ENTRY4_OFFSET 3
+
+typedef void qconfig_hand_t(int, void *);
+
+int ixpqmgr_qconfig(int qId, int qSizeInWords, int ne, int nf, int srcSel,
+ qconfig_hand_t *cb, void *cbarg);
+int ixpqmgr_qwrite(int qId, uint32_t entry);
+int ixpqmgr_qread(int qId, uint32_t *entry);
+int ixpqmgr_qreadm(int qId, uint32_t n, uint32_t *p);
+uint32_t ixpqmgr_getqstatus(int qId);
+uint32_t ixpqmgr_getqconfig(int qId);
+void ixpqmgr_notify_enable(int qId, int srcSel);
+void ixpqmgr_notify_disable(int qId);
+void ixpqmgr_dump(void);
+
+#endif /* ARM_XSCALE_IXP425_QMGR_H */
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_qmgr.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_space.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_space.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_space.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,130 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_space.c,v 1.6 2006/04/10 03:36:03 simonb Exp $ */
+
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_space.c 278727 2015-02-13 22:32:02Z ian $");
+
+/*
+ * bus_space I/O functions for ixp425
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/pcb.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+/* Proto types for all the bus_space structure functions */
+bs_protos(generic);
+
+struct bus_space ixp425_bs_tag = {
+ /* cookie */
+ .bs_privdata = (void *) 0,
+
+ /* mapping/unmapping */
+ .bs_map = generic_bs_map,
+ .bs_unmap = generic_bs_unmap,
+ .bs_subregion = generic_bs_subregion,
+
+ /* allocation/deallocation */
+ .bs_alloc = generic_bs_alloc,
+ .bs_free = generic_bs_free,
+
+ /* barrier */
+ .bs_barrier = generic_bs_barrier,
+
+ /* read (single) */
+ .bs_r_1 = generic_bs_r_1,
+ .bs_r_2 = generic_bs_r_2,
+ .bs_r_4 = generic_bs_r_4,
+ .bs_r_8 = NULL,
+
+ /* read multiple */
+ .bs_rm_1 = generic_bs_rm_1,
+ .bs_rm_2 = generic_bs_rm_2,
+ .bs_rm_4 = generic_bs_rm_4,
+ .bs_rm_8 = NULL,
+
+ /* read region */
+ .bs_rr_1 = generic_bs_rr_1,
+ .bs_rr_2 = generic_bs_rr_2,
+ .bs_rr_4 = generic_bs_rr_4,
+ .bs_rr_8 = NULL,
+
+ /* write (single) */
+ .bs_w_1 = generic_bs_w_1,
+ .bs_w_2 = generic_bs_w_2,
+ .bs_w_4 = generic_bs_w_4,
+ .bs_w_8 = NULL,
+
+ /* write multiple */
+ .bs_wm_1 = generic_bs_wm_1,
+ .bs_wm_2 = generic_bs_wm_2,
+ .bs_wm_4 = generic_bs_wm_4,
+ .bs_wm_8 = NULL,
+
+ /* write region */
+ .bs_wr_1 = generic_bs_wr_1,
+ .bs_wr_2 = generic_bs_wr_2,
+ .bs_wr_4 = generic_bs_wr_4,
+ .bs_wr_8 = NULL,
+
+ /* set multiple */
+ /* XXX not implemented */
+
+ /* set region */
+ .bs_sr_1 = NULL,
+ .bs_sr_2 = generic_bs_sr_2,
+ .bs_sr_4 = generic_bs_sr_4,
+ .bs_sr_8 = NULL,
+
+ /* copy */
+ .bs_c_1 = NULL,
+ .bs_c_2 = generic_bs_c_2,
+ .bs_c_4 = NULL,
+ .bs_c_8 = NULL,
+};
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_space.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_timer.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_timer.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,270 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425_timer.c,v 1.11 2006/04/10 03:36:03 simonb Exp $ */
+
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_timer.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+static uint32_t counts_per_hz;
+
+/* callback functions for intr_functions */
+int ixpclk_intr(void *);
+
+struct ixpclk_softc {
+ device_t sc_dev;
+ bus_addr_t sc_baseaddr;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+static unsigned ixp425_timer_get_timecount(struct timecounter *tc);
+
+#ifndef IXP425_CLOCK_FREQ
+#define COUNTS_PER_SEC 66666600 /* 66MHz */
+#else
+#define COUNTS_PER_SEC IXP425_CLOCK_FREQ
+#endif
+#define COUNTS_PER_USEC ((COUNTS_PER_SEC / 1000000) + 1)
+
+static struct ixpclk_softc *ixpclk_sc = NULL;
+
+#define GET_TS_VALUE(sc) (*(volatile u_int32_t *) \
+ (IXP425_TIMER_VBASE + IXP425_OST_TS))
+
+static struct timecounter ixp425_timer_timecounter = {
+ ixp425_timer_get_timecount, /* get_timecount */
+ NULL, /* no poll_pps */
+ ~0u, /* counter_mask */
+ COUNTS_PER_SEC, /* frequency */
+ "IXP4XX Timer", /* name */
+ 1000, /* quality */
+};
+
+static int
+ixpclk_probe(device_t dev)
+{
+ device_set_desc(dev, "IXP4XX Timer");
+ return (0);
+}
+
+static int
+ixpclk_attach(device_t dev)
+{
+ struct ixpclk_softc *sc = device_get_softc(dev);
+ struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
+
+ ixpclk_sc = sc;
+
+ sc->sc_dev = dev;
+ sc->sc_iot = sa->sc_iot;
+ sc->sc_baseaddr = IXP425_TIMER_HWBASE;
+
+ if (bus_space_map(sc->sc_iot, sc->sc_baseaddr, 8, 0,
+ &sc->sc_ioh))
+ panic("%s: Cannot map registers", device_get_name(dev));
+
+ return (0);
+}
+
+static device_method_t ixpclk_methods[] = {
+ DEVMETHOD(device_probe, ixpclk_probe),
+ DEVMETHOD(device_attach, ixpclk_attach),
+ {0, 0},
+};
+
+static driver_t ixpclk_driver = {
+ "ixpclk",
+ ixpclk_methods,
+ sizeof(struct ixpclk_softc),
+};
+static devclass_t ixpclk_devclass;
+
+DRIVER_MODULE(ixpclk, ixp, ixpclk_driver, ixpclk_devclass, 0, 0);
+static unsigned
+ixp425_timer_get_timecount(struct timecounter *tc)
+{
+ uint32_t ret;
+
+ ret = GET_TS_VALUE(sc);
+ return (ret);
+}
+
+/*
+ * cpu_initclocks:
+ *
+ * Initialize the clock and get them going.
+ */
+void
+cpu_initclocks(void)
+{
+ struct ixpclk_softc* sc = ixpclk_sc;
+ struct resource *irq;
+ device_t dev = sc->sc_dev;
+ u_int oldirqstate;
+ int rid = 0;
+ void *ihl;
+
+ if (hz < 50 || COUNTS_PER_SEC % hz) {
+ printf("Cannot get %d Hz clock; using 100 Hz\n", hz);
+ hz = 100;
+ }
+ tick = 1000000 / hz; /* number of microseconds between interrupts */
+
+ /*
+ * We only have one timer available; stathz and profhz are
+ * always left as 0 (the upper-layer clock code deals with
+ * this situation).
+ */
+ if (stathz != 0)
+ printf("Cannot get %d Hz statclock\n", stathz);
+ stathz = 0;
+
+ if (profhz != 0)
+ printf("Cannot get %d Hz profclock\n", profhz);
+ profhz = 0;
+
+ /* Report the clock frequency. */
+
+ oldirqstate = disable_interrupts(PSR_I);
+
+ irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, IXP425_INT_TMR0,
+ IXP425_INT_TMR0, 1, RF_ACTIVE);
+ if (!irq)
+ panic("Unable to setup the clock irq handler.\n");
+ else
+ bus_setup_intr(dev, irq, INTR_TYPE_CLK, ixpclk_intr, NULL,
+ NULL, &ihl);
+
+ /* Set up the new clock parameters. */
+
+ /* clear interrupt */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS,
+ OST_WARM_RESET | OST_WDOG_INT | OST_TS_INT |
+ OST_TIM1_INT | OST_TIM0_INT);
+
+ counts_per_hz = COUNTS_PER_SEC / hz;
+
+ /* reload value & Timer enable */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_TIM0_RELOAD,
+ (counts_per_hz & TIMERRELOAD_MASK) | OST_TIMER_EN);
+
+ tc_init(&ixp425_timer_timecounter);
+ restore_interrupts(oldirqstate);
+ rid = 0;
+}
+
+
+/*
+ * DELAY:
+ *
+ * Delay for at least N microseconds.
+ */
+void
+DELAY(int n)
+{
+ u_int32_t first, last;
+ int usecs;
+
+ if (n == 0)
+ return;
+
+ /*
+ * Clamp the timeout at a maximum value (about 32 seconds with
+ * a 66MHz clock). *Nobody* should be delay()ing for anywhere
+ * near that length of time and if they are, they should be hung
+ * out to dry.
+ */
+ if (n >= (0x80000000U / COUNTS_PER_USEC))
+ usecs = (0x80000000U / COUNTS_PER_USEC) - 1;
+ else
+ usecs = n * COUNTS_PER_USEC;
+
+ /* Note: Timestamp timer counts *up*, unlike the other timers */
+ first = GET_TS_VALUE();
+
+ while (usecs > 0) {
+ last = GET_TS_VALUE();
+ usecs -= (int)(last - first);
+ first = last;
+ }
+}
+
+/*
+ * ixpclk_intr:
+ *
+ * Handle the hardclock interrupt.
+ */
+int
+ixpclk_intr(void *arg)
+{
+ struct ixpclk_softc* sc = ixpclk_sc;
+ struct trapframe *frame = arg;
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS,
+ OST_TIM0_INT);
+
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+ return (FILTER_HANDLED);
+}
+
+void
+cpu_startprofclock(void)
+{
+}
+
+void
+cpu_stopprofclock(void)
+{
+}
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425_wdog.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425_wdog.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425_wdog.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,118 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Sam Leffler. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425_wdog.c 259329 2013-12-13 20:43:11Z ian $");
+
+/*
+ * IXP4XX Watchdog Timer Support.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/watchdog.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+struct ixpwdog_softc {
+ device_t sc_dev;
+};
+
+static __inline uint32_t
+RD4(struct ixpwdog_softc *sc, bus_size_t off)
+{
+ return bus_space_read_4(&ixp425_bs_tag, IXP425_TIMER_VBASE, off);
+}
+
+static __inline void
+WR4(struct ixpwdog_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_space_write_4(&ixp425_bs_tag, IXP425_TIMER_VBASE, off, val);
+}
+
+static void
+ixp425_watchdog(void *arg, u_int cmd, int *error)
+{
+ struct ixpwdog_softc *sc = arg;
+ u_int u = cmd & WD_INTERVAL;
+
+ WR4(sc, IXP425_OST_WDOG_KEY, OST_WDOG_KEY_MAJICK);
+ if (4 <= u && u <= 35) {
+ WR4(sc, IXP425_OST_WDOG_ENAB, 0);
+ /* approximate 66.66MHz cycles */
+ WR4(sc, IXP425_OST_WDOG, 2<<(u - 4));
+ /* NB: reset on timer expiration */
+ WR4(sc, IXP425_OST_WDOG_ENAB,
+ OST_WDOG_ENAB_CNT_ENA | OST_WDOG_ENAB_RST_ENA);
+ *error = 0;
+ } else {
+ /* disable watchdog */
+ WR4(sc, IXP425_OST_WDOG_ENAB, 0);
+ }
+ WR4(sc, IXP425_OST_WDOG_KEY, 0);
+}
+
+static int
+ixpwdog_probe(device_t dev)
+{
+ device_set_desc(dev, "IXP4XX Watchdog Timer");
+ return (0);
+}
+
+static int
+ixpwdog_attach(device_t dev)
+{
+ struct ixpwdog_softc *sc = device_get_softc(dev);
+
+ sc->sc_dev = dev;
+
+ EVENTHANDLER_REGISTER(watchdog_list, ixp425_watchdog, sc, 0);
+ return (0);
+}
+
+static device_method_t ixpwdog_methods[] = {
+ DEVMETHOD(device_probe, ixpwdog_probe),
+ DEVMETHOD(device_attach, ixpwdog_attach),
+ {0, 0},
+};
+
+static driver_t ixpwdog_driver = {
+ "ixpwdog",
+ ixpwdog_methods,
+ sizeof(struct ixpwdog_softc),
+};
+static devclass_t ixpwdog_devclass;
+DRIVER_MODULE(ixpwdog, ixp, ixpwdog_driver, ixpwdog_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425_wdog.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425reg.h
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425reg.h (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425reg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,715 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425reg.h,v 1.19 2005/12/11 12:16:51 christos Exp $ */
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425reg.h 261455 2014-02-04 03:36:42Z eadler $
+ *
+ */
+
+#ifndef _IXP425REG_H_
+#define _IXP425REG_H_
+
+/*
+ * Physical memory map for the Intel IXP425
+ */
+/*
+ * CC00 00FF ---------------------------
+ * SDRAM Configuration Registers
+ * CC00 0000 ---------------------------
+ *
+ * C800 BFFF ---------------------------
+ * System and Peripheral Registers
+ * C800 0000 ---------------------------
+ * Expansion Bus Configuration Registers
+ * C400 0000 ---------------------------
+ * PCI Configuration and Status Registers
+ * C000 0000 ---------------------------
+ *
+ * 6400 0000 ---------------------------
+ * Queue manager
+ * 6000 0000 ---------------------------
+ * Expansion Bus Data
+ * 5000 0000 ---------------------------
+ * PCI Data
+ * 4800 0000 ---------------------------
+ *
+ * 4000 0000 ---------------------------
+ * SDRAM
+ * 0000 0000 ---------------------------
+ */
+
+/*
+ * Virtual memory map for the Intel IXP425/IXP435 integrated devices
+ */
+/*
+ * FFFF FFFF ---------------------------
+ *
+ * Global cache clean area
+ * FF00 0000 ---------------------------
+ *
+ * FE00 0000 ---------------------------
+ * 16M CFI Flash (on ext bus)
+ * FD00 0000 ---------------------------
+ *
+ * FC00 0000 ---------------------------
+ * PCI Data (memory space)
+ * F800 0000 --------------------------- IXP425_PCI_MEM_VBASE
+ *
+ * F020 1000 ---------------------------
+ * SDRAM/DDR Memory Controller
+ * F020 0000 --------------------------- IXP425_MCU_VBASE
+ *
+ * F001 F000 RS485 (Cambria) CAMBRIA_RS485_VBASE
+ * F001 E000 GPS (Cambria) CAMBRIA_GPS_VBASE
+ * F001 D000 EHCI USB 2 (IXP435) IXP435_USB2_VBASE
+ * F001 C000 EHCI USB 1 (IXP435) IXP435_USB1_VBASE
+ * Queue manager
+ * F001 8000 --------------------------- IXP425_QMGR_VBASE
+ * PCI Configuration and Status
+ * F001 7000 --------------------------- IXP425_PCI_VBASE
+ *
+ * (NB: gap for future addition of EXP CS5-7)
+ * F001 4000 Expansion Bus Chip Select 4
+ * F001 3000 Expansion Bus Chip Select 3
+ * F001 2000 Expansion Bus Chip Select 2
+ * F001 1000 Expansion Bus Chip Select 1
+ * Expansion Bus Configuration
+ * F001 0000 --------------------------- IXP425_EXP_VBASE
+ *
+ * F000 C000 MAC-A (IXP435)
+ * F000 B000 USB (option on IXP425)
+ * F000 A000 MAC-B (IXP425) | MAC-C (IXP435)
+ * F000 9000 MAC-A (IXP425)
+ * F000 8000 NPE-C
+ * F000 7000 NPE-B (IXP425)
+ * F000 6000 NPE-A
+ * F000 5000 Timers
+ * F000 4000 GPIO Controller
+ * F000 3000 Interrupt Controller
+ * F000 2000 Performance Monitor Controller (PMC)
+ * F000 1000 UART 1 (IXP425)
+ * F000 0000 UART 0
+ * F000 0000 --------------------------- IXP425_IO_VBASE
+ *
+ * 0000 0000 ---------------------------
+ *
+ */
+
+/* Physical/Virtual address for I/O space */
+
+#define IXP425_IO_VBASE 0xf0000000UL
+#define IXP425_IO_HWBASE 0xc8000000UL
+#define IXP425_IO_SIZE 0x00010000UL
+
+/* Physical/Virtual addresss offsets */
+#define IXP425_UART0_OFFSET 0x00000000UL
+#define IXP425_UART1_OFFSET 0x00001000UL
+#define IXP425_PMC_OFFSET 0x00002000UL
+#define IXP425_INTR_OFFSET 0x00003000UL
+#define IXP425_GPIO_OFFSET 0x00004000UL
+#define IXP425_TIMER_OFFSET 0x00005000UL
+#define IXP425_NPE_A_OFFSET 0x00006000UL /* Not User Programmable */
+#define IXP425_NPE_B_OFFSET 0x00007000UL /* Not User Programmable */
+#define IXP425_NPE_C_OFFSET 0x00008000UL /* Not User Programmable */
+#define IXP425_MAC_B_OFFSET 0x00009000UL /* Ethernet MAC on NPE-B */
+#define IXP425_MAC_C_OFFSET 0x0000a000UL /* Ethernet MAC on NPE-C */
+#define IXP425_USB_OFFSET 0x0000b000UL
+
+#define IXP435_MAC_A_OFFSET 0x0000c000UL /* Ethernet MAC on NPE-A */
+
+#define IXP425_REG_SIZE 0x1000
+
+/*
+ * UART
+ * UART0 0xc8000000
+ * UART1 0xc8001000
+ *
+ */
+/* I/O space */
+#define IXP425_UART0_HWBASE (IXP425_IO_HWBASE + IXP425_UART0_OFFSET)
+#define IXP425_UART1_HWBASE (IXP425_IO_HWBASE + IXP425_UART1_OFFSET)
+
+#define IXP425_UART0_VBASE (IXP425_IO_VBASE + IXP425_UART0_OFFSET)
+ /* 0xf0000000 */
+#define IXP425_UART1_VBASE (IXP425_IO_VBASE + IXP425_UART1_OFFSET)
+ /* 0xf0001000 */
+
+#define IXP425_UART_FREQ 14745600
+
+#define IXP425_UART_IER 0x01 /* interrupt enable register */
+#define IXP425_UART_IER_RTOIE 0x10 /* receiver timeout interrupt enable */
+#define IXP425_UART_IER_UUE 0x40 /* UART Unit enable */
+
+/*#define IXP4XX_COM_NPORTS 8*/
+
+/*
+ * Timers
+ */
+#define IXP425_TIMER_HWBASE (IXP425_IO_HWBASE + IXP425_TIMER_OFFSET)
+#define IXP425_TIMER_VBASE (IXP425_IO_VBASE + IXP425_TIMER_OFFSET)
+
+#define IXP425_OST_TS 0x0000
+#define IXP425_OST_TIM0 0x0004
+#define IXP425_OST_TIM1 0x000C
+
+#define IXP425_OST_TIM0_RELOAD 0x0008
+#define IXP425_OST_TIM1_RELOAD 0x0010
+#define TIMERRELOAD_MASK 0xFFFFFFFC
+#define OST_ONESHOT_EN (1U << 1)
+#define OST_TIMER_EN (1U << 0)
+
+#define IXP425_OST_STATUS 0x0020
+#define OST_WARM_RESET (1U << 4)
+#define OST_WDOG_INT (1U << 3)
+#define OST_TS_INT (1U << 2)
+#define OST_TIM1_INT (1U << 1)
+#define OST_TIM0_INT (1U << 0)
+
+#define IXP425_OST_WDOG 0x0014
+#define IXP425_OST_WDOG_ENAB 0x0018
+#define IXP425_OST_WDOG_KEY 0x001c
+#define OST_WDOG_KEY_MAJICK 0x482e
+#define OST_WDOG_ENAB_RST_ENA (1u << 0)
+#define OST_WDOG_ENAB_INT_ENA (1u << 1)
+#define OST_WDOG_ENAB_CNT_ENA (1u << 2)
+
+/*
+ * Interrupt Controller Unit.
+ * PA 0xc8003000
+ */
+
+#define IXP425_IRQ_HWBASE IXP425_IO_HWBASE + IXP425_INTR_OFFSET
+#define IXP425_IRQ_VBASE IXP425_IO_VBASE + IXP425_INTR_OFFSET
+ /* 0xf0003000 */
+#define IXP425_IRQ_SIZE 0x00000020UL
+
+#define IXP425_INT_STATUS (IXP425_IRQ_VBASE + 0x00)
+#define IXP425_INT_ENABLE (IXP425_IRQ_VBASE + 0x04)
+#define IXP425_INT_SELECT (IXP425_IRQ_VBASE + 0x08)
+#define IXP425_IRQ_STATUS (IXP425_IRQ_VBASE + 0x0C)
+#define IXP425_FIQ_STATUS (IXP425_IRQ_VBASE + 0x10)
+#define IXP425_INT_PRTY (IXP425_IRQ_VBASE + 0x14)
+#define IXP425_IRQ_ENC (IXP425_IRQ_VBASE + 0x18)
+#define IXP425_FIQ_ENC (IXP425_IRQ_VBASE + 0x1C)
+
+#define IXP425_INT_SW1 31 /* SW Interrupt 1 */
+#define IXP425_INT_SW0 30 /* SW Interrupt 0 */
+#define IXP425_INT_GPIO_12 29 /* GPIO 12 */
+#define IXP425_INT_GPIO_11 28 /* GPIO 11 */
+#define IXP425_INT_GPIO_10 27 /* GPIO 11 */
+#define IXP425_INT_GPIO_9 26 /* GPIO 9 */
+#define IXP425_INT_GPIO_8 25 /* GPIO 8 */
+#define IXP425_INT_GPIO_7 24 /* GPIO 7 */
+#define IXP425_INT_GPIO_6 23 /* GPIO 6 */
+#define IXP425_INT_GPIO_5 22 /* GPIO 5 */
+#define IXP425_INT_GPIO_4 21 /* GPIO 4 */
+#define IXP425_INT_GPIO_3 20 /* GPIO 3 */
+#define IXP425_INT_GPIO_2 19 /* GPIO 2 */
+#define IXP425_INT_XSCALE_PMU 18 /* XScale PMU */
+#define IXP425_INT_AHB_PMU 17 /* AHB PMU */
+#define IXP425_INT_WDOG 16 /* Watchdog Timer */
+#define IXP425_INT_UART0 15 /* HighSpeed UART */
+#define IXP425_INT_STAMP 14 /* Timestamp Timer */
+#define IXP425_INT_UART1 13 /* Console UART */
+#define IXP425_INT_USB 12 /* USB */
+#define IXP425_INT_TMR1 11 /* General-Purpose Timer1 */
+#define IXP425_INT_PCIDMA2 10 /* PCI DMA Channel 2 */
+#define IXP425_INT_PCIDMA1 9 /* PCI DMA Channel 1 */
+#define IXP425_INT_PCIINT 8 /* PCI Interrupt */
+#define IXP425_INT_GPIO_1 7 /* GPIO 1 */
+#define IXP425_INT_GPIO_0 6 /* GPIO 0 */
+#define IXP425_INT_TMR0 5 /* General-Purpose Timer0 */
+#define IXP425_INT_QUE33_64 4 /* Queue Manager 33-64 */
+#define IXP425_INT_QUE1_32 3 /* Queue Manager 1-32 */
+#define IXP425_INT_NPE_C 2 /* NPE C */
+#define IXP425_INT_NPE_B 1 /* NPE B */
+#define IXP425_INT_NPE_A 0 /* NPE A */
+
+/* NB: IXP435 has an additional 32 IRQ's */
+#define IXP435_INT_STATUS2 (IXP425_IRQ_VBASE + 0x20)
+#define IXP435_INT_ENABLE2 (IXP425_IRQ_VBASE + 0x24)
+#define IXP435_INT_SELECT2 (IXP425_IRQ_VBASE + 0x28)
+#define IXP435_IRQ_STATUS2 (IXP425_IRQ_VBASE + 0x2C)
+#define IXP435_FIQ_STATUS2 (IXP425_IRQ_VBASE + 0x30)
+
+#define IXP435_INT_USB0 32 /* USB Host 2.0 Host 0 */
+#define IXP435_INT_USB1 33 /* USB Host 2.0 Host 1 */
+#define IXP435_INT_QMGR_PER 60 /* Queue manager parity error */
+#define IXP435_INT_ECC 61 /* Single or multi-bit ECC error */
+
+/*
+ * software interrupt
+ */
+#define IXP425_INT_bit31 31
+#define IXP425_INT_bit30 30
+#define IXP425_INT_bit14 14
+#define IXP425_INT_bit11 11
+
+#define IXP425_INT_HWMASK (0xffffffff & \
+ ~((1 << IXP425_INT_bit31) | \
+ (1 << IXP425_INT_bit30) | \
+ (1 << IXP425_INT_bit14) | \
+ (1 << IXP425_INT_bit11)))
+#define IXP425_INT_GPIOMASK (0x3ff800c0u)
+
+#define IXP435_INT_HWMASK ((1 << (IXP435_INT_USB0 - 32)) | \
+ (1 << (IXP435_INT_USB1 - 32)) | \
+ (1 << (IXP435_INT_QMGR_PER - 32)) | \
+ (1 << (IXP435_INT_ECC - 32)))
+
+/*
+ * GPIO
+ */
+#define IXP425_GPIO_HWBASE IXP425_IO_HWBASE + IXP425_GPIO_OFFSET
+#define IXP425_GPIO_VBASE IXP425_IO_VBASE + IXP425_GPIO_OFFSET
+ /* 0xf0004000 */
+#define IXP425_GPIO_SIZE 0x00000020UL
+
+#define IXP425_GPIO_GPOUTR 0x00
+#define IXP425_GPIO_GPOER 0x04
+#define IXP425_GPIO_GPINR 0x08
+#define IXP425_GPIO_GPISR 0x0c
+#define IXP425_GPIO_GPIT1R 0x10
+#define IXP425_GPIO_GPIT2R 0x14
+#define IXP425_GPIO_GPCLKR 0x18
+# define GPCLKR_MUX14 (1U << 8)
+# define GPCLKR_CLK0TC_SHIFT 4
+# define GPCLKR_CLK0DC_SHIFT 0
+
+/* GPIO Output */
+#define GPOUT_ON 0x1
+#define GPOUT_OFF 0x0
+
+/* GPIO direction */
+#define GPOER_INPUT 0x1
+#define GPOER_OUTPUT 0x0
+
+/* GPIO Type bits */
+#define GPIO_TYPE_ACT_HIGH 0x0
+#define GPIO_TYPE_ACT_LOW 0x1
+#define GPIO_TYPE_EDG_RISING 0x2
+#define GPIO_TYPE_EDG_FALLING 0x3
+#define GPIO_TYPE_TRANSITIONAL 0x4
+#define GPIO_TYPE_MASK 0x7
+#define GPIO_TYPE(b,v) ((v) << (((b) & 0x7) * 3))
+#define GPIO_TYPE_REG(b) (((b)&8)?IXP425_GPIO_GPIT2R:IXP425_GPIO_GPIT1R)
+
+#define IXP4XX_GPIO_PINS 16
+
+/*
+ * Expansion Bus Configuration Space.
+ */
+#define IXP425_EXP_HWBASE 0xc4000000UL
+#define IXP425_EXP_VBASE 0xf0010000UL
+#define IXP425_EXP_SIZE 0x1000
+
+/* offset */
+#define EXP_TIMING_CS0_OFFSET 0x0000
+#define EXP_TIMING_CS1_OFFSET 0x0004
+#define EXP_TIMING_CS2_OFFSET 0x0008
+#define EXP_TIMING_CS3_OFFSET 0x000c
+#define EXP_TIMING_CS4_OFFSET 0x0010
+#define EXP_TIMING_CS5_OFFSET 0x0014
+#define EXP_TIMING_CS6_OFFSET 0x0018
+#define EXP_TIMING_CS7_OFFSET 0x001c
+#define EXP_CNFG0_OFFSET 0x0020
+#define EXP_CNFG1_OFFSET 0x0024
+#define EXP_FCTRL_OFFSET 0x0028
+
+#define IXP425_EXP_RECOVERY_SHIFT 16
+#define IXP425_EXP_HOLD_SHIFT 20
+#define IXP425_EXP_STROBE_SHIFT 22
+#define IXP425_EXP_SETUP_SHIFT 26
+#define IXP425_EXP_ADDR_SHIFT 28
+#define IXP425_EXP_CS_EN (1U << 31)
+
+#define IXP425_EXP_RECOVERY_T(x) (((x) & 15) << IXP425_EXP_RECOVERY_SHIFT)
+#define IXP425_EXP_HOLD_T(x) (((x) & 3) << IXP425_EXP_HOLD_SHIFT)
+#define IXP425_EXP_STROBE_T(x) (((x) & 15) << IXP425_EXP_STROBE_SHIFT)
+#define IXP425_EXP_SETUP_T(x) (((x) & 3) << IXP425_EXP_SETUP_SHIFT)
+#define IXP425_EXP_ADDR_T(x) (((x) & 3) << IXP425_EXP_ADDR_SHIFT)
+
+/* EXP_CSn bits */
+#define EXP_BYTE_EN 0x00000001 /* bus uses only 8-bit data */
+#define EXP_WR_EN 0x00000002 /* ena writes to CS region */
+/* bit 2 is reserved */
+#define EXP_SPLT_EN 0x00000008 /* ena AHB split transfers */
+#define EXP_MUX_EN 0x00000010 /* multiplexed address/data */
+#define EXP_HRDY_POL 0x00000020 /* HPI|HRDY polarity */
+#define EXP_BYTE_RD16 0x00000040 /* byte rd access to word dev */
+#define EXP_CNFG 0x00003c00 /* device config size */
+#define EXP_SZ_512 (0 << 10)
+#define EXP_SZ_1K (1 << 10)
+#define EXP_SZ_2K (2 << 10)
+#define EXP_SZ_4K (3 << 10)
+#define EXP_SZ_8K (4 << 10)
+#define EXP_SZ_16K (5 << 10)
+#define EXP_SZ_32K (6 << 10)
+#define EXP_SZ_64K (7 << 10)
+#define EXP_SZ_128K (8 << 10)
+#define EXP_SZ_256K (9 << 10)
+#define EXP_SZ_512K (10 << 10)
+#define EXP_SZ_1M (11 << 10)
+#define EXP_SZ_2M (12 << 10)
+#define EXP_SZ_4M (13 << 10)
+#define EXP_SZ_8M (14 << 10)
+#define EXP_SZ_16M (15 << 10)
+#define EXP_CYC_TYPE 0x0000c000 /* bus cycle "type" */
+#define EXP_CYC_INTEL (0 << 14)
+#define EXP_CYC_MOTO (1 << 14)
+#define EXP_CYC_HPI (2 << 14)
+#define EXP_T5 0x000f0000 /* recovery timing */
+#define EXP_T4 0x00300000 /* hold timing */
+#define EXP_T3 0x03c00000 /* strobe timing */
+#define EXP_T2 0x0c000000 /* setup/chip select timing */
+#define EXP_T1 0x30000000 /* address timing */
+/* bit 30 is reserved */
+#define EXP_CS_EN 0x80000000 /* chip select enabled */
+
+/* EXP_CNFG0 bits */
+#define EXP_CNFG0_8BIT (1 << 0)
+#define EXP_CNFG0_PCI_HOST (1 << 1)
+#define EXP_CNFG0_PCI_ARB (1 << 2)
+#define EXP_CNFG0_PCI_66MHZ (1 << 4)
+#define EXP_CNFG0_MEM_MAP (1U << 31)
+
+/* EXP_CNFG1 bits */
+#define EXP_CNFG1_SW_INT0 (1 << 0)
+#define EXP_CNFG1_SW_INT1 (1 << 1)
+
+#define EXP_FCTRL_RCOMP (1<<0)
+#define EXP_FCTRL_USB_DEVICE (1<<1)
+#define EXP_FCTRL_HASH (1<<2)
+#define EXP_FCTRL_AES (1<<3)
+#define EXP_FCTRL_DES (1<<4)
+#define EXP_FCTRL_HDLC (1<<5)
+#define EXP_FCTRL_AAL (1<<6)
+#define EXP_FCTRL_HSS (1<<7)
+#define EXP_FCTRL_UTOPIA (1<<8)
+#define EXP_FCTRL_ETH0 (1<<9)
+#define EXP_FCTRL_ETH1 (1<<10)
+#define EXP_FCTRL_NPEA (1<<11) /* reset */
+#define EXP_FCTRL_NPEB (1<<12) /* reset */
+#define EXP_FCTRL_NPEC (1<<13) /* reset */
+#define EXP_FCTRL_PCI (1<<14)
+#define EXP_FCTRL_ECC_TIMESYNC (1<<15)
+#define EXP_FCTRL_UTOPIA_PHY (3<<16) /* PHY limit */
+#define EXP_FCTRL_USB_HOST (1<<18)
+#define EXP_FCTRL_NPEA_ETH (1<<19)
+#define EXP_FCTRL_NPEB_ETH (1<<20)
+#define EXP_FCTRL_RSA (1<<21)
+#define EXP_FCTRL_MAXFREQ (3<<22) /* XScale frequency */
+#define EXP_FCTRL_RESVD (0xff<<24)
+
+#define EXP_FCTRL_IXP46X_ONLY \
+ (EXP_FCTRL_ECC_TIMESYNC | EXP_FCTRL_USB_HOST | EXP_FCTRL_NPEA_ETH | \
+ EXP_FCTRL_NPEB_ETH | EXP_FCTRL_RSA | EXP_FCTRL_MAXFREQ)
+
+#define EXP_FCTRL_BITS \
+ "\20\1RCOMP\2USB\3HASH\4AES\5DES\6HDLC\7AAL\10HSS\11UTOPIA\12ETH0" \
+ "\13ETH1\17PCI\20ECC\23USB_HOST\24NPEA_ETH\25NPEB_ETH\26RSA"
+
+/*
+ * PCI
+ */
+#define IXP425_PCI_HWBASE 0xc0000000
+#define IXP425_PCI_VBASE 0xf0017000UL
+#define IXP425_PCI_SIZE 0x1000
+
+#define IXP425_AHB_OFFSET 0x00000000UL /* AHB bus */
+
+/*
+ * Mapping registers of IXP425 PCI Configuration
+ */
+/* PCI_ID_REG 0x00 */
+/* PCI_COMMAND_STATUS_REG 0x04 */
+/* PCI_CLASS_REG 0x08 */
+/* PCI_BHLC_REG 0x0c */
+#define PCI_MAPREG_BAR0 0x10 /* Base Address 0 */
+#define PCI_MAPREG_BAR1 0x14 /* Base Address 1 */
+#define PCI_MAPREG_BAR2 0x18 /* Base Address 2 */
+#define PCI_MAPREG_BAR3 0x1c /* Base Address 3 */
+#define PCI_MAPREG_BAR4 0x20 /* Base Address 4 */
+#define PCI_MAPREG_BAR5 0x24 /* Base Address 5 */
+/* PCI_SUBSYS_ID_REG 0x2c */
+/* PCI_INTERRUPT_REG 0x3c */
+#define PCI_RTOTTO 0x40
+
+/* PCI Controller CSR Base Address */
+#define IXP425_PCI_CSR_BASE IXP425_PCI_VBASE
+
+/* PCI Memory Space */
+#define IXP425_PCI_MEM_HWBASE 0x48000000UL
+#define IXP425_PCI_MEM_VBASE 0xf8000000UL
+#define IXP425_PCI_MEM_SIZE 0x04000000UL /* 64MB */
+
+/* PCI I/O Space */
+#define IXP425_PCI_IO_HWBASE 0x00000000UL
+#define IXP425_PCI_IO_SIZE 0x00100000UL /* 1Mbyte */
+
+/* PCI Controller Configuration Offset */
+#define PCI_NP_AD 0x00
+#define PCI_NP_CBE 0x04
+# define NP_CBE_SHIFT 4
+#define PCI_NP_WDATA 0x08
+#define PCI_NP_RDATA 0x0c
+#define PCI_CRP_AD_CBE 0x10
+#define PCI_CRP_AD_WDATA 0x14
+#define PCI_CRP_AD_RDATA 0x18
+#define PCI_CSR 0x1c
+# define CSR_PRST (1U << 16)
+# define CSR_IC (1U << 15)
+# define CSR_ABE (1U << 4)
+# define CSR_PDS (1U << 3)
+# define CSR_ADS (1U << 2)
+# define CSR_HOST (1U << 0)
+#define PCI_ISR 0x20
+# define ISR_AHBE (1U << 3)
+# define ISR_PPE (1U << 2)
+# define ISR_PFE (1U << 1)
+# define ISR_PSE (1U << 0)
+#define PCI_INTEN 0x24
+#define PCI_DMACTRL 0x28
+#define PCI_AHBMEMBASE 0x2c
+#define PCI_AHBIOBASE 0x30
+#define PCI_PCIMEMBASE 0x34
+#define PCI_AHBDOORBELL 0x38
+#define PCI_PCIDOORBELL 0x3c
+#define PCI_ATPDMA0_AHBADDR 0x40
+#define PCI_ATPDMA0_PCIADDR 0x44
+#define PCI_ATPDMA0_LENGTH 0x48
+#define PCI_ATPDMA1_AHBADDR 0x4c
+#define PCI_ATPDMA1_PCIADDR 0x50
+#define PCI_ATPDMA1_LENGTH 0x54
+#define PCI_PTADMA0_AHBADDR 0x58
+#define PCI_PTADMA0_PCIADDR 0x5c
+#define PCI_PTADMA0_LENGTH 0x60
+#define PCI_PTADMA1_AHBADDR 0x64
+#define PCI_PTADMA1_PCIADDR 0x68
+#define PCI_PTADMA1_LENGTH 0x6c
+
+/* PCI target(T)/initiator(I) Interface Commands for PCI_NP_CBE register */
+#define COMMAND_NP_IA 0x0 /* Interrupt Acknowledge (I)*/
+#define COMMAND_NP_SC 0x1 /* Special Cycle (I)*/
+#define COMMAND_NP_IO_READ 0x2 /* I/O Read (T)(I) */
+#define COMMAND_NP_IO_WRITE 0x3 /* I/O Write (T)(I) */
+#define COMMAND_NP_MEM_READ 0x6 /* Memory Read (T)(I) */
+#define COMMAND_NP_MEM_WRITE 0x7 /* Memory Write (T)(I) */
+#define COMMAND_NP_CONF_READ 0xa /* Configuration Read (T)(I) */
+#define COMMAND_NP_CONF_WRITE 0xb /* Configuration Write (T)(I) */
+
+/* PCI byte enables */
+#define BE_8BIT(a) ((0x10u << ((a) & 0x03)) ^ 0xf0)
+#define BE_16BIT(a) ((0x30u << ((a) & 0x02)) ^ 0xf0)
+#define BE_32BIT(a) 0x00
+
+/* PCI byte selects */
+#define READ_8BIT(v,a) ((u_int8_t)((v) >> (((a) & 3) * 8)))
+#define READ_16BIT(v,a) ((u_int16_t)((v) >> (((a) & 2) * 8)))
+#define WRITE_8BIT(v,a) (((u_int32_t)(v)) << (((a) & 3) * 8))
+#define WRITE_16BIT(v,a) (((u_int32_t)(v)) << (((a) & 2) * 8))
+
+/* PCI Controller Configuration Commands for PCI_CRP_AD_CBE */
+#define COMMAND_CRP_READ 0x00
+#define COMMAND_CRP_WRITE (1U << 16)
+
+/*
+ * SDRAM Configuration Register
+ */
+#define IXP425_MCU_HWBASE 0xcc000000UL
+#define IXP425_MCU_VBASE 0xf0200000UL
+#define IXP425_MCU_SIZE 0x1000 /* Actually only 256 bytes */
+#define MCU_SDR_CONFIG 0x00
+#define MCU_SDR_CONFIG_MCONF(x) ((x) & 0x7)
+#define MCU_SDR_CONFIG_64MBIT (1u << 5)
+#define MCU_SDR_REFRESH 0x04
+#define MCU_SDR_IR 0x08
+
+/*
+ * IXP435 DDR MCU Registers
+ */
+#define IXP435_MCU_HWBASE 0xcc00e500UL
+#define MCU_DDR_SDIR 0x00 /* DDR SDAM Initialization Reg*/
+#define MCU_DDR_SDCR0 0x04 /* DDR SDRAM Control Reg 0 */
+#define MCU_DDR_SDCR1 0x08 /* DDR SDRAM Control Reg 1 */
+#define MCU_DDR_SDBR 0x0c /* SDRAM Base Register */
+#define MCU_DDR_SBR0 0x10 /* SDRAM Boundary Register 0 */
+#define MCU_DDR_SBR1 0x14 /* SDRAM Boundary Register 1 */
+#define MCU_DDR_ECCR 0x1c /* ECC Control Register */
+#define MCU_DDR_ELOG0 0x20 /* ECC Log Register 0 */
+#define MCU_DDR_ELOG1 0x24 /* ECC Log Register 1 */
+#define MCU_DDR_ECAR0 0x28 /* ECC Address Register 0 */
+#define MCU_DDR_ECAR1 0x2c /* ECC Address Register 1 */
+#define MCU_DDR_ECTST 0x30 /* ECC Test Register */
+#define MCU_DDR_MCISR 0x34 /* MC Interrupt Status Reg */
+#define MCU_DDR_MPTCR 0x3c /* MC Port Transaction Cnt Reg*/
+#define MCU_DDR_RFR 0x48 /* Refresh Frequency Register */
+#define MCU_DDR_SDPR(n) (0x50+(n)*4) /* SDRAM Page Register 0-7 */
+/* NB: RCVDLY at 0x1050 and LEGOVERIDE at 0x1074 */
+
+/*
+ * Performance Monitoring Unit (CP14)
+ *
+ * CP14.0.1 Performance Monitor Control Register(PMNC)
+ * CP14.1.1 Clock Counter(CCNT)
+ * CP14.4.1 Interrupt Enable Register(INTEN)
+ * CP14.5.1 Overflow Flag Register(FLAG)
+ * CP14.8.1 Event Selection Register(EVTSEL)
+ * CP14.0.2 Performance Counter Register 0(PMN0)
+ * CP14.1.2 Performance Counter Register 0(PMN1)
+ * CP14.2.2 Performance Counter Register 0(PMN2)
+ * CP14.3.2 Performance Counter Register 0(PMN3)
+ */
+
+#define PMNC_E 0x00000001 /* enable all counters */
+#define PMNC_P 0x00000002 /* reset all PMNs to 0 */
+#define PMNC_C 0x00000004 /* clock counter reset */
+#define PMNC_D 0x00000008 /* clock counter / 64 */
+
+#define INTEN_CC_IE 0x00000001 /* enable clock counter interrupt */
+#define INTEN_PMN0_IE 0x00000002 /* enable PMN0 interrupt */
+#define INTEN_PMN1_IE 0x00000004 /* enable PMN1 interrupt */
+#define INTEN_PMN2_IE 0x00000008 /* enable PMN2 interrupt */
+#define INTEN_PMN3_IE 0x00000010 /* enable PMN3 interrupt */
+
+#define FLAG_CC_IF 0x00000001 /* clock counter overflow */
+#define FLAG_PMN0_IF 0x00000002 /* PMN0 overflow */
+#define FLAG_PMN1_IF 0x00000004 /* PMN1 overflow */
+#define FLAG_PMN2_IF 0x00000008 /* PMN2 overflow */
+#define FLAG_PMN3_IF 0x00000010 /* PMN3 overflow */
+
+#define EVTSEL_EVCNT_MASK 0x0000000ff /* event to count for PMNs */
+#define PMNC_EVCNT0_SHIFT 0
+#define PMNC_EVCNT1_SHIFT 8
+#define PMNC_EVCNT2_SHIFT 16
+#define PMNC_EVCNT3_SHIFT 24
+
+/*
+ * Queue Manager
+ */
+#define IXP425_QMGR_HWBASE 0x60000000UL
+#define IXP425_QMGR_VBASE 0xf0018000UL
+#define IXP425_QMGR_SIZE 0x4000
+
+/*
+ * Network Processing Engines (NPE's) and associated Ethernet MAC's.
+ */
+#define IXP425_NPE_A_HWBASE (IXP425_IO_HWBASE + IXP425_NPE_A_OFFSET)
+#define IXP425_NPE_A_VBASE (IXP425_IO_VBASE + IXP425_NPE_A_OFFSET)
+#define IXP425_NPE_A_SIZE 0x1000 /* Actually only 256 bytes */
+
+#define IXP425_NPE_B_HWBASE (IXP425_IO_HWBASE + IXP425_NPE_B_OFFSET)
+#define IXP425_NPE_B_VBASE (IXP425_IO_VBASE + IXP425_NPE_B_OFFSET)
+#define IXP425_NPE_B_SIZE 0x1000 /* Actually only 256 bytes */
+
+#define IXP425_NPE_C_HWBASE (IXP425_IO_HWBASE + IXP425_NPE_C_OFFSET)
+#define IXP425_NPE_C_VBASE (IXP425_IO_VBASE + IXP425_NPE_C_OFFSET)
+#define IXP425_NPE_C_SIZE 0x1000 /* Actually only 256 bytes */
+
+#define IXP425_MAC_B_HWBASE (IXP425_IO_HWBASE + IXP425_MAC_B_OFFSET)
+#define IXP425_MAC_B_VBASE (IXP425_IO_VBASE + IXP425_MAC_B_OFFSET)
+#define IXP425_MAC_B_SIZE 0x1000 /* Actually only 256 bytes */
+
+#define IXP425_MAC_C_HWBASE (IXP425_IO_HWBASE + IXP425_MAC_C_OFFSET)
+#define IXP425_MAC_C_VBASE (IXP425_IO_VBASE + IXP425_MAC_C_OFFSET)
+#define IXP425_MAC_C_SIZE 0x1000 /* Actually only 256 bytes */
+
+#define IXP435_MAC_A_HWBASE (IXP425_IO_HWBASE + IXP435_MAC_A_OFFSET)
+#define IXP435_MAC_A_VBASE (IXP425_IO_VBASE + IXP435_MAC_A_OFFSET)
+#define IXP435_MAC_A_SIZE 0x1000 /* Actually only 256 bytes */
+
+/*
+ * Expansion Bus Data Space.
+ */
+#define IXP425_EXP_BUS_HWBASE 0x50000000UL
+#define IXP425_EXP_BUS_SIZE 0x01000000 /* max, typically smaller */
+
+#define IXP425_EXP_BUS_CSx_HWBASE(i) \
+ (IXP425_EXP_BUS_HWBASE + (i)*IXP425_EXP_BUS_SIZE)
+#define IXP425_EXP_BUS_CSx_SIZE 0x1000
+#define IXP425_EXP_BUS_CSx_VBASE(i) \
+ (0xF0011000UL + (((i)-1)*IXP425_EXP_BUS_CSx_SIZE))
+
+/* NB: CS0 is special; it maps flash */
+#define IXP425_EXP_BUS_CS0_HWBASE IXP425_EXP_BUS_CSx_HWBASE(0)
+#define IXP425_EXP_BUS_CS0_VBASE 0xFD000000UL
+#ifndef IXP4XX_FLASH_SIZE
+#define IXP425_EXP_BUS_CS0_SIZE 0x01000000 /* NB: 16M */
+#else
+#define IXP425_EXP_BUS_CS0_SIZE IXP4XX_FLASH_SIZE
+#endif
+#define IXP425_EXP_BUS_CS1_HWBASE IXP425_EXP_BUS_CSx_HWBASE(1)
+#define IXP425_EXP_BUS_CS1_VBASE IXP425_EXP_BUS_CSx_VBASE(1)
+#define IXP425_EXP_BUS_CS1_SIZE IXP425_EXP_BUS_CSx_SIZE
+#define IXP425_EXP_BUS_CS2_HWBASE IXP425_EXP_BUS_CSx_HWBASE(2)
+#define IXP425_EXP_BUS_CS2_VBASE IXP425_EXP_BUS_CSx_VBASE(2)
+#define IXP425_EXP_BUS_CS2_SIZE IXP425_EXP_BUS_CSx_SIZE
+#define IXP425_EXP_BUS_CS3_HWBASE IXP425_EXP_BUS_CSx_HWBASE(3)
+#define IXP425_EXP_BUS_CS3_VBASE IXP425_EXP_BUS_CSx_VBASE(3)
+#define IXP425_EXP_BUS_CS3_SIZE IXP425_EXP_BUS_CSx_SIZE
+#define IXP425_EXP_BUS_CS4_HWBASE IXP425_EXP_BUS_CSx_HWBASE(4)
+#define IXP425_EXP_BUS_CS4_VBASE IXP425_EXP_BUS_CSx_VBASE(4)
+#define IXP425_EXP_BUS_CS4_SIZE IXP425_EXP_BUS_CSx_SIZE
+
+/* NB: not mapped (yet) */
+#define IXP425_EXP_BUS_CS5_HWBASE IXP425_EXP_BUS_CSx_HWBASE(5)
+#define IXP425_EXP_BUS_CS6_HWBASE IXP425_EXP_BUS_CSx_HWBASE(6)
+#define IXP425_EXP_BUS_CS7_HWBASE IXP425_EXP_BUS_CSx_HWBASE(7)
+
+/*
+ * IXP435/Gateworks Cambria
+ */
+#define IXP435_USB1_HWBASE 0xCD000000UL /* USB host controller 1 */
+#define IXP435_USB1_VBASE 0xF001C000UL
+#define IXP435_USB1_SIZE 0x1000 /* NB: only uses 0x300 */
+
+#define IXP435_USB2_HWBASE 0xCE000000UL /* USB host controller 2 */
+#define IXP435_USB2_VBASE 0xF001D000UL
+#define IXP435_USB2_SIZE 0x1000 /* NB: only uses 0x300 */
+
+#define CAMBRIA_GPS_HWBASE 0x53FC0000UL /* optional GPS Serial Port */
+#define CAMBRIA_GPS_VBASE 0xF001E000UL
+#define CAMBRIA_GPS_SIZE 0x1000
+#define CAMBRIA_RS485_HWBASE 0x53F80000UL /* optional RS485 Serial Port */
+#define CAMBRIA_RS485_VBASE 0xF001F000UL
+#define CAMBRIA_RS485_SIZE 0x1000
+
+/* NB: these are mapped on the fly, so no fixed virtual addresses */
+#define CAMBRIA_OCTAL_LED_HWBASE 0x53F40000UL /* Octal Status LED Latch */
+#define CAMBRIA_OCTAL_LED_SIZE 0x1000
+#define CAMBRIA_CFSEL1_HWBASE 0x53E40000UL /* Compact Flash Socket Sel 0 */
+#define CAMBRIA_CFSEL1_SIZE 0x40000
+#define CAMBRIA_CFSEL0_HWBASE 0x53E00000UL /* Compact Flash Socket Sel 1 */
+#define CAMBRIA_CFSEL0_SIZE 0x40000
+
+#endif /* _IXP425REG_H_ */
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/ixp425var.h
===================================================================
--- trunk/sys/arm/xscale/ixp425/ixp425var.h (rev 0)
+++ trunk/sys/arm/xscale/ixp425/ixp425var.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,129 @@
+/* $MidnightBSD$ */
+/* $NetBSD: ixp425var.h,v 1.10 2006/04/10 03:36:03 simonb Exp $ */
+
+/*
+ * Copyright (c) 2003
+ * Ichiro FUKUHARA <ichiro at ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/ixp425/ixp425var.h 229125 2011-12-31 15:53:34Z marius $
+ *
+ */
+
+#ifndef _IXP425VAR_H_
+#define _IXP425VAR_H_
+
+#include <sys/conf.h>
+#include <sys/queue.h>
+
+#include <machine/bus.h>
+
+#include <sys/rman.h>
+
+/* NB: cputype is setup by set_cpufuncs */
+#define cpu_is_ixp42x() (cputype == CPU_ID_IXP425)
+#define cpu_is_ixp43x() (cputype == CPU_ID_IXP435)
+#define cpu_is_ixp46x() (cputype == CPU_ID_IXP465)
+
+struct ixp425_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_gpio_ioh;
+ bus_space_handle_t sc_exp_ioh;
+
+ u_int32_t sc_intrmask;
+
+ struct rman sc_irq_rman;
+ struct rman sc_mem_rman;
+ bus_dma_tag_t sc_dmat;
+};
+
+void ixp425_set_gpio(struct ixp425_softc *sc, int pin, int type);
+
+struct ixppcib_softc {
+ device_t sc_dev;
+
+ u_int sc_bus;
+
+ struct resource *sc_csr;
+ struct resource *sc_mem;
+
+ struct rman sc_io_rman;
+ struct rman sc_mem_rman;
+ struct rman sc_irq_rman;
+
+ struct bus_space sc_pci_memt;
+ struct bus_space sc_pci_iot;
+ bus_dma_tag_t sc_dmat;
+};
+
+#define EXP_BUS_WRITE_4(sc, reg, data) \
+ bus_space_write_4(sc->sc_iot, sc->sc_exp_ioh, reg, data)
+#define EXP_BUS_READ_4(sc, reg) \
+ bus_space_read_4(sc->sc_iot, sc->sc_exp_ioh, reg)
+
+#define GPIO_CONF_WRITE_4(sc, reg, data) \
+ bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh, reg, data)
+#define GPIO_CONF_READ_4(sc, reg) \
+ bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, reg)
+#define IXP4XX_GPIO_LOCK() mtx_lock(&ixp425_gpio_mtx)
+#define IXP4XX_GPIO_UNLOCK() mtx_unlock(&ixp425_gpio_mtx)
+extern struct mtx ixp425_gpio_mtx;
+
+extern struct bus_space ixp425_bs_tag;
+extern struct bus_space ixp425_a4x_bs_tag;
+
+extern struct bus_space cambria_exp_bs_tag;
+void cambria_exp_bus_init(struct ixp425_softc *);
+
+void ixp425_io_bs_init(bus_space_tag_t, void *);
+void ixp425_mem_bs_init(bus_space_tag_t, void *);
+
+uint32_t ixp425_sdram_size(void);
+uint32_t ixp435_ddram_size(void);
+uint32_t ixp4xx_read_feature_bits(void);
+void ixp4xx_write_feature_bits(uint32_t);
+
+int ixp425_md_route_interrupt(device_t, device_t, int);
+void ixp425_md_attach(device_t);
+
+int getvbase(uint32_t, uint32_t, uint32_t *);
+
+struct ixp425_ivar {
+ uint32_t addr;
+ int irq;
+};
+#define IXP425_IVAR(d) ((struct ixp425_ivar *) device_get_ivars(d))
+
+enum {
+ IXP425_IVAR_ADDR, /* base physical address */
+ IXP425_IVAR_IRQ /* irq/gpio pin assignment */
+};
+#endif /* _IXP425VAR_H_ */
Property changes on: trunk/sys/arm/xscale/ixp425/ixp425var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/std.avila
===================================================================
--- trunk/sys/arm/xscale/ixp425/std.avila (rev 0)
+++ trunk/sys/arm/xscale/ixp425/std.avila 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,21 @@
+#$FreeBSD: stable/10/sys/arm/xscale/ixp425/std.avila 266110 2014-05-15 02:41:23Z ian $
+
+#
+# Gateworks GW23XX board configuration
+#
+files "../xscale/ixp425/files.avila"
+#
+# Physical memory starts at 0. We assume images are loaded at
+# 0x200000, e.g. from redboot with load -b 0x200000 kernel.
+#
+# Redboot is expected to handle unmapping the flash memory that
+# appears at 0 on boot. Likewise we expect the expansion bus to
+# be remapped away from 0.
+#
+options PHYSADDR=0x00000000
+options KERNPHYSADDR=0x00200000
+makeoptions KERNPHYSADDR=0x00200000
+options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+makeoptions KERNVIRTADDR=0xc0200000
+options FLASHADDR=0x50000000
+options LOADERRAMADDR=0x00000000
Property changes on: trunk/sys/arm/xscale/ixp425/std.avila
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/std.ixp425
===================================================================
--- trunk/sys/arm/xscale/ixp425/std.ixp425 (rev 0)
+++ trunk/sys/arm/xscale/ixp425/std.ixp425 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+#XScale IXP425 generic configuration
+#$FreeBSD: stable/10/sys/arm/xscale/ixp425/std.ixp425 239362 2012-08-18 05:48:19Z andrew $
+files "../xscale/ixp425/files.ixp425"
+include "../xscale/std.xscale-be"
+cpu CPU_XSCALE_IXP425
Property changes on: trunk/sys/arm/xscale/ixp425/std.ixp425
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/std.ixp435
===================================================================
--- trunk/sys/arm/xscale/ixp425/std.ixp435 (rev 0)
+++ trunk/sys/arm/xscale/ixp425/std.ixp435 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,7 @@
+#XScale IXP435 generic configuration
+#$FreeBSD: stable/10/sys/arm/xscale/ixp425/std.ixp435 239362 2012-08-18 05:48:19Z andrew $
+
+files "../xscale/ixp425/files.ixp425"
+include "../xscale/std.xscale-be"
+cpu CPU_XSCALE_IXP435
+cpu CPU_XSCALE_IXP425
Property changes on: trunk/sys/arm/xscale/ixp425/std.ixp435
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/uart_bus_ixp425.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/uart_bus_ixp425.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/uart_bus_ixp425.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,83 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Kevin Lo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/uart_bus_ixp425.c 194668 2009-06-22 22:46:37Z sam $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/ic/ns16550.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+#include "uart_if.h"
+
+static int uart_ixp425_probe(device_t dev);
+
+static device_method_t uart_ixp425_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uart_ixp425_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, uart_bus_detach),
+ { 0, 0 }
+};
+
+static driver_t uart_ixp425_driver = {
+ uart_driver_name,
+ uart_ixp425_methods,
+ sizeof(struct uart_softc),
+};
+DRIVER_MODULE(uart, ixp, uart_ixp425_driver, uart_devclass, 0, 0);
+
+static int
+uart_ixp425_probe(device_t dev)
+{
+ struct uart_softc *sc;
+ int unit = device_get_unit(dev);
+ u_int rclk;
+
+ sc = device_get_softc(dev);
+ sc->sc_class = &uart_ns8250_class;
+ if (resource_int_value("uart", unit, "rclk", &rclk))
+ rclk = IXP425_UART_FREQ;
+ if (bootverbose)
+ device_printf(dev, "rclk %u\n", rclk);
+
+ return uart_bus_probe(dev, 0, rclk, 0, 0);
+}
Property changes on: trunk/sys/arm/xscale/ixp425/uart_bus_ixp425.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/ixp425/uart_cpu_ixp425.c
===================================================================
--- trunk/sys/arm/xscale/ixp425/uart_cpu_ixp425.c (rev 0)
+++ trunk/sys/arm/xscale/ixp425/uart_cpu_ixp425.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,97 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/ixp425/uart_cpu_ixp425.c 170109 2007-05-29 18:10:42Z jhay $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/xscale/ixp425/ixp425reg.h>
+#include <arm/xscale/ixp425/ixp425var.h>
+
+bus_space_tag_t uart_bus_space_io;
+bus_space_tag_t uart_bus_space_mem;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+ return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+ uint32_t i, ivar, vaddr;
+
+ /*
+ * Scan the hints. The IXP425 only have 2 serial ports, so only
+ * scan them.
+ */
+ for (i = 0; i < 2; i++) {
+ if (resource_int_value("uart", i, "flags", &ivar))
+ continue;
+ if (devtype == UART_DEV_CONSOLE && !UART_FLAGS_CONSOLE(ivar))
+ continue;
+ if (devtype == UART_DEV_DBGPORT && !UART_FLAGS_DBGPORT(ivar))
+ continue;
+ /*
+ * We have a possible device. Make sure it's enabled and
+ * that we have an I/O port.
+ */
+ if (resource_int_value("uart", i, "disabled", &ivar) == 0 &&
+ ivar != 0)
+ continue;
+ if (resource_int_value("uart", i, "addr", &ivar) != 0 ||
+ ivar == 0)
+ continue;
+ /* Got it. Fill in the instance and return it. */
+ di->ops = uart_getops(&uart_ns8250_class);
+ di->bas.chan = 0;
+ di->bas.bst = &ixp425_a4x_bs_tag;
+ di->bas.regshft = 0;
+ di->bas.rclk = IXP425_UART_FREQ;
+ di->baudrate = 115200;
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ uart_bus_space_io = NULL;
+ uart_bus_space_mem = &ixp425_a4x_bs_tag;
+
+ getvbase(ivar, IXP425_REG_SIZE, &vaddr);
+ di->bas.bsh = vaddr;
+ return (0);
+ }
+
+ return (ENXIO);
+}
Property changes on: trunk/sys/arm/xscale/ixp425/uart_cpu_ixp425.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/files.pxa
===================================================================
--- trunk/sys/arm/xscale/pxa/files.pxa (rev 0)
+++ trunk/sys/arm/xscale/pxa/files.pxa 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,17 @@
+# $FreeBSD: stable/10/sys/arm/xscale/pxa/files.pxa 266311 2014-05-17 13:53:38Z ian $
+
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_xscale.S standard
+
+arm/xscale/pxa/pxa_gpio.c standard
+arm/xscale/pxa/pxa_icu.c standard
+arm/xscale/pxa/pxa_machdep.c standard
+arm/xscale/pxa/pxa_obio.c standard
+arm/xscale/pxa/pxa_smi.c standard
+arm/xscale/pxa/pxa_space.c standard
+arm/xscale/pxa/pxa_timer.c standard
+
+arm/xscale/pxa/uart_bus_pxa.c optional uart
+arm/xscale/pxa/uart_cpu_pxa.c optional uart
+
+arm/xscale/pxa/if_smc_smi.c optional smc
Property changes on: trunk/sys/arm/xscale/pxa/files.pxa
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/if_smc_smi.c
===================================================================
--- trunk/sys/arm/xscale/pxa/if_smc_smi.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/if_smc_smi.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,126 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Benno Rice
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/if_smc_smi.c 259342 2013-12-13 22:08:31Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
+
+#include <dev/smc/if_smcvar.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include "miibus_if.h"
+
+#include <arm/xscale/pxa/pxareg.h>
+#include <arm/xscale/pxa/pxavar.h>
+
+static int smc_smi_probe(device_t);
+static int smc_smi_attach(device_t);
+static int smc_smi_detach(device_t);
+
+static int
+smc_smi_probe(device_t dev)
+{
+ struct smc_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->smc_usemem = 1;
+
+ if (smc_probe(dev) != 0) {
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static int
+smc_smi_attach(device_t dev)
+{
+ int err;
+ struct smc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ err = smc_attach(dev);
+ if (err) {
+ return (err);
+ }
+
+ return (0);
+}
+
+static int
+smc_smi_detach(device_t dev)
+{
+
+ smc_detach(dev);
+
+ return (0);
+}
+
+static device_method_t smc_smi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, smc_smi_probe),
+ DEVMETHOD(device_attach, smc_smi_attach),
+ DEVMETHOD(device_detach, smc_smi_detach),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, smc_miibus_readreg),
+ DEVMETHOD(miibus_writereg, smc_miibus_writereg),
+ DEVMETHOD(miibus_statchg, smc_miibus_statchg),
+
+ { 0, 0 }
+};
+
+static driver_t smc_smi_driver = {
+ "smc",
+ smc_smi_methods,
+ sizeof(struct smc_softc),
+};
+
+extern devclass_t smc_devclass;
+
+DRIVER_MODULE(smc, smi, smc_smi_driver, smc_devclass, 0, 0);
+DRIVER_MODULE(miibus, smc, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(smc, smi, 1, 1, 1);
+MODULE_DEPEND(smc, ether, 1, 1, 1);
+MODULE_DEPEND(smc, miibus, 1, 1, 1);
Property changes on: trunk/sys/arm/xscale/pxa/if_smc_smi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxa_gpio.c
===================================================================
--- trunk/sys/arm/xscale/pxa/pxa_gpio.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxa_gpio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,359 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/pxa_gpio.c 179595 2008-06-06 05:08:09Z benno $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/interrupt.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/timetc.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/pxa/pxavar.h>
+#include <arm/xscale/pxa/pxareg.h>
+
+struct pxa_gpio_softc {
+ struct resource * pg_res[4];
+ bus_space_tag_t pg_bst;
+ bus_space_handle_t pg_bsh;
+ struct mtx pg_mtx;
+
+ uint32_t pg_intr[3];
+};
+
+static struct resource_spec pxa_gpio_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct pxa_gpio_softc *pxa_gpio_softc = NULL;
+
+static int pxa_gpio_probe(device_t);
+static int pxa_gpio_attach(device_t);
+
+static driver_filter_t pxa_gpio_intr0;
+static driver_filter_t pxa_gpio_intr1;
+static driver_filter_t pxa_gpio_intrN;
+
+static int
+pxa_gpio_probe(device_t dev)
+{
+
+ device_set_desc(dev, "GPIO Controller");
+ return (0);
+}
+
+static int
+pxa_gpio_attach(device_t dev)
+{
+ int error;
+ void *ihl;
+ struct pxa_gpio_softc *sc;
+
+ sc = (struct pxa_gpio_softc *)device_get_softc(dev);
+
+ if (pxa_gpio_softc != NULL)
+ return (ENXIO);
+ pxa_gpio_softc = sc;
+
+ error = bus_alloc_resources(dev, pxa_gpio_spec, sc->pg_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->pg_bst = rman_get_bustag(sc->pg_res[0]);
+ sc->pg_bsh = rman_get_bushandle(sc->pg_res[0]);
+
+ /* Disable and clear all interrupts. */
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER0, 0);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER1, 0);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER2, 0);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER0, 0);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER1, 0);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER2, 0);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, ~0);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, ~0);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, ~0);
+
+ mtx_init(&sc->pg_mtx, "GPIO mutex", NULL, MTX_SPIN);
+
+ if (bus_setup_intr(dev, sc->pg_res[1], INTR_TYPE_MISC|INTR_MPSAFE,
+ pxa_gpio_intr0, NULL, sc, &ihl) != 0) {
+ bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
+ device_printf(dev, "could not set up intr0\n");
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->pg_res[2], INTR_TYPE_MISC|INTR_MPSAFE,
+ pxa_gpio_intr1, NULL, sc, &ihl) != 0) {
+ bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
+ device_printf(dev, "could not set up intr1\n");
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->pg_res[3], INTR_TYPE_MISC|INTR_MPSAFE,
+ pxa_gpio_intrN, NULL, sc, &ihl) != 0) {
+ bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
+ device_printf(dev, "could not set up intrN\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+pxa_gpio_intr0(void *arg)
+{
+ struct pxa_gpio_softc *sc;
+
+ sc = (struct pxa_gpio_softc *)arg;
+
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x1);
+ sc->pg_intr[0] |= 1;
+
+ return (FILTER_HANDLED);
+}
+
+static int
+pxa_gpio_intr1(void *arg)
+{
+ struct pxa_gpio_softc *sc;
+
+ sc = (struct pxa_gpio_softc *)arg;
+
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x2);
+ sc->pg_intr[1] |= 2;
+
+ return (FILTER_HANDLED);
+}
+
+static int
+pxa_gpio_intrN(void *arg)
+{
+ uint32_t gedr0, gedr1, gedr2;
+ struct pxa_gpio_softc *sc;
+
+ sc = (struct pxa_gpio_softc *)arg;
+
+ gedr0 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0);
+ gedr0 &= 0xfffffffc;
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, gedr0);
+
+ gedr1 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1);
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, gedr1);
+
+ gedr2 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2);
+ gedr2 &= 0x001fffff;
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, gedr2);
+
+ sc->pg_intr[0] |= gedr0;
+ sc->pg_intr[1] |= gedr1;
+ sc->pg_intr[2] |= gedr2;
+
+ return (FILTER_HANDLED);
+}
+
+static device_method_t pxa_gpio_methods[] = {
+ DEVMETHOD(device_probe, pxa_gpio_probe),
+ DEVMETHOD(device_attach, pxa_gpio_attach),
+
+ {0, 0}
+};
+
+static driver_t pxa_gpio_driver = {
+ "gpio",
+ pxa_gpio_methods,
+ sizeof(struct pxa_gpio_softc),
+};
+
+static devclass_t pxa_gpio_devclass;
+
+DRIVER_MODULE(pxagpio, pxa, pxa_gpio_driver, pxa_gpio_devclass, 0, 0);
+
+#define pxagpio_reg_read(softc, reg) \
+ bus_space_read_4(sc->pg_bst, sc->pg_bsh, reg)
+#define pxagpio_reg_write(softc, reg, val) \
+ bus_space_write_4(sc->pg_bst, sc->pg_bsh, reg, val)
+
+uint32_t
+pxa_gpio_get_function(int gpio)
+{
+ struct pxa_gpio_softc *sc;
+ uint32_t rv, io;
+
+ sc = pxa_gpio_softc;
+
+ rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio);
+ rv = GPIO_FN(rv);
+
+ io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio));
+ if (io & GPIO_BIT(gpio))
+ rv |= GPIO_OUT;
+
+ io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPLR0, gpio));
+ if (io & GPIO_BIT(gpio))
+ rv |= GPIO_SET;
+
+ return (rv);
+}
+
+uint32_t
+pxa_gpio_set_function(int gpio, uint32_t fn)
+{
+ struct pxa_gpio_softc *sc;
+ uint32_t rv, bit, oldfn;
+
+ sc = pxa_gpio_softc;
+
+ oldfn = pxa_gpio_get_function(gpio);
+
+ if (GPIO_FN(fn) == GPIO_FN(oldfn) &&
+ GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) {
+ /*
+ * The pin's function is not changing.
+ * For Alternate Functions and GPIO input, we can just
+ * return now.
+ * For GPIO output pins, check the initial state is
+ * the same.
+ *
+ * Return 'fn' instead of 'oldfn' so the caller can
+ * reliably detect that we didn't change anything.
+ * (The initial state might be different for non-
+ * GPIO output pins).
+ */
+ if (!GPIO_IS_GPIO_OUT(fn) ||
+ GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn))
+ return (fn);
+ }
+
+ /*
+ * See section 4.1.3.7 of the PXA2x0 Developer's Manual for
+ * the correct procedure for changing GPIO pin functions.
+ */
+
+ bit = GPIO_BIT(gpio);
+
+ /*
+ * 1. Configure the correct set/clear state of the pin
+ */
+ if (GPIO_FN_IS_SET(fn))
+ pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPSR0, gpio), bit);
+ else
+ pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPCR0, gpio), bit);
+
+ /*
+ * 2. Configure the pin as an input or output as appropriate
+ */
+ rv = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
+ if (GPIO_FN_IS_OUT(fn))
+ rv |= bit;
+ pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio), rv);
+
+ /*
+ * 3. Configure the pin's function
+ */
+ bit = GPIO_FN_MASK << GPIO_FN_SHIFT(gpio);
+ fn = GPIO_FN(fn) << GPIO_FN_SHIFT(gpio);
+ rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) & ~bit;
+ pxagpio_reg_write(sc, GPIO_FN_REG(gpio), rv | fn);
+
+ return (oldfn);
+}
+
+/*
+ * GPIO "interrupt" handling.
+ */
+
+void
+pxa_gpio_mask_irq(int irq)
+{
+ uint32_t val;
+ struct pxa_gpio_softc *sc;
+ int gpio;
+
+ sc = pxa_gpio_softc;
+ gpio = IRQ_TO_GPIO(irq);
+
+ val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio));
+ val &= ~GPIO_BIT(gpio);
+ pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val);
+}
+
+void
+pxa_gpio_unmask_irq(int irq)
+{
+ uint32_t val;
+ struct pxa_gpio_softc *sc;
+ int gpio;
+
+ sc = pxa_gpio_softc;
+ gpio = IRQ_TO_GPIO(irq);
+
+ val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio));
+ val |= GPIO_BIT(gpio);
+ pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val);
+}
+
+int
+pxa_gpio_get_next_irq()
+{
+ struct pxa_gpio_softc *sc;
+ int gpio;
+
+ sc = pxa_gpio_softc;
+
+ if (sc->pg_intr[0] != 0) {
+ gpio = ffs(sc->pg_intr[0]) - 1;
+ sc->pg_intr[0] &= ~(1 << gpio);
+ return (GPIO_TO_IRQ(gpio));
+ }
+ if (sc->pg_intr[1] != 0) {
+ gpio = ffs(sc->pg_intr[1]) - 1;
+ sc->pg_intr[1] &= ~(1 << gpio);
+ return (GPIO_TO_IRQ(gpio + 32));
+ }
+ if (sc->pg_intr[2] != 0) {
+ gpio = ffs(sc->pg_intr[2]) - 1;
+ sc->pg_intr[2] &= ~(1 << gpio);
+ return (GPIO_TO_IRQ(gpio + 64));
+ }
+
+ return (-1);
+}
Property changes on: trunk/sys/arm/xscale/pxa/pxa_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxa_icu.c
===================================================================
--- trunk/sys/arm/xscale/pxa/pxa_icu.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxa_icu.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,260 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/pxa_icu.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/pxa/pxavar.h>
+#include <arm/xscale/pxa/pxareg.h>
+
+struct pxa_icu_softc {
+ struct resource * pi_res[1];
+ bus_space_tag_t pi_bst;
+ bus_space_handle_t pi_bsh;
+};
+
+static struct resource_spec pxa_icu_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct pxa_icu_softc *pxa_icu_softc = NULL;
+
+static int pxa_icu_probe(device_t);
+static int pxa_icu_attach(device_t);
+
+uint32_t pxa_icu_get_icip(void);
+void pxa_icu_clear_icip(int);
+uint32_t pxa_icu_get_icfp(void);
+void pxa_icu_clear_icfp(int);
+uint32_t pxa_icu_get_icmr(void);
+void pxa_icu_set_icmr(uint32_t);
+uint32_t pxa_icu_get_iclr(void);
+void pxa_icu_set_iclr(uint32_t);
+uint32_t pxa_icu_get_icpr(void);
+void pxa_icu_idle_enable(void);
+void pxa_icu_idle_disable(void);
+
+extern uint32_t pxa_gpio_intr_flags[];
+
+static int
+pxa_icu_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Interrupt Controller");
+ return (0);
+}
+
+static int
+pxa_icu_attach(device_t dev)
+{
+ int error;
+ struct pxa_icu_softc *sc;
+
+ sc = (struct pxa_icu_softc *)device_get_softc(dev);
+
+ if (pxa_icu_softc != NULL)
+ return (ENXIO);
+ pxa_icu_softc = sc;
+
+ error = bus_alloc_resources(dev, pxa_icu_spec, sc->pi_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->pi_bst = rman_get_bustag(sc->pi_res[0]);
+ sc->pi_bsh = rman_get_bushandle(sc->pi_res[0]);
+
+ /* Disable all interrupts. */
+ pxa_icu_set_icmr(0);
+
+ /* Route all interrupts to IRQ rather than FIQ. */
+ pxa_icu_set_iclr(0);
+
+ /* XXX: This should move to configure_final or something. */
+ enable_interrupts(PSR_I|PSR_F);
+
+ return (0);
+}
+
+static device_method_t pxa_icu_methods[] = {
+ DEVMETHOD(device_probe, pxa_icu_probe),
+ DEVMETHOD(device_attach, pxa_icu_attach),
+
+ {0, 0}
+};
+
+static driver_t pxa_icu_driver = {
+ "icu",
+ pxa_icu_methods,
+ sizeof(struct pxa_icu_softc),
+};
+
+static devclass_t pxa_icu_devclass;
+
+DRIVER_MODULE(pxaicu, pxa, pxa_icu_driver, pxa_icu_devclass, 0, 0);
+
+int
+arm_get_next_irq(int last __unused)
+{
+ int irq;
+
+ if ((irq = pxa_icu_get_icip()) != 0) {
+ return (ffs(irq) - 1);
+ }
+
+ return (pxa_gpio_get_next_irq());
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ uint32_t mr;
+
+ if (nb >= IRQ_GPIO0) {
+ pxa_gpio_mask_irq(nb);
+ return;
+ }
+
+ mr = pxa_icu_get_icmr();
+ mr &= ~(1 << nb);
+ pxa_icu_set_icmr(mr);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ uint32_t mr;
+
+ if (nb >= IRQ_GPIO0) {
+ pxa_gpio_unmask_irq(nb);
+ return;
+ }
+
+ mr = pxa_icu_get_icmr();
+ mr |= (1 << nb);
+ pxa_icu_set_icmr(mr);
+}
+
+uint32_t
+pxa_icu_get_icip()
+{
+
+ return (bus_space_read_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_IP));
+}
+
+void
+pxa_icu_clear_icip(int irq)
+{
+
+ bus_space_write_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_IP, (1 << irq));
+}
+
+uint32_t
+pxa_icu_get_icfp()
+{
+
+ return (bus_space_read_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_FP));
+}
+
+void
+pxa_icu_clear_icfp(int irq)
+{
+
+ bus_space_write_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_FP, (1 << irq));
+}
+
+uint32_t
+pxa_icu_get_icmr()
+{
+
+ return (bus_space_read_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_MR));
+}
+
+void
+pxa_icu_set_icmr(uint32_t val)
+{
+
+ bus_space_write_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_MR, val);
+}
+
+uint32_t
+pxa_icu_get_iclr()
+{
+
+ return (bus_space_read_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_LR));
+}
+
+void
+pxa_icu_set_iclr(uint32_t val)
+{
+
+ bus_space_write_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_LR, val);
+}
+
+uint32_t
+pxa_icu_get_icpr()
+{
+
+ return (bus_space_read_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_PR));
+}
+
+void
+pxa_icu_idle_enable()
+{
+
+ bus_space_write_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_CR, 0x0);
+}
+
+void
+pxa_icu_idle_disable()
+{
+
+ bus_space_write_4(pxa_icu_softc->pi_bst,
+ pxa_icu_softc->pi_bsh, ICU_CR, 0x1);
+}
Property changes on: trunk/sys/arm/xscale/pxa/pxa_icu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxa_machdep.c
===================================================================
--- trunk/sys/arm/xscale/pxa/pxa_machdep.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxa_machdep.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,436 @@
+/* $MidnightBSD$ */
+/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
+
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work.
+ *
+ * Created : 17/09/94
+ */
+
+#include "opt_ddb.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/pxa_machdep.c 266386 2014-05-18 00:32:35Z ian $");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/cons.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/kdb.h>
+#include <sys/msgbuf.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <machine/devmap.h>
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/undefined.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/physmem.h>
+#include <sys/reboot.h>
+
+#include <arm/xscale/pxa/pxareg.h>
+#include <arm/xscale/pxa/pxavar.h>
+
+#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
+#define KERNEL_PT_IOPXS 1
+#define KERNEL_PT_BEFOREKERN 2
+#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */
+#define KERNEL_PT_AFKERNEL_NUM 9
+
+/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
+#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
+
+struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
+
+/* Physical and virtual addresses for some global pages */
+
+struct pv_addr systempage;
+struct pv_addr msgbufpv;
+struct pv_addr irqstack;
+struct pv_addr undstack;
+struct pv_addr abtstack;
+struct pv_addr kernelstack;
+struct pv_addr minidataclean;
+
+static void pxa_probe_sdram(bus_space_tag_t, bus_space_handle_t,
+ uint32_t *, uint32_t *);
+
+/* Static device mappings. */
+static const struct arm_devmap_entry pxa_devmap[] = {
+ /*
+ * Map the on-board devices up into the KVA region so we don't muck
+ * up user-space.
+ */
+ {
+ PXA2X0_PERIPH_START + PXA2X0_PERIPH_OFFSET,
+ PXA2X0_PERIPH_START,
+ PXA250_PERIPH_END - PXA2X0_PERIPH_START,
+ VM_PROT_READ|VM_PROT_WRITE,
+ PTE_DEVICE,
+ },
+ { 0, 0, 0, 0, 0, }
+};
+
+#define SDRAM_START 0xa0000000
+
+extern vm_offset_t xscale_cache_clean_addr;
+
+void *
+initarm(struct arm_boot_params *abp)
+{
+ struct pv_addr kernel_l1pt;
+ struct pv_addr dpcpu;
+ int loop;
+ u_int l1pagetable;
+ vm_offset_t freemempos;
+ vm_offset_t freemem_pt;
+ vm_offset_t afterkern;
+ vm_offset_t freemem_after;
+ vm_offset_t lastaddr;
+ int i, j;
+ uint32_t memsize[PXA2X0_SDRAM_BANKS], memstart[PXA2X0_SDRAM_BANKS];
+
+ lastaddr = parse_boot_param(abp);
+ arm_physmem_kernaddr = abp->abp_physaddr;
+ set_cpufuncs();
+ pcpu_init(pcpup, 0, sizeof(struct pcpu));
+ PCPU_SET(curthread, &thread0);
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+ freemempos = 0xa0200000;
+ /* Define a macro to simplify memory allocation */
+#define valloc_pages(var, np) \
+ alloc_pages((var).pv_pa, (np)); \
+ (var).pv_va = (var).pv_pa + 0x20000000;
+
+#define alloc_pages(var, np) \
+ freemempos -= (np * PAGE_SIZE); \
+ (var) = freemempos; \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
+ freemempos -= PAGE_SIZE;
+ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+ for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+ if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
+ valloc_pages(kernel_pt_table[loop],
+ L2_TABLE_SIZE / PAGE_SIZE);
+ } else {
+ kernel_pt_table[loop].pv_pa = freemempos +
+ (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
+ L2_TABLE_SIZE_REAL;
+ kernel_pt_table[loop].pv_va =
+ kernel_pt_table[loop].pv_pa + 0x20000000;
+ }
+ }
+ freemem_pt = freemempos;
+ freemempos = 0xa0100000;
+ /*
+ * Allocate a page for the system page mapped to V0x00000000
+ * This page will just contain the system vectors and can be
+ * shared by all processes.
+ */
+ valloc_pages(systempage, 1);
+
+ /* Allocate dynamic per-cpu area. */
+ valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
+ dpcpu_init((void *)dpcpu.pv_va, 0);
+
+ /* Allocate stacks for all modes */
+ valloc_pages(irqstack, IRQ_STACK_SIZE);
+ valloc_pages(abtstack, ABT_STACK_SIZE);
+ valloc_pages(undstack, UND_STACK_SIZE);
+ valloc_pages(kernelstack, KSTACK_PAGES);
+ alloc_pages(minidataclean.pv_pa, 1);
+ valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+ /*
+ * Allocate memory for the l1 and l2 page tables. The scheme to avoid
+ * wasting memory by allocating the l1pt on the first 16k memory was
+ * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for
+ * this to work (which is supposed to be the case).
+ */
+
+ /*
+ * Now we start construction of the L1 page table
+ * We start by mapping the L2 page tables into the L1.
+ * This means that we can replace L1 mappings later on if necessary
+ */
+ l1pagetable = kernel_l1pt.pv_va;
+
+ /* Map the L2 pages tables in the L1 page table */
+ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1),
+ &kernel_pt_table[KERNEL_PT_SYS]);
+#if 0 /* XXXBJR: What is this? Don't know if there's an analogue. */
+ pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE,
+ &kernel_pt_table[KERNEL_PT_IOPXS]);
+#endif
+ pmap_link_l2pt(l1pagetable, KERNBASE,
+ &kernel_pt_table[KERNEL_PT_BEFOREKERN]);
+ pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000,
+ 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+ pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000,
+ (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1),
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1);
+ afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) &
+ ~(L1_S_SIZE - 1));
+ for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
+ pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
+ &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
+ }
+ pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+
+ /* Map the Mini-Data cache clean area. */
+ xscale_setup_minidata(l1pagetable, afterkern,
+ minidataclean.pv_pa);
+
+ /* Map the vector page. */
+ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
+ VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+ arm_devmap_bootstrap(l1pagetable, pxa_devmap);
+
+ /*
+ * Give the XScale global cache clean code an appropriately
+ * sized chunk of unmapped VA space starting at 0xff000000
+ * (our device mappings end before this address).
+ */
+ xscale_cache_clean_addr = 0xff000000U;
+
+ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
+ setttb(kernel_l1pt.pv_pa);
+ cpu_tlb_flushID();
+ cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
+
+ /*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+ set_stackptrs(0);
+
+ /*
+ * We must now clean the cache again....
+ * Cleaning may be done by reading new data to displace any
+ * dirty data in the cache. This will have happened in setttb()
+ * but since we are boot strapping the addresses used for the read
+ * may have just been remapped and thus the cache could be out
+ * of sync. A re-clean after the switch will cure this.
+ * After booting there are no gross relocations of the kernel thus
+ * this problem will not occur after initarm().
+ */
+ cpu_idcache_wbinv_all();
+ cpu_setup("");
+
+ /*
+ * Sort out bus_space for on-board devices.
+ */
+ pxa_obio_tag_init();
+
+ /*
+ * Fetch the SDRAM start/size from the PXA2X0 SDRAM configration
+ * registers.
+ */
+ pxa_probe_sdram(obio_tag, PXA2X0_MEMCTL_BASE, memstart, memsize);
+
+ /* Fire up consoles. */
+ cninit();
+
+ undefined_init();
+
+ init_proc0(kernelstack.pv_va);
+
+ /* Enable MMU, I-cache, D-cache, write buffer. */
+ arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+
+ pmap_curmaxkvaddr = afterkern + PAGE_SIZE;
+ vm_max_kernel_address = 0xd0000000;
+ pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
+ msgbufp = (void*)msgbufpv.pv_va;
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+
+ /*
+ * Add the physical ram we have available.
+ *
+ * Exclude the kernel (and all the things we allocated which immediately
+ * follow the kernel) from the VM allocation pool but not from crash
+ * dumps. virtual_avail is a global variable which tracks the kva we've
+ * "allocated" while setting up pmaps.
+ *
+ * Prepare the list of physical memory available to the vm subsystem.
+ */
+ for (j = 0; j < PXA2X0_SDRAM_BANKS; j++) {
+ if (memsize[j] > 0)
+ arm_physmem_hardware_region(memstart[j], memsize[j]);
+ }
+ arm_physmem_exclude_region(abp->abp_physaddr,
+ virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
+ arm_physmem_init_kernel_globals();
+
+ init_param2(physmem);
+ kdb_init();
+ return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
+ sizeof(struct pcb)));
+}
+
+static void
+pxa_probe_sdram(bus_space_tag_t bst, bus_space_handle_t bsh,
+ uint32_t *memstart, uint32_t *memsize)
+{
+ uint32_t mdcnfg, dwid, dcac, drac, dnb;
+ int i;
+
+ mdcnfg = bus_space_read_4(bst, bsh, MEMCTL_MDCNFG);
+
+ /*
+ * Scan all 4 SDRAM banks
+ */
+ for (i = 0; i < PXA2X0_SDRAM_BANKS; i++) {
+ memstart[i] = 0;
+ memsize[i] = 0;
+
+ switch (i) {
+ case 0:
+ case 1:
+ if ((i == 0 && (mdcnfg & MDCNFG_DE0) == 0) ||
+ (i == 1 && (mdcnfg & MDCNFG_DE1) == 0))
+ continue;
+ dwid = mdcnfg >> MDCNFD_DWID01_SHIFT;
+ dcac = mdcnfg >> MDCNFD_DCAC01_SHIFT;
+ drac = mdcnfg >> MDCNFD_DRAC01_SHIFT;
+ dnb = mdcnfg >> MDCNFD_DNB01_SHIFT;
+ break;
+
+ case 2:
+ case 3:
+ if ((i == 2 && (mdcnfg & MDCNFG_DE2) == 0) ||
+ (i == 3 && (mdcnfg & MDCNFG_DE3) == 0))
+ continue;
+ dwid = mdcnfg >> MDCNFD_DWID23_SHIFT;
+ dcac = mdcnfg >> MDCNFD_DCAC23_SHIFT;
+ drac = mdcnfg >> MDCNFD_DRAC23_SHIFT;
+ dnb = mdcnfg >> MDCNFD_DNB23_SHIFT;
+ break;
+ default:
+ panic("pxa_probe_sdram: impossible");
+ }
+
+ dwid = 2 << (1 - (dwid & MDCNFD_DWID_MASK)); /* 16/32 width */
+ dcac = 1 << ((dcac & MDCNFD_DCAC_MASK) + 8); /* 8-11 columns */
+ drac = 1 << ((drac & MDCNFD_DRAC_MASK) + 11); /* 11-13 rows */
+ dnb = 2 << (dnb & MDCNFD_DNB_MASK); /* # of banks */
+
+ memsize[i] = dwid * dcac * drac * dnb;
+ memstart[i] = PXA2X0_SDRAM0_START +
+ (i * PXA2X0_SDRAM_BANK_SIZE);
+ }
+}
+
+#define TIMER_FREQUENCY 3686400
+#define UNIMPLEMENTED panic("%s: unimplemented", __func__)
+
+/* XXXBJR: Belongs with DELAY in a timer.c of some sort. */
+void
+cpu_startprofclock(void)
+{
+ UNIMPLEMENTED;
+}
+
+void
+cpu_stopprofclock(void)
+{
+ UNIMPLEMENTED;
+}
+
+static struct arm32_dma_range pxa_range = {
+ .dr_sysbase = 0,
+ .dr_busbase = 0,
+ .dr_len = ~0u,
+};
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (&pxa_range);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (1);
+}
Property changes on: trunk/sys/arm/xscale/pxa/pxa_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxa_obio.c
===================================================================
--- trunk/sys/arm/xscale/pxa/pxa_obio.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxa_obio.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,398 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/pxa_obio.c 265999 2014-05-14 01:35:43Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/pxa/pxavar.h>
+#include <arm/xscale/pxa/pxareg.h>
+
+static void pxa_identify(driver_t *, device_t);
+static int pxa_probe(device_t);
+static int pxa_attach(device_t);
+
+static int pxa_print_child(device_t, device_t);
+
+static int pxa_setup_intr(device_t, device_t, struct resource *, int,
+ driver_filter_t *, driver_intr_t *, void *, void **);
+static int pxa_read_ivar(device_t, device_t, int, uintptr_t *);
+
+static struct resource_list * pxa_get_resource_list(device_t, device_t);
+static struct resource * pxa_alloc_resource(device_t, device_t, int,
+ int *, u_long, u_long, u_long, u_int);
+static int pxa_release_resource(device_t, device_t, int,
+ int, struct resource *);
+static int pxa_activate_resource(device_t, device_t,
+ int, int, struct resource *);
+
+static struct resource * pxa_alloc_gpio_irq(device_t, device_t, int,
+ int *, u_long, u_long, u_long, u_int);
+
+struct obio_device {
+ const char *od_name;
+ u_long od_base;
+ u_long od_size;
+ u_int od_irqs[5];
+ struct resource_list od_resources;
+};
+
+static struct obio_device obio_devices[] = {
+ { "icu", PXA2X0_INTCTL_BASE, PXA2X0_INTCTL_SIZE, { 0 } },
+ { "timer", PXA2X0_OST_BASE, PXA2X0_OST_SIZE, { PXA2X0_INT_OST0, PXA2X0_INT_OST1, PXA2X0_INT_OST2, PXA2X0_INT_OST3, 0 } },
+ { "dmac", PXA2X0_DMAC_BASE, PXA2X0_DMAC_SIZE, { PXA2X0_INT_DMA, 0 } },
+ { "gpio", PXA2X0_GPIO_BASE, PXA250_GPIO_SIZE, { PXA2X0_INT_GPIO0, PXA2X0_INT_GPIO1, PXA2X0_INT_GPION, 0 } },
+ { "uart", PXA2X0_FFUART_BASE, PXA2X0_FFUART_SIZE, { PXA2X0_INT_FFUART, 0 } },
+ { "uart", PXA2X0_BTUART_BASE, PXA2X0_BTUART_SIZE, { PXA2X0_INT_BTUART, 0 } },
+ { "uart", PXA2X0_STUART_BASE, PXA2X0_STUART_SIZE, { PXA2X0_INT_STUART, 0 } },
+ { "uart", PXA2X0_HWUART_BASE, PXA2X0_HWUART_SIZE, { PXA2X0_INT_HWUART, 0 } },
+ { "smi", PXA2X0_CS0_START, PXA2X0_CS_SIZE * 6, { 0 } },
+ { NULL, 0, 0, { 0 } }
+};
+
+void
+pxa_identify(driver_t *driver, device_t parent)
+{
+
+ BUS_ADD_CHILD(parent, 0, "pxa", 0);
+}
+
+int
+pxa_probe(device_t dev)
+{
+
+ device_set_desc(dev, "XScale PXA On-board IO");
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+int
+pxa_attach(device_t dev)
+{
+ struct obio_softc *sc;
+ struct obio_device *od;
+ int i;
+ device_t child;
+
+ sc = device_get_softc(dev);
+
+ sc->obio_bst = obio_tag;
+
+ sc->obio_mem.rm_type = RMAN_ARRAY;
+ sc->obio_mem.rm_descr = "PXA2X0 OBIO Memory";
+ if (rman_init(&sc->obio_mem) != 0)
+ panic("pxa_attach: failed to init obio mem rman");
+ if (rman_manage_region(&sc->obio_mem, 0, PXA250_PERIPH_END) != 0)
+ panic("pxa_attach: failed to set up obio mem rman");
+
+ sc->obio_irq.rm_type = RMAN_ARRAY;
+ sc->obio_irq.rm_descr = "PXA2X0 OBIO IRQ";
+ if (rman_init(&sc->obio_irq) != 0)
+ panic("pxa_attach: failed to init obio irq rman");
+ if (rman_manage_region(&sc->obio_irq, 0, 31) != 0)
+ panic("pxa_attach: failed to set up obio irq rman (main irqs)");
+ if (rman_manage_region(&sc->obio_irq, IRQ_GPIO0, IRQ_GPIO_MAX) != 0)
+ panic("pxa_attach: failed to set up obio irq rman (gpio irqs)");
+
+ for (od = obio_devices; od->od_name != NULL; od++) {
+ resource_list_init(&od->od_resources);
+
+ resource_list_add(&od->od_resources, SYS_RES_MEMORY, 0,
+ od->od_base, od->od_base + od->od_size, od->od_size);
+
+ for (i = 0; od->od_irqs[i] != 0; i++) {
+ resource_list_add(&od->od_resources, SYS_RES_IRQ, i,
+ od->od_irqs[i], od->od_irqs[i], 1);
+ }
+
+ child = device_add_child(dev, od->od_name, -1);
+ device_set_ivars(child, od);
+ }
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static int
+pxa_print_child(device_t dev, device_t child)
+{
+ struct obio_device *od;
+ int retval;
+
+ od = (struct obio_device *)device_get_ivars(child);
+ if (od == NULL)
+ panic("Unknown device on pxa0");
+
+ retval = 0;
+
+ retval += bus_print_child_header(dev, child);
+
+ retval += resource_list_print_type(&od->od_resources, "at mem",
+ SYS_RES_MEMORY, "0x%08lx");
+ retval += resource_list_print_type(&od->od_resources, "irq",
+ SYS_RES_IRQ, "%ld");
+
+ retval += bus_print_child_footer(dev, child);
+
+ return (retval);
+}
+
+static int
+pxa_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
+ driver_filter_t *filter, driver_intr_t *ithread, void *arg, void **cookiep)
+{
+ struct obio_softc *sc;
+ int error;
+
+ sc = (struct obio_softc *)device_get_softc(dev);
+
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags,
+ filter, ithread, arg, cookiep);
+ if (error)
+ return (error);
+ return (0);
+}
+
+static int
+pxa_teardown_intr(device_t dev, device_t child, struct resource *ires,
+ void *cookie)
+{
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, ires, cookie));}
+
+static int
+pxa_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct obio_device *od;
+
+ od = (struct obio_device *)device_get_ivars(child);
+
+ switch (which) {
+ case PXA_IVAR_BASE:
+ *((u_long *)result) = od->od_base;
+ break;
+
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+static struct resource_list *
+pxa_get_resource_list(device_t dev, device_t child)
+{
+ struct obio_device *od;
+
+ od = (struct obio_device *)device_get_ivars(child);
+
+ if (od == NULL)
+ return (NULL);
+
+ return (&od->od_resources);
+}
+
+static struct resource *
+pxa_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct obio_softc *sc;
+ struct obio_device *od;
+ struct resource *rv;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+ struct rman *rm;
+ int needactivate;
+
+ sc = (struct obio_softc *)device_get_softc(dev);
+ od = (struct obio_device *)device_get_ivars(child);
+ rl = &od->od_resources;
+
+ rle = resource_list_find(rl, type, *rid);
+ if (rle == NULL) {
+ /* We can allocate GPIO-based IRQs lazily. */
+ if (type == SYS_RES_IRQ)
+ return (pxa_alloc_gpio_irq(dev, child, type, rid,
+ start, end, count, flags));
+ return (NULL);
+ }
+ if (rle->res != NULL)
+ panic("pxa_alloc_resource: resource is busy");
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ rm = &sc->obio_irq;
+ break;
+
+ case SYS_RES_MEMORY:
+ rm = &sc->obio_mem;
+ break;
+
+ default:
+ return (NULL);
+ }
+
+ needactivate = flags & RF_ACTIVE;
+ flags &= ~RF_ACTIVE;
+ rv = rman_reserve_resource(rm, rle->start, rle->end, rle->count, flags,
+ child);
+ if (rv == NULL)
+ return (NULL);
+ rle->res = rv;
+ rman_set_rid(rv, *rid);
+ if (type == SYS_RES_MEMORY) {
+ rman_set_bustag(rv, sc->obio_bst);
+ rman_set_bushandle(rv, rle->start);
+ }
+
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+
+ return (rv);
+}
+
+static int
+pxa_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct obio_device *od;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+
+ od = (struct obio_device *)device_get_ivars(child);
+ rl = &od->od_resources;
+
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ rle = resource_list_find(rl, type, rid);
+
+ if (!rle)
+ panic("pxa_release_resource: can't find resource");
+ if (!rle->res)
+ panic("pxa_release_resource: resource entry is not busy");
+
+ rman_release_resource(rle->res);
+ rle->res = NULL;
+
+ return (0);
+}
+
+static int
+pxa_activate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ return (rman_activate_resource(r));
+}
+
+static device_method_t pxa_methods[] = {
+ DEVMETHOD(device_identify, pxa_identify),
+ DEVMETHOD(device_probe, pxa_probe),
+ DEVMETHOD(device_attach, pxa_attach),
+
+ DEVMETHOD(bus_print_child, pxa_print_child),
+
+ DEVMETHOD(bus_read_ivar, pxa_read_ivar),
+ DEVMETHOD(bus_setup_intr, pxa_setup_intr),
+ DEVMETHOD(bus_teardown_intr, pxa_teardown_intr),
+
+ DEVMETHOD(bus_get_resource_list, pxa_get_resource_list),
+ DEVMETHOD(bus_alloc_resource, pxa_alloc_resource),
+ DEVMETHOD(bus_release_resource, pxa_release_resource),
+ DEVMETHOD(bus_activate_resource, pxa_activate_resource),
+
+ {0, 0}
+};
+
+static driver_t pxa_driver = {
+ "pxa",
+ pxa_methods,
+ sizeof(struct obio_softc),
+};
+
+static devclass_t pxa_devclass;
+
+DRIVER_MODULE(pxa, nexus, pxa_driver, pxa_devclass, 0, 0);
+
+static struct resource *
+pxa_alloc_gpio_irq(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct obio_softc *sc;
+ struct obio_device *od;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+ struct resource *rv;
+ struct rman *rm;
+ int needactivate;
+
+ sc = device_get_softc(dev);
+ od = device_get_ivars(child);
+ rl = &od->od_resources;
+ rm = &sc->obio_irq;
+
+ needactivate = flags & RF_ACTIVE;
+ flags &= ~RF_ACTIVE;
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == NULL)
+ return (NULL);
+
+ resource_list_add(rl, type, *rid, start, end, count);
+ rle = resource_list_find(rl, type, *rid);
+ if (rle == NULL)
+ panic("pxa_alloc_gpio_irq: unexpectedly can't find resource");
+
+ rle->res = rv;
+ rle->start = rman_get_start(rv);
+ rle->end = rman_get_end(rv);
+ rle->count = count;
+
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+
+ if (bootverbose)
+ device_printf(dev, "lazy allocation of irq %ld for %s\n",
+ start, device_get_nameunit(child));
+
+ return (rv);
+}
Property changes on: trunk/sys/arm/xscale/pxa/pxa_obio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxa_smi.c
===================================================================
--- trunk/sys/arm/xscale/pxa/pxa_smi.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxa_smi.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,357 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/pxa_smi.c 241885 2012-10-22 13:06:09Z eadler $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <arm/xscale/pxa/pxavar.h>
+#include <arm/xscale/pxa/pxareg.h>
+
+static MALLOC_DEFINE(M_PXASMI, "PXA SMI",
+ "Data for static memory interface devices.");
+
+struct pxa_smi_softc {
+ struct resource *ps_res[1];
+ struct rman ps_mem;
+ bus_space_tag_t ps_bst;
+ bus_addr_t ps_base;
+};
+
+struct smi_ivars {
+ struct resource_list smid_resources;
+ bus_addr_t smid_mem;
+};
+
+static struct resource_spec pxa_smi_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static int pxa_smi_probe(device_t);
+static int pxa_smi_attach(device_t);
+
+static int pxa_smi_print_child(device_t, device_t);
+
+static int pxa_smi_read_ivar(device_t, device_t, int, uintptr_t *);
+
+static struct resource * pxa_smi_alloc_resource(device_t, device_t,
+ int, int *, u_long, u_long, u_long, u_int);
+static int pxa_smi_release_resource(device_t, device_t,
+ int, int, struct resource *);
+static int pxa_smi_activate_resource(device_t, device_t,
+ int, int, struct resource *);
+
+static void pxa_smi_add_device(device_t, const char *, int);
+
+static int
+pxa_smi_probe(device_t dev)
+{
+
+ if (resource_disabled("smi", device_get_unit(dev)))
+ return (ENXIO);
+
+ device_set_desc(dev, "Static Memory Interface");
+ return (0);
+}
+
+static int
+pxa_smi_attach(device_t dev)
+{
+ int error, i, dunit;
+ const char *dname;
+ struct pxa_smi_softc *sc;
+
+ sc = (struct pxa_smi_softc *)device_get_softc(dev);
+
+ error = bus_alloc_resources(dev, pxa_smi_spec, sc->ps_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->ps_mem.rm_type = RMAN_ARRAY;
+ sc->ps_mem.rm_descr = device_get_nameunit(dev);
+ if (rman_init(&sc->ps_mem) != 0)
+ panic("pxa_smi_attach: failed to init mem rman");
+ if (rman_manage_region(&sc->ps_mem, 0, PXA2X0_CS_SIZE * 6) != 0)
+ panic("pxa_smi_attach: failed ot set up mem rman");
+
+ sc->ps_bst = base_tag;
+ sc->ps_base = rman_get_start(sc->ps_res[0]);
+
+ i = 0;
+ while (resource_find_match(&i, &dname, &dunit, "at",
+ device_get_nameunit(dev)) == 0) {
+ pxa_smi_add_device(dev, dname, dunit);
+ }
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static int
+pxa_smi_print_child(device_t dev, device_t child)
+{
+ struct smi_ivars *smid;
+ int retval;
+
+ smid = (struct smi_ivars *)device_get_ivars(child);
+ if (smid == NULL) {
+ device_printf(dev, "unknown device: %s\n",
+ device_get_nameunit(child));
+ return (0);
+ }
+
+ retval = 0;
+
+ retval += bus_print_child_header(dev, child);
+
+ retval += resource_list_print_type(&smid->smid_resources, "at mem",
+ SYS_RES_MEMORY, "%#lx");
+ retval += resource_list_print_type(&smid->smid_resources, "irq",
+ SYS_RES_IRQ, "%ld");
+
+ retval += bus_print_child_footer(dev, child);
+
+ return (retval);
+}
+
+static int
+pxa_smi_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct pxa_smi_softc *sc;
+ struct smi_ivars *smid;
+
+ sc = device_get_softc(dev);
+ smid = device_get_ivars(child);
+
+ switch (which) {
+ case SMI_IVAR_PHYSBASE:
+ *((bus_addr_t *)result) = smid->smid_mem;
+ break;
+
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+static struct resource *
+pxa_smi_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct pxa_smi_softc *sc;
+ struct smi_ivars *smid;
+ struct resource *rv;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+ int needactivate;
+
+ sc = (struct pxa_smi_softc *)device_get_softc(dev);
+ smid = (struct smi_ivars *)device_get_ivars(child);
+ rl = &smid->smid_resources;
+
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ rle = resource_list_find(rl, type, *rid);
+ if (rle == NULL)
+ return (NULL);
+ if (rle->res != NULL)
+ panic("pxa_smi_alloc_resource: resource is busy");
+
+ needactivate = flags & RF_ACTIVE;
+ flags &= ~RF_ACTIVE;
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ rv = rman_reserve_resource(&sc->ps_mem, rle->start, rle->end,
+ rle->count, flags, child);
+ if (rv == NULL)
+ return (NULL);
+ rle->res = rv;
+ rman_set_rid(rv, *rid);
+ rman_set_bustag(rv, sc->ps_bst);
+ rman_set_bushandle(rv, rle->start);
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv) != 0) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+
+ break;
+
+ case SYS_RES_IRQ:
+ rv = bus_alloc_resource(dev, type, rid, rle->start, rle->end,
+ rle->count, flags);
+ if (rv == NULL)
+ return (NULL);
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv) != 0) {
+ bus_release_resource(dev, type, *rid, rv);
+ return (NULL);
+ }
+ }
+
+ break;
+
+ default:
+ return (NULL);
+ }
+
+ return (rv);
+}
+
+static int
+pxa_smi_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct smi_ivars *smid;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+
+ if (type == SYS_RES_IRQ)
+ return (bus_release_resource(dev, SYS_RES_IRQ, rid, r));
+
+ smid = (struct smi_ivars *)device_get_ivars(child);
+ rl = &smid->smid_resources;
+
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ rle = resource_list_find(rl, type, rid);
+ if (rle == NULL)
+ panic("pxa_smi_release_resource: can't find resource");
+ if (rle->res == NULL)
+ panic("pxa_smi_release_resource: resource entry not busy");
+
+ rman_release_resource(rle->res);
+ rle->res = NULL;
+
+ return (0);
+}
+
+static int
+pxa_smi_activate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct pxa_smi_softc *sc;
+
+ sc = (struct pxa_smi_softc *)device_get_softc(dev);
+
+ if (type == SYS_RES_IRQ)
+ return (bus_activate_resource(dev, SYS_RES_IRQ, rid, r));
+
+ rman_set_bushandle(r, (bus_space_handle_t)pmap_mapdev(rman_get_start(r),
+ rman_get_size(r)));
+ return (rman_activate_resource(r));
+}
+
+static device_method_t pxa_smi_methods[] = {
+ DEVMETHOD(device_probe, pxa_smi_probe),
+ DEVMETHOD(device_attach, pxa_smi_attach),
+
+ DEVMETHOD(bus_print_child, pxa_smi_print_child),
+
+ DEVMETHOD(bus_read_ivar, pxa_smi_read_ivar),
+
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+
+ DEVMETHOD(bus_alloc_resource, pxa_smi_alloc_resource),
+ DEVMETHOD(bus_release_resource, pxa_smi_release_resource),
+ DEVMETHOD(bus_activate_resource, pxa_smi_activate_resource),
+
+ {0, 0}
+};
+
+static driver_t pxa_smi_driver = {
+ "smi",
+ pxa_smi_methods,
+ sizeof(struct pxa_smi_softc),
+};
+
+static devclass_t pxa_smi_devclass;
+
+DRIVER_MODULE(smi, pxa, pxa_smi_driver, pxa_smi_devclass, 0, 0);
+
+static void
+pxa_smi_add_device(device_t dev, const char *name, int unit)
+{
+ device_t child;
+ int start, count;
+ struct smi_ivars *ivars;
+
+ ivars = (struct smi_ivars *)malloc(
+ sizeof(struct smi_ivars), M_PXASMI, M_WAITOK);
+ if (ivars == NULL)
+ return;
+
+ child = device_add_child(dev, name, unit);
+ if (child == NULL) {
+ free(ivars, M_PXASMI);
+ return;
+ }
+
+ device_set_ivars(child, ivars);
+ resource_list_init(&ivars->smid_resources);
+
+ start = 0;
+ count = 0;
+ resource_int_value(name, unit, "mem", &start);
+ resource_int_value(name, unit, "size", &count);
+ if (start > 0 || count > 0) {
+ resource_list_add(&ivars->smid_resources, SYS_RES_MEMORY, 0,
+ start, start + count, count);
+ ivars->smid_mem = (bus_addr_t)start;
+ }
+
+ start = -1;
+ count = 0;
+ resource_int_value(name, unit, "irq", &start);
+ if (start > -1)
+ resource_list_add(&ivars->smid_resources, SYS_RES_IRQ, 0, start,
+ start, 1);
+
+ if (resource_disabled(name, unit))
+ device_disable(child);
+}
Property changes on: trunk/sys/arm/xscale/pxa/pxa_smi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxa_space.c
===================================================================
--- trunk/sys/arm/xscale/pxa/pxa_space.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxa_space.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,269 @@
+/* $MidnightBSD$ */
+/* $NetBSD: obio_space.c,v 1.6 2003/07/15 00:25:05 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * bus_space functions for PXA devices
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/pxa_space.c 278727 2015-02-13 22:32:02Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+#include <arm/xscale/pxa/pxareg.h>
+#include <arm/xscale/pxa/pxavar.h>
+
+static MALLOC_DEFINE(M_PXATAG, "PXA bus_space tags", "Bus_space tags for PXA");
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(generic);
+bs_protos(pxa);
+
+/*
+ * The obio bus space tag. This is constant for all instances, so
+ * we never have to explicitly "create" it.
+ */
+struct bus_space _base_tag = {
+ /* cookie */
+ .bs_privdata = NULL,
+
+ /* mapping/unmapping */
+ .bs_map = generic_bs_map,
+ .bs_unmap = generic_bs_unmap,
+ .bs_subregion = generic_bs_subregion,
+
+ /* allocation/deallocation */
+ .bs_alloc = generic_bs_alloc,
+ .bs_free = generic_bs_free,
+
+ /* barrier */
+ .bs_barrier = generic_bs_barrier,
+
+ /* read (single) */
+ .bs_r_1 = pxa_bs_r_1,
+ .bs_r_2 = pxa_bs_r_2,
+ .bs_r_4 = pxa_bs_r_4,
+ .bs_r_8 = BS_UNIMPLEMENTED,
+
+ /* read multiple */
+ .bs_rm_1 = pxa_bs_rm_1,
+ .bs_rm_2 = pxa_bs_rm_2,
+ .bs_rm_4 = BS_UNIMPLEMENTED,
+ .bs_rm_8 = BS_UNIMPLEMENTED,
+
+ /* read region */
+ .bs_rr_1 = pxa_bs_rr_1,
+ .bs_rr_2 = BS_UNIMPLEMENTED,
+ .bs_rr_4 = BS_UNIMPLEMENTED,
+ .bs_rr_8 = BS_UNIMPLEMENTED,
+
+ /* write (single) */
+ .bs_w_1 = pxa_bs_w_1,
+ .bs_w_2 = pxa_bs_w_2,
+ .bs_w_4 = pxa_bs_w_4,
+ .bs_w_8 = BS_UNIMPLEMENTED,
+
+ /* write multiple */
+ .bs_wm_1 = pxa_bs_wm_1,
+ .bs_wm_2 = pxa_bs_wm_2,
+ .bs_wm_4 = BS_UNIMPLEMENTED,
+ .bs_wm_8 = BS_UNIMPLEMENTED,
+
+ /* write region */
+ .bs_wr_1 = BS_UNIMPLEMENTED,
+ .bs_wr_2 = BS_UNIMPLEMENTED,
+ .bs_wr_4 = BS_UNIMPLEMENTED,
+ .bs_wr_8 = BS_UNIMPLEMENTED,
+
+ /* set multiple */
+ .bs_sm_1 = BS_UNIMPLEMENTED,
+ .bs_sm_2 = BS_UNIMPLEMENTED,
+ .bs_sm_4 = BS_UNIMPLEMENTED,
+ .bs_sm_8 = BS_UNIMPLEMENTED,
+
+ /* set region */
+ .bs_sr_1 = BS_UNIMPLEMENTED,
+ .bs_sr_2 = BS_UNIMPLEMENTED,
+ .bs_sr_4 = BS_UNIMPLEMENTED,
+ .bs_sr_8 = BS_UNIMPLEMENTED,
+
+ /* copy */
+ .bs_c_1 = BS_UNIMPLEMENTED,
+ .bs_c_2 = BS_UNIMPLEMENTED,
+ .bs_c_4 = BS_UNIMPLEMENTED,
+ .bs_c_8 = BS_UNIMPLEMENTED,
+
+ /* read stream (single) */
+ .bs_r_1_s = BS_UNIMPLEMENTED,
+ .bs_r_2_s = BS_UNIMPLEMENTED,
+ .bs_r_4_s = BS_UNIMPLEMENTED,
+ .bs_r_8_s = BS_UNIMPLEMENTED,
+
+ /* read multiple stream */
+ .bs_rm_1_s = BS_UNIMPLEMENTED,
+ .bs_rm_2_s = BS_UNIMPLEMENTED,
+ .bs_rm_4_s = BS_UNIMPLEMENTED,
+ .bs_rm_8_s = BS_UNIMPLEMENTED,
+
+ /* read region stream */
+ .bs_rr_1_s = BS_UNIMPLEMENTED,
+ .bs_rr_2_s = BS_UNIMPLEMENTED,
+ .bs_rr_4_s = BS_UNIMPLEMENTED,
+ .bs_rr_8_s = BS_UNIMPLEMENTED,
+
+ /* write stream (single) */
+ .bs_w_1_s = BS_UNIMPLEMENTED,
+ .bs_w_2_s = BS_UNIMPLEMENTED,
+ .bs_w_4_s = BS_UNIMPLEMENTED,
+ .bs_w_8_s = BS_UNIMPLEMENTED,
+
+ /* write multiple stream */
+ .bs_wm_1_s = BS_UNIMPLEMENTED,
+ .bs_wm_2_s = BS_UNIMPLEMENTED,
+ .bs_wm_4_s = BS_UNIMPLEMENTED,
+ .bs_wm_8_s = BS_UNIMPLEMENTED,
+
+ /* write region stream */
+ .bs_wr_1_s = BS_UNIMPLEMENTED,
+ .bs_wr_2_s = BS_UNIMPLEMENTED,
+ .bs_wr_4_s = BS_UNIMPLEMENTED,
+ .bs_wr_8_s = BS_UNIMPLEMENTED,
+};
+
+static struct bus_space _obio_tag;
+
+bus_space_tag_t base_tag = &_base_tag;
+bus_space_tag_t obio_tag = NULL;
+
+void
+pxa_obio_tag_init()
+{
+
+ bcopy(&_base_tag, &_obio_tag, sizeof(struct bus_space));
+ _obio_tag.bs_privdata = (void *)PXA2X0_PERIPH_OFFSET;
+ obio_tag = &_obio_tag;
+}
+
+bus_space_tag_t
+pxa_bus_tag_alloc(bus_addr_t offset)
+{
+ struct bus_space *tag;
+
+ tag = (struct bus_space *)malloc(sizeof(struct bus_space), M_PXATAG,
+ M_WAITOK);
+ if (tag == NULL) {
+ return (NULL);
+ }
+
+ bcopy(&_base_tag, tag, sizeof(struct bus_space));
+ tag->bs_privdata = (void *)offset;
+
+ return ((bus_space_tag_t)tag);
+}
+
+
+#define READ_SINGLE(type, proto, base) \
+ type \
+ proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset) \
+ { \
+ bus_addr_t tag_offset; \
+ type value; \
+ tag_offset = (bus_addr_t)tag->bs_privdata; \
+ value = base(NULL, bsh + tag_offset, offset); \
+ return (value); \
+ }
+
+READ_SINGLE(u_int8_t, pxa_bs_r_1, generic_bs_r_1)
+READ_SINGLE(u_int16_t, pxa_bs_r_2, generic_bs_r_2)
+READ_SINGLE(u_int32_t, pxa_bs_r_4, generic_bs_r_4)
+
+#undef READ_SINGLE
+
+#define WRITE_SINGLE(type, proto, base) \
+ void \
+ proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \
+ type value) \
+ { \
+ bus_addr_t tag_offset; \
+ tag_offset = (bus_addr_t)tag->bs_privdata; \
+ base(NULL, bsh + tag_offset, offset, value); \
+ }
+
+WRITE_SINGLE(u_int8_t, pxa_bs_w_1, generic_bs_w_1)
+WRITE_SINGLE(u_int16_t, pxa_bs_w_2, generic_bs_w_2)
+WRITE_SINGLE(u_int32_t, pxa_bs_w_4, generic_bs_w_4)
+
+#undef WRITE_SINGLE
+
+#define READ_MULTI(type, proto, base) \
+ void \
+ proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \
+ type *dest, bus_size_t count) \
+ { \
+ bus_addr_t tag_offset; \
+ tag_offset = (bus_addr_t)tag->bs_privdata; \
+ base(NULL, bsh + tag_offset, offset, dest, count); \
+ }
+
+READ_MULTI(u_int8_t, pxa_bs_rm_1, generic_bs_rm_1)
+READ_MULTI(u_int16_t, pxa_bs_rm_2, generic_bs_rm_2)
+
+READ_MULTI(u_int8_t, pxa_bs_rr_1, generic_bs_rr_1)
+
+#undef READ_MULTI
+
+#define WRITE_MULTI(type, proto, base) \
+ void \
+ proto(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, \
+ const type *src, bus_size_t count) \
+ { \
+ bus_addr_t tag_offset; \
+ tag_offset = (bus_addr_t)tag->bs_privdata; \
+ base(NULL, bsh + tag_offset, offset, src, count); \
+ }
+
+WRITE_MULTI(u_int8_t, pxa_bs_wm_1, generic_bs_wm_1)
+WRITE_MULTI(u_int16_t, pxa_bs_wm_2, generic_bs_wm_2)
+
+#undef WRITE_MULTI
Property changes on: trunk/sys/arm/xscale/pxa/pxa_space.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxa_timer.c
===================================================================
--- trunk/sys/arm/xscale/pxa/pxa_timer.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxa_timer.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,319 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/pxa_timer.c 278613 2015-02-12 03:50:33Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+#include <machine/armreg.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <arm/xscale/pxa/pxavar.h>
+#include <arm/xscale/pxa/pxareg.h>
+
+#define PXA_TIMER_FREQUENCY 3686400
+#define PXA_TIMER_TICK (PXA_TIMER_FREQUENCY / hz)
+
+struct pxa_timer_softc {
+ struct resource * pt_res[5];
+ bus_space_tag_t pt_bst;
+ bus_space_handle_t pt_bsh;
+};
+
+static struct resource_spec pxa_timer_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 1, RF_ACTIVE },
+ { SYS_RES_IRQ, 2, RF_ACTIVE },
+ { SYS_RES_IRQ, 3, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct pxa_timer_softc *timer_softc = NULL;
+
+static int pxa_timer_probe(device_t);
+static int pxa_timer_attach(device_t);
+
+static driver_filter_t pxa_hardclock;
+
+static unsigned pxa_timer_get_timecount(struct timecounter *);
+
+uint32_t pxa_timer_get_osmr(int);
+void pxa_timer_set_osmr(int, uint32_t);
+uint32_t pxa_timer_get_oscr(void);
+void pxa_timer_set_oscr(uint32_t);
+uint32_t pxa_timer_get_ossr(void);
+void pxa_timer_clear_ossr(uint32_t);
+void pxa_timer_watchdog_enable(void);
+void pxa_timer_watchdog_disable(void);
+void pxa_timer_interrupt_enable(int);
+void pxa_timer_interrupt_disable(int);
+
+static struct timecounter pxa_timer_timecounter = {
+ .tc_get_timecount = pxa_timer_get_timecount,
+ .tc_name = "OS Timer",
+ .tc_frequency = PXA_TIMER_FREQUENCY,
+ .tc_counter_mask = ~0u,
+ .tc_quality = 1000,
+};
+
+static int
+pxa_timer_probe(device_t dev)
+{
+
+ device_set_desc(dev, "OS Timer");
+ return (0);
+}
+
+static int
+pxa_timer_attach(device_t dev)
+{
+ int error;
+ void *ihl;
+ struct pxa_timer_softc *sc;
+
+ sc = (struct pxa_timer_softc *)device_get_softc(dev);
+
+ if (timer_softc != NULL)
+ return (ENXIO);
+
+ error = bus_alloc_resources(dev, pxa_timer_spec, sc->pt_res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->pt_bst = rman_get_bustag(sc->pt_res[0]);
+ sc->pt_bsh = rman_get_bushandle(sc->pt_res[0]);
+
+ timer_softc = sc;
+
+ pxa_timer_interrupt_disable(-1);
+ pxa_timer_watchdog_disable();
+
+ if (bus_setup_intr(dev, sc->pt_res[1], INTR_TYPE_CLK,
+ pxa_hardclock, NULL, NULL, &ihl) != 0) {
+ bus_release_resources(dev, pxa_timer_spec, sc->pt_res);
+ device_printf(dev, "could not setup hardclock interrupt\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+pxa_hardclock(void *arg)
+{
+ struct trapframe *frame;
+
+ frame = (struct trapframe *)arg;
+
+ /* Clear the interrupt */
+ pxa_timer_clear_ossr(OST_SR_CH0);
+
+ /* Schedule next tick */
+ pxa_timer_set_osmr(0, pxa_timer_get_oscr() + PXA_TIMER_TICK);
+
+ /* Do what we came here for */
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+
+ return (FILTER_HANDLED);
+}
+
+static device_method_t pxa_timer_methods[] = {
+ DEVMETHOD(device_probe, pxa_timer_probe),
+ DEVMETHOD(device_attach, pxa_timer_attach),
+
+ {0, 0}
+};
+
+static driver_t pxa_timer_driver = {
+ "timer",
+ pxa_timer_methods,
+ sizeof(struct pxa_timer_softc),
+};
+
+static devclass_t pxa_timer_devclass;
+
+DRIVER_MODULE(pxatimer, pxa, pxa_timer_driver, pxa_timer_devclass, 0, 0);
+
+static unsigned
+pxa_timer_get_timecount(struct timecounter *tc)
+{
+
+ return (pxa_timer_get_oscr());
+}
+
+void
+cpu_initclocks(void)
+{
+
+ pxa_timer_set_oscr(0);
+ pxa_timer_set_osmr(0, PXA_TIMER_TICK);
+ pxa_timer_interrupt_enable(0);
+
+ tc_init(&pxa_timer_timecounter);
+}
+
+void
+cpu_reset(void)
+{
+ uint32_t val;
+
+ (void)disable_interrupts(PSR_I|PSR_F);
+
+ val = pxa_timer_get_oscr();
+ val += PXA_TIMER_FREQUENCY;
+ pxa_timer_set_osmr(3, val);
+ pxa_timer_watchdog_enable();
+
+ for(;;);
+}
+
+void
+DELAY(int usec)
+{
+ uint32_t val;
+
+ if (timer_softc == NULL) {
+ for (; usec > 0; usec--)
+ for (val = 100; val > 0; val--)
+ ;
+ return;
+ }
+
+ val = pxa_timer_get_oscr();
+ val += (PXA_TIMER_FREQUENCY * usec) / 1000000;
+ while (pxa_timer_get_oscr() <= val);
+}
+
+uint32_t
+pxa_timer_get_osmr(int which)
+{
+
+ return (bus_space_read_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, which * 0x4));
+}
+
+void
+pxa_timer_set_osmr(int which, uint32_t val)
+{
+
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, which * 0x4, val);
+}
+
+uint32_t
+pxa_timer_get_oscr()
+{
+
+ return (bus_space_read_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_CR));
+}
+
+void
+pxa_timer_set_oscr(uint32_t val)
+{
+
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_CR, val);
+}
+
+uint32_t
+pxa_timer_get_ossr()
+{
+
+ return (bus_space_read_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_SR));
+}
+
+void
+pxa_timer_clear_ossr(uint32_t val)
+{
+
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_SR, val);
+}
+
+void
+pxa_timer_watchdog_enable()
+{
+
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_WR, 0x1);
+}
+
+void
+pxa_timer_watchdog_disable()
+{
+
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_WR, 0x0);
+}
+
+void
+pxa_timer_interrupt_enable(int which)
+{
+ uint32_t oier;
+
+ if (which == -1) {
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_IR, 0xf);
+ return;
+ }
+
+ oier = bus_space_read_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_IR);
+ oier |= 1 << which;
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_IR, oier);
+}
+
+void
+pxa_timer_interrupt_disable(int which)
+{
+ uint32_t oier;
+
+ if (which == -1) {
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_IR, 0);
+ }
+
+ oier = bus_space_read_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_IR);
+ oier &= ~(1 << which);
+ bus_space_write_4(timer_softc->pt_bst,
+ timer_softc->pt_bsh, OST_IR, oier);
+}
Property changes on: trunk/sys/arm/xscale/pxa/pxa_timer.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxareg.h
===================================================================
--- trunk/sys/arm/xscale/pxa/pxareg.h (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxareg.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,757 @@
+/* $MidnightBSD$ */
+/* $NetBSD: pxa2x0reg.h,v 1.9 2006/04/10 04:13:58 simonb Exp $ */
+
+/*
+ * Copyright (c) 2002 Genetec Corporation. All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Genetec Corporation.
+ * 4. The name of Genetec Corporation may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/pxa/pxareg.h 266311 2014-05-17 13:53:38Z ian $
+ */
+
+
+/*
+ * Intel PXA2[15]0 processor is XScale based integrated CPU
+ *
+ * Reference:
+ * Intel(r) PXA250 and PXA210 Application Processors
+ * Developer's Manual
+ * (278522-001.pdf)
+ */
+#ifndef _ARM_XSCALE_PXAREG_H_
+#define _ARM_XSCALE_PXAREG_H_
+
+#ifndef _LOCORE
+#include <sys/types.h> /* for uint32_t */
+#endif
+
+/*
+ * Chip select domains
+ */
+#define PXA2X0_CS0_START 0x00000000
+#define PXA2X0_CS1_START 0x04000000
+#define PXA2X0_CS2_START 0x08000000
+#define PXA2X0_CS3_START 0x0c000000
+#define PXA2X0_CS4_START 0x10000000
+#define PXA2X0_CS5_START 0x14000000
+#define PXA2X0_CS_SIZE 0x04000000
+
+#define PXA2X0_PCMCIA_SLOT0 0x20000000
+#define PXA2X0_PCMCIA_SLOT1 0x30000000
+
+#define PXA2X0_PERIPH_START 0x40000000
+/* #define PXA2X0_MEMCTL_START 0x48000000 */
+#define PXA270_PERIPH_END 0x530fffff
+#define PXA250_PERIPH_END 0x480fffff
+#define PXA2X0_PERIPH_OFFSET 0xa8000000
+
+#define PXA2X0_SDRAM0_START 0xa0000000
+#define PXA2X0_SDRAM1_START 0xa4000000
+#define PXA2X0_SDRAM2_START 0xa8000000
+#define PXA2X0_SDRAM3_START 0xac000000
+#define PXA2X0_SDRAM_BANKS 4
+#define PXA2X0_SDRAM_BANK_SIZE 0x04000000
+
+/*
+ * Physical address of integrated peripherals
+ */
+
+#define PXA2X0_DMAC_BASE 0x40000000
+#define PXA2X0_DMAC_SIZE 0x300
+#define PXA2X0_FFUART_BASE 0x40100000 /* Full Function UART */
+#define PXA2X0_FFUART_SIZE 0x20
+#define PXA2X0_BTUART_BASE 0x40200000 /* Bluetooth UART */
+#define PXA2X0_BTUART_SIZE 0x24
+#define PXA2X0_I2C_BASE 0x40300000
+#define PXA2X0_I2C_SIZE 0x000016a4
+#define PXA2X0_I2S_BASE 0x40400000
+#define PXA2X0_AC97_BASE 0x40500000
+#define PXA2X0_AC97_SIZE 0x600
+#define PXA2X0_USBDC_BASE 0x40600000 /* USB Client */
+#define PXA2X0_USBDC_SIZE 0x0e04
+#define PXA2X0_STUART_BASE 0x40700000 /* Standard UART */
+#define PXA2X0_STUART_SIZE 0x24
+#define PXA2X0_ICP_BASE 0x40800000
+#define PXA2X0_RTC_BASE 0x40900000
+#define PXA2X0_RTC_SIZE 0x10
+#define PXA2X0_OST_BASE 0x40a00000 /* OS Timer */
+#define PXA2X0_OST_SIZE 0x20
+#define PXA2X0_PWM0_BASE 0x40b00000
+#define PXA2X0_PWM1_BASE 0x40c00000
+#define PXA2X0_INTCTL_BASE 0x40d00000 /* Interrupt controller */
+#define PXA2X0_INTCTL_SIZE 0x20
+#define PXA2X0_GPIO_BASE 0x40e00000
+
+#define PXA270_GPIO_SIZE 0x150
+#define PXA250_GPIO_SIZE 0x70
+#define PXA2X0_POWMAN_BASE 0x40f00000 /* Power management */
+#define PXA2X0_SSP_BASE 0x41000000
+#define PXA2X0_MMC_BASE 0x41100000 /* MultiMediaCard */
+#define PXA2X0_MMC_SIZE 0x48
+#define PXA2X0_CLKMAN_BASE 0x41300000 /* Clock Manager */
+#define PXA2X0_CLKMAN_SIZE 12
+#define PXA2X0_HWUART_BASE 0x41600000 /* Hardware UART */
+#define PXA2X0_HWUART_SIZE 0x30
+#define PXA2X0_LCDC_BASE 0x44000000 /* LCD Controller */
+#define PXA2X0_LCDC_SIZE 0x220
+#define PXA2X0_MEMCTL_BASE 0x48000000 /* Memory Controller */
+#define PXA2X0_MEMCTL_SIZE 0x48
+#define PXA2X0_USBH_BASE 0x4c000000 /* USB Host controller */
+#define PXA2X0_USBH_SIZE 0x70
+
+/* Internal SRAM storage. PXA27x only */
+#define PXA270_SRAM0_START 0x5c000000
+#define PXA270_SRAM1_START 0x5c010000
+#define PXA270_SRAM2_START 0x5c020000
+#define PXA270_SRAM3_START 0x5c030000
+#define PXA270_SRAM_BANKS 4
+#define PXA270_SRAM_BANK_SIZE 0x00010000
+
+/* width of interrupt controller */
+#define ICU_LEN 32 /* but [0..7,15,16] is not used */
+#define ICU_INT_HWMASK 0xffffff00
+#define PXA250_IRQ_MIN 8 /* 0..7 are not used by integrated
+ peripherals */
+#define PXA270_IRQ_MIN 0
+
+#define PXA2X0_INT_USBH1 3 /* USB host (OHCI) */
+
+#define PXA2X0_INT_HWUART 7
+#define PXA2X0_INT_GPIO0 8
+#define PXA2X0_INT_GPIO1 9
+#define PXA2X0_INT_GPION 10 /* irq from GPIO[2..80] */
+#define PXA2X0_INT_USB 11
+#define PXA2X0_INT_PMU 12
+#define PXA2X0_INT_I2S 13
+#define PXA2X0_INT_AC97 14
+#define PXA2X0_INT_LCD 17
+#define PXA2X0_INT_I2C 18
+#define PXA2X0_INT_ICP 19
+#define PXA2X0_INT_STUART 20
+#define PXA2X0_INT_BTUART 21
+#define PXA2X0_INT_FFUART 22
+#define PXA2X0_INT_MMC 23
+#define PXA2X0_INT_SSP 24
+#define PXA2X0_INT_DMA 25
+#define PXA2X0_INT_OST0 26
+#define PXA2X0_INT_OST1 27
+#define PXA2X0_INT_OST2 28
+#define PXA2X0_INT_OST3 29
+#define PXA2X0_INT_RTCHZ 30
+#define PXA2X0_INT_ALARM 31 /* RTC Alarm interrupt */
+
+/* DMAC */
+#define DMAC_N_CHANNELS 16
+#define DMAC_N_PRIORITIES 3
+
+#define DMAC_DCSR(n) ((n)*4)
+#define DCSR_BUSERRINTR (1<<0) /* bus error interrupt */
+#define DCSR_STARTINTR (1<<1) /* start interrupt */
+#define DCSR_ENDINTR (1<<2) /* end interrupt */
+#define DCSR_STOPSTATE (1<<3) /* channel is not running */
+#define DCSR_REQPEND (1<<8) /* request pending */
+#define DCSR_STOPIRQEN (1<<29) /* stop interrupt enable */
+#define DCSR_NODESCFETCH (1<<30) /* no-descriptor fetch mode */
+#define DCSR_RUN (1<<31)
+#define DMAC_DINT 0x00f0 /* DAM interrupt */
+#define DMAC_DINT_MASK 0xffffu
+#define DMAC_DRCMR(n) (0x100+(n)*4) /* Channel map register */
+#define DRCMR_CHLNUM 0x0f /* channel number */
+#define DRCMR_MAPVLD (1<<7) /* map valid */
+#define DMAC_DDADR(n) (0x0200+(n)*16)
+#define DDADR_STOP (1<<0)
+#define DMAC_DSADR(n) (0x0204+(n)*16)
+#define DMAC_DTADR(n) (0x0208+(n)*16)
+#define DMAC_DCMD(n) (0x020c+(n)*16)
+#define DCMD_LENGTH_MASK 0x1fff
+#define DCMD_WIDTH_SHIFT 14
+#define DCMD_WIDTH_0 (0<<DCMD_WIDTH_SHIFT) /* for mem-to-mem transfer*/
+#define DCMD_WIDTH_1 (1<<DCMD_WIDTH_SHIFT)
+#define DCMD_WIDTH_2 (2<<DCMD_WIDTH_SHIFT)
+#define DCMD_WIDTH_4 (3<<DCMD_WIDTH_SHIFT)
+#define DCMD_SIZE_SHIFT 16
+#define DCMD_SIZE_8 (1<<DCMD_SIZE_SHIFT)
+#define DCMD_SIZE_16 (2<<DCMD_SIZE_SHIFT)
+#define DCMD_SIZE_32 (3<<DCMD_SIZE_SHIFT)
+#define DCMD_LITTLE_ENDIEN (0<<18)
+#define DCMD_ENDIRQEN (1<<21)
+#define DCMD_STARTIRQEN (1<<22)
+#define DCMD_FLOWTRG (1<<28) /* flow control by target */
+#define DCMD_FLOWSRC (1<<29) /* flow control by source */
+#define DCMD_INCTRGADDR (1<<30) /* increment target address */
+#define DCMD_INCSRCADDR (1<<31) /* increment source address */
+
+#ifndef __ASSEMBLER__
+/* DMA descriptor */
+struct pxa_dma_desc {
+ volatile uint32_t dd_ddadr;
+#define DMAC_DESC_LAST 0x1
+ volatile uint32_t dd_dsadr;
+ volatile uint32_t dd_dtadr;
+ volatile uint32_t dd_dcmd; /* command and length */
+};
+#endif
+
+/* UART */
+#define PXA2X0_COM_FREQ 14745600L
+
+/* I2C */
+#define I2C_IBMR 0x1680 /* Bus monitor register */
+#define I2C_IDBR 0x1688 /* Data buffer */
+#define I2C_ICR 0x1690 /* Control register */
+#define ICR_START (1<<0)
+#define ICR_STOP (1<<1)
+#define ICR_ACKNAK (1<<2)
+#define ICR_TB (1<<3)
+#define ICR_MA (1<<4)
+#define I2C_ISR 0x1698 /* Status register */
+#define I2C_ISAR 0x16a0 /* Slave address */
+
+/* Clock Manager */
+#define CLKMAN_CCCR 0x00 /* Core Clock Configuration */
+#define CCCR_TURBO_X1 (2<<7)
+#define CCCR_TURBO_X15 (3<<7) /* x 1.5 */
+#define CCCR_TURBO_X2 (4<<7)
+#define CCCR_TURBO_X25 (5<<7) /* x 2.5 */
+#define CCCR_TURBO_X3 (6<<7) /* x 3.0 */
+#define CCCR_RUN_X1 (1<<5)
+#define CCCR_RUN_X2 (2<<5)
+#define CCCR_RUN_X4 (3<<5)
+#define CCCR_MEM_X27 (1<<0) /* x27, 99.53MHz */
+#define CCCR_MEM_X32 (2<<0) /* x32, 117,96MHz */
+#define CCCR_MEM_X36 (3<<0) /* x26, 132.71MHz */
+#define CCCR_MEM_X40 (4<<0) /* x27, 99.53MHz */
+#define CCCR_MEM_X45 (5<<0) /* x27, 99.53MHz */
+#define CCCR_MEM_X9 (0x1f<<0) /* x9, 33.2MHz */
+
+#define CLKMAN_CKEN 0x04 /* Clock Enable Register */
+#define CLKMAN_OSCC 0x08 /* Osillcator Configuration Register */
+
+#define CCCR_N_SHIFT 7
+#define CCCR_N_MASK (0x07<<CCCR_N_SHIFT)
+#define CCCR_M_SHIFT 5
+#define CCCR_M_MASK (0x03<<CCCR_M_SHIFT)
+#define CCCR_L_MASK 0x1f
+
+#define CKEN_PWM0 (1<<0)
+#define CKEN_PWM1 (1<<1)
+#define CKEN_AC97 (1<<2)
+#define CKEN_SSP (1<<3)
+#define CKEN_STUART (1<<5)
+#define CKEN_FFUART (1<<6)
+#define CKEN_BTUART (1<<7)
+#define CKEN_I2S (1<<8)
+#define CKEN_USBH (1<<10)
+#define CKEN_USB (1<<11)
+#define CKEN_MMC (1<<12)
+#define CKEN_FICP (1<<13)
+#define CKEN_I2C (1<<14)
+#define CKEN_LCD (1<<16)
+
+#define OSCC_OOK (1<<0) /* 32.768 kHz oscillator status */
+#define OSCC_OON (1<<1) /* 32.768 kHz oscillator */
+
+/*
+ * RTC
+ */
+#define RTC_RCNR 0x0000 /* count register */
+#define RTC_RTAR 0x0004 /* alarm register */
+#define RTC_RTSR 0x0008 /* status register */
+#define RTC_RTTR 0x000c /* trim register */
+/*
+ * GPIO
+ */
+#define GPIO_GPLR0 0x00 /* Level reg [31:0] */
+#define GPIO_GPLR1 0x04 /* Level reg [63:32] */
+#define GPIO_GPLR2 0x08 /* Level reg [80:64] */
+
+#define GPIO_GPDR0 0x0c /* dir reg [31:0] */
+#define GPIO_GPDR1 0x10 /* dir reg [63:32] */
+#define GPIO_GPDR2 0x14 /* dir reg [80:64] */
+
+#define GPIO_GPSR0 0x18 /* set reg [31:0] */
+#define GPIO_GPSR1 0x1c /* set reg [63:32] */
+#define GPIO_GPSR2 0x20 /* set reg [80:64] */
+
+#define GPIO_GPCR0 0x24 /* clear reg [31:0] */
+#define GPIO_GPCR1 0x28 /* clear reg [63:32] */
+#define GPIO_GPCR2 0x2c /* clear reg [80:64] */
+
+#define GPIO_GPER0 0x30 /* rising edge [31:0] */
+#define GPIO_GPER1 0x34 /* rising edge [63:32] */
+#define GPIO_GPER2 0x38 /* rising edge [80:64] */
+
+#define GPIO_GRER0 0x30 /* rising edge [31:0] */
+#define GPIO_GRER1 0x34 /* rising edge [63:32] */
+#define GPIO_GRER2 0x38 /* rising edge [80:64] */
+
+#define GPIO_GFER0 0x3c /* falling edge [31:0] */
+#define GPIO_GFER1 0x40 /* falling edge [63:32] */
+#define GPIO_GFER2 0x44 /* falling edge [80:64] */
+
+#define GPIO_GEDR0 0x48 /* edge detect [31:0] */
+#define GPIO_GEDR1 0x4c /* edge detect [63:32] */
+#define GPIO_GEDR2 0x50 /* edge detect [80:64] */
+
+#define GPIO_GAFR0_L 0x54 /* alternate function [15:0] */
+#define GPIO_GAFR0_U 0x58 /* alternate function [31:16] */
+#define GPIO_GAFR1_L 0x5c /* alternate function [47:32] */
+#define GPIO_GAFR1_U 0x60 /* alternate function [63:48] */
+#define GPIO_GAFR2_L 0x64 /* alternate function [79:64] */
+#define GPIO_GAFR2_U 0x68 /* alternate function [80] */
+
+/* Only for PXA270 */
+#define GPIO_GAFR3_L 0x6c /* alternate function [111:96] */
+#define GPIO_GAFR3_U 0x70 /* alternate function [120:112] */
+
+#define GPIO_GPLR3 0x100 /* Level reg [120:96] */
+#define GPIO_GPDR3 0x10c /* dir reg [120:96] */
+#define GPIO_GPSR3 0x118 /* set reg [120:96] */
+#define GPIO_GPCR3 0x124 /* clear reg [120:96] */
+#define GPIO_GRER3 0x130 /* rising edge [120:96] */
+#define GPIO_GFER3 0x13c /* falling edge [120:96] */
+#define GPIO_GEDR3 0x148 /* edge detect [120:96] */
+
+/* a bit simpler if we don't support PXA270 */
+#define PXA250_GPIO_REG(r, pin) ((r) + (((pin) / 32) * 4))
+#define PXA250_GPIO_NPINS 85
+
+#define PXA270_GPIO_REG(r, pin) \
+(pin < 96 ? PXA250_GPIO_REG(r,pin) : ((r) + 0x100 + ((((pin)-96) / 32) * 4)))
+#define PXA270_GPIO_NPINS 121
+
+
+#define GPIO_BANK(pin) ((pin) / 32)
+#define GPIO_BIT(pin) (1u << ((pin) & 0x1f))
+#define GPIO_FN_REG(pin) (GPIO_GAFR0_L + (((pin) / 16) * 4))
+#define GPIO_FN_SHIFT(pin) ((pin & 0xf) * 2)
+
+#define GPIO_IN 0x00 /* Regular GPIO input pin */
+#define GPIO_OUT 0x10 /* Regular GPIO output pin */
+#define GPIO_ALT_FN_1_IN 0x01 /* Alternate function 1 input */
+#define GPIO_ALT_FN_1_OUT 0x11 /* Alternate function 1 output */
+#define GPIO_ALT_FN_2_IN 0x02 /* Alternate function 2 input */
+#define GPIO_ALT_FN_2_OUT 0x12 /* Alternate function 2 output */
+#define GPIO_ALT_FN_3_IN 0x03 /* Alternate function 3 input */
+#define GPIO_ALT_FN_3_OUT 0x13 /* Alternate function 3 output */
+#define GPIO_SET 0x20 /* Initial state is Set */
+#define GPIO_CLR 0x00 /* Initial state is Clear */
+
+#define GPIO_FN_MASK 0x03
+#define GPIO_FN_IS_OUT(n) ((n) & GPIO_OUT)
+#define GPIO_FN_IS_SET(n) ((n) & GPIO_SET)
+#define GPIO_FN(n) ((n) & GPIO_FN_MASK)
+#define GPIO_IS_GPIO(n) (GPIO_FN(n) == 0)
+#define GPIO_IS_GPIO_IN(n) (((n) & (GPIO_FN_MASK|GPIO_OUT)) == GPIO_IN)
+#define GPIO_IS_GPIO_OUT(n) (((n) & (GPIO_FN_MASK|GPIO_OUT)) == GPIO_OUT)
+
+#define IRQ_GPIO0 64
+#define IRQ_NGPIO 128
+#define IRQ_GPIO_MAX IRQ_GPIO0 + IRQ_NGPIO
+#define IRQ_TO_GPIO(x) (x - IRQ_GPIO0)
+#define GPIO_TO_IRQ(x) (x + IRQ_GPIO0)
+
+/*
+ * memory controller
+ */
+
+#define MEMCTL_MDCNFG 0x0000
+#define MDCNFG_DE0 (1<<0)
+#define MDCNFG_DE1 (1<<1)
+#define MDCNFD_DWID01_SHIFT 2
+#define MDCNFD_DCAC01_SHIFT 3
+#define MDCNFD_DRAC01_SHIFT 5
+#define MDCNFD_DNB01_SHIFT 7
+#define MDCNFG_DE2 (1<<16)
+#define MDCNFG_DE3 (1<<17)
+#define MDCNFD_DWID23_SHIFT 18
+#define MDCNFD_DCAC23_SHIFT 19
+#define MDCNFD_DRAC23_SHIFT 21
+#define MDCNFD_DNB23_SHIFT 23
+
+#define MDCNFD_DWID_MASK 0x1
+#define MDCNFD_DCAC_MASK 0x3
+#define MDCNFD_DRAC_MASK 0x3
+#define MDCNFD_DNB_MASK 0x1
+
+#define MEMCTL_MDREFR 0x04 /* refresh control register */
+#define MDREFR_DRI 0xfff
+#define MDREFR_E0PIN (1<<12)
+#define MDREFR_K0RUN (1<<13) /* SDCLK0 enable */
+#define MDREFR_K0DB2 (1<<14) /* SDCLK0 1/2 freq */
+#define MDREFR_E1PIN (1<<15)
+#define MDREFR_K1RUN (1<<16) /* SDCLK1 enable */
+#define MDREFR_K1DB2 (1<<17) /* SDCLK1 1/2 freq */
+#define MDREFR_K2RUN (1<<18) /* SDCLK2 enable */
+#define MDREFR_K2DB2 (1<<19) /* SDCLK2 1/2 freq */
+#define MDREFR_APD (1<<20) /* Auto Power Down */
+#define MDREFR_SLFRSH (1<<22) /* Self Refresh */
+#define MDREFR_K0FREE (1<<23) /* SDCLK0 free run */
+#define MDREFR_K1FREE (1<<24) /* SDCLK1 free run */
+#define MDREFR_K2FREE (1<<25) /* SDCLK2 free run */
+
+#define MEMCTL_MSC0 0x08 /* Asychronous Statis memory Control CS[01] */
+#define MEMCTL_MSC1 0x0c /* Asychronous Statis memory Control CS[23] */
+#define MEMCTL_MSC2 0x10 /* Asychronous Statis memory Control CS[45] */
+#define MSC_RBUFF_SHIFT 15 /* return data buffer */
+#define MSC_RBUFF (1<<MSC_RBUFF_SHIFT)
+#define MSC_RRR_SHIFT 12 /* recovery time */
+#define MSC_RRR (7<<MSC_RRR_SHIFT)
+#define MSC_RDN_SHIFT 8 /* ROM delay next access */
+#define MSC_RDN (0x0f<<MSC_RDN_SHIFT)
+#define MSC_RDF_SHIFT 4 /* ROM delay first access*/
+#define MSC_RDF (0x0f<<MSC_RDF_SHIFT)
+#define MSC_RBW_SHIFT 3 /* 32/16 bit bus */
+#define MSC_RBW (1<<MSC_RBW_SHIFT)
+#define MSC_RT_SHIFT 0 /* type */
+#define MSC_RT (7<<MSC_RT_SHIFT)
+#define MSC_RT_NONBURST 0
+#define MSC_RT_SRAM 1
+#define MSC_RT_BURST4 2
+#define MSC_RT_BURST8 3
+#define MSC_RT_VLIO 4
+
+/* expansion memory timing configuration */
+#define MEMCTL_MCMEM(n) (0x28+4*(n))
+#define MEMCTL_MCATT(n) (0x30+4*(n))
+#define MEMCTL_MCIO(n) (0x38+4*(n))
+
+#define MC_HOLD_SHIFT 14
+#define MC_ASST_SHIFT 7
+#define MC_SET_SHIFT 0
+#define MC_TIMING_VAL(hold,asst,set) (((hold)<<MC_HOLD_SHIFT)| \
+ ((asst)<<MC_ASST_SHIFT)|((set)<<MC_SET_SHIFT))
+
+#define MEMCTL_MECR 0x14 /* Expansion memory configuration */
+#define MECR_NOS (1<<0) /* Number of sockets */
+#define MECR_CIT (1<<1) /* Card-is-there */
+
+#define MEMCTL_MDMRS 0x0040
+
+/*
+ * LCD Controller
+ */
+#define LCDC_LCCR0 0x000 /* Controller Control Register 0 */
+#define LCCR0_ENB (1U<<0) /* LCD Controller Enable */
+#define LCCR0_CMS (1U<<1) /* Color/Mono select */
+#define LCCR0_SDS (1U<<2) /* Single/Dual -panel */
+#define LCCR0_LDM (1U<<3) /* LCD Disable Done Mask */
+#define LCCR0_SFM (1U<<4) /* Start of Frame Mask */
+#define LCCR0_IUM (1U<<5) /* Input FIFO Underrun Mask */
+#define LCCR0_EFM (1U<<6) /* End of Frame Mask */
+#define LCCR0_PAS (1U<<7) /* Passive/Active Display select */
+#define LCCR0_DPD (1U<<9) /* Double-Pixel Data pin mode */
+#define LCCR0_DIS (1U<<10) /* LCD Disable */
+#define LCCR0_QDM (1U<<11) /* LCD Quick Disable Mask */
+#define LCCR0_BM (1U<<20) /* Branch Mask */
+#define LCCR0_OUM (1U<<21) /* Output FIFO Underrun Mask */
+
+#define LCCR0_IMASK (LCCR0_LDM|LCCR0_SFM|LCCR0_IUM|LCCR0_EFM|LCCR0_QDM|LCCR0_BM|LCCR0_OUM)
+
+
+#define LCDC_LCCR1 0x004 /* Controller Control Register 1 */
+#define LCDC_LCCR2 0x008 /* Controller Control Register 2 */
+#define LCDC_LCCR3 0x00c /* Controller Control Register 2 */
+#define LCCR3_BPP_SHIFT 24 /* Bits per pixel */
+#define LCCR3_BPP (0x07<<LCCR3_BPP_SHIFT)
+#define LCDC_LCCR4 0x010 /* Controller Control Register 4 */
+#define LCDC_LCCR5 0x014 /* Controller Control Register 5 */
+#define LCDC_FBR0 0x020 /* DMA ch0 frame branch register */
+#define LCDC_FBR1 0x024 /* DMA ch1 frame branch register */
+#define LCDC_FBR2 0x028 /* DMA ch2 frame branch register */
+#define LCDC_FBR3 0x02c /* DMA ch3 frame branch register */
+#define LCDC_FBR4 0x030 /* DMA ch4 frame branch register */
+#define LCDC_LCSR1 0x034 /* controller status register 1 PXA27x only */
+#define LCDC_LCSR 0x038 /* controller status register */
+#define LCSR_LDD (1U<<0) /* LCD disable done */
+#define LCSR_SOF (1U<<1) /* Start of frame */
+#define LCDC_LIIDR 0x03c /* controller interrupt ID Register */
+#define LCDC_TRGBR 0x040 /* TMED RGB Speed Register */
+#define LCDC_TCR 0x044 /* TMED Control Register */
+#define LCDC_OVL1C1 0x050 /* Overlay 1 control register 1 */
+#define LCDC_OVL1C2 0x060 /* Overlay 1 control register 2 */
+#define LCDC_OVL2C1 0x070 /* Overlay 1 control register 1 */
+#define LCDC_OVL2C2 0x080 /* Overlay 1 control register 2 */
+#define LCDC_CCR 0x090 /* Cursor control register */
+#define LCDC_CMDCR 0x100 /* Command control register */
+#define LCDC_PRSR 0x104 /* Panel read status register */
+#define LCDC_FBR5 0x110 /* DMA ch5 frame branch register */
+#define LCDC_FBR6 0x114 /* DMA ch6 frame branch register */
+#define LCDC_FDADR0 0x200 /* DMA ch0 frame descriptor address */
+#define LCDC_FSADR0 0x204 /* DMA ch0 frame source address */
+#define LCDC_FIDR0 0x208 /* DMA ch0 frame ID register */
+#define LCDC_LDCMD0 0x20c /* DMA ch0 command register */
+#define LCDC_FDADR1 0x210 /* DMA ch1 frame descriptor address */
+#define LCDC_FSADR1 0x214 /* DMA ch1 frame source address */
+#define LCDC_FIDR1 0x218 /* DMA ch1 frame ID register */
+#define LCDC_LDCMD1 0x21c /* DMA ch1 command register */
+#define LCDC_FDADR2 0x220 /* DMA ch2 frame descriptor address */
+#define LCDC_FSADR2 0x224 /* DMA ch2 frame source address */
+#define LCDC_FIDR2 0x228 /* DMA ch2 frame ID register */
+#define LCDC_LDCMD2 0x22c /* DMA ch2 command register */
+#define LCDC_FDADR3 0x230 /* DMA ch3 frame descriptor address */
+#define LCDC_FSADR3 0x234 /* DMA ch3 frame source address */
+#define LCDC_FIDR3 0x238 /* DMA ch3 frame ID register */
+#define LCDC_LDCMD3 0x23c /* DMA ch3 command register */
+#define LCDC_FDADR4 0x240 /* DMA ch4 frame descriptor address */
+#define LCDC_FSADR4 0x244 /* DMA ch4 frame source address */
+#define LCDC_FIDR4 0x248 /* DMA ch4 frame ID register */
+#define LCDC_LDCMD4 0x24c /* DMA ch4 command register */
+#define LCDC_FDADR5 0x250 /* DMA ch5 frame descriptor address */
+#define LCDC_FSADR5 0x254 /* DMA ch5 frame source address */
+#define LCDC_FIDR5 0x258 /* DMA ch5 frame ID register */
+#define LCDC_LDCMD5 0x25c /* DMA ch5 command register */
+#define LCDC_FDADR6 0x260 /* DMA ch6 frame descriptor address */
+#define LCDC_FSADR6 0x264 /* DMA ch6 frame source address */
+#define LCDC_FIDR6 0x268 /* DMA ch6 frame ID register */
+#define LCDC_LDCMD6 0x26c /* DMA ch6 command register */
+#define LCDC_LCDBSCNTR 0x054 /* LCD buffer strength control register */
+
+/*
+ * MMC/SD controller
+ */
+#define MMC_STRPCL 0x00 /* start/stop MMC clock */
+#define STRPCL_NOOP 0
+#define STRPCL_STOP 1 /* stop MMC clock */
+#define STRPCL_START 2 /* start MMC clock */
+#define MMC_STAT 0x04 /* status register */
+#define STAT_READ_TIME_OUT (1<<0)
+#define STAT_TIMEOUT_RESPONSE (1<<1)
+#define STAT_CRC_WRITE_ERROR (1<<2)
+#define STAT_CRC_READ_ERROR (1<<3)
+#define STAT_SPI_READ_ERROR_TOKEN (1<<4)
+#define STAT_RES_CRC_ERR (1<<5)
+#define STAT_XMIT_FIFO_EMPTY (1<<6)
+#define STAT_RECV_FIFO_FULL (1<<7)
+#define STAT_CLK_EN (1<<8)
+#define STAT_DATA_TRAN_DONE (1<<11)
+#define STAT_PRG_DONE (1<<12)
+#define STAT_END_CMD_RES (1<<13)
+#define MMC_CLKRT 0x08 /* MMC clock rate */
+#define CLKRT_20M 0
+#define CLKRT_10M 1
+#define CLKRT_5M 2
+#define CLKRT_2_5M 3
+#define CLKRT_1_25M 4
+#define CLKRT_625K 5
+#define CLKRT_312K 6
+#define MMC_SPI 0x0c /* SPI mode control */
+#define SPI_EN (1<<0) /* enable SPI mode */
+#define SPI_CRC_ON (1<<1) /* enable CRC generation */
+#define SPI_CS_EN (1<<2) /* Enable CS[01] */
+#define SPI_CS_ADDRESS (1<<3) /* CS0/CS1 */
+#define MMC_CMDAT 0x10 /* command/response/data */
+#define CMDAT_RESPONSE_FORMAT 0x03
+#define CMDAT_RESPONSE_FORMAT_NO 0 /* no response */
+#define CMDAT_RESPONSE_FORMAT_R1 1 /* R1, R1b, R4, R5 */
+#define CMDAT_RESPONSE_FORMAT_R2 2
+#define CMDAT_RESPONSE_FORMAT_R3 3
+#define CMDAT_DATA_EN (1<<2)
+#define CMDAT_WRITE (1<<3) /* 1=write 0=read operation */
+#define CMDAT_STREAM_BLOCK (1<<4) /* stream mode */
+#define CMDAT_BUSY (1<<5) /* busy signal is expected */
+#define CMDAT_INIT (1<<6) /* preceede command with 80 clocks */
+#define CMDAT_MMC_DMA_EN (1<<7) /* DMA enable */
+#define MMC_RESTO 0x14 /* expected response time out */
+#define MMC_RDTO 0x18 /* expected data read time out */
+#define MMC_BLKLEN 0x1c /* block length of data transaction */
+#define MMC_NOB 0x20 /* number of blocks (block mode) */
+#define MMC_PRTBUF 0x24 /* partial MMC_TXFIFO written */
+#define PRTBUF_BUF_PART_FULL (1<<0) /* buffer partially full */
+#define MMC_I_MASK 0x28 /* interrupt mask */
+#define MMC_I_REG 0x2c /* interrupt register */
+#define MMC_I_DATA_TRAN_DONE (1<<0)
+#define MMC_I_PRG_DONE (1<<1)
+#define MMC_I_END_CMD_RES (1<<2)
+#define MMC_I_STOP_CMD (1<<3)
+#define MMC_I_CLK_IS_OFF (1<<4)
+#define MMC_I_RXFIFO_RD_REQ (1<<5)
+#define MMC_I_TXFIFO_WR_REQ (1<<6)
+#define MMC_CMD 0x30 /* index of current command */
+#define MMC_ARGH 0x34 /* MSW part of the current command arg */
+#define MMC_ARGL 0x38 /* LSW part of the current command arg */
+#define MMC_RES 0x3c /* response FIFO */
+#define MMC_RXFIFO 0x40 /* receive FIFO */
+#define MMC_TXFIFO 0x44 /* transmit FIFO */
+
+/*
+ * AC97
+ */
+#define AC97_N_CODECS 2
+#define AC97_GCR 0x000c /* Global control register */
+#define GCR_GIE (1<<0) /* interrupt enable */
+#define GCR_COLD_RST (1<<1)
+#define GCR_WARM_RST (1<<2)
+#define GCR_ACLINK_OFF (1<<3)
+#define GCR_PRIRES_IEN (1<<4) /* Primary resume interrupt enable */
+#define GCR_SECRES_IEN (1<<5) /* Secondary resume interrupt enable */
+#define GCR_PRIRDY_IEN (1<<8) /* Primary ready interrupt enable */
+#define GCR_SECRDY_IEN (1<<9) /* Primary ready interrupt enable */
+#define GCR_SDONE_IE (1<<18) /* Status done interrupt enable */
+#define GCR_CDONE_IE (1<<19) /* Command done interrupt enable */
+
+#define AC97_GSR 0x001c /* Global status register */
+#define GSR_GSCI (1<<0) /* codec GPI status change interrupt */
+#define GSR_MIINT (1<<1) /* modem in interrupt */
+#define GSR_MOINT (1<<2) /* modem out interrupt */
+#define GSR_PIINT (1<<5) /* PCM in interrupt */
+#define GSR_POINT (1<<6) /* PCM out interrupt */
+#define GSR_MINT (1<<7) /* Mic in interrupt */
+#define GSR_PCR (1<<8) /* primary code ready */
+#define GSR_SCR (1<<9) /* secondary code ready */
+#define GSR_PRIRES (1<<10) /* primary resume interrupt */
+#define GSR_SECRES (1<<11) /* secondary resume interrupt */
+#define GSR_BIT1SLT12 (1<<12) /* Bit 1 of slot 12 */
+#define GSR_BIT2SLT12 (1<<13) /* Bit 2 of slot 12 */
+#define GSR_BIT3SLT12 (1<<14) /* Bit 3 of slot 12 */
+#define GSR_RDCS (1<<15) /* Read completion status */
+#define GSR_SDONE (1<<18) /* status done */
+#define GSR_CDONE (1<<19) /* command done */
+
+#define AC97_POCR 0x0000 /* PCM-out control */
+#define AC97_PICR 0x0004 /* PCM-in control */
+#define AC97_POSR 0x0010 /* PCM-out status */
+#define AC97_PISR 0x0014 /* PCM-out status */
+#define AC97_MCCR 0x0008 /* MIC-in control register */
+#define AC97_MCSR 0x0018 /* MIC-in status register */
+#define AC97_MICR 0x0100 /* Modem-in control register */
+#define AC97_MISR 0x0108 /* Modem-in status register */
+#define AC97_MOCR 0x0110 /* Modem-out control register */
+#define AC97_MOSR 0x0118 /* Modem-out status register */
+#define AC97_FEFIE (1<<3) /* fifo error interrupt enable */
+#define AC97_FIFOE (1<<4) /* fifo error */
+
+#define AC97_CAR 0x0020 /* Codec access register */
+#define CAR_CAIP (1<<0) /* Codec access in progress */
+
+#define AC97_PCDR 0x0040 /* PCM data register */
+#define AC97_MCDR 0x0060 /* MIC-in data register */
+#define AC97_MODR 0x0140 /* Modem data register */
+
+/* address to access codec registers */
+#define AC97_PRIAUDIO 0x0200 /* Primary audio codec */
+#define AC97_SECAUDIO 0x0300 /* Secondary autio codec */
+#define AC97_PRIMODEM 0x0400 /* Primary modem codec */
+#define AC97_SECMODEM 0x0500 /* Secondary modem codec */
+#define AC97_CODEC_BASE(c) (AC97_PRIAUDIO + ((c) * 0x100))
+
+/*
+ * USB device controller
+ */
+#define USBDC_UDCCR 0x0000 /* UDC control register */
+#define USBDC_UDCCS(n) (0x0010+4*(n)) /* Endpoint Control/Status Registers */
+#define USBDC_UICR0 0x0050 /* UDC Interrupt Control Register 0 */
+#define USBDC_UICR1 0x0054 /* UDC Interrupt Control Register 1 */
+#define USBDC_USIR0 0x0058 /* UDC Status Interrupt Register 0 */
+#define USBDC_USIR1 0x005C /* UDC Status Interrupt Register 1 */
+#define USBDC_UFNHR 0x0060 /* UDC Frame Number Register High */
+#define USBDC_UFNLR 0x0064 /* UDC Frame Number Register Low */
+#define USBDC_UBCR2 0x0068 /* UDC Byte Count Register 2 */
+#define USBDC_UBCR4 0x006C /* UDC Byte Count Register 4 */
+#define USBDC_UBCR7 0x0070 /* UDC Byte Count Register 7 */
+#define USBDC_UBCR9 0x0074 /* UDC Byte Count Register 9 */
+#define USBDC_UBCR12 0x0078 /* UDC Byte Count Register 12 */
+#define USBDC_UBCR14 0x007C /* UDC Byte Count Register 14 */
+#define USBDC_UDDR0 0x0080 /* UDC Endpoint 0 Data Register */
+#define USBDC_UDDR1 0x0100 /* UDC Endpoint 1 Data Register */
+#define USBDC_UDDR2 0x0180 /* UDC Endpoint 2 Data Register */
+#define USBDC_UDDR3 0x0200 /* UDC Endpoint 3 Data Register */
+#define USBDC_UDDR4 0x0400 /* UDC Endpoint 4 Data Register */
+#define USBDC_UDDR5 0x00A0 /* UDC Endpoint 5 Data Register */
+#define USBDC_UDDR6 0x0600 /* UDC Endpoint 6 Data Register */
+#define USBDC_UDDR7 0x0680 /* UDC Endpoint 7 Data Register */
+#define USBDC_UDDR8 0x0700 /* UDC Endpoint 8 Data Register */
+#define USBDC_UDDR9 0x0900 /* UDC Endpoint 9 Data Register */
+#define USBDC_UDDR10 0x00C0 /* UDC Endpoint 10 Data Register */
+#define USBDC_UDDR11 0x0B00 /* UDC Endpoint 11 Data Register */
+#define USBDC_UDDR12 0x0B80 /* UDC Endpoint 12 Data Register */
+#define USBDC_UDDR13 0x0C00 /* UDC Endpoint 13 Data Register */
+#define USBDC_UDDR14 0x0E00 /* UDC Endpoint 14 Data Register */
+#define USBDC_UDDR15 0x00E0 /* UDC Endpoint 15 Data Register */
+
+#define USBHC_UHCRHDA 0x0048 /* UHC Root Hub Descriptor A */
+#define UHCRHDA_POTPGT_SHIFT 24 /* Power on to power good time */
+#define UHCRHDA_NOCP (1<<12) /* No over current protection */
+#define UHCRHDA_OCPM (1<<11) /* Over current protection mode */
+#define UHCRHDA_DT (1<<10) /* Device type */
+#define UHCRHDA_NPS (1<<9) /* No power switching */
+#define UHCRHDA_PSM (1<<8) /* Power switching mode */
+#define UHCRHDA_NDP_MASK 0xff /* Number downstream ports */
+#define USBHC_UHCRHDB 0x004c /* UHC Root Hub Descriptor B */
+#define USBHC_UHCRHS 0x0050 /* UHC Root Hub Stauts */
+#define USBHC_UHCHR 0x0064 /* UHC Reset Register */
+#define UHCHR_SSEP3 (1<<11) /* Sleep standby enable for port3 */
+#define UHCHR_SSEP2 (1<<10) /* Sleep standby enable for port2 */
+#define UHCHR_SSEP1 (1<<9) /* Sleep standby enable for port1 */
+#define UHCHR_PCPL (1<<7) /* Power control polarity low */
+#define UHCHR_PSPL (1<<6) /* Power sense polarity low */
+#define UHCHR_SSE (1<<5) /* Sleep standby enable */
+#define UHCHR_UIT (1<<4) /* USB interrupt test */
+#define UHCHR_SSDC (1<<3) /* Simulation scale down clock */
+#define UHCHR_CGR (1<<2) /* Clock generation reset */
+#define UHCHR_FHR (1<<1) /* Force host controller reset */
+#define UHCHR_FSBIR (1<<0) /* Force system bus interface reset */
+#define UHCHR_MASK 0xeff
+
+/*
+ * PWM controller
+ */
+#define PWM_PWMCR 0x0000 /* Control register */
+#define PWM_PWMDCR 0x0004 /* Duty cycle register */
+#define PWM_FD (1<<10) /* Full duty */
+#define PWM_PWMPCR 0x0008 /* Period register */
+
+/*
+ * OS timer
+ */
+#define OST_MR0 0x00 /* Match register 0 */
+#define OST_MR1 0x04 /* Match register 1 */
+#define OST_MR2 0x08 /* Match register 2 */
+#define OST_MR3 0x0c /* Match register 3 */
+#define OST_CR 0x10 /* Count register */
+#define OST_SR 0x14 /* Status register */
+#define OST_SR_CH0 (1<<0)
+#define OST_SR_CH1 (1<<1)
+#define OST_SR_CH2 (1<<2)
+#define OST_SR_CH3 (1<<3)
+#define OST_WR 0x18 /* Watchdog enable register */
+#define OST_IR 0x1c /* Interrupt enable register */
+
+/*
+ * Interrupt controller
+ */
+#define ICU_IP 0x00 /* IRQ pending register */
+#define ICU_MR 0x04 /* Mask register */
+#define ICU_LR 0x08 /* Level register */
+#define ICU_FP 0x0c /* FIQ pending register */
+#define ICU_PR 0x10 /* Pending register */
+#define ICU_CR 0x14 /* Control register */
+
+#endif /* _ARM_XSCALE_PXAREG_H_ */
Property changes on: trunk/sys/arm/xscale/pxa/pxareg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/pxavar.h
===================================================================
--- trunk/sys/arm/xscale/pxa/pxavar.h (rev 0)
+++ trunk/sys/arm/xscale/pxa/pxavar.h 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,113 @@
+/* $MidnightBSD$ */
+/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/arm/xscale/pxa/pxavar.h 179595 2008-06-06 05:08:09Z benno $
+ *
+ */
+
+#ifndef _PXAVAR_H_
+#define _PXAVAR_H_
+
+#include <sys/rman.h>
+
+struct obio_softc {
+ bus_space_tag_t obio_bst; /* bus space tag */
+ struct rman obio_mem;
+ struct rman obio_irq;
+};
+
+extern bus_space_tag_t base_tag;
+extern bus_space_tag_t obio_tag;
+void pxa_obio_tag_init(void);
+bus_space_tag_t pxa_bus_tag_alloc(bus_addr_t);
+
+uint32_t pxa_gpio_get_function(int);
+uint32_t pxa_gpio_set_function(int, uint32_t);
+int pxa_gpio_setup_intrhandler(const char *, driver_filter_t *,
+ driver_intr_t *, void *, int, int, void **);
+void pxa_gpio_mask_irq(int);
+void pxa_gpio_unmask_irq(int);
+int pxa_gpio_get_next_irq(void);
+
+struct dmac_channel;
+
+struct dmac_descriptor {
+ uint32_t ddadr;
+ uint32_t dsadr;
+ uint32_t dtadr;
+ uint32_t dcmd;
+};
+#define DMACD_SET_DESCRIPTOR(d, dadr) do { d->ddadr = dadr; } while (0)
+#define DMACD_SET_SOURCE(d, sadr) do { d->dsadr = sadr; } while (0)
+#define DMACD_SET_TARGET(d, tadr) do { d->dtadr = tadr; } while (0)
+#define DMACD_SET_COMMAND(d, cmd) do { d->dcmd = cmd; } while (0)
+
+#define DMAC_PRIORITY_HIGHEST 1
+#define DMAC_PRIORITY_HIGH 2
+#define DMAC_PRIORITY_LOW 3
+
+int pxa_dmac_alloc(int, struct dmac_channel **, int);
+void pxa_dmac_release(struct dmac_channel *);
+int pxa_dmac_transfer(struct dmac_channel *, bus_addr_t);
+int pxa_dmac_transfer_single(struct dmac_channel *,
+ bus_addr_t, bus_addr_t, uint32_t);
+int pxa_dmac_transfer_done(struct dmac_channel *);
+int pxa_dmac_transfer_failed(struct dmac_channel *);
+
+enum pxa_device_ivars {
+ PXA_IVAR_BASE,
+};
+
+enum smi_device_ivars {
+ SMI_IVAR_PHYSBASE,
+};
+
+#define PXA_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(pxa, var, PXA, ivar, type)
+
+PXA_ACCESSOR(base, BASE, u_long)
+
+#undef PXA_ACCESSOR
+
+#define SMI_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(smi, var, SMI, ivar, type)
+
+SMI_ACCESSOR(physbase, PHYSBASE, bus_addr_t)
+
+#undef CSR_ACCESSOR
+
+#endif /* _PXAVAR_H_ */
Property changes on: trunk/sys/arm/xscale/pxa/pxavar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/std.pxa
===================================================================
--- trunk/sys/arm/xscale/pxa/std.pxa (rev 0)
+++ trunk/sys/arm/xscale/pxa/std.pxa 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,9 @@
+# XScale PXA generic configuration
+# $FreeBSD: stable/10/sys/arm/xscale/pxa/std.pxa 266175 2014-05-15 19:09:31Z ian $
+files "../xscale/pxa/files.pxa"
+include "../xscale/std.xscale"
+makeoptions KERNPHYSADDR=0xa0200000
+makeoptions KERNVIRTADDR=0xc0200000
+makeoptions CONF_CFLAGS=-mcpu=xscale
+options XSCALE_CACHE_READ_WRITE_ALLOCATE
+machine arm
Property changes on: trunk/sys/arm/xscale/pxa/std.pxa
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/uart_bus_pxa.c
===================================================================
--- trunk/sys/arm/xscale/pxa/uart_bus_pxa.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/uart_bus_pxa.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,104 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Benno Rice. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/uart_bus_pxa.c 234004 2012-04-07 23:47:08Z stas $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <dev/ic/ns16550.h>
+
+#include <arm/xscale/pxa/pxavar.h>
+#include <arm/xscale/pxa/pxareg.h>
+
+#include "uart_if.h"
+
+#define PXA_UART_UUE 0x40 /* UART Unit Enable */
+
+static int uart_pxa_probe(device_t dev);
+
+static device_method_t uart_pxa_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uart_pxa_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, uart_bus_detach),
+ { 0, 0 }
+};
+
+static driver_t uart_pxa_driver = {
+ uart_driver_name,
+ uart_pxa_methods,
+ sizeof(struct uart_softc),
+};
+
+static int
+uart_pxa_probe(device_t dev)
+{
+ bus_space_handle_t base;
+ struct uart_softc *sc;
+
+ base = (bus_space_handle_t)pxa_get_base(dev);
+#ifdef QEMU_WORKAROUNDS
+ /*
+ * QEMU really exposes only the first uart unless
+ * you specify several of them in the configuration.
+ * Otherwise all the rest of UARTs stay unconnected,
+ * which causes problems in the ns16550 attach routine.
+ * Unfortunately, even if you provide qemu with 4 uarts
+ * on the command line, it has a bug where it segfaults
+ * trying to enable bluetooth on the HWUART. So we just
+ * allow the FFUART to be attached.
+ * Also, don't check the UUE (UART Unit Enable) bit, as
+ * the gumstix bootloader doesn't set it.
+ */
+ if (base != PXA2X0_FFUART_BASE)
+ return (ENXIO);
+#else
+ /* Check to see if the enable bit's on. */
+ if ((bus_space_read_4(obio_tag, base,
+ (REG_IER << 2)) & PXA_UART_UUE) == 0)
+ return (ENXIO);
+#endif
+ sc = device_get_softc(dev);
+ sc->sc_class = &uart_ns8250_class;
+
+ return(uart_bus_probe(dev, 2, PXA2X0_COM_FREQ, 0, 0));
+}
+
+DRIVER_MODULE(uart, pxa, uart_pxa_driver, uart_devclass, 0, 0);
Property changes on: trunk/sys/arm/xscale/pxa/uart_bus_pxa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/pxa/uart_cpu_pxa.c
===================================================================
--- trunk/sys/arm/xscale/pxa/uart_cpu_pxa.c (rev 0)
+++ trunk/sys/arm/xscale/pxa/uart_cpu_pxa.c 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/arm/xscale/pxa/uart_cpu_pxa.c 179595 2008-06-06 05:08:09Z benno $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <arm/xscale/pxa/pxavar.h>
+#include <arm/xscale/pxa/pxareg.h>
+
+bus_space_tag_t uart_bus_space_io;
+bus_space_tag_t uart_bus_space_mem;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+
+ return (b1->bsh == b2->bsh ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+
+ di->ops = uart_getops(&uart_ns8250_class);
+ di->bas.chan = 0;
+ di->bas.bst = obio_tag;
+ di->bas.regshft = 2;
+ di->bas.rclk = PXA2X0_COM_FREQ;
+ di->baudrate = 115200;
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ uart_bus_space_mem = obio_tag;
+ uart_bus_space_io = NULL;
+ di->bas.bsh = PXA2X0_FFUART_BASE;
+ return (0);
+}
Property changes on: trunk/sys/arm/xscale/pxa/uart_cpu_pxa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/arm/xscale/std.xscale
===================================================================
--- trunk/sys/arm/xscale/std.xscale (rev 0)
+++ trunk/sys/arm/xscale/std.xscale 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,3 @@
+# $FreeBSD: stable/10/sys/arm/xscale/std.xscale 239362 2012-08-18 05:48:19Z andrew $
+options ARM_CACHE_LOCK_ENABLE
+options NO_EVENTTIMERS
Property changes on: trunk/sys/arm/xscale/std.xscale
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/arm/xscale/std.xscale-be
===================================================================
--- trunk/sys/arm/xscale/std.xscale-be (rev 0)
+++ trunk/sys/arm/xscale/std.xscale-be 2018-06-02 15:44:28 UTC (rev 10219)
@@ -0,0 +1,5 @@
+#Big-Endian XScale generic configuration
+#$FreeBSD: stable/10/sys/arm/xscale/std.xscale-be 239362 2012-08-18 05:48:19Z andrew $
+
+include "../xscale/std.xscale"
+machine arm armeb
Property changes on: trunk/sys/arm/xscale/std.xscale-be
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
More information about the Midnightbsd-cvs
mailing list