Pull up following revision(s) (requested by jmcneill in ticket #114):
sys/arch/arm/samsung/exynos_intr.h: revision 1.3 sys/arch/arm/sunxi/sun8i_h3_ccu.c: revision 1.1 sys/arch/arm/sunxi/sun8i_h3_ccu.c: revision 1.2 sys/arch/arm/sunxi/sun8i_h3_ccu.c: revision 1.3 sys/arch/arm/sunxi/sunxi_gates.c: revision 1.1 distrib/utils/embedded/mkimage: revision 1.66 sys/arch/arm/sunxi/sun8i_h3_ccu.c: revision 1.4 sys/arch/arm/sunxi/sunxi_rsb.c: revision 1.1 sys/arch/arm/sunxi/sun8i_h3_ccu.c: revision 1.5 sys/arch/arm/sunxi/sun8i_h3_ccu.c: revision 1.6 sys/arch/arm/sunxi/sun8i_h3_ccu.c: revision 1.7 sys/dev/gpio/gpio.c: revision 1.59 sys/arch/arm/sunxi/sunxi_ccu_prediv.c: revision 1.1 sys/conf/Makefile.kern.inc: revision 1.257 sys/arch/evbarm/conf/ODROID-XU_INSTALL: file removal sys/arch/arm/sunxi/sunxi_ccu_prediv.c: revision 1.2 sys/conf/Makefile.kern.inc: revision 1.258 sys/arch/arm/fdt/psci_fdt.h: revision 1.1 sys/arch/arm/sunxi/sunxi_resets.c: revision 1.1 sys/arch/evbarm/conf/files.sunxi: revision 1.1 sys/arch/evbarm/fdt/fdt_machdep.c: revision 1.8 sys/arch/evbarm/fdt/fdt_machdep.c: revision 1.9 sys/arch/arm/samsung/files.exynos: revision 1.22 distrib/utils/embedded/conf/armv7.conf: revision 1.13 sys/arch/arm/samsung/files.exynos: revision 1.23 sys/arch/evbarm/conf/std.tegra: revision 1.15 distrib/utils/embedded/conf/armv7.conf: revision 1.14 sys/arch/arm/samsung/files.exynos: revision 1.24 distrib/utils/embedded/conf/armv7.conf: revision 1.15 sys/arch/evbarm/sunxi/genassym.cf: revision 1.1 sys/arch/arm/samsung/exynos_fdt.c: file removal sys/dev/fdt/fdt_pinctrl.c: revision 1.4 sys/arch/arm/samsung/exynos_sysmmu.c: revision 1.2 sys/arch/arm/sunxi/sun8i_h3_gpio.c: revision 1.1 sys/arch/arm/sunxi/sunxi_twi.c: revision 1.1 sys/dev/usb/ehci.c: revision 1.255 sys/arch/arm/sunxi/sunxi_twi.c: revision 1.2 sys/arch/arm/sunxi/sun8i_a83t_ccu.h: revision 1.1 sys/dev/ic/dwc_mmc.c: revision 1.11 sys/arch/arm/cortex/gic.c: revision 1.24 distrib/evbarm/instkernel/ramdisk/Makefile: revision 1.17 etc/etc.evbarm/Makefile.inc: revision 1.87 etc/etc.evbarm/Makefile.inc: revision 1.88 sys/arch/arm/fdt/gic_fdt.c: revision 1.5 etc/Makefile: revision 1.429 sys/arch/arm/fdt/gic_fdt.c: revision 1.6 sys/arch/arm/fdt/gic_fdt.c: revision 1.7 sys/arch/arm/sunxi/sunxi_gpio.c: revision 1.1 sys/arch/arm/sunxi/sunxi_gpio.c: revision 1.2 sys/arch/evbarm/conf/std.sunxi: revision 1.1 sys/arch/arm/sunxi/sunxi_gpio.c: revision 1.3 sys/arch/evbarm/conf/std.sunxi: revision 1.2 sys/arch/arm/sunxi/sunxi_gpio.c: revision 1.4 sys/arch/evbarm/conf/std.sunxi: revision 1.3 sys/arch/arm/sunxi/sunxi_gpio.c: revision 1.5 sys/arch/arm/sunxi/sunxi_ccu_div.c: revision 1.1 sys/dev/gpio/gpiovar.h: revision 1.17 sys/arch/arm/sunxi/sunxi_gpio.c: revision 1.6 sys/arch/arm/sunxi/sunxi_gpio.c: revision 1.7 sys/arch/arm/sunxi/sunxi_gpio.c: revision 1.8 sys/arch/arm/sunxi/sunxi_rsb.h: revision 1.1 sys/arch/arm/samsung/exynos_i2c.c: revision 1.12 sys/dev/fdt/fdtvar.h: revision 1.21 sys/arch/evbarm/sunxi/sunxi_start.S: revision 1.1 sys/arch/arm/samsung/exynos_i2c.c: revision 1.13 sys/dev/fdt/fdtvar.h: revision 1.22 sys/arch/evbarm/conf/SUNXI: revision 1.10 sys/dev/fdt/fdtvar.h: revision 1.23 sys/arch/evbarm/conf/SUNXI: revision 1.11 sys/dev/fdt/gpioleds.c: revision 1.1 sys/dev/fdt/fdtvar.h: revision 1.24 sys/arch/evbarm/conf/SUNXI: revision 1.12 sys/arch/evbarm/conf/SUNXI: revision 1.13 sys/arch/arm/cortex/gic.c: revision 1.30 sys/arch/evbarm/conf/SUNXI: revision 1.14 sys/arch/evbarm/conf/SUNXI: revision 1.15 sys/arch/evbarm/conf/SUNXI: revision 1.16 sys/arch/arm/sunxi/sunxi_emac.c: revision 1.1 etc/Makefile: revision 1.430 sys/arch/arm/sunxi/sunxi_emac.c: revision 1.2 etc/Makefile: revision 1.431 sys/arch/evbarm/conf/VEXPRESS_A15: revision 1.17 sys/arch/arm/sunxi/sunxi_emac.c: revision 1.3 sys/arch/arm/sunxi/sunxi_emac.c: revision 1.4 sys/arch/arm/samsung/exynos5422_clock.c: revision 1.6 sys/arch/arm/samsung/exynos_platform.c: revision 1.1 sys/dev/ofw/ofw_subr.c: revision 1.29 sys/arch/arm/samsung/exynos_platform.c: revision 1.2 sys/arch/evbarm/conf/mk.vexpress: revision 1.3 sys/arch/arm/samsung/exynos_platform.c: revision 1.3 sys/arch/evbarm/conf/mk.vexpress: revision 1.4 sys/arch/arm/samsung/exynos_platform.c: revision 1.4 sys/arch/arm/arm/psci.h: revision 1.1 sys/arch/arm/samsung/exynos_platform.c: revision 1.5 sys/arch/arm/samsung/exynos_platform.c: revision 1.6 sys/arch/evbarm/fdt/fdt_machdep.c: revision 1.10 external/bsd/mdocml/bin/mandoc/Makefile: revision 1.12 sys/dev/fdt/files.fdt: revision 1.17 sys/dev/fdt/files.fdt: revision 1.18 sys/dev/fdt/files.fdt: revision 1.19 sys/arch/arm/samsung/exynos_sscom.c: revision 1.8 sys/arch/arm/sunxi/sun8i_a83t_ccu.c: revision 1.1 sys/arch/arm/sunxi/sunxi_mmc.c: revision 1.1 sys/arch/arm/samsung/exynos_sscom.c: revision 1.9 sys/arch/arm/conf/files.arm: revision 1.133 sys/arch/arm/samsung/mct_var.h: revision 1.5 sys/arch/arm/sunxi/sunxi_platform.c: revision 1.1 sys/arch/arm/sunxi/sunxi_platform.c: revision 1.2 sys/arch/evbarm/conf/std.vexpress: revision 1.6 sys/arch/arm/sunxi/sunxi_platform.c: revision 1.3 sys/arch/arm/sunxi/sun6i_a31_gpio.c: revision 1.1 sys/arch/arm/sunxi/sunxi_platform.c: revision 1.4 sys/arch/arm/sunxi/sun6i_a31_gpio.c: revision 1.2 sys/arch/arm/sunxi/files.sunxi: revision 1.1 sys/dev/ofw/ofw_subr.c: revision 1.30 sys/arch/arm/sunxi/files.sunxi: revision 1.2 sys/dev/ofw/openfirm.h: revision 1.35 sys/arch/arm/sunxi/files.sunxi: revision 1.3 sys/dev/ofw/openfirm.h: revision 1.36 sys/arch/arm/sunxi/files.sunxi: revision 1.4 sys/arch/arm/sunxi/files.sunxi: revision 1.5 sys/arch/evbarm/exynos/exynos_machdep.c: file removal sys/arch/arm/sunxi/sunxi_gpio.h: revision 1.1 sys/arch/arm/samsung/sscom.c: revision 1.9 sys/arch/arm/sunxi/files.sunxi: revision 1.6 sys/dev/fdt/ohci_fdt.c: revision 1.1 sys/arch/arm/sunxi/sunxi_usbphy.c: revision 1.1 sys/arch/arm/sunxi/sunxi_gpio.h: revision 1.2 sys/arch/arm/sunxi/files.sunxi: revision 1.7 sys/arch/arm/sunxi/sunxi_usbphy.c: revision 1.2 sys/arch/arm/sunxi/sunxi_gpio.h: revision 1.3 sys/arch/arm/sunxi/files.sunxi: revision 1.8 sys/arch/arm/sunxi/sunxi_usbphy.c: revision 1.3 sys/arch/arm/sunxi/files.sunxi: revision 1.9 sys/arch/arm/samsung/exynos_sscom.c: revision 1.10 sys/arch/evbarm/conf/mk.tegra: revision 1.5 sys/arch/arm/samsung/exynos_dwcmmc.c: revision 1.4 sys/arch/evbarm/conf/mk.tegra: revision 1.6 sys/arch/evbarm/conf/EXYNOS: revision 1.15 sys/arch/evbarm/conf/EXYNOS: revision 1.16 sys/arch/evbarm/conf/EXYNOS: revision 1.17 sys/arch/arm/sunxi/sunxi_ccu.c: revision 1.1 sys/arch/evbarm/conf/EXYNOS: revision 1.19 sys/arch/arm/sunxi/sunxi_ccu.c: revision 1.2 sys/arch/arm/sunxi/sunxi_ccu.c: revision 1.3 sys/arch/arm/sunxi/sunxi_ccu.c: revision 1.4 sys/arch/arm/sunxi/sunxi_ccu.c: revision 1.5 sys/arch/arm/sunxi/sunxi_emac.h: revision 1.1 sys/arch/evbarm/conf/mk.sunxi: revision 1.1 sys/arch/evbarm/include/bootconfig.h: revision 1.7 sys/arch/evbarm/conf/TEGRA: revision 1.24 sys/arch/arm/arm/psci.c: revision 1.1 sys/dev/led.c: revision 1.1 sys/dev/led.c: revision 1.2 sys/arch/arm/arm/psci_arm.S: revision 1.1 sys/arch/arm/sunxi/sunxi_ccu_gate.c: revision 1.1 sys/arch/arm/sunxi/sunxi_ccu_gate.c: revision 1.2 sys/dev/fdt/ehci_fdt.c: revision 1.1 sys/dev/fdt/ehci_fdt.c: revision 1.2 sys/arch/arm/sunxi/sun6i_a31_ccu.h: revision 1.1 sys/arch/evbarm/conf/EXYNOS: revision 1.21 sys/arch/arm/sunxi/files.sunxi: revision 1.10 sys/arch/arm/sunxi/files.sunxi: revision 1.11 sys/dev/fdt/fdtbus.c: revision 1.14 sys/arch/arm/sunxi/sunxi_mmc.h: revision 1.1 sys/arch/arm/samsung/exynos5422_dma.c: file removal usr.bin/config/mkmakefile.c: revision 1.69 sys/conf/files: revision 1.1178 sys/arch/arm/sunxi/sunxi_platform.h: revision 1.1 sys/arch/evbarm/exynos/exynos_start.S: revision 1.4 sys/arch/arm/samsung/exynos_pinctrl.c: revision 1.11 sys/arch/arm/samsung/exynos_pinctrl.c: revision 1.12 sys/arch/arm/sunxi/sunxi_rtc.c: revision 1.1 sys/arch/arm/sunxi/sun8i_h3_ccu.h: revision 1.1 sys/arch/arm/samsung/exynos5410_clock.c: revision 1.1 sys/arch/arm/samsung/exynos5410_clock.c: revision 1.2 sys/arch/evbarm/conf/SUNXI: revision 1.1 external/bsd/elftosb/usr.sbin/elftosb/Makefile: revision 1.5 sys/arch/evbarm/conf/SUNXI: revision 1.2 sys/arch/arm/fdt/psci_fdt.c: revision 1.1 sys/arch/evbarm/conf/SUNXI: revision 1.3 sys/arch/evbarm/conf/SUNXI: revision 1.4 sys/arch/evbarm/conf/files.exynos: revision 1.3 sys/arch/evbarm/conf/SUNXI: revision 1.5 sys/arch/evbarm/conf/SUNXI: revision 1.6 sys/arch/arm/sunxi/sunxi_ccu_nm.c: revision 1.1 sys/dev/fdt/fixedfactorclock.c: revision 1.1 sys/dev/fdt/fdt_subr.c: revision 1.14 sys/arch/evbarm/conf/SUNXI: revision 1.7 sys/arch/arm/sunxi/sunxi_ccu_nm.c: revision 1.2 sys/arch/arm/sunxi/sun8i_a83t_gpio.c: revision 1.1 sys/dev/fdt/fdt_subr.c: revision 1.15 sys/arch/evbarm/conf/SUNXI: revision 1.8 sys/arch/arm/sunxi/sunxi_ccu_nm.c: revision 1.3 sys/dev/ic/dwc_mmc_reg.h: revision 1.6 sys/dev/fdt/fdt_subr.c: revision 1.16 sys/arch/evbarm/conf/SUNXI: revision 1.9 usr.bin/config/mkmakefile.c: revision 1.70 sys/dev/fdt/fdt_phy.c: revision 1.1 sys/arch/evbarm/conf/ODROID-XU: file removal sys/arch/arm/fdt/arm_fdt.c: revision 1.4 sys/arch/arm/samsung/exynos_reg.h: revision 1.14 sys/conf/files: revision 1.1180 sys/arch/arm/samsung/exynos_reg.h: revision 1.15 sys/arch/arm/sunxi/sunxi_ccu.h: revision 1.1 sys/arch/arm/sunxi/sunxi_ccu.h: revision 1.2 sys/arch/arm/sunxi/sunxi_ccu.h: revision 1.3 sys/arch/arm/sunxi/sunxi_ccu.h: revision 1.4 sys/arch/arm/sunxi/sunxi_ccu.h: revision 1.5 sys/arch/arm/sunxi/sunxi_ccu.h: revision 1.6 sys/dev/ic/dwc_mmc_var.h: revision 1.6 sys/arch/arm/samsung/exynos_combiner.c: revision 1.7 sys/arch/evbarm/exynos/platform.h: revision 1.2 sys/arch/arm/fdt/files.fdt: revision 1.12 sys/arch/evbarm/conf/std.exynos: revision 1.2 sys/arch/evbarm/conf/std.exynos: revision 1.3 sys/arch/arm/rockchip/rockchip_dwcmmc.c: revision 1.6 sys/arch/arm/sunxi/sunxi_com.c: revision 1.1 sys/dev/led.h: revision 1.1 sys/arch/evbarm/conf/std.exynos: revision 1.5 sys/arch/arm/sunxi/sunxi_com.c: revision 1.2 sys/arch/evbarm/conf/files.evbarm: revision 1.26 usr.bin/config/defs.h: revision 1.99 sys/arch/arm/fdt/arm_fdtvar.h: revision 1.6 sys/arch/arm/samsung/exynos_soc.c: revision 1.32 sys/arch/arm/sunxi/sun6i_a31_ccu.c: revision 1.1 sys/arch/arm/sunxi/sun6i_a31_ccu.c: revision 1.2 sys/arch/arm/samsung/mct.c: revision 1.11 sys/arch/evbarm/conf/ODROID-U: file removal sys/arch/arm/samsung/mct.c: revision 1.12 sys/arch/arm/sunxi/sunxi_ccu_nkmp.c: revision 1.1 sys/arch/arm/sunxi/sunxi_ccu_nkmp.c: revision 1.2 sys/arch/arm/sunxi/sunxi_ccu_nkmp.c: revision 1.3 sys/arch/arm/sunxi/sunxi_ccu_nkmp.c: revision 1.4 Get the EXYNOS kernel building again with recent FDT changes. Untested. Use arm_fdt_cpu_hatch and add mmu entry for DTB Fix exynos5 devmap, bootstrap, and implement early_putchar. Calculate UART frequency based on bootloader config. Fix KERNEL_BASE_PHYS (how did this ever work?) Avoid divide-by-zero for unconfigured PLLs Correctly initialize i2cbus attach args. Add delay and enable mct timecounter. Fix build w/o VERBOSE_INIT_ARM Remove ODROID-U and ODROID-XU kernel configs as they no longer work. - Replace CONSADDR with SSCOM2CONSOLE in example - Remove gtmr (Exynos5422 uses mct) - cinclude EXYNOS.local instead of TEGRA.local Use fdtbus_intr_establish to hook in block interrupts instead of intr_establish. Simplify MCT; just enable it and then attach an ARMv7 generic timer. Add support for building DTB files during kernel build, from christos. build vexpress-v2p-ca15-tc1.dtb with the kernel build tegra124-apalis-eval.dtb, tegra124-jetson-tk1.dtb, tegra124-nyan-big.dtb, tegra124-nyan-blaze.dtb, and tegra124-venice2.dtb with the kernel Allow multiline makeoptions to work by quoting the newline.. Bump for quoting makeoptions with multiple lines. un-c99 bump required config version for multiline makeoptions feature Set DTS makeoption in kernel config Assign DTB files to a variable so we can make -V DTB put the dtb files with their kernels. no need for debug printing. Don't assume that CPU index = GIC CPU interface number. We can determine the current CPU interface number by reading from the read-only GICD_ITARGETSR0 through GICD_ITARGETSR7 registers. This gets interrupts working on Exynos 5422, where the boot processor has GIC CPU interface #4. use -v to get the expanded variable. Use -v to get the expanded variables. Get baud rate from sclk_uartN instead of uartN. Print IRQ number at attach. Fix PLL con0 register locations and add uart clocks Disable exyortc for now, it doesn't work. More or less a rewrite of dwc_mmc, based on awin_mmc, adding DMA support. Update for new dwc_mmc driver Fix dmesg Add Exynos 5410 clock controller driver. Fix a few typos in clock parent names for mmc clocks. From jmcneill@ Update for new dwc_mmc driver Implement platform reset for exynos5 Attach fdtbus to a /clocks node with no compatible string. Add support for ARM Power State Coordination Interface (PSCI). Support interrupt sharing. Add initial support for Allwinner H3 SoC. ARM Trusted Firmware reserves SGIs 8-15 for secure use. Even without ATF, U-Boot on some platforms may use SGIs in this range for the PSCI implementation. Change ARMGIC_IPI_BASE to 0 from (16 - NIPI) and add a compile-time assert to ensure that we don't end up with a conflict. Add H3 MMC support SD/MMC clock fixes Add FDT PHY interface. Add glue for generic ehci/ohci bindings. Rename a variable, NFC. Support parents in different clock domains. Add USB stuff. Doesn't quite work yet. Synopsys DesignWare APB UART needs "options COM_AWIN" for now. Add i2c glue. Add RTC driver. PHY registers start at index 1. Now USB works. Don't allow sharing edge and level triggered interrupts. Add arm_fdt_memory_dump helper for dumping physical addresses from ddb Print clocks with aprint_debug Remove unused defines Add fdtbus_get_string helper Add of_search_compatible, which searches an array of compat_data structures for a matching "compatible" entry matching the supplied OFW node. This allows us to associate data with compatible strings. Add driver for Allwinner Gigabit Ethernet (EMAC) as found in sun8i and later family SoCs. This is a port of my FreeBSD driver which has been confirmed to work on Allwinner H3, A83T, and A64 SoCs. Fix dmesg Add basic support for Allwinner A31. Add basic FDT GPIO support. Fix the pinctrl api to match the spec. A pinctrl config can have more than one xref, and an xref may have specifier data associated with it. Enable sunxi pinctrl support Adjust to new pinctrl API Add P2WI/RSB driver, based on awin_p2wi.c. Fix typo in a compat string. Configure pin defaults at attach No need to explicitly set pinctrl config 0 now Fix some register definitions. Disallow sharing between MPSAFE and non-MPSAFE handlers. Add of_match_compat_data. This routine searches an array of compat_data structures for a matching "compatible" entry matching the supplied OFW node. Add options __HAVE_CPU_UAREA_ALLOC_IDLELWP Add support for reserved memory and MEMORY_DISK_DYNAMIC for FDT-based kernels. the extent code cannot use the full range of u_long, so ignore the last page before 4GB too. ok jmcneill@ Copy install ramdisk to releasedir. Provide both a raw ffs and Legacy U-Boot version of it. Replace HUMMINGBIRD_A31 with SUNXI kernel on armv7.img and include .dtb files for SUNXI and TEGRA kernels on the MSDOS partition. Let the controller provide a default name for pins. This makes pins easier to locate when we have multiple banks and a variable number of pins per bank. Attach gpio(4) to sunxigpio Test for kernel build directory before reading DTB list Add support for Allwinner A83T SoC. Add A83T files Fixup busdma sync and locking in the RX path. Disable batch RX/TX ints. Fix AHB2 register definition and explicitly set AHB2 parent to PLL_PERIPH0/2 -- this gives us 50% more bus bandwidth for emac Restore TX_INTERVAL_DEFAULT to 64 Drop the sunxi_emac_rx_batch feature. It was originally designed to reduce the amount of mutex unlock/lock cycles during the RX path on FreeBSD and if_input, but it is not required to drop the lock before calling if_percpuq_enqueue on NetBSD. Write back the data value instead of mask in sunxi_gpio_write Add a helper for exposing LED controls via sysctl. Add GPIO LED driver. add gpioleds Add misc. gates and resets driver, and explicitly enable PIO clocks at attach. Add fdtbus_get_string_index helper. Add driver for fixed-factor clocks. Add ffclock Remove the requirement for ehci to attach after companion devices. "go for it" - skrll@ Remove the hack to find companion devices and just assume 1 companion if ETTF flag is not set. Remove pass numbers for ehci/ohci now that the attach order no longer matters Use unsigned char for ctype functions, suggested by christos Add : to body of populate_sunxi to appease bash. port-evbarm/52388: Fix number of args to a debug printf.
This commit is contained in:
parent
58286d5890
commit
5e6f0c1418
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.16 2017/01/27 15:20:31 rin Exp $
|
||||
# $NetBSD: Makefile,v 1.16.4.1 2017/07/18 19:13:07 snj Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
.include "${NETBSDSRCDIR}/distrib/common/Makefile.distrib"
|
||||
|
@ -38,6 +38,11 @@ ${CRUNCHBIN}: libhack.o
|
|||
.include "${DISTRIBDIR}/common/Makefile.makedev"
|
||||
.include "${DISTRIBDIR}/common/Makefile.image"
|
||||
|
||||
release:
|
||||
release: ${IMAGE}
|
||||
${RELEASE_INSTALL} ${IMAGE} \
|
||||
${RELEASEDIR}/${RELEASEMACHINEDIR}/installation/ramdisk/
|
||||
${TOOL_MKUBOOTIMAGE} -A arm -C none -O linux -T ramdisk \
|
||||
-a 0 -n "NetBSD/${MACHINE_ARCH} ramdisk" ${IMAGE} \
|
||||
${RELEASEDIR}/${RELEASEMACHINEDIR}/installation/ramdisk/${IMAGE:S/.fs/.ub/}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: armv7.conf,v 1.12 2017/04/12 23:35:29 jmcneill Exp $
|
||||
# $NetBSD: armv7.conf,v 1.12.4.1 2017/07/18 19:13:07 snj Exp $
|
||||
# ARMv7 customization script used by mkimage
|
||||
#
|
||||
board=armv7
|
||||
|
@ -8,10 +8,11 @@ resize=true
|
|||
. ${DIR}/conf/evbarm.conf
|
||||
|
||||
kernels_beagle="BEAGLEBOARD BEAGLEBONE"
|
||||
kernels_awin="BPI CUBIEBOARD CUBIETRUCK HUMMINGBIRD_A31"
|
||||
kernels_awin="BPI CUBIEBOARD CUBIETRUCK"
|
||||
kernels_rpi="RPI2"
|
||||
kernels_amlogic="ODROID-C1"
|
||||
kernels_tegra="TEGRA"
|
||||
kernels_sunxi="SUNXI"
|
||||
|
||||
make_label() {
|
||||
make_label_evbarm
|
||||
|
@ -105,6 +106,10 @@ run bootcmd
|
|||
EOF
|
||||
}
|
||||
|
||||
populate_sunxi() {
|
||||
:
|
||||
}
|
||||
|
||||
populate_tegra() {
|
||||
tegra_kernelimg=netbsd-TEGRA.ub
|
||||
tegra_loadaddr=0x90000000
|
||||
|
@ -124,7 +129,7 @@ populate() {
|
|||
echo "${bar} looking for kernels in ${kernel} ${bar}"
|
||||
kernels=""
|
||||
# .ub kernels
|
||||
for k in $kernels_beagle $kernels_awin $kernels_amlogic $kernels_tegra; do
|
||||
for k in $kernels_beagle $kernels_awin $kernels_sunxi $kernels_amlogic $kernels_tegra; do
|
||||
f="${kernel}/netbsd-${k}.ub.gz"
|
||||
test -f "${f}" && kernels="${kernels} ${f}"
|
||||
done
|
||||
|
@ -133,6 +138,16 @@ populate() {
|
|||
f="${kernel}/netbsd-${k}.bin.gz"
|
||||
test -f "${f}" && kernels="${kernels} ${f}"
|
||||
done
|
||||
# .dtb files
|
||||
for k in $kernels_sunxi $kernels_tegra; do
|
||||
test -d "${KERNOBJDIR}/${k}" && \
|
||||
dtbs="$(${MAKE} -C ${KERNOBJDIR}/${k} -v DTB)" || \
|
||||
dtbs=
|
||||
for dtb in $dtbs; do
|
||||
f="${kernel}/${dtb}.gz"
|
||||
test -f "${f}" && kernels="${kernels} ${f}"
|
||||
done
|
||||
done
|
||||
|
||||
# install kernels to /boot partition
|
||||
for k in ${kernels}; do
|
||||
|
@ -154,4 +169,5 @@ populate() {
|
|||
populate_rpi
|
||||
populate_amlogic
|
||||
populate_tegra
|
||||
populate_sunxi
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/sh
|
||||
# $NetBSD: mkimage,v 1.64 2017/04/11 21:06:30 jmcneill Exp $
|
||||
# $NetBSD: mkimage,v 1.64.4.1 2017/07/18 19:13:07 snj Exp $
|
||||
#
|
||||
# Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
|
@ -51,6 +51,7 @@ set -e
|
|||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROG="$(basename "$0")"
|
||||
|
||||
MAKE=${TOOL_MAKE:-make}
|
||||
DISKLABEL=${TOOL_DISKLABEL:-disklabel}
|
||||
FDISK=${TOOL_FDISK:-fdisk}
|
||||
MAKEFS=${TOOL_MAKEFS:-makefs}
|
||||
|
|
22
etc/Makefile
22
etc/Makefile
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.428 2017/05/21 15:28:38 riastradh Exp $
|
||||
# $NetBSD: Makefile,v 1.428.2.1 2017/07/18 19:13:07 snj Exp $
|
||||
# from: @(#)Makefile 8.7 (Berkeley) 5/25/95
|
||||
|
||||
# Environment variables without default values:
|
||||
|
@ -605,7 +605,7 @@ build_kernelsets: .PHONY
|
|||
.if ${configfile} == ${configsel}
|
||||
build_kernelsets: kernset-${configfile}
|
||||
kernset-${configfile}: .PHONY build_kernels snap_pre
|
||||
@ kernlist=$$(${GETKERNELAWK} ${KERNCONFDIR}/${configfile}); \
|
||||
@kernlist=$$(${GETKERNELAWK} ${KERNCONFDIR}/${configfile}); \
|
||||
kerndir=${KERNOBJDIR}/${configfile:C/.*\///}; \
|
||||
kernsuffixes="${KERNEL_SUFFIXES:S/^/./}"; \
|
||||
kern_tgz=${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/sets/kern-${configfile}.tgz; \
|
||||
|
@ -625,6 +625,10 @@ kernset-${configfile}: .PHONY build_kernels snap_pre
|
|||
echo "echo $${kernels} | $${pax_cmd}"; \
|
||||
( echo "/set uname=${BINOWN} gname=${BINGRP}"; \
|
||||
echo ". type=dir optional"; \
|
||||
dtblist=$$(${MAKE} -v DTB); \
|
||||
for dtb in $${dtblist}; do \
|
||||
echo "./$${dtb} type=file"; \
|
||||
done; \
|
||||
for kernel in $${kernels}; do \
|
||||
echo "./$${kernel} type=file"; \
|
||||
done ) | eval $${pax_cmd}; \
|
||||
|
@ -643,15 +647,25 @@ build_releasekernels: .PHONY
|
|||
.if ${configfile} == ${configsel}
|
||||
build_releasekernels: releasekern-${configfile}
|
||||
releasekern-${configfile}: .PHONY build_kernels snap_pre
|
||||
@ kernlist=$$(${GETKERNELAWK} ${KERNCONFDIR}/${configfile:C/.*\///}); \
|
||||
@kernlist=$$(${GETKERNELAWK} ${KERNCONFDIR}/${configfile:C/.*\///}); \
|
||||
kerndir=${KERNOBJDIR}/${configfile:C/.*\///}; \
|
||||
kernsuffixes="${KERNEL_SUFFIXES:S/^/./}"; \
|
||||
dest="${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/kernel"; \
|
||||
cd $${kerndir} && { \
|
||||
dtblist=$$(${MAKE} -v DTB); \
|
||||
for dtb in $${dtblist}; do \
|
||||
[ ! -f $${dtb} ] && continue; \
|
||||
dtb_gz="$${dest}/$${dtb}.gz"; \
|
||||
[ $${dtb_gz} -nt $${dtb} ] && continue; \
|
||||
rm -f $${dtb_gz}; \
|
||||
echo "${TOOL_GZIP} ${GZIP_FLAGS} -c < $${kerndir}/$${dtb} > $${dtb_gz}"; \
|
||||
${TOOL_GZIP} ${GZIP_FLAGS} -c < $${dtb} > $${dtb_gz}; \
|
||||
done; \
|
||||
for kernel in $${kernlist}; do \
|
||||
for s in "" $${kernsuffixes}; do \
|
||||
ks="$${kernel}$${s}"; \
|
||||
[ ! -f $${ks} ] && continue; \
|
||||
knl_gz="${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/kernel/$${kernel}-${configfile:C/.*\///}$${s}.gz"; \
|
||||
knl_gz="$${dest}/$${kernel}-${configfile:C/.*\///}$${s}.gz"; \
|
||||
[ $${knl_gz} -nt $${ks} ] && continue; \
|
||||
rm -f $${knl_gz}; \
|
||||
echo "${TOOL_GZIP} ${GZIP_FLAGS} -c < $${kerndir}/$${ks} > $${knl_gz}"; \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile.inc,v 1.81 2017/01/07 16:29:04 kiyohara Exp $
|
||||
# $NetBSD: Makefile.inc,v 1.81.6.1 2017/07/18 19:13:08 snj Exp $
|
||||
#
|
||||
# etc.evbarm/Makefile.inc -- evbarm-specific etc Makefile targets
|
||||
#
|
||||
|
@ -134,6 +134,7 @@ IMAGE.kern= ${IMAGE.rel}/binary/kernel
|
|||
IMAGE.instk= ${IMAGE.rel}/installation/instkernel
|
||||
|
||||
__mkimage: .USE
|
||||
TOOL_MAKE=${MAKE} \
|
||||
TOOL_MAKEFS=${TOOL_MAKEFS} \
|
||||
TOOL_DISKLABEL=${TOOL_DISKLABEL} \
|
||||
TOOL_FDISK=${TOOL_FDISK} \
|
||||
|
@ -143,6 +144,8 @@ __mkimage: .USE
|
|||
TOOL_MKUBOOTIMAGE=${TOOL_MKUBOOTIMAGE} \
|
||||
TOOL_MTREE=${TOOL_MTREE} \
|
||||
HOST_SH=${HOST_SH} \
|
||||
KERNOBJDIR=${KERNOBJDIR} \
|
||||
MACHINE=${MACHINE} \
|
||||
${HOST_SH} ${MKIMAGE} -x -h ${.TARGET:S/smp_//} -D ${DESTDIR} \
|
||||
-S ${NETBSDSRCDIR} -B ${IMAGEENDIAN} ${MKI_OPTS.${.TARGET}} \
|
||||
${IMAGE.dir}/${.TARGET:S/smp_//}.img.gz
|
||||
|
@ -197,4 +200,5 @@ snap_md_post: check_DESTDIR check_RELEASEDIR snap_post .WAIT ${SNAP_MD_POST_DEPS
|
|||
KERNEL_SUFFIXES= bin srec ub
|
||||
|
||||
INSTALLATION_DIRS+= binary/gzimg \
|
||||
installation/instkernel
|
||||
installation/instkernel \
|
||||
installation/ramdisk
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.4 2013/05/02 03:56:39 matt Exp $
|
||||
# $NetBSD: Makefile,v 1.4.22.1 2017/07/18 19:13:08 snj Exp $
|
||||
|
||||
.include <bsd.init.mk>
|
||||
.include <bsd.endian.mk>
|
||||
|
@ -19,7 +19,7 @@ SRCS= BootImageGenerator.cpp \
|
|||
elftosb_parser.tab.cpp
|
||||
|
||||
.ifdef HOSTPROG
|
||||
SRCS.lib!=cd ${.PARSEDIR}/../../lib && ${MAKE} -V '$${SRCS}'
|
||||
SRCS.lib!=cd ${.PARSEDIR}/../../lib && ${MAKE} -v SRCS
|
||||
SRCS+=${SRCS.lib}
|
||||
.endif
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.11 2016/07/15 19:40:42 christos Exp $
|
||||
# $NetBSD: Makefile,v 1.11.6.1 2017/07/18 19:13:08 snj Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
|
@ -15,7 +15,7 @@ DPADD+= ${MDOCMLLIB.mandoc} ${LIBZ}
|
|||
LDADD+= -L${MDOCMLOBJDIR.mandoc} -lmandoc -lz
|
||||
CPPFLAGS+= -DUSE_WCHAR
|
||||
.else
|
||||
SRCS.libmandoc!=cd ${.PARSEDIR}/../../lib/libmandoc && ${MAKE} -V '$${SRCS}'
|
||||
SRCS.libmandoc!=cd ${.PARSEDIR}/../../lib/libmandoc && ${MAKE} -v SRCS
|
||||
|
||||
SRCS+= ${SRCS.libmandoc} compat_strtonum.c compat_reallocarray.c
|
||||
.endif
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/* $NetBSD: psci.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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_diagnostic.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: psci.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <arm/arm/psci.h>
|
||||
|
||||
/* PSCI methods */
|
||||
#define PSCI_VERSION 0x84000000
|
||||
#define PSCI_SYSTEM_OFF 0x84000008
|
||||
#define PSCI_SYSTEM_RESET 0x84000009
|
||||
#if defined(__aarch64__)
|
||||
#define PSCI_CPU_ON 0xc4000002
|
||||
#else
|
||||
#define PSCI_CPU_ON 0x84000002
|
||||
#endif
|
||||
|
||||
static psci_fn psci_call_fn;
|
||||
|
||||
static uint32_t psci_functions[PSCI_FUNC_MAX] = {
|
||||
[PSCI_FUNC_VERSION] = PSCI_VERSION,
|
||||
[PSCI_FUNC_SYSTEM_OFF] = PSCI_SYSTEM_OFF,
|
||||
[PSCI_FUNC_SYSTEM_RESET] = PSCI_SYSTEM_RESET,
|
||||
[PSCI_FUNC_CPU_ON] = PSCI_CPU_ON,
|
||||
};
|
||||
|
||||
static int
|
||||
psci_call(register_t fid, register_t arg1, register_t arg2, register_t arg3)
|
||||
{
|
||||
KASSERT(psci_call_fn != NULL);
|
||||
|
||||
if (fid == 0)
|
||||
return PSCI_NOT_SUPPORTED;
|
||||
|
||||
return psci_call_fn(fid, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
psci_version(void)
|
||||
{
|
||||
if (psci_functions[PSCI_FUNC_VERSION] == 0) {
|
||||
/* Pre-0.2 implementation */
|
||||
return __SHIFTIN(0, PSCI_VERSION_MAJOR) |
|
||||
__SHIFTIN(1, PSCI_VERSION_MINOR);
|
||||
}
|
||||
|
||||
return psci_call(psci_functions[PSCI_FUNC_VERSION], 0, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
psci_cpu_on(register_t target_cpu, register_t entry_point_address,
|
||||
register_t context_id)
|
||||
{
|
||||
return psci_call(psci_functions[PSCI_FUNC_CPU_ON], target_cpu,
|
||||
entry_point_address, context_id);
|
||||
}
|
||||
|
||||
void
|
||||
psci_system_off(void)
|
||||
{
|
||||
psci_call(psci_functions[PSCI_FUNC_SYSTEM_OFF], 0, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
psci_system_reset(void)
|
||||
{
|
||||
psci_call(psci_functions[PSCI_FUNC_SYSTEM_RESET], 0, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
psci_init(psci_fn fn)
|
||||
{
|
||||
psci_call_fn = fn;
|
||||
}
|
||||
|
||||
void
|
||||
psci_clearfunc(void)
|
||||
{
|
||||
for (int i = 0; i < PSCI_FUNC_MAX; i++)
|
||||
psci_setfunc(i, 0);
|
||||
}
|
||||
|
||||
void
|
||||
psci_setfunc(enum psci_function func, uint32_t fid)
|
||||
{
|
||||
psci_functions[func] = fid;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/* $NetBSD: psci.h,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_PSCI_H
|
||||
#define _ARM_PSCI_H
|
||||
|
||||
/*
|
||||
* List of supported PSCI functions.
|
||||
*/
|
||||
enum psci_function {
|
||||
PSCI_FUNC_VERSION,
|
||||
PSCI_FUNC_CPU_ON,
|
||||
PSCI_FUNC_SYSTEM_OFF,
|
||||
PSCI_FUNC_SYSTEM_RESET,
|
||||
PSCI_FUNC_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* PSCI error codes
|
||||
*/
|
||||
#define PSCI_SUCCESS 0
|
||||
#define PSCI_NOT_SUPPORTED -1
|
||||
#define PSCI_INVALID_PARAMETERS -2
|
||||
#define PSCI_DENIED -3
|
||||
#define PSCI_ALREADY_ON -4
|
||||
#define PSCI_ON_PENDING -5
|
||||
#define PSCI_INTERNAL_FAILURE -6
|
||||
#define PSCI_NOT_PRESENT -7
|
||||
#define PSCI_DISABLED -8
|
||||
#define PSCI_INVALID_ADDRESS -9
|
||||
|
||||
/*
|
||||
* PSCI call method interface.
|
||||
*/
|
||||
typedef int (*psci_fn)(register_t, register_t, register_t, register_t);
|
||||
|
||||
/*
|
||||
* Set the PSCI call method. Pass either psci_call_smc or psci_call_hvc.
|
||||
*/
|
||||
void psci_init(psci_fn);
|
||||
|
||||
/*
|
||||
* PSCI call methods, implemented in psci.S
|
||||
*/
|
||||
int psci_call_smc(register_t, register_t, register_t, register_t);
|
||||
int psci_call_hvc(register_t, register_t, register_t, register_t);
|
||||
|
||||
/*
|
||||
* Clear PSCI function table. The default table includes function IDs for
|
||||
* PSCI 0.2+. A PSCI 0.1 implementation will use its own function ID mappings.
|
||||
*/
|
||||
void psci_clearfunc(void);
|
||||
|
||||
/*
|
||||
* Set PSCI function ID for a given PSCI function.
|
||||
*/
|
||||
void psci_setfunc(enum psci_function, uint32_t);
|
||||
|
||||
/*
|
||||
* Return the version of PSCI implemented.
|
||||
*/
|
||||
uint32_t psci_version(void);
|
||||
#define PSCI_VERSION_MAJOR __BITS(31,16)
|
||||
#define PSCI_VERSION_MINOR __BITS(15,0)
|
||||
|
||||
/*
|
||||
* Power up a core. Args: target_cpu, entry_point_address, context_id
|
||||
*/
|
||||
int psci_cpu_on(register_t, register_t, register_t);
|
||||
|
||||
/*
|
||||
* Shut down the system.
|
||||
*/
|
||||
void psci_system_off(void);
|
||||
|
||||
/*
|
||||
* Reset the system.
|
||||
*/
|
||||
void psci_system_reset(void);
|
||||
|
||||
#endif /* _ARM_PSCI_H */
|
|
@ -0,0 +1,47 @@
|
|||
/* $NetBSD: psci_arm.S,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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/asm.h>
|
||||
|
||||
RCSID("$NetBSD: psci_arm.S,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
.arch armv7a
|
||||
.arch_extension sec
|
||||
.arch_extension virt
|
||||
|
||||
/* Invoke PSCI function using Secure Monitor Call interface */
|
||||
ENTRY(psci_call_smc)
|
||||
smc #0
|
||||
RET
|
||||
END(psci_call_smc)
|
||||
|
||||
/* Invoke PSCI function using Hypervisor Call interface */
|
||||
ENTRY(psci_call_hvc)
|
||||
hvc #0
|
||||
RET
|
||||
END(psci_call_hvc)
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.arm,v 1.132 2017/05/26 21:17:46 jmcneill Exp $
|
||||
# $NetBSD: files.arm,v 1.132.2.1 2017/07/18 19:13:08 snj Exp $
|
||||
|
||||
# temporary define to allow easy moving to ../arch/arm/arm32
|
||||
defflag ARM32
|
||||
|
@ -91,6 +91,11 @@ obsolete defflag ARMFPE
|
|||
file arch/arm/vfp/vfp_init.c arm32
|
||||
#file arch/arm/vfp/pmap_vfp.S arm32 & fpu_vfp
|
||||
|
||||
# Power State Coordination Interface (PSCI)
|
||||
device psci
|
||||
file arch/arm/arm/psci.c psci
|
||||
file arch/arm/arm/psci_arm.S psci
|
||||
|
||||
# PMAP_DEBUG (heavily abused option)
|
||||
defflag PMAP_DEBUG
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: gic.c,v 1.21.2.1 2017/06/05 08:20:36 snj Exp $ */
|
||||
/* $NetBSD: gic.c,v 1.21.2.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
|
@ -34,7 +34,7 @@
|
|||
#define _INTR_PRIVATE
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.21.2.1 2017/06/05 08:20:36 snj Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.21.2.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -53,7 +53,12 @@ __KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.21.2.1 2017/06/05 08:20:36 snj Exp $");
|
|||
|
||||
void armgic_irq_handler(void *);
|
||||
|
||||
#define ARMGIC_SGI_IPIBASE (16 - NIPI)
|
||||
#define ARMGIC_SGI_IPIBASE 0
|
||||
|
||||
/*
|
||||
* SGIs 8-16 are reserved for use by ARM Trusted Firmware.
|
||||
*/
|
||||
__CTASSERT(ARMGIC_SGI_IPIBASE + NIPI <= 8);
|
||||
|
||||
static int armgic_match(device_t, cfdata_t, void *);
|
||||
static void armgic_attach(device_t, device_t, void *);
|
||||
|
@ -100,6 +105,7 @@ static struct armgic_softc {
|
|||
#ifdef MULTIPROCESSOR
|
||||
uint32_t sc_mptargets;
|
||||
#endif
|
||||
uint32_t sc_bptargets;
|
||||
} armgic_softc = {
|
||||
.sc_pic = {
|
||||
.pic_ops = &armgic_picops,
|
||||
|
@ -139,6 +145,29 @@ gicd_write(struct armgic_softc *sc, bus_size_t o, uint32_t v)
|
|||
bus_space_write_4(sc->sc_memt, sc->sc_gicdh, o, v);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
gicd_find_targets(struct armgic_softc *sc)
|
||||
{
|
||||
uint32_t targets = 0;
|
||||
|
||||
/*
|
||||
* GICD_ITARGETSR0 through 7 are read-only, and each field returns
|
||||
* a value that corresponds only to the processor reading the
|
||||
* register. Use this to determine the current processor's
|
||||
* CPU interface number.
|
||||
*/
|
||||
for (int i = 0; i < 8; i++) {
|
||||
targets = gicd_read(sc, GICD_ITARGETSRn(i));
|
||||
if (targets != 0)
|
||||
break;
|
||||
}
|
||||
targets |= (targets >> 16);
|
||||
targets |= (targets >> 8);
|
||||
targets &= 0xff;
|
||||
|
||||
return targets ? targets : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the GIC prioritization scheme, lower numbers have higher priority.
|
||||
* Only write priorities that could be non-secure.
|
||||
|
@ -356,7 +385,7 @@ armgic_establish_irq(struct pic_softc *pic, struct intrsource *is)
|
|||
} else
|
||||
#endif
|
||||
#endif
|
||||
targets |= 1 << byte_shift;
|
||||
targets |= sc->sc_bptargets << byte_shift;
|
||||
gicd_write(sc, targets_reg, targets);
|
||||
|
||||
/*
|
||||
|
@ -458,11 +487,11 @@ void
|
|||
armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
|
||||
{
|
||||
struct armgic_softc * const sc = PICTOSOFTC(pic);
|
||||
sc->sc_mptargets |= 1 << cpu_index(ci);
|
||||
sc->sc_mptargets |= gicd_find_targets(sc);
|
||||
KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl);
|
||||
armgic_cpu_init_priorities(sc);
|
||||
if (!CPU_IS_PRIMARY(ci)) {
|
||||
if (sc->sc_mptargets != 1) {
|
||||
if (popcount(sc->sc_mptargets) != 1) {
|
||||
armgic_cpu_init_targets(sc);
|
||||
}
|
||||
if (sc->sc_enabled_local) {
|
||||
|
@ -544,6 +573,11 @@ armgic_attach(device_t parent, device_t self, void *aux)
|
|||
uint32_t pmr = gicc_read(sc, GICC_PMR);
|
||||
u_int priorities = 1 << popcount32(pmr);
|
||||
|
||||
/*
|
||||
* Find the boot processor's CPU interface number.
|
||||
*/
|
||||
sc->sc_bptargets = gicd_find_targets(sc);
|
||||
|
||||
/*
|
||||
* Let's find out how many real sources we have.
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: arm_fdt.c,v 1.3 2017/05/30 22:00:25 jmcneill Exp $ */
|
||||
/* $NetBSD: arm_fdt.c,v 1.3.2.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: arm_fdt.c,v 1.3 2017/05/30 22:00:25 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: arm_fdt.c,v 1.3.2.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -143,3 +143,26 @@ arm_fdt_irq_handler(void *tf)
|
|||
{
|
||||
_arm_fdt_irq_handler(tf);
|
||||
}
|
||||
|
||||
void
|
||||
arm_fdt_memory_dump(paddr_t pa)
|
||||
{
|
||||
const struct arm_platform *plat = arm_fdt_platform();
|
||||
struct fdt_attach_args faa;
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
|
||||
plat->init_attach_args(&faa);
|
||||
|
||||
bst = faa.faa_bst;
|
||||
bus_space_map(bst, pa, 0x100, 0, &bsh);
|
||||
|
||||
for (int i = 0; i < 0x100; i += 0x10) {
|
||||
printf("%" PRIxPTR ": %08x %08x %08x %08x\n",
|
||||
(uintptr_t)(pa + i),
|
||||
bus_space_read_4(bst, bsh, i + 0),
|
||||
bus_space_read_4(bst, bsh, i + 4),
|
||||
bus_space_read_4(bst, bsh, i + 8),
|
||||
bus_space_read_4(bst, bsh, i + 12));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: arm_fdtvar.h,v 1.5 2017/06/02 13:53:28 jmcneill Exp $ */
|
||||
/* $NetBSD: arm_fdtvar.h,v 1.5.2.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -71,4 +71,6 @@ void arm_fdt_cpu_hatch(struct cpu_info *);
|
|||
void arm_fdt_irq_set_handler(void (*)(void *));
|
||||
void arm_fdt_irq_handler(void *);
|
||||
|
||||
void arm_fdt_memory_dump(paddr_t);
|
||||
|
||||
#endif /* !_ARM_ARM_FDTVAR_H */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.fdt,v 1.9.2.2 2017/06/10 05:57:08 snj Exp $
|
||||
# $NetBSD: files.fdt,v 1.9.2.3 2017/07/18 19:13:08 snj Exp $
|
||||
|
||||
include "dev/pckbport/files.pckbport"
|
||||
|
||||
|
@ -38,5 +38,8 @@ file arch/arm/fdt/aaci_fdt.c aaci_fdt
|
|||
attach plrtc at fdt with plrtc_fdt
|
||||
file arch/arm/fdt/plrtc_fdt.c plrtc_fdt
|
||||
|
||||
attach psci at fdt with psci_fdt
|
||||
file arch/arm/fdt/psci_fdt.c psci_fdt
|
||||
|
||||
# Console parameters
|
||||
defparam opt_fdt_arm.h CONSADDR
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: gic_fdt.c,v 1.4 2017/05/30 22:00:25 jmcneill Exp $ */
|
||||
/* $NetBSD: gic_fdt.c,v 1.4.2.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: gic_fdt.c,v 1.4 2017/05/30 22:00:25 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: gic_fdt.c,v 1.4.2.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -35,6 +35,7 @@ __KERNEL_RCSID(0, "$NetBSD: gic_fdt.c,v 1.4 2017/05/30 22:00:25 jmcneill Exp $")
|
|||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lwp.h>
|
||||
#include <sys/kmem.h>
|
||||
|
||||
#include <arm/cortex/gic_intr.h>
|
||||
|
@ -42,9 +43,13 @@ __KERNEL_RCSID(0, "$NetBSD: gic_fdt.c,v 1.4 2017/05/30 22:00:25 jmcneill Exp $")
|
|||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#define GIC_MAXIRQ 1020
|
||||
|
||||
static int gic_fdt_match(device_t, cfdata_t, void *);
|
||||
static void gic_fdt_attach(device_t, device_t, void *);
|
||||
|
||||
static int gic_fdt_intr(void *);
|
||||
|
||||
static void * gic_fdt_establish(device_t, u_int *, int, int,
|
||||
int (*)(void *), void *);
|
||||
static void gic_fdt_disestablish(device_t, void *);
|
||||
|
@ -56,9 +61,32 @@ struct fdtbus_interrupt_controller_func gic_fdt_funcs = {
|
|||
.intrstr = gic_fdt_intrstr
|
||||
};
|
||||
|
||||
struct gic_fdt_softc;
|
||||
struct gic_fdt_irq;
|
||||
|
||||
struct gic_fdt_irqhandler {
|
||||
struct gic_fdt_irq *ih_irq;
|
||||
int (*ih_fn)(void *);
|
||||
void *ih_arg;
|
||||
bool ih_mpsafe;
|
||||
TAILQ_ENTRY(gic_fdt_irqhandler) ih_next;
|
||||
};
|
||||
|
||||
struct gic_fdt_irq {
|
||||
struct gic_fdt_softc *intr_sc;
|
||||
void *intr_ih;
|
||||
int intr_refcnt;
|
||||
int intr_ipl;
|
||||
int intr_level;
|
||||
int intr_mpsafe;
|
||||
TAILQ_HEAD(, gic_fdt_irqhandler) intr_handlers;
|
||||
};
|
||||
|
||||
struct gic_fdt_softc {
|
||||
device_t sc_dev;
|
||||
int sc_phandle;
|
||||
|
||||
struct gic_fdt_irq *sc_irq[GIC_MAXIRQ];
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(gic_fdt, sizeof(struct gic_fdt_softc),
|
||||
|
@ -137,7 +165,9 @@ static void *
|
|||
gic_fdt_establish(device_t dev, u_int *specifier, int ipl, int flags,
|
||||
int (*func)(void *), void *arg)
|
||||
{
|
||||
int iflags = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
|
||||
struct gic_fdt_softc * const sc = device_private(dev);
|
||||
struct gic_fdt_irq *firq;
|
||||
struct gic_fdt_irqhandler *firqh;
|
||||
|
||||
/* 1st cell is the interrupt type; 0 is SPI, 1 is PPI */
|
||||
/* 2nd cell is the interrupt number */
|
||||
|
@ -149,13 +179,80 @@ gic_fdt_establish(device_t dev, u_int *specifier, int ipl, int flags,
|
|||
const u_int trig = be32toh(specifier[2]) & 0xf;
|
||||
const u_int level = (trig & 0x3) ? IST_EDGE : IST_LEVEL;
|
||||
|
||||
return intr_establish(irq, ipl, level | iflags, func, arg);
|
||||
const u_int mpsafe = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
|
||||
|
||||
firq = sc->sc_irq[irq];
|
||||
if (firq == NULL) {
|
||||
firq = kmem_alloc(sizeof(*firq), KM_SLEEP);
|
||||
firq->intr_sc = sc;
|
||||
firq->intr_refcnt = 0;
|
||||
firq->intr_ipl = ipl;
|
||||
firq->intr_level = level;
|
||||
firq->intr_mpsafe = mpsafe;
|
||||
TAILQ_INIT(&firq->intr_handlers);
|
||||
firq->intr_ih = intr_establish(irq, ipl, level | mpsafe,
|
||||
gic_fdt_intr, firq);
|
||||
if (firq->intr_ih == NULL) {
|
||||
kmem_free(firq, sizeof(*firq));
|
||||
return NULL;
|
||||
}
|
||||
sc->sc_irq[irq] = firq;
|
||||
}
|
||||
|
||||
if (firq->intr_ipl != ipl) {
|
||||
device_printf(dev, "cannot share irq with different ipl\n");
|
||||
return NULL;
|
||||
}
|
||||
if (firq->intr_level != level) {
|
||||
device_printf(dev, "cannot share edge and level interrupts\n");
|
||||
return NULL;
|
||||
}
|
||||
if (firq->intr_mpsafe != mpsafe) {
|
||||
device_printf(dev, "cannot share between mpsafe/non-mpsafe\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
firq->intr_refcnt++;
|
||||
|
||||
firqh = kmem_alloc(sizeof(*firqh), KM_SLEEP);
|
||||
firqh->ih_mpsafe = (flags & FDT_INTR_MPSAFE) != 0;
|
||||
firqh->ih_irq = firq;
|
||||
firqh->ih_fn = func;
|
||||
firqh->ih_arg = arg;
|
||||
TAILQ_INSERT_TAIL(&firq->intr_handlers, firqh, ih_next);
|
||||
|
||||
return firqh;
|
||||
}
|
||||
|
||||
static void
|
||||
gic_fdt_disestablish(device_t dev, void *ih)
|
||||
{
|
||||
intr_disestablish(ih);
|
||||
struct gic_fdt_irqhandler *firqh = ih;
|
||||
struct gic_fdt_irq *firq = firqh->ih_irq;
|
||||
|
||||
KASSERT(firq->intr_refcnt > 0);
|
||||
|
||||
TAILQ_REMOVE(&firq->intr_handlers, firqh, ih_next);
|
||||
kmem_free(firqh, sizeof(*firqh));
|
||||
|
||||
firq->intr_refcnt--;
|
||||
if (firq->intr_refcnt == 0) {
|
||||
intr_disestablish(firq->intr_ih);
|
||||
kmem_free(firq, sizeof(*firq));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
gic_fdt_intr(void *priv)
|
||||
{
|
||||
struct gic_fdt_irq *firq = priv;
|
||||
struct gic_fdt_irqhandler *firqh;
|
||||
int handled = 0;
|
||||
|
||||
TAILQ_FOREACH(firqh, &firq->intr_handlers, ih_next)
|
||||
handled += firqh->ih_fn(firqh->ih_arg);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
/* $NetBSD: psci_fdt.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: psci_fdt.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <arm/locore.h>
|
||||
#include <arm/armreg.h>
|
||||
|
||||
#include <arm/arm/psci.h>
|
||||
#include <arm/fdt/psci_fdt.h>
|
||||
|
||||
static int psci_fdt_match(device_t, cfdata_t, void *);
|
||||
static void psci_fdt_attach(device_t, device_t, void *);
|
||||
|
||||
static int psci_fdt_init(const int);
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"arm,psci",
|
||||
"arm,psci-0.2",
|
||||
"arm,psci-1.0",
|
||||
NULL
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(psci_fdt, 0, psci_fdt_match, psci_fdt_attach, NULL, NULL);
|
||||
|
||||
static int
|
||||
psci_fdt_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
psci_fdt_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
|
||||
psci_fdt_init(phandle);
|
||||
|
||||
const uint32_t ver = psci_version();
|
||||
const u_int ver_maj = __SHIFTOUT(ver, PSCI_VERSION_MAJOR);
|
||||
const u_int ver_min = __SHIFTOUT(ver, PSCI_VERSION_MINOR);
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": PSCI %u.%u\n", ver_maj, ver_min);
|
||||
}
|
||||
|
||||
static int
|
||||
psci_fdt_init(const int phandle)
|
||||
{
|
||||
char method[4];
|
||||
uint32_t val;
|
||||
|
||||
if (!of_hasprop(phandle, "method")) {
|
||||
aprint_error("PSCI: missing 'method' property\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
OF_getprop(phandle, "method", method, sizeof(method));
|
||||
if (strcmp(method, "smc") == 0)
|
||||
psci_init(psci_call_smc);
|
||||
else if (strcmp(method, "hvc") == 0)
|
||||
psci_init(psci_call_hvc);
|
||||
else {
|
||||
aprint_error("PSCI: unsupported method '%s'\n", method);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
const char * const compat_0_1[] = { "arm,psci", NULL };
|
||||
if (of_match_compatible(phandle, compat_0_1)) {
|
||||
psci_clearfunc();
|
||||
if (of_getprop_uint32(phandle, "cpu_on", &val) == 0)
|
||||
psci_setfunc(PSCI_FUNC_CPU_ON, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
psci_fdt_bootstrap(void)
|
||||
{
|
||||
extern void cortex_mpstart(void);
|
||||
bus_addr_t mpidr;
|
||||
uint32_t bp_mpidr;
|
||||
int child;
|
||||
|
||||
const int cpus = OF_finddevice("/cpus");
|
||||
if (cpus == -1) {
|
||||
aprint_error("PSCI: no /cpus node found\n");
|
||||
arm_cpu_max = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Count CPUs */
|
||||
arm_cpu_max = 0;
|
||||
for (child = OF_child(cpus); child; child = OF_peer(child))
|
||||
if (fdtbus_status_okay(child))
|
||||
arm_cpu_max++;
|
||||
|
||||
const int phandle = OF_finddevice("/psci");
|
||||
if (phandle == -1) {
|
||||
aprint_error("PSCI: no /psci node found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (psci_fdt_init(phandle) != 0)
|
||||
return;
|
||||
|
||||
/* MPIDR affinity levels of boot processor. */
|
||||
bp_mpidr = armreg_mpidr_read() & (MPIDR_AFF2|MPIDR_AFF1|MPIDR_AFF0);
|
||||
|
||||
/* Boot APs */
|
||||
uint32_t started = 0;
|
||||
for (child = OF_child(cpus); child; child = OF_peer(child)) {
|
||||
if (!fdtbus_status_okay(child))
|
||||
continue;
|
||||
if (fdtbus_get_reg(child, 0, &mpidr, NULL) != 0)
|
||||
continue;
|
||||
if (mpidr == bp_mpidr)
|
||||
continue; /* BP already started */
|
||||
|
||||
/* XXX NetBSD requires all CPUs to be in the same cluster */
|
||||
const u_int bp_clid = __SHIFTOUT(bp_mpidr, CORTEXA9_MPIDR_CLID);
|
||||
const u_int clid = __SHIFTOUT(mpidr, CORTEXA9_MPIDR_CLID);
|
||||
if (bp_clid != clid)
|
||||
continue;
|
||||
|
||||
const u_int cpuid = __SHIFTOUT(mpidr, CORTEXA9_MPIDR_CPUID);
|
||||
int ret = psci_cpu_on(cpuid, (register_t)cortex_mpstart, 0);
|
||||
if (ret == PSCI_SUCCESS)
|
||||
started |= __BIT(cpuid);
|
||||
}
|
||||
|
||||
/* Wait for APs to start */
|
||||
for (u_int i = 0x10000000; i > 0; i--) {
|
||||
arm_dmb();
|
||||
if (arm_cpu_hatched == started)
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* $NetBSD: psci_fdt.h,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_PSCI_FDT_H
|
||||
#define _ARM_PSCI_FDT_H
|
||||
|
||||
/* Initialize PSCI and boot APs */
|
||||
void psci_fdt_bootstrap(void);
|
||||
|
||||
#endif /* !_ARM_PSCI_FDT_H */
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rockchip_dwcmmc.c,v 1.5 2015/01/03 13:29:02 jmcneill Exp $ */
|
||||
/* $NetBSD: rockchip_dwcmmc.c,v 1.5.12.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: rockchip_dwcmmc.c,v 1.5 2015/01/03 13:29:02 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: rockchip_dwcmmc.c,v 1.5.12.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -46,8 +46,6 @@ __KERNEL_RCSID(0, "$NetBSD: rockchip_dwcmmc.c,v 1.5 2015/01/03 13:29:02 jmcneill
|
|||
static int rk_dwcmmc_match(device_t, cfdata_t, void *);
|
||||
static void rk_dwcmmc_attach(device_t, device_t, void *);
|
||||
|
||||
static void rk_dwcmmc_attach_i(device_t);
|
||||
|
||||
CFATTACH_DECL_NEW(rkdwcmmc, sizeof(struct dwc_mmc_softc),
|
||||
rk_dwcmmc_match, rk_dwcmmc_attach, NULL, NULL);
|
||||
|
||||
|
@ -68,8 +66,7 @@ rk_dwcmmc_attach(device_t parent, device_t self, void *aux)
|
|||
sc->sc_dev = self;
|
||||
sc->sc_bst = obio->obio_bst;
|
||||
sc->sc_dmat = obio->obio_dmat;
|
||||
sc->sc_flags = DWC_MMC_F_USE_HOLD_REG | DWC_MMC_F_PWREN_CLEAR |
|
||||
DWC_MMC_F_FORCE_CLK;
|
||||
sc->sc_flags = DWC_MMC_F_USE_HOLD_REG;
|
||||
sc->sc_clock_freq = rockchip_mmc0_get_rate();
|
||||
#if 0
|
||||
sc->sc_clock_max = 24000;
|
||||
|
@ -82,6 +79,9 @@ rk_dwcmmc_attach(device_t parent, device_t self, void *aux)
|
|||
aprint_naive("\n");
|
||||
aprint_normal(": SD/MMC controller\n");
|
||||
|
||||
if (dwc_mmc_init(sc) != 0)
|
||||
return;
|
||||
|
||||
sc->sc_ih = intr_establish(obio->obio_intr, IPL_BIO, IST_LEVEL,
|
||||
dwc_mmc_intr, sc);
|
||||
if (sc->sc_ih == NULL) {
|
||||
|
@ -89,14 +89,4 @@ rk_dwcmmc_attach(device_t parent, device_t self, void *aux)
|
|||
obio->obio_intr);
|
||||
return;
|
||||
}
|
||||
|
||||
config_interrupts(self, rk_dwcmmc_attach_i);
|
||||
}
|
||||
|
||||
static void
|
||||
rk_dwcmmc_attach_i(device_t self)
|
||||
{
|
||||
struct dwc_mmc_softc *sc = device_private(self);
|
||||
|
||||
dwc_mmc_init(sc);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,864 @@
|
|||
/* $NetBSD: exynos5410_clock.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos5410_clock.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/atomic.h>
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#include <arm/samsung/exynos_reg.h>
|
||||
#include <arm/samsung/exynos_var.h>
|
||||
#include <arm/samsung/exynos_clock.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
static struct clk *exynos5410_clock_decode(device_t, const void *, size_t);
|
||||
|
||||
static const struct fdtbus_clock_controller_func exynos5410_car_fdtclock_funcs = {
|
||||
.decode = exynos5410_clock_decode
|
||||
};
|
||||
|
||||
/* DT clock ID to clock name mappings */
|
||||
static struct exynos5410_clock_id {
|
||||
u_int id;
|
||||
const char *name;
|
||||
} exynos5410_clock_ids[] = {
|
||||
/* core clocks */
|
||||
{ 1, "fin_pll" },
|
||||
{ 2, "fout_apll" },
|
||||
{ 3, "fout_cpll" },
|
||||
{ 4, "fout_dpll" },
|
||||
{ 5, "fout_mpll" },
|
||||
{ 6, "fout_kpll" },
|
||||
{ 7, "fout_epll" },
|
||||
|
||||
/* gate for special clocks (sclk) */
|
||||
{ 128, "sclk_uart0" },
|
||||
{ 129, "sclk_uart1" },
|
||||
{ 130, "sclk_uart2" },
|
||||
{ 131, "sclk_uart3" },
|
||||
{ 132, "sclk_mmc0" },
|
||||
{ 133, "sclk_mmc1" },
|
||||
{ 134, "sclk_mmc2" },
|
||||
{ 150, "sclk_usbd300" },
|
||||
{ 151, "sclk_usbd301" },
|
||||
{ 152, "sclk_usbphy300" },
|
||||
{ 153, "sclk_usbphy301" },
|
||||
{ 155, "sclk_pwm" },
|
||||
|
||||
/* gate clocks */
|
||||
{ 257, "uart0" },
|
||||
{ 258, "uart1" },
|
||||
{ 259, "uart2" },
|
||||
{ 260, "uart3" },
|
||||
{ 261, "i2c0" },
|
||||
{ 262, "i2c1" },
|
||||
{ 263, "i2c2" },
|
||||
{ 264, "i2c3" },
|
||||
{ 265, "usi0" },
|
||||
{ 266, "usi1" },
|
||||
{ 267, "usi2" },
|
||||
{ 268, "usi3" },
|
||||
{ 279, "pwm" },
|
||||
{ 315, "mct" },
|
||||
{ 316, "wdt" },
|
||||
{ 317, "rtc" },
|
||||
{ 318, "tmu" },
|
||||
{ 351, "mmc0" },
|
||||
{ 352, "mmc1" },
|
||||
{ 353, "mmc2" },
|
||||
{ 362, "pdma0" },
|
||||
{ 363, "pdma1" },
|
||||
{ 365, "usbh20" },
|
||||
{ 366, "usbd300" },
|
||||
{ 367, "usbd301" },
|
||||
{ 471, "sss" },
|
||||
};
|
||||
|
||||
static struct clk *exynos5410_clock_get(void *, const char *);
|
||||
static void exynos5410_clock_put(void *, struct clk *);
|
||||
static u_int exynos5410_clock_get_rate(void *, struct clk *);
|
||||
static int exynos5410_clock_set_rate(void *, struct clk *, u_int);
|
||||
static int exynos5410_clock_enable(void *, struct clk *);
|
||||
static int exynos5410_clock_disable(void *, struct clk *);
|
||||
static int exynos5410_clock_set_parent(void *, struct clk *, struct clk *);
|
||||
static struct clk *exynos5410_clock_get_parent(void *, struct clk *);
|
||||
|
||||
static const struct clk_funcs exynos5410_clock_funcs = {
|
||||
.get = exynos5410_clock_get,
|
||||
.put = exynos5410_clock_put,
|
||||
.get_rate = exynos5410_clock_get_rate,
|
||||
.set_rate = exynos5410_clock_set_rate,
|
||||
.enable = exynos5410_clock_enable,
|
||||
.disable = exynos5410_clock_disable,
|
||||
.set_parent = exynos5410_clock_set_parent,
|
||||
.get_parent = exynos5410_clock_get_parent,
|
||||
};
|
||||
|
||||
#define CLK_FIXED(_name, _rate) { \
|
||||
.base = { .name = (_name) }, .type = EXYNOS_CLK_FIXED, \
|
||||
.u = { .fixed = { .rate = (_rate) } } \
|
||||
}
|
||||
|
||||
#define CLK_PLL(_name, _parent, _lock, _con0) { \
|
||||
.base = { .name = (_name) }, .type = EXYNOS_CLK_PLL, \
|
||||
.parent = (_parent), \
|
||||
.u = { \
|
||||
.pll = { \
|
||||
.lock_reg = (_lock), \
|
||||
.con0_reg = (_con0), \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CLK_MUXF(_name, _alias, _reg, _bits, _f, _p) { \
|
||||
.base = { .name = (_name), .flags = (_f) }, \
|
||||
.type = EXYNOS_CLK_MUX, \
|
||||
.alias = (_alias), \
|
||||
.u = { \
|
||||
.mux = { \
|
||||
.nparents = __arraycount(_p), \
|
||||
.parents = (_p), \
|
||||
.reg = (_reg), \
|
||||
.bits = (_bits) \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CLK_MUXA(_name, _alias, _reg, _bits, _p) \
|
||||
CLK_MUXF(_name, _alias, _reg, _bits, 0, _p)
|
||||
|
||||
#define CLK_MUX(_name, _reg, _bits, _p) \
|
||||
CLK_MUXF(_name, NULL, _reg, _bits, 0, _p)
|
||||
|
||||
#define CLK_DIVF(_name, _parent, _reg, _bits, _f) { \
|
||||
.base = { .name = (_name), .flags = (_f) }, \
|
||||
.type = EXYNOS_CLK_DIV, \
|
||||
.parent = (_parent), \
|
||||
.u = { \
|
||||
.div = { \
|
||||
.reg = (_reg), \
|
||||
.bits = (_bits) \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CLK_DIV(_name, _parent, _reg, _bits) \
|
||||
CLK_DIVF(_name, _parent, _reg, _bits, 0)
|
||||
|
||||
#define CLK_GATE(_name, _parent, _reg, _bits, _f) { \
|
||||
.base = { .name = (_name), .flags = (_f) }, \
|
||||
.type = EXYNOS_CLK_GATE, \
|
||||
.parent = (_parent), \
|
||||
.u = { \
|
||||
.gate = { \
|
||||
.reg = (_reg), \
|
||||
.bits = (_bits) \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define EXYNOS5410_APLL_LOCK 0x00000
|
||||
#define EXYNOS5410_APLL_CON0 0x00100
|
||||
#define EXYNOS5410_MPLL_LOCK 0x04000
|
||||
#define EXYNOS5410_MPLL_CON0 0x04100
|
||||
#define EXYNOS5410_CPLL_LOCK 0x10020
|
||||
#define EXYNOS5410_EPLL_LOCK 0x10040
|
||||
#define EXYNOS5410_CPLL_CON0 0x10120
|
||||
#define EXYNOS5410_EPLL_CON0 0x10130
|
||||
#define EXYNOS5410_EPLL_CON1 0x10134
|
||||
#define EXYNOS5410_EPLL_CON2 0x10138
|
||||
#define EXYNOS5410_BPLL_LOCK 0x20010
|
||||
#define EXYNOS5410_BPLL_CON0 0x20110
|
||||
#define EXYNOS5410_KPLL_LOCK 0x28000
|
||||
#define EXYNOS5410_KPLL_CON0 0x28100
|
||||
|
||||
#define EXYNOS5410_SRC_CPU 0x00200
|
||||
#define EXYNOS5410_SRC_CPERI1 0x04204
|
||||
#define EXYNOS5410_SRC_TOP0 0x10210
|
||||
#define EXYNOS5410_SRC_TOP1 0x10214
|
||||
#define EXYNOS5410_SRC_TOP2 0x10218
|
||||
#define EXYNOS5410_SRC_FSYS 0x10244
|
||||
#define EXYNOS5410_SRC_PERIC0 0x10250
|
||||
#define EXYNOS5410_SRC_MASK_FSYS 0x10340
|
||||
#define EXYNOS5410_SRC_MASK_PERIC0 0x10350
|
||||
#define EXYNOS5410_SRC_CDREX 0x20200
|
||||
#define EXYNOS5410_SRC_KFC 0x28200
|
||||
|
||||
#define EXYNOS5410_DIV_CPU0 0x00500
|
||||
#define EXYNOS5410_DIV_TOP0 0x10510
|
||||
#define EXYNOS5410_DIV_TOP1 0x10514
|
||||
#define EXYNOS5410_DIV_FSYS0 0x10548
|
||||
#define EXYNOS5410_DIV_FSYS1 0x1054c
|
||||
#define EXYNOS5410_DIV_FSYS2 0x10550
|
||||
#define EXYNOS5410_DIV_PERIC0 0x10558
|
||||
#define EXYNOS5410_DIV_PERIC3 0x10564
|
||||
#define EXYNOS5410_DIV_KFC0 0x28500
|
||||
|
||||
#define EXYNOS5410_GATE_IP_G2D 0x08800
|
||||
#define EXYNOS5410_GATE_BUS_FSYS0 0x10740
|
||||
#define EXYNOS5410_GATE_TOP_SCLK_FSYS 0x10840
|
||||
#define EXYNOS5410_GATE_TOP_SCLK_PERIC 0x10850
|
||||
#define EXYNOS5410_GATE_IP_FSYS 0x10944
|
||||
#define EXYNOS5410_GATE_IP_PERIC 0x10950
|
||||
#define EXYNOS5410_GATE_IP_PERIS 0x10960
|
||||
|
||||
static const char *mout_apll_p[] = { "fin_pll", "fout_apll" };
|
||||
static const char *mout_bpll_p[] = { "fin_pll", "fout_bpll" };
|
||||
static const char *mout_cpll_p[] = { "fin_pll", "fout_cpll" };
|
||||
static const char *mout_epll_p[] = { "fin_pll", "fout_epll" };
|
||||
static const char *mout_mpll_p[] = { "fin_pll", "fout_mpll" };
|
||||
static const char *mout_kpll_p[] = { "fin_pll", "fout_kpll" };
|
||||
|
||||
static const char *mout_cpu_p[] = { "mout_apll", "sclk_mpll" };
|
||||
static const char *mout_kfc_p[] = { "mout_kpll", "sclk_mpll" };
|
||||
|
||||
static const char *mout_mpll_user_p[] = { "fin_pll", "sclk_mpll" };
|
||||
static const char *mout_bpll_user_p[] = { "fin_pll", "sclk_bpll" };
|
||||
static const char *mout_mpll_bpll_p[] =
|
||||
{ "sclk_mpll_muxed", "sclk_bpll_muxed" };
|
||||
static const char *mout_sclk_mpll_bpll_p[] = { "sclk_mpll_bpll", "fin_pll" };
|
||||
|
||||
static const char *mout_group2_p[] =
|
||||
{ "fin_pll", "fin_pll", "none", "none", "none", "none",
|
||||
"sclk_mpll_bpll", "none", "none", "sclk_cpll" };
|
||||
|
||||
static struct exynos_clk exynos5410_clocks[] = {
|
||||
CLK_FIXED("fin_pll", EXYNOS_F_IN_FREQ),
|
||||
|
||||
CLK_PLL("fout_apll", "fin_pll", EXYNOS5410_APLL_LOCK,
|
||||
EXYNOS5410_APLL_CON0),
|
||||
CLK_PLL("fout_bpll", "fin_pll", EXYNOS5410_BPLL_LOCK,
|
||||
EXYNOS5410_BPLL_CON0),
|
||||
CLK_PLL("fout_cpll", "fin_pll", EXYNOS5410_CPLL_LOCK,
|
||||
EXYNOS5410_CPLL_CON0),
|
||||
CLK_PLL("fout_epll", "fin_pll", EXYNOS5410_EPLL_LOCK,
|
||||
EXYNOS5410_EPLL_CON0),
|
||||
CLK_PLL("fout_mpll", "fin_pll", EXYNOS5410_MPLL_LOCK,
|
||||
EXYNOS5410_MPLL_CON0),
|
||||
CLK_PLL("fout_kpll", "fin_pll", EXYNOS5410_KPLL_LOCK,
|
||||
EXYNOS5410_KPLL_CON0),
|
||||
|
||||
CLK_MUX("mout_apll", EXYNOS5410_SRC_CPU, __BIT(0), mout_apll_p),
|
||||
CLK_MUX("mout_cpu", EXYNOS5410_SRC_CPU, __BIT(16), mout_cpu_p),
|
||||
CLK_MUX("mout_kpll", EXYNOS5410_SRC_KFC, __BIT(0), mout_kpll_p),
|
||||
CLK_MUX("mout_kfc", EXYNOS5410_SRC_KFC, __BIT(16), mout_kfc_p),
|
||||
|
||||
CLK_MUX("sclk_mpll", EXYNOS5410_SRC_CPERI1, __BIT(8), mout_mpll_p),
|
||||
CLK_MUX("sclk_mpll_muxed", EXYNOS5410_SRC_TOP2, __BIT(20), mout_mpll_user_p),
|
||||
CLK_MUX("sclk_bpll", EXYNOS5410_SRC_CDREX, __BIT(0), mout_bpll_p),
|
||||
CLK_MUX("sclk_bpll_muxed", EXYNOS5410_SRC_TOP2, __BIT(24), mout_bpll_user_p),
|
||||
CLK_MUX("sclk_epll", EXYNOS5410_SRC_TOP2, __BIT(12), mout_epll_p),
|
||||
CLK_MUX("sclk_cpll", EXYNOS5410_SRC_TOP2, __BIT(8), mout_cpll_p),
|
||||
CLK_MUX("sclk_mpll_bpll", EXYNOS5410_SRC_TOP1, __BIT(20), mout_mpll_bpll_p),
|
||||
|
||||
CLK_MUX("mout_mmc0", EXYNOS5410_SRC_FSYS, __BITS(3,0), mout_group2_p),
|
||||
CLK_MUX("mout_mmc1", EXYNOS5410_SRC_FSYS, __BITS(7,4), mout_group2_p),
|
||||
CLK_MUX("mout_mmc2", EXYNOS5410_SRC_FSYS, __BITS(11,8), mout_group2_p),
|
||||
CLK_MUX("mout_usbd300", EXYNOS5410_SRC_FSYS, __BIT(28), mout_sclk_mpll_bpll_p),
|
||||
CLK_MUX("mout_usbd301", EXYNOS5410_SRC_FSYS, __BIT(29), mout_sclk_mpll_bpll_p),
|
||||
CLK_MUX("mout_uart0", EXYNOS5410_SRC_PERIC0, __BITS(3,0), mout_group2_p),
|
||||
CLK_MUX("mout_uart1", EXYNOS5410_SRC_PERIC0, __BITS(7,4), mout_group2_p),
|
||||
CLK_MUX("mout_uart2", EXYNOS5410_SRC_PERIC0, __BITS(11,8), mout_group2_p),
|
||||
CLK_MUX("mout_uart3", EXYNOS5410_SRC_PERIC0, __BITS(15,12), mout_group2_p),
|
||||
CLK_MUX("mout_pwm", EXYNOS5410_SRC_PERIC0, __BITS(27,24), mout_group2_p),
|
||||
CLK_MUX("mout_aclk200", EXYNOS5410_SRC_TOP0, __BIT(12), mout_mpll_bpll_p),
|
||||
CLK_MUX("mout_aclk400", EXYNOS5410_SRC_TOP0, __BIT(20), mout_mpll_bpll_p),
|
||||
|
||||
CLK_DIV("div_arm", "mout_cpu", EXYNOS5410_DIV_CPU0, __BITS(2,0)),
|
||||
CLK_DIV("div_arm2", "div_arm", EXYNOS5410_DIV_CPU0, __BITS(30,28)),
|
||||
|
||||
CLK_DIV("div_acp", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(10,8)),
|
||||
CLK_DIV("div_cpud", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(6,4)),
|
||||
CLK_DIV("div_atb", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(18,16)),
|
||||
CLK_DIV("pclk_dbg", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(22,20)),
|
||||
|
||||
CLK_DIV("div_kfc", "mout_kfc", EXYNOS5410_DIV_KFC0, __BITS(2,0)),
|
||||
CLK_DIV("div_aclk", "div_kfc", EXYNOS5410_DIV_KFC0, __BITS(6,4)),
|
||||
CLK_DIV("div_pclk", "div_kfc", EXYNOS5410_DIV_KFC0, __BITS(22,20)),
|
||||
|
||||
CLK_DIV("aclk66_pre", "sclk_mpll_muxed", EXYNOS5410_DIV_TOP1, __BITS(26,24)),
|
||||
CLK_DIV("aclk66", "aclk66_pre", EXYNOS5410_DIV_TOP0, __BITS(2,0)),
|
||||
|
||||
CLK_DIV("dout_usbphy300", "mout_usbd300", EXYNOS5410_DIV_FSYS0, __BITS(19,16)),
|
||||
CLK_DIV("dout_usbphy301", "mout_usbd301", EXYNOS5410_DIV_FSYS0, __BITS(23,20)),
|
||||
CLK_DIV("dout_usbd300", "mout_usbd300", EXYNOS5410_DIV_FSYS0, __BITS(27,24)),
|
||||
CLK_DIV("dout_usbd301", "mout_usbd301", EXYNOS5410_DIV_FSYS0, __BITS(31,28)),
|
||||
|
||||
CLK_DIV("dout_mmc0", "mout_mmc0", EXYNOS5410_DIV_FSYS1, __BITS(3,0)),
|
||||
CLK_DIV("dout_mmc1", "mout_mmc1", EXYNOS5410_DIV_FSYS1, __BITS(19,16)),
|
||||
CLK_DIV("dout_mmc2", "mout_mmc2", EXYNOS5410_DIV_FSYS2, __BITS(3,0)),
|
||||
|
||||
CLK_DIVF("dout_mmc_pre0", "dout_mmc0", EXYNOS5410_DIV_FSYS1, __BITS(15,8),
|
||||
CLK_SET_RATE_PARENT),
|
||||
CLK_DIVF("dout_mmc_pre1", "dout_mmc1", EXYNOS5410_DIV_FSYS1, __BITS(31,24),
|
||||
CLK_SET_RATE_PARENT),
|
||||
CLK_DIVF("dout_mmc_pre2", "dout_mmc2", EXYNOS5410_DIV_FSYS2, __BITS(15,8),
|
||||
CLK_SET_RATE_PARENT),
|
||||
|
||||
CLK_DIV("div_uart0", "mout_uart0", EXYNOS5410_DIV_PERIC0, __BITS(3,0)),
|
||||
CLK_DIV("div_uart1", "mout_uart1", EXYNOS5410_DIV_PERIC0, __BITS(7,4)),
|
||||
CLK_DIV("div_uart2", "mout_uart2", EXYNOS5410_DIV_PERIC0, __BITS(11,8)),
|
||||
CLK_DIV("div_uart3", "mout_uart3", EXYNOS5410_DIV_PERIC0, __BITS(15,12)),
|
||||
|
||||
CLK_DIV("dout_pwm", "mout_pwm", EXYNOS5410_DIV_PERIC3, __BITS(3,0)),
|
||||
|
||||
CLK_DIV("aclk200", "mout_aclk200", EXYNOS5410_DIV_TOP0, __BITS(14,12)),
|
||||
CLK_DIV("aclk266", "sclk_mpll_muxed", EXYNOS5410_DIV_TOP0, __BITS(18,16)),
|
||||
CLK_DIV("aclk400", "mout_aclk400", EXYNOS5410_DIV_TOP0, __BITS(26,24)),
|
||||
|
||||
CLK_GATE("sss", "aclk266", EXYNOS5410_GATE_IP_G2D, __BIT(2), 0),
|
||||
|
||||
CLK_GATE("mct", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(18), 0),
|
||||
CLK_GATE("wdt", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(19), 0),
|
||||
CLK_GATE("rtc", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(20), 0),
|
||||
CLK_GATE("tmu", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(21), 0),
|
||||
|
||||
CLK_GATE("sclk_mmc0", "dout_mmc_pre0", EXYNOS5410_SRC_MASK_FSYS,
|
||||
__BIT(0), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_mmc1", "dout_mmc_pre1", EXYNOS5410_SRC_MASK_FSYS,
|
||||
__BIT(4), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_mmc2", "dout_mmc_pre2", EXYNOS5410_SRC_MASK_FSYS,
|
||||
__BIT(8), CLK_SET_RATE_PARENT),
|
||||
|
||||
CLK_GATE("mmc0", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(12), 0),
|
||||
CLK_GATE("mmc1", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(13), 0),
|
||||
CLK_GATE("mmc2", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(14), 0),
|
||||
CLK_GATE("pdma1", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(2), 0),
|
||||
CLK_GATE("pdma0", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(1), 0),
|
||||
|
||||
CLK_GATE("sclk_usbphy301", "dout_usbphy301", EXYNOS5410_GATE_TOP_SCLK_FSYS,
|
||||
__BIT(7), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_usbphy300", "dout_usbphy300", EXYNOS5410_GATE_TOP_SCLK_FSYS,
|
||||
__BIT(8), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_usbd301", "dout_usbd301", EXYNOS5410_GATE_TOP_SCLK_FSYS,
|
||||
__BIT(9), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_usbd301", "dout_usbd301", EXYNOS5410_GATE_TOP_SCLK_FSYS,
|
||||
__BIT(10), CLK_SET_RATE_PARENT),
|
||||
|
||||
CLK_GATE("sclk_pwm", "dout_pwm", EXYNOS5410_GATE_TOP_SCLK_PERIC,
|
||||
__BIT(11), CLK_SET_RATE_PARENT),
|
||||
|
||||
CLK_GATE("uart0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(0), 0),
|
||||
CLK_GATE("uart1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(1), 0),
|
||||
CLK_GATE("uart2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(2), 0),
|
||||
CLK_GATE("uart3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(3), 0),
|
||||
CLK_GATE("i2c0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(6), 0),
|
||||
CLK_GATE("i2c1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(7), 0),
|
||||
CLK_GATE("i2c2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(8), 0),
|
||||
CLK_GATE("i2c3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(9), 0),
|
||||
CLK_GATE("usi0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(10), 0),
|
||||
CLK_GATE("usi1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(11), 0),
|
||||
CLK_GATE("usi2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(12), 0),
|
||||
CLK_GATE("usi3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(13), 0),
|
||||
CLK_GATE("pwm", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(24), 0),
|
||||
|
||||
CLK_GATE("sclk_uart0", "div_uart0", EXYNOS5410_SRC_MASK_PERIC0,
|
||||
__BIT(0), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_uart1", "div_uart1", EXYNOS5410_SRC_MASK_PERIC0,
|
||||
__BIT(4), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_uart2", "div_uart2", EXYNOS5410_SRC_MASK_PERIC0,
|
||||
__BIT(8), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_uart3", "div_uart3", EXYNOS5410_SRC_MASK_PERIC0,
|
||||
__BIT(12), CLK_SET_RATE_PARENT),
|
||||
|
||||
CLK_GATE("usbh20", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(18), 0),
|
||||
CLK_GATE("usbd301", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(19), 0),
|
||||
CLK_GATE("usbd300", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(20), 0),
|
||||
};
|
||||
|
||||
static int exynos5410_clock_match(device_t, cfdata_t, void *);
|
||||
static void exynos5410_clock_attach(device_t, device_t, void *);
|
||||
|
||||
struct exynos5410_clock_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
|
||||
struct clk_domain sc_clkdom;
|
||||
};
|
||||
|
||||
static void exynos5410_clock_print_header(void);
|
||||
static void exynos5410_clock_print(struct exynos5410_clock_softc *,
|
||||
struct exynos_clk *);
|
||||
|
||||
CFATTACH_DECL_NEW(exynos5410_clock, sizeof(struct exynos5410_clock_softc),
|
||||
exynos5410_clock_match, exynos5410_clock_attach, NULL, NULL);
|
||||
|
||||
#define CLOCK_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||
#define CLOCK_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||
|
||||
static int
|
||||
exynos5410_clock_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
const char * const compatible[] = { "samsung,exynos5410-clock", NULL };
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
exynos5410_clock_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct exynos5410_clock_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
int error;
|
||||
|
||||
if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
|
||||
error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
|
||||
if (error) {
|
||||
aprint_error(": couldn't map %#llx: %d",
|
||||
(uint64_t)addr, error);
|
||||
return;
|
||||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": Exynos5410 Clock Controller\n");
|
||||
|
||||
sc->sc_clkdom.funcs = &exynos5410_clock_funcs;
|
||||
sc->sc_clkdom.priv = sc;
|
||||
for (u_int n = 0; n < __arraycount(exynos5410_clocks); n++) {
|
||||
exynos5410_clocks[n].base.domain = &sc->sc_clkdom;
|
||||
}
|
||||
|
||||
fdtbus_register_clock_controller(self, faa->faa_phandle,
|
||||
&exynos5410_car_fdtclock_funcs);
|
||||
|
||||
exynos5410_clock_print_header();
|
||||
for (u_int n = 0; n < __arraycount(exynos5410_clocks); n++) {
|
||||
exynos5410_clock_print(sc, &exynos5410_clocks[n]);
|
||||
}
|
||||
}
|
||||
|
||||
static struct exynos_clk *
|
||||
exynos5410_clock_find(const char *name)
|
||||
{
|
||||
u_int n;
|
||||
|
||||
for (n = 0; n < __arraycount(exynos5410_clocks); n++) {
|
||||
if (strcmp(exynos5410_clocks[n].base.name, name) == 0) {
|
||||
return &exynos5410_clocks[n];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct exynos_clk *
|
||||
exynos5410_clock_find_by_id(u_int clock_id)
|
||||
{
|
||||
u_int n;
|
||||
|
||||
for (n = 0; n < __arraycount(exynos5410_clock_ids); n++) {
|
||||
if (exynos5410_clock_ids[n].id == clock_id) {
|
||||
const char *name = exynos5410_clock_ids[n].name;
|
||||
return exynos5410_clock_find(name);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
exynos5410_clock_print_header(void)
|
||||
{
|
||||
printf(" %-10s %2s %-10s %-5s %10s\n",
|
||||
"clock", "", "parent", "type", "rate");
|
||||
printf(" %-10s %2s %-10s %-5s %10s\n",
|
||||
"=====", "", "======", "====", "====");
|
||||
}
|
||||
|
||||
static void
|
||||
exynos5410_clock_print(struct exynos5410_clock_softc *sc,
|
||||
struct exynos_clk *eclk)
|
||||
{
|
||||
struct exynos_clk *eclk_parent;
|
||||
struct clk *clk_parent;
|
||||
const char *type = "?";
|
||||
|
||||
switch (eclk->type) {
|
||||
case EXYNOS_CLK_FIXED:
|
||||
type = "fixed";
|
||||
break;
|
||||
case EXYNOS_CLK_PLL:
|
||||
type = "pll";
|
||||
break;
|
||||
case EXYNOS_CLK_MUX:
|
||||
type = "mux";
|
||||
break;
|
||||
case EXYNOS_CLK_DIV:
|
||||
type = "div";
|
||||
break;
|
||||
case EXYNOS_CLK_GATE:
|
||||
type = "gate";
|
||||
break;
|
||||
}
|
||||
|
||||
clk_parent = exynos5410_clock_get_parent(sc, &eclk->base);
|
||||
eclk_parent = (struct exynos_clk *)clk_parent;
|
||||
|
||||
printf(" %-10s %2s %-10s %-5s %10d Hz\n",
|
||||
eclk->base.name,
|
||||
eclk_parent ? "<-" : "",
|
||||
eclk_parent ? eclk_parent->base.name : "",
|
||||
type, clk_get_rate(&eclk->base));
|
||||
}
|
||||
|
||||
static struct clk *
|
||||
exynos5410_clock_decode(device_t dev, const void *data, size_t len)
|
||||
{
|
||||
struct exynos_clk *eclk;
|
||||
|
||||
/* #clock-cells should be 1 */
|
||||
if (len != 4) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const u_int clock_id = be32dec(data);
|
||||
|
||||
eclk = exynos5410_clock_find_by_id(clock_id);
|
||||
if (eclk)
|
||||
return &eclk->base;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static u_int
|
||||
exynos5410_clock_get_rate_pll(struct exynos5410_clock_softc *sc,
|
||||
struct exynos_clk *eclk)
|
||||
{
|
||||
struct exynos_pll_clk *epll = &eclk->u.pll;
|
||||
struct exynos_clk *clk_parent;
|
||||
|
||||
KASSERT(eclk->type == EXYNOS_CLK_PLL);
|
||||
|
||||
clk_parent = exynos5410_clock_find(eclk->parent);
|
||||
KASSERT(clk_parent != NULL);
|
||||
const u_int rate_parent = exynos5410_clock_get_rate(sc,
|
||||
&clk_parent->base);
|
||||
|
||||
const uint32_t v = CLOCK_READ(sc, epll->con0_reg);
|
||||
|
||||
return PLL_FREQ(rate_parent, v);
|
||||
}
|
||||
|
||||
static int
|
||||
exynos5410_clock_set_rate_pll(struct exynos5410_clock_softc *sc,
|
||||
struct exynos_clk *eclk, u_int rate)
|
||||
{
|
||||
/* TODO */
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int
|
||||
exynos5410_clock_set_parent_mux(struct exynos5410_clock_softc *sc,
|
||||
struct exynos_clk *eclk, struct exynos_clk *eclk_parent)
|
||||
{
|
||||
struct exynos_mux_clk *emux = &eclk->u.mux;
|
||||
const char *pname = eclk_parent->base.name;
|
||||
u_int sel;
|
||||
|
||||
KASSERT(eclk->type == EXYNOS_CLK_MUX);
|
||||
|
||||
for (sel = 0; sel < emux->nparents; sel++) {
|
||||
if (strcmp(pname, emux->parents[sel]) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sel == emux->nparents) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
uint32_t v = CLOCK_READ(sc, emux->reg);
|
||||
v &= ~emux->bits;
|
||||
v |= __SHIFTIN(sel, emux->bits);
|
||||
CLOCK_WRITE(sc, emux->reg, v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct exynos_clk *
|
||||
exynos5410_clock_get_parent_mux(struct exynos5410_clock_softc *sc,
|
||||
struct exynos_clk *eclk)
|
||||
{
|
||||
struct exynos_mux_clk *emux = &eclk->u.mux;
|
||||
|
||||
KASSERT(eclk->type == EXYNOS_CLK_MUX);
|
||||
|
||||
const uint32_t v = CLOCK_READ(sc, emux->reg);
|
||||
const u_int sel = __SHIFTOUT(v, emux->bits);
|
||||
|
||||
KASSERT(sel < emux->nparents);
|
||||
|
||||
return exynos5410_clock_find(emux->parents[sel]);
|
||||
}
|
||||
|
||||
static u_int
|
||||
exynos5410_clock_get_rate_div(struct exynos5410_clock_softc *sc,
|
||||
struct exynos_clk *eclk)
|
||||
{
|
||||
struct exynos_div_clk *ediv = &eclk->u.div;
|
||||
struct clk *clk_parent;
|
||||
|
||||
KASSERT(eclk->type == EXYNOS_CLK_DIV);
|
||||
|
||||
clk_parent = exynos5410_clock_get_parent(sc, &eclk->base);
|
||||
const u_int parent_rate = exynos5410_clock_get_rate(sc, clk_parent);
|
||||
|
||||
const uint32_t v = CLOCK_READ(sc, ediv->reg);
|
||||
const u_int div = __SHIFTOUT(v, ediv->bits);
|
||||
|
||||
return parent_rate / (div + 1);
|
||||
}
|
||||
|
||||
static int
|
||||
exynos5410_clock_set_rate_div(struct exynos5410_clock_softc *sc,
|
||||
struct exynos_clk *eclk, u_int rate)
|
||||
{
|
||||
struct exynos_div_clk *ediv = &eclk->u.div;
|
||||
struct clk *clk_parent;
|
||||
int tmp_div, new_div = -1;
|
||||
u_int tmp_rate;
|
||||
|
||||
KASSERT(eclk->type == EXYNOS_CLK_DIV);
|
||||
|
||||
clk_parent = exynos5410_clock_get_parent(sc, &eclk->base);
|
||||
const u_int parent_rate = exynos5410_clock_get_rate(sc, clk_parent);
|
||||
|
||||
for (tmp_div = 0; tmp_div < popcount32(ediv->bits); tmp_div++) {
|
||||
tmp_rate = parent_rate / (tmp_div + 1);
|
||||
if (tmp_rate <= rate) {
|
||||
new_div = tmp_div;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (new_div == -1)
|
||||
return EINVAL;
|
||||
|
||||
uint32_t v = CLOCK_READ(sc, ediv->reg);
|
||||
v &= ~ediv->bits;
|
||||
v |= __SHIFTIN(new_div, ediv->bits);
|
||||
CLOCK_WRITE(sc, ediv->reg, v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
exynos5410_clock_enable_gate(struct exynos5410_clock_softc *sc,
|
||||
struct exynos_clk *eclk, bool enable)
|
||||
{
|
||||
struct exynos_gate_clk *egate = &eclk->u.gate;
|
||||
|
||||
KASSERT(eclk->type == EXYNOS_CLK_GATE);
|
||||
|
||||
uint32_t v = CLOCK_READ(sc, egate->reg);
|
||||
if (enable) {
|
||||
v |= egate->bits;
|
||||
} else {
|
||||
v &= ~egate->bits;
|
||||
}
|
||||
CLOCK_WRITE(sc, egate->reg, v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* clk api
|
||||
*/
|
||||
|
||||
static struct clk *
|
||||
exynos5410_clock_get(void *priv, const char *name)
|
||||
{
|
||||
struct exynos_clk *eclk;
|
||||
|
||||
eclk = exynos5410_clock_find(name);
|
||||
if (eclk == NULL)
|
||||
return NULL;
|
||||
|
||||
atomic_inc_uint(&eclk->refcnt);
|
||||
|
||||
return &eclk->base;
|
||||
}
|
||||
|
||||
static void
|
||||
exynos5410_clock_put(void *priv, struct clk *clk)
|
||||
{
|
||||
struct exynos_clk *eclk = (struct exynos_clk *)clk;
|
||||
|
||||
KASSERT(eclk->refcnt > 0);
|
||||
|
||||
atomic_dec_uint(&eclk->refcnt);
|
||||
}
|
||||
|
||||
static u_int
|
||||
exynos5410_clock_get_rate(void *priv, struct clk *clk)
|
||||
{
|
||||
struct exynos_clk *eclk = (struct exynos_clk *)clk;
|
||||
struct clk *clk_parent;
|
||||
|
||||
switch (eclk->type) {
|
||||
case EXYNOS_CLK_FIXED:
|
||||
return eclk->u.fixed.rate;
|
||||
case EXYNOS_CLK_PLL:
|
||||
return exynos5410_clock_get_rate_pll(priv, eclk);
|
||||
case EXYNOS_CLK_MUX:
|
||||
case EXYNOS_CLK_GATE:
|
||||
clk_parent = exynos5410_clock_get_parent(priv, clk);
|
||||
return exynos5410_clock_get_rate(priv, clk_parent);
|
||||
case EXYNOS_CLK_DIV:
|
||||
return exynos5410_clock_get_rate_div(priv, eclk);
|
||||
default:
|
||||
panic("exynos5410: unknown eclk type %d", eclk->type);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
exynos5410_clock_set_rate(void *priv, struct clk *clk, u_int rate)
|
||||
{
|
||||
struct exynos_clk *eclk = (struct exynos_clk *)clk;
|
||||
|
||||
KASSERT((clk->flags & CLK_SET_RATE_PARENT) == 0);
|
||||
|
||||
switch (eclk->type) {
|
||||
case EXYNOS_CLK_FIXED:
|
||||
return EIO;
|
||||
case EXYNOS_CLK_PLL:
|
||||
return exynos5410_clock_set_rate_pll(priv, eclk, rate);
|
||||
case EXYNOS_CLK_MUX:
|
||||
return EIO;
|
||||
case EXYNOS_CLK_DIV:
|
||||
return exynos5410_clock_set_rate_div(priv, eclk, rate);
|
||||
case EXYNOS_CLK_GATE:
|
||||
return EINVAL;
|
||||
default:
|
||||
panic("exynos5410: unknown eclk type %d", eclk->type);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
exynos5410_clock_enable(void *priv, struct clk *clk)
|
||||
{
|
||||
struct exynos_clk *eclk = (struct exynos_clk *)clk;
|
||||
|
||||
switch (eclk->type) {
|
||||
case EXYNOS_CLK_FIXED:
|
||||
return 0; /* always on */
|
||||
case EXYNOS_CLK_PLL:
|
||||
return 0; /* XXX */
|
||||
case EXYNOS_CLK_MUX:
|
||||
case EXYNOS_CLK_DIV:
|
||||
return 0;
|
||||
case EXYNOS_CLK_GATE:
|
||||
return exynos5410_clock_enable_gate(priv, eclk, true);
|
||||
default:
|
||||
panic("exynos5410: unknown eclk type %d", eclk->type);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
exynos5410_clock_disable(void *priv, struct clk *clk)
|
||||
{
|
||||
struct exynos_clk *eclk = (struct exynos_clk *)clk;
|
||||
|
||||
switch (eclk->type) {
|
||||
case EXYNOS_CLK_FIXED:
|
||||
return EINVAL; /* always on */
|
||||
case EXYNOS_CLK_PLL:
|
||||
return EINVAL; /* XXX */
|
||||
case EXYNOS_CLK_MUX:
|
||||
case EXYNOS_CLK_DIV:
|
||||
return EINVAL;
|
||||
case EXYNOS_CLK_GATE:
|
||||
return exynos5410_clock_enable_gate(priv, eclk, false);
|
||||
default:
|
||||
panic("exynos5410: unknown eclk type %d", eclk->type);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
exynos5410_clock_set_parent(void *priv, struct clk *clk, struct clk *clk_parent)
|
||||
{
|
||||
struct exynos_clk *eclk = (struct exynos_clk *)clk;
|
||||
struct exynos_clk *eclk_parent = (struct exynos_clk *)clk_parent;
|
||||
|
||||
switch (eclk->type) {
|
||||
case EXYNOS_CLK_FIXED:
|
||||
case EXYNOS_CLK_PLL:
|
||||
case EXYNOS_CLK_DIV:
|
||||
case EXYNOS_CLK_GATE:
|
||||
return EINVAL;
|
||||
case EXYNOS_CLK_MUX:
|
||||
return exynos5410_clock_set_parent_mux(priv, eclk, eclk_parent);
|
||||
default:
|
||||
panic("exynos5410: unknown eclk type %d", eclk->type);
|
||||
}
|
||||
}
|
||||
|
||||
static struct clk *
|
||||
exynos5410_clock_get_parent(void *priv, struct clk *clk)
|
||||
{
|
||||
struct exynos_clk *eclk = (struct exynos_clk *)clk;
|
||||
struct exynos_clk *eclk_parent = NULL;
|
||||
|
||||
switch (eclk->type) {
|
||||
case EXYNOS_CLK_FIXED:
|
||||
case EXYNOS_CLK_PLL:
|
||||
case EXYNOS_CLK_DIV:
|
||||
case EXYNOS_CLK_GATE:
|
||||
if (eclk->parent != NULL) {
|
||||
eclk_parent = exynos5410_clock_find(eclk->parent);
|
||||
}
|
||||
break;
|
||||
case EXYNOS_CLK_MUX:
|
||||
eclk_parent = exynos5410_clock_get_parent_mux(priv, eclk);
|
||||
break;
|
||||
default:
|
||||
panic("exynos5410: unknown eclk type %d", eclk->type);
|
||||
}
|
||||
|
||||
return (struct clk *)eclk_parent;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos5422_clock.c,v 1.5 2017/04/16 15:52:43 jmcneill Exp $ */
|
||||
/* $NetBSD: exynos5422_clock.c,v 1.5.4.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -29,7 +29,7 @@
|
|||
#include "locators.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos5422_clock.c,v 1.5 2017/04/16 15:52:43 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos5422_clock.c,v 1.5.4.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -277,13 +277,13 @@ static const struct clk_funcs exynos5422_clock_funcs = {
|
|||
.u = { .fixed = { .rate = (_rate) } } \
|
||||
}
|
||||
|
||||
#define CLK_PLL(_name, _parent, _base) { \
|
||||
#define CLK_PLL(_name, _parent, _lock, _con0) { \
|
||||
.base = { .name = (_name) }, .type = EXYNOS_CLK_PLL, \
|
||||
.parent = (_parent), \
|
||||
.u = { \
|
||||
.pll = { \
|
||||
.con0_reg = (_base) + PLL_CON0_OFFSET, \
|
||||
.lock_reg = (_base) + PLL_LOCK_OFFSET, \
|
||||
.lock_reg = (_lock), \
|
||||
.con0_reg = (_con0), \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
@ -331,17 +331,32 @@ static const struct clk_funcs exynos5422_clock_funcs = {
|
|||
} \
|
||||
}
|
||||
|
||||
#define EXYNOS5422_APLL_BASE 0x00000
|
||||
#define EXYNOS5422_CPLL_BASE 0x10020
|
||||
#define EXYNOS5422_DPLL_BASE 0x10030
|
||||
#define EXYNOS5422_EPLL_BASE 0x10040
|
||||
#define EXYNOS5422_RPLL_BASE 0x10050
|
||||
#define EXYNOS5422_IPLL_BASE 0x10060
|
||||
#define EXYNOS5422_SPLL_BASE 0x10070
|
||||
#define EXYNOS5422_VPLL_BASE 0x10080
|
||||
#define EXYNOS5422_MPLL_BASE 0x10090
|
||||
#define EXYNOS5422_BPLL_BASE 0x20010
|
||||
#define EXYNOS5422_KPLL_BASE 0x28000
|
||||
#define EXYNOS5422_APLL_LOCK 0x00000
|
||||
#define EXYNOS5422_APLL_CON0 0x00100
|
||||
#define EXYNOS5422_CPLL_LOCK 0x10020
|
||||
#define EXYNOS5422_DPLL_LOCK 0x10030
|
||||
#define EXYNOS5422_EPLL_LOCK 0x10040
|
||||
#define EXYNOS5422_RPLL_LOCK 0x10050
|
||||
#define EXYNOS5422_IPLL_LOCK 0x10060
|
||||
#define EXYNOS5422_SPLL_LOCK 0x10070
|
||||
#define EXYNOS5422_VPLL_LOCK 0x10080
|
||||
#define EXYNOS5422_MPLL_LOCK 0x10090
|
||||
#define EXYNOS5422_CPLL_CON0 0x10120
|
||||
#define EXYNOS5422_DPLL_CON0 0x10128
|
||||
#define EXYNOS5422_EPLL_CON0 0x10130
|
||||
#define EXYNOS5422_EPLL_CON1 0x10134
|
||||
#define EXYNOS5422_EPLL_CON2 0x10138
|
||||
#define EXYNOS5422_RPLL_CON0 0x10140
|
||||
#define EXYNOS5422_RPLL_CON1 0x10144
|
||||
#define EXYNOS5422_RPLL_CON2 0x10148
|
||||
#define EXYNOS5422_IPLL_CON0 0x10150
|
||||
#define EXYNOS5422_SPLL_CON0 0x10160
|
||||
#define EXYNOS5422_VPLL_CON0 0x10170
|
||||
#define EXYNOS5422_MPLL_CON0 0x10180
|
||||
#define EXYNOS5422_BPLL_LOCK 0x20010
|
||||
#define EXYNOS5422_BPLL_CON0 0x20110
|
||||
#define EXYNOS5422_KPLL_LOCK 0x28000
|
||||
#define EXYNOS5422_KPLL_CON0 0x28100
|
||||
|
||||
#define EXYNOS5422_SRC_CPU 0x00200
|
||||
#define EXYNOS5422_SRC_TOP0 0x10200
|
||||
|
@ -363,8 +378,10 @@ static const struct clk_funcs exynos5422_clock_funcs = {
|
|||
#define EXYNOS5422_SRC_TOP12 0x10280
|
||||
|
||||
#define EXYNOS5422_DIV_FSYS1 0x1054c
|
||||
#define EXYNOS5422_DIV_PERIC0 0x10558
|
||||
|
||||
#define EXYNOS5422_GATE_TOP_SCLK_FSYS 0x10840
|
||||
#define EXYNOS5422_GATE_TOP_SCLK_PERIC 0x10850
|
||||
|
||||
static const char *mout_cpll_p[] = { "fin_pll", "fout_cpll" };
|
||||
static const char *mout_dpll_p[] = { "fin_pll", "fout_dpll" };
|
||||
|
@ -380,17 +397,28 @@ static const char *mout_group2_p[] =
|
|||
static struct exynos_clk exynos5422_clocks[] = {
|
||||
CLK_FIXED("fin_pll", EXYNOS_F_IN_FREQ),
|
||||
|
||||
CLK_PLL("fout_apll", "fin_pll", EXYNOS5422_APLL_BASE),
|
||||
CLK_PLL("fout_cpll", "fin_pll", EXYNOS5422_CPLL_BASE),
|
||||
CLK_PLL("fout_dpll", "fin_pll", EXYNOS5422_DPLL_BASE),
|
||||
CLK_PLL("fout_epll", "fin_pll", EXYNOS5422_EPLL_BASE),
|
||||
CLK_PLL("fout_rpll", "fin_pll", EXYNOS5422_RPLL_BASE),
|
||||
CLK_PLL("fout_ipll", "fin_pll", EXYNOS5422_IPLL_BASE),
|
||||
CLK_PLL("fout_spll", "fin_pll", EXYNOS5422_SPLL_BASE),
|
||||
CLK_PLL("fout_vpll", "fin_pll", EXYNOS5422_VPLL_BASE),
|
||||
CLK_PLL("fout_mpll", "fin_pll", EXYNOS5422_MPLL_BASE),
|
||||
CLK_PLL("fout_bpll", "fin_pll", EXYNOS5422_BPLL_BASE),
|
||||
CLK_PLL("fout_kpll", "fin_pll", EXYNOS5422_KPLL_BASE),
|
||||
CLK_PLL("fout_apll", "fin_pll", EXYNOS5422_APLL_LOCK,
|
||||
EXYNOS5422_APLL_CON0),
|
||||
CLK_PLL("fout_cpll", "fin_pll", EXYNOS5422_CPLL_LOCK,
|
||||
EXYNOS5422_CPLL_CON0),
|
||||
CLK_PLL("fout_dpll", "fin_pll", EXYNOS5422_DPLL_LOCK,
|
||||
EXYNOS5422_DPLL_CON0),
|
||||
CLK_PLL("fout_epll", "fin_pll", EXYNOS5422_EPLL_LOCK,
|
||||
EXYNOS5422_EPLL_CON0),
|
||||
CLK_PLL("fout_rpll", "fin_pll", EXYNOS5422_RPLL_LOCK,
|
||||
EXYNOS5422_RPLL_CON0),
|
||||
CLK_PLL("fout_ipll", "fin_pll", EXYNOS5422_IPLL_LOCK,
|
||||
EXYNOS5422_IPLL_CON0),
|
||||
CLK_PLL("fout_spll", "fin_pll", EXYNOS5422_SPLL_LOCK,
|
||||
EXYNOS5422_SPLL_CON0),
|
||||
CLK_PLL("fout_vpll", "fin_pll", EXYNOS5422_VPLL_LOCK,
|
||||
EXYNOS5422_VPLL_CON0),
|
||||
CLK_PLL("fout_mpll", "fin_pll", EXYNOS5422_MPLL_LOCK,
|
||||
EXYNOS5422_MPLL_CON0),
|
||||
CLK_PLL("fout_bpll", "fin_pll", EXYNOS5422_BPLL_LOCK,
|
||||
EXYNOS5422_BPLL_CON0),
|
||||
CLK_PLL("fout_kpll", "fin_pll", EXYNOS5422_KPLL_LOCK,
|
||||
EXYNOS5422_KPLL_CON0),
|
||||
|
||||
CLK_MUXA("sclk_cpll", "mout_cpll", EXYNOS5422_SRC_TOP6, __BIT(28),
|
||||
mout_cpll_p),
|
||||
|
@ -413,10 +441,26 @@ static struct exynos_clk exynos5422_clocks[] = {
|
|||
mout_group2_p),
|
||||
CLK_MUX("mout_mmc2", EXYNOS5422_SRC_FSYS, __BITS(18,16),
|
||||
mout_group2_p),
|
||||
CLK_MUX("mout_uart0", EXYNOS5422_SRC_PERIC0, __BITS(6,4),
|
||||
mout_group2_p),
|
||||
CLK_MUX("mout_uart1", EXYNOS5422_SRC_PERIC0, __BITS(10,8),
|
||||
mout_group2_p),
|
||||
CLK_MUX("mout_uart2", EXYNOS5422_SRC_PERIC0, __BITS(14,12),
|
||||
mout_group2_p),
|
||||
CLK_MUX("mout_uart3", EXYNOS5422_SRC_PERIC0, __BITS(18,16),
|
||||
mout_group2_p),
|
||||
|
||||
CLK_DIV("dout_mmc0", "mout_mmc0", EXYNOS5422_DIV_FSYS1, __BITS(9,0)),
|
||||
CLK_DIV("dout_mmc1", "mout_mmc1", EXYNOS5422_DIV_FSYS1, __BITS(19,10)),
|
||||
CLK_DIV("dout_mmc2", "mout_mmc2", EXYNOS5422_DIV_FSYS1, __BITS(29,20)),
|
||||
CLK_DIV("dout_uart0", "mout_uart0", EXYNOS5422_DIV_PERIC0,
|
||||
__BITS(11,8)),
|
||||
CLK_DIV("dout_uart1", "mout_uart1", EXYNOS5422_DIV_PERIC0,
|
||||
__BITS(15,12)),
|
||||
CLK_DIV("dout_uart2", "mout_uart2", EXYNOS5422_DIV_PERIC0,
|
||||
__BITS(19,16)),
|
||||
CLK_DIV("dout_uart3", "mout_uart3", EXYNOS5422_DIV_PERIC0,
|
||||
__BITS(23,20)),
|
||||
|
||||
CLK_GATE("sclk_mmc0", "dout_mmc0", EXYNOS5422_GATE_TOP_SCLK_FSYS,
|
||||
__BIT(0), CLK_SET_RATE_PARENT),
|
||||
|
@ -424,6 +468,14 @@ static struct exynos_clk exynos5422_clocks[] = {
|
|||
__BIT(1), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_mmc2", "dout_mmc2", EXYNOS5422_GATE_TOP_SCLK_FSYS,
|
||||
__BIT(2), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_uart0", "dout_uart0", EXYNOS5422_GATE_TOP_SCLK_PERIC,
|
||||
__BIT(0), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_uart1", "dout_uart1", EXYNOS5422_GATE_TOP_SCLK_PERIC,
|
||||
__BIT(1), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_uart2", "dout_uart2", EXYNOS5422_GATE_TOP_SCLK_PERIC,
|
||||
__BIT(2), CLK_SET_RATE_PARENT),
|
||||
CLK_GATE("sclk_uart3", "dout_uart3", EXYNOS5422_GATE_TOP_SCLK_PERIC,
|
||||
__BIT(3), CLK_SET_RATE_PARENT),
|
||||
};
|
||||
|
||||
static int exynos5422_clock_match(device_t, cfdata_t, void *);
|
||||
|
@ -886,5 +938,5 @@ exynos5422_clock_get_parent(void *priv, struct clk *clk)
|
|||
panic("exynos5422: unknown eclk type %d", eclk->type);
|
||||
}
|
||||
|
||||
return &eclk_parent->base;
|
||||
return (struct clk *)eclk_parent;
|
||||
}
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
/* $NetBSD: exynos5422_dma.c,v 1.1 2015/12/11 04:05:54 marty Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Nick Hudson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this 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 "opt_exynos.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos5422_dma.c,v 1.1 2015/12/11 04:05:54 marty Exp $");
|
||||
|
||||
#define _ARM32_BUS_DMA_PRIVATE
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <arm/samsung/exynos_reg.h>
|
||||
#include <arm/samsung/exynos_var.h>
|
||||
|
||||
struct arm32_bus_dma_tag exynos_bus_dma_tag = {
|
||||
_BUS_DMAMAP_FUNCS,
|
||||
_BUS_DMAMEM_FUNCS,
|
||||
_BUS_DMATAG_FUNCS,
|
||||
};
|
||||
|
||||
struct arm32_dma_range exynos_coherent_dma_ranges[1] = {
|
||||
[0] = {
|
||||
.dr_sysbase = 0, /* filled in */
|
||||
.dr_busbase = 0, /* filled in */
|
||||
.dr_flags = _BUS_DMAMAP_COHERENT,
|
||||
},
|
||||
};
|
||||
|
||||
struct arm32_bus_dma_tag exynos_coherent_bus_dma_tag = {
|
||||
._ranges = exynos_coherent_dma_ranges,
|
||||
._nranges = __arraycount(exynos_coherent_dma_ranges),
|
||||
_BUS_DMAMAP_FUNCS,
|
||||
_BUS_DMAMEM_FUNCS,
|
||||
_BUS_DMATAG_FUNCS,
|
||||
};
|
||||
|
||||
void
|
||||
exynos_dma_bootstrap(psize_t memsize)
|
||||
{
|
||||
bus_addr_t dram_base = EXYNOS5_SDRAM_PBASE;
|
||||
|
||||
KASSERT(dram_base);
|
||||
exynos_coherent_dma_ranges[0].dr_sysbase = dram_base;
|
||||
exynos_coherent_dma_ranges[0].dr_busbase = dram_base;
|
||||
exynos_coherent_dma_ranges[0].dr_len = memsize;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_combiner.c,v 1.6 2016/01/05 21:53:48 marty Exp $ */
|
||||
/* $NetBSD: exynos_combiner.c,v 1.6.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 The NetBSD Foundation, Inc.
|
||||
|
@ -34,7 +34,7 @@
|
|||
#include "gpio.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_combiner.c,v 1.6 2016/01/05 21:53:48 marty Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_combiner.c,v 1.6.10.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -66,6 +66,7 @@ struct exynos_combiner_irq_entry {
|
|||
int (*irq_handler)(void *);
|
||||
void * irq_arg;
|
||||
struct exynos_combiner_irq_entry *irq_next;
|
||||
bool irq_mpsafe;
|
||||
};
|
||||
|
||||
struct exynos_combiner_irq_block {
|
||||
|
@ -73,6 +74,7 @@ struct exynos_combiner_irq_block {
|
|||
struct exynos_combiner_softc *irq_sc;
|
||||
struct exynos_combiner_irq_entry *irq_entries;
|
||||
struct exynos_combiner_irq_block *irq_block_next;
|
||||
void *irq_ih;
|
||||
};
|
||||
|
||||
struct exynos_combiner_softc {
|
||||
|
@ -173,7 +175,7 @@ exynos_combiner_get_block(struct exynos_combiner_softc *sc, int block)
|
|||
|
||||
static struct exynos_combiner_irq_entry *
|
||||
exynos_combiner_new_irq(struct exynos_combiner_irq_block *block,
|
||||
int irq, int (*func)(void *), void *arg)
|
||||
int irq, bool mpsafe, int (*func)(void *), void *arg)
|
||||
{
|
||||
struct exynos_combiner_irq_entry * n = kmem_zalloc(sizeof(*n),
|
||||
KM_SLEEP);
|
||||
|
@ -181,6 +183,7 @@ exynos_combiner_new_irq(struct exynos_combiner_irq_block *block,
|
|||
n->irq_handler = func;
|
||||
n->irq_next = block->irq_entries;
|
||||
n->irq_arg = arg;
|
||||
n->irq_mpsafe = mpsafe;
|
||||
block->irq_entries = n;
|
||||
return n;
|
||||
}
|
||||
|
@ -196,7 +199,8 @@ exynos_combiner_get_irq(struct exynos_combiner_irq_block *b, int irq)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int exynos_combiner_irq(void *cookie)
|
||||
static int
|
||||
exynos_combiner_irq(void *cookie)
|
||||
{
|
||||
struct exynos_combiner_irq_block *blockp = cookie;
|
||||
struct exynos_combiner_softc *sc = blockp->irq_sc;
|
||||
|
@ -211,9 +215,13 @@ static int exynos_combiner_irq(void *cookie)
|
|||
if (istatus & 1 << irq) {
|
||||
struct exynos_combiner_irq_entry *e =
|
||||
exynos_combiner_get_irq(blockp, irq);
|
||||
if (e)
|
||||
if (e) {
|
||||
if (!e->irq_mpsafe)
|
||||
KERNEL_LOCK(1, curlwp);
|
||||
e->irq_handler(e->irq_arg);
|
||||
else
|
||||
if (!e->irq_mpsafe)
|
||||
KERNEL_UNLOCK_ONE(curlwp);
|
||||
} else
|
||||
printf("%s: Unexpected irq %d, %d\n", __func__,
|
||||
intr, irq);
|
||||
}
|
||||
|
@ -229,6 +237,7 @@ exynos_combiner_establish(device_t dev, u_int *specifier,
|
|||
struct exynos_combiner_softc * const sc = device_private(dev);
|
||||
struct exynos_combiner_irq_block *blockp;
|
||||
struct exynos_combiner_irq_entry *entryp;
|
||||
const bool mpsafe = (flags & FDT_INTR_MPSAFE) != 0;
|
||||
|
||||
const u_int intr = be32toh(specifier[0]);
|
||||
const u_int irq = be32toh(specifier[1]);
|
||||
|
@ -237,18 +246,19 @@ exynos_combiner_establish(device_t dev, u_int *specifier,
|
|||
intr / COMBINER_BLOCKS_PER_GROUP * COMBINER_GROUP_SIZE
|
||||
+ COMBINER_IESR_OFFSET;
|
||||
|
||||
blockp = exynos_combiner_get_block(sc, intr);
|
||||
blockp = exynos_combiner_get_block(sc, intr);
|
||||
if (!blockp) {
|
||||
blockp = exynos_combiner_new_block(sc, intr);
|
||||
KASSERT(blockp);
|
||||
intr_establish(intr, ipl, IST_LEVEL, exynos_combiner_irq,
|
||||
blockp);
|
||||
blockp->irq_ih = fdtbus_intr_establish(sc->sc_phandle, intr,
|
||||
IPL_VM /* XXX */, FDT_INTR_MPSAFE, exynos_combiner_irq,
|
||||
blockp);
|
||||
}
|
||||
|
||||
entryp = exynos_combiner_get_irq(blockp, irq);
|
||||
if (entryp)
|
||||
return NULL;
|
||||
entryp = exynos_combiner_new_irq(blockp, irq, func, arg);
|
||||
entryp = exynos_combiner_new_irq(blockp, irq, mpsafe, func, arg);
|
||||
KASSERT(entryp);
|
||||
|
||||
int istatus =
|
||||
|
@ -262,7 +272,7 @@ static void
|
|||
exynos_combiner_disestablish(device_t dev, void *ih)
|
||||
{
|
||||
/* MJF: Find the ih and disable the handler. */
|
||||
intr_disestablish(ih);
|
||||
panic("exynos_combiner_disestablish not implemented");
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_dwcmmc.c,v 1.3 2016/05/30 16:38:35 dholland Exp $ */
|
||||
/* $NetBSD: exynos_dwcmmc.c,v 1.3.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_dwcmmc.c,v 1.3 2016/05/30 16:38:35 dholland Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_dwcmmc.c,v 1.3.10.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -43,11 +43,18 @@ __KERNEL_RCSID(0, "$NetBSD: exynos_dwcmmc.c,v 1.3 2016/05/30 16:38:35 dholland E
|
|||
#include <dev/ic/dwc_mmc_var.h>
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#define FIFO_REG 0x200
|
||||
#define MPS_BEGIN 0x200
|
||||
#define MPS_END 0x204
|
||||
#define MPS_CTRL 0x20c
|
||||
#define MPS_CTRL_SECURE_WRITE __BIT(6)
|
||||
#define MPS_CTRL_NON_SECURE_READ __BIT(5)
|
||||
#define MPS_CTRL_NON_SECURE_WRITE __BIT(4)
|
||||
#define MPS_CTRL_VALID __BIT(0)
|
||||
|
||||
static int exynos_dwcmmc_match(device_t, cfdata_t, void *);
|
||||
static void exynos_dwcmmc_attach(device_t, device_t, void *);
|
||||
|
||||
static void exynos_dwcmmc_attach_i(device_t);
|
||||
|
||||
static int exynos_dwcmmc_card_detect(struct dwc_mmc_softc *);
|
||||
|
||||
struct exynos_dwcmmc_softc {
|
||||
|
@ -137,12 +144,13 @@ exynos_dwcmmc_attach(device_t parent, device_t self, void *aux)
|
|||
|
||||
sc->sc_clock_freq = clk_get_rate(esc->sc_clk_ciu) / (ciu_div + 1);
|
||||
sc->sc_fifo_depth = fifo_depth;
|
||||
sc->sc_fifo_reg = FIFO_REG;
|
||||
sc->sc_flags = DWC_MMC_F_USE_HOLD_REG | DWC_MMC_F_DMA;
|
||||
|
||||
esc->sc_pin_cd = fdtbus_gpio_acquire(phandle, "cd-gpios",
|
||||
GPIO_PIN_INPUT);
|
||||
if (esc->sc_pin_cd) {
|
||||
if (esc->sc_pin_cd)
|
||||
sc->sc_card_detect = exynos_dwcmmc_card_detect;
|
||||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": MHS (%u Hz)\n", sc->sc_clock_freq);
|
||||
|
@ -152,6 +160,9 @@ exynos_dwcmmc_attach(device_t parent, device_t self, void *aux)
|
|||
return;
|
||||
}
|
||||
|
||||
if (dwc_mmc_init(sc) != 0)
|
||||
return;
|
||||
|
||||
sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_BIO, 0,
|
||||
dwc_mmc_intr, sc);
|
||||
if (sc->sc_ih == NULL) {
|
||||
|
@ -161,16 +172,15 @@ exynos_dwcmmc_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
|
||||
config_interrupts(self, exynos_dwcmmc_attach_i);
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_dwcmmc_attach_i(device_t self)
|
||||
{
|
||||
struct exynos_dwcmmc_softc *esc = device_private(self);
|
||||
struct dwc_mmc_softc *sc = &esc->sc;
|
||||
|
||||
dwc_mmc_init(sc);
|
||||
/* Disable encryption mode */
|
||||
const char * compat_enc[] = { "samsung,exynos5420-dw-mshc-smu", NULL };
|
||||
if (of_match_compatible(phandle, compat_enc)) {
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, MPS_BEGIN, 0);
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, MPS_END, ~0U);
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, MPS_CTRL,
|
||||
MPS_CTRL_NON_SECURE_READ | MPS_CTRL_NON_SECURE_WRITE |
|
||||
MPS_CTRL_SECURE_WRITE | MPS_CTRL_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_i2c.c,v 1.11 2016/02/14 19:54:20 chs Exp $ */
|
||||
/* $NetBSD: exynos_i2c.c,v 1.11.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -31,7 +31,7 @@
|
|||
#include "opt_arm_debug.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_i2c.c,v 1.11 2016/02/14 19:54:20 chs Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_i2c.c,v 1.11.10.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -138,7 +138,8 @@ exynos_i2c_attach(device_t parent, device_t self, void *aux)
|
|||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
struct i2cbus_attach_args iba;
|
||||
|
||||
prop_dictionary_t devs;
|
||||
uint32_t address_cells;
|
||||
char intrstr[128];
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
|
@ -176,8 +177,6 @@ exynos_i2c_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
|
||||
fdtbus_pinctrl_set_config_index(phandle, 0);
|
||||
|
||||
sc->sc_ic.ic_cookie = sc;
|
||||
sc->sc_ic.ic_acquire_bus = exynos_i2c_acquire_bus;
|
||||
sc->sc_ic.ic_release_bus = exynos_i2c_release_bus;
|
||||
|
@ -187,7 +186,22 @@ exynos_i2c_attach(device_t parent, device_t self, void *aux)
|
|||
sc->sc_ic.ic_read_byte = exynos_i2c_read_byte;
|
||||
sc->sc_ic.ic_write_byte = exynos_i2c_write_byte;
|
||||
|
||||
fdtbus_register_i2c_controller(self, phandle, &exynos_i2c_funcs);
|
||||
|
||||
devs = prop_dictionary_create();
|
||||
if (of_getprop_uint32(phandle, "#address-cells", &address_cells))
|
||||
address_cells = 1;
|
||||
of_enter_i2c_devs(devs, phandle, address_cells * 4, 0);
|
||||
|
||||
memset(&iba, 0, sizeof(iba));
|
||||
iba.iba_tag = &sc->sc_ic;
|
||||
iba.iba_child_devices = prop_dictionary_get(devs, "i2c-child-devices");
|
||||
if (iba.iba_child_devices != NULL)
|
||||
prop_object_retain(iba.iba_child_devices);
|
||||
else
|
||||
iba.iba_child_devices = prop_array_create();
|
||||
prop_object_release(devs);
|
||||
|
||||
sc->sc_i2cdev = config_found_ia(self, "i2cbus", &iba, iicbus_print);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_intr.h,v 1.2 2014/09/05 08:01:05 skrll Exp $ */
|
||||
/* $NetBSD: exynos_intr.h,v 1.2.12.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
|
@ -32,18 +32,6 @@
|
|||
#ifndef _ARM_SAMSUNG_EXYNOS_INTR_H_
|
||||
#define _ARM_SAMSUNG_EXYNOS_INTR_H_
|
||||
|
||||
#define PIC_MAXSOURCES GIC_MAXSOURCES(224)
|
||||
#define PIC_MAXMAXSOURCES (PIC_MAXSOURCES + 32) /* XXX */
|
||||
|
||||
/*
|
||||
* The Exynos uses a generic interrupt controller
|
||||
*/
|
||||
#include <arm/cortex/gic_intr.h>
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_exynos.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The GIC supports
|
||||
* - 16 Software Generated Interrupts (SGIs)
|
||||
|
@ -61,9 +49,5 @@
|
|||
|
||||
#define IRQ_MCT_LTIMER IRQ_PPI(12)
|
||||
|
||||
#ifdef EXYNOS5
|
||||
#include <arm/cortex/gtmr_intr.h>
|
||||
#endif
|
||||
|
||||
#endif /* _ARM_SAMSUNG_EXYNOS_INTR_H_ */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_pinctrl.c,v 1.9 2016/01/01 22:37:07 marty Exp $ */
|
||||
/* $NetBSD: exynos_pinctrl.c,v 1.9.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 The NetBSD Foundation, Inc.
|
||||
|
@ -34,7 +34,7 @@
|
|||
#include "gpio.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.9 2016/01/01 22:37:07 marty Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.9.10.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -55,16 +55,15 @@ __KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.9 2016/01/01 22:37:07 marty Exp
|
|||
|
||||
struct exynos_pinctrl_config {
|
||||
int pc_phandle;
|
||||
struct exynos_gpio_pin_cfg *pc_pincfg;
|
||||
struct exynos_gpio_pin_cfg pc_pincfg;
|
||||
struct exynos_pinctrl_softc *pc_sc;
|
||||
};
|
||||
|
||||
static int exynos_pinctrl_match(device_t, cfdata_t, void *);
|
||||
static void exynos_pinctrl_attach(device_t, device_t, void *);
|
||||
|
||||
static int exynos_pinctrl_set_cfg(void *);
|
||||
static struct exynos_gpio_pin_cfg *
|
||||
exynos_parse_config(struct exynos_pinctrl_config *pc);
|
||||
static int exynos_pinctrl_set_cfg(device_t, const void *, size_t);
|
||||
static void exynos_parse_config(int, struct exynos_gpio_pin_cfg *);
|
||||
|
||||
static struct fdtbus_pinctrl_controller_func exynos_pinctrl_controller_func = {
|
||||
.set_config = exynos_pinctrl_set_cfg
|
||||
|
@ -126,90 +125,61 @@ exynos_pinctrl_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
|
||||
if (is_pinctrl(child)) {
|
||||
struct exynos_pinctrl_config *pc;
|
||||
pc = kmem_alloc(sizeof(*pc), KM_SLEEP);
|
||||
pc->pc_phandle = child;
|
||||
pc->pc_sc = sc;
|
||||
pc->pc_pincfg = exynos_parse_config(pc);
|
||||
fdtbus_register_pinctrl_config(pc, child,
|
||||
fdtbus_register_pinctrl_config(self, child,
|
||||
&exynos_pinctrl_controller_func);
|
||||
}
|
||||
}
|
||||
|
||||
fdtbus_pinctrl_configure();
|
||||
}
|
||||
|
||||
static struct exynos_gpio_pin_cfg *
|
||||
exynos_parse_config(struct exynos_pinctrl_config *pc)
|
||||
static void
|
||||
exynos_parse_config(int phandle, struct exynos_gpio_pin_cfg *gc)
|
||||
{
|
||||
struct exynos_gpio_pin_cfg *gc = kmem_zalloc(sizeof(*gc), KM_SLEEP);
|
||||
int len;
|
||||
int value;
|
||||
|
||||
len = OF_getprop(pc->pc_phandle, "samsung,pin-function",
|
||||
&value, sizeof(value));
|
||||
if (len > 0) {
|
||||
gc->cfg = be32toh(value);
|
||||
}
|
||||
|
||||
len = OF_getprop(pc->pc_phandle, "samsung,pin-pud", &value,
|
||||
sizeof(&value));
|
||||
if (len > 0) {
|
||||
gc->pud = be32toh(value);
|
||||
}
|
||||
|
||||
len = OF_getprop(pc->pc_phandle, "samsung,pin-drv", &value,
|
||||
sizeof(&value));
|
||||
if (len > 0) {
|
||||
gc->drv = be32toh(value);
|
||||
}
|
||||
|
||||
len = OF_getprop(pc->pc_phandle, "samsung,pin-conpwd", &value,
|
||||
sizeof(&value));
|
||||
if (len > 0) {
|
||||
gc->conpwd = be32toh(value);
|
||||
}
|
||||
|
||||
len = OF_getprop(pc->pc_phandle, "samsung,pin-pudpwd", &value,
|
||||
sizeof(&value));
|
||||
if (len > 0) {
|
||||
gc->pudpwd = be32toh(value);
|
||||
}
|
||||
return gc;
|
||||
of_getprop_uint32(phandle, "samsung,pin-function", &gc->cfg);
|
||||
of_getprop_uint32(phandle, "samsung,pin-pud", &gc->pud);
|
||||
of_getprop_uint32(phandle, "samsung,pin-drv", &gc->drv);
|
||||
of_getprop_uint32(phandle, "samsung,pin-conpwd", &gc->conpwd);
|
||||
of_getprop_uint32(phandle, "samsung,pin-pudpwd", &gc->pudpwd);
|
||||
}
|
||||
|
||||
static int
|
||||
exynos_do_config(struct exynos_pinctrl_config *pc)
|
||||
{
|
||||
struct exynos_gpio_pin_cfg *gc = pc->pc_pincfg;
|
||||
struct exynos_gpio_pin_cfg *gc = &pc->pc_pincfg;
|
||||
struct exynos_gpio_bank *bank;
|
||||
int len;
|
||||
char result[20];
|
||||
const char *pins;
|
||||
|
||||
if (gc == NULL) {
|
||||
printf("%s: No configuration available\n", __func__);
|
||||
int pins_len = OF_getproplen(pc->pc_phandle, "samsung,pins");
|
||||
if (pins_len <= 0)
|
||||
return -1;
|
||||
|
||||
for (pins = fdtbus_get_string(pc->pc_phandle, "samsung,pins");
|
||||
pins_len > 0;
|
||||
pins_len -= strlen(pins) + 1, pins += strlen(pins) + 1) {
|
||||
bank = exynos_gpio_bank_lookup(pins);
|
||||
if (bank == NULL) {
|
||||
aprint_error_dev(pc->pc_sc->sc_dev,
|
||||
"unknown pin name '%s'\n", pins);
|
||||
continue;
|
||||
}
|
||||
exynos_gpio_pin_ctl_write(bank, gc);
|
||||
}
|
||||
|
||||
len = OF_getprop(pc->pc_phandle, "samsung,pins", result,
|
||||
sizeof(result));
|
||||
if (len <= 0) {
|
||||
printf("%s: couldn't get pins. (%d)\n", __func__,
|
||||
pc->pc_phandle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bank = exynos_gpio_bank_lookup(&result[0]);
|
||||
if (!bank) {
|
||||
printf("%s: Couldn't get bank \"%s\".\n", __func__, result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
exynos_gpio_pin_ctl_write(bank, gc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
exynos_pinctrl_set_cfg(void *cookie)
|
||||
exynos_pinctrl_set_cfg(device_t dev, const void *data, size_t len)
|
||||
{
|
||||
struct exynos_pinctrl_config *pc = cookie;
|
||||
return exynos_do_config(pc);
|
||||
struct exynos_pinctrl_config pc;
|
||||
|
||||
if (len != 4)
|
||||
return -1;
|
||||
|
||||
pc.pc_phandle = fdtbus_get_phandle_from_native(be32dec(data));
|
||||
pc.pc_sc = device_private(dev);
|
||||
exynos_parse_config(pc.pc_phandle, &pc.pc_pincfg);
|
||||
|
||||
return exynos_do_config(&pc);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/* $NetBSD: exynos_platform.c,v 1.6.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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_exynos.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
#include "opt_fdt_arm.h"
|
||||
|
||||
#include "ukbd.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_platform.c,v 1.6.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/termios.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/bootconfig.h>
|
||||
#include <arm/cpufunc.h>
|
||||
|
||||
#include <arm/samsung/exynos_reg.h>
|
||||
#include <arm/samsung/exynos_var.h>
|
||||
|
||||
#include <evbarm/exynos/platform.h>
|
||||
|
||||
#include <arm/cortex/gtmr_var.h>
|
||||
|
||||
#include <arm/fdt/arm_fdtvar.h>
|
||||
|
||||
#define EXYNOS5_SWRESET_REG 0x10040400
|
||||
|
||||
#define DEVMAP_ALIGN(a) ((a) & ~L1_S_OFFSET)
|
||||
#define DEVMAP_SIZE(s) roundup2((s), L1_S_SIZE)
|
||||
#define DEVMAP_ENTRY(va, pa, sz) \
|
||||
{ \
|
||||
.pd_va = DEVMAP_ALIGN(va), \
|
||||
.pd_pa = DEVMAP_ALIGN(pa), \
|
||||
.pd_size = DEVMAP_SIZE(sz), \
|
||||
.pd_prot = VM_PROT_READ|VM_PROT_WRITE, \
|
||||
.pd_cache = PTE_NOCACHE \
|
||||
}
|
||||
#define DEVMAP_ENTRY_END { 0 }
|
||||
|
||||
static const struct pmap_devmap *
|
||||
exynos_platform_devmap(void)
|
||||
{
|
||||
static const struct pmap_devmap devmap[] = {
|
||||
DEVMAP_ENTRY(EXYNOS_CORE_VBASE,
|
||||
EXYNOS_CORE_PBASE,
|
||||
EXYNOS5_CORE_SIZE),
|
||||
DEVMAP_ENTRY(EXYNOS5_AUDIOCORE_VBASE,
|
||||
EXYNOS5_AUDIOCORE_PBASE,
|
||||
EXYNOS5_AUDIOCORE_SIZE),
|
||||
DEVMAP_ENTRY_END
|
||||
};
|
||||
|
||||
return devmap;
|
||||
}
|
||||
|
||||
#define EXYNOS_IOPHYSTOVIRT(a) \
|
||||
((vaddr_t)(((a) - EXYNOS_CORE_PBASE) + EXYNOS_CORE_VBASE))
|
||||
|
||||
static void
|
||||
exynos_platform_bootstrap(void)
|
||||
{
|
||||
paddr_t uart_address = armreg_tpidruro_read(); /* XXX */
|
||||
exynos_bootstrap(EXYNOS_CORE_VBASE, EXYNOS_IOPHYSTOVIRT(uart_address));
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_platform_init_attach_args(struct fdt_attach_args *faa)
|
||||
{
|
||||
extern struct bus_space armv7_generic_bs_tag;
|
||||
extern struct bus_space armv7_generic_a4x_bs_tag;
|
||||
extern struct arm32_bus_dma_tag armv7_generic_dma_tag;
|
||||
|
||||
faa->faa_bst = &armv7_generic_bs_tag;
|
||||
faa->faa_a4x_bst = &armv7_generic_a4x_bs_tag;
|
||||
faa->faa_dmat = &armv7_generic_dma_tag;
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_platform_early_putchar(char c)
|
||||
{
|
||||
#if defined(VERBOSE_INIT_ARM)
|
||||
extern void exynos_putchar(int); /* XXX from exynos_start.S */
|
||||
|
||||
exynos_putchar(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_platform_device_register(device_t self, void *aux)
|
||||
{
|
||||
exynos_device_register(self, aux);
|
||||
}
|
||||
|
||||
static void
|
||||
exynos5_platform_reset(void)
|
||||
{
|
||||
bus_space_tag_t bst = &armv7_generic_bs_tag;
|
||||
bus_space_handle_t bsh;
|
||||
|
||||
bus_space_map(bst, EXYNOS5_SWRESET_REG, 4, 0, &bsh);
|
||||
bus_space_write_4(bst, bsh, 0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_platform_delay(u_int us)
|
||||
{
|
||||
gtmr_delay(us);
|
||||
}
|
||||
|
||||
static u_int
|
||||
exynos_platform_uart_freq(void)
|
||||
{
|
||||
return EXYNOS_UART_FREQ;
|
||||
}
|
||||
|
||||
static const struct arm_platform exynos5_platform = {
|
||||
.devmap = exynos_platform_devmap,
|
||||
.bootstrap = exynos_platform_bootstrap,
|
||||
.init_attach_args = exynos_platform_init_attach_args,
|
||||
.early_putchar = exynos_platform_early_putchar,
|
||||
.device_register = exynos_platform_device_register,
|
||||
.reset = exynos5_platform_reset,
|
||||
.delay = exynos_platform_delay,
|
||||
.uart_freq = exynos_platform_uart_freq,
|
||||
};
|
||||
|
||||
ARM_PLATFORM(exynos5, "samsung,exynos5", &exynos5_platform);
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_reg.h,v 1.13 2014/09/30 14:20:55 reinoud Exp $ */
|
||||
/* $NetBSD: exynos_reg.h,v 1.13.12.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
|
@ -97,10 +97,10 @@
|
|||
#define EXYNOS_BLOCK_SIZE 0x00010000
|
||||
|
||||
|
||||
#if defined(EXYNOS5)
|
||||
#if defined(SOC_EXYNOS5)
|
||||
#include <arm/samsung/exynos5_reg.h>
|
||||
#endif
|
||||
#if defined(EXYNOS4)
|
||||
#if defined(SOC_EXYNOS4)
|
||||
#include <arm/samsung/exynos4_reg.h>
|
||||
#endif
|
||||
|
||||
|
@ -124,7 +124,8 @@
|
|||
#define PLL_CON0_P __BITS( 8,13) /* PLL P divide value */
|
||||
#define PLL_CON0_S __BITS( 0, 2) /* PLL S divide value */
|
||||
|
||||
#define PLL_PMS2FREQ(F, M, P, S) (((M)*(F))/((P)*(1<<(S))))
|
||||
#define PLL_PMS2FREQ(F, M, P, S) \
|
||||
((P) == 0 ? 0 : (((M)*(F))/((P)*(1<<(S)))))
|
||||
#define PLL_FREQ(f, v) PLL_PMS2FREQ( \
|
||||
(f),\
|
||||
__SHIFTOUT((v), PLL_CON0_M),\
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_soc.c,v 1.31 2015/12/21 04:58:50 marty Exp $ */
|
||||
/* $NetBSD: exynos_soc.c,v 1.31.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
|
@ -31,10 +31,8 @@
|
|||
|
||||
#include "opt_exynos.h"
|
||||
|
||||
#define _ARM32_BUS_DMA_PRIVATE
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_soc.c,v 1.31 2015/12/21 04:58:50 marty Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_soc.c,v 1.31.10.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -76,7 +74,7 @@ struct cpu_freq {
|
|||
};
|
||||
|
||||
|
||||
#ifdef EXYNOS4
|
||||
#ifdef SOC_EXYNOS4
|
||||
const struct cpu_freq cpu_freq_settings_exynos4[] = {
|
||||
{ 200, 3, 100, 2},
|
||||
{ 300, 4, 200, 2},
|
||||
|
@ -100,7 +98,7 @@ const struct cpu_freq cpu_freq_settings_exynos4[] = {
|
|||
#endif
|
||||
|
||||
|
||||
#ifdef EXYNOS5
|
||||
#ifdef SOC_EXYNOS5
|
||||
#define EXYNOS5_DEFAULT_ENTRY 7
|
||||
const struct cpu_freq cpu_freq_settings_exynos5[] = {
|
||||
{ 200, 3, 100, 2},
|
||||
|
@ -207,7 +205,7 @@ exynos_cpu_boot(int cpu)
|
|||
}
|
||||
|
||||
|
||||
#ifdef EXYNOS4
|
||||
#ifdef SOC_EXYNOS4
|
||||
/*
|
||||
* The latency values used below are `magic' and probably chosen empirically.
|
||||
* For the 4210 variant the data latency is lower, a 0x110. This is currently
|
||||
|
@ -456,13 +454,13 @@ exynos_dump_clocks(void)
|
|||
uint32_t freq;
|
||||
|
||||
printf("Initial PLL settings\n");
|
||||
#ifdef EXYNOS4
|
||||
#ifdef SOC_EXYNOS4
|
||||
DUMP_PLL(4, APLL);
|
||||
DUMP_PLL(4, MPLL);
|
||||
DUMP_PLL(4, EPLL);
|
||||
DUMP_PLL(4, VPLL);
|
||||
#endif
|
||||
#ifdef EXYNOS5
|
||||
#ifdef SOC_EXYNOS5
|
||||
DUMP_PLL(5, APLL);
|
||||
DUMP_PLL(5, MPLL);
|
||||
DUMP_PLL(5, KPLL);
|
||||
|
@ -479,6 +477,15 @@ exynos_dump_clocks(void)
|
|||
|
||||
/* XXX clock stuff needs major work XXX */
|
||||
|
||||
void
|
||||
exynos_init_clkout_for_usb(void)
|
||||
{
|
||||
/* Select XUSBXTI as source for CLKOUT */
|
||||
bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh,
|
||||
EXYNOS_PMU_DEBUG_CLKOUT, 0x1000);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
exynos_clocks_bootstrap(void)
|
||||
{
|
||||
|
@ -493,7 +500,7 @@ exynos_clocks_bootstrap(void)
|
|||
/* set (max) cpufreq */
|
||||
fsel = ncpu_freq_settings-1;
|
||||
|
||||
#ifdef EXYNOS5
|
||||
#ifdef SOC_EXYNOS5
|
||||
/* XXX BUGFIX selecting freq on E5 goes wrong for now XXX */
|
||||
fsel = EXYNOS5_DEFAULT_ENTRY;
|
||||
#endif
|
||||
|
@ -524,7 +531,7 @@ exynos_bootstrap(vaddr_t iobase, vaddr_t uartbase)
|
|||
printf("Exynos early console operational\n\n");
|
||||
#endif
|
||||
|
||||
#ifdef EXYNOS4
|
||||
#ifdef SOC_EXYNOS4
|
||||
core_size = EXYNOS4_CORE_SIZE;
|
||||
audiocore_size = EXYNOS4_AUDIOCORE_SIZE;
|
||||
audiocore_pbase = EXYNOS4_AUDIOCORE_PBASE;
|
||||
|
@ -538,7 +545,7 @@ exynos_bootstrap(vaddr_t iobase, vaddr_t uartbase)
|
|||
ncpu_freq_settings = __arraycount(cpu_freq_settings_exynos4);
|
||||
#endif
|
||||
|
||||
#ifdef EXYNOS5
|
||||
#ifdef SOC_EXYNOS5
|
||||
core_size = EXYNOS5_CORE_SIZE;
|
||||
audiocore_size = EXYNOS5_AUDIOCORE_SIZE;
|
||||
audiocore_pbase = EXYNOS5_AUDIOCORE_PBASE;
|
||||
|
@ -594,9 +601,6 @@ exynos_bootstrap(vaddr_t iobase, vaddr_t uartbase)
|
|||
panic("%s: failed to subregion cmu apll registers: %d",
|
||||
__func__, error);
|
||||
|
||||
/* init bus dma tags */
|
||||
exynos_dma_bootstrap(physmem * PAGE_SIZE);
|
||||
|
||||
/* gpio bootstrapping delayed */
|
||||
}
|
||||
|
||||
|
@ -625,7 +629,7 @@ exynos_device_register(device_t self, void *aux)
|
|||
extern uint32_t exynos_soc_id;
|
||||
|
||||
switch (EXYNOS_PRODUCT_ID(exynos_soc_id)) {
|
||||
#ifdef EXYNOS5
|
||||
#ifdef SOC_EXYNOS5
|
||||
case 0xe5410:
|
||||
/* offsets not changed on matt's request */
|
||||
#if 0
|
||||
|
@ -643,7 +647,7 @@ exynos_device_register(device_t self, void *aux)
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef EXYNOS4
|
||||
#ifdef SOC_EXYNOS4
|
||||
case 0xe4410:
|
||||
case 0xe4412: {
|
||||
struct mpcore_attach_args * const mpcaa = aux;
|
||||
|
@ -661,7 +665,7 @@ exynos_device_register(device_t self, void *aux)
|
|||
return;
|
||||
}
|
||||
if (device_is_a(self, "armgtmr") || device_is_a(self, "mct")) {
|
||||
#ifdef EXYNOS5
|
||||
#ifdef SOC_EXYNOS5
|
||||
/*
|
||||
* The global timer is dependent on the MCT running.
|
||||
*/
|
||||
|
@ -733,7 +737,7 @@ exynos_usb2_set_isolation(bool on)
|
|||
}
|
||||
|
||||
|
||||
#ifdef EXYNOS4
|
||||
#ifdef SOC_EXYNOS4
|
||||
static void
|
||||
exynos4_usb2phy_enable(bus_space_handle_t usb2phy_bsh)
|
||||
{
|
||||
|
@ -794,7 +798,7 @@ exynos4_usb2phy_enable(bus_space_handle_t usb2phy_bsh)
|
|||
#endif
|
||||
|
||||
|
||||
#ifdef EXYNOS5
|
||||
#ifdef SOC_EXYNOS5
|
||||
static void
|
||||
exynos5410_usb2phy_enable(bus_space_handle_t usb2phy_bsh)
|
||||
{
|
||||
|
@ -909,10 +913,10 @@ exynos_usb_phy_init(bus_space_handle_t usb2phy_bsh)
|
|||
/* disable phy isolation */
|
||||
exynos_usb2_set_isolation(false);
|
||||
|
||||
#ifdef EXYNOS4
|
||||
#ifdef SOC_EXYNOS4
|
||||
exynos4_usb2phy_enable(usb2phy_bsh);
|
||||
#endif
|
||||
#ifdef EXYNOS5
|
||||
#ifdef SOC_EXYNOS5
|
||||
if (IS_EXYNOS5410_P()) {
|
||||
exynos5410_usb2phy_enable(usb2phy_bsh);
|
||||
/* TBD: USB3 phy init */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_sscom.c,v 1.7 2015/12/21 00:54:35 marty Exp $ */
|
||||
/* $NetBSD: exynos_sscom.c,v 1.7.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Reinoud Zandijk
|
||||
|
@ -34,7 +34,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_sscom.c,v 1.7 2015/12/21 00:54:35 marty Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_sscom.c,v 1.7.10.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include "opt_sscom.h"
|
||||
#include "opt_ddb.h"
|
||||
|
@ -79,10 +79,14 @@ static void sscom_attach(device_t, device_t, void *);
|
|||
CFATTACH_DECL_NEW(exynos_sscom, sizeof(struct sscom_softc), sscom_match,
|
||||
sscom_attach, NULL, NULL);
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"samsung,exynos4210-uart",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
sscom_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
const char * const compatible[] = { "samsung,exynos4210-uart", NULL };
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
|
@ -147,32 +151,46 @@ sscom_attach(device_t parent, device_t self, void *aux)
|
|||
{
|
||||
struct sscom_softc *sc = device_private(self);
|
||||
struct fdt_attach_args *faa = aux;
|
||||
int unit = -1;
|
||||
const int phandle = faa->faa_phandle;
|
||||
bus_space_tag_t bst = faa->faa_bst;
|
||||
bus_space_handle_t bsh;
|
||||
bus_space_tag_t bst;
|
||||
struct clk *clk_uart, *clk_uart_baud0;
|
||||
char intrstr[128];
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
/* unit is required for the sscom driver, which desperately
|
||||
* needs to be rewritten. For now, this hack gets the answer.
|
||||
* MJF: FIX ME
|
||||
*/
|
||||
for (i = 1; i < num_exynos_uarts_entries; i += 2)
|
||||
if (EXYNOS_CORE_PBASE + exynos_uarts[i] == addr)
|
||||
break;
|
||||
unit = exynos_uarts[i-1];
|
||||
|
||||
if (bus_space_map(bst, addr, size, 0, &bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
clk_uart = fdtbus_clock_get(phandle, "uart");
|
||||
if (clk_uart != NULL) {
|
||||
if (clk_enable(clk_uart) != 0) {
|
||||
aprint_error(": couldn't enable uart clock\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
clk_uart_baud0 = fdtbus_clock_get(phandle, "clk_uart_baud0");
|
||||
if (clk_uart_baud0 == NULL) {
|
||||
aprint_error(": couldn't get baud clock\n");
|
||||
return;
|
||||
}
|
||||
if (clk_enable(clk_uart_baud0) != 0) {
|
||||
aprint_error(": couldn't enable baud clock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_iot = bst = faa->faa_bst;
|
||||
sc->sc_ioh = exynos_uarts[i] + EXYNOS_CORE_VBASE;
|
||||
sc->sc_unit = unit;
|
||||
sc->sc_frequency = EXYNOS_UART_FREQ;
|
||||
sc->sc_ioh = bsh;
|
||||
sc->sc_unit = phandle;
|
||||
sc->sc_frequency = clk_get_rate(clk_uart_baud0);
|
||||
|
||||
sc->sc_change_txrx_interrupts = exynos_change_txrx_interrupts;
|
||||
sc->sc_clear_interrupts = exynos_clear_interrupts;
|
||||
|
@ -181,26 +199,22 @@ sscom_attach(device_t parent, device_t self, void *aux)
|
|||
sc->sc_rx_irqno = 0;
|
||||
sc->sc_tx_irqno = 0;
|
||||
|
||||
if (!sscom_is_console(sc->sc_iot, unit, &sc->sc_ioh)) {
|
||||
error = bus_space_map(bst, addr, size, 0, &bsh);
|
||||
if (error) {
|
||||
aprint_error(": couldn't map %#llx: %d\n",
|
||||
(uint64_t)addr, error);
|
||||
return;
|
||||
}
|
||||
sc->sc_ioh = bsh;
|
||||
} else {
|
||||
aprint_normal(" (console) ");
|
||||
}
|
||||
if (sscom_is_console(sc->sc_iot, phandle, &sc->sc_ioh))
|
||||
aprint_normal(" (console)");
|
||||
|
||||
aprint_normal("\n");
|
||||
|
||||
#if 0
|
||||
void *ih = fdtbus_intr_establish(faa->faa_phandle, 0, IPL_SERIAL,
|
||||
if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
|
||||
aprint_error_dev(self, "failed to decode interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
void *ih = fdtbus_intr_establish(phandle, 0, IPL_SERIAL,
|
||||
FDT_INTR_MPSAFE, sscomintr, sc);
|
||||
if (ih == NULL)
|
||||
aprint_error_dev(self, "failed to establish interrupt\n");
|
||||
#endif
|
||||
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
|
||||
sscom_attach_subr(sc);
|
||||
|
||||
|
@ -226,3 +240,56 @@ exynos_sscom_kgdb_attach(bus_space_tag_t iot, int unit, int rate,
|
|||
}
|
||||
#endif /* KGDB */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Console support
|
||||
*/
|
||||
|
||||
static int
|
||||
exynos_sscom_console_match(int phandle)
|
||||
{
|
||||
return of_match_compatible(phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_sscom_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
|
||||
{
|
||||
const struct sscom_uart_info info = {
|
||||
.iobase = 0, /* Offset from bsh */
|
||||
.unit = faa->faa_phandle
|
||||
};
|
||||
const int phandle = faa->faa_phandle;
|
||||
bus_space_tag_t bst = faa->faa_bst;
|
||||
bus_space_handle_t bsh;
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
tcflag_t flags;
|
||||
int speed;
|
||||
|
||||
fdtbus_get_reg(phandle, 0, &addr, &size);
|
||||
speed = fdtbus_get_stdout_speed();
|
||||
if (speed < 0)
|
||||
speed = 115200; /* default */
|
||||
flags = fdtbus_get_stdout_flags();
|
||||
|
||||
if (bus_space_map(bst, addr, size, 0, &bsh) != 0)
|
||||
panic("cannot map console UART");
|
||||
|
||||
/* Calculate UART frequency from bootloader (XXX) */
|
||||
uint32_t freq = speed
|
||||
* (16 * (bus_space_read_4(bst, bsh, SSCOM_UBRDIV) + 1)
|
||||
+ bus_space_read_4(bst, bsh, SSCOM_UFRACVAL));
|
||||
freq = (freq + speed / 2) / 1000;
|
||||
freq *= 1000;
|
||||
|
||||
if (sscom_cnattach(bst, bsh, &info, speed, freq, flags) != 0)
|
||||
panic("cannot attach console UART");
|
||||
}
|
||||
|
||||
static const struct fdt_console exynos_sscom_console = {
|
||||
.match = exynos_sscom_console_match,
|
||||
.consinit = exynos_sscom_console_consinit,
|
||||
};
|
||||
|
||||
FDT_CONSOLE(exynos_sscom, &exynos_sscom_console);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_sysmmu.c,v 1.1 2016/01/03 04:10:58 marty Exp $ */
|
||||
/* $NetBSD: exynos_sysmmu.c,v 1.1.12.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 The NetBSD Foundation, Inc.
|
||||
|
@ -34,7 +34,7 @@
|
|||
#include "gpio.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_sysmmu.c,v 1.1 2016/01/03 04:10:58 marty Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_sysmmu.c,v 1.1.12.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -102,6 +102,10 @@ exynos_sysmmu_attach(device_t parent, device_t self, void *aux)
|
|||
return;
|
||||
}
|
||||
|
||||
aprint_normal(" @ 0x%08x: SYSMMU - NOT IMPLEMENTED", (uint)addr);
|
||||
aprint_naive("\n");
|
||||
aprint_normal("\n");
|
||||
|
||||
if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) {
|
||||
aprint_error_dev(self, "failed to decode interrupt\n");
|
||||
return;
|
||||
|
@ -116,9 +120,6 @@ exynos_sysmmu_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
|
||||
aprint_normal(" @ 0x%08x: SYSMMU - NOT IMPLEMENTED", (uint)addr);
|
||||
aprint_naive("\n");
|
||||
aprint_normal("\n");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.exynos,v 1.21 2016/01/03 04:10:58 marty Exp $
|
||||
# $NetBSD: files.exynos,v 1.21.10.1 2017/07/18 19:13:08 snj Exp $
|
||||
#
|
||||
# Configuration info for Samsung Exynos SoC ARM Peripherals
|
||||
#
|
||||
|
@ -13,10 +13,10 @@ file arch/arm/arm32/arm32_kvminit.c
|
|||
file arch/arm/arm32/arm32_reboot.c
|
||||
file arch/arm/arm32/irq_dispatch.S
|
||||
file arch/arm/arm32/armv7_generic_space.c
|
||||
file arch/arm/arm32/armv7_generic_dma.c
|
||||
file arch/arm/arm/bus_space_a4x.S
|
||||
|
||||
file arch/arm/samsung/exynos_soc.c
|
||||
#file arch/arm/samsung/exynos_space.c
|
||||
file arch/arm/samsung/exynos_smc.S arm_trustzone_firmware
|
||||
|
||||
# Console parameters
|
||||
|
@ -30,23 +30,20 @@ defparam opt_exynos.h EXYNOS_WDT_DEFAULT_PERIOD
|
|||
defflag opt_exynos.h EXYNOS_CONSOLE_EARLY
|
||||
|
||||
#
|
||||
defflag opt_exynos.h EXYNOS4: CPU_CORTEXA9
|
||||
defflag opt_exynos.h EXYNOS4120: EXYNOS4
|
||||
defflag opt_exynos.h EXYNOS4212: EXYNOS4
|
||||
defflag opt_exynos.h EXYNOS4412: EXYNOS4
|
||||
defflag opt_exynos.h EXYNOS4412P: EXYNOS4
|
||||
defflag opt_exynos.h EXYNOS5: CPU_CORTEXA15
|
||||
defflag opt_exynos.h EXYNOS5250: EXYNOS5
|
||||
defflag opt_exynos.h EXYNOS5260: EXYNOS5
|
||||
defflag opt_exynos.h EXYNOS5410: EXYNOS5
|
||||
defflag opt_exynos.h EXYNOS5420: EXYNOS5
|
||||
defflag opt_exynos.h EXYNOS5440: EXYNOS5
|
||||
defflag opt_exynos.h EXYNOS5422: EXYNOS5
|
||||
defflag opt_exynos.h SOC_EXYNOS4: CPU_CORTEXA9
|
||||
defflag opt_exynos.h SOC_EXYNOS4120: SOC_EXYNOS4
|
||||
defflag opt_exynos.h SOC_EXYNOS4212: SOC_EXYNOS4
|
||||
defflag opt_exynos.h SOC_EXYNOS4412: SOC_EXYNOS4
|
||||
defflag opt_exynos.h SOC_EXYNOS4412P: SOC_EXYNOS4
|
||||
defflag opt_exynos.h SOC_EXYNOS5: CPU_CORTEXA15
|
||||
defflag opt_exynos.h SOC_EXYNOS5250: SOC_EXYNOS5
|
||||
defflag opt_exynos.h SOC_EXYNOS5260: SOC_EXYNOS5
|
||||
defflag opt_exynos.h SOC_EXYNOS5410: SOC_EXYNOS5
|
||||
defflag opt_exynos.h SOC_EXYNOS5420: SOC_EXYNOS5
|
||||
defflag opt_exynos.h SOC_EXYNOS5440: SOC_EXYNOS5
|
||||
defflag opt_exynos.h SOC_EXYNOS5422: SOC_EXYNOS5
|
||||
|
||||
# On-board I/O
|
||||
device exynosfdt : bus_space_generic, fdtbus
|
||||
attach exynosfdt at mainbus with exynos_fdt
|
||||
file arch/arm/samsung/exynos_fdt.c exynos_fdt
|
||||
file arch/arm/samsung/exynos_platform.c soc_exynos5
|
||||
|
||||
# Interrupt combiner
|
||||
device exyointr
|
||||
|
@ -64,12 +61,12 @@ attach sysmmu at fdt with exynos_sysmmu
|
|||
file arch/arm/samsung/exynos_sysmmu.c exynos_sysmmu
|
||||
|
||||
# real time clock
|
||||
device exyortc : ftdbus
|
||||
device exyortc : fdtbus
|
||||
attach exyortc at fdt with exynos_rtc
|
||||
file arch/arm/samsung/exynos_rtc.c exynos_rtc
|
||||
|
||||
# Multi Core timer
|
||||
device mct : ftdbus
|
||||
device mct { } : fdtbus, mpcorebus
|
||||
attach mct at fdt with exyo_mct
|
||||
file arch/arm/samsung/mct.c exyo_mct
|
||||
|
||||
|
@ -120,8 +117,10 @@ device exyoi2c: i2cbus, i2c_bitbang
|
|||
attach exyoi2c at fdt with exynos_i2c
|
||||
file arch/arm/samsung/exynos_i2c.c exynos_i2c needs-flag
|
||||
|
||||
file arch/arm/samsung/exynos5422_dma.c
|
||||
|
||||
device exy5422clk: clk
|
||||
attach exy5422clk at fdt with exynos5422_clock
|
||||
file arch/arm/samsung/exynos5422_clock.c exynos5422_clock
|
||||
|
||||
device exy5410clk: clk
|
||||
attach exy5410clk at fdt with exynos5410_clock
|
||||
file arch/arm/samsung/exynos5410_clock.c exynos5410_clock
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mct.c,v 1.10 2016/01/07 04:45:10 marty Exp $ */
|
||||
/* $NetBSD: mct.c,v 1.10.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__KERNEL_RCSID(1, "$NetBSD: mct.c,v 1.10 2016/01/07 04:45:10 marty Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: mct.c,v 1.10.10.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -50,36 +50,24 @@ __KERNEL_RCSID(1, "$NetBSD: mct.c,v 1.10 2016/01/07 04:45:10 marty Exp $");
|
|||
#include <arm/samsung/mct_reg.h>
|
||||
#include <arm/samsung/mct_var.h>
|
||||
|
||||
#include <arm/cortex/gtmr_intr.h>
|
||||
#include <arm/cortex/mpcore_var.h>
|
||||
#include <arm/cortex/gtmr_var.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
#include <arm/fdt/arm_fdtvar.h>
|
||||
|
||||
static int mct_match(device_t, cfdata_t, void *);
|
||||
static void mct_attach(device_t, device_t, void *);
|
||||
|
||||
static int clockhandler(void *);
|
||||
|
||||
CFATTACH_DECL_NEW(exyo_mct, 0, mct_match, mct_attach, NULL, NULL);
|
||||
|
||||
|
||||
#if 0
|
||||
static struct timecounter mct_timecounter = {
|
||||
.tc_get_timecount = mct_get_timecount,
|
||||
.tc_poll_pps = 0,
|
||||
.tc_counter_mask = ~0u,
|
||||
.tc_frequency = 0, /* set by cpu_initclocks() */
|
||||
.tc_name = NULL, /* set by cpu_initclocks() */
|
||||
.tc_quality = 500, /* why 500? */
|
||||
.tc_priv = &mct_sc,
|
||||
.tc_next = NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline uint32_t
|
||||
mct_read_global(struct mct_softc *sc, bus_size_t o)
|
||||
{
|
||||
return bus_space_read_4(sc->sc_bst, sc->sc_bsh, o);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
mct_write_global(struct mct_softc *sc, bus_size_t o, uint32_t v)
|
||||
{
|
||||
|
@ -129,6 +117,12 @@ mct_write_global(struct mct_softc *sc, bus_size_t o, uint32_t v)
|
|||
panic("MCT hangs after writing %#x at %#x", v, (uint32_t) o);
|
||||
}
|
||||
|
||||
static void
|
||||
mct_fdt_cpu_hatch(void *priv, struct cpu_info *ci)
|
||||
{
|
||||
gtmr_init_cpu_clock(ci);
|
||||
}
|
||||
|
||||
static int
|
||||
mct_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
|
@ -139,7 +133,6 @@ mct_match(device_t parent, cfdata_t cf, void *aux)
|
|||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mct_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
|
@ -157,6 +150,7 @@ mct_attach(device_t parent, device_t self, void *aux)
|
|||
self->dv_private = sc;
|
||||
sc->sc_dev = self;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
sc->sc_freq = EXYNOS_F_IN_FREQ;
|
||||
|
||||
error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
|
||||
if (error) {
|
||||
|
@ -166,122 +160,20 @@ mct_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": Exynos SoC multi core timer (64 bits) - NOT IMPLEMENTED\n");
|
||||
aprint_normal(": Exynos SoC multi core timer (64 bits)\n");
|
||||
|
||||
evcnt_attach_dynamic(&sc->sc_ev_missing_ticks, EVCNT_TYPE_MISC, NULL,
|
||||
device_xname(self), "missing interrupts");
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
fdtbus_intr_establish(faa->faa_phandle, i, 0, 0,
|
||||
clockhandler, 0);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
mct_gettime(struct mct_softc *sc)
|
||||
{
|
||||
uint32_t lo, hi;
|
||||
do {
|
||||
hi = mct_read_global(sc, MCT_G_CNT_U);
|
||||
lo = mct_read_global(sc, MCT_G_CNT_L);
|
||||
} while (hi != mct_read_global(sc, MCT_G_CNT_U));
|
||||
return ((uint64_t) hi << 32) | lo;
|
||||
}
|
||||
|
||||
|
||||
/* interrupt handler */
|
||||
static int
|
||||
clockhandler(void *arg)
|
||||
{
|
||||
struct clockframe * const cf = arg;
|
||||
struct mct_softc * const sc = &mct_sc;
|
||||
const uint64_t now = mct_gettime(sc);
|
||||
int64_t delta = now - sc->sc_lastintr;
|
||||
int64_t periods = delta / sc->sc_autoinc;
|
||||
|
||||
KASSERT(delta >= 0);
|
||||
KASSERT(periods >= 0);
|
||||
|
||||
/* ack the interrupt */
|
||||
mct_write_global(sc, MCT_G_INT_CSTAT, G_INT_CSTAT_CLEAR);
|
||||
|
||||
/* check if we missed clock interrupts */
|
||||
if (periods > 1)
|
||||
sc->sc_ev_missing_ticks.ev_count += periods - 1;
|
||||
|
||||
sc->sc_lastintr = now;
|
||||
hardclock(cf);
|
||||
|
||||
/* handled */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
mct_init_cpu_clock(struct cpu_info *ci)
|
||||
{
|
||||
struct mct_softc * const sc = &mct_sc;
|
||||
uint64_t now = mct_gettime(sc);
|
||||
uint64_t then;
|
||||
uint32_t tcon;
|
||||
|
||||
KASSERT(ci == curcpu());
|
||||
|
||||
sc->sc_lastintr = now;
|
||||
|
||||
/* get current config */
|
||||
tcon = mct_read_global(sc, MCT_G_TCON);
|
||||
|
||||
/* setup auto increment */
|
||||
mct_write_global(sc, MCT_G_COMP0_ADD_INCR, sc->sc_autoinc);
|
||||
|
||||
/* (re)setup comparator */
|
||||
then = now + sc->sc_autoinc;
|
||||
mct_write_global(sc, MCT_G_COMP0_L, (uint32_t) then);
|
||||
mct_write_global(sc, MCT_G_COMP0_U, (uint32_t) (then >> 32));
|
||||
tcon |= G_TCON_COMP0_AUTOINC;
|
||||
tcon |= G_TCON_COMP0_ENABLE;
|
||||
|
||||
/* start timer */
|
||||
/* Start the timer */
|
||||
uint32_t tcon = mct_read_global(sc, MCT_G_TCON);
|
||||
tcon |= G_TCON_START;
|
||||
|
||||
/* enable interrupt */
|
||||
mct_write_global(sc, MCT_G_INT_ENB, G_INT_ENB_ENABLE);
|
||||
|
||||
/* update config, starting the thing */
|
||||
mct_write_global(sc, MCT_G_TCON, tcon);
|
||||
|
||||
/* Attach ARMv7 generic timer */
|
||||
struct mpcore_attach_args mpcaa = {
|
||||
.mpcaa_name = "armgtmr",
|
||||
.mpcaa_irq = IRQ_GTMR_PPI_VTIMER
|
||||
};
|
||||
|
||||
config_found(self, &mpcaa, NULL);
|
||||
|
||||
arm_fdt_cpu_hatch_register(self, mct_fdt_cpu_hatch);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void
|
||||
cpu_initclocks(void)
|
||||
{
|
||||
struct mct_softc * const sc = &mct_sc;
|
||||
|
||||
sc->sc_autoinc = sc->sc_freq / hz;
|
||||
mct_init_cpu_clock(curcpu());
|
||||
|
||||
mct_timecounter.tc_name = device_xname(sc->sc_dev);
|
||||
mct_timecounter.tc_frequency = sc->sc_freq;
|
||||
|
||||
tc_init(&mct_timecounter);
|
||||
|
||||
#if 0
|
||||
{
|
||||
uint64_t then, now;
|
||||
|
||||
printf("testing timer\n");
|
||||
for (int i = 0; i < 200; i++) {
|
||||
printf("cstat %d\n", mct_read_global(sc, MCT_G_INT_CSTAT));
|
||||
then = mct_get_timecount(&mct_timecounter);
|
||||
do {
|
||||
now = mct_get_timecount(&mct_timecounter);
|
||||
} while (now == then);
|
||||
printf("\tgot %"PRIu64"\n", now);
|
||||
for (int j = 0; j < 90000; j++);
|
||||
}
|
||||
printf("passed\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mct_var.h,v 1.4 2015/12/21 00:54:35 marty Exp $ */
|
||||
/* $NetBSD: mct_var.h,v 1.4.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
|
@ -52,6 +52,7 @@ static struct mct_softc {
|
|||
} mct_sc;
|
||||
|
||||
void mct_init_cpu_clock(struct cpu_info *ci);
|
||||
void mct_delay(u_int);
|
||||
|
||||
#endif /* _ARM_SAMSUNG_MCT_VAR_H_ */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sscom.c,v 1.8 2015/04/13 21:18:41 riastradh Exp $ */
|
||||
/* $NetBSD: sscom.c,v 1.8.10.1 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002, 2003 Fujitsu Component Limited
|
||||
|
@ -98,7 +98,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sscom.c,v 1.8 2015/04/13 21:18:41 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sscom.c,v 1.8.10.1 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include "opt_sscom.h"
|
||||
#include "opt_ddb.h"
|
||||
|
@ -179,13 +179,9 @@ static int sscom_to_tiocm(struct sscom_softc *);
|
|||
static void sscom_iflush(struct sscom_softc *);
|
||||
|
||||
static int sscomhwiflow(struct tty *tp, int block);
|
||||
#if defined(KGDB) || \
|
||||
defined(SSCOM0CONSOLE) || defined(SSCOM1CONSOLE) || \
|
||||
defined(SSCOM2CONSOLE) || defined(SSCOM3CONSOLE)
|
||||
static int sscom_init(bus_space_tag_t, bus_space_handle_t,
|
||||
const struct sscom_uart_info *,
|
||||
int, int, tcflag_t, bus_space_handle_t *);
|
||||
#endif
|
||||
|
||||
extern struct cfdriver sscom_cd;
|
||||
|
||||
|
@ -1836,9 +1832,6 @@ sscomintr(void *v)
|
|||
}
|
||||
|
||||
|
||||
#if defined(KGDB) || \
|
||||
defined(SSCOM0CONSOLE) || defined(SSCOM1CONSOLE) || \
|
||||
defined(SSCOM2CONSOLE) || defined(SSCOM3CONSOLE)
|
||||
/*
|
||||
* Initialize UART for use as console or KGDB line.
|
||||
*/
|
||||
|
@ -1882,11 +1875,6 @@ sscom_init(bus_space_tag_t iot, bus_space_handle_t base_ioh,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if \
|
||||
defined(SSCOM0CONSOLE) || defined(SSCOM1CONSOLE) || \
|
||||
defined(SSCOM2CONSOLE) || defined(SSCOM3CONSOLE)
|
||||
/*
|
||||
* Following are all routines needed for SSCOM to act as console
|
||||
*/
|
||||
|
@ -2024,8 +2012,6 @@ sscomcnpollc(dev_t dev, int on)
|
|||
sscom_readaheadcount = 0;
|
||||
}
|
||||
|
||||
#endif /* SSCOM0CONSOLE||SSCOM1CONSOLE */
|
||||
|
||||
#ifdef KGDB
|
||||
int
|
||||
sscom_kgdb_attach(bus_space_tag_t iot, bus_space_handle_t ioh,
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
# $NetBSD: files.sunxi,v 1.12.4.2 2017/07/18 19:13:08 snj Exp $
|
||||
#
|
||||
# Configuration info for Allwinner sunxi family SoCs
|
||||
#
|
||||
#
|
||||
|
||||
include "arch/arm/pic/files.pic"
|
||||
include "arch/arm/cortex/files.cortex"
|
||||
|
||||
file arch/arm/arm32/arm32_boot.c
|
||||
file arch/arm/arm32/arm32_kvminit.c
|
||||
file arch/arm/arm32/arm32_reboot.c
|
||||
file arch/arm/arm32/irq_dispatch.S
|
||||
file arch/arm/arm32/armv7_generic_space.c
|
||||
file arch/arm/arm32/armv7_generic_dma.c
|
||||
file arch/arm/arm/bus_space_a4x.S
|
||||
|
||||
file arch/arm/sunxi/sunxi_platform.c soc_sunxi
|
||||
|
||||
# CCU
|
||||
define sunxi_ccu
|
||||
file arch/arm/sunxi/sunxi_ccu.c sunxi_ccu
|
||||
file arch/arm/sunxi/sunxi_ccu_div.c sunxi_ccu
|
||||
file arch/arm/sunxi/sunxi_ccu_gate.c sunxi_ccu
|
||||
file arch/arm/sunxi/sunxi_ccu_nm.c sunxi_ccu
|
||||
file arch/arm/sunxi/sunxi_ccu_nkmp.c sunxi_ccu
|
||||
file arch/arm/sunxi/sunxi_ccu_prediv.c sunxi_ccu
|
||||
|
||||
# CCU (A31)
|
||||
device sun6ia31ccu: sunxi_ccu
|
||||
attach sun6ia31ccu at fdt with sunxi_a31_ccu
|
||||
file arch/arm/sunxi/sun6i_a31_ccu.c sunxi_a31_ccu
|
||||
|
||||
# CCU (A83T)
|
||||
device sun8ia83tccu: sunxi_ccu
|
||||
attach sun8ia83tccu at fdt with sunxi_a83t_ccu
|
||||
file arch/arm/sunxi/sun8i_a83t_ccu.c sunxi_a83t_ccu
|
||||
|
||||
# CCU (H3)
|
||||
device sun8ih3ccu: sunxi_ccu
|
||||
attach sun8ih3ccu at fdt with sunxi_h3_ccu
|
||||
file arch/arm/sunxi/sun8i_h3_ccu.c sunxi_h3_ccu
|
||||
|
||||
# Misc. clock resets
|
||||
device sunxiresets
|
||||
attach sunxiresets at fdt with sunxi_resets
|
||||
file arch/arm/sunxi/sunxi_resets.c sunxi_resets
|
||||
|
||||
# Misc. clock gates
|
||||
device sunxigates
|
||||
attach sunxigates at fdt with sunxi_gates
|
||||
file arch/arm/sunxi/sunxi_gates.c sunxi_gates
|
||||
|
||||
# GPIO
|
||||
device sunxigpio: gpiobus
|
||||
attach sunxigpio at fdt with sunxi_gpio
|
||||
file arch/arm/sunxi/sunxi_gpio.c sunxi_gpio
|
||||
file arch/arm/sunxi/sun6i_a31_gpio.c sunxi_gpio & soc_sun6i_a31
|
||||
file arch/arm/sunxi/sun8i_a83t_gpio.c sunxi_gpio & soc_sun8i_a83t
|
||||
file arch/arm/sunxi/sun8i_h3_gpio.c sunxi_gpio & soc_sun8i_h3
|
||||
|
||||
# UART
|
||||
attach com at fdt with sunxi_com
|
||||
file arch/arm/sunxi/sunxi_com.c sunxi_com needs-flag
|
||||
|
||||
# SD/MMC
|
||||
device sunximmc: sdmmcbus
|
||||
attach sunximmc at fdt with sunxi_mmc
|
||||
file arch/arm/sunxi/sunxi_mmc.c sunxi_mmc
|
||||
|
||||
# USB PHY
|
||||
device sunxiusbphy
|
||||
attach sunxiusbphy at fdt with sunxi_usbphy
|
||||
file arch/arm/sunxi/sunxi_usbphy.c sunxi_usbphy
|
||||
|
||||
# EHCI
|
||||
attach ehci at fdt with ehci_fdt
|
||||
file dev/fdt/ehci_fdt.c ehci_fdt
|
||||
|
||||
# OHCI
|
||||
attach ohci at fdt with ohci_fdt
|
||||
file dev/fdt/ohci_fdt.c ohci_fdt
|
||||
|
||||
# TWI
|
||||
device sunxitwi: i2cbus, i2cexec, mvi2c
|
||||
attach sunxitwi at fdt with sunxi_twi
|
||||
file arch/arm/sunxi/sunxi_twi.c sunxi_twi
|
||||
|
||||
# P2WI/RSB
|
||||
device sunxirsb: i2cbus, i2cexec
|
||||
attach sunxirsb at fdt with sunxi_rsb
|
||||
file arch/arm/sunxi/sunxi_rsb.c sunxi_rsb
|
||||
|
||||
# RTC
|
||||
device sunxirtc
|
||||
attach sunxirtc at fdt with sunxi_rtc
|
||||
file arch/arm/sunxi/sunxi_rtc.c sunxi_rtc
|
||||
|
||||
# EMAC
|
||||
device sunxiemac: arp, ether, ifnet, mii
|
||||
attach sunxiemac at fdt with sunxi_emac
|
||||
file arch/arm/sunxi/sunxi_emac.c sunxi_emac
|
||||
|
||||
# SOC parameters
|
||||
defflag opt_soc.h SOC_SUNXI
|
||||
defflag opt_soc.h SOC_SUN8I: SOC_SUNXI
|
||||
defflag opt_soc.h SOC_SUN8I_A83T: SOC_SUN8I
|
||||
defflag opt_soc.h SOC_SUN8I_H3: SOC_SUN8I
|
||||
defflag opt_soc.h SOC_SUN6I: SOC_SUNXI
|
||||
defflag opt_soc.h SOC_SUN6I_A31: SOC_SUN6I
|
|
@ -0,0 +1,280 @@
|
|||
/* $NetBSD: sun6i_a31_ccu.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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>
|
||||
|
||||
__KERNEL_RCSID(1, "$NetBSD: sun6i_a31_ccu.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
#include <arm/sunxi/sun6i_a31_ccu.h>
|
||||
|
||||
#define PLL_PERIPH_CTRL_REG 0x028
|
||||
#define AHB1_APB1_CFG_REG 0x054
|
||||
#define APB2_CLK_DIV_REG 0x058
|
||||
#define AHB1_GATING_REG0 0x060
|
||||
#define AHB1_GATING_REG1 0x064
|
||||
#define APB1_GATING_REG 0x068
|
||||
#define APB2_GATING_REG 0x06c
|
||||
#define SD0_CLK_REG 0x088
|
||||
#define SD1_CLK_REG 0x08c
|
||||
#define SD2_CLK_REG 0x090
|
||||
#define SD3_CLK_REG 0x094
|
||||
#define USBPHY_CFG_REG 0x0cc
|
||||
#define BUS_SOFT_RST_REG0 0x2c0
|
||||
#define BUS_SOFT_RST_REG1 0x2c4
|
||||
#define BUS_SOFT_RST_REG2 0x2c8
|
||||
#define BUS_SOFT_RST_REG3 0x2d0
|
||||
#define BUS_SOFT_RST_REG4 0x2d8
|
||||
|
||||
static int sun6i_a31_ccu_match(device_t, cfdata_t, void *);
|
||||
static void sun6i_a31_ccu_attach(device_t, device_t, void *);
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"allwinner,sun6i-a31-ccu",
|
||||
NULL
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_a31_ccu, sizeof(struct sunxi_ccu_softc),
|
||||
sun6i_a31_ccu_match, sun6i_a31_ccu_attach, NULL, NULL);
|
||||
|
||||
static struct sunxi_ccu_reset sun6i_a31_ccu_resets[] = {
|
||||
SUNXI_CCU_RESET(A31_RST_USB_PHY0, USBPHY_CFG_REG, 0),
|
||||
SUNXI_CCU_RESET(A31_RST_USB_PHY1, USBPHY_CFG_REG, 1),
|
||||
SUNXI_CCU_RESET(A31_RST_USB_PHY2, USBPHY_CFG_REG, 2),
|
||||
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_MIPI_DSI, BUS_SOFT_RST_REG0, 1),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_SS, BUS_SOFT_RST_REG0, 5),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_DMA, BUS_SOFT_RST_REG0, 6),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_MMC0, BUS_SOFT_RST_REG0, 8),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_MMC1, BUS_SOFT_RST_REG0, 9),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_MMC2, BUS_SOFT_RST_REG0, 10),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_MMC3, BUS_SOFT_RST_REG0, 11),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_NAND1, BUS_SOFT_RST_REG0, 12),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_NAND0, BUS_SOFT_RST_REG0, 13),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_SDRAM, BUS_SOFT_RST_REG0, 14),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_EMAC, BUS_SOFT_RST_REG0, 17),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_TS, BUS_SOFT_RST_REG0, 18),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_HSTIMER, BUS_SOFT_RST_REG0, 19),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_SPI0, BUS_SOFT_RST_REG0, 20),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_SPI1, BUS_SOFT_RST_REG0, 21),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_SPI2, BUS_SOFT_RST_REG0, 22),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_SPI3, BUS_SOFT_RST_REG0, 23),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_OTG, BUS_SOFT_RST_REG0, 24),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_EHCI0, BUS_SOFT_RST_REG0, 26),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_EHCI1, BUS_SOFT_RST_REG0, 27),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_OHCI0, BUS_SOFT_RST_REG0, 29),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_OHCI1, BUS_SOFT_RST_REG0, 30),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_OHCI2, BUS_SOFT_RST_REG0, 31),
|
||||
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_VE, BUS_SOFT_RST_REG1, 0),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_LCD0, BUS_SOFT_RST_REG1, 4),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_LCD1, BUS_SOFT_RST_REG1, 5),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_CSI, BUS_SOFT_RST_REG1, 8),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_HDMI, BUS_SOFT_RST_REG1, 11),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_BE0, BUS_SOFT_RST_REG1, 12),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_BE1, BUS_SOFT_RST_REG1, 13),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_FE0, BUS_SOFT_RST_REG1, 14),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_FE1, BUS_SOFT_RST_REG1, 15),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_MP, BUS_SOFT_RST_REG1, 16),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_GPU, BUS_SOFT_RST_REG1, 20),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_DEU0, BUS_SOFT_RST_REG1, 23),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_DEU1, BUS_SOFT_RST_REG1, 24),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_DRC0, BUS_SOFT_RST_REG1, 25),
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_DRC1, BUS_SOFT_RST_REG1, 26),
|
||||
|
||||
SUNXI_CCU_RESET(A31_RST_AHB1_LVDS, BUS_SOFT_RST_REG2, 0),
|
||||
|
||||
SUNXI_CCU_RESET(A31_RST_APB1_CODEC, BUS_SOFT_RST_REG3, 0),
|
||||
SUNXI_CCU_RESET(A31_RST_APB1_SPDIF, BUS_SOFT_RST_REG3, 1),
|
||||
SUNXI_CCU_RESET(A31_RST_APB1_DIGITAL_MIC, BUS_SOFT_RST_REG3, 4),
|
||||
SUNXI_CCU_RESET(A31_RST_APB1_DAUDIO0, BUS_SOFT_RST_REG3, 12),
|
||||
SUNXI_CCU_RESET(A31_RST_APB1_DAUDIO1, BUS_SOFT_RST_REG3, 13),
|
||||
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_I2C0, BUS_SOFT_RST_REG4, 0),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_I2C1, BUS_SOFT_RST_REG4, 1),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_I2C2, BUS_SOFT_RST_REG4, 2),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_I2C3, BUS_SOFT_RST_REG4, 3),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_UART0, BUS_SOFT_RST_REG4, 16),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_UART1, BUS_SOFT_RST_REG4, 17),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_UART2, BUS_SOFT_RST_REG4, 18),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_UART3, BUS_SOFT_RST_REG4, 19),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_UART4, BUS_SOFT_RST_REG4, 20),
|
||||
SUNXI_CCU_RESET(A31_RST_APB2_UART5, BUS_SOFT_RST_REG4, 21),
|
||||
};
|
||||
|
||||
static const char *ahb1_parents[] = { "losc", "hosc", "axi", "pll_periph" };
|
||||
static const char *apb1_parents[] = { "ahb1" };
|
||||
static const char *apb2_parents[] = { "losc", "hosc", "pll_periph", "pll_periph" };
|
||||
static const char *mod_parents[] = { "hosc", "pll_periph" };
|
||||
|
||||
static struct sunxi_ccu_clk sun6i_a31_ccu_clks[] = {
|
||||
SUNXI_CCU_NKMP(A31_CLK_PLL_PERIPH, "pll_periph", "hosc",
|
||||
PLL_PERIPH_CTRL_REG, /* reg */
|
||||
__BITS(12,8), /* n */
|
||||
__BITS(5,4), /* k */
|
||||
0, /* m */
|
||||
0, /* p */
|
||||
__BIT(31), /* enable */
|
||||
SUNXI_CCU_NKMP_DIVIDE_BY_TWO),
|
||||
|
||||
SUNXI_CCU_DIV(A31_CLK_APB1, "apb1", apb1_parents,
|
||||
AHB1_APB1_CFG_REG, /* reg */
|
||||
__BITS(9,8), /* div */
|
||||
0, /* sel */
|
||||
SUNXI_CCU_DIV_POWER_OF_TWO|SUNXI_CCU_DIV_ZERO_IS_ONE),
|
||||
|
||||
SUNXI_CCU_PREDIV(A31_CLK_AHB1, "ahb1", ahb1_parents,
|
||||
AHB1_APB1_CFG_REG, /* reg */
|
||||
__BITS(7,6), /* prediv */
|
||||
__BIT(3), /* prediv_sel */
|
||||
__BITS(5,4), /* div */
|
||||
__BITS(13,12), /* sel */
|
||||
SUNXI_CCU_PREDIV_POWER_OF_TWO),
|
||||
|
||||
SUNXI_CCU_NM(A31_CLK_APB2, "apb2", apb2_parents,
|
||||
APB2_CLK_DIV_REG, /* reg */
|
||||
__BITS(17,16), /* n */
|
||||
__BITS(4,0), /* m */
|
||||
__BITS(25,24), /* sel */
|
||||
0, /* enable */
|
||||
SUNXI_CCU_NM_POWER_OF_TWO),
|
||||
|
||||
SUNXI_CCU_NM(A31_CLK_MMC0, "mmc0", mod_parents,
|
||||
SD0_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
SUNXI_CCU_NM(A31_CLK_MMC1, "mmc1", mod_parents,
|
||||
SD1_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
SUNXI_CCU_NM(A31_CLK_MMC2, "mmc2", mod_parents,
|
||||
SD2_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
SUNXI_CCU_NM(A31_CLK_MMC3, "mmc3", mod_parents,
|
||||
SD3_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_MMC0, "ahb1-mmc0", "ahb1",
|
||||
AHB1_GATING_REG0, 8),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_MMC1, "ahb1-mmc1", "ahb1",
|
||||
AHB1_GATING_REG0, 9),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_MMC2, "ahb1-mmc2", "ahb1",
|
||||
AHB1_GATING_REG0, 10),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_MMC3, "ahb1-mmc3", "ahb1",
|
||||
AHB1_GATING_REG0, 11),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_EMAC, "ahb1-emac", "ahb1",
|
||||
AHB1_GATING_REG0, 17),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_OTG, "ahb1-otg", "ahb1",
|
||||
AHB1_GATING_REG0, 24),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_EHCI0, "ahb1-ehci0", "ahb1",
|
||||
AHB1_GATING_REG0, 26),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_EHCI1, "ahb1-ehci1", "ahb1",
|
||||
AHB1_GATING_REG0, 27),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_OHCI0, "ahb1-ohci0", "ahb1",
|
||||
AHB1_GATING_REG0, 29),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_OHCI1, "ahb1-ohci1", "ahb1",
|
||||
AHB1_GATING_REG0, 30),
|
||||
SUNXI_CCU_GATE(A31_CLK_AHB1_OHCI2, "ahb1-ohci2", "ahb1",
|
||||
AHB1_GATING_REG0, 31),
|
||||
|
||||
SUNXI_CCU_GATE(A31_CLK_APB1_PIO, "ahb1-pio", "apb1",
|
||||
APB1_GATING_REG, 5),
|
||||
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_I2C0, "apb2-i2c0", "apb2",
|
||||
APB2_GATING_REG, 0),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_I2C1, "apb2-i2c1", "apb2",
|
||||
APB2_GATING_REG, 1),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_I2C2, "apb2-i2c2", "apb2",
|
||||
APB2_GATING_REG, 2),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_I2C3, "apb2-i2c3", "apb2",
|
||||
APB2_GATING_REG, 3),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_UART0, "apb2-uart0", "apb2",
|
||||
APB2_GATING_REG, 16),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_UART1, "apb2-uart1", "apb2",
|
||||
APB2_GATING_REG, 17),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_UART2, "apb2-uart2", "apb2",
|
||||
APB2_GATING_REG, 18),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_UART3, "apb2-uart3", "apb2",
|
||||
APB2_GATING_REG, 19),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_UART4, "apb2-uart4", "apb2",
|
||||
APB2_GATING_REG, 20),
|
||||
SUNXI_CCU_GATE(A31_CLK_APB2_UART5, "apb2-uart5", "apb2",
|
||||
APB2_GATING_REG, 21),
|
||||
|
||||
SUNXI_CCU_GATE(A31_CLK_USB_PHY0, "usb-phy0", "hosc",
|
||||
USBPHY_CFG_REG, 8),
|
||||
SUNXI_CCU_GATE(A31_CLK_USB_PHY1, "usb-phy1", "hosc",
|
||||
USBPHY_CFG_REG, 9),
|
||||
SUNXI_CCU_GATE(A31_CLK_USB_PHY2, "usb-phy2", "hosc",
|
||||
USBPHY_CFG_REG, 10),
|
||||
SUNXI_CCU_GATE(A31_CLK_USB_OHCI0, "usb-ohci0", "hosc",
|
||||
USBPHY_CFG_REG, 16),
|
||||
SUNXI_CCU_GATE(A31_CLK_USB_OHCI1, "usb-ohci1", "hosc",
|
||||
USBPHY_CFG_REG, 17),
|
||||
SUNXI_CCU_GATE(A31_CLK_USB_OHCI2, "usb-ohci2", "hosc",
|
||||
USBPHY_CFG_REG, 18),
|
||||
};
|
||||
|
||||
static int
|
||||
sun6i_a31_ccu_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sun6i_a31_ccu_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_phandle = faa->faa_phandle;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
|
||||
sc->sc_resets = sun6i_a31_ccu_resets;
|
||||
sc->sc_nresets = __arraycount(sun6i_a31_ccu_resets);
|
||||
|
||||
sc->sc_clks = sun6i_a31_ccu_clks;
|
||||
sc->sc_nclks = __arraycount(sun6i_a31_ccu_clks);
|
||||
|
||||
if (sunxi_ccu_attach(sc) != 0)
|
||||
return;
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": A31 CCU\n");
|
||||
|
||||
sunxi_ccu_print(sc);
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/* $NetBSD: sun6i_a31_ccu.h,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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$
|
||||
*/
|
||||
|
||||
#ifndef __CCU_A31_H__
|
||||
#define __CCU_A31_H__
|
||||
|
||||
#define A31_RST_USB_PHY0 0
|
||||
#define A31_RST_USB_PHY1 1
|
||||
#define A31_RST_USB_PHY2 2
|
||||
#define A31_RST_AHB1_MIPI_DSI 3
|
||||
#define A31_RST_AHB1_SS 4
|
||||
#define A31_RST_AHB1_DMA 5
|
||||
#define A31_RST_AHB1_MMC0 6
|
||||
#define A31_RST_AHB1_MMC1 7
|
||||
#define A31_RST_AHB1_MMC2 8
|
||||
#define A31_RST_AHB1_MMC3 9
|
||||
#define A31_RST_AHB1_NAND1 10
|
||||
#define A31_RST_AHB1_NAND0 11
|
||||
#define A31_RST_AHB1_SDRAM 12
|
||||
#define A31_RST_AHB1_EMAC 13
|
||||
#define A31_RST_AHB1_TS 14
|
||||
#define A31_RST_AHB1_HSTIMER 15
|
||||
#define A31_RST_AHB1_SPI0 16
|
||||
#define A31_RST_AHB1_SPI1 17
|
||||
#define A31_RST_AHB1_SPI2 18
|
||||
#define A31_RST_AHB1_SPI3 19
|
||||
#define A31_RST_AHB1_OTG 20
|
||||
#define A31_RST_AHB1_EHCI0 21
|
||||
#define A31_RST_AHB1_EHCI1 22
|
||||
#define A31_RST_AHB1_OHCI0 23
|
||||
#define A31_RST_AHB1_OHCI1 24
|
||||
#define A31_RST_AHB1_OHCI2 25
|
||||
#define A31_RST_AHB1_VE 26
|
||||
#define A31_RST_AHB1_LCD0 27
|
||||
#define A31_RST_AHB1_LCD1 28
|
||||
#define A31_RST_AHB1_CSI 29
|
||||
#define A31_RST_AHB1_HDMI 30
|
||||
#define A31_RST_AHB1_BE0 31
|
||||
#define A31_RST_AHB1_BE1 32
|
||||
#define A31_RST_AHB1_FE0 33
|
||||
#define A31_RST_AHB1_FE1 34
|
||||
#define A31_RST_AHB1_MP 35
|
||||
#define A31_RST_AHB1_GPU 36
|
||||
#define A31_RST_AHB1_DEU0 37
|
||||
#define A31_RST_AHB1_DEU1 38
|
||||
#define A31_RST_AHB1_DRC0 39
|
||||
#define A31_RST_AHB1_DRC1 40
|
||||
#define A31_RST_AHB1_LVDS 41
|
||||
#define A31_RST_APB1_CODEC 42
|
||||
#define A31_RST_APB1_SPDIF 43
|
||||
#define A31_RST_APB1_DIGITAL_MIC 44
|
||||
#define A31_RST_APB1_DAUDIO0 45
|
||||
#define A31_RST_APB1_DAUDIO1 46
|
||||
#define A31_RST_APB2_I2C0 47
|
||||
#define A31_RST_APB2_I2C1 48
|
||||
#define A31_RST_APB2_I2C2 49
|
||||
#define A31_RST_APB2_I2C3 50
|
||||
#define A31_RST_APB2_UART0 51
|
||||
#define A31_RST_APB2_UART1 52
|
||||
#define A31_RST_APB2_UART2 53
|
||||
#define A31_RST_APB2_UART3 54
|
||||
#define A31_RST_APB2_UART4 55
|
||||
#define A31_RST_APB2_UART5 56
|
||||
|
||||
#define A31_CLK_PLL_CPU 0
|
||||
#define A31_CLK_PLL_AUDIO_BASE 1
|
||||
#define A31_CLK_PLL_AUDIO 2
|
||||
#define A31_CLK_PLL_AUDIO_2X 3
|
||||
#define A31_CLK_PLL_AUDIO_4X 4
|
||||
#define A31_CLK_PLL_AUDIO_8X 5
|
||||
#define A31_CLK_PLL_VIDEO0 6
|
||||
#define A31_CLK_PLL_VIDEO0_2X 7
|
||||
#define A31_CLK_PLL_VE 8
|
||||
#define A31_CLK_PLL_DDR 9
|
||||
#define A31_CLK_PLL_PERIPH 10
|
||||
#define A31_CLK_PLL_PERIPH_2X 11
|
||||
#define A31_CLK_PLL_VIDEO1 12
|
||||
#define A31_CLK_PLL_VIDEO1_2X 13
|
||||
#define A31_CLK_PLL_GPU 14
|
||||
#define A31_CLK_PLL_MIPI 15
|
||||
#define A31_CLK_PLL9 16
|
||||
#define A31_CLK_PLL10 17
|
||||
#define A31_CLK_CPU 18
|
||||
#define A31_CLK_AXI 19
|
||||
#define A31_CLK_AHB1 20
|
||||
#define A31_CLK_APB1 21
|
||||
#define A31_CLK_APB2 22
|
||||
#define A31_CLK_AHB1_MIPIDSI 23
|
||||
#define A31_CLK_AHB1_SS 24
|
||||
#define A31_CLK_AHB1_DMA 25
|
||||
#define A31_CLK_AHB1_MMC0 26
|
||||
#define A31_CLK_AHB1_MMC1 27
|
||||
#define A31_CLK_AHB1_MMC2 28
|
||||
#define A31_CLK_AHB1_MMC3 29
|
||||
#define A31_CLK_AHB1_NAND1 30
|
||||
#define A31_CLK_AHB1_NAND0 31
|
||||
#define A31_CLK_AHB1_SDRAM 32
|
||||
#define A31_CLK_AHB1_EMAC 33
|
||||
#define A31_CLK_AHB1_TS 34
|
||||
#define A31_CLK_AHB1_HSTIMER 35
|
||||
#define A31_CLK_AHB1_SPI0 36
|
||||
#define A31_CLK_AHB1_SPI1 37
|
||||
#define A31_CLK_AHB1_SPI2 38
|
||||
#define A31_CLK_AHB1_SPI3 39
|
||||
#define A31_CLK_AHB1_OTG 40
|
||||
#define A31_CLK_AHB1_EHCI0 41
|
||||
#define A31_CLK_AHB1_EHCI1 42
|
||||
#define A31_CLK_AHB1_OHCI0 43
|
||||
#define A31_CLK_AHB1_OHCI1 44
|
||||
#define A31_CLK_AHB1_OHCI2 45
|
||||
#define A31_CLK_AHB1_VE 46
|
||||
#define A31_CLK_AHB1_LCD0 47
|
||||
#define A31_CLK_AHB1_LCD1 48
|
||||
#define A31_CLK_AHB1_CSI 49
|
||||
#define A31_CLK_AHB1_HDMI 50
|
||||
#define A31_CLK_AHB1_BE0 51
|
||||
#define A31_CLK_AHB1_BE1 52
|
||||
#define A31_CLK_AHB1_FE0 53
|
||||
#define A31_CLK_AHB1_FE1 54
|
||||
#define A31_CLK_AHB1_MP 55
|
||||
#define A31_CLK_AHB1_GPU 56
|
||||
#define A31_CLK_AHB1_DEU0 57
|
||||
#define A31_CLK_AHB1_DEU1 58
|
||||
#define A31_CLK_AHB1_DRC0 59
|
||||
#define A31_CLK_AHB1_DRC1 60
|
||||
#define A31_CLK_APB1_CODEC 61
|
||||
#define A31_CLK_APB1_SPDIF 62
|
||||
#define A31_CLK_APB1_DIGITAL_MIC 63
|
||||
#define A31_CLK_APB1_PIO 64
|
||||
#define A31_CLK_APB1_DAUDIO0 65
|
||||
#define A31_CLK_APB1_DAUDIO1 66
|
||||
#define A31_CLK_APB2_I2C0 67
|
||||
#define A31_CLK_APB2_I2C1 68
|
||||
#define A31_CLK_APB2_I2C2 69
|
||||
#define A31_CLK_APB2_I2C3 70
|
||||
#define A31_CLK_APB2_UART0 71
|
||||
#define A31_CLK_APB2_UART1 72
|
||||
#define A31_CLK_APB2_UART2 73
|
||||
#define A31_CLK_APB2_UART3 74
|
||||
#define A31_CLK_APB2_UART4 75
|
||||
#define A31_CLK_APB2_UART5 76
|
||||
#define A31_CLK_NAND0 77
|
||||
#define A31_CLK_NAND1 78
|
||||
#define A31_CLK_MMC0 79
|
||||
#define A31_CLK_MMC0_SAMPLE 80
|
||||
#define A31_CLK_MMC0_OUTPUT 81
|
||||
#define A31_CLK_MMC1 82
|
||||
#define A31_CLK_MMC1_SAMPLE 83
|
||||
#define A31_CLK_MMC1_OUTPUT 84
|
||||
#define A31_CLK_MMC2 85
|
||||
#define A31_CLK_MMC2_SAMPLE 86
|
||||
#define A31_CLK_MMC2_OUTPUT 87
|
||||
#define A31_CLK_MMC3 88
|
||||
#define A31_CLK_MMC3_SAMPLE 89
|
||||
#define A31_CLK_MMC3_OUTPUT 90
|
||||
#define A31_CLK_TS 91
|
||||
#define A31_CLK_SS 92
|
||||
#define A31_CLK_SPI0 93
|
||||
#define A31_CLK_SPI1 94
|
||||
#define A31_CLK_SPI2 95
|
||||
#define A31_CLK_SPI3 96
|
||||
#define A31_CLK_DAUDIO0 97
|
||||
#define A31_CLK_DAUDIO1 98
|
||||
#define A31_CLK_SPDIF 99
|
||||
#define A31_CLK_USB_PHY0 100
|
||||
#define A31_CLK_USB_PHY1 101
|
||||
#define A31_CLK_USB_PHY2 102
|
||||
#define A31_CLK_USB_OHCI0 103
|
||||
#define A31_CLK_USB_OHCI1 104
|
||||
#define A31_CLK_USB_OHCI2 105
|
||||
#define A31_CLK_MDFS 107
|
||||
#define A31_CLK_SDRAM0 108
|
||||
#define A31_CLK_SDRAM1 109
|
||||
#define A31_CLK_DRAM_VE 110
|
||||
#define A31_CLK_DRAM_CSI_ISP 111
|
||||
#define A31_CLK_DRAM_TS 112
|
||||
#define A31_CLK_DRAM_DRC0 113
|
||||
#define A31_CLK_DRAM_DRC1 114
|
||||
#define A31_CLK_DRAM_DEU0 115
|
||||
#define A31_CLK_DRAM_DEU1 116
|
||||
#define A31_CLK_DRAM_FE0 117
|
||||
#define A31_CLK_DRAM_FE1 118
|
||||
#define A31_CLK_DRAM_BE0 119
|
||||
#define A31_CLK_DRAM_BE1 120
|
||||
#define A31_CLK_DRAM_MP 121
|
||||
#define A31_CLK_BE0 122
|
||||
#define A31_CLK_BE1 123
|
||||
#define A31_CLK_FE0 124
|
||||
#define A31_CLK_FE1 125
|
||||
#define A31_CLK_MP 126
|
||||
#define A31_CLK_LCD0_CH0 127
|
||||
#define A31_CLK_LCD1_CH0 128
|
||||
#define A31_CLK_LCD0_CH1 129
|
||||
#define A31_CLK_LCD1_CH1 130
|
||||
#define A31_CLK_CSI0_SCLK 131
|
||||
#define A31_CLK_CSI0_MCLK 132
|
||||
#define A31_CLK_CSI1_MCLK 133
|
||||
#define A31_CLK_VE 134
|
||||
#define A31_CLK_CODEC 135
|
||||
#define A31_CLK_AVS 136
|
||||
#define A31_CLK_DIGITAL_MIC 137
|
||||
#define A31_CLK_HDMI 138
|
||||
#define A31_CLK_HDMI_DDC 139
|
||||
#define A31_CLK_PS 140
|
||||
#define A31_CLK_MBUS0 141
|
||||
#define A31_CLK_MBUS1 142
|
||||
#define A31_CLK_MIPI_DSI 143
|
||||
#define A31_CLK_MIPI_DSI_DPHY 144
|
||||
#define A31_CLK_MIPI_CSI_DPHY 145
|
||||
#define A31_CLK_IEP_DRC0 146
|
||||
#define A31_CLK_IEP_DRC1 147
|
||||
#define A31_CLK_IEP_DEU0 148
|
||||
#define A31_CLK_IEP_DEU1 149
|
||||
#define A31_CLK_GPU_CORE 150
|
||||
#define A31_CLK_GPU_MEMORY 151
|
||||
#define A31_CLK_GPU_HYD 152
|
||||
#define A31_CLK_ATS 153
|
||||
#define A31_CLK_TRACE 154
|
||||
#define A31_CLK_OUT_A 155
|
||||
#define A31_CLK_OUT_B 156
|
||||
#define A31_CLK_OUT_C 157
|
||||
|
||||
#endif /* __CCU_A31 H__ */
|
|
@ -0,0 +1,244 @@
|
|||
/* $NetBSD: sun6i_a31_gpio.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 Emmanuel Vadot <manu@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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sun6i_a31_gpio.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_gpio.h>
|
||||
|
||||
static const struct sunxi_gpio_pins a31_pins[] = {
|
||||
{"PA0", 0, 0, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint0", NULL}, 6, 0},
|
||||
{"PA1", 0, 1, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint1", NULL}, 6, 1},
|
||||
{"PA2", 0, 2, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint2", NULL}, 6, 2},
|
||||
{"PA3", 0, 3, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint3", NULL}, 6, 3},
|
||||
{"PA4", 0, 4, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint4", NULL}, 6, 4},
|
||||
{"PA5", 0, 5, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint5", NULL}, 6, 5},
|
||||
{"PA6", 0, 6, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint6", NULL}, 6, 6},
|
||||
{"PA7", 0, 7, {"gpio_in", "gpio_out", "gmac", "lcd1", "uart1", NULL, "pa_eint7", NULL}, 6, 7},
|
||||
{"PA8", 0, 8, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, NULL, "pa_eint8", NULL}, 6, 8},
|
||||
{"PA9", 0, 9, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, "mmc2", "pa_eint9", NULL}, 6, 9},
|
||||
{"PA10", 0, 10, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint10", NULL}, 6, 10},
|
||||
{"PA11", 0, 11, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint11", NULL}, 6, 11},
|
||||
{"PA12", 0, 12, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint12", NULL}, 6, 12},
|
||||
{"PA13", 0, 13, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint13", NULL}, 6, 13},
|
||||
{"PA14", 0, 14, {"gpio_in", "gpio_out", "gmac", "lcd1", "mmc3", "mmc2", "pa_eint14", NULL}, 6, 14},
|
||||
{"PA15", 0, 15, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_a", NULL, "pa_eint15", NULL}, 6, 15},
|
||||
{"PA16", 0, 16, {"gpio_in", "gpio_out", "gmac", "lcd1", "dmic", NULL, "pa_eint16", NULL}, 6, 16},
|
||||
{"PA17", 0, 17, {"gpio_in", "gpio_out", "gmac", "lcd1", "dmic", NULL, "pa_eint17", NULL}, 6, 17},
|
||||
{"PA18", 0, 18, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_b", NULL, "pa_eint18", NULL}, 6, 18},
|
||||
{"PA19", 0, 19, {"gpio_in", "gpio_out", "gmac", "lcd1", "pwm3", NULL, "pa_eint19", NULL}, 6, 19},
|
||||
{"PA20", 0, 20, {"gpio_in", "gpio_out", "gmac", "lcd1", "pwm3", NULL, "pa_eint20", NULL}, 6, 20},
|
||||
{"PA21", 0, 21, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint21", NULL}, 6, 21},
|
||||
{"PA22", 0, 22, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint22", NULL}, 6, 22},
|
||||
{"PA23", 0, 23, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint23", NULL}, 6, 23},
|
||||
{"PA24", 0, 24, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint24", NULL}, 6, 24},
|
||||
{"PA25", 0, 25, {"gpio_in", "gpio_out", "gmac", "lcd1", "spi3", NULL, "pa_eint25", NULL}, 6, 25},
|
||||
{"PA26", 0, 26, {"gpio_in", "gpio_out", "gmac", "lcd1", "clk_out_c", NULL, "pa_eint26", NULL}, 6, 26},
|
||||
{"PA27", 0, 27, {"gpio_in", "gpio_out", "gmac", "lcd1", NULL, NULL, "pa_eint27", NULL}, 6, 27},
|
||||
|
||||
{"PB0", 1, 0, {"gpio_in", "gpio_out", "i2s0", "uart3", "csi", NULL, "pb_eint0", NULL}, 6, 0},
|
||||
{"PB1", 1, 1, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint1", NULL}, 6, 1},
|
||||
{"PB2", 1, 2, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint2", NULL}, 6, 2},
|
||||
{"PB3", 1, 3, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint3", NULL}, 6, 3},
|
||||
{"PB4", 1, 4, {"gpio_in", "gpio_out", "i2s0", "uart3", NULL, NULL, "pb_eint4", NULL}, 6, 4},
|
||||
{"PB5", 1, 5, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint5", NULL}, 6, 5},
|
||||
{"PB6", 1, 6, {"gpio_in", "gpio_out", "i2s0", "uart3", "i2c3", NULL, "pb_eint6", NULL}, 6, 6},
|
||||
{"PB7", 1, 7, {"gpio_in", "gpio_out", "i2s0", NULL, NULL, NULL, "pb_eint7", NULL}, 6, 7},
|
||||
|
||||
{"PC0", 2, 0, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC1", 2, 1, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC2", 2, 2, {"gpio_in", "gpio_out", "nand0", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC3", 2, 3, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC4", 2, 4, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC5", 2, 5, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC6", 2, 6, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC7", 2, 7, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC8", 2, 8, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC9", 2, 9, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC10", 2, 10, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC11", 2, 11, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC12", 2, 12, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC13", 2, 13, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC14", 2, 14, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC15", 2, 15, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC16", 2, 16, {"gpio_in", "gpio_out", "nand0", "nand1", NULL, NULL, NULL, NULL}},
|
||||
{"PC17", 2, 17, {"gpio_in", "gpio_out", "nand0", "nand1", NULL, NULL, NULL, NULL}},
|
||||
{"PC18", 2, 18, {"gpio_in", "gpio_out", "nand0", "nand1", NULL, NULL, NULL, NULL}},
|
||||
{"PC19", 2, 19, {"gpio_in", "gpio_out", "nand0", "nand1", NULL, NULL, NULL, NULL}},
|
||||
{"PC20", 2, 20, {"gpio_in", "gpio_out", "nand0", "nand1", NULL, NULL, NULL, NULL}},
|
||||
{"PC21", 2, 21, {"gpio_in", "gpio_out", "nand0", "nand1", NULL, NULL, NULL, NULL}},
|
||||
{"PC22", 2, 22, {"gpio_in", "gpio_out", "nand0", "nand1", NULL, NULL, NULL, NULL}},
|
||||
{"PC23", 2, 23, {"gpio_in", "gpio_out", "nand0", "nand1", NULL, NULL, NULL, NULL}},
|
||||
{"PC24", 2, 24, {"gpio_in", "gpio_out", "nand0", "mmc2", "mmc3", NULL, NULL, NULL}},
|
||||
{"PC25", 2, 25, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC26", 2, 26, {"gpio_in", "gpio_out", "nand0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC27", 2, 27, {"gpio_in", "gpio_out", NULL, "spi0",NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PD0", 3, 0, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD1", 3, 1, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD2", 3, 2, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD3", 3, 3, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD4", 3, 4, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD5", 3, 5, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD6", 3, 6, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD7", 3, 7, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD8", 3, 8, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD9", 3, 9, {"gpio_in", "gpio_out", "lcd0", "lvds0", NULL, NULL, NULL, NULL}},
|
||||
{"PD10", 3, 10, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD11", 3, 11, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD12", 3, 12, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD13", 3, 13, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD14", 3, 14, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD15", 3, 15, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD16", 3, 16, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD17", 3, 17, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD18", 3, 18, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD19", 3, 19, {"gpio_in", "gpio_out", "lcd0", "lvds1", NULL, NULL, NULL, NULL}},
|
||||
{"PD20", 3, 20, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD21", 3, 21, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD22", 3, 22, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD23", 3, 23, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD24", 3, 24, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD25", 3, 25, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD26", 3, 26, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD27", 3, 27, {"gpio_in", "gpio_out", "lcd0", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PE0", 4, 0, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint0", NULL}, 6, 0},
|
||||
{"PE1", 4, 1, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint1", NULL}, 6, 1},
|
||||
{"PE2", 4, 2, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint2", NULL}, 6, 2},
|
||||
{"PE3", 4, 3, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint3", NULL}, 6, 3},
|
||||
{"PE4", 4, 4, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint4", NULL}, 6, 4},
|
||||
{"PE5", 4, 5, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint5", NULL}, 6, 5},
|
||||
{"PE6", 4, 6, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint6", NULL}, 6, 6},
|
||||
{"PE7", 4, 7, {"gpio_in", "gpio_out", "csi", "uart5", NULL, NULL, "pe_eint7", NULL}, 6, 7},
|
||||
{"PE8", 4, 8, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint8", NULL}, 6, 8},
|
||||
{"PE9", 4, 9, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint9", NULL}, 6, 9},
|
||||
{"PE10", 4, 10, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint10", NULL}, 6, 10},
|
||||
{"PE11", 4, 11, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint11", NULL}, 6, 11},
|
||||
{"PE12", 4, 12, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint12", NULL}, 6, 12},
|
||||
{"PE13", 4, 13, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint13", NULL}, 6, 13},
|
||||
{"PE14", 4, 14, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint14", NULL}, 6, 14},
|
||||
{"PE15", 4, 15, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, "pe_eint15", NULL}, 6, 15},
|
||||
{"PE16", 4, 16, {"gpio_in", "gpio_out", "csi", NULL, NULL, NULL, "pe_eint16", NULL}, 6, 16},
|
||||
|
||||
{"PF0", 5, 0, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
{"PF1", 5, 1, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
{"PF2", 5, 2, {"gpio_in", "gpio_out", "mmc0", NULL, "uart0", NULL, NULL, NULL}},
|
||||
{"PF3", 5, 3, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
{"PF4", 5, 4, {"gpio_in", "gpio_out", "mmc0", NULL, "uart0", NULL, NULL, NULL}},
|
||||
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", NULL, "jtag", NULL, NULL, NULL}},
|
||||
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3", NULL}, 6, 3},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4", NULL}, 6, 4},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5", NULL}, 6, 5},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint6", NULL}, 6, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint7", NULL}, 6, 7},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint8", NULL}, 6, 8},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart2", NULL, NULL, NULL, "pg_eint9", NULL}, 6, 9},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2c3", "usb", NULL, NULL, "pg_eint10", NULL}, 6, 10},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2c3", "usb", NULL, NULL, "pg_eint11", NULL}, 6, 11},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint12", NULL}, 6, 12},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint13", NULL}, 6, 13},
|
||||
{"PG14", 6, 14, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint14", NULL}, 6, 14},
|
||||
{"PG15", 6, 15, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint15", NULL}, 6, 15},
|
||||
{"PG16", 6, 16, {"gpio_in", "gpio_out", "spi1", "i2s1", NULL, NULL, "pg_eint16", NULL}, 6, 16},
|
||||
{"PG17", 6, 17, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint17", NULL}, 6, 17},
|
||||
{"PG18", 6, 18, {"gpio_in", "gpio_out", "uart4", NULL, NULL, NULL, "pg_eint18", NULL}, 6, 18},
|
||||
|
||||
{"PH0", 7, 0, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH1", 7, 1, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH2", 7, 2, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH3", 7, 3, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH4", 7, 4, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH5", 7, 5, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH6", 7, 6, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH7", 7, 7, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH8", 7, 8, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH9", 7, 9, {"gpio_in", "gpio_out", "spi2", "jtag", "pwm1", NULL, NULL, NULL}},
|
||||
{"PH10", 7, 10, {"gpio_in", "gpio_out", "spi2", "jtag", "pwm1", NULL, NULL, NULL}},
|
||||
{"PH11", 7, 11, {"gpio_in", "gpio_out", "spi2", "jtag", "pwm2", NULL, NULL, NULL}},
|
||||
{"PH12", 7, 12, {"gpio_in", "gpio_out", "spi2", "jtag", "pwm2", NULL, NULL, NULL}},
|
||||
{"PH13", 7, 13, {"gpio_in", "gpio_out", "pwm0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH14", 7, 14, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH15", 7, 15, {"gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH16", 7, 16, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH17", 7, 17, {"gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH18", 7, 18, {"gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH19", 7, 19, {"gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH20", 7, 20, {"gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH21", 7, 21, {"gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH22", 7, 22, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH23", 7, 23, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH24", 7, 24, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH25", 7, 25, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH26", 7, 26, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH27", 7, 27, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH28", 7, 28, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH29", 7, 29, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PH30", 7, 30, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
|
||||
};
|
||||
|
||||
static const struct sunxi_gpio_pins a31_r_pins[] = {
|
||||
{"PL0", 0, 0, {"gpio_in", "gpio_out", "s_twi", "s_p2wi", NULL, NULL, NULL, NULL}},
|
||||
{"PL1", 0, 1, {"gpio_in", "gpio_out", "s_twi", "s_p2wi", NULL, NULL, NULL, NULL}},
|
||||
{"PL2", 0, 2, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PL3", 0, 3, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PL4", 0, 4, {"gpio_in", "gpio_out", "s_ir", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PL5", 0, 5, {"gpio_in", "gpio_out", "pl_eint0", "s_jtag", NULL, NULL, NULL, NULL}, 2, 0},
|
||||
{"PL6", 0, 6, {"gpio_in", "gpio_out", "pl_eint1", "s_jtag", NULL, NULL, NULL, NULL}, 2, 1},
|
||||
{"PL7", 0, 7, {"gpio_in", "gpio_out", "pl_eint2", "s_jtag", NULL, NULL, NULL, NULL}, 2, 2},
|
||||
{"PL8", 0, 8, {"gpio_in", "gpio_out", "pl_eint3", "s_jtag", NULL, NULL, NULL, NULL}, 2, 3},
|
||||
|
||||
{"PM0", 1, 0, {"gpio_in", "gpio_out", "pm_eint0", NULL, NULL, NULL, NULL, NULL}, 2, 0},
|
||||
{"PM1", 1, 1, {"gpio_in", "gpio_out", "pm_eint1", NULL, NULL, NULL, NULL, NULL}, 2, 1},
|
||||
{"PM2", 1, 2, {"gpio_in", "gpio_out", "pm_eint2", "1wire", NULL, NULL, NULL, NULL}, 2, 2},
|
||||
{"PM3", 1, 3, {"gpio_in", "gpio_out", "pm_eint3", NULL, NULL, NULL, NULL, NULL}, 2, 3},
|
||||
{"PM4", 1, 4, {"gpio_in", "gpio_out", "pm_eint4", NULL, NULL, NULL, NULL, NULL}, 2, 4},
|
||||
{"PM5", 1, 5, {"gpio_in", "gpio_out", "pm_eint5", NULL, NULL, NULL, NULL, NULL}, 2, 5},
|
||||
{"PM6", 1, 6, {"gpio_in", "gpio_out", "pm_eint6", NULL, NULL, NULL, NULL, NULL}, 2, 6},
|
||||
{"PM7", 1, 7, {"gpio_in", "gpio_out", "pm_eint7", "rtc", NULL, NULL, NULL, NULL}, 2, 7},
|
||||
};
|
||||
|
||||
const struct sunxi_gpio_padconf sun6i_a31_padconf = {
|
||||
.npins = __arraycount(a31_pins),
|
||||
.pins = a31_pins,
|
||||
};
|
||||
|
||||
const struct sunxi_gpio_padconf sun6i_a31_r_padconf = {
|
||||
.npins = __arraycount(a31_r_pins),
|
||||
.pins = a31_r_pins,
|
||||
};
|
|
@ -0,0 +1,285 @@
|
|||
/* $NetBSD: sun8i_a83t_ccu.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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>
|
||||
|
||||
__KERNEL_RCSID(1, "$NetBSD: sun8i_a83t_ccu.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
#include <arm/sunxi/sun8i_a83t_ccu.h>
|
||||
|
||||
#define PLL_PERIPH0_CTRL_REG 0x028
|
||||
#define AHB1_APB1_CFG_REG 0x054
|
||||
#define APB2_CFG_REG 0x058
|
||||
#define BUS_CLK_GATING_REG0 0x060
|
||||
#define BUS_CLK_GATING_REG2 0x068
|
||||
#define BUS_CLK_GATING_REG3 0x06c
|
||||
#define SDMMC0_CLK_REG 0x088
|
||||
#define SDMMC1_CLK_REG 0x08c
|
||||
#define SDMMC2_CLK_REG 0x090
|
||||
#define USBPHY_CFG_REG 0x0cc
|
||||
#define MBUS_RST_REG 0x0fc
|
||||
#define BUS_SOFT_RST_REG0 0x2c0
|
||||
#define BUS_SOFT_RST_REG1 0x2c4
|
||||
#define BUS_SOFT_RST_REG2 0x2c8
|
||||
#define BUS_SOFT_RST_REG3 0x2d0
|
||||
#define BUS_SOFT_RST_REG4 0x2d8
|
||||
|
||||
static int sun8i_a83t_ccu_match(device_t, cfdata_t, void *);
|
||||
static void sun8i_a83t_ccu_attach(device_t, device_t, void *);
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"allwinner,sun8i-a83t-ccu",
|
||||
NULL
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_a83t_ccu, sizeof(struct sunxi_ccu_softc),
|
||||
sun8i_a83t_ccu_match, sun8i_a83t_ccu_attach, NULL, NULL);
|
||||
|
||||
static struct sunxi_ccu_reset sun8i_a83t_ccu_resets[] = {
|
||||
SUNXI_CCU_RESET(H3_RST_USB_PHY0, USBPHY_CFG_REG, 0),
|
||||
SUNXI_CCU_RESET(H3_RST_USB_PHY1, USBPHY_CFG_REG, 1),
|
||||
SUNXI_CCU_RESET(H3_RST_USB_PHY2, USBPHY_CFG_REG, 2),
|
||||
SUNXI_CCU_RESET(H3_RST_USB_PHY3, USBPHY_CFG_REG, 3),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_MBUS, MBUS_RST_REG, 31),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_CE, BUS_SOFT_RST_REG0, 5),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DMA, BUS_SOFT_RST_REG0, 6),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_MMC0, BUS_SOFT_RST_REG0, 8),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_MMC1, BUS_SOFT_RST_REG0, 9),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_MMC2, BUS_SOFT_RST_REG0, 10),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_NAND, BUS_SOFT_RST_REG0, 13),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DRAM, BUS_SOFT_RST_REG0, 14),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EMAC, BUS_SOFT_RST_REG0, 17),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_TS, BUS_SOFT_RST_REG0, 18),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_HSTIMER, BUS_SOFT_RST_REG0, 19),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SPI0, BUS_SOFT_RST_REG0, 20),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SPI1, BUS_SOFT_RST_REG0, 21),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OTG, BUS_SOFT_RST_REG0, 23),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EHCI0, BUS_SOFT_RST_REG0, 24),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EHCI1, BUS_SOFT_RST_REG0, 25),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EHCI2, BUS_SOFT_RST_REG0, 26),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EHCI3, BUS_SOFT_RST_REG0, 27),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OHCI0, BUS_SOFT_RST_REG0, 28),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OHCI1, BUS_SOFT_RST_REG0, 29),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OHCI2, BUS_SOFT_RST_REG0, 30),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OHCI3, BUS_SOFT_RST_REG0, 31),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_VE, BUS_SOFT_RST_REG1, 0),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_TCON0, BUS_SOFT_RST_REG1, 3),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_TCON1, BUS_SOFT_RST_REG1, 4),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DEINTERLACE, BUS_SOFT_RST_REG1, 5),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_CSI, BUS_SOFT_RST_REG1, 8),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_TVE, BUS_SOFT_RST_REG1, 9),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_HDMI0, BUS_SOFT_RST_REG1, 10),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_HDMI1, BUS_SOFT_RST_REG1, 11),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DE, BUS_SOFT_RST_REG1, 12),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_GPU, BUS_SOFT_RST_REG1, 20),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_MSGBOX, BUS_SOFT_RST_REG1, 21),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SPINLOCK, BUS_SOFT_RST_REG1, 22),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DBG, BUS_SOFT_RST_REG1, 31),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EPHY, BUS_SOFT_RST_REG2, 2),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_CODEC, BUS_SOFT_RST_REG3, 0),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SPDIF, BUS_SOFT_RST_REG3, 1),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_THS, BUS_SOFT_RST_REG3, 8),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2S0, BUS_SOFT_RST_REG3, 12),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2S1, BUS_SOFT_RST_REG3, 13),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2S2, BUS_SOFT_RST_REG3, 14),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2C0, BUS_SOFT_RST_REG4, 0),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2C1, BUS_SOFT_RST_REG4, 1),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2C2, BUS_SOFT_RST_REG4, 2),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_UART0, BUS_SOFT_RST_REG4, 16),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_UART1, BUS_SOFT_RST_REG4, 17),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_UART2, BUS_SOFT_RST_REG4, 18),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_UART3, BUS_SOFT_RST_REG4, 19),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SCR, BUS_SOFT_RST_REG4, 20),
|
||||
};
|
||||
|
||||
static const char *ahb1_parents[] = { "losc", "hosc", "pll_periph" };
|
||||
static const char *ahb2_parents[] = { "ahb1", "pll_periph" };
|
||||
static const char *apb1_parents[] = { "ahb1" };
|
||||
static const char *apb2_parents[] = { "losc", "hosc", "pll_periph" };
|
||||
static const char *mod_parents[] = { "hosc", "pll_periph" };
|
||||
|
||||
static struct sunxi_ccu_clk sun8i_a83t_ccu_clks[] = {
|
||||
SUNXI_CCU_NKMP(H3_CLK_PLL_PERIPH0, "pll_periph", "hosc",
|
||||
PLL_PERIPH0_CTRL_REG, /* reg */
|
||||
__BITS(15,8), /* n */
|
||||
0, /* k */
|
||||
__BIT(18), /* m */
|
||||
__BIT(16), /* p */
|
||||
__BIT(31), /* enable */
|
||||
SUNXI_CCU_NKMP_FACTOR_N_EXACT),
|
||||
|
||||
SUNXI_CCU_PREDIV(H3_CLK_AHB1, "ahb1", ahb1_parents,
|
||||
AHB1_APB1_CFG_REG, /* reg */
|
||||
__BITS(7,6), /* prediv */
|
||||
__BIT(3), /* prediv_sel */
|
||||
__BITS(5,4), /* div */
|
||||
__BITS(13,12), /* sel */
|
||||
SUNXI_CCU_PREDIV_POWER_OF_TWO),
|
||||
|
||||
SUNXI_CCU_PREDIV(H3_CLK_AHB2, "ahb2", ahb2_parents,
|
||||
APB2_CFG_REG, /* reg */
|
||||
0, /* prediv */
|
||||
__BIT(1), /* prediv_sel */
|
||||
0, /* div */
|
||||
__BITS(1,0), /* sel */
|
||||
SUNXI_CCU_PREDIV_DIVIDE_BY_TWO),
|
||||
|
||||
SUNXI_CCU_DIV(H3_CLK_APB1, "apb1", apb1_parents,
|
||||
AHB1_APB1_CFG_REG, /* reg */
|
||||
__BITS(9,8), /* div */
|
||||
0, /* sel */
|
||||
SUNXI_CCU_DIV_POWER_OF_TWO|SUNXI_CCU_DIV_ZERO_IS_ONE),
|
||||
|
||||
SUNXI_CCU_NM(H3_CLK_APB2, "apb2", apb2_parents,
|
||||
APB2_CFG_REG, /* reg */
|
||||
__BITS(17,16), /* n */
|
||||
__BITS(4,0), /* m */
|
||||
__BITS(25,24), /* sel */
|
||||
0, /* enable */
|
||||
SUNXI_CCU_NM_POWER_OF_TWO),
|
||||
|
||||
SUNXI_CCU_NM(H3_CLK_MMC0, "mmc0", mod_parents,
|
||||
SDMMC0_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
SUNXI_CCU_NM(H3_CLK_MMC1, "mmc1", mod_parents,
|
||||
SDMMC1_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
SUNXI_CCU_NM(H3_CLK_MMC2, "mmc2", mod_parents,
|
||||
SDMMC2_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_MMC0, "bus-mmc0", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 8),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_MMC1, "bus-mmc1", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 9),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_MMC2, "bus-mmc2", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 10),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EMAC, "bus-emac", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 17),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OTG, "bus-otg", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 23),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI0, "bus-ehci0", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 24),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI1, "bus-ehci1", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 25),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI2, "bus-ehci2", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 26),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI3, "bus-ehci3", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 27),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OHCI0, "bus-ohci0", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 28),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OHCI1, "bus-ohci1", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 29),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OHCI2, "bus-ohci2", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 30),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OHCI3, "bus-ohci3", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 31),
|
||||
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_PIO, "bus-pio", "apb1",
|
||||
BUS_CLK_GATING_REG2, 5),
|
||||
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_I2C0, "bus-i2c0", "apb2",
|
||||
BUS_CLK_GATING_REG3, 0),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_I2C1, "bus-i2c1", "apb2",
|
||||
BUS_CLK_GATING_REG3, 1),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_I2C2, "bus-i2c2", "apb2",
|
||||
BUS_CLK_GATING_REG3, 2),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_UART0, "bus-uart0", "apb2",
|
||||
BUS_CLK_GATING_REG3, 16),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_UART1, "bus-uart1", "apb2",
|
||||
BUS_CLK_GATING_REG3, 17),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_UART2, "bus-uart2", "apb2",
|
||||
BUS_CLK_GATING_REG3, 18),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_UART3, "bus-uart3", "apb2",
|
||||
BUS_CLK_GATING_REG3, 19),
|
||||
|
||||
SUNXI_CCU_GATE(H3_CLK_USBPHY0, "usb-phy0", "hosc",
|
||||
USBPHY_CFG_REG, 8),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBPHY1, "usb-phy1", "hosc",
|
||||
USBPHY_CFG_REG, 9),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBPHY2, "usb-phy2", "hosc",
|
||||
USBPHY_CFG_REG, 10),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBPHY3, "usb-phy3", "hosc",
|
||||
USBPHY_CFG_REG, 11),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBOHCI0, "usb-ohci0", "hosc",
|
||||
USBPHY_CFG_REG, 16),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBOHCI1, "usb-ohci1", "hosc",
|
||||
USBPHY_CFG_REG, 17),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBOHCI2, "usb-ohci2", "hosc",
|
||||
USBPHY_CFG_REG, 18),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBOHCI3, "usb-ohci3", "hosc",
|
||||
USBPHY_CFG_REG, 19),
|
||||
};
|
||||
|
||||
static int
|
||||
sun8i_a83t_ccu_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sun8i_a83t_ccu_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_phandle = faa->faa_phandle;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
|
||||
sc->sc_resets = sun8i_a83t_ccu_resets;
|
||||
sc->sc_nresets = __arraycount(sun8i_a83t_ccu_resets);
|
||||
|
||||
sc->sc_clks = sun8i_a83t_ccu_clks;
|
||||
sc->sc_nclks = __arraycount(sun8i_a83t_ccu_clks);
|
||||
|
||||
if (sunxi_ccu_attach(sc) != 0)
|
||||
return;
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": A83T CCU\n");
|
||||
|
||||
sunxi_ccu_print(sc);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* $NetBSD: sun8i_a83t_ccu.h,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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.
|
||||
*/
|
||||
|
||||
#ifndef _SUN8I_A83T_CCU_H
|
||||
#define _SUN8I_A83T_CCU_H
|
||||
|
||||
#include <arm/sunxi/sun8i_h3_ccu.h>
|
||||
|
||||
#endif /* !_SUN8I_A83T_CCU_H */
|
|
@ -0,0 +1,181 @@
|
|||
/* $NetBSD: sun8i_a83t_gpio.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sun8i_a83t_gpio.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_gpio.h>
|
||||
|
||||
static const struct sunxi_gpio_pins a83t_pins[] = {
|
||||
{ "PB0", 1, 0, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } },
|
||||
{ "PB1", 1, 1, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } },
|
||||
{ "PB2", 1, 2, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } },
|
||||
{ "PB3", 1, 3, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } },
|
||||
{ "PB4", 1, 4, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB5", 1, 5, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB6", 1, 6, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB7", 1, 7, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB8", 1, 8, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } },
|
||||
{ "PB9", 1, 9, { "gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "eint" } },
|
||||
{ "PB10", 1, 10, { "gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "eint" } },
|
||||
|
||||
{ "PC0", 2, 0, { "gpio_in", "gpio_out", "nand", "spi0" } },
|
||||
{ "PC1", 2, 1, { "gpio_in", "gpio_out", "nand", "spi0" } },
|
||||
{ "PC2", 2, 2, { "gpio_in", "gpio_out", "nand", "spi0" } },
|
||||
{ "PC3", 2, 3, { "gpio_in", "gpio_out", "nand", "spi0" } },
|
||||
{ "PC4", 2, 4, { "gpio_in", "gpio_out", "nand" } },
|
||||
{ "PC5", 2, 5, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC6", 2, 6, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC7", 2, 7, { "gpio_in", "gpio_out", "nand" } },
|
||||
{ "PC8", 2, 8, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC9", 2, 9, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC10", 2, 10, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC11", 2, 11, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC12", 2, 12, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC13", 2, 13, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC14", 2, 14, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC15", 2, 15, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC16", 2, 16, { "gpio_in", "gpio_out", "nand", "mmc2" } },
|
||||
{ "PC17", 2, 17, { "gpio_in", "gpio_out", "nand" } },
|
||||
{ "PC18", 2, 18, { "gpio_in", "gpio_out", "nand" } },
|
||||
|
||||
{ "PD2", 3, 2, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD3", 3, 3, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD4", 3, 4, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD5", 3, 5, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD6", 3, 6, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD7", 3, 7, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD10", 3, 10, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD11", 3, 11, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD12", 3, 12, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD13", 3, 13, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD14", 3, 14, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD15", 3, 15, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } },
|
||||
{ "PD18", 3, 18, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } },
|
||||
{ "PD19", 3, 19, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } },
|
||||
{ "PD20", 3, 20, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } },
|
||||
{ "PD21", 3, 21, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } },
|
||||
{ "PD22", 3, 22, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } },
|
||||
{ "PD23", 3, 23, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } },
|
||||
{ "PD24", 3, 24, { "gpio_in", "gpio_out", "lcd", "lvds" } },
|
||||
{ "PD25", 3, 25, { "gpio_in", "gpio_out", "lcd", "lvds" } },
|
||||
{ "PD26", 3, 26, { "gpio_in", "gpio_out", "lcd", "lvds" } },
|
||||
{ "PD27", 3, 27, { "gpio_in", "gpio_out", "lcd", "lvds" } },
|
||||
{ "PD28", 3, 28, { "gpio_in", "gpio_out", "pwm" } },
|
||||
{ "PD29", 3, 29, { "gpio_in", "gpio_out" } },
|
||||
|
||||
{ "PE0", 4, 0, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } },
|
||||
{ "PE1", 4, 1, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } },
|
||||
{ "PE2", 4, 2, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } },
|
||||
{ "PE3", 4, 3, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } },
|
||||
{ "PE4", 4, 4, { "gpio_in", "gpio_out", "csi" } },
|
||||
{ "PE5", 4, 5, { "gpio_in", "gpio_out", "csi" } },
|
||||
{ "PE6", 4, 6, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } },
|
||||
{ "PE7", 4, 7, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } },
|
||||
{ "PE8", 4, 8, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } },
|
||||
{ "PE9", 4, 9, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } },
|
||||
{ "PE10", 4, 10, { "gpio_in", "gpio_out", "csi", "uart4", "ccir" } },
|
||||
{ "PE11", 4, 11, { "gpio_in", "gpio_out", "csi", "uart4", "ccir" } },
|
||||
{ "PE12", 4, 12, { "gpio_in", "gpio_out", "csi", "uart4", "ccir" } },
|
||||
{ "PE13", 4, 13, { "gpio_in", "gpio_out", "csi", "uart4", "ccir" } },
|
||||
{ "PE14", 4, 14, { "gpio_in", "gpio_out", "csi", "twi2" } },
|
||||
{ "PE15", 4, 15, { "gpio_in", "gpio_out", "csi", "twi2" } },
|
||||
{ "PE16", 4, 16, { "gpio_in", "gpio_out" } },
|
||||
{ "PE17", 4, 17, { "gpio_in", "gpio_out" } },
|
||||
{ "PE18", 4, 18, { "gpio_in", "gpio_out", NULL, "owa" } },
|
||||
{ "PE19", 4, 19, { "gpio_in", "gpio_out" } },
|
||||
|
||||
{ "PF0", 5, 0, { "gpio_in", "gpio_out", "mmc0", "jtag" } },
|
||||
{ "PF1", 5, 1, { "gpio_in", "gpio_out", "mmc0", "jtag" } },
|
||||
{ "PF2", 5, 2, { "gpio_in", "gpio_out", "mmc0", "uart0" } },
|
||||
{ "PF3", 5, 3, { "gpio_in", "gpio_out", "mmc0", "jtag" } },
|
||||
{ "PF4", 5, 4, { "gpio_in", "gpio_out", "mmc0", "uart0" } },
|
||||
{ "PF5", 5, 5, { "gpio_in", "gpio_out", "mmc0", "jtag" } },
|
||||
{ "PF6", 5, 6, { "gpio_in", "gpio_out" } },
|
||||
|
||||
{ "PG0", 6, 0, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG1", 6, 1, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG2", 6, 2, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG3", 6, 3, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG4", 6, 4, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG5", 6, 5, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PG6", 6, 6, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } },
|
||||
{ "PG7", 6, 7, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } },
|
||||
{ "PG8", 6, 8, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } },
|
||||
{ "PG9", 6, 9, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } },
|
||||
{ "PG10", 6, 10, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } },
|
||||
{ "PG11", 6, 11, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } },
|
||||
{ "PG12", 6, 12, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } },
|
||||
{ "PG13", 6, 13, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } },
|
||||
|
||||
{ "PH0", 7, 0, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH1", 7, 1, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH2", 7, 2, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH3", 7, 3, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH4", 7, 4, { "gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH5", 7, 5, { "gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH6", 7, 6, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH7", 7, 7, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH8", 7, 8, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } },
|
||||
{ "PH9", 7, 9, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } },
|
||||
{ "PH10", 7, 10, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } },
|
||||
{ "PH11", 7, 11, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } },
|
||||
};
|
||||
|
||||
static const struct sunxi_gpio_pins a83t_r_pins[] = {
|
||||
{ "PL0", 0, 0, { "gpio_in", "gpio_out", "s_rsb", "s_i2c", NULL, NULL, "eint" } },
|
||||
{ "PL1", 0, 1, { "gpio_in", "gpio_out", "s_rsb", "s_i2c", NULL, NULL, "eint" } },
|
||||
{ "PL2", 0, 2, { "gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL3", 0, 3, { "gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL4", 0, 4, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL5", 0, 5, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL6", 0, 6, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL7", 0, 7, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL8", 0, 8, { "gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL9", 0, 9, { "gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL10", 0, 10, { "gpio_in", "gpio_out", "s_pwm", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL11", 0, 11, { "gpio_in", "gpio_out", NULL, NULL, NULL, "eint" } },
|
||||
{ "PL12", 0, 12, { "gpio_in", "gpio_out", "s_cir", NULL, NULL, NULL, "eint" } },
|
||||
};
|
||||
|
||||
const struct sunxi_gpio_padconf sun8i_a83t_padconf = {
|
||||
.npins = __arraycount(a83t_pins),
|
||||
.pins = a83t_pins,
|
||||
};
|
||||
|
||||
const struct sunxi_gpio_padconf sun8i_a83t_r_padconf = {
|
||||
.npins = __arraycount(a83t_r_pins),
|
||||
.pins = a83t_r_pins,
|
||||
};
|
|
@ -0,0 +1,302 @@
|
|||
/* $NetBSD: sun8i_h3_ccu.c,v 1.8.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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>
|
||||
|
||||
__KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu.c,v 1.8.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
#include <arm/sunxi/sun8i_h3_ccu.h>
|
||||
|
||||
#define PLL_PERIPH0_CTRL_REG 0x028
|
||||
#define AHB1_APB1_CFG_REG 0x054
|
||||
#define APB2_CFG_REG 0x058
|
||||
#define AHB2_CFG_REG 0x05c
|
||||
#define AHB2_CLK_CFG __BITS(1,0)
|
||||
#define AHB2_CLK_CFG_PLL_PERIPH0_2 1
|
||||
#define BUS_CLK_GATING_REG0 0x060
|
||||
#define BUS_CLK_GATING_REG2 0x068
|
||||
#define BUS_CLK_GATING_REG3 0x06c
|
||||
#define SDMMC0_CLK_REG 0x088
|
||||
#define SDMMC1_CLK_REG 0x08c
|
||||
#define SDMMC2_CLK_REG 0x090
|
||||
#define USBPHY_CFG_REG 0x0cc
|
||||
#define MBUS_RST_REG 0x0fc
|
||||
#define BUS_SOFT_RST_REG0 0x2c0
|
||||
#define BUS_SOFT_RST_REG1 0x2c4
|
||||
#define BUS_SOFT_RST_REG2 0x2c8
|
||||
#define BUS_SOFT_RST_REG3 0x2d0
|
||||
#define BUS_SOFT_RST_REG4 0x2d8
|
||||
|
||||
static int sun8i_h3_ccu_match(device_t, cfdata_t, void *);
|
||||
static void sun8i_h3_ccu_attach(device_t, device_t, void *);
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"allwinner,sun8i-h3-ccu",
|
||||
NULL
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_h3_ccu, sizeof(struct sunxi_ccu_softc),
|
||||
sun8i_h3_ccu_match, sun8i_h3_ccu_attach, NULL, NULL);
|
||||
|
||||
static struct sunxi_ccu_reset sun8i_h3_ccu_resets[] = {
|
||||
SUNXI_CCU_RESET(H3_RST_USB_PHY0, USBPHY_CFG_REG, 0),
|
||||
SUNXI_CCU_RESET(H3_RST_USB_PHY1, USBPHY_CFG_REG, 1),
|
||||
SUNXI_CCU_RESET(H3_RST_USB_PHY2, USBPHY_CFG_REG, 2),
|
||||
SUNXI_CCU_RESET(H3_RST_USB_PHY3, USBPHY_CFG_REG, 3),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_MBUS, MBUS_RST_REG, 31),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_CE, BUS_SOFT_RST_REG0, 5),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DMA, BUS_SOFT_RST_REG0, 6),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_MMC0, BUS_SOFT_RST_REG0, 8),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_MMC1, BUS_SOFT_RST_REG0, 9),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_MMC2, BUS_SOFT_RST_REG0, 10),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_NAND, BUS_SOFT_RST_REG0, 13),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DRAM, BUS_SOFT_RST_REG0, 14),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EMAC, BUS_SOFT_RST_REG0, 17),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_TS, BUS_SOFT_RST_REG0, 18),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_HSTIMER, BUS_SOFT_RST_REG0, 19),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SPI0, BUS_SOFT_RST_REG0, 20),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SPI1, BUS_SOFT_RST_REG0, 21),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OTG, BUS_SOFT_RST_REG0, 23),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EHCI0, BUS_SOFT_RST_REG0, 24),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EHCI1, BUS_SOFT_RST_REG0, 25),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EHCI2, BUS_SOFT_RST_REG0, 26),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EHCI3, BUS_SOFT_RST_REG0, 27),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OHCI0, BUS_SOFT_RST_REG0, 28),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OHCI1, BUS_SOFT_RST_REG0, 29),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OHCI2, BUS_SOFT_RST_REG0, 30),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_OHCI3, BUS_SOFT_RST_REG0, 31),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_VE, BUS_SOFT_RST_REG1, 0),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_TCON0, BUS_SOFT_RST_REG1, 3),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_TCON1, BUS_SOFT_RST_REG1, 4),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DEINTERLACE, BUS_SOFT_RST_REG1, 5),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_CSI, BUS_SOFT_RST_REG1, 8),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_TVE, BUS_SOFT_RST_REG1, 9),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_HDMI0, BUS_SOFT_RST_REG1, 10),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_HDMI1, BUS_SOFT_RST_REG1, 11),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DE, BUS_SOFT_RST_REG1, 12),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_GPU, BUS_SOFT_RST_REG1, 20),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_MSGBOX, BUS_SOFT_RST_REG1, 21),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SPINLOCK, BUS_SOFT_RST_REG1, 22),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_DBG, BUS_SOFT_RST_REG1, 31),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_EPHY, BUS_SOFT_RST_REG2, 2),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_CODEC, BUS_SOFT_RST_REG3, 0),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SPDIF, BUS_SOFT_RST_REG3, 1),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_THS, BUS_SOFT_RST_REG3, 8),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2S0, BUS_SOFT_RST_REG3, 12),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2S1, BUS_SOFT_RST_REG3, 13),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2S2, BUS_SOFT_RST_REG3, 14),
|
||||
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2C0, BUS_SOFT_RST_REG4, 0),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2C1, BUS_SOFT_RST_REG4, 1),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_I2C2, BUS_SOFT_RST_REG4, 2),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_UART0, BUS_SOFT_RST_REG4, 16),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_UART1, BUS_SOFT_RST_REG4, 17),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_UART2, BUS_SOFT_RST_REG4, 18),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_UART3, BUS_SOFT_RST_REG4, 19),
|
||||
SUNXI_CCU_RESET(H3_RST_BUS_SCR, BUS_SOFT_RST_REG4, 20),
|
||||
};
|
||||
|
||||
static const char *ahb1_parents[] = { "losc", "hosc", "axi", "pll_periph0" };
|
||||
static const char *ahb2_parents[] = { "ahb1", "pll_periph0" };
|
||||
static const char *apb1_parents[] = { "ahb1" };
|
||||
static const char *apb2_parents[] = { "losc", "hosc", "pll_periph0" };
|
||||
static const char *mod_parents[] = { "hosc", "pll_periph0", "pll_periph1" };
|
||||
|
||||
static struct sunxi_ccu_clk sun8i_h3_ccu_clks[] = {
|
||||
SUNXI_CCU_NKMP(H3_CLK_PLL_PERIPH0, "pll_periph0", "hosc",
|
||||
PLL_PERIPH0_CTRL_REG, /* reg */
|
||||
__BITS(12,8), /* n */
|
||||
__BITS(5,4), /* k */
|
||||
0, /* m */
|
||||
__BITS(17,16), /* p */
|
||||
__BIT(31), /* enable */
|
||||
SUNXI_CCU_NKMP_DIVIDE_BY_TWO),
|
||||
|
||||
SUNXI_CCU_PREDIV(H3_CLK_AHB1, "ahb1", ahb1_parents,
|
||||
AHB1_APB1_CFG_REG, /* reg */
|
||||
__BITS(7,6), /* prediv */
|
||||
__BIT(3), /* prediv_sel */
|
||||
__BITS(5,4), /* div */
|
||||
__BITS(13,12), /* sel */
|
||||
SUNXI_CCU_PREDIV_POWER_OF_TWO),
|
||||
|
||||
SUNXI_CCU_PREDIV(H3_CLK_AHB2, "ahb2", ahb2_parents,
|
||||
AHB2_CFG_REG, /* reg */
|
||||
0, /* prediv */
|
||||
__BIT(1), /* prediv_sel */
|
||||
0, /* div */
|
||||
__BITS(1,0), /* sel */
|
||||
SUNXI_CCU_PREDIV_DIVIDE_BY_TWO),
|
||||
|
||||
SUNXI_CCU_DIV(H3_CLK_APB1, "apb1", apb1_parents,
|
||||
AHB1_APB1_CFG_REG, /* reg */
|
||||
__BITS(9,8), /* div */
|
||||
0, /* sel */
|
||||
SUNXI_CCU_DIV_POWER_OF_TWO|SUNXI_CCU_DIV_ZERO_IS_ONE),
|
||||
|
||||
SUNXI_CCU_NM(H3_CLK_APB2, "apb2", apb2_parents,
|
||||
APB2_CFG_REG, /* reg */
|
||||
__BITS(17,16), /* n */
|
||||
__BITS(4,0), /* m */
|
||||
__BITS(25,24), /* sel */
|
||||
0, /* enable */
|
||||
SUNXI_CCU_NM_POWER_OF_TWO),
|
||||
|
||||
SUNXI_CCU_NM(H3_CLK_MMC0, "mmc0", mod_parents,
|
||||
SDMMC0_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
SUNXI_CCU_NM(H3_CLK_MMC1, "mmc1", mod_parents,
|
||||
SDMMC1_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
SUNXI_CCU_NM(H3_CLK_MMC2, "mmc2", mod_parents,
|
||||
SDMMC2_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
|
||||
SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
|
||||
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_MMC0, "bus-mmc0", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 8),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_MMC1, "bus-mmc1", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 9),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_MMC2, "bus-mmc2", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 10),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EMAC, "bus-emac", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 17),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OTG, "bus-otg", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 23),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI0, "bus-ehci0", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 24),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI1, "bus-ehci1", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 25),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI2, "bus-ehci2", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 26),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI3, "bus-ehci3", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 27),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OHCI0, "bus-ohci0", "ahb1",
|
||||
BUS_CLK_GATING_REG0, 28),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OHCI1, "bus-ohci1", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 29),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OHCI2, "bus-ohci2", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 30),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_OHCI3, "bus-ohci3", "ahb2",
|
||||
BUS_CLK_GATING_REG0, 31),
|
||||
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_PIO, "bus-pio", "apb1",
|
||||
BUS_CLK_GATING_REG2, 5),
|
||||
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_I2C0, "bus-i2c0", "apb2",
|
||||
BUS_CLK_GATING_REG3, 0),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_I2C1, "bus-i2c1", "apb2",
|
||||
BUS_CLK_GATING_REG3, 1),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_I2C2, "bus-i2c2", "apb2",
|
||||
BUS_CLK_GATING_REG3, 2),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_UART0, "bus-uart0", "apb2",
|
||||
BUS_CLK_GATING_REG3, 16),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_UART1, "bus-uart1", "apb2",
|
||||
BUS_CLK_GATING_REG3, 17),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_UART2, "bus-uart2", "apb2",
|
||||
BUS_CLK_GATING_REG3, 18),
|
||||
SUNXI_CCU_GATE(H3_CLK_BUS_UART3, "bus-uart3", "apb2",
|
||||
BUS_CLK_GATING_REG3, 19),
|
||||
|
||||
SUNXI_CCU_GATE(H3_CLK_USBPHY0, "usb-phy0", "hosc",
|
||||
USBPHY_CFG_REG, 8),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBPHY1, "usb-phy1", "hosc",
|
||||
USBPHY_CFG_REG, 9),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBPHY2, "usb-phy2", "hosc",
|
||||
USBPHY_CFG_REG, 10),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBPHY3, "usb-phy3", "hosc",
|
||||
USBPHY_CFG_REG, 11),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBOHCI0, "usb-ohci0", "hosc",
|
||||
USBPHY_CFG_REG, 16),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBOHCI1, "usb-ohci1", "hosc",
|
||||
USBPHY_CFG_REG, 17),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBOHCI2, "usb-ohci2", "hosc",
|
||||
USBPHY_CFG_REG, 18),
|
||||
SUNXI_CCU_GATE(H3_CLK_USBOHCI3, "usb-ohci3", "hosc",
|
||||
USBPHY_CFG_REG, 19),
|
||||
};
|
||||
|
||||
static void
|
||||
sun8i_h3_ccu_init(struct sunxi_ccu_softc *sc)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/* Set AHB2 source to PLL_PERIPH/2 */
|
||||
val = CCU_READ(sc, AHB2_CFG_REG);
|
||||
val &= ~AHB2_CLK_CFG;
|
||||
val |= __SHIFTIN(AHB2_CLK_CFG_PLL_PERIPH0_2, AHB2_CLK_CFG);
|
||||
CCU_WRITE(sc, AHB2_CFG_REG, val);
|
||||
}
|
||||
|
||||
static int
|
||||
sun8i_h3_ccu_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sun8i_h3_ccu_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_phandle = faa->faa_phandle;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
|
||||
sc->sc_resets = sun8i_h3_ccu_resets;
|
||||
sc->sc_nresets = __arraycount(sun8i_h3_ccu_resets);
|
||||
|
||||
sc->sc_clks = sun8i_h3_ccu_clks;
|
||||
sc->sc_nclks = __arraycount(sun8i_h3_ccu_clks);
|
||||
|
||||
if (sunxi_ccu_attach(sc) != 0)
|
||||
return;
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": H3 CCU\n");
|
||||
|
||||
sun8i_h3_ccu_init(sc);
|
||||
|
||||
sunxi_ccu_print(sc);
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
/* $NetBSD: sun8i_h3_ccu.h,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Emmanuel Vadot <manu@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$
|
||||
*/
|
||||
|
||||
#ifndef __CCU_H3_H__
|
||||
#define __CCU_H3_H__
|
||||
|
||||
#define H3_RST_USB_PHY0 0
|
||||
#define H3_RST_USB_PHY1 1
|
||||
#define H3_RST_USB_PHY2 2
|
||||
#define H3_RST_USB_PHY3 3
|
||||
#define H3_RST_MBUS 4
|
||||
#define H3_RST_BUS_CE 5
|
||||
#define H3_RST_BUS_DMA 6
|
||||
#define H3_RST_BUS_MMC0 7
|
||||
#define H3_RST_BUS_MMC1 8
|
||||
#define H3_RST_BUS_MMC2 9
|
||||
#define H3_RST_BUS_NAND 10
|
||||
#define H3_RST_BUS_DRAM 11
|
||||
#define H3_RST_BUS_EMAC 12
|
||||
#define H3_RST_BUS_TS 13
|
||||
#define H3_RST_BUS_HSTIMER 14
|
||||
#define H3_RST_BUS_SPI0 15
|
||||
#define H3_RST_BUS_SPI1 16
|
||||
#define H3_RST_BUS_OTG 17
|
||||
#define H3_RST_BUS_EHCI0 18
|
||||
#define H3_RST_BUS_EHCI1 19
|
||||
#define H3_RST_BUS_EHCI2 20
|
||||
#define H3_RST_BUS_EHCI3 21
|
||||
#define H3_RST_BUS_OHCI0 22
|
||||
#define H3_RST_BUS_OHCI1 23
|
||||
#define H3_RST_BUS_OHCI2 24
|
||||
#define H3_RST_BUS_OHCI3 25
|
||||
#define H3_RST_BUS_VE 26
|
||||
#define H3_RST_BUS_TCON0 27
|
||||
#define H3_RST_BUS_TCON1 28
|
||||
#define H3_RST_BUS_DEINTERLACE 29
|
||||
#define H3_RST_BUS_CSI 30
|
||||
#define H3_RST_BUS_TVE 31
|
||||
#define H3_RST_BUS_HDMI0 32
|
||||
#define H3_RST_BUS_HDMI1 33
|
||||
#define H3_RST_BUS_DE 34
|
||||
#define H3_RST_BUS_GPU 35
|
||||
#define H3_RST_BUS_MSGBOX 36
|
||||
#define H3_RST_BUS_SPINLOCK 37
|
||||
#define H3_RST_BUS_DBG 38
|
||||
#define H3_RST_BUS_EPHY 39
|
||||
#define H3_RST_BUS_CODEC 40
|
||||
#define H3_RST_BUS_SPDIF 41
|
||||
#define H3_RST_BUS_THS 42
|
||||
#define H3_RST_BUS_I2S0 43
|
||||
#define H3_RST_BUS_I2S1 44
|
||||
#define H3_RST_BUS_I2S2 45
|
||||
#define H3_RST_BUS_I2C0 46
|
||||
#define H3_RST_BUS_I2C1 47
|
||||
#define H3_RST_BUS_I2C2 48
|
||||
#define H3_RST_BUS_UART0 49
|
||||
#define H3_RST_BUS_UART1 50
|
||||
#define H3_RST_BUS_UART2 51
|
||||
#define H3_RST_BUS_UART3 52
|
||||
#define H3_RST_BUS_SCR 53
|
||||
|
||||
#define H3_CLK_PLL_CPUX 0
|
||||
#define H3_CLK_PLL_AUDIO_BASE 1
|
||||
#define H3_CLK_PLL_AUDIO 2
|
||||
#define H3_CLK_PLL_AUDIO_2X 3
|
||||
#define H3_CLK_PLL_AUDIO_4X 4
|
||||
#define H3_CLK_PLL_AUDIO_8X 5
|
||||
#define H3_CLK_PLL_VIDEO 6
|
||||
#define H3_CLK_PLL_VE 7
|
||||
#define H3_CLK_PLL_DDR 8
|
||||
#define H3_CLK_PLL_PERIPH0 9
|
||||
#define H3_CLK_PLL_PERIPH0_2X 10
|
||||
#define H3_CLK_PLL_GPU 11
|
||||
#define H3_CLK_PLL_PERIPH1 12
|
||||
#define H3_CLK_PLL_DE 13
|
||||
#define H3_CLK_CPUX 14
|
||||
#define H3_CLK_AXI 15
|
||||
#define H3_CLK_AHB1 16
|
||||
#define H3_CLK_APB1 17
|
||||
#define H3_CLK_APB2 18
|
||||
#define H3_CLK_AHB2 19
|
||||
#define H3_CLK_BUS_CE 20
|
||||
#define H3_CLK_BUS_DMA 21
|
||||
#define H3_CLK_BUS_MMC0 22
|
||||
#define H3_CLK_BUS_MMC1 23
|
||||
#define H3_CLK_BUS_MMC2 24
|
||||
#define H3_CLK_BUS_NAND 25
|
||||
#define H3_CLK_BUS_DRAM 26
|
||||
#define H3_CLK_BUS_EMAC 27
|
||||
#define H3_CLK_BUS_TS 28
|
||||
#define H3_CLK_BUS_HSTIMER 29
|
||||
#define H3_CLK_BUS_SPI0 30
|
||||
#define H3_CLK_BUS_SPI1 31
|
||||
#define H3_CLK_BUS_OTG 32
|
||||
#define H3_CLK_BUS_EHCI0 33
|
||||
#define H3_CLK_BUS_EHCI1 34
|
||||
#define H3_CLK_BUS_EHCI2 35
|
||||
#define H3_CLK_BUS_EHCI3 36
|
||||
#define H3_CLK_BUS_OHCI0 37
|
||||
#define H3_CLK_BUS_OHCI1 38
|
||||
#define H3_CLK_BUS_OHCI2 39
|
||||
#define H3_CLK_BUS_OHCI3 40
|
||||
#define H3_CLK_BUS_VE 41
|
||||
#define H3_CLK_BUS_TCON0 42
|
||||
#define H3_CLK_BUS_TCON1 43
|
||||
#define H3_CLK_BUS_DEINTERLACE 44
|
||||
#define H3_CLK_BUS_CSI 45
|
||||
#define H3_CLK_BUS_TVE 46
|
||||
#define H3_CLK_BUS_HDMI 47
|
||||
#define H3_CLK_BUS_DE 48
|
||||
#define H3_CLK_BUS_GPU 49
|
||||
#define H3_CLK_BUS_MSGBOX 50
|
||||
#define H3_CLK_BUS_SPINLOCK 51
|
||||
#define H3_CLK_BUS_CODEC 52
|
||||
#define H3_CLK_BUS_SPDIF 53
|
||||
#define H3_CLK_BUS_PIO 54
|
||||
#define H3_CLK_BUS_THS 55
|
||||
#define H3_CLK_BUS_I2S0 56
|
||||
#define H3_CLK_BUS_I2S1 57
|
||||
#define H3_CLK_BUS_I2S2 58
|
||||
#define H3_CLK_BUS_I2C0 59
|
||||
#define H3_CLK_BUS_I2C1 60
|
||||
#define H3_CLK_BUS_I2C2 61
|
||||
#define H3_CLK_BUS_UART0 62
|
||||
#define H3_CLK_BUS_UART1 63
|
||||
#define H3_CLK_BUS_UART2 64
|
||||
#define H3_CLK_BUS_UART3 65
|
||||
#define H3_CLK_BUS_SCR 66
|
||||
#define H3_CLK_BUS_EPHY 67
|
||||
#define H3_CLK_BUS_DBG 68
|
||||
#define H3_CLK_THS 69
|
||||
#define H3_CLK_NAND 70
|
||||
#define H3_CLK_MMC0 71
|
||||
#define H3_CLK_MMC0_SAMPLE 72
|
||||
#define H3_CLK_MMC0_OUTPUT 73
|
||||
#define H3_CLK_MMC1 74
|
||||
#define H3_CLK_MMC1_SAMPLE 75
|
||||
#define H3_CLK_MMC1_OUTPUT 76
|
||||
#define H3_CLK_MMC2 77
|
||||
#define H3_CLK_MMC2_SAMPLE 78
|
||||
#define H3_CLK_MMC2_OUTPUT 79
|
||||
#define H3_CLK_TS 80
|
||||
#define H3_CLK_CE 81
|
||||
#define H3_CLK_SPI0 82
|
||||
#define H3_CLK_SPI1 83
|
||||
#define H3_CLK_I2S0 84
|
||||
#define H3_CLK_I2S1 85
|
||||
#define H3_CLK_I2S2 86
|
||||
#define H3_CLK_SPDIF 87
|
||||
#define H3_CLK_USBPHY0 88
|
||||
#define H3_CLK_USBPHY1 89
|
||||
#define H3_CLK_USBPHY2 90
|
||||
#define H3_CLK_USBPHY3 91
|
||||
#define H3_CLK_USBOHCI0 92
|
||||
#define H3_CLK_USBOHCI1 93
|
||||
#define H3_CLK_USBOHCI2 94
|
||||
#define H3_CLK_USBOHCI3 95
|
||||
#define H3_CLK_DRAM 96
|
||||
#define H3_CLK_DRAM_VE 97
|
||||
#define H3_CLK_DRAM_CSI 98
|
||||
#define H3_CLK_DRAM_DEINTERLACE 99
|
||||
#define H3_CLK_DRAM_TS 100
|
||||
#define H3_CLK_DE 101
|
||||
#define H3_CLK_TCON0 102
|
||||
#define H3_CLK_TVE 103
|
||||
#define H3_CLK_DEINTERLACE 104
|
||||
#define H3_CLK_CSI_MISC 105
|
||||
#define H3_CLK_CSI_SCLK 106
|
||||
#define H3_CLK_CSI_MCLK 107
|
||||
#define H3_CLK_VE 108
|
||||
#define H3_CLK_AC_DIG 109
|
||||
#define H3_CLK_AVS 110
|
||||
#define H3_CLK_HDMI 111
|
||||
#define H3_CLK_HDMI_DDC 112
|
||||
#define H3_CLK_MBUS 113
|
||||
#define H3_CLK_GPU 114
|
||||
|
||||
#endif /* __CCU_H3_H__ */
|
|
@ -0,0 +1,165 @@
|
|||
/* $NetBSD: sun8i_h3_gpio.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 Emmanuel Vadot <manu@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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sun8i_h3_gpio.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_gpio.h>
|
||||
|
||||
static const struct sunxi_gpio_pins h3_pins[] = {
|
||||
{"PA0", 0, 0, {"gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "pa_eint0", NULL}, 6, 0},
|
||||
{"PA1", 0, 1, {"gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "pa_eint1", NULL}, 6, 1},
|
||||
{"PA2", 0, 2, {"gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "pa_eint2", NULL}, 6, 2},
|
||||
{"PA3", 0, 3, {"gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "pa_eint3", NULL}, 6, 3},
|
||||
{"PA4", 0, 4, {"gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "pa_eint4", NULL}, 6, 4},
|
||||
{"PA5", 0, 5, {"gpio_in", "gpio_out", "uart0", "pwm0", NULL, NULL, "pa_eint5", NULL}, 6, 5},
|
||||
{"PA6", 0, 6, {"gpio_in", "gpio_out", "sim", NULL, NULL, NULL, "pa_eint6", NULL}, 6, 6},
|
||||
{"PA7", 0, 7, {"gpio_in", "gpio_out", "sim", NULL, NULL, NULL, "pa_eint7", NULL}, 6, 7},
|
||||
{"PA8", 0, 8, {"gpio_in", "gpio_out", "sim", NULL, NULL, NULL, "pa_eint8", NULL}, 6, 8},
|
||||
{"PA9", 0, 9, {"gpio_in", "gpio_out", "sim", NULL, NULL, NULL, "pa_eint9", NULL}, 6, 9},
|
||||
{"PA10", 0, 10, {"gpio_in", "gpio_out", "sim", NULL, NULL, NULL, "pa_eint10", NULL}, 6, 10},
|
||||
{"PA11", 0, 11, {"gpio_in", "gpio_out", "i2c0", "di", NULL, NULL, "pa_eint11", NULL}, 6, 11},
|
||||
{"PA12", 0, 12, {"gpio_in", "gpio_out", "i2c0", "di", NULL, NULL, "pa_eint12", NULL}, 6, 12},
|
||||
{"PA13", 0, 13, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "pa_eint13", NULL}, 6, 13},
|
||||
{"PA14", 0, 14, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "pa_eint14", NULL}, 6, 14},
|
||||
{"PA15", 0, 15, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "pa_eint15", NULL}, 6, 15},
|
||||
{"PA16", 0, 16, {"gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "pa_eint16", NULL}, 6, 16},
|
||||
{"PA17", 0, 17, {"gpio_in", "gpio_out", "spdif", NULL, NULL, NULL, "pa_eint17", NULL}, 6, 17},
|
||||
{"PA18", 0, 18, {"gpio_in", "gpio_out", "i2s0", "i2c1", NULL, NULL, "pa_eint18", NULL}, 6, 18},
|
||||
{"PA19", 0, 19, {"gpio_in", "gpio_out", "i2s0", "i2c1", NULL, NULL, "pa_eint19", NULL}, 6, 19},
|
||||
{"PA20", 0, 20, {"gpio_in", "gpio_out", "i2s0", "sim", NULL, NULL, "pa_eint20", NULL}, 6, 20},
|
||||
{"PA21", 0, 21, {"gpio_in", "gpio_out", "i2s0", "sim", NULL, NULL, "pa_eint21", NULL}, 6, 21},
|
||||
|
||||
{"PC0", 2, 0, {"gpio_in", "gpio_out", "nand", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC1", 2, 1, {"gpio_in", "gpio_out", "nand", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC2", 2, 2, {"gpio_in", "gpio_out", "nand", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC3", 2, 3, {"gpio_in", "gpio_out", "nand", "spi0", NULL, NULL, NULL, NULL}},
|
||||
{"PC4", 2, 4, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC5", 2, 5, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC6", 2, 6, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC7", 2, 7, {"gpio_in", "gpio_out", "nand", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PC8", 2, 8, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC9", 2, 9, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC10", 2, 10, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC11", 2, 11, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC12", 2, 12, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC13", 2, 13, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC14", 2, 14, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC15", 2, 15, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
{"PC16", 2, 16, {"gpio_in", "gpio_out", "nand", "mmc2", NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PD0", 3, 0, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD1", 3, 1, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD2", 3, 2, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD3", 3, 3, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD4", 3, 4, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD5", 3, 5, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD6", 3, 6, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD7", 3, 7, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD8", 3, 8, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD9", 3, 9, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD10", 3, 10, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD11", 3, 11, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD12", 3, 12, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD13", 3, 13, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD14", 3, 14, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD15", 3, 15, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD16", 3, 16, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PD17", 3, 17, {"gpio_in", "gpio_out", "emac", NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PE0", 4, 0, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE1", 4, 1, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE2", 4, 2, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE3", 4, 3, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE4", 4, 4, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE5", 4, 5, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE6", 4, 6, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE7", 4, 7, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE8", 4, 8, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE9", 4, 9, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE10", 4, 10, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE11", 4, 11, {"gpio_in", "gpio_out", "csi", "ts", NULL, NULL, NULL, NULL}},
|
||||
{"PE12", 4, 12, {"gpio_in", "gpio_out", "csi", "i2c2", NULL, NULL, NULL, NULL}},
|
||||
{"PE13", 4, 13, {"gpio_in", "gpio_out", "csi", "i2c2", NULL, NULL, NULL, NULL}},
|
||||
{"PE14", 4, 14, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
{"PE15", 4, 15, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PF0", 5, 0, {"gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, NULL, NULL}},
|
||||
{"PF1", 5, 1, {"gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, NULL, NULL}},
|
||||
{"PF2", 5, 2, {"gpio_in", "gpio_out", "mmc0", "uart0", NULL, NULL, NULL, NULL}},
|
||||
{"PF3", 5, 3, {"gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, NULL, NULL}},
|
||||
{"PF4", 5, 4, {"gpio_in", "gpio_out", "mmc0", "uart0", NULL, NULL, NULL, NULL}},
|
||||
{"PF5", 5, 5, {"gpio_in", "gpio_out", "mmc0", "jtag", NULL, NULL, NULL, NULL}},
|
||||
{"PF6", 5, 6, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, NULL, NULL}},
|
||||
|
||||
{"PG0", 6, 0, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint0", NULL}, 6, 0},
|
||||
{"PG1", 6, 1, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint1", NULL}, 6, 1},
|
||||
{"PG2", 6, 2, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint2", NULL}, 6, 2},
|
||||
{"PG3", 6, 3, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint3", NULL}, 6, 3},
|
||||
{"PG4", 6, 4, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint4", NULL}, 6, 4},
|
||||
{"PG5", 6, 5, {"gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "pg_eint5", NULL}, 6, 5},
|
||||
{"PG6", 6, 6, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint6", NULL}, 6, 6},
|
||||
{"PG7", 6, 7, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint7", NULL}, 6, 7},
|
||||
{"PG8", 6, 8, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint8", NULL}, 6, 8},
|
||||
{"PG9", 6, 9, {"gpio_in", "gpio_out", "uart1", NULL, NULL, NULL, "pg_eint9", NULL}, 6, 9},
|
||||
{"PG10", 6, 10, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint10", NULL}, 6, 10},
|
||||
{"PG11", 6, 11, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint11", NULL}, 6, 11},
|
||||
{"PG12", 6, 12, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint12", NULL}, 6, 12},
|
||||
{"PG13", 6, 13, {"gpio_in", "gpio_out", "i2s1", NULL, NULL, NULL, "pg_eint13", NULL}, 6, 13},
|
||||
};
|
||||
|
||||
static const struct sunxi_gpio_pins h3_r_pins[] = {
|
||||
{"PL0", 0, 0, {"gpio_in", "gpio_out", "s_twi", NULL, NULL, NULL, "pl_eint0", NULL}, 6, 0},
|
||||
{"PL1", 0, 1, {"gpio_in", "gpio_out", "s_twi", NULL, NULL, NULL, "pl_eint1", NULL}, 6, 1},
|
||||
{"PL2", 0, 2, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint2", NULL}, 6, 2},
|
||||
{"PL3", 0, 3, {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "pl_eint3", NULL}, 6, 3},
|
||||
{"PL4", 0, 4, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint4", NULL}, 6, 4},
|
||||
{"PL5", 0, 5, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint5", NULL}, 6, 5},
|
||||
{"PL6", 0, 6, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint6", NULL}, 6, 6},
|
||||
{"PL7", 0, 7, {"gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "pl_eint7", NULL}, 6, 7},
|
||||
{"PL8", 0, 8, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pl_eint8", NULL}, 6, 8},
|
||||
{"PL9", 0, 9, {"gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "pl_eint9", NULL}, 6, 9},
|
||||
{"PL10", 0, 10, {"gpio_in", "gpio_out", "s_pwm", NULL, NULL, NULL, "pl_eint10", NULL}, 6, 10},
|
||||
{"PL11", 0, 11, {"gpio_in", "gpio_out", "s_cir_rx", NULL, NULL, NULL, "pl_eint11", NULL}, 6, 11},
|
||||
};
|
||||
|
||||
const struct sunxi_gpio_padconf sun8i_h3_padconf = {
|
||||
.npins = __arraycount(h3_pins),
|
||||
.pins = h3_pins,
|
||||
};
|
||||
|
||||
const struct sunxi_gpio_padconf sun8i_h3_r_padconf = {
|
||||
.npins = __arraycount(h3_r_pins),
|
||||
.pins = h3_r_pins,
|
||||
};
|
|
@ -0,0 +1,344 @@
|
|||
/* $NetBSD: sunxi_ccu.c,v 1.6.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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_soc.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
#include "opt_fdt_arm.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu.c,v 1.6.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
|
||||
static void *
|
||||
sunxi_ccu_reset_acquire(device_t dev, const void *data, size_t len)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = device_private(dev);
|
||||
struct sunxi_ccu_reset *reset;
|
||||
|
||||
if (len != 4)
|
||||
return NULL;
|
||||
|
||||
const u_int reset_id = be32dec(data);
|
||||
|
||||
if (reset_id >= sc->sc_nresets)
|
||||
return NULL;
|
||||
|
||||
reset = &sc->sc_resets[reset_id];
|
||||
if (reset->mask == 0)
|
||||
return NULL;
|
||||
|
||||
return reset;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_ccu_reset_release(device_t dev, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_ccu_reset_assert(device_t dev, void *priv)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = device_private(dev);
|
||||
struct sunxi_ccu_reset * const reset = priv;
|
||||
|
||||
const uint32_t val = CCU_READ(sc, reset->reg);
|
||||
CCU_WRITE(sc, reset->reg, val & ~reset->mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_ccu_reset_deassert(device_t dev, void *priv)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = device_private(dev);
|
||||
struct sunxi_ccu_reset * const reset = priv;
|
||||
|
||||
const uint32_t val = CCU_READ(sc, reset->reg);
|
||||
CCU_WRITE(sc, reset->reg, val | reset->mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fdtbus_reset_controller_func sunxi_ccu_fdtreset_funcs = {
|
||||
.acquire = sunxi_ccu_reset_acquire,
|
||||
.release = sunxi_ccu_reset_release,
|
||||
.reset_assert = sunxi_ccu_reset_assert,
|
||||
.reset_deassert = sunxi_ccu_reset_deassert,
|
||||
};
|
||||
|
||||
static struct clk *
|
||||
sunxi_ccu_clock_decode(device_t dev, const void *data, size_t len)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = device_private(dev);
|
||||
struct sunxi_ccu_clk *clk;
|
||||
|
||||
if (len != 4)
|
||||
return NULL;
|
||||
|
||||
const u_int clock_id = be32dec(data);
|
||||
if (clock_id >= sc->sc_nclks)
|
||||
return NULL;
|
||||
|
||||
clk = &sc->sc_clks[clock_id];
|
||||
if (clk->type == SUNXI_CCU_UNKNOWN)
|
||||
return NULL;
|
||||
|
||||
return &clk->base;
|
||||
}
|
||||
|
||||
static const struct fdtbus_clock_controller_func sunxi_ccu_fdtclock_funcs = {
|
||||
.decode = sunxi_ccu_clock_decode,
|
||||
};
|
||||
|
||||
static struct clk *
|
||||
sunxi_ccu_clock_get(void *priv, const char *name)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = priv;
|
||||
struct sunxi_ccu_clk *clk;
|
||||
|
||||
clk = sunxi_ccu_clock_find(sc, name);
|
||||
if (clk == NULL)
|
||||
return NULL;
|
||||
|
||||
return &clk->base;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_ccu_clock_put(void *priv, struct clk *clk)
|
||||
{
|
||||
}
|
||||
|
||||
static u_int
|
||||
sunxi_ccu_clock_get_rate(void *priv, struct clk *clkp)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = priv;
|
||||
struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
|
||||
struct clk *clkp_parent;
|
||||
|
||||
if (clk->get_rate)
|
||||
return clk->get_rate(sc, clk);
|
||||
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL) {
|
||||
aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return clk_get_rate(clkp_parent);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_ccu_clock_set_rate(void *priv, struct clk *clkp, u_int rate)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = priv;
|
||||
struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
|
||||
struct clk *clkp_parent;
|
||||
|
||||
if (clkp->flags & CLK_SET_RATE_PARENT) {
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL) {
|
||||
aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
|
||||
return ENXIO;
|
||||
}
|
||||
return clk_set_rate(clkp_parent, rate);
|
||||
}
|
||||
|
||||
if (clk->set_rate)
|
||||
return clk->set_rate(sc, clk, rate);
|
||||
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_ccu_clock_enable(void *priv, struct clk *clkp)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = priv;
|
||||
struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
|
||||
struct clk *clkp_parent;
|
||||
int error = 0;
|
||||
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent != NULL) {
|
||||
error = clk_enable(clkp_parent);
|
||||
if (error != 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (clk->enable)
|
||||
error = clk->enable(sc, clk, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_ccu_clock_disable(void *priv, struct clk *clkp)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = priv;
|
||||
struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
|
||||
int error = EINVAL;
|
||||
|
||||
if (clk->enable)
|
||||
error = clk->enable(sc, clk, 0);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_ccu_clock_set_parent(void *priv, struct clk *clkp,
|
||||
struct clk *clkp_parent)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = priv;
|
||||
struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
|
||||
|
||||
if (clk->set_parent == NULL)
|
||||
return EINVAL;
|
||||
|
||||
return clk->set_parent(sc, clk, clkp_parent->name);
|
||||
}
|
||||
|
||||
static struct clk *
|
||||
sunxi_ccu_clock_get_parent(void *priv, struct clk *clkp)
|
||||
{
|
||||
struct sunxi_ccu_softc * const sc = priv;
|
||||
struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
|
||||
struct sunxi_ccu_clk *clk_parent;
|
||||
const char *parent;
|
||||
|
||||
if (clk->get_parent == NULL)
|
||||
return NULL;
|
||||
|
||||
parent = clk->get_parent(sc, clk);
|
||||
if (parent == NULL)
|
||||
return NULL;
|
||||
|
||||
clk_parent = sunxi_ccu_clock_find(sc, parent);
|
||||
if (clk_parent != NULL)
|
||||
return &clk_parent->base;
|
||||
|
||||
/* No parent in this domain, try FDT */
|
||||
return fdtbus_clock_get(sc->sc_phandle, parent);
|
||||
}
|
||||
|
||||
static const struct clk_funcs sunxi_ccu_clock_funcs = {
|
||||
.get = sunxi_ccu_clock_get,
|
||||
.put = sunxi_ccu_clock_put,
|
||||
.get_rate = sunxi_ccu_clock_get_rate,
|
||||
.set_rate = sunxi_ccu_clock_set_rate,
|
||||
.enable = sunxi_ccu_clock_enable,
|
||||
.disable = sunxi_ccu_clock_disable,
|
||||
.set_parent = sunxi_ccu_clock_set_parent,
|
||||
.get_parent = sunxi_ccu_clock_get_parent,
|
||||
};
|
||||
|
||||
struct sunxi_ccu_clk *
|
||||
sunxi_ccu_clock_find(struct sunxi_ccu_softc *sc, const char *name)
|
||||
{
|
||||
for (int i = 0; i < sc->sc_nclks; i++) {
|
||||
if (sc->sc_clks[i].base.name == NULL)
|
||||
continue;
|
||||
if (strcmp(sc->sc_clks[i].base.name, name) == 0)
|
||||
return &sc->sc_clks[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
sunxi_ccu_attach(struct sunxi_ccu_softc *sc)
|
||||
{
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
int i;
|
||||
|
||||
if (fdtbus_get_reg(sc->sc_phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return ENXIO;
|
||||
}
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
sc->sc_clkdom.funcs = &sunxi_ccu_clock_funcs;
|
||||
sc->sc_clkdom.priv = sc;
|
||||
for (i = 0; i < sc->sc_nclks; i++)
|
||||
sc->sc_clks[i].base.domain = &sc->sc_clkdom;
|
||||
|
||||
fdtbus_register_clock_controller(sc->sc_dev, sc->sc_phandle,
|
||||
&sunxi_ccu_fdtclock_funcs);
|
||||
|
||||
fdtbus_register_reset_controller(sc->sc_dev, sc->sc_phandle,
|
||||
&sunxi_ccu_fdtreset_funcs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
sunxi_ccu_print(struct sunxi_ccu_softc *sc)
|
||||
{
|
||||
struct sunxi_ccu_clk *clk;
|
||||
struct clk *clkp_parent;
|
||||
const char *type;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc->sc_nclks; i++) {
|
||||
clk = &sc->sc_clks[i];
|
||||
if (clk->type == SUNXI_CCU_UNKNOWN)
|
||||
continue;
|
||||
|
||||
clkp_parent = clk_get_parent(&clk->base);
|
||||
|
||||
switch (clk->type) {
|
||||
case SUNXI_CCU_GATE: type = "gate"; break;
|
||||
case SUNXI_CCU_NM: type = "nm"; break;
|
||||
case SUNXI_CCU_NKMP: type = "nkmp"; break;
|
||||
case SUNXI_CCU_PREDIV: type = "prediv"; break;
|
||||
case SUNXI_CCU_DIV: type = "div"; break;
|
||||
default: type = "???"; break;
|
||||
}
|
||||
|
||||
aprint_debug_dev(sc->sc_dev,
|
||||
"%3d %-12s %2s %-12s %-7s ",
|
||||
i,
|
||||
clk->base.name,
|
||||
clkp_parent ? "<-" : "",
|
||||
clkp_parent ? clkp_parent->name : "",
|
||||
type);
|
||||
aprint_debug("%10d Hz\n", clk_get_rate(&clk->base));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,304 @@
|
|||
/* $NetBSD: sunxi_ccu.h,v 1.7.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_SUNXI_CCU_H
|
||||
#define _ARM_SUNXI_CCU_H
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
struct sunxi_ccu_softc;
|
||||
struct sunxi_ccu_clk;
|
||||
struct sunxi_ccu_reset;
|
||||
|
||||
/*
|
||||
* Resets
|
||||
*/
|
||||
|
||||
struct sunxi_ccu_reset {
|
||||
bus_size_t reg;
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
#define SUNXI_CCU_RESET(_id, _reg, _bit) \
|
||||
[_id] = { \
|
||||
.reg = (_reg), \
|
||||
.mask = __BIT(_bit), \
|
||||
}
|
||||
|
||||
/*
|
||||
* Clocks
|
||||
*/
|
||||
|
||||
enum sunxi_ccu_clktype {
|
||||
SUNXI_CCU_UNKNOWN,
|
||||
SUNXI_CCU_GATE,
|
||||
SUNXI_CCU_NM,
|
||||
SUNXI_CCU_NKMP,
|
||||
SUNXI_CCU_PREDIV,
|
||||
SUNXI_CCU_DIV,
|
||||
};
|
||||
|
||||
struct sunxi_ccu_gate {
|
||||
bus_size_t reg;
|
||||
uint32_t mask;
|
||||
const char *parent;
|
||||
};
|
||||
|
||||
int sunxi_ccu_gate_enable(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, int);
|
||||
const char *sunxi_ccu_gate_get_parent(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
|
||||
#define SUNXI_CCU_GATE(_id, _name, _pname, _reg, _bit) \
|
||||
[_id] = { \
|
||||
.type = SUNXI_CCU_GATE, \
|
||||
.base.name = (_name), \
|
||||
.u.gate.parent = (_pname), \
|
||||
.u.gate.reg = (_reg), \
|
||||
.u.gate.mask = __BIT(_bit), \
|
||||
.enable = sunxi_ccu_gate_enable, \
|
||||
.get_parent = sunxi_ccu_gate_get_parent, \
|
||||
}
|
||||
|
||||
struct sunxi_ccu_nkmp {
|
||||
bus_size_t reg;
|
||||
const char *parent;
|
||||
uint32_t n;
|
||||
uint32_t k;
|
||||
uint32_t m;
|
||||
uint32_t p;
|
||||
uint32_t lock;
|
||||
uint32_t enable;
|
||||
uint32_t flags;
|
||||
#define SUNXI_CCU_NKMP_DIVIDE_BY_TWO __BIT(0)
|
||||
#define SUNXI_CCU_NKMP_FACTOR_N_EXACT __BIT(1)
|
||||
};
|
||||
|
||||
int sunxi_ccu_nkmp_enable(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, int);
|
||||
u_int sunxi_ccu_nkmp_get_rate(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
int sunxi_ccu_nkmp_set_rate(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, u_int);
|
||||
const char *sunxi_ccu_nkmp_get_parent(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
|
||||
#define SUNXI_CCU_NKMP(_id, _name, _parent, _reg, _n, _k, _m, \
|
||||
_p, _enable, _flags) \
|
||||
[_id] = { \
|
||||
.type = SUNXI_CCU_NKMP, \
|
||||
.base.name = (_name), \
|
||||
.u.nkmp.reg = (_reg), \
|
||||
.u.nkmp.parent = (_parent), \
|
||||
.u.nkmp.n = (_n), \
|
||||
.u.nkmp.k = (_k), \
|
||||
.u.nkmp.m = (_m), \
|
||||
.u.nkmp.p = (_p), \
|
||||
.u.nkmp.enable = (_enable), \
|
||||
.u.nkmp.flags = (_flags), \
|
||||
.enable = sunxi_ccu_nkmp_enable, \
|
||||
.get_rate = sunxi_ccu_nkmp_get_rate, \
|
||||
.set_rate = sunxi_ccu_nkmp_set_rate, \
|
||||
.get_parent = sunxi_ccu_nkmp_get_parent, \
|
||||
}
|
||||
|
||||
struct sunxi_ccu_nm {
|
||||
bus_size_t reg;
|
||||
const char **parents;
|
||||
u_int nparents;
|
||||
uint32_t n;
|
||||
uint32_t m;
|
||||
uint32_t sel;
|
||||
uint32_t enable;
|
||||
uint32_t flags;
|
||||
#define SUNXI_CCU_NM_POWER_OF_TWO __BIT(0)
|
||||
#define SUNXI_CCU_NM_ROUND_DOWN __BIT(1)
|
||||
};
|
||||
|
||||
int sunxi_ccu_nm_enable(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, int);
|
||||
u_int sunxi_ccu_nm_get_rate(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
int sunxi_ccu_nm_set_rate(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, u_int);
|
||||
int sunxi_ccu_nm_set_parent(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *,
|
||||
const char *);
|
||||
const char *sunxi_ccu_nm_get_parent(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
|
||||
#define SUNXI_CCU_NM(_id, _name, _parents, _reg, _n, _m, _sel, \
|
||||
_enable, _flags) \
|
||||
[_id] = { \
|
||||
.type = SUNXI_CCU_NM, \
|
||||
.base.name = (_name), \
|
||||
.u.nm.reg = (_reg), \
|
||||
.u.nm.parents = (_parents), \
|
||||
.u.nm.nparents = __arraycount(_parents), \
|
||||
.u.nm.n = (_n), \
|
||||
.u.nm.m = (_m), \
|
||||
.u.nm.sel = (_sel), \
|
||||
.u.nm.enable = (_enable), \
|
||||
.u.nm.flags = (_flags), \
|
||||
.enable = sunxi_ccu_nm_enable, \
|
||||
.get_rate = sunxi_ccu_nm_get_rate, \
|
||||
.set_rate = sunxi_ccu_nm_set_rate, \
|
||||
.set_parent = sunxi_ccu_nm_set_parent, \
|
||||
.get_parent = sunxi_ccu_nm_get_parent, \
|
||||
}
|
||||
|
||||
struct sunxi_ccu_div {
|
||||
bus_size_t reg;
|
||||
const char **parents;
|
||||
u_int nparents;
|
||||
uint32_t div;
|
||||
uint32_t sel;
|
||||
uint32_t flags;
|
||||
#define SUNXI_CCU_DIV_POWER_OF_TWO __BIT(0)
|
||||
#define SUNXI_CCU_DIV_ZERO_IS_ONE __BIT(1)
|
||||
};
|
||||
|
||||
u_int sunxi_ccu_div_get_rate(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
int sunxi_ccu_div_set_rate(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, u_int);
|
||||
int sunxi_ccu_div_set_parent(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *,
|
||||
const char *);
|
||||
const char *sunxi_ccu_div_get_parent(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
|
||||
#define SUNXI_CCU_DIV(_id, _name, _parents, _reg, _div, \
|
||||
_sel, _flags) \
|
||||
[_id] = { \
|
||||
.type = SUNXI_CCU_DIV, \
|
||||
.base.name = (_name), \
|
||||
.u.div.reg = (_reg), \
|
||||
.u.div.parents = (_parents), \
|
||||
.u.div.nparents = __arraycount(_parents), \
|
||||
.u.div.div = (_div), \
|
||||
.u.div.sel = (_sel), \
|
||||
.u.div.flags = (_flags), \
|
||||
.get_rate = sunxi_ccu_div_get_rate, \
|
||||
.set_rate = sunxi_ccu_div_set_rate, \
|
||||
.set_parent = sunxi_ccu_div_set_parent, \
|
||||
.get_parent = sunxi_ccu_div_get_parent, \
|
||||
}
|
||||
|
||||
struct sunxi_ccu_prediv {
|
||||
bus_size_t reg;
|
||||
const char **parents;
|
||||
u_int nparents;
|
||||
uint32_t prediv;
|
||||
uint32_t prediv_sel;
|
||||
uint32_t div;
|
||||
uint32_t sel;
|
||||
uint32_t flags;
|
||||
#define SUNXI_CCU_PREDIV_POWER_OF_TWO __BIT(0)
|
||||
#define SUNXI_CCU_PREDIV_DIVIDE_BY_TWO __BIT(1)
|
||||
};
|
||||
|
||||
u_int sunxi_ccu_prediv_get_rate(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
int sunxi_ccu_prediv_set_rate(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, u_int);
|
||||
int sunxi_ccu_prediv_set_parent(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *,
|
||||
const char *);
|
||||
const char *sunxi_ccu_prediv_get_parent(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
|
||||
#define SUNXI_CCU_PREDIV(_id, _name, _parents, _reg, _prediv, \
|
||||
_prediv_sel, _div, _sel, _flags) \
|
||||
[_id] = { \
|
||||
.type = SUNXI_CCU_PREDIV, \
|
||||
.base.name = (_name), \
|
||||
.u.prediv.reg = (_reg), \
|
||||
.u.prediv.parents = (_parents), \
|
||||
.u.prediv.nparents = __arraycount(_parents), \
|
||||
.u.prediv.prediv = (_prediv), \
|
||||
.u.prediv.prediv_sel = (_prediv_sel), \
|
||||
.u.prediv.div = (_div), \
|
||||
.u.prediv.sel = (_sel), \
|
||||
.u.prediv.flags = (_flags), \
|
||||
.get_rate = sunxi_ccu_prediv_get_rate, \
|
||||
.set_rate = sunxi_ccu_prediv_set_rate, \
|
||||
.set_parent = sunxi_ccu_prediv_set_parent, \
|
||||
.get_parent = sunxi_ccu_prediv_get_parent, \
|
||||
}
|
||||
|
||||
struct sunxi_ccu_clk {
|
||||
struct clk base;
|
||||
enum sunxi_ccu_clktype type;
|
||||
union {
|
||||
struct sunxi_ccu_gate gate;
|
||||
struct sunxi_ccu_nm nm;
|
||||
struct sunxi_ccu_nkmp nkmp;
|
||||
struct sunxi_ccu_prediv prediv;
|
||||
struct sunxi_ccu_div div;
|
||||
} u;
|
||||
|
||||
int (*enable)(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, int);
|
||||
u_int (*get_rate)(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
int (*set_rate)(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *, u_int);
|
||||
const char * (*get_parent)(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *);
|
||||
int (*set_parent)(struct sunxi_ccu_softc *,
|
||||
struct sunxi_ccu_clk *,
|
||||
const char *);
|
||||
};
|
||||
|
||||
struct sunxi_ccu_softc {
|
||||
device_t sc_dev;
|
||||
int sc_phandle;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
|
||||
struct clk_domain sc_clkdom;
|
||||
|
||||
struct sunxi_ccu_reset *sc_resets;
|
||||
u_int sc_nresets;
|
||||
|
||||
struct sunxi_ccu_clk *sc_clks;
|
||||
u_int sc_nclks;
|
||||
};
|
||||
|
||||
int sunxi_ccu_attach(struct sunxi_ccu_softc *);
|
||||
struct sunxi_ccu_clk *sunxi_ccu_clock_find(struct sunxi_ccu_softc *,
|
||||
const char *);
|
||||
void sunxi_ccu_print(struct sunxi_ccu_softc *);
|
||||
|
||||
#define CCU_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||
#define CCU_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||
|
||||
#endif /* _ARM_SUNXI_CCU_H */
|
|
@ -0,0 +1,124 @@
|
|||
/* $NetBSD: sunxi_ccu_div.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_div.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
|
||||
u_int
|
||||
sunxi_ccu_div_get_rate(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
struct sunxi_ccu_div *div = &clk->u.div;
|
||||
struct clk *clkp, *clkp_parent;
|
||||
u_int rate, ratio;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_DIV);
|
||||
|
||||
clkp = &clk->base;
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(clkp_parent);
|
||||
if (rate == 0)
|
||||
return 0;
|
||||
|
||||
val = CCU_READ(sc, div->reg);
|
||||
ratio = __SHIFTOUT(val, div->div);
|
||||
if ((div->flags & SUNXI_CCU_DIV_ZERO_IS_ONE) != 0 && ratio == 0)
|
||||
ratio = 1;
|
||||
if (div->flags & SUNXI_CCU_DIV_POWER_OF_TWO)
|
||||
ratio = 1 << ratio;
|
||||
else
|
||||
ratio++;
|
||||
|
||||
return rate / ratio;
|
||||
}
|
||||
|
||||
int
|
||||
sunxi_ccu_div_set_rate(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk, u_int new_rate)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
int
|
||||
sunxi_ccu_div_set_parent(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk, const char *name)
|
||||
{
|
||||
struct sunxi_ccu_div *div = &clk->u.div;
|
||||
uint32_t val;
|
||||
u_int index;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_DIV);
|
||||
|
||||
if (div->sel == 0)
|
||||
return ENODEV;
|
||||
|
||||
for (index = 0; index < div->nparents; index++) {
|
||||
if (div->parents[index] != NULL &&
|
||||
strcmp(div->parents[index], name) == 0)
|
||||
break;
|
||||
}
|
||||
if (index == div->nparents)
|
||||
return EINVAL;
|
||||
|
||||
val = CCU_READ(sc, div->reg);
|
||||
val &= ~div->sel;
|
||||
val |= __SHIFTIN(index, div->sel);
|
||||
CCU_WRITE(sc, div->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
sunxi_ccu_div_get_parent(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
struct sunxi_ccu_div *div = &clk->u.div;
|
||||
u_int index;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_DIV);
|
||||
|
||||
if (div->sel == 0)
|
||||
return div->parents[0];
|
||||
|
||||
val = CCU_READ(sc, div->reg);
|
||||
index = __SHIFTOUT(val, div->sel);
|
||||
|
||||
return div->parents[index];
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: exynos_fdt.c,v 1.4 2017/04/16 15:52:16 jmcneill Exp $ */
|
||||
/* $NetBSD: sunxi_ccu_gate.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -26,55 +26,41 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_exynos.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_fdt.c,v 1.4 2017/04/16 15:52:16 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_gate.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <arm/mainbus/mainbus.h>
|
||||
#include <arm/samsung/exynos_reg.h>
|
||||
#include <arm/samsung/exynos_var.h>
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
static int exynosfdt_match(device_t, cfdata_t, void *);
|
||||
static void exynosfdt_attach(device_t, device_t, void *);
|
||||
|
||||
CFATTACH_DECL_NEW(exynos_fdt, 0,
|
||||
exynosfdt_match, exynosfdt_attach, NULL, NULL);
|
||||
|
||||
static bool exynosfdt_found = false;
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
|
||||
int
|
||||
exynosfdt_match(device_t parent, cfdata_t cf, void *aux)
|
||||
sunxi_ccu_gate_enable(struct sunxi_ccu_softc *sc, struct sunxi_ccu_clk *clk,
|
||||
int enable)
|
||||
{
|
||||
if (exynosfdt_found)
|
||||
return 0;
|
||||
return 1;
|
||||
struct sunxi_ccu_gate *gate = &clk->u.gate;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_GATE);
|
||||
|
||||
val = CCU_READ(sc, gate->reg);
|
||||
if (enable)
|
||||
val |= gate->mask;
|
||||
else
|
||||
val &= ~gate->mask;
|
||||
CCU_WRITE(sc, gate->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
exynosfdt_attach(device_t parent, device_t self, void *aux)
|
||||
const char *
|
||||
sunxi_ccu_gate_get_parent(struct sunxi_ccu_softc *sc, struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
exynosfdt_found = true;
|
||||
struct sunxi_ccu_gate *gate = &clk->u.gate;
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal("\n");
|
||||
KASSERT(clk->type == SUNXI_CCU_GATE);
|
||||
|
||||
struct fdt_attach_args faa = {
|
||||
.faa_name = "",
|
||||
.faa_bst = &armv7_generic_bs_tag,
|
||||
.faa_a4x_bst = &armv7_generic_a4x_bs_tag,
|
||||
.faa_dmat = &exynos_bus_dma_tag,
|
||||
.faa_phandle = OF_peer(0),
|
||||
};
|
||||
config_found(self, &faa, NULL);
|
||||
return gate->parent;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/* $NetBSD: sunxi_ccu_nkmp.c,v 1.4.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_nkmp.c,v 1.4.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
|
||||
int
|
||||
sunxi_ccu_nkmp_enable(struct sunxi_ccu_softc *sc, struct sunxi_ccu_clk *clk,
|
||||
int enable)
|
||||
{
|
||||
struct sunxi_ccu_nkmp *nkmp = &clk->u.nkmp;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_NKMP);
|
||||
|
||||
if (!nkmp->enable)
|
||||
return enable ? 0 : EINVAL;
|
||||
|
||||
val = CCU_READ(sc, nkmp->reg);
|
||||
if (enable)
|
||||
val |= nkmp->enable;
|
||||
else
|
||||
val &= ~nkmp->enable;
|
||||
CCU_WRITE(sc, nkmp->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u_int
|
||||
sunxi_ccu_nkmp_get_rate(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
struct sunxi_ccu_nkmp *nkmp = &clk->u.nkmp;
|
||||
struct clk *clkp, *clkp_parent;
|
||||
u_int rate, n, k, m, p;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_NKMP);
|
||||
|
||||
clkp = &clk->base;
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(clkp_parent);
|
||||
if (rate == 0)
|
||||
return 0;
|
||||
|
||||
val = CCU_READ(sc, nkmp->reg);
|
||||
if (nkmp->n)
|
||||
n = __SHIFTOUT(val, nkmp->n);
|
||||
else
|
||||
n = 0;
|
||||
if (nkmp->k)
|
||||
k = __SHIFTOUT(val, nkmp->k);
|
||||
else
|
||||
k = 0;
|
||||
if (nkmp->m)
|
||||
m = __SHIFTOUT(val, nkmp->m);
|
||||
else
|
||||
m = 0;
|
||||
if (nkmp->p)
|
||||
p = __SHIFTOUT(val, nkmp->p);
|
||||
else
|
||||
p = 0;
|
||||
|
||||
if (nkmp->enable && !(val & nkmp->enable))
|
||||
return 0;
|
||||
|
||||
if ((nkmp->flags & SUNXI_CCU_NKMP_FACTOR_N_EXACT) == 0)
|
||||
n++;
|
||||
k++;
|
||||
m++;
|
||||
p++;
|
||||
|
||||
if (nkmp->flags & SUNXI_CCU_NKMP_DIVIDE_BY_TWO)
|
||||
m *= 2;
|
||||
|
||||
return (u_int)((uint64_t)rate * n * k) / (m * p);
|
||||
}
|
||||
|
||||
int
|
||||
sunxi_ccu_nkmp_set_rate(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk, u_int rate)
|
||||
{
|
||||
return EIO;
|
||||
}
|
||||
|
||||
const char *
|
||||
sunxi_ccu_nkmp_get_parent(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
struct sunxi_ccu_nkmp *nkmp = &clk->u.nkmp;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_NKMP);
|
||||
|
||||
return nkmp->parent;
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
/* $NetBSD: sunxi_ccu_nm.c,v 1.3.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_nm.c,v 1.3.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
|
||||
int
|
||||
sunxi_ccu_nm_enable(struct sunxi_ccu_softc *sc, struct sunxi_ccu_clk *clk,
|
||||
int enable)
|
||||
{
|
||||
struct sunxi_ccu_nm *nm = &clk->u.nm;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_NM);
|
||||
|
||||
if (!nm->enable)
|
||||
return enable ? 0 : EINVAL;
|
||||
|
||||
val = CCU_READ(sc, nm->reg);
|
||||
if (enable)
|
||||
val |= nm->enable;
|
||||
else
|
||||
val &= ~nm->enable;
|
||||
CCU_WRITE(sc, nm->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u_int
|
||||
sunxi_ccu_nm_get_rate(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
struct sunxi_ccu_nm *nm = &clk->u.nm;
|
||||
struct clk *clkp, *clkp_parent;
|
||||
u_int rate, n, m;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_NM);
|
||||
|
||||
clkp = &clk->base;
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(clkp_parent);
|
||||
if (rate == 0)
|
||||
return 0;
|
||||
|
||||
val = CCU_READ(sc, nm->reg);
|
||||
n = __SHIFTOUT(val, nm->n);
|
||||
m = __SHIFTOUT(val, nm->m);
|
||||
|
||||
if (nm->enable && !(val & nm->enable))
|
||||
return 0;
|
||||
|
||||
if (nm->flags & SUNXI_CCU_NM_POWER_OF_TWO)
|
||||
n = 1 << n;
|
||||
else
|
||||
n++;
|
||||
|
||||
m++;
|
||||
|
||||
return rate / n / m;
|
||||
}
|
||||
|
||||
int
|
||||
sunxi_ccu_nm_set_rate(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk, u_int new_rate)
|
||||
{
|
||||
struct sunxi_ccu_nm *nm = &clk->u.nm;
|
||||
struct clk *clkp, *clkp_parent;
|
||||
u_int parent_rate, best_rate, best_n, best_m, best_parent;
|
||||
u_int n, m, pindex, rate;
|
||||
int best_diff;
|
||||
uint32_t val;
|
||||
|
||||
const u_int n_max = __SHIFTOUT(nm->n, nm->n);
|
||||
const u_int m_max = __SHIFTOUT(nm->m, nm->m);
|
||||
|
||||
clkp = &clk->base;
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(clkp_parent);
|
||||
if (rate == 0)
|
||||
return 0;
|
||||
|
||||
best_rate = 0;
|
||||
best_diff = INT_MAX;
|
||||
for (pindex = 0; pindex < nm->nparents; pindex++) {
|
||||
/* XXX
|
||||
* Shouldn't have to set parent to get potential parent clock rate
|
||||
*/
|
||||
val = CCU_READ(sc, nm->reg);
|
||||
val &= ~nm->sel;
|
||||
val |= __SHIFTIN(pindex, nm->sel);
|
||||
CCU_WRITE(sc, nm->reg, val);
|
||||
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL)
|
||||
continue;
|
||||
parent_rate = clk_get_rate(clkp_parent);
|
||||
if (parent_rate == 0)
|
||||
continue;
|
||||
|
||||
for (n = 0; n <= n_max; n++) {
|
||||
for (m = 0; m <= m_max; m++) {
|
||||
if (nm->flags & SUNXI_CCU_NM_POWER_OF_TWO)
|
||||
rate = parent_rate / (1 << n) / (m + 1);
|
||||
else
|
||||
rate = parent_rate / (n + 1) / (m + 1);
|
||||
|
||||
if (nm->flags & SUNXI_CCU_NM_ROUND_DOWN) {
|
||||
const int diff = new_rate - rate;
|
||||
if (diff >= 0 && rate > best_rate) {
|
||||
best_diff = diff;
|
||||
best_rate = rate;
|
||||
best_n = n;
|
||||
best_m = m;
|
||||
best_parent = pindex;
|
||||
}
|
||||
} else {
|
||||
const int diff = abs(new_rate - rate);
|
||||
if (diff < best_diff) {
|
||||
best_diff = diff;
|
||||
best_rate = rate;
|
||||
best_n = n;
|
||||
best_m = m;
|
||||
best_parent = pindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_rate == 0)
|
||||
return ERANGE;
|
||||
|
||||
val = CCU_READ(sc, nm->reg);
|
||||
val &= ~nm->sel;
|
||||
val |= __SHIFTIN(best_parent, nm->sel);
|
||||
val &= ~nm->n;
|
||||
val |= __SHIFTIN(best_n, nm->n);
|
||||
val &= ~nm->m;
|
||||
val |= __SHIFTIN(best_m, nm->m);
|
||||
CCU_WRITE(sc, nm->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sunxi_ccu_nm_set_parent(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk, const char *name)
|
||||
{
|
||||
struct sunxi_ccu_nm *nm = &clk->u.nm;
|
||||
uint32_t val;
|
||||
u_int index;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_NM);
|
||||
|
||||
if (nm->sel == 0)
|
||||
return ENODEV;
|
||||
|
||||
for (index = 0; index < nm->nparents; index++) {
|
||||
if (nm->parents[index] != NULL &&
|
||||
strcmp(nm->parents[index], name) == 0)
|
||||
break;
|
||||
}
|
||||
if (index == nm->nparents)
|
||||
return EINVAL;
|
||||
|
||||
val = CCU_READ(sc, nm->reg);
|
||||
val &= ~nm->sel;
|
||||
val |= __SHIFTIN(index, nm->sel);
|
||||
CCU_WRITE(sc, nm->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
sunxi_ccu_nm_get_parent(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
struct sunxi_ccu_nm *nm = &clk->u.nm;
|
||||
u_int index;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_NM);
|
||||
|
||||
val = CCU_READ(sc, nm->reg);
|
||||
index = __SHIFTOUT(val, nm->sel);
|
||||
|
||||
return nm->parents[index];
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/* $NetBSD: sunxi_ccu_prediv.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_prediv.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_ccu.h>
|
||||
|
||||
u_int
|
||||
sunxi_ccu_prediv_get_rate(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
struct sunxi_ccu_prediv *prediv = &clk->u.prediv;
|
||||
struct clk *clkp, *clkp_parent;
|
||||
u_int rate, pre, div, sel;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_PREDIV);
|
||||
|
||||
clkp = &clk->base;
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(clkp_parent);
|
||||
if (rate == 0)
|
||||
return 0;
|
||||
|
||||
val = CCU_READ(sc, prediv->reg);
|
||||
if (prediv->prediv)
|
||||
pre = __SHIFTOUT(val, prediv->prediv);
|
||||
else
|
||||
pre = 0;
|
||||
if (prediv->div)
|
||||
div = __SHIFTOUT(val, prediv->div);
|
||||
else
|
||||
div = 0;
|
||||
sel = __SHIFTOUT(val, prediv->sel);
|
||||
|
||||
if (prediv->flags & SUNXI_CCU_PREDIV_POWER_OF_TWO)
|
||||
div = 1 << div;
|
||||
else
|
||||
div++;
|
||||
|
||||
pre++;
|
||||
|
||||
if (prediv->flags & SUNXI_CCU_PREDIV_DIVIDE_BY_TWO)
|
||||
pre *= 2;
|
||||
|
||||
if (prediv->prediv_sel & __BIT(sel))
|
||||
return rate / pre / div;
|
||||
else
|
||||
return rate / div;
|
||||
}
|
||||
|
||||
int
|
||||
sunxi_ccu_prediv_set_rate(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk, u_int new_rate)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
int
|
||||
sunxi_ccu_prediv_set_parent(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk, const char *name)
|
||||
{
|
||||
struct sunxi_ccu_prediv *prediv = &clk->u.prediv;
|
||||
uint32_t val;
|
||||
u_int index;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_PREDIV);
|
||||
|
||||
if (prediv->sel == 0)
|
||||
return ENODEV;
|
||||
|
||||
for (index = 0; index < prediv->nparents; index++) {
|
||||
if (prediv->parents[index] != NULL &&
|
||||
strcmp(prediv->parents[index], name) == 0)
|
||||
break;
|
||||
}
|
||||
if (index == prediv->nparents)
|
||||
return EINVAL;
|
||||
|
||||
val = CCU_READ(sc, prediv->reg);
|
||||
val &= ~prediv->sel;
|
||||
val |= __SHIFTIN(index, prediv->sel);
|
||||
CCU_WRITE(sc, prediv->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
sunxi_ccu_prediv_get_parent(struct sunxi_ccu_softc *sc,
|
||||
struct sunxi_ccu_clk *clk)
|
||||
{
|
||||
struct sunxi_ccu_prediv *prediv = &clk->u.prediv;
|
||||
u_int index;
|
||||
uint32_t val;
|
||||
|
||||
KASSERT(clk->type == SUNXI_CCU_PREDIV);
|
||||
|
||||
val = CCU_READ(sc, prediv->reg);
|
||||
index = __SHIFTOUT(val, prediv->sel);
|
||||
|
||||
return prediv->parents[index];
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/* $NetBSD: sunxi_com.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this 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 <sys/cdefs.h>
|
||||
|
||||
__KERNEL_RCSID(1, "$NetBSD: sunxi_com.c,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/termios.h>
|
||||
|
||||
#include <dev/ic/comvar.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
static int sunxi_com_match(device_t, cfdata_t, void *);
|
||||
static void sunxi_com_attach(device_t, device_t, void *);
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"snps,dw-apb-uart",
|
||||
NULL
|
||||
};
|
||||
|
||||
struct sunxi_com_softc {
|
||||
struct com_softc ssc_sc;
|
||||
void *ssc_ih;
|
||||
|
||||
struct clk *ssc_clk;
|
||||
struct fdtbus_reset *ssc_rst;
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_com, sizeof(struct sunxi_com_softc),
|
||||
sunxi_com_match, sunxi_com_attach, NULL, NULL);
|
||||
|
||||
static int
|
||||
sunxi_com_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_com_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_com_softc * const ssc = device_private(self);
|
||||
struct com_softc * const sc = &ssc->ssc_sc;
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
bus_space_handle_t bsh;
|
||||
bus_space_tag_t bst;
|
||||
char intrstr[128];
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
u_int reg_shift;
|
||||
int error;
|
||||
|
||||
if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (of_getprop_uint32(faa->faa_phandle, "reg-shift", ®_shift)) {
|
||||
/* missing or bad reg-shift property, assume 2 */
|
||||
bst = faa->faa_a4x_bst;
|
||||
} else {
|
||||
if (reg_shift == 2) {
|
||||
bst = faa->faa_a4x_bst;
|
||||
} else if (reg_shift == 0) {
|
||||
bst = faa->faa_bst;
|
||||
} else {
|
||||
aprint_error(": unsupported reg-shift value %d\n",
|
||||
reg_shift);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
|
||||
ssc->ssc_clk = fdtbus_clock_get_index(faa->faa_phandle, 0);
|
||||
ssc->ssc_rst = fdtbus_reset_get_index(faa->faa_phandle, 0);
|
||||
|
||||
if (ssc->ssc_clk == NULL) {
|
||||
aprint_error(": couldn't get frequency\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_frequency = clk_get_rate(ssc->ssc_clk);
|
||||
sc->sc_type = COM_TYPE_NORMAL;
|
||||
|
||||
error = bus_space_map(bst, addr, size, 0, &bsh);
|
||||
if (error) {
|
||||
aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
|
||||
return;
|
||||
}
|
||||
|
||||
COM_INIT_REGS(sc->sc_regs, bst, bsh, addr);
|
||||
|
||||
com_attach_subr(sc);
|
||||
aprint_naive("\n");
|
||||
|
||||
if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) {
|
||||
aprint_error_dev(self, "failed to decode interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ssc->ssc_ih = fdtbus_intr_establish(faa->faa_phandle, 0, IPL_SERIAL,
|
||||
FDT_INTR_MPSAFE, comintr, sc);
|
||||
if (ssc->ssc_ih == NULL) {
|
||||
aprint_error_dev(self, "failed to establish interrupt on %s\n",
|
||||
intrstr);
|
||||
}
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Console support
|
||||
*/
|
||||
|
||||
static int
|
||||
sunxi_com_console_match(int phandle)
|
||||
{
|
||||
return of_match_compatible(phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_com_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
|
||||
{
|
||||
const int phandle = faa->faa_phandle;
|
||||
bus_space_tag_t bst = faa->faa_a4x_bst;
|
||||
bus_addr_t addr;
|
||||
tcflag_t flags;
|
||||
int speed;
|
||||
|
||||
fdtbus_get_reg(phandle, 0, &addr, NULL);
|
||||
speed = fdtbus_get_stdout_speed();
|
||||
if (speed < 0)
|
||||
speed = 115200; /* default */
|
||||
flags = fdtbus_get_stdout_flags();
|
||||
|
||||
if (comcnattach(bst, addr, speed, uart_freq, COM_TYPE_NORMAL, flags))
|
||||
panic("Cannot initialize sunxi com console");
|
||||
}
|
||||
|
||||
static const struct fdt_console sunxi_com_console = {
|
||||
.match = sunxi_com_console_match,
|
||||
.consinit = sunxi_com_console_consinit,
|
||||
};
|
||||
|
||||
FDT_CONSOLE(sunxi_com, &sunxi_com_console);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,184 @@
|
|||
/*-
|
||||
* Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allwinner Gigabit Ethernet
|
||||
*/
|
||||
|
||||
#ifndef __SUNXI_EMAC_H__
|
||||
#define __SUNXI_EMAC_H__
|
||||
|
||||
#define EMAC_BASIC_CTL_0 0x00
|
||||
#define BASIC_CTL_SPEED (0x3 << 2)
|
||||
#define BASIC_CTL_SPEED_SHIFT 2
|
||||
#define BASIC_CTL_SPEED_1000 0
|
||||
#define BASIC_CTL_SPEED_10 2
|
||||
#define BASIC_CTL_SPEED_100 3
|
||||
#define BASIC_CTL_LOOPBACK (1 << 1)
|
||||
#define BASIC_CTL_DUPLEX (1 << 0)
|
||||
#define EMAC_BASIC_CTL_1 0x04
|
||||
#define BASIC_CTL_BURST_LEN (0x3f << 24)
|
||||
#define BASIC_CTL_BURST_LEN_SHIFT 24
|
||||
#define BASIC_CTL_RX_TX_PRI (1 << 1)
|
||||
#define BASIC_CTL_SOFT_RST (1 << 0)
|
||||
#define EMAC_INT_STA 0x08
|
||||
#define RX_BUF_UA_INT (1 << 10)
|
||||
#define RX_INT (1 << 8)
|
||||
#define TX_UNDERFLOW_INT (1 << 4)
|
||||
#define TX_BUF_UA_INT (1 << 2)
|
||||
#define TX_DMA_STOPPED_INT (1 << 1)
|
||||
#define TX_INT (1 << 0)
|
||||
#define EMAC_INT_EN 0x0c
|
||||
#define RX_BUF_UA_INT_EN (1 << 10)
|
||||
#define RX_INT_EN (1 << 8)
|
||||
#define TX_UNDERFLOW_INT_EN (1 << 4)
|
||||
#define TX_BUF_UA_INT_EN (1 << 2)
|
||||
#define TX_DMA_STOPPED_INT_EN (1 << 1)
|
||||
#define TX_INT_EN (1 << 0)
|
||||
#define EMAC_TX_CTL_0 0x10
|
||||
#define TX_EN (1 << 31)
|
||||
#define EMAC_TX_CTL_1 0x14
|
||||
#define TX_DMA_START (1 << 31)
|
||||
#define TX_DMA_EN (1 << 30)
|
||||
#define TX_NEXT_FRAME (1 << 2)
|
||||
#define TX_MD (1 << 1)
|
||||
#define FLUSH_TX_FIFO (1 << 0)
|
||||
#define EMAC_TX_FLOW_CTL 0x1c
|
||||
#define PAUSE_TIME (0xffff << 4)
|
||||
#define PAUSE_TIME_SHIFT 4
|
||||
#define TX_FLOW_CTL_EN (1 << 0)
|
||||
#define EMAC_TX_DMA_LIST 0x20
|
||||
#define EMAC_RX_CTL_0 0x24
|
||||
#define RX_EN (1 << 31)
|
||||
#define JUMBO_FRM_EN (1 << 29)
|
||||
#define STRIP_FCS (1 << 28)
|
||||
#define CHECK_CRC (1 << 27)
|
||||
#define RX_FLOW_CTL_EN (1 << 16)
|
||||
#define EMAC_RX_CTL_1 0x28
|
||||
#define RX_DMA_START (1 << 31)
|
||||
#define RX_DMA_EN (1 << 30)
|
||||
#define RX_MD (1 << 1)
|
||||
#define EMAC_RX_DMA_LIST 0x34
|
||||
#define EMAC_RX_FRM_FLT 0x38
|
||||
#define DIS_ADDR_FILTER (1 << 31)
|
||||
#define DIS_BROADCAST (1 << 17)
|
||||
#define RX_ALL_MULTICAST (1 << 16)
|
||||
#define CTL_FRM_FILTER (0x3 << 12)
|
||||
#define CTL_FRM_FILTER_SHIFT 12
|
||||
#define HASH_MULTICAST (1 << 9)
|
||||
#define HASH_UNICAST (1 << 8)
|
||||
#define SA_FILTER_EN (1 << 6)
|
||||
#define SA_INV_FILTER (1 << 5)
|
||||
#define DA_INV_FILTER (1 << 4)
|
||||
#define FLT_MD (1 << 1)
|
||||
#define RX_ALL (1 << 0)
|
||||
#define EMAC_RX_HASH_0 0x40
|
||||
#define EMAC_RX_HASH_1 0x44
|
||||
#define EMAC_MII_CMD 0x48
|
||||
#define MDC_DIV_RATIO_M (0x7 << 20)
|
||||
#define MDC_DIV_RATIO_M_16 0
|
||||
#define MDC_DIV_RATIO_M_32 1
|
||||
#define MDC_DIV_RATIO_M_64 2
|
||||
#define MDC_DIV_RATIO_M_128 3
|
||||
#define MDC_DIV_RATIO_M_SHIFT 20
|
||||
#define PHY_ADDR (0x1f << 12)
|
||||
#define PHY_ADDR_SHIFT 12
|
||||
#define PHY_REG_ADDR (0x1f << 4)
|
||||
#define PHY_REG_ADDR_SHIFT 4
|
||||
#define MII_WR (1 << 1)
|
||||
#define MII_BUSY (1 << 0)
|
||||
#define EMAC_MII_DATA 0x4c
|
||||
#define EMAC_ADDR_HIGH(n) (0x50 + (n) * 8)
|
||||
#define EMAC_ADDR_LOW(n) (0x54 + (n) * 8)
|
||||
#define EMAC_TX_DMA_STA 0x80
|
||||
#define EMAC_TX_DMA_CUR_DESC 0x84
|
||||
#define EMAC_TX_DMA_CUR_BUF 0x88
|
||||
#define EMAC_RX_DMA_STA 0xc0
|
||||
#define EMAC_RX_DMA_CUR_DESC 0xc4
|
||||
#define EMAC_RX_DMA_CUR_BUF 0xc8
|
||||
#define EMAC_RGMII_STA 0xd0
|
||||
|
||||
struct sunxi_emac_desc {
|
||||
uint32_t status;
|
||||
/* Transmit */
|
||||
#define TX_DESC_CTL (1 << 31)
|
||||
#define TX_HEADER_ERR (1 << 16)
|
||||
#define TX_LENGTH_ERR (1 << 14)
|
||||
#define TX_PAYLOAD_ERR (1 << 12)
|
||||
#define TX_CRS_ERR (1 << 10)
|
||||
#define TX_COL_ERR_0 (1 << 9)
|
||||
#define TX_COL_ERR_1 (1 << 8)
|
||||
#define TX_COL_CNT (0xf << 3)
|
||||
#define TX_COL_CNT_SHIFT 3
|
||||
#define TX_DEFER_ERR (1 << 2)
|
||||
#define TX_UNDERFLOW_ERR (1 << 1)
|
||||
#define TX_DEFER (1 << 0)
|
||||
/* Receive */
|
||||
#define RX_DESC_CTL (1 << 31)
|
||||
#define RX_DAF_FAIL (1 << 30)
|
||||
#define RX_FRM_LEN (0x3fff << 16)
|
||||
#define RX_FRM_LEN_SHIFT 16
|
||||
#define RX_NO_ENOUGH_BUF_ERR (1 << 14)
|
||||
#define RX_SAF_FAIL (1 << 13)
|
||||
#define RX_OVERFLOW_ERR (1 << 11)
|
||||
#define RX_FIR_DESC (1 << 9)
|
||||
#define RX_LAST_DESC (1 << 8)
|
||||
#define RX_HEADER_ERR (1 << 7)
|
||||
#define RX_COL_ERR (1 << 6)
|
||||
#define RX_FRM_TYPE (1 << 5)
|
||||
#define RX_LENGTH_ERR (1 << 4)
|
||||
#define RX_PHY_ERR (1 << 3)
|
||||
#define RX_CRC_ERR (1 << 1)
|
||||
#define RX_PAYLOAD_ERR (1 << 0)
|
||||
|
||||
uint32_t size;
|
||||
/* Transmit */
|
||||
#define TX_INT_CTL (1 << 31)
|
||||
#define TX_LAST_DESC (1 << 30)
|
||||
#define TX_FIR_DESC (1 << 29)
|
||||
#define TX_CHECKSUM_CTL (0x3 << 27)
|
||||
#define TX_CHECKSUM_CTL_IP 1
|
||||
#define TX_CHECKSUM_CTL_NO_PSE 2
|
||||
#define TX_CHECKSUM_CTL_FULL 3
|
||||
#define TX_CHECKSUM_CTL_SHIFT 27
|
||||
#define TX_CRC_CTL (1 << 26)
|
||||
#define TX_BUF_SIZE (0xfff << 0)
|
||||
#define TX_BUF_SIZE_SHIFT 0
|
||||
/* Receive */
|
||||
#define RX_INT_CTL (1 << 31)
|
||||
#define RX_BUF_SIZE (0xfff << 0)
|
||||
#define RX_BUF_SIZE_SHIFT 0
|
||||
|
||||
uint32_t addr;
|
||||
|
||||
uint32_t next;
|
||||
} __packed __aligned(CACHE_LINE_SIZE);
|
||||
|
||||
__CTASSERT(sizeof(struct sunxi_emac_desc) == CACHE_LINE_SIZE);
|
||||
|
||||
#endif /* !__SUNXI_EMAC_H__ */
|
|
@ -0,0 +1,277 @@
|
|||
/* $NetBSD: sunxi_gates.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_gates.c,v 1.1.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/kmem.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#define GATE_REG(index) (((index) / 32) * 4)
|
||||
#define GATE_MASK(index) __BIT((index) % 32)
|
||||
|
||||
static const char * compatible[] = {
|
||||
"allwinner,sun4i-a10-gates-clk",
|
||||
NULL
|
||||
};
|
||||
|
||||
struct sunxi_gate {
|
||||
struct clk base;
|
||||
u_int index;
|
||||
|
||||
TAILQ_ENTRY(sunxi_gate) gates;
|
||||
};
|
||||
|
||||
struct sunxi_gates_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
int sc_phandle;
|
||||
|
||||
struct clk_domain sc_clkdom;
|
||||
TAILQ_HEAD(, sunxi_gate) sc_gates;
|
||||
};
|
||||
|
||||
#define GATE_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||
#define GATE_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||
|
||||
static struct clk *
|
||||
sunxi_gates_clock_decode(device_t dev, const void *data, size_t len)
|
||||
{
|
||||
struct sunxi_gates_softc * const sc = device_private(dev);
|
||||
struct sunxi_gate *gate;
|
||||
|
||||
if (len != 4)
|
||||
return NULL;
|
||||
|
||||
const u_int index = be32dec(data);
|
||||
|
||||
TAILQ_FOREACH(gate, &sc->sc_gates, gates)
|
||||
if (gate->index == index)
|
||||
return &gate->base;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct fdtbus_clock_controller_func sunxi_gates_fdtclock_funcs = {
|
||||
.decode = sunxi_gates_clock_decode,
|
||||
};
|
||||
|
||||
static struct clk *
|
||||
sunxi_gates_clock_get(void *priv, const char *name)
|
||||
{
|
||||
struct sunxi_gates_softc * const sc = priv;
|
||||
struct sunxi_gate *gate;
|
||||
|
||||
TAILQ_FOREACH(gate, &sc->sc_gates, gates)
|
||||
if (strcmp(gate->base.name, name) == 0)
|
||||
return &gate->base;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_gates_clock_put(void *priv, struct clk *clk)
|
||||
{
|
||||
}
|
||||
|
||||
static u_int
|
||||
sunxi_gates_clock_get_rate(void *priv, struct clk *clkp)
|
||||
{
|
||||
struct sunxi_gates_softc * const sc = priv;
|
||||
struct sunxi_gate *gate = (struct sunxi_gate *)clkp;
|
||||
struct clk *clkp_parent;
|
||||
|
||||
clkp_parent = clk_get_parent(clkp);
|
||||
if (clkp_parent == NULL)
|
||||
return 0;
|
||||
|
||||
const bus_size_t gate_reg = GATE_REG(gate->index);
|
||||
const uint32_t gate_mask = GATE_MASK(gate->index);
|
||||
|
||||
if ((GATE_READ(sc, gate_reg) & gate_mask) == 0)
|
||||
return 0;
|
||||
|
||||
return clk_get_rate(clkp_parent);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gates_clock_enable(void *priv, struct clk *clkp)
|
||||
{
|
||||
struct sunxi_gates_softc * const sc = priv;
|
||||
struct sunxi_gate *gate = (struct sunxi_gate *)clkp;
|
||||
uint32_t val;
|
||||
|
||||
const bus_size_t gate_reg = GATE_REG(gate->index);
|
||||
const uint32_t gate_mask = GATE_MASK(gate->index);
|
||||
|
||||
val = GATE_READ(sc, gate_reg);
|
||||
val |= gate_mask;
|
||||
GATE_WRITE(sc, gate_reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gates_clock_disable(void *priv, struct clk *clkp)
|
||||
{
|
||||
struct sunxi_gates_softc * const sc = priv;
|
||||
struct sunxi_gate *gate = (struct sunxi_gate *)clkp;
|
||||
uint32_t val;
|
||||
|
||||
const bus_size_t gate_reg = GATE_REG(gate->index);
|
||||
const uint32_t gate_mask = GATE_MASK(gate->index);
|
||||
|
||||
val = GATE_READ(sc, gate_reg);
|
||||
val &= ~gate_mask;
|
||||
GATE_WRITE(sc, gate_reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk *
|
||||
sunxi_gates_clock_get_parent(void *priv, struct clk *clkp)
|
||||
{
|
||||
struct sunxi_gates_softc * const sc = priv;
|
||||
|
||||
return fdtbus_clock_get_index(sc->sc_phandle, 0);
|
||||
}
|
||||
|
||||
static const struct clk_funcs sunxi_gates_clock_funcs = {
|
||||
.get = sunxi_gates_clock_get,
|
||||
.put = sunxi_gates_clock_put,
|
||||
.get_rate = sunxi_gates_clock_get_rate,
|
||||
.enable = sunxi_gates_clock_enable,
|
||||
.disable = sunxi_gates_clock_disable,
|
||||
.get_parent = sunxi_gates_clock_get_parent,
|
||||
};
|
||||
|
||||
static void
|
||||
sunxi_gates_print(struct sunxi_gates_softc *sc)
|
||||
{
|
||||
struct sunxi_gate *gate;
|
||||
struct clk *clkp_parent;
|
||||
|
||||
TAILQ_FOREACH(gate, &sc->sc_gates, gates) {
|
||||
clkp_parent = clk_get_parent(&gate->base);
|
||||
|
||||
aprint_debug_dev(sc->sc_dev,
|
||||
"%3d %-12s %2s %-12s %-7s ",
|
||||
gate->index,
|
||||
gate->base.name,
|
||||
clkp_parent ? "<-" : "",
|
||||
clkp_parent ? clkp_parent->name : "",
|
||||
"gate");
|
||||
aprint_debug("%10d Hz\n", clk_get_rate(&gate->base));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gates_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_gates_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_gates_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
struct sunxi_gate *gate;
|
||||
const u_int *indices;
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
int len, i;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_phandle = phandle;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
TAILQ_INIT(&sc->sc_gates);
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal("\n");
|
||||
|
||||
sc->sc_clkdom.funcs = &sunxi_gates_clock_funcs;
|
||||
sc->sc_clkdom.priv = sc;
|
||||
|
||||
indices = fdtbus_get_prop(phandle, "clock-indices", &len);
|
||||
if (indices == NULL) {
|
||||
aprint_error_dev(self, "no clock-indices property\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0;
|
||||
len >= sizeof(u_int);
|
||||
len -= sizeof(u_int), i++, indices++) {
|
||||
const u_int index = be32dec(indices);
|
||||
const char *name = fdtbus_get_string_index(phandle,
|
||||
"clock-output-names", i);
|
||||
|
||||
if (name == NULL) {
|
||||
aprint_error_dev(self, "no name for clk index %d\n",
|
||||
index);
|
||||
continue;
|
||||
}
|
||||
|
||||
gate = kmem_zalloc(sizeof(*gate), KM_SLEEP);
|
||||
gate->base.domain = &sc->sc_clkdom;
|
||||
gate->base.name = name;
|
||||
gate->index = index;
|
||||
|
||||
TAILQ_INSERT_TAIL(&sc->sc_gates, gate, gates);
|
||||
}
|
||||
|
||||
fdtbus_register_clock_controller(sc->sc_dev, phandle,
|
||||
&sunxi_gates_fdtclock_funcs);
|
||||
|
||||
sunxi_gates_print(sc);
|
||||
}
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_gates, sizeof(struct sunxi_gates_softc),
|
||||
sunxi_gates_match, sunxi_gates_attach, NULL, NULL);
|
|
@ -0,0 +1,556 @@
|
|||
/* $NetBSD: sunxi_gpio.c,v 1.8.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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_soc.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.8.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/gpio.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
#include <dev/gpio/gpiovar.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_gpio.h>
|
||||
|
||||
#define SUNXI_GPIO_PORT(port) (0x24 * (port))
|
||||
#define SUNXI_GPIO_CFG(port, pin) (SUNXI_GPIO_PORT(port) + 0x00 + (0x4 * ((pin) / 8)))
|
||||
#define SUNXI_GPIO_CFG_PINMASK(pin) (0x7 << (((pin) % 8) * 4))
|
||||
#define SUNXI_GPIO_DATA(port) (SUNXI_GPIO_PORT(port) + 0x10)
|
||||
#define SUNXI_GPIO_DRV(port, pin) (SUNXI_GPIO_PORT(port) + 0x14 + (0x4 * ((pin) / 16)))
|
||||
#define SUNXI_GPIO_DRV_PINMASK(pin) (0x3 << (((pin) % 16) * 2))
|
||||
#define SUNXI_GPIO_PULL(port, pin) (SUNXI_GPIO_PORT(port) + 0x1c + (0x4 * ((pin) / 16)))
|
||||
#define SUNXI_GPIO_PULL_DISABLE 0
|
||||
#define SUNXI_GPIO_PULL_UP 1
|
||||
#define SUNXI_GPIO_PULL_DOWN 2
|
||||
#define SUNXI_GPIO_PULL_PINMASK(pin) (0x3 << (((pin) % 16) * 2))
|
||||
|
||||
static const struct of_compat_data compat_data[] = {
|
||||
#ifdef SOC_SUN6I_A31
|
||||
{ "allwinner,sun6i-a31-pinctrl", (uintptr_t)&sun6i_a31_padconf },
|
||||
{ "allwinner,sun6i-a31-r-pinctrl", (uintptr_t)&sun6i_a31_r_padconf },
|
||||
#endif
|
||||
#ifdef SOC_SUN8I_A83T
|
||||
{ "allwinner,sun8i-a83t-pinctrl", (uintptr_t)&sun8i_a83t_padconf },
|
||||
{ "allwinner,sun8i-a83t-r-pinctrl", (uintptr_t)&sun8i_a83t_r_padconf },
|
||||
#endif
|
||||
#ifdef SOC_SUN8I_H3
|
||||
{ "allwinner,sun8i-h3-pinctrl", (uintptr_t)&sun8i_h3_padconf },
|
||||
{ "allwinner,sun8i-h3-r-pinctrl", (uintptr_t)&sun8i_h3_r_padconf },
|
||||
#endif
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct sunxi_gpio_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
const struct sunxi_gpio_padconf *sc_padconf;
|
||||
kmutex_t sc_lock;
|
||||
|
||||
struct gpio_chipset_tag sc_gp;
|
||||
gpio_pin_t *sc_pins;
|
||||
device_t sc_gpiodev;
|
||||
};
|
||||
|
||||
struct sunxi_gpio_pin {
|
||||
struct sunxi_gpio_softc *pin_sc;
|
||||
const struct sunxi_gpio_pins *pin_def;
|
||||
int pin_flags;
|
||||
bool pin_actlo;
|
||||
};
|
||||
|
||||
#define GPIO_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||
#define GPIO_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||
|
||||
static int sunxi_gpio_match(device_t, cfdata_t, void *);
|
||||
static void sunxi_gpio_attach(device_t, device_t, void *);
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_gpio, sizeof(struct sunxi_gpio_softc),
|
||||
sunxi_gpio_match, sunxi_gpio_attach, NULL, NULL);
|
||||
|
||||
static const struct sunxi_gpio_pins *
|
||||
sunxi_gpio_lookup(struct sunxi_gpio_softc *sc, uint8_t port, uint8_t pin)
|
||||
{
|
||||
const struct sunxi_gpio_pins *pin_def;
|
||||
u_int n;
|
||||
|
||||
for (n = 0; n < sc->sc_padconf->npins; n++) {
|
||||
pin_def = &sc->sc_padconf->pins[n];
|
||||
if (pin_def->port == port && pin_def->pin == pin)
|
||||
return pin_def;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct sunxi_gpio_pins *
|
||||
sunxi_gpio_lookup_byname(struct sunxi_gpio_softc *sc, const char *name)
|
||||
{
|
||||
const struct sunxi_gpio_pins *pin_def;
|
||||
u_int n;
|
||||
|
||||
for (n = 0; n < sc->sc_padconf->npins; n++) {
|
||||
pin_def = &sc->sc_padconf->pins[n];
|
||||
if (strcmp(pin_def->name, name) == 0)
|
||||
return pin_def;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gpio_setfunc(struct sunxi_gpio_softc *sc,
|
||||
const struct sunxi_gpio_pins *pin_def, const char *func)
|
||||
{
|
||||
uint32_t cfg;
|
||||
u_int n;
|
||||
|
||||
KASSERT(mutex_owned(&sc->sc_lock));
|
||||
|
||||
const bus_size_t cfg_reg = SUNXI_GPIO_CFG(pin_def->port, pin_def->pin);
|
||||
const uint32_t cfg_mask = SUNXI_GPIO_CFG_PINMASK(pin_def->pin);
|
||||
|
||||
for (n = 0; n < SUNXI_GPIO_MAXFUNC; n++) {
|
||||
if (pin_def->functions[n] == NULL)
|
||||
continue;
|
||||
if (strcmp(pin_def->functions[n], func) == 0) {
|
||||
cfg = GPIO_READ(sc, cfg_reg);
|
||||
cfg &= ~cfg_mask;
|
||||
cfg |= __SHIFTIN(n, cfg_mask);
|
||||
#ifdef SUNXI_GPIO_DEBUG
|
||||
device_printf(sc->sc_dev, "P%c%02d cfg %08x -> %08x\n",
|
||||
pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, cfg_reg), cfg);
|
||||
#endif
|
||||
GPIO_WRITE(sc, cfg_reg, cfg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function not found */
|
||||
device_printf(sc->sc_dev, "function '%s' not supported on P%c%02d\n",
|
||||
func, pin_def->port + 'A', pin_def->pin);
|
||||
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gpio_setpull(struct sunxi_gpio_softc *sc,
|
||||
const struct sunxi_gpio_pins *pin_def, int flags)
|
||||
{
|
||||
uint32_t pull;
|
||||
|
||||
KASSERT(mutex_owned(&sc->sc_lock));
|
||||
|
||||
const bus_size_t pull_reg = SUNXI_GPIO_PULL(pin_def->port, pin_def->pin);
|
||||
const uint32_t pull_mask = SUNXI_GPIO_PULL_PINMASK(pin_def->pin);
|
||||
|
||||
pull = GPIO_READ(sc, pull_reg);
|
||||
pull &= ~pull_mask;
|
||||
if (flags & GPIO_PIN_PULLUP)
|
||||
pull |= __SHIFTIN(SUNXI_GPIO_PULL_UP, pull_mask);
|
||||
else if (flags & GPIO_PIN_PULLDOWN)
|
||||
pull |= __SHIFTIN(SUNXI_GPIO_PULL_DOWN, pull_mask);
|
||||
else
|
||||
pull |= __SHIFTIN(SUNXI_GPIO_PULL_DISABLE, pull_mask);
|
||||
#ifdef SUNXI_GPIO_DEBUG
|
||||
device_printf(sc->sc_dev, "P%c%02d pull %08x -> %08x\n",
|
||||
pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, pull_reg), pull);
|
||||
#endif
|
||||
GPIO_WRITE(sc, pull_reg, pull);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gpio_setdrv(struct sunxi_gpio_softc *sc,
|
||||
const struct sunxi_gpio_pins *pin_def, int drive_strength)
|
||||
{
|
||||
uint32_t drv;
|
||||
|
||||
KASSERT(mutex_owned(&sc->sc_lock));
|
||||
|
||||
if (drive_strength < 10 || drive_strength > 40)
|
||||
return EINVAL;
|
||||
|
||||
const bus_size_t drv_reg = SUNXI_GPIO_DRV(pin_def->port, pin_def->pin);
|
||||
const uint32_t drv_mask = SUNXI_GPIO_DRV_PINMASK(pin_def->pin);
|
||||
|
||||
drv = GPIO_READ(sc, drv_reg);
|
||||
drv &= ~drv_mask;
|
||||
drv |= __SHIFTIN((drive_strength / 10) - 1, drv_mask);
|
||||
#ifdef SUNXI_GPIO_DEBUG
|
||||
device_printf(sc->sc_dev, "P%c%02d drv %08x -> %08x\n",
|
||||
pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, drv_reg), drv);
|
||||
#endif
|
||||
GPIO_WRITE(sc, drv_reg, drv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gpio_ctl(struct sunxi_gpio_softc *sc, const struct sunxi_gpio_pins *pin_def,
|
||||
int flags)
|
||||
{
|
||||
KASSERT(mutex_owned(&sc->sc_lock));
|
||||
|
||||
if (flags & GPIO_PIN_INPUT)
|
||||
return sunxi_gpio_setfunc(sc, pin_def, "gpio_in");
|
||||
if (flags & GPIO_PIN_OUTPUT)
|
||||
return sunxi_gpio_setfunc(sc, pin_def, "gpio_out");
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static void *
|
||||
sunxi_gpio_acquire(device_t dev, const void *data, size_t len, int flags)
|
||||
{
|
||||
struct sunxi_gpio_softc * const sc = device_private(dev);
|
||||
const struct sunxi_gpio_pins *pin_def;
|
||||
struct sunxi_gpio_pin *gpin;
|
||||
const u_int *gpio = data;
|
||||
int error;
|
||||
|
||||
if (len != 16)
|
||||
return NULL;
|
||||
|
||||
const uint8_t port = be32toh(gpio[1]) & 0xff;
|
||||
const uint8_t pin = be32toh(gpio[2]) & 0xff;
|
||||
const bool actlo = be32toh(gpio[3]) & 1;
|
||||
|
||||
pin_def = sunxi_gpio_lookup(sc, port, pin);
|
||||
if (pin_def == NULL)
|
||||
return NULL;
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
error = sunxi_gpio_ctl(sc, pin_def, flags);
|
||||
mutex_exit(&sc->sc_lock);
|
||||
|
||||
if (error != 0)
|
||||
return NULL;
|
||||
|
||||
gpin = kmem_zalloc(sizeof(*gpin), KM_SLEEP);
|
||||
gpin->pin_sc = sc;
|
||||
gpin->pin_def = pin_def;
|
||||
gpin->pin_flags = flags;
|
||||
gpin->pin_actlo = actlo;
|
||||
|
||||
return gpin;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_gpio_release(device_t dev, void *priv)
|
||||
{
|
||||
struct sunxi_gpio_pin *pin = priv;
|
||||
|
||||
sunxi_gpio_ctl(pin->pin_sc, pin->pin_def, GPIO_PIN_INPUT);
|
||||
|
||||
kmem_free(pin, sizeof(*pin));
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gpio_read(device_t dev, void *priv, bool raw)
|
||||
{
|
||||
struct sunxi_gpio_softc * const sc = device_private(dev);
|
||||
struct sunxi_gpio_pin *pin = priv;
|
||||
const struct sunxi_gpio_pins *pin_def = pin->pin_def;
|
||||
uint32_t data;
|
||||
int val;
|
||||
|
||||
KASSERT(sc == pin->pin_sc);
|
||||
|
||||
const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
|
||||
const uint32_t data_mask = __BIT(pin_def->pin);
|
||||
|
||||
/* No lock required for reads */
|
||||
data = GPIO_READ(sc, data_reg);
|
||||
val = __SHIFTOUT(data, data_mask);
|
||||
if (!raw && pin->pin_actlo)
|
||||
val = !val;
|
||||
|
||||
#ifdef SUNXI_GPIO_DEBUG
|
||||
device_printf(dev, "P%c%02d rd %08x (%d %d)\n",
|
||||
pin_def->port + 'A', pin_def->pin, data,
|
||||
__SHIFTOUT(val, data_mask), val);
|
||||
#endif
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_gpio_write(device_t dev, void *priv, int val, bool raw)
|
||||
{
|
||||
struct sunxi_gpio_softc * const sc = device_private(dev);
|
||||
struct sunxi_gpio_pin *pin = priv;
|
||||
const struct sunxi_gpio_pins *pin_def = pin->pin_def;
|
||||
uint32_t data;
|
||||
|
||||
KASSERT(sc == pin->pin_sc);
|
||||
|
||||
const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
|
||||
const uint32_t data_mask = __BIT(pin_def->pin);
|
||||
|
||||
if (!raw && pin->pin_actlo)
|
||||
val = !val;
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
data = GPIO_READ(sc, data_reg);
|
||||
data &= ~data_mask;
|
||||
data |= __SHIFTIN(val, data_mask);
|
||||
#ifdef SUNXI_GPIO_DEBUG
|
||||
device_printf(dev, "P%c%02d wr %08x -> %08x\n",
|
||||
pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, data_reg), data);
|
||||
#endif
|
||||
GPIO_WRITE(sc, data_reg, data);
|
||||
mutex_exit(&sc->sc_lock);
|
||||
}
|
||||
|
||||
static struct fdtbus_gpio_controller_func sunxi_gpio_funcs = {
|
||||
.acquire = sunxi_gpio_acquire,
|
||||
.release = sunxi_gpio_release,
|
||||
.read = sunxi_gpio_read,
|
||||
.write = sunxi_gpio_write,
|
||||
};
|
||||
|
||||
static int
|
||||
sunxi_pinctrl_set_config(device_t dev, const void *data, size_t len)
|
||||
{
|
||||
struct sunxi_gpio_softc * const sc = device_private(dev);
|
||||
const struct sunxi_gpio_pins *pin_def;
|
||||
u_int drive_strength;
|
||||
|
||||
if (len != 4)
|
||||
return -1;
|
||||
|
||||
const int phandle = fdtbus_get_phandle_from_native(be32dec(data));
|
||||
|
||||
/*
|
||||
* Required: pins, function
|
||||
* Optional: bias-disable, bias-pull-up, bias-pull-down, drive-strength
|
||||
*/
|
||||
|
||||
const char *function = fdtbus_get_string(phandle, "function");
|
||||
if (function == NULL)
|
||||
return -1;
|
||||
int pins_len = OF_getproplen(phandle, "pins");
|
||||
if (pins_len <= 0)
|
||||
return -1;
|
||||
const char *pins = fdtbus_get_string(phandle, "pins");
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
|
||||
for (pins = fdtbus_get_string(phandle, "pins");
|
||||
pins_len > 0;
|
||||
pins_len -= strlen(pins) + 1, pins += strlen(pins) + 1) {
|
||||
pin_def = sunxi_gpio_lookup_byname(sc, pins);
|
||||
if (pin_def == NULL) {
|
||||
aprint_error_dev(dev, "unknown pin name '%s'\n", pins);
|
||||
continue;
|
||||
}
|
||||
if (sunxi_gpio_setfunc(sc, pin_def, function) != 0)
|
||||
continue;
|
||||
|
||||
if (of_hasprop(phandle, "bias-disable"))
|
||||
sunxi_gpio_setpull(sc, pin_def, 0);
|
||||
else if (of_hasprop(phandle, "bias-pull-up"))
|
||||
sunxi_gpio_setpull(sc, pin_def, GPIO_PIN_PULLUP);
|
||||
else if (of_hasprop(phandle, "bias-pull-down"))
|
||||
sunxi_gpio_setpull(sc, pin_def, GPIO_PIN_PULLDOWN);
|
||||
|
||||
if (of_getprop_uint32(phandle, "drive-strength", &drive_strength) == 0)
|
||||
sunxi_gpio_setdrv(sc, pin_def, drive_strength);
|
||||
}
|
||||
|
||||
mutex_exit(&sc->sc_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fdtbus_pinctrl_controller_func sunxi_pinctrl_funcs = {
|
||||
.set_config = sunxi_pinctrl_set_config,
|
||||
};
|
||||
|
||||
static int
|
||||
sunxi_gpio_pin_read(void *priv, int pin)
|
||||
{
|
||||
struct sunxi_gpio_softc * const sc = priv;
|
||||
const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
|
||||
uint32_t data;
|
||||
int val;
|
||||
|
||||
KASSERT(pin < sc->sc_padconf->npins);
|
||||
|
||||
const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
|
||||
const uint32_t data_mask = __BIT(pin_def->pin);
|
||||
|
||||
/* No lock required for reads */
|
||||
data = GPIO_READ(sc, data_reg);
|
||||
val = __SHIFTOUT(data, data_mask);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_gpio_pin_write(void *priv, int pin, int val)
|
||||
{
|
||||
struct sunxi_gpio_softc * const sc = priv;
|
||||
const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
|
||||
uint32_t data;
|
||||
|
||||
KASSERT(pin < sc->sc_padconf->npins);
|
||||
|
||||
const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
|
||||
const uint32_t data_mask = __BIT(pin_def->pin);
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
data = GPIO_READ(sc, data_reg);
|
||||
if (val)
|
||||
data |= data_mask;
|
||||
else
|
||||
data &= ~data_mask;
|
||||
GPIO_WRITE(sc, data_reg, data);
|
||||
mutex_exit(&sc->sc_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_gpio_pin_ctl(void *priv, int pin, int flags)
|
||||
{
|
||||
struct sunxi_gpio_softc * const sc = priv;
|
||||
const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
|
||||
|
||||
KASSERT(pin < sc->sc_padconf->npins);
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
sunxi_gpio_ctl(sc, pin_def, flags);
|
||||
sunxi_gpio_setpull(sc, pin_def, flags);
|
||||
mutex_exit(&sc->sc_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_gpio_attach_ports(struct sunxi_gpio_softc *sc)
|
||||
{
|
||||
const struct sunxi_gpio_pins *pin_def;
|
||||
struct gpio_chipset_tag *gp = &sc->sc_gp;
|
||||
struct gpiobus_attach_args gba;
|
||||
u_int pin;
|
||||
|
||||
gp->gp_cookie = sc;
|
||||
gp->gp_pin_read = sunxi_gpio_pin_read;
|
||||
gp->gp_pin_write = sunxi_gpio_pin_write;
|
||||
gp->gp_pin_ctl = sunxi_gpio_pin_ctl;
|
||||
|
||||
const u_int npins = sc->sc_padconf->npins;
|
||||
sc->sc_pins = kmem_zalloc(sizeof(*sc->sc_pins) * npins, KM_SLEEP);
|
||||
|
||||
for (pin = 0; pin < sc->sc_padconf->npins; pin++) {
|
||||
pin_def = &sc->sc_padconf->pins[pin];
|
||||
sc->sc_pins[pin].pin_num = pin;
|
||||
sc->sc_pins[pin].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
|
||||
GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
|
||||
sc->sc_pins[pin].pin_state = sunxi_gpio_pin_read(sc, pin);
|
||||
strlcpy(sc->sc_pins[pin].pin_defname, pin_def->name,
|
||||
sizeof(sc->sc_pins[pin].pin_defname));
|
||||
}
|
||||
|
||||
memset(&gba, 0, sizeof(gba));
|
||||
gba.gba_gc = gp;
|
||||
gba.gba_pins = sc->sc_pins;
|
||||
gba.gba_npins = npins;
|
||||
sc->sc_gpiodev = config_found_ia(sc->sc_dev, "gpiobus", &gba, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_gpio_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compat_data(faa->faa_phandle, compat_data);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_gpio_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_gpio_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
struct fdtbus_reset *rst;
|
||||
struct clk *clk;
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
int child;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((clk = fdtbus_clock_get_index(phandle, 0)) != NULL)
|
||||
if (clk_enable(clk) != 0) {
|
||||
aprint_error(": couldn't enable clock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL)
|
||||
if (fdtbus_reset_deassert(rst) != 0) {
|
||||
aprint_error(": couldn't de-assert reset\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
|
||||
sc->sc_padconf = (void *)of_search_compatible(phandle, compat_data)->data;
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": PIO\n");
|
||||
|
||||
fdtbus_register_gpio_controller(self, phandle, &sunxi_gpio_funcs);
|
||||
|
||||
for (child = OF_child(phandle); child; child = OF_peer(child)) {
|
||||
if (!of_hasprop(child, "function") || !of_hasprop(child, "pins"))
|
||||
continue;
|
||||
fdtbus_register_pinctrl_config(self, child, &sunxi_pinctrl_funcs);
|
||||
}
|
||||
|
||||
fdtbus_pinctrl_configure();
|
||||
|
||||
sunxi_gpio_attach_ports(sc);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* $NetBSD: sunxi_gpio.h,v 1.3.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* Copyright (c) 2016 Emmanuel Vadot <manu@bidouilliste.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$
|
||||
*/
|
||||
|
||||
#ifndef _ARM_SUNXI_GPIO_H
|
||||
#define _ARM_SUNXI_GPIO_H
|
||||
|
||||
#include "opt_soc.h"
|
||||
|
||||
#define SUNXI_GPIO_MAXFUNC 8
|
||||
|
||||
struct sunxi_gpio_pins {
|
||||
const char *name;
|
||||
uint8_t port;
|
||||
uint8_t pin;
|
||||
const char *functions[SUNXI_GPIO_MAXFUNC];
|
||||
uint8_t eint_func;
|
||||
uint8_t eint_num;
|
||||
};
|
||||
|
||||
struct sunxi_gpio_padconf {
|
||||
uint32_t npins;
|
||||
const struct sunxi_gpio_pins *pins;
|
||||
};
|
||||
|
||||
#ifdef SOC_SUN6I_A31
|
||||
extern const struct sunxi_gpio_padconf sun6i_a31_padconf;
|
||||
extern const struct sunxi_gpio_padconf sun6i_a31_r_padconf;
|
||||
#endif
|
||||
|
||||
#ifdef SOC_SUN8I_A83T
|
||||
extern const struct sunxi_gpio_padconf sun8i_a83t_padconf;
|
||||
extern const struct sunxi_gpio_padconf sun8i_a83t_r_padconf;
|
||||
#endif
|
||||
|
||||
#ifdef SOC_SUN8I_H3
|
||||
extern const struct sunxi_gpio_padconf sun8i_h3_padconf;
|
||||
extern const struct sunxi_gpio_padconf sun8i_h3_r_padconf;
|
||||
#endif
|
||||
|
||||
#endif /* _ARM_SUNXI_GPIO_H */
|
|
@ -0,0 +1,857 @@
|
|||
/* $NetBSD: sunxi_mmc.c,v 1.3.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_mmc.c,v 1.3.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/gpio.h>
|
||||
|
||||
#include <dev/sdmmc/sdmmcvar.h>
|
||||
#include <dev/sdmmc/sdmmcchip.h>
|
||||
#include <dev/sdmmc/sdmmc_ioreg.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_mmc.h>
|
||||
|
||||
#define SUNXI_MMC_NDESC 16
|
||||
#define SUNXI_MMC_DMA_XFERLEN 0x10000
|
||||
#define SUNXI_MMC_DMA_FTRGLEVEL 0x20070008
|
||||
|
||||
struct sunxi_mmc_softc;
|
||||
|
||||
static int sunxi_mmc_match(device_t, cfdata_t, void *);
|
||||
static void sunxi_mmc_attach(device_t, device_t, void *);
|
||||
static void sunxi_mmc_attach_i(device_t);
|
||||
|
||||
static int sunxi_mmc_intr(void *);
|
||||
static int sunxi_mmc_idma_setup(struct sunxi_mmc_softc *);
|
||||
|
||||
static int sunxi_mmc_host_reset(sdmmc_chipset_handle_t);
|
||||
static uint32_t sunxi_mmc_host_ocr(sdmmc_chipset_handle_t);
|
||||
static int sunxi_mmc_host_maxblklen(sdmmc_chipset_handle_t);
|
||||
static int sunxi_mmc_card_detect(sdmmc_chipset_handle_t);
|
||||
static int sunxi_mmc_write_protect(sdmmc_chipset_handle_t);
|
||||
static int sunxi_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
|
||||
static int sunxi_mmc_bus_clock(sdmmc_chipset_handle_t, int);
|
||||
static int sunxi_mmc_bus_width(sdmmc_chipset_handle_t, int);
|
||||
static int sunxi_mmc_bus_rod(sdmmc_chipset_handle_t, int);
|
||||
static void sunxi_mmc_exec_command(sdmmc_chipset_handle_t,
|
||||
struct sdmmc_command *);
|
||||
static void sunxi_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
|
||||
static void sunxi_mmc_card_intr_ack(sdmmc_chipset_handle_t);
|
||||
|
||||
static struct sdmmc_chip_functions sunxi_mmc_chip_functions = {
|
||||
.host_reset = sunxi_mmc_host_reset,
|
||||
.host_ocr = sunxi_mmc_host_ocr,
|
||||
.host_maxblklen = sunxi_mmc_host_maxblklen,
|
||||
.card_detect = sunxi_mmc_card_detect,
|
||||
.write_protect = sunxi_mmc_write_protect,
|
||||
.bus_power = sunxi_mmc_bus_power,
|
||||
.bus_clock = sunxi_mmc_bus_clock,
|
||||
.bus_width = sunxi_mmc_bus_width,
|
||||
.bus_rod = sunxi_mmc_bus_rod,
|
||||
.exec_command = sunxi_mmc_exec_command,
|
||||
.card_enable_intr = sunxi_mmc_card_enable_intr,
|
||||
.card_intr_ack = sunxi_mmc_card_intr_ack,
|
||||
};
|
||||
|
||||
struct sunxi_mmc_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
bus_dma_tag_t sc_dmat;
|
||||
int sc_phandle;
|
||||
|
||||
void *sc_ih;
|
||||
kmutex_t sc_intr_lock;
|
||||
kcondvar_t sc_intr_cv;
|
||||
kcondvar_t sc_idst_cv;
|
||||
|
||||
int sc_mmc_width;
|
||||
int sc_mmc_present;
|
||||
|
||||
device_t sc_sdmmc_dev;
|
||||
|
||||
uint32_t sc_dma_ftrglevel;
|
||||
|
||||
uint32_t sc_idma_xferlen;
|
||||
bus_dma_segment_t sc_idma_segs[1];
|
||||
int sc_idma_nsegs;
|
||||
bus_size_t sc_idma_size;
|
||||
bus_dmamap_t sc_idma_map;
|
||||
int sc_idma_ndesc;
|
||||
void *sc_idma_desc;
|
||||
|
||||
uint32_t sc_intr_rint;
|
||||
uint32_t sc_intr_mint;
|
||||
uint32_t sc_idma_idst;
|
||||
|
||||
struct clk *sc_clk_ahb;
|
||||
struct clk *sc_clk_mmc;
|
||||
struct clk *sc_clk_output;
|
||||
struct clk *sc_clk_sample;
|
||||
|
||||
struct fdtbus_reset *sc_rst_ahb;
|
||||
|
||||
struct fdtbus_gpio_pin *sc_gpio_cd;
|
||||
int sc_gpio_cd_inverted;
|
||||
struct fdtbus_gpio_pin *sc_gpio_wp;
|
||||
int sc_gpio_wp_inverted;
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_mmc, sizeof(struct sunxi_mmc_softc),
|
||||
sunxi_mmc_match, sunxi_mmc_attach, NULL, NULL);
|
||||
|
||||
#define MMC_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||
#define MMC_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"allwinner,sun7i-a20-mmc",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
sunxi_mmc_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_mmc_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_mmc_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
char intrstr[128];
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_clk_ahb = fdtbus_clock_get(phandle, "ahb");
|
||||
sc->sc_clk_mmc = fdtbus_clock_get(phandle, "mmc");
|
||||
sc->sc_clk_output = fdtbus_clock_get(phandle, "output");
|
||||
sc->sc_clk_sample = fdtbus_clock_get(phandle, "sample");
|
||||
|
||||
#if notyet
|
||||
if (sc->sc_clk_ahb == NULL || sc->sc_clk_mmc == NULL ||
|
||||
sc->sc_clk_output == NULL || sc->sc_clk_sample == NULL) {
|
||||
#else
|
||||
if (sc->sc_clk_ahb == NULL || sc->sc_clk_mmc == NULL) {
|
||||
#endif
|
||||
aprint_error(": couldn't get clocks\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_rst_ahb = fdtbus_reset_get(phandle, "ahb");
|
||||
if (sc->sc_rst_ahb == NULL) {
|
||||
aprint_error(": couldn't get resets\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clk_enable(sc->sc_clk_ahb) != 0 ||
|
||||
clk_enable(sc->sc_clk_mmc) != 0) {
|
||||
aprint_error(": couldn't enable clocks\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fdtbus_reset_deassert(sc->sc_rst_ahb) != 0) {
|
||||
aprint_error(": couldn't de-assert resets\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_phandle = phandle;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
sc->sc_dmat = faa->faa_dmat;
|
||||
mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
|
||||
cv_init(&sc->sc_intr_cv, "awinmmcirq");
|
||||
cv_init(&sc->sc_idst_cv, "awinmmcdma");
|
||||
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": SD/MMC controller\n");
|
||||
|
||||
sc->sc_gpio_cd = fdtbus_gpio_acquire(phandle, "cd-gpios",
|
||||
GPIO_PIN_INPUT);
|
||||
sc->sc_gpio_wp = fdtbus_gpio_acquire(phandle, "wp-gpios",
|
||||
GPIO_PIN_INPUT);
|
||||
|
||||
sc->sc_gpio_cd_inverted = of_hasprop(phandle, "cd-inverted") ? 0 : 1;
|
||||
sc->sc_gpio_wp_inverted = of_hasprop(phandle, "wp-inverted") ? 0 : 1;
|
||||
|
||||
sc->sc_dma_ftrglevel = SUNXI_MMC_DMA_FTRGLEVEL;
|
||||
|
||||
if (sunxi_mmc_idma_setup(sc) != 0) {
|
||||
aprint_error_dev(self, "failed to setup DMA\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
|
||||
aprint_error_dev(self, "failed to decode interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_BIO, FDT_INTR_MPSAFE,
|
||||
sunxi_mmc_intr, sc);
|
||||
if (sc->sc_ih == NULL) {
|
||||
aprint_error_dev(self, "failed to establish interrupt on %s\n",
|
||||
intrstr);
|
||||
return;
|
||||
}
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
|
||||
config_interrupts(self, sunxi_mmc_attach_i);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_idma_setup(struct sunxi_mmc_softc *sc)
|
||||
{
|
||||
int error;
|
||||
|
||||
sc->sc_idma_xferlen = SUNXI_MMC_DMA_XFERLEN;
|
||||
|
||||
sc->sc_idma_ndesc = SUNXI_MMC_NDESC;
|
||||
sc->sc_idma_size = sizeof(struct sunxi_mmc_idma_descriptor) *
|
||||
sc->sc_idma_ndesc;
|
||||
error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 0,
|
||||
sc->sc_idma_size, sc->sc_idma_segs, 1,
|
||||
&sc->sc_idma_nsegs, BUS_DMA_WAITOK);
|
||||
if (error)
|
||||
return error;
|
||||
error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs,
|
||||
sc->sc_idma_nsegs, sc->sc_idma_size,
|
||||
&sc->sc_idma_desc, BUS_DMA_WAITOK);
|
||||
if (error)
|
||||
goto free;
|
||||
error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1,
|
||||
sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map);
|
||||
if (error)
|
||||
goto unmap;
|
||||
error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map,
|
||||
sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK);
|
||||
if (error)
|
||||
goto destroy;
|
||||
return 0;
|
||||
|
||||
destroy:
|
||||
bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map);
|
||||
unmap:
|
||||
bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size);
|
||||
free:
|
||||
bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_set_clock(struct sunxi_mmc_softc *sc, u_int freq)
|
||||
{
|
||||
return clk_set_rate(sc->sc_clk_mmc, freq * 1000);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_mmc_attach_i(device_t self)
|
||||
{
|
||||
struct sunxi_mmc_softc *sc = device_private(self);
|
||||
struct sdmmcbus_attach_args saa;
|
||||
uint32_t width;
|
||||
|
||||
sunxi_mmc_host_reset(sc);
|
||||
sunxi_mmc_bus_width(sc, 1);
|
||||
sunxi_mmc_set_clock(sc, 400);
|
||||
|
||||
if (of_getprop_uint32(sc->sc_phandle, "bus-width", &width) != 0)
|
||||
width = 4;
|
||||
|
||||
memset(&saa, 0, sizeof(saa));
|
||||
saa.saa_busname = "sdmmc";
|
||||
saa.saa_sct = &sunxi_mmc_chip_functions;
|
||||
saa.saa_sch = sc;
|
||||
saa.saa_dmat = sc->sc_dmat;
|
||||
saa.saa_clkmin = 400;
|
||||
saa.saa_clkmax = 52000;
|
||||
saa.saa_caps = SMC_CAPS_DMA |
|
||||
SMC_CAPS_MULTI_SEG_DMA |
|
||||
SMC_CAPS_AUTO_STOP |
|
||||
SMC_CAPS_SD_HIGHSPEED |
|
||||
SMC_CAPS_MMC_HIGHSPEED;
|
||||
if (width == 4)
|
||||
saa.saa_caps |= SMC_CAPS_4BIT_MODE;
|
||||
if (width == 8)
|
||||
saa.saa_caps |= SMC_CAPS_8BIT_MODE;
|
||||
|
||||
if (sc->sc_gpio_cd)
|
||||
saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
|
||||
|
||||
sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_intr(void *priv)
|
||||
{
|
||||
struct sunxi_mmc_softc *sc = priv;
|
||||
uint32_t idst, rint, mint;
|
||||
|
||||
mutex_enter(&sc->sc_intr_lock);
|
||||
idst = MMC_READ(sc, SUNXI_MMC_IDST);
|
||||
rint = MMC_READ(sc, SUNXI_MMC_RINT);
|
||||
mint = MMC_READ(sc, SUNXI_MMC_MINT);
|
||||
if (!idst && !rint && !mint) {
|
||||
mutex_exit(&sc->sc_intr_lock);
|
||||
return 0;
|
||||
}
|
||||
MMC_WRITE(sc, SUNXI_MMC_IDST, idst);
|
||||
MMC_WRITE(sc, SUNXI_MMC_RINT, rint);
|
||||
MMC_WRITE(sc, SUNXI_MMC_MINT, mint);
|
||||
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
device_printf(sc->sc_dev, "mmc intr idst=%08X rint=%08X mint=%08X\n",
|
||||
idst, rint, mint);
|
||||
#endif
|
||||
|
||||
if (idst) {
|
||||
sc->sc_idma_idst |= idst;
|
||||
cv_broadcast(&sc->sc_idst_cv);
|
||||
}
|
||||
|
||||
if (rint) {
|
||||
sc->sc_intr_rint |= rint;
|
||||
cv_broadcast(&sc->sc_intr_cv);
|
||||
}
|
||||
|
||||
mutex_exit(&sc->sc_intr_lock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_wait_rint(struct sunxi_mmc_softc *sc, uint32_t mask, int timeout)
|
||||
{
|
||||
int retry;
|
||||
int error;
|
||||
|
||||
KASSERT(mutex_owned(&sc->sc_intr_lock));
|
||||
|
||||
if (sc->sc_intr_rint & mask)
|
||||
return 0;
|
||||
|
||||
retry = timeout / hz;
|
||||
|
||||
while (retry > 0) {
|
||||
error = cv_timedwait(&sc->sc_intr_cv,
|
||||
&sc->sc_intr_lock, hz);
|
||||
if (error && error != EWOULDBLOCK)
|
||||
return error;
|
||||
if (sc->sc_intr_rint & mask)
|
||||
return 0;
|
||||
--retry;
|
||||
}
|
||||
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_host_reset(sdmmc_chipset_handle_t sch)
|
||||
{
|
||||
struct sunxi_mmc_softc *sc = sch;
|
||||
int retry = 1000;
|
||||
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_normal_dev(sc->sc_dev, "host reset\n");
|
||||
#endif
|
||||
|
||||
MMC_WRITE(sc, SUNXI_MMC_GCTRL,
|
||||
MMC_READ(sc, SUNXI_MMC_GCTRL) | SUNXI_MMC_GCTRL_RESET);
|
||||
while (--retry > 0) {
|
||||
if (!(MMC_READ(sc, SUNXI_MMC_GCTRL) & SUNXI_MMC_GCTRL_RESET))
|
||||
break;
|
||||
delay(100);
|
||||
}
|
||||
|
||||
MMC_WRITE(sc, SUNXI_MMC_TIMEOUT, 0xffffffff);
|
||||
|
||||
MMC_WRITE(sc, SUNXI_MMC_IMASK,
|
||||
SUNXI_MMC_INT_CMD_DONE | SUNXI_MMC_INT_ERROR |
|
||||
SUNXI_MMC_INT_DATA_OVER | SUNXI_MMC_INT_AUTO_CMD_DONE);
|
||||
|
||||
MMC_WRITE(sc, SUNXI_MMC_GCTRL,
|
||||
MMC_READ(sc, SUNXI_MMC_GCTRL) | SUNXI_MMC_GCTRL_INTEN);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
sunxi_mmc_host_ocr(sdmmc_chipset_handle_t sch)
|
||||
{
|
||||
return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_host_maxblklen(sdmmc_chipset_handle_t sch)
|
||||
{
|
||||
return 8192;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_card_detect(sdmmc_chipset_handle_t sch)
|
||||
{
|
||||
struct sunxi_mmc_softc *sc = sch;
|
||||
|
||||
if (sc->sc_gpio_cd == NULL) {
|
||||
return 1; /* no card detect pin, assume present */
|
||||
} else {
|
||||
int v = 0, i;
|
||||
for (i = 0; i < 5; i++) {
|
||||
v += (fdtbus_gpio_read(sc->sc_gpio_cd) ^
|
||||
sc->sc_gpio_cd_inverted);
|
||||
delay(1000);
|
||||
}
|
||||
if (v == 5)
|
||||
sc->sc_mmc_present = 0;
|
||||
else if (v == 0)
|
||||
sc->sc_mmc_present = 1;
|
||||
return sc->sc_mmc_present;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_write_protect(sdmmc_chipset_handle_t sch)
|
||||
{
|
||||
struct sunxi_mmc_softc *sc = sch;
|
||||
|
||||
if (sc->sc_gpio_wp == NULL) {
|
||||
return 0; /* no write protect pin, assume rw */
|
||||
} else {
|
||||
return fdtbus_gpio_read(sc->sc_gpio_wp) ^
|
||||
sc->sc_gpio_wp_inverted;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_update_clock(struct sunxi_mmc_softc *sc)
|
||||
{
|
||||
uint32_t cmd;
|
||||
int retry;
|
||||
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_normal_dev(sc->sc_dev, "update clock\n");
|
||||
#endif
|
||||
|
||||
cmd = SUNXI_MMC_CMD_START |
|
||||
SUNXI_MMC_CMD_UPCLK_ONLY |
|
||||
SUNXI_MMC_CMD_WAIT_PRE_OVER;
|
||||
MMC_WRITE(sc, SUNXI_MMC_CMD, cmd);
|
||||
retry = 0xfffff;
|
||||
while (--retry > 0) {
|
||||
if (!(MMC_READ(sc, SUNXI_MMC_CMD) & SUNXI_MMC_CMD_START))
|
||||
break;
|
||||
delay(10);
|
||||
}
|
||||
|
||||
if (retry == 0) {
|
||||
aprint_error_dev(sc->sc_dev, "timeout updating clock\n");
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
device_printf(sc->sc_dev, "GCTRL: 0x%08x\n",
|
||||
MMC_READ(sc, SUNXI_MMC_GCTRL));
|
||||
device_printf(sc->sc_dev, "CLKCR: 0x%08x\n",
|
||||
MMC_READ(sc, SUNXI_MMC_CLKCR));
|
||||
device_printf(sc->sc_dev, "TIMEOUT: 0x%08x\n",
|
||||
MMC_READ(sc, SUNXI_MMC_TIMEOUT));
|
||||
device_printf(sc->sc_dev, "WIDTH: 0x%08x\n",
|
||||
MMC_READ(sc, SUNXI_MMC_WIDTH));
|
||||
device_printf(sc->sc_dev, "CMD: 0x%08x\n",
|
||||
MMC_READ(sc, SUNXI_MMC_CMD));
|
||||
device_printf(sc->sc_dev, "MINT: 0x%08x\n",
|
||||
MMC_READ(sc, SUNXI_MMC_MINT));
|
||||
device_printf(sc->sc_dev, "RINT: 0x%08x\n",
|
||||
MMC_READ(sc, SUNXI_MMC_RINT));
|
||||
device_printf(sc->sc_dev, "STATUS: 0x%08x\n",
|
||||
MMC_READ(sc, SUNXI_MMC_STATUS));
|
||||
#endif
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
|
||||
{
|
||||
struct sunxi_mmc_softc *sc = sch;
|
||||
uint32_t clkcr;
|
||||
|
||||
clkcr = MMC_READ(sc, SUNXI_MMC_CLKCR);
|
||||
if (clkcr & SUNXI_MMC_CLKCR_CARDCLKON) {
|
||||
clkcr &= ~SUNXI_MMC_CLKCR_CARDCLKON;
|
||||
MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr);
|
||||
if (sunxi_mmc_update_clock(sc) != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (freq) {
|
||||
|
||||
clkcr &= ~SUNXI_MMC_CLKCR_DIV;
|
||||
MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr);
|
||||
if (sunxi_mmc_update_clock(sc) != 0)
|
||||
return 1;
|
||||
|
||||
if (sunxi_mmc_set_clock(sc, freq) != 0)
|
||||
return 1;
|
||||
|
||||
clkcr |= SUNXI_MMC_CLKCR_CARDCLKON;
|
||||
MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr);
|
||||
if (sunxi_mmc_update_clock(sc) != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_bus_width(sdmmc_chipset_handle_t sch, int width)
|
||||
{
|
||||
struct sunxi_mmc_softc *sc = sch;
|
||||
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_normal_dev(sc->sc_dev, "width = %d\n", width);
|
||||
#endif
|
||||
|
||||
switch (width) {
|
||||
case 1:
|
||||
MMC_WRITE(sc, SUNXI_MMC_WIDTH, SUNXI_MMC_WIDTH_1);
|
||||
break;
|
||||
case 4:
|
||||
MMC_WRITE(sc, SUNXI_MMC_WIDTH, SUNXI_MMC_WIDTH_4);
|
||||
break;
|
||||
case 8:
|
||||
MMC_WRITE(sc, SUNXI_MMC_WIDTH, SUNXI_MMC_WIDTH_8);
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
sc->sc_mmc_width = width;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_bus_rod(sdmmc_chipset_handle_t sch, int on)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_mmc_dma_prepare(struct sunxi_mmc_softc *sc, struct sdmmc_command *cmd)
|
||||
{
|
||||
struct sunxi_mmc_idma_descriptor *dma = sc->sc_idma_desc;
|
||||
bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr;
|
||||
bus_size_t off;
|
||||
int desc, resid, seg;
|
||||
uint32_t val;
|
||||
|
||||
desc = 0;
|
||||
for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
|
||||
bus_addr_t paddr = cmd->c_dmamap->dm_segs[seg].ds_addr;
|
||||
bus_size_t len = cmd->c_dmamap->dm_segs[seg].ds_len;
|
||||
resid = min(len, cmd->c_resid);
|
||||
off = 0;
|
||||
while (resid > 0) {
|
||||
if (desc == sc->sc_idma_ndesc)
|
||||
break;
|
||||
len = min(sc->sc_idma_xferlen, resid);
|
||||
dma[desc].dma_buf_size = htole32(len);
|
||||
dma[desc].dma_buf_addr = htole32(paddr + off);
|
||||
dma[desc].dma_config = htole32(SUNXI_MMC_IDMA_CONFIG_CH |
|
||||
SUNXI_MMC_IDMA_CONFIG_OWN);
|
||||
cmd->c_resid -= len;
|
||||
resid -= len;
|
||||
off += len;
|
||||
if (desc == 0) {
|
||||
dma[desc].dma_config |= htole32(SUNXI_MMC_IDMA_CONFIG_FD);
|
||||
}
|
||||
if (cmd->c_resid == 0) {
|
||||
dma[desc].dma_config |= htole32(SUNXI_MMC_IDMA_CONFIG_LD);
|
||||
dma[desc].dma_config |= htole32(SUNXI_MMC_IDMA_CONFIG_ER);
|
||||
dma[desc].dma_next = 0;
|
||||
} else {
|
||||
dma[desc].dma_config |=
|
||||
htole32(SUNXI_MMC_IDMA_CONFIG_DIC);
|
||||
dma[desc].dma_next = htole32(
|
||||
desc_paddr + ((desc+1) *
|
||||
sizeof(struct sunxi_mmc_idma_descriptor)));
|
||||
}
|
||||
++desc;
|
||||
}
|
||||
}
|
||||
if (desc == sc->sc_idma_ndesc) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"not enough descriptors for %d byte transfer!\n",
|
||||
cmd->c_datalen);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
|
||||
sc->sc_idma_size, BUS_DMASYNC_PREWRITE);
|
||||
|
||||
sc->sc_idma_idst = 0;
|
||||
|
||||
val = MMC_READ(sc, SUNXI_MMC_GCTRL);
|
||||
val |= SUNXI_MMC_GCTRL_DMAEN;
|
||||
val |= SUNXI_MMC_GCTRL_INTEN;
|
||||
MMC_WRITE(sc, SUNXI_MMC_GCTRL, val);
|
||||
val |= SUNXI_MMC_GCTRL_DMARESET;
|
||||
MMC_WRITE(sc, SUNXI_MMC_GCTRL, val);
|
||||
MMC_WRITE(sc, SUNXI_MMC_DMAC, SUNXI_MMC_DMAC_SOFTRESET);
|
||||
MMC_WRITE(sc, SUNXI_MMC_DMAC,
|
||||
SUNXI_MMC_DMAC_IDMA_ON|SUNXI_MMC_DMAC_FIX_BURST);
|
||||
val = MMC_READ(sc, SUNXI_MMC_IDIE);
|
||||
val &= ~(SUNXI_MMC_IDST_RECEIVE_INT|SUNXI_MMC_IDST_TRANSMIT_INT);
|
||||
if (cmd->c_flags & SCF_CMD_READ)
|
||||
val |= SUNXI_MMC_IDST_RECEIVE_INT;
|
||||
else
|
||||
val |= SUNXI_MMC_IDST_TRANSMIT_INT;
|
||||
MMC_WRITE(sc, SUNXI_MMC_IDIE, val);
|
||||
MMC_WRITE(sc, SUNXI_MMC_DLBA, desc_paddr);
|
||||
MMC_WRITE(sc, SUNXI_MMC_FTRGLEVEL, sc->sc_dma_ftrglevel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_mmc_dma_complete(struct sunxi_mmc_softc *sc)
|
||||
{
|
||||
bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
|
||||
sc->sc_idma_size, BUS_DMASYNC_POSTWRITE);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
|
||||
{
|
||||
struct sunxi_mmc_softc *sc = sch;
|
||||
uint32_t cmdval = SUNXI_MMC_CMD_START;
|
||||
int retry;
|
||||
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_normal_dev(sc->sc_dev,
|
||||
"opcode %d flags 0x%x data %p datalen %d blklen %d\n",
|
||||
cmd->c_opcode, cmd->c_flags, cmd->c_data, cmd->c_datalen,
|
||||
cmd->c_blklen);
|
||||
#endif
|
||||
|
||||
mutex_enter(&sc->sc_intr_lock);
|
||||
|
||||
if (cmd->c_opcode == 0)
|
||||
cmdval |= SUNXI_MMC_CMD_SEND_INIT_SEQ;
|
||||
if (cmd->c_flags & SCF_RSP_PRESENT)
|
||||
cmdval |= SUNXI_MMC_CMD_RSP_EXP;
|
||||
if (cmd->c_flags & SCF_RSP_136)
|
||||
cmdval |= SUNXI_MMC_CMD_LONG_RSP;
|
||||
if (cmd->c_flags & SCF_RSP_CRC)
|
||||
cmdval |= SUNXI_MMC_CMD_CHECK_RSP_CRC;
|
||||
|
||||
if (cmd->c_datalen > 0) {
|
||||
unsigned int nblks;
|
||||
|
||||
cmdval |= SUNXI_MMC_CMD_DATA_EXP | SUNXI_MMC_CMD_WAIT_PRE_OVER;
|
||||
if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
|
||||
cmdval |= SUNXI_MMC_CMD_WRITE;
|
||||
}
|
||||
|
||||
nblks = cmd->c_datalen / cmd->c_blklen;
|
||||
if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
|
||||
++nblks;
|
||||
|
||||
if (nblks > 1) {
|
||||
cmdval |= SUNXI_MMC_CMD_SEND_AUTO_STOP;
|
||||
}
|
||||
|
||||
MMC_WRITE(sc, SUNXI_MMC_BLKSZ, cmd->c_blklen);
|
||||
MMC_WRITE(sc, SUNXI_MMC_BYTECNT, nblks * cmd->c_blklen);
|
||||
}
|
||||
|
||||
sc->sc_intr_rint = 0;
|
||||
|
||||
MMC_WRITE(sc, SUNXI_MMC_A12A,
|
||||
(cmdval & SUNXI_MMC_CMD_SEND_AUTO_STOP) ? 0 : 0xffff);
|
||||
|
||||
MMC_WRITE(sc, SUNXI_MMC_ARG, cmd->c_arg);
|
||||
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_normal_dev(sc->sc_dev, "cmdval = %08x\n", cmdval);
|
||||
#endif
|
||||
|
||||
if (cmd->c_datalen == 0) {
|
||||
MMC_WRITE(sc, SUNXI_MMC_CMD, cmdval | cmd->c_opcode);
|
||||
} else {
|
||||
cmd->c_resid = cmd->c_datalen;
|
||||
cmd->c_error = sunxi_mmc_dma_prepare(sc, cmd);
|
||||
MMC_WRITE(sc, SUNXI_MMC_CMD, cmdval | cmd->c_opcode);
|
||||
if (cmd->c_error == 0) {
|
||||
const uint32_t idst_mask =
|
||||
SUNXI_MMC_IDST_ERROR | SUNXI_MMC_IDST_COMPLETE;
|
||||
retry = 10;
|
||||
while ((sc->sc_idma_idst & idst_mask) == 0) {
|
||||
if (retry-- == 0) {
|
||||
cmd->c_error = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
cv_timedwait(&sc->sc_idst_cv,
|
||||
&sc->sc_intr_lock, hz);
|
||||
}
|
||||
}
|
||||
sunxi_mmc_dma_complete(sc);
|
||||
if (sc->sc_idma_idst & SUNXI_MMC_IDST_ERROR) {
|
||||
cmd->c_error = EIO;
|
||||
} else if (!(sc->sc_idma_idst & SUNXI_MMC_IDST_COMPLETE)) {
|
||||
cmd->c_error = ETIMEDOUT;
|
||||
}
|
||||
if (cmd->c_error) {
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"xfer failed, error %d\n", cmd->c_error);
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
cmd->c_error = sunxi_mmc_wait_rint(sc,
|
||||
SUNXI_MMC_INT_ERROR|SUNXI_MMC_INT_CMD_DONE, hz * 10);
|
||||
if (cmd->c_error == 0 && (sc->sc_intr_rint & SUNXI_MMC_INT_ERROR)) {
|
||||
if (sc->sc_intr_rint & SUNXI_MMC_INT_RESP_TIMEOUT) {
|
||||
cmd->c_error = ETIMEDOUT;
|
||||
} else {
|
||||
cmd->c_error = EIO;
|
||||
}
|
||||
}
|
||||
if (cmd->c_error) {
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"cmd failed, error %d\n", cmd->c_error);
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (cmd->c_datalen > 0) {
|
||||
cmd->c_error = sunxi_mmc_wait_rint(sc,
|
||||
SUNXI_MMC_INT_ERROR|
|
||||
SUNXI_MMC_INT_AUTO_CMD_DONE|
|
||||
SUNXI_MMC_INT_DATA_OVER,
|
||||
hz*10);
|
||||
if (cmd->c_error == 0 &&
|
||||
(sc->sc_intr_rint & SUNXI_MMC_INT_ERROR)) {
|
||||
cmd->c_error = ETIMEDOUT;
|
||||
}
|
||||
if (cmd->c_error) {
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"data timeout, rint = %08x\n",
|
||||
sc->sc_intr_rint);
|
||||
#endif
|
||||
cmd->c_error = ETIMEDOUT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->c_flags & SCF_RSP_PRESENT) {
|
||||
if (cmd->c_flags & SCF_RSP_136) {
|
||||
cmd->c_resp[0] = MMC_READ(sc, SUNXI_MMC_RESP0);
|
||||
cmd->c_resp[1] = MMC_READ(sc, SUNXI_MMC_RESP1);
|
||||
cmd->c_resp[2] = MMC_READ(sc, SUNXI_MMC_RESP2);
|
||||
cmd->c_resp[3] = MMC_READ(sc, SUNXI_MMC_RESP3);
|
||||
if (cmd->c_flags & SCF_RSP_CRC) {
|
||||
cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
|
||||
(cmd->c_resp[1] << 24);
|
||||
cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
|
||||
(cmd->c_resp[2] << 24);
|
||||
cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
|
||||
(cmd->c_resp[3] << 24);
|
||||
cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
|
||||
}
|
||||
} else {
|
||||
cmd->c_resp[0] = MMC_READ(sc, SUNXI_MMC_RESP0);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
cmd->c_flags |= SCF_ITSDONE;
|
||||
mutex_exit(&sc->sc_intr_lock);
|
||||
|
||||
if (cmd->c_error) {
|
||||
#ifdef SUNXI_MMC_DEBUG
|
||||
aprint_error_dev(sc->sc_dev, "i/o error %d\n", cmd->c_error);
|
||||
#endif
|
||||
MMC_WRITE(sc, SUNXI_MMC_GCTRL,
|
||||
MMC_READ(sc, SUNXI_MMC_GCTRL) |
|
||||
SUNXI_MMC_GCTRL_DMARESET | SUNXI_MMC_GCTRL_FIFORESET);
|
||||
for (retry = 0; retry < 1000; retry++) {
|
||||
if (!(MMC_READ(sc, SUNXI_MMC_GCTRL) & SUNXI_MMC_GCTRL_RESET))
|
||||
break;
|
||||
delay(10);
|
||||
}
|
||||
sunxi_mmc_update_clock(sc);
|
||||
}
|
||||
|
||||
MMC_WRITE(sc, SUNXI_MMC_GCTRL,
|
||||
MMC_READ(sc, SUNXI_MMC_GCTRL) | SUNXI_MMC_GCTRL_FIFORESET);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_mmc_card_intr_ack(sdmmc_chipset_handle_t sch)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/* $NetBSD: sunxi_mmc.h,v 1.2.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_SUNXI_MMC_H
|
||||
#define _ARM_SUNXI_MMC_H
|
||||
|
||||
#define SUNXI_MMC_GCTRL 0x0000
|
||||
#define SUNXI_MMC_CLKCR 0x0004
|
||||
#define SUNXI_MMC_TIMEOUT 0x0008
|
||||
#define SUNXI_MMC_WIDTH 0x000C
|
||||
#define SUNXI_MMC_BLKSZ 0x0010
|
||||
#define SUNXI_MMC_BYTECNT 0x0014
|
||||
#define SUNXI_MMC_CMD 0x0018
|
||||
#define SUNXI_MMC_ARG 0x001C
|
||||
#define SUNXI_MMC_RESP0 0x0020
|
||||
#define SUNXI_MMC_RESP1 0x0024
|
||||
#define SUNXI_MMC_RESP2 0x0028
|
||||
#define SUNXI_MMC_RESP3 0x002C
|
||||
#define SUNXI_MMC_IMASK 0x0030
|
||||
#define SUNXI_MMC_MINT 0x0034
|
||||
#define SUNXI_MMC_RINT 0x0038
|
||||
#define SUNXI_MMC_STATUS 0x003C
|
||||
#define SUNXI_MMC_FTRGLEVEL 0x0040
|
||||
#define SUNXI_MMC_FUNCSEL 0x0044
|
||||
#define SUNXI_MMC_CBCR 0x0048
|
||||
#define SUNXI_MMC_BBCR 0x004C
|
||||
#define SUNXI_MMC_DBGC 0x0050
|
||||
#define SUNXI_MMC_A12A 0x0058 /* A80 */
|
||||
#define SUNXI_MMC_HWRST 0x0078 /* A80 */
|
||||
#define SUNXI_MMC_DMAC 0x0080
|
||||
#define SUNXI_MMC_DLBA 0x0084
|
||||
#define SUNXI_MMC_IDST 0x0088
|
||||
#define SUNXI_MMC_IDIE 0x008C
|
||||
#define SUNXI_MMC_CHDA 0x0090
|
||||
#define SUNXI_MMC_CBDA 0x0094
|
||||
#define SUNXI_MMC_FIFO 0x0100
|
||||
#define SUNXI_MMC_GCTRL_ACCESS_BY_AHB __BIT(31)
|
||||
#define SUNXI_MMC_GCTRL_WAIT_MEM_ACCESS_DONE __BIT(30)
|
||||
#define SUNXI_MMC_GCTRL_DDR_MODE __BIT(10)
|
||||
#define SUNXI_MMC_GCTRL_DEBOUNCEEN __BIT(8)
|
||||
#define SUNXI_MMC_GCTRL_DMAEN __BIT(5)
|
||||
#define SUNXI_MMC_GCTRL_INTEN __BIT(4)
|
||||
#define SUNXI_MMC_GCTRL_DMARESET __BIT(2)
|
||||
#define SUNXI_MMC_GCTRL_FIFORESET __BIT(1)
|
||||
#define SUNXI_MMC_GCTRL_SOFTRESET __BIT(0)
|
||||
#define SUNXI_MMC_GCTRL_RESET \
|
||||
(SUNXI_MMC_GCTRL_SOFTRESET | SUNXI_MMC_GCTRL_FIFORESET | \
|
||||
SUNXI_MMC_GCTRL_DMARESET)
|
||||
#define SUNXI_MMC_CLKCR_LOWPOWERON __BIT(17)
|
||||
#define SUNXI_MMC_CLKCR_CARDCLKON __BIT(16)
|
||||
#define SUNXI_MMC_CLKCR_DIV __BITS(15,0)
|
||||
#define SUNXI_MMC_WIDTH_1 0
|
||||
#define SUNXI_MMC_WIDTH_4 1
|
||||
#define SUNXI_MMC_WIDTH_8 2
|
||||
#define SUNXI_MMC_CMD_START __BIT(31)
|
||||
#define SUNXI_MMC_CMD_USE_HOLD_REG __BIT(29)
|
||||
#define SUNXI_MMC_CMD_VOL_SWITCH __BIT(28)
|
||||
#define SUNXI_MMC_CMD_BOOT_ABORT __BIT(27)
|
||||
#define SUNXI_MMC_CMD_BOOT_ACK_EXP __BIT(26)
|
||||
#define SUNXI_MMC_CMD_ALT_BOOT_OPT __BIT(25)
|
||||
#define SUNXI_MMC_CMD_ENBOOT __BIT(24)
|
||||
#define SUNXI_MMC_CMD_CCS_EXP __BIT(23)
|
||||
#define SUNXI_MMC_CMD_RD_CEATA_DEV __BIT(22)
|
||||
#define SUNXI_MMC_CMD_UPCLK_ONLY __BIT(21)
|
||||
#define SUNXI_MMC_CMD_SEND_INIT_SEQ __BIT(15)
|
||||
#define SUNXI_MMC_CMD_STOP_ABORT_CMD __BIT(14)
|
||||
#define SUNXI_MMC_CMD_WAIT_PRE_OVER __BIT(13)
|
||||
#define SUNXI_MMC_CMD_SEND_AUTO_STOP __BIT(12)
|
||||
#define SUNXI_MMC_CMD_SEQMOD __BIT(11)
|
||||
#define SUNXI_MMC_CMD_WRITE __BIT(10)
|
||||
#define SUNXI_MMC_CMD_DATA_EXP __BIT(9)
|
||||
#define SUNXI_MMC_CMD_CHECK_RSP_CRC __BIT(8)
|
||||
#define SUNXI_MMC_CMD_LONG_RSP __BIT(7)
|
||||
#define SUNXI_MMC_CMD_RSP_EXP __BIT(6)
|
||||
#define SUNXI_MMC_INT_CARD_REMOVE __BIT(31)
|
||||
#define SUNXI_MMC_INT_CARD_INSERT __BIT(30)
|
||||
#define SUNXI_MMC_INT_SDIO_INT __BIT(16)
|
||||
#define SUNXI_MMC_INT_END_BIT_ERR __BIT(15)
|
||||
#define SUNXI_MMC_INT_AUTO_CMD_DONE __BIT(14)
|
||||
#define SUNXI_MMC_INT_START_BIT_ERR __BIT(13)
|
||||
#define SUNXI_MMC_INT_HW_LOCKED __BIT(12)
|
||||
#define SUNXI_MMC_INT_FIFO_RUN_ERR __BIT(11)
|
||||
#define SUNXI_MMC_INT_VOL_CHG_DONE __BIT(10)
|
||||
#define SUNXI_MMC_INT_DATA_STARVE __BIT(10)
|
||||
#define SUNXI_MMC_INT_BOOT_START __BIT(9)
|
||||
#define SUNXI_MMC_INT_DATA_TIMEOUT __BIT(9)
|
||||
#define SUNXI_MMC_INT_ACK_RCV __BIT(8)
|
||||
#define SUNXI_MMC_INT_RESP_TIMEOUT __BIT(8)
|
||||
#define SUNXI_MMC_INT_DATA_CRC_ERR __BIT(7)
|
||||
#define SUNXI_MMC_INT_RESP_CRC_ERR __BIT(6)
|
||||
#define SUNXI_MMC_INT_RX_DATA_REQ __BIT(5)
|
||||
#define SUNXI_MMC_INT_TX_DATA_REQ __BIT(4)
|
||||
#define SUNXI_MMC_INT_DATA_OVER __BIT(3)
|
||||
#define SUNXI_MMC_INT_CMD_DONE __BIT(2)
|
||||
#define SUNXI_MMC_INT_RESP_ERR __BIT(1)
|
||||
#define SUNXI_MMC_INT_ERROR \
|
||||
(SUNXI_MMC_INT_RESP_ERR | SUNXI_MMC_INT_RESP_CRC_ERR | \
|
||||
SUNXI_MMC_INT_DATA_CRC_ERR | SUNXI_MMC_INT_RESP_TIMEOUT | \
|
||||
SUNXI_MMC_INT_FIFO_RUN_ERR | SUNXI_MMC_INT_HW_LOCKED | \
|
||||
SUNXI_MMC_INT_START_BIT_ERR | SUNXI_MMC_INT_END_BIT_ERR)
|
||||
#define SUNXI_MMC_STATUS_DMAREQ __BIT(31)
|
||||
#define SUNXI_MMC_STATUS_DATA_FSM_BUSY __BIT(10)
|
||||
#define SUNXI_MMC_STATUS_CARD_DATA_BUSY __BIT(9)
|
||||
#define SUNXI_MMC_STATUS_CARD_PRESENT __BIT(8)
|
||||
#define SUNXI_MMC_STATUS_FIFO_FULL __BIT(3)
|
||||
#define SUNXI_MMC_STATUS_FIFO_EMPTY __BIT(2)
|
||||
#define SUNXI_MMC_STATUS_TXWL_FLAG __BIT(1)
|
||||
#define SUNXI_MMC_STATUS_RXWL_FLAG __BIT(0)
|
||||
#define SUNXI_MMC_FUNCSEL_CEATA_DEV_INTEN __BIT(10)
|
||||
#define SUNXI_MMC_FUNCSEL_SEND_AUTO_STOP_CCSD __BIT(9)
|
||||
#define SUNXI_MMC_FUNCSEL_SEND_CCSD __BIT(8)
|
||||
#define SUNXI_MMC_FUNCSEL_ABT_RD_DATA __BIT(2)
|
||||
#define SUNXI_MMC_FUNCSEL_SDIO_RD_WAIT __BIT(1)
|
||||
#define SUNXI_MMC_FUNCSEL_SEND_IRQ_RSP __BIT(0)
|
||||
#define SUNXI_MMC_DMAC_REFETCH_DES __BIT(31)
|
||||
#define SUNXI_MMC_DMAC_IDMA_ON __BIT(7)
|
||||
#define SUNXI_MMC_DMAC_FIX_BURST __BIT(1)
|
||||
#define SUNXI_MMC_DMAC_SOFTRESET __BIT(0)
|
||||
#define SUNXI_MMC_IDST_HOST_ABT __BIT(10)
|
||||
#define SUNXI_MMC_IDST_ABNORMAL_INT_SUM __BIT(9)
|
||||
#define SUNXI_MMC_IDST_NORMAL_INT_SUM __BIT(8)
|
||||
#define SUNXI_MMC_IDST_CARD_ERR_SUM __BIT(5)
|
||||
#define SUNXI_MMC_IDST_DES_INVALID __BIT(4)
|
||||
#define SUNXI_MMC_IDST_FATAL_BUS_ERR __BIT(2)
|
||||
#define SUNXI_MMC_IDST_RECEIVE_INT __BIT(1)
|
||||
#define SUNXI_MMC_IDST_TRANSMIT_INT __BIT(0)
|
||||
#define SUNXI_MMC_IDST_ERROR \
|
||||
(SUNXI_MMC_IDST_ABNORMAL_INT_SUM | SUNXI_MMC_IDST_CARD_ERR_SUM | \
|
||||
SUNXI_MMC_IDST_DES_INVALID | SUNXI_MMC_IDST_FATAL_BUS_ERR)
|
||||
#define SUNXI_MMC_IDST_COMPLETE \
|
||||
(SUNXI_MMC_IDST_RECEIVE_INT | SUNXI_MMC_IDST_TRANSMIT_INT)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_DIC __BIT(1)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_LD __BIT(2)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_FD __BIT(3)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_CH __BIT(4)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_ER __BIT(5)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_CES __BIT(30)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_OWN __BIT(31)
|
||||
|
||||
struct sunxi_mmc_idma_descriptor {
|
||||
uint32_t dma_config;
|
||||
#define SUNXI_MMC_IDMA_CONFIG_DIC __BIT(1)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_LD __BIT(2)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_FD __BIT(3)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_CH __BIT(4)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_ER __BIT(5)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_CES __BIT(30)
|
||||
#define SUNXI_MMC_IDMA_CONFIG_OWN __BIT(31)
|
||||
uint32_t dma_buf_size;
|
||||
uint32_t dma_buf_addr;
|
||||
uint32_t dma_next;
|
||||
} __packed;
|
||||
|
||||
#endif /* _ARM_SUNXI_MMC_H */
|
|
@ -0,0 +1,170 @@
|
|||
/* $NetBSD: sunxi_platform.c,v 1.5.4.2 2017/07/18 19:13:08 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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_soc.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
#include "opt_fdt_arm.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_platform.c,v 1.5.4.2 2017/07/18 19:13:08 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/termios.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
#include <arm/fdt/arm_fdtvar.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/bootconfig.h>
|
||||
#include <arm/cpufunc.h>
|
||||
|
||||
#include <arm/cortex/gtmr_var.h>
|
||||
#include <arm/cortex/gic_reg.h>
|
||||
|
||||
#include <dev/ic/ns16550reg.h>
|
||||
#include <dev/ic/comreg.h>
|
||||
|
||||
#include <arm/arm/psci.h>
|
||||
#include <arm/fdt/psci_fdt.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_platform.h>
|
||||
|
||||
#define SUNXI_REF_FREQ 24000000
|
||||
|
||||
#define SUN6I_WDT_BASE 0x01c20ca0
|
||||
#define SUN6I_WDT_SIZE 0x20
|
||||
#define SUN6I_WDT_CFG 0x14
|
||||
#define SUN6I_WDT_CFG_SYS 1
|
||||
#define SUN6I_WDT_MODE 0x18
|
||||
#define SUN6I_WDT_MODE_EN 1
|
||||
|
||||
|
||||
#define DEVMAP_ALIGN(a) ((a) & ~L1_S_OFFSET)
|
||||
#define DEVMAP_SIZE(s) roundup2((s), L1_S_SIZE)
|
||||
#define DEVMAP_ENTRY(va, pa, sz) \
|
||||
{ \
|
||||
.pd_va = DEVMAP_ALIGN(va), \
|
||||
.pd_pa = DEVMAP_ALIGN(pa), \
|
||||
.pd_size = DEVMAP_SIZE(sz), \
|
||||
.pd_prot = VM_PROT_READ|VM_PROT_WRITE, \
|
||||
.pd_cache = PTE_NOCACHE \
|
||||
}
|
||||
#define DEVMAP_ENTRY_END { 0 }
|
||||
|
||||
extern struct bus_space armv7_generic_bs_tag;
|
||||
extern struct bus_space armv7_generic_a4x_bs_tag;
|
||||
extern struct arm32_bus_dma_tag armv7_generic_dma_tag;
|
||||
|
||||
static const struct pmap_devmap *
|
||||
sunxi_platform_devmap(void)
|
||||
{
|
||||
static const struct pmap_devmap devmap[] = {
|
||||
DEVMAP_ENTRY(SUNXI_CORE_VBASE,
|
||||
SUNXI_CORE_PBASE,
|
||||
SUNXI_CORE_SIZE),
|
||||
DEVMAP_ENTRY_END
|
||||
};
|
||||
|
||||
return devmap;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_platform_init_attach_args(struct fdt_attach_args *faa)
|
||||
{
|
||||
faa->faa_bst = &armv7_generic_bs_tag;
|
||||
faa->faa_a4x_bst = &armv7_generic_a4x_bs_tag;
|
||||
faa->faa_dmat = &armv7_generic_dma_tag;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_platform_early_putchar(char c)
|
||||
{
|
||||
#ifdef CONSADDR
|
||||
#define CONSADDR_VA ((CONSADDR - SUNXI_CORE_PBASE) + SUNXI_CORE_VBASE)
|
||||
volatile uint32_t *uartaddr = (volatile uint32_t *)CONSADDR_VA;
|
||||
|
||||
while ((uartaddr[com_lsr] & LSR_TXRDY) == 0)
|
||||
;
|
||||
|
||||
uartaddr[com_data] = c;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_platform_device_register(device_t self, void *aux)
|
||||
{
|
||||
}
|
||||
|
||||
static u_int
|
||||
sunxi_platform_uart_freq(void)
|
||||
{
|
||||
return SUNXI_REF_FREQ;
|
||||
}
|
||||
|
||||
static void
|
||||
sun6i_platform_reset(void)
|
||||
{
|
||||
bus_space_tag_t bst = &armv7_generic_bs_tag;
|
||||
bus_space_handle_t bsh;
|
||||
|
||||
bus_space_map(bst, SUN6I_WDT_BASE, SUN6I_WDT_SIZE, 0, &bsh);
|
||||
|
||||
bus_space_write_4(bst, bsh, SUN6I_WDT_CFG, SUN6I_WDT_CFG_SYS);
|
||||
bus_space_write_4(bst, bsh, SUN6I_WDT_MODE, SUN6I_WDT_MODE_EN);
|
||||
}
|
||||
|
||||
static const struct arm_platform sun8i_platform = {
|
||||
.devmap = sunxi_platform_devmap,
|
||||
.bootstrap = psci_fdt_bootstrap,
|
||||
.init_attach_args = sunxi_platform_init_attach_args,
|
||||
.early_putchar = sunxi_platform_early_putchar,
|
||||
.device_register = sunxi_platform_device_register,
|
||||
.reset = sun6i_platform_reset,
|
||||
.delay = gtmr_delay,
|
||||
.uart_freq = sunxi_platform_uart_freq,
|
||||
};
|
||||
|
||||
ARM_PLATFORM(sun8i_h3, "allwinner,sun8i-h3", &sun8i_platform);
|
||||
ARM_PLATFORM(sun8i_a83t, "allwinner,sun8i-a83t", &sun8i_platform);
|
||||
|
||||
static const struct arm_platform sun6i_platform = {
|
||||
.devmap = sunxi_platform_devmap,
|
||||
.bootstrap = psci_fdt_bootstrap,
|
||||
.init_attach_args = sunxi_platform_init_attach_args,
|
||||
.early_putchar = sunxi_platform_early_putchar,
|
||||
.device_register = sunxi_platform_device_register,
|
||||
.reset = sun6i_platform_reset,
|
||||
.delay = gtmr_delay,
|
||||
.uart_freq = sunxi_platform_uart_freq,
|
||||
};
|
||||
|
||||
ARM_PLATFORM(sun6i_a31, "allwinner,sun6i-a31", &sun6i_platform);
|
|
@ -0,0 +1,38 @@
|
|||
/* $NetBSD: sunxi_platform.h,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_SUNXI_PLATFORM_H
|
||||
#define _ARM_SUNXI_PLATFORM_H
|
||||
|
||||
#include <arch/evbarm/fdt/platform.h>
|
||||
|
||||
#define SUNXI_CORE_VBASE (KERNEL_VM_BASE + KERNEL_VM_SIZE)
|
||||
#define SUNXI_CORE_PBASE 0x01c00000
|
||||
#define SUNXI_CORE_SIZE 0x00400000
|
||||
|
||||
#endif /* _ARM_SUNXI_PLATFORM_H */
|
|
@ -0,0 +1,149 @@
|
|||
/* $NetBSD: sunxi_resets.c,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_resets.c,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <dev/clk/clk_backend.h>
|
||||
|
||||
#define RESET_REG(index) (((index) / 32) * 4)
|
||||
#define RESET_MASK(index) __BIT((index) % 32)
|
||||
|
||||
static const char * compatible[] = {
|
||||
"allwinner,sun6i-a31-clock-reset",
|
||||
NULL
|
||||
};
|
||||
|
||||
struct sunxi_resets_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
};
|
||||
|
||||
#define RESET_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||
#define RESET_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||
|
||||
static void *
|
||||
sunxi_resets_acquire(device_t dev, const void *data, size_t len)
|
||||
{
|
||||
if (len != 4)
|
||||
return NULL;
|
||||
|
||||
/* Specifier is an index. Just return it. */
|
||||
return (void *)(uintptr_t)be32dec(data);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_resets_release(device_t dev, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_resets_assert(device_t dev, void *priv)
|
||||
{
|
||||
struct sunxi_resets_softc * const sc = device_private(dev);
|
||||
const uintptr_t index = (uintptr_t)priv;
|
||||
|
||||
const bus_size_t reset_reg = RESET_REG(index);
|
||||
const uint32_t reset_mask = RESET_MASK(index);
|
||||
|
||||
const uint32_t val = RESET_READ(sc, reset_reg);
|
||||
RESET_WRITE(sc, reset_reg, val & ~reset_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_resets_deassert(device_t dev, void *priv)
|
||||
{
|
||||
struct sunxi_resets_softc * const sc = device_private(dev);
|
||||
const uintptr_t index = (uintptr_t)priv;
|
||||
|
||||
const bus_size_t reset_reg = RESET_REG(index);
|
||||
const uint32_t reset_mask = RESET_MASK(index);
|
||||
|
||||
const uint32_t val = RESET_READ(sc, reset_reg);
|
||||
RESET_WRITE(sc, reset_reg, val | reset_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fdtbus_reset_controller_func sunxi_fdtreset_funcs = {
|
||||
.acquire = sunxi_resets_acquire,
|
||||
.release = sunxi_resets_release,
|
||||
.reset_assert = sunxi_resets_assert,
|
||||
.reset_deassert = sunxi_resets_deassert,
|
||||
};
|
||||
|
||||
static int
|
||||
sunxi_resets_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_resets_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_resets_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal("\n");
|
||||
|
||||
fdtbus_register_reset_controller(sc->sc_dev, phandle,
|
||||
&sunxi_fdtreset_funcs);
|
||||
}
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_resets, sizeof(struct sunxi_resets_softc),
|
||||
sunxi_resets_match, sunxi_resets_attach, NULL, NULL);
|
|
@ -0,0 +1,479 @@
|
|||
/* $NetBSD: sunxi_rsb.c,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_rsb.c,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/condvar.h>
|
||||
|
||||
#include <dev/i2c/i2cvar.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <arm/sunxi/sunxi_rsb.h>
|
||||
|
||||
enum sunxi_rsb_type {
|
||||
SUNXI_P2WI,
|
||||
SUNXI_RSB,
|
||||
};
|
||||
|
||||
static const struct of_compat_data compat_data[] = {
|
||||
{ "allwinner,sun6i-a31-p2wi", SUNXI_P2WI },
|
||||
{ "allwinner,sun8i-a23-rsb", SUNXI_RSB },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
#define RSB_ADDR_PMIC_PRIMARY 0x3a3
|
||||
#define RSB_ADDR_PMIC_SECONDARY 0x745
|
||||
#define RSB_ADDR_PERIPH_IC 0xe89
|
||||
|
||||
/*
|
||||
* Device address to Run-time address mappings.
|
||||
*
|
||||
* Run-time address (RTA) is an 8-bit value used to address the device during
|
||||
* a read or write transaction. The following are valid RTAs:
|
||||
* 0x17 0x2d 0x3a 0x4e 0x59 0x63 0x74 0x8b 0x9c 0xa6 0xb1 0xc5 0xd2 0xe8 0xff
|
||||
*
|
||||
* Allwinner uses RTA 0x2d for the primary PMIC, 0x3a for the secondary PMIC,
|
||||
* and 0x4e for the peripheral IC (where applicable).
|
||||
*/
|
||||
static const struct {
|
||||
uint16_t addr;
|
||||
uint8_t rta;
|
||||
} rsb_rtamap[] = {
|
||||
{ .addr = RSB_ADDR_PMIC_PRIMARY, .rta = 0x2d },
|
||||
{ .addr = RSB_ADDR_PMIC_SECONDARY, .rta = 0x3a },
|
||||
{ .addr = RSB_ADDR_PERIPH_IC, .rta = 0x4e },
|
||||
{ .addr = 0, .rta = 0 }
|
||||
};
|
||||
|
||||
struct sunxi_rsb_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
enum sunxi_rsb_type sc_type;
|
||||
struct i2c_controller sc_ic;
|
||||
kmutex_t sc_lock;
|
||||
kcondvar_t sc_cv;
|
||||
device_t sc_i2cdev;
|
||||
void *sc_ih;
|
||||
uint32_t sc_stat;
|
||||
|
||||
uint16_t sc_rsb_last_da;
|
||||
};
|
||||
|
||||
#define RSB_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||
#define RSB_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||
|
||||
static int sunxi_rsb_acquire_bus(void *, int);
|
||||
static void sunxi_rsb_release_bus(void *, int);
|
||||
static int sunxi_rsb_exec(void *, i2c_op_t, i2c_addr_t, const void *,
|
||||
size_t, void *, size_t, int);
|
||||
|
||||
static int sunxi_rsb_intr(void *);
|
||||
static int sunxi_rsb_wait(struct sunxi_rsb_softc *, int);
|
||||
static int sunxi_rsb_rsb_config(struct sunxi_rsb_softc *,
|
||||
uint8_t, i2c_addr_t, int);
|
||||
|
||||
static int sunxi_rsb_match(device_t, cfdata_t, void *);
|
||||
static void sunxi_rsb_attach(device_t, device_t, void *);
|
||||
|
||||
static i2c_tag_t
|
||||
sunxi_rsb_get_tag(device_t dev)
|
||||
{
|
||||
struct sunxi_rsb_softc * const sc = device_private(dev);
|
||||
|
||||
return &sc->sc_ic;
|
||||
}
|
||||
|
||||
static const struct fdtbus_i2c_controller_func sunxi_rsb_funcs = {
|
||||
.get_tag = sunxi_rsb_get_tag,
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_rsb, sizeof(struct sunxi_rsb_softc),
|
||||
sunxi_rsb_match, sunxi_rsb_attach, NULL, NULL);
|
||||
|
||||
static int
|
||||
sunxi_rsb_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compat_data(faa->faa_phandle, compat_data);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_rsb_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_rsb_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
struct i2cbus_attach_args iba;
|
||||
prop_dictionary_t devs;
|
||||
uint32_t address_cells;
|
||||
struct fdtbus_reset *rst;
|
||||
struct clk *clk;
|
||||
char intrstr[128];
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
|
||||
aprint_error(": couldn't decode interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((clk = fdtbus_clock_get_index(phandle, 0)) != NULL)
|
||||
if (clk_enable(clk) != 0) {
|
||||
aprint_error(": couldn't enable clock\n");
|
||||
return;
|
||||
}
|
||||
if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL)
|
||||
if (fdtbus_reset_deassert(rst) != 0) {
|
||||
aprint_error(": couldn't de-assert reset\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_type = of_search_compatible(phandle, compat_data)->data;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SCHED);
|
||||
cv_init(&sc->sc_cv, "awinp2wi");
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": %s\n", sc->sc_type == SUNXI_P2WI ? "P2WI" : "RSB");
|
||||
|
||||
sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM, 0,
|
||||
sunxi_rsb_intr, sc);
|
||||
if (sc->sc_ih == NULL) {
|
||||
aprint_error_dev(self, "couldn't establish interrupt on %s\n",
|
||||
intrstr);
|
||||
return;
|
||||
}
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
|
||||
/* Enable interrupts */
|
||||
RSB_WRITE(sc, RSB_INTE_REG,
|
||||
RSB_INTE_LOAD_BSY_ENB |
|
||||
RSB_INTE_TRANS_ERR_ENB |
|
||||
RSB_INTE_TRANS_OVER_ENB);
|
||||
RSB_WRITE(sc, RSB_CTRL_REG,
|
||||
RSB_CTRL_GLOBAL_INT_ENB);
|
||||
|
||||
sc->sc_ic.ic_cookie = sc;
|
||||
sc->sc_ic.ic_acquire_bus = sunxi_rsb_acquire_bus;
|
||||
sc->sc_ic.ic_release_bus = sunxi_rsb_release_bus;
|
||||
sc->sc_ic.ic_exec = sunxi_rsb_exec;
|
||||
|
||||
fdtbus_register_i2c_controller(self, phandle, &sunxi_rsb_funcs);
|
||||
|
||||
devs = prop_dictionary_create();
|
||||
if (of_getprop_uint32(phandle, "#address-cells", &address_cells))
|
||||
address_cells = 1;
|
||||
|
||||
of_enter_i2c_devs(devs, phandle, address_cells * 4, 0);
|
||||
|
||||
memset(&iba, 0, sizeof(iba));
|
||||
iba.iba_tag = &sc->sc_ic;
|
||||
iba.iba_child_devices = prop_dictionary_get(devs, "i2c-child-devices");
|
||||
if (iba.iba_child_devices)
|
||||
prop_object_retain(iba.iba_child_devices);
|
||||
else
|
||||
iba.iba_child_devices = prop_array_create();
|
||||
prop_object_release(devs);
|
||||
|
||||
sc->sc_i2cdev = config_found_ia(self, "i2cbus", &iba, iicbus_print);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_rsb_intr(void *priv)
|
||||
{
|
||||
struct sunxi_rsb_softc *sc = priv;
|
||||
uint32_t stat;
|
||||
|
||||
stat = RSB_READ(sc, RSB_STAT_REG);
|
||||
if ((stat & RSB_STAT_MASK) == 0)
|
||||
return 0;
|
||||
|
||||
RSB_WRITE(sc, RSB_STAT_REG, stat & RSB_STAT_MASK);
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
sc->sc_stat |= stat;
|
||||
cv_broadcast(&sc->sc_cv);
|
||||
mutex_exit(&sc->sc_lock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_rsb_wait(struct sunxi_rsb_softc *sc, int flags)
|
||||
{
|
||||
int error = 0, retry;
|
||||
|
||||
/* Wait up to 5 seconds for a transfer to complete */
|
||||
sc->sc_stat = 0;
|
||||
for (retry = (flags & I2C_F_POLL) ? 100 : 5; retry > 0; retry--) {
|
||||
if (flags & I2C_F_POLL) {
|
||||
sc->sc_stat |= RSB_READ(sc, RSB_STAT_REG);
|
||||
} else {
|
||||
error = cv_timedwait(&sc->sc_cv, &sc->sc_lock, hz);
|
||||
if (error && error != EWOULDBLOCK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sc->sc_stat & RSB_STAT_MASK) {
|
||||
break;
|
||||
}
|
||||
if (flags & I2C_F_POLL) {
|
||||
delay(10000);
|
||||
}
|
||||
}
|
||||
if (retry == 0)
|
||||
error = EAGAIN;
|
||||
|
||||
if (flags & I2C_F_POLL) {
|
||||
RSB_WRITE(sc, RSB_STAT_REG,
|
||||
sc->sc_stat & RSB_STAT_MASK);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
/* Abort transaction */
|
||||
device_printf(sc->sc_dev, "transfer timeout, error = %d\n",
|
||||
error);
|
||||
RSB_WRITE(sc, RSB_CTRL_REG,
|
||||
RSB_CTRL_ABORT_TRANS);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (sc->sc_stat & RSB_STAT_LOAD_BSY) {
|
||||
device_printf(sc->sc_dev, "transfer busy\n");
|
||||
return EBUSY;
|
||||
}
|
||||
if (sc->sc_stat & RSB_STAT_TRANS_ERR) {
|
||||
device_printf(sc->sc_dev, "transfer error, id 0x%02llx\n",
|
||||
__SHIFTOUT(sc->sc_stat, RSB_STAT_TRANS_ERR_ID));
|
||||
return EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_rsb_rsb_config(struct sunxi_rsb_softc *sc, uint8_t rta, i2c_addr_t da,
|
||||
int flags)
|
||||
{
|
||||
uint32_t dar, ctrl;
|
||||
|
||||
KASSERT(mutex_owned(&sc->sc_lock));
|
||||
|
||||
RSB_WRITE(sc, RSB_STAT_REG,
|
||||
RSB_READ(sc, RSB_STAT_REG) & RSB_STAT_MASK);
|
||||
|
||||
dar = __SHIFTIN(rta, RSB_DAR_RTA);
|
||||
dar |= __SHIFTIN(da, RSB_DAR_DA);
|
||||
RSB_WRITE(sc, RSB_DAR_REG, dar);
|
||||
RSB_WRITE(sc, RSB_CMD_REG, RSB_CMD_IDX_SRTA);
|
||||
|
||||
/* Make sure the controller is idle */
|
||||
ctrl = RSB_READ(sc, RSB_CTRL_REG);
|
||||
if (ctrl & RSB_CTRL_START_TRANS) {
|
||||
device_printf(sc->sc_dev, "device is busy\n");
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
/* Start the transfer */
|
||||
RSB_WRITE(sc, RSB_CTRL_REG,
|
||||
ctrl | RSB_CTRL_START_TRANS);
|
||||
|
||||
return sunxi_rsb_wait(sc, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_rsb_acquire_bus(void *priv, int flags)
|
||||
{
|
||||
struct sunxi_rsb_softc *sc = priv;
|
||||
|
||||
if (flags & I2C_F_POLL) {
|
||||
if (!mutex_tryenter(&sc->sc_lock))
|
||||
return EBUSY;
|
||||
} else {
|
||||
mutex_enter(&sc->sc_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_rsb_release_bus(void *priv, int flags)
|
||||
{
|
||||
struct sunxi_rsb_softc *sc = priv;
|
||||
|
||||
mutex_exit(&sc->sc_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_rsb_exec(void *priv, i2c_op_t op, i2c_addr_t addr,
|
||||
const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
|
||||
{
|
||||
struct sunxi_rsb_softc *sc = priv;
|
||||
uint32_t dlen, ctrl;
|
||||
uint8_t rta;
|
||||
int error, i;
|
||||
|
||||
KASSERT(mutex_owned(&sc->sc_lock));
|
||||
|
||||
if (cmdlen != 1 || (len != 1 && len != 2 && len != 4))
|
||||
return EINVAL;
|
||||
|
||||
if (sc->sc_type == SUNXI_RSB && sc->sc_rsb_last_da != addr) {
|
||||
/* Lookup run-time address for given device address */
|
||||
for (rta = 0, i = 0; rsb_rtamap[i].rta != 0; i++)
|
||||
if (rsb_rtamap[i].addr == addr) {
|
||||
rta = rsb_rtamap[i].rta;
|
||||
break;
|
||||
}
|
||||
if (rta == 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"RTA not known for address %#x\n", addr);
|
||||
return ENXIO;
|
||||
}
|
||||
error = sunxi_rsb_rsb_config(sc, rta, addr, flags);
|
||||
if (error) {
|
||||
device_printf(sc->sc_dev,
|
||||
"SRTA failed, flags = %x, error = %d\n",
|
||||
flags, error);
|
||||
sc->sc_rsb_last_da = 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
sc->sc_rsb_last_da = addr;
|
||||
}
|
||||
|
||||
/* Data byte register */
|
||||
RSB_WRITE(sc, RSB_DADDR0_REG, *(const uint8_t *)cmdbuf);
|
||||
|
||||
if (I2C_OP_WRITE_P(op)) {
|
||||
uint8_t *pbuf = buf;
|
||||
uint32_t data;
|
||||
/* Write data */
|
||||
switch (len) {
|
||||
case 1:
|
||||
data = pbuf[0];
|
||||
break;
|
||||
case 2:
|
||||
data = pbuf[0] | (pbuf[1] << 8);
|
||||
break;
|
||||
case 4:
|
||||
data = pbuf[0] | (pbuf[1] << 8) |
|
||||
(pbuf[2] << 16) | (pbuf[3] << 24);
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
RSB_WRITE(sc, RSB_DATA0_REG, data);
|
||||
}
|
||||
|
||||
if (sc->sc_type == SUNXI_RSB) {
|
||||
uint8_t cmd;
|
||||
if (I2C_OP_WRITE_P(op)) {
|
||||
switch (len) {
|
||||
case 1: cmd = RSB_CMD_IDX_WR8; break;
|
||||
case 2: cmd = RSB_CMD_IDX_WR16; break;
|
||||
case 4: cmd = RSB_CMD_IDX_WR32; break;
|
||||
default: return EINVAL;
|
||||
}
|
||||
} else {
|
||||
switch (len) {
|
||||
case 1: cmd = RSB_CMD_IDX_RD8; break;
|
||||
case 2: cmd = RSB_CMD_IDX_RD16; break;
|
||||
case 4: cmd = RSB_CMD_IDX_RD32; break;
|
||||
default: return EINVAL;
|
||||
}
|
||||
}
|
||||
RSB_WRITE(sc, RSB_CMD_REG, cmd);
|
||||
}
|
||||
|
||||
/* Program data length register; if reading, set read/write bit */
|
||||
dlen = __SHIFTIN(len - 1, RSB_DLEN_ACCESS_LENGTH);
|
||||
if (I2C_OP_READ_P(op)) {
|
||||
dlen |= RSB_DLEN_READ_WRITE_FLAG;
|
||||
}
|
||||
RSB_WRITE(sc, RSB_DLEN_REG, dlen);
|
||||
|
||||
/* Make sure the controller is idle */
|
||||
ctrl = RSB_READ(sc, RSB_CTRL_REG);
|
||||
if (ctrl & RSB_CTRL_START_TRANS) {
|
||||
device_printf(sc->sc_dev, "device is busy\n");
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
/* Start the transfer */
|
||||
RSB_WRITE(sc, RSB_CTRL_REG,
|
||||
ctrl | RSB_CTRL_START_TRANS);
|
||||
|
||||
error = sunxi_rsb_wait(sc, flags);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (I2C_OP_READ_P(op)) {
|
||||
uint32_t data = RSB_READ(sc, RSB_DATA0_REG);
|
||||
switch (len) {
|
||||
case 4:
|
||||
*(uint32_t *)buf = data;
|
||||
break;
|
||||
case 2:
|
||||
*(uint16_t *)buf = data & 0xffff;
|
||||
break;
|
||||
case 1:
|
||||
*(uint8_t *)buf = data & 0xff;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/* $NetBSD: sunxi_rsb.h,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_SUNXI_RSB_H
|
||||
#define _ARM_SUNXI_RSB_H
|
||||
|
||||
#define RSB_CTRL_REG 0x0000
|
||||
#define RSB_CTRL_START_TRANS __BIT(7)
|
||||
#define RSB_CTRL_ABORT_TRANS __BIT(6)
|
||||
#define RSB_CTRL_GLOBAL_INT_ENB __BIT(1)
|
||||
#define RSB_CTRL_SOFT_RESET __BIT(0)
|
||||
#define RSB_CCR_REG 0x0004
|
||||
#define RSB_CCR_SDA_ODLY __BITS(10,8)
|
||||
#define RSB_CCR_CLK_DIV __BITS(7,0)
|
||||
#define RSB_INTE_REG 0x0008
|
||||
#define RSB_INTE_LOAD_BSY_ENB __BIT(2)
|
||||
#define RSB_INTE_TRANS_ERR_ENB __BIT(1)
|
||||
#define RSB_INTE_TRANS_OVER_ENB __BIT(0)
|
||||
#define RSB_STAT_REG 0x000c
|
||||
#define RSB_STAT_TRANS_ERR_ID __BITS(15,8)
|
||||
#define RSB_STAT_LOAD_BSY __BIT(2)
|
||||
#define RSB_STAT_TRANS_ERR __BIT(1)
|
||||
#define RSB_STAT_TRANS_OVER __BIT(0)
|
||||
#define RSB_STAT_MASK \
|
||||
(RSB_STAT_LOAD_BSY | \
|
||||
RSB_STAT_TRANS_ERR | \
|
||||
RSB_STAT_TRANS_OVER)
|
||||
#define RSB_DADDR0_REG 0x0010
|
||||
#define RSB_DADDR1_REG 0x0014
|
||||
#define RSB_DLEN_REG 0x0018
|
||||
#define RSB_DLEN_READ_WRITE_FLAG __BIT(4)
|
||||
#define RSB_DLEN_ACCESS_LENGTH __BITS(2,0)
|
||||
#define RSB_DATA0_REG 0x001c
|
||||
#define RSB_DATA1_REG 0x0020
|
||||
#define RSB_LCR_REG 0x0024
|
||||
#define RSB_LCR_SCL_STATE __BIT(5)
|
||||
#define RSB_LCR_SDA_STATE __BIT(4)
|
||||
#define RSB_LCR_SCL_CTL __BIT(3)
|
||||
#define RSB_LCR_SCL_CTL_EN __BIT(2)
|
||||
#define RSB_LCR_SDA_CTL __BIT(1)
|
||||
#define RSB_LCR_SDA_CTL_EN __BIT(0)
|
||||
#define RSB_PMCR_REG 0x0028
|
||||
#define RSB_PMCR_PMU_INIT_SEND __BIT(31)
|
||||
#define RSB_PMCR_PMU_INIT_DATA __BITS(23,16)
|
||||
#define RSB_PMCR_PMU_MODE_CTRL_REG_ADDR __BITS(15,8)
|
||||
#define RSB_PMCR_PMU_DEVICE_ADDR __BITS(7,0)
|
||||
#define RSB_CMD_REG 0x002c
|
||||
#define RSB_CMD_IDX __BITS(7,0)
|
||||
#define RSB_CMD_IDX_SRTA 0xe8
|
||||
#define RSB_CMD_IDX_RD8 0x8b
|
||||
#define RSB_CMD_IDX_RD16 0x9c
|
||||
#define RSB_CMD_IDX_RD32 0xa6
|
||||
#define RSB_CMD_IDX_WR8 0x4e
|
||||
#define RSB_CMD_IDX_WR16 0x59
|
||||
#define RSB_CMD_IDX_WR32 0x63
|
||||
#define RSB_DAR_REG 0x0030
|
||||
#define RSB_DAR_RTA __BITS(23,16)
|
||||
#define RSB_DAR_DA __BITS(15,0)
|
||||
|
||||
#endif /* _ARM_SUNXI_RSB_H */
|
|
@ -0,0 +1,174 @@
|
|||
/* $NetBSD: sunxi_rtc.c,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_rtc.c,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#include <dev/clock_subr.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#define RTC_YY_MM_DD_REG 0x10
|
||||
#define SUNXI_RTC_LEAP __BIT(22)
|
||||
#define SUNXI_RTC_YEAR __BITS(21,16)
|
||||
#define SUNXI_RTC_MONTH __BITS(11,8)
|
||||
#define SUNXI_RTC_DAY __BITS(4,0)
|
||||
#define RTC_HH_MM_SS_REG 0x14
|
||||
#define SUNXI_RTC_WK_NO __BITS(31,29)
|
||||
#define SUNXI_RTC_HOUR __BITS(20,16)
|
||||
#define SUNXI_RTC_MINUTE __BITS(13,8)
|
||||
#define SUNXI_RTC_SECOND __BITS(5,0)
|
||||
|
||||
#define SUNXI_RTC_BASE_YEAR 2000
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"allwinner,sun6i-a31-rtc",
|
||||
NULL
|
||||
};
|
||||
|
||||
struct sunxi_rtc_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
struct todr_chip_handle sc_todr;
|
||||
};
|
||||
|
||||
#define RTC_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||
#define RTC_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||
|
||||
static int sunxi_rtc_match(device_t, cfdata_t, void *);
|
||||
static void sunxi_rtc_attach(device_t, device_t, void *);
|
||||
|
||||
static int sunxi_rtc_gettime(todr_chip_handle_t, struct clock_ymdhms *);
|
||||
static int sunxi_rtc_settime(todr_chip_handle_t, struct clock_ymdhms *);
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_rtc, sizeof(struct sunxi_rtc_softc),
|
||||
sunxi_rtc_match, sunxi_rtc_attach, NULL, NULL);
|
||||
|
||||
static int
|
||||
sunxi_rtc_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_rtc_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_rtc_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": RTC\n");
|
||||
|
||||
sc->sc_todr.todr_gettime_ymdhms = sunxi_rtc_gettime;
|
||||
sc->sc_todr.todr_settime_ymdhms = sunxi_rtc_settime;
|
||||
sc->sc_todr.cookie = sc;
|
||||
|
||||
fdtbus_todr_attach(self, phandle, &sc->sc_todr);
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_rtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
|
||||
{
|
||||
struct sunxi_rtc_softc *sc = tch->cookie;
|
||||
|
||||
const uint32_t yymmdd = RTC_READ(sc, RTC_YY_MM_DD_REG);
|
||||
const uint32_t hhmmss = RTC_READ(sc, RTC_HH_MM_SS_REG);
|
||||
|
||||
dt->dt_year = __SHIFTOUT(yymmdd, SUNXI_RTC_YEAR) + SUNXI_RTC_BASE_YEAR;
|
||||
dt->dt_mon = __SHIFTOUT(yymmdd, SUNXI_RTC_MONTH);
|
||||
dt->dt_day = __SHIFTOUT(yymmdd, SUNXI_RTC_DAY);
|
||||
dt->dt_wday = __SHIFTOUT(hhmmss, SUNXI_RTC_WK_NO);
|
||||
dt->dt_hour = __SHIFTOUT(hhmmss, SUNXI_RTC_HOUR);
|
||||
dt->dt_min = __SHIFTOUT(hhmmss, SUNXI_RTC_MINUTE);
|
||||
dt->dt_sec = __SHIFTOUT(hhmmss, SUNXI_RTC_SECOND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_rtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
|
||||
{
|
||||
struct sunxi_rtc_softc *sc = tch->cookie;
|
||||
uint32_t yymmdd, hhmmss, maxyear;
|
||||
|
||||
/*
|
||||
* Sanity check the date before writing it back
|
||||
*/
|
||||
if (dt->dt_year < SUNXI_RTC_BASE_YEAR) {
|
||||
aprint_normal_dev(sc->sc_dev, "year pre the epoch: %llu, "
|
||||
"not writing back time\n", dt->dt_year);
|
||||
return EIO;
|
||||
}
|
||||
maxyear = __SHIFTOUT(0xffffffff, SUNXI_RTC_YEAR) + SUNXI_RTC_BASE_YEAR;
|
||||
if (dt->dt_year > maxyear) {
|
||||
aprint_normal_dev(sc->sc_dev, "year exceeds available field:"
|
||||
" %llu, not writing back time\n", dt->dt_year);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
yymmdd = __SHIFTIN(dt->dt_year - SUNXI_RTC_BASE_YEAR, SUNXI_RTC_YEAR);
|
||||
yymmdd |= __SHIFTIN(dt->dt_mon, SUNXI_RTC_MONTH);
|
||||
yymmdd |= __SHIFTIN(dt->dt_day, SUNXI_RTC_DAY);
|
||||
|
||||
hhmmss = __SHIFTIN(dt->dt_wday, SUNXI_RTC_WK_NO);
|
||||
hhmmss |= __SHIFTIN(dt->dt_hour, SUNXI_RTC_HOUR);
|
||||
hhmmss |= __SHIFTIN(dt->dt_min, SUNXI_RTC_MINUTE);
|
||||
hhmmss |= __SHIFTIN(dt->dt_sec, SUNXI_RTC_SECOND);
|
||||
|
||||
RTC_WRITE(sc, RTC_YY_MM_DD_REG, yymmdd);
|
||||
RTC_WRITE(sc, RTC_HH_MM_SS_REG, hhmmss);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/* $NetBSD: sunxi_twi.c,v 1.2.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this 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 <sys/cdefs.h>
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_twi.c,v 1.2.4.2 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <dev/i2c/i2cvar.h>
|
||||
#include <dev/i2c/gttwsivar.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
static int sunxi_twi_match(device_t, cfdata_t, void *);
|
||||
static void sunxi_twi_attach(device_t, device_t, void *);
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"allwinner,sun6i-a31-i2c",
|
||||
NULL
|
||||
};
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_twi, sizeof(struct gttwsi_softc),
|
||||
sunxi_twi_match, sunxi_twi_attach, NULL, NULL);
|
||||
|
||||
static i2c_tag_t
|
||||
sunxi_twi_get_tag(device_t dev)
|
||||
{
|
||||
struct gttwsi_softc * const sc = device_private(dev);
|
||||
|
||||
return &sc->sc_i2c;
|
||||
}
|
||||
|
||||
const struct fdtbus_i2c_controller_func sunxi_twi_funcs = {
|
||||
.get_tag = sunxi_twi_get_tag,
|
||||
};
|
||||
|
||||
static int
|
||||
sunxi_twi_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_twi_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct gttwsi_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
struct i2cbus_attach_args iba;
|
||||
const int phandle = faa->faa_phandle;
|
||||
bus_space_tag_t bst = faa->faa_bst;
|
||||
bus_space_handle_t bsh;
|
||||
prop_dictionary_t devs;
|
||||
uint32_t address_cells;
|
||||
struct fdtbus_reset *rst;
|
||||
struct clk *clk;
|
||||
char intrstr[128];
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
void *ih;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bus_space_map(bst, addr, size, 0, &bsh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
|
||||
aprint_error(": failed to decode interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((clk = fdtbus_clock_get_index(phandle, 0)) != NULL)
|
||||
if (clk_enable(clk) != 0) {
|
||||
aprint_error(": couldn't enable clock\n");
|
||||
return;
|
||||
}
|
||||
if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL)
|
||||
if (fdtbus_reset_deassert(rst) != 0) {
|
||||
aprint_error(": couldn't de-assert reset\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gttwsi_attach_subr(self, bst, bsh);
|
||||
|
||||
ih = fdtbus_intr_establish(phandle, 0, IPL_VM, 0, gttwsi_intr, sc);
|
||||
if (ih == NULL) {
|
||||
aprint_error_dev(self, "couldn't establish interrupt on %s\n",
|
||||
intrstr);
|
||||
return;
|
||||
}
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
|
||||
fdtbus_register_i2c_controller(self, phandle, &sunxi_twi_funcs);
|
||||
|
||||
devs = prop_dictionary_create();
|
||||
if (of_getprop_uint32(phandle, "#address-cells", &address_cells))
|
||||
address_cells = 1;
|
||||
|
||||
of_enter_i2c_devs(devs, phandle, address_cells * 4, 0);
|
||||
|
||||
memset(&iba, 0, sizeof(iba));
|
||||
iba.iba_tag = &sc->sc_i2c;
|
||||
iba.iba_child_devices = prop_dictionary_get(devs, "i2c-child-devices");
|
||||
if (iba.iba_child_devices)
|
||||
prop_object_retain(iba.iba_child_devices);
|
||||
else
|
||||
iba.iba_child_devices = prop_array_create();
|
||||
prop_object_release(devs);
|
||||
|
||||
config_found_ia(self, "i2cbus", &iba, iicbus_print);
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
/* $NetBSD: sunxi_usbphy.c,v 1.3.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this 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 <sys/cdefs.h>
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunxi_usbphy.c,v 1.3.4.2 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#define OTG_PHY_CFG 0x20
|
||||
#define OTG_PHY_ROUTE_OTG __BIT(0)
|
||||
|
||||
#define HCI_ICR 0x00
|
||||
#define HCI_AHB_INCR8 __BIT(10)
|
||||
#define HCI_AHB_INCR4 __BIT(9)
|
||||
#define HCI_AHB_INCRX_ALIGN __BIT(8)
|
||||
#define HCI_ULPI_BYPASS __BIT(0)
|
||||
#define PMU_UNK_H3 0x10
|
||||
#define PMU_UNK_H3_CLR __BIT(1)
|
||||
|
||||
static int sunxi_usbphy_match(device_t, cfdata_t, void *);
|
||||
static void sunxi_usbphy_attach(device_t, device_t, void *);
|
||||
|
||||
enum sunxi_usbphy_type {
|
||||
USBPHY_A31,
|
||||
USBPHY_H3,
|
||||
};
|
||||
|
||||
static const struct of_compat_data compat_data[] = {
|
||||
{ "allwinner,sun6i-a31-usb-phy", USBPHY_A31 },
|
||||
{ "allwinner,sun8i-h3-usb-phy", USBPHY_H3 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
#define SUNXI_MAXUSBPHY 4
|
||||
|
||||
struct sunxi_usbphy {
|
||||
u_int phy_index;
|
||||
bus_space_handle_t phy_bsh;
|
||||
struct fdtbus_regulator *phy_reg;
|
||||
};
|
||||
|
||||
struct sunxi_usbphy_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh_phy_ctrl;
|
||||
enum sunxi_usbphy_type sc_type;
|
||||
|
||||
struct sunxi_usbphy sc_phys[SUNXI_MAXUSBPHY];
|
||||
u_int sc_nphys;
|
||||
|
||||
struct fdtbus_gpio_pin *sc_gpio_id_det;
|
||||
struct fdtbus_gpio_pin *sc_gpio_vbus_det;
|
||||
};
|
||||
|
||||
#define USBPHY_READ(sc, id, reg) \
|
||||
bus_space_read_4((sc)->sc_bst, \
|
||||
(sc)->sc_phys[(id)].phy_bsh, (reg))
|
||||
#define USBPHY_WRITE(sc, id, reg, val) \
|
||||
bus_space_write_4((sc)->sc_bst, \
|
||||
(sc)->sc_phys[(id)].phy_bsh, (reg), (val))
|
||||
|
||||
CFATTACH_DECL_NEW(sunxi_usbphy, sizeof(struct sunxi_usbphy_softc),
|
||||
sunxi_usbphy_match, sunxi_usbphy_attach, NULL, NULL);
|
||||
|
||||
static bool
|
||||
sunxi_usbphy_vbus_detect(struct sunxi_usbphy_softc *sc)
|
||||
{
|
||||
if (sc->sc_gpio_vbus_det)
|
||||
return fdtbus_gpio_read(sc->sc_gpio_vbus_det);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *
|
||||
sunxi_usbphy_acquire(device_t dev, const void *data, size_t len)
|
||||
{
|
||||
struct sunxi_usbphy_softc * const sc = device_private(dev);
|
||||
|
||||
if (len != 4)
|
||||
return NULL;
|
||||
|
||||
const int phy_id = be32dec(data);
|
||||
if (phy_id >= sc->sc_nphys)
|
||||
return NULL;
|
||||
|
||||
return &sc->sc_phys[phy_id];
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_usbphy_release(device_t dev, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
sunxi_usbphy_enable(device_t dev, void *priv, bool enable)
|
||||
{
|
||||
struct sunxi_usbphy_softc * const sc = device_private(dev);
|
||||
struct sunxi_usbphy * const phy = priv;
|
||||
uint32_t val;
|
||||
|
||||
if (phy->phy_index > 0) {
|
||||
/* Enable passby */
|
||||
val = USBPHY_READ(sc, phy->phy_index, HCI_ICR);
|
||||
val |= HCI_ULPI_BYPASS;
|
||||
val |= HCI_AHB_INCR8;
|
||||
val |= HCI_AHB_INCR4;
|
||||
val |= HCI_AHB_INCRX_ALIGN;
|
||||
USBPHY_WRITE(sc, phy->phy_index, HCI_ICR, val);
|
||||
}
|
||||
|
||||
if (sc->sc_type == USBPHY_H3) {
|
||||
/* H3-specific */
|
||||
val = USBPHY_READ(sc, phy->phy_index, PMU_UNK_H3);
|
||||
val &= ~PMU_UNK_H3_CLR;
|
||||
USBPHY_WRITE(sc, phy->phy_index, PMU_UNK_H3, val);
|
||||
}
|
||||
|
||||
if (phy->phy_reg == NULL)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
/* If an external vbus is detected, do not enable phy 0 */
|
||||
if (phy->phy_index == 0 && sunxi_usbphy_vbus_detect(sc))
|
||||
return 0;
|
||||
return fdtbus_regulator_enable(phy->phy_reg);
|
||||
} else {
|
||||
return fdtbus_regulator_disable(phy->phy_reg);
|
||||
}
|
||||
}
|
||||
|
||||
const struct fdtbus_phy_controller_func sunxi_usbphy_funcs = {
|
||||
.acquire = sunxi_usbphy_acquire,
|
||||
.release = sunxi_usbphy_release,
|
||||
.enable = sunxi_usbphy_enable,
|
||||
};
|
||||
|
||||
static int
|
||||
sunxi_usbphy_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compat_data(faa->faa_phandle, compat_data);
|
||||
}
|
||||
|
||||
static void
|
||||
sunxi_usbphy_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct sunxi_usbphy_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
struct fdtbus_reset *rst;
|
||||
struct sunxi_usbphy *phy;
|
||||
struct clk *clk;
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
char pname[20];
|
||||
u_int n;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_bst = faa->faa_bst;
|
||||
sc->sc_type = of_search_compatible(phandle, compat_data)->data;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get phy ctrl registers\n");
|
||||
return;
|
||||
}
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh_phy_ctrl) != 0) {
|
||||
aprint_error(": couldn't map phy ctrl registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (sc->sc_nphys = 0; sc->sc_nphys < SUNXI_MAXUSBPHY; sc->sc_nphys++) {
|
||||
if (fdtbus_get_reg(phandle, sc->sc_nphys + 1, &addr, &size) != 0)
|
||||
break;
|
||||
phy = &sc->sc_phys[sc->sc_nphys];
|
||||
phy->phy_index = sc->sc_nphys;
|
||||
if (bus_space_map(sc->sc_bst, addr, size, 0, &phy->phy_bsh) != 0) {
|
||||
aprint_error(": failed to map reg #%d\n", sc->sc_nphys);
|
||||
return;
|
||||
}
|
||||
/* Get optional regulator */
|
||||
snprintf(pname, sizeof(pname), "usb%d_vbus-supply", sc->sc_nphys);
|
||||
phy->phy_reg = fdtbus_regulator_acquire(phandle, pname);
|
||||
}
|
||||
|
||||
/* Enable clocks */
|
||||
for (n = 0; (clk = fdtbus_clock_get_index(phandle, n)) != NULL; n++)
|
||||
if (clk_enable(clk) != 0) {
|
||||
aprint_error(": couldn't enable clock #%d\n", n);
|
||||
return;
|
||||
}
|
||||
/* De-assert resets */
|
||||
for (n = 0; (rst = fdtbus_reset_get_index(phandle, n)) != NULL; n++)
|
||||
if (fdtbus_reset_deassert(rst) != 0) {
|
||||
aprint_error(": couldn't de-assert reset #%d\n", n);
|
||||
return;
|
||||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": USB PHY\n");
|
||||
|
||||
fdtbus_register_phy_controller(self, phandle, &sunxi_usbphy_funcs);
|
||||
}
|
|
@ -1,301 +1,94 @@
|
|||
#
|
||||
# $NetBSD: EXYNOS,v 1.14 2017/04/16 15:49:26 jmcneill Exp $
|
||||
# $NetBSD: EXYNOS,v 1.14.4.1 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# ODROID-XU -- ODROID-XU4 Exynos5422 based kernel
|
||||
# Samsung Exynos SoC kernel
|
||||
#
|
||||
|
||||
include "arch/evbarm/conf/std.exynos"
|
||||
include "arch/evbarm/conf/GENERIC.common"
|
||||
|
||||
no makeoptions CPUFLAGS
|
||||
makeoptions CPUFLAGS="-mcpu=cortex-a7 -mfpu=neon"
|
||||
no makeoptions BOARDTYPE
|
||||
makeoptions BOARDTYPE="hardkernel_odroid_xu4"
|
||||
no makeoptions KERNEL_BASE_PHYS
|
||||
no makeoptions KERNEL_BASE_VIRT
|
||||
makeoptions KERNEL_BASE_PHYS="0x80000000"
|
||||
makeoptions KERNEL_BASE_VIRT="0x80000000"
|
||||
options PMAP_NEED_ALLOC_POOLPAGE
|
||||
options MEMSIZE=2048
|
||||
|
||||
# estimated number of users
|
||||
|
||||
maxusers 8
|
||||
|
||||
# Standard system options
|
||||
|
||||
options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT
|
||||
#options NTP # NTP phase/frequency locked loop
|
||||
|
||||
# CPU options
|
||||
options CPU_CORTEX
|
||||
options CPU_CORTEXA7
|
||||
options CPU_CORTEXA15
|
||||
options EXYNOS5422
|
||||
#options MULTIPROCESSOR
|
||||
options SOC_EXYNOS5422
|
||||
options MULTIPROCESSOR
|
||||
|
||||
options FDT # not really but soon
|
||||
pseudo-device openfirm # jmcneill: oops, fdtbus should depend on
|
||||
# openfirm. don't let me forget.
|
||||
pseudo-device openfirm # /dev/openfirm
|
||||
|
||||
|
||||
options PMAPCOUNTERS
|
||||
options BUSDMA_COUNTERS
|
||||
options EXYNOS_CONSOLE_EARLY
|
||||
#options UVMHIST
|
||||
options USBHIST
|
||||
options USBHIST_SIZE=100000
|
||||
#options UVMHIST_PRINT,KERNHIST_DELAY=0
|
||||
options __HAVE_MM_MD_DIRECT_MAPPED_PHYS
|
||||
#options PMAP_NEED_ALLOC_POOLPAGE
|
||||
|
||||
# Specify the memory size in megabytes (optional).
|
||||
#options MEMSIZE=2048
|
||||
|
||||
# File systems
|
||||
file-system FFS # UFS
|
||||
#file-system LFS # log-structured file system
|
||||
file-system MFS # memory file system
|
||||
file-system NFS # Network file system
|
||||
#file-system ADOSFS # AmigaDOS-compatible file system
|
||||
#file-system EXT2FS # second extended file system (linux)
|
||||
#file-system CD9660 # ISO 9660 + Rock Ridge file system
|
||||
file-system MSDOSFS # MS-DOS file system
|
||||
#file-system FDESC # /dev/fd
|
||||
file-system KERNFS # /kern
|
||||
#file-system NULLFS # loopback file system
|
||||
file-system PROCFS # /proc
|
||||
#file-system PUFFS # Userspace file systems (e.g. ntfs-3g & sshfs)
|
||||
#file-system UMAPFS # NULLFS + uid and gid remapping
|
||||
#file-system UNION # union file system
|
||||
file-system TMPFS # memory file system
|
||||
file-system PTYFS # /dev/pts/N support
|
||||
|
||||
# File system options
|
||||
#options QUOTA # legacy UFS quotas
|
||||
#options QUOTA2 # new, in-filesystem UFS quotas
|
||||
#options DISKLABEL_EI # disklabel Endian Independent support
|
||||
#options FFS_EI # FFS Endian Independent support
|
||||
options NFSSERVER
|
||||
options WAPBL # File system journaling support
|
||||
#options FFS_NO_SNAPSHOT # No FFS snapshot support
|
||||
|
||||
# Networking options
|
||||
|
||||
#options GATEWAY # packet forwarding
|
||||
options INET # IP + ICMP + TCP + UDP
|
||||
options INET6 # IPV6
|
||||
#options IPSEC # IP security
|
||||
#options IPSEC_DEBUG # debug for IP security
|
||||
#options MROUTING # IP multicast routing
|
||||
#options PIM # Protocol Independent Multicast
|
||||
#options NETATALK # AppleTalk networking
|
||||
#options PPP_BSDCOMP # BSD-Compress compression support for PPP
|
||||
#options PPP_DEFLATE # Deflate compression support for PPP
|
||||
#options PPP_FILTER # Active filter support for PPP (requires bpf)
|
||||
#options TCP_DEBUG # Record last TCP_NDEBUG packets with SO_DEBUG
|
||||
|
||||
#options NFS_BOOT_BOOTP
|
||||
#options NFS_BOOT_DHCP
|
||||
#options NFS_BOOT_BOOTSTATIC
|
||||
#options NFS_BOOTSTATIC_MYIP="\"192.168.0.22\""
|
||||
#options NFS_BOOTSTATIC_GWIP="\"192.168.0.1\""
|
||||
#options NFS_BOOTSTATIC_MASK="\"255.255.255.0\""
|
||||
#options NFS_BOOTSTATIC_SERVADDR="\"192.168.0.5\""
|
||||
#options NFS_BOOTSTATIC_SERVER="\"192.168.0.5:/stuff/nfs/odroid\""
|
||||
|
||||
#options NFS_BOOT_RWSIZE=1024
|
||||
|
||||
# Compatibility options
|
||||
|
||||
options COMPAT_NETBSD32 # allow running arm (e.g. non-earm) binaries
|
||||
#options COMPAT_43 # 4.3BSD compatibility.
|
||||
#options COMPAT_09 # NetBSD 0.9,
|
||||
#options COMPAT_10 # NetBSD 1.0,
|
||||
#options COMPAT_11 # NetBSD 1.1,
|
||||
#options COMPAT_12 # NetBSD 1.2,
|
||||
#options COMPAT_13 # NetBSD 1.3,
|
||||
#options COMPAT_14 # NetBSD 1.4,
|
||||
#options COMPAT_15 # NetBSD 1.5,
|
||||
#options COMPAT_16 # NetBSD 1.6,
|
||||
#options COMPAT_20 # NetBSD 2.0,
|
||||
#options COMPAT_30 # NetBSD 3.0,
|
||||
#options COMPAT_40 # NetBSD 4.0,
|
||||
#options COMPAT_50 # NetBSD 5.0,
|
||||
options COMPAT_60 # NetBSD 6.0, and
|
||||
options COMPAT_70 # NetBSD 7.0 binary compatibility.
|
||||
#options TCP_COMPAT_42 # 4.2BSD TCP/IP bug compat. Not recommended.
|
||||
#options COMPAT_BSDPTY # /dev/[pt]ty?? ptys.
|
||||
|
||||
# Shared memory options
|
||||
|
||||
options SYSVMSG # System V-like message queues
|
||||
options SYSVSEM # System V-like semaphores
|
||||
options SYSVSHM # System V-like memory sharing
|
||||
|
||||
# Device options
|
||||
|
||||
#options MEMORY_DISK_HOOKS # boottime setup of ramdisk
|
||||
#options MEMORY_DISK_ROOT_SIZE=8192 # Size in blocks
|
||||
#options MEMORY_DISK_DYNAMIC
|
||||
#options MINIROOTSIZE=1000 # Size in blocks
|
||||
#options MEMORY_DISK_IS_ROOT # use memory disk as root
|
||||
|
||||
# Wedge support
|
||||
options DKWEDGE_AUTODISCOVER # Automatically add dk(4) instances
|
||||
options DKWEDGE_METHOD_GPT # Supports GPT partitions as wedges
|
||||
|
||||
# Miscellaneous kernel options
|
||||
options KTRACE # system call tracing, a la ktrace(1)
|
||||
#options SCSIVERBOSE # Verbose SCSI errors
|
||||
#options MIIVERBOSE # Verbose MII autoconfuration messages
|
||||
options DDB_KEYCODE=0x40
|
||||
#options USERCONF # userconf(4) support
|
||||
#options PIPE_SOCKETPAIR # smaller, but slower pipe(2)
|
||||
|
||||
# Development and Debugging options
|
||||
|
||||
#options PERFCTRS # performance counters
|
||||
options DIAGNOSTIC # internal consistency checks
|
||||
options DEBUG
|
||||
options LOCKDEBUG
|
||||
options PMAP_DEBUG # Enable pmap_debug_level code
|
||||
#options DIAGNOSTIC # internal consistency checks
|
||||
#options DEBUG
|
||||
#options LOCKDEBUG
|
||||
#options PMAP_DEBUG # Enable pmap_debug_level code
|
||||
#options IPKDB # remote kernel debugging
|
||||
options VERBOSE_INIT_ARM # verbose bootstraping messages
|
||||
options DDB # in-kernel debugger
|
||||
options DDB_ONPANIC=1
|
||||
options DDB_HISTORY_SIZE=100 # Enable history editing in DDB
|
||||
options DDB_VERBOSE_HELP
|
||||
#options KGDB
|
||||
#options VERBOSE_INIT_ARM # verbose bootstrapping messages
|
||||
# SSCOMnCONSOLE is required for early init messages from VERBOSE_INIT_ARM.
|
||||
#options SSCOM2CONSOLE
|
||||
|
||||
makeoptions DEBUG="-g" # compile full symbol table
|
||||
makeoptions COPY_SYMTAB=1
|
||||
|
||||
## USB Debugging options
|
||||
options USB_DEBUG
|
||||
options EHCI_DEBUG
|
||||
options OHCI_DEBUG
|
||||
options UHUB_DEBUG
|
||||
options USBVERBOSE
|
||||
|
||||
|
||||
# Valid options for BOOT_ARGS:
|
||||
# single Boot to single user only
|
||||
# kdb Give control to kernel debugger
|
||||
# ask Ask for file name to reboot from
|
||||
# memorydisk=<n> Set memorydisk size to <n> KB
|
||||
# quiet Show aprint_naive output
|
||||
# verbose Show aprint_normal and aprint_verbose output
|
||||
#options BOOT_ARGS="\"\""
|
||||
options BOOT_ARGS="\"verbose\""
|
||||
|
||||
config netbsd root on ? type ?
|
||||
|
||||
# The main bus device
|
||||
mainbus0 at root
|
||||
|
||||
# The boot cpu and secondary CPUs
|
||||
cpu0 at mainbus?
|
||||
cpu* at mainbus? # Multiprocessor
|
||||
|
||||
# core devices
|
||||
armperiph0 at mainbus?
|
||||
armgic0 at armperiph? # Interrupt Controller
|
||||
armgtmr0 at armperiph? # Generic Timer
|
||||
|
||||
# On-board I/O
|
||||
exynosfdt0 at mainbus?
|
||||
# Device tree support
|
||||
armfdt0 at root
|
||||
fdt* at fdtbus?
|
||||
|
||||
fregulator* at fdt?
|
||||
# CPUs
|
||||
cpus* at fdt? pass 0
|
||||
cpu* at cpus?
|
||||
|
||||
#interrupt controller
|
||||
exyointr0 at fdt?
|
||||
gic* at fdt?
|
||||
fclock* at fdt? pass 4
|
||||
fregulator* at fdt? pass 4
|
||||
gpiokeys* at fdt?
|
||||
|
||||
# Timer
|
||||
mct* at fdt? # Exynos Multi Core Timer (MCT)
|
||||
armgtmr0 at mct? # ARM Generic Timer
|
||||
|
||||
# Interrupt controller
|
||||
exyointr* at fdt? pass 1
|
||||
gic* at fdt? pass 1 # GIC
|
||||
armgic0 at gic?
|
||||
|
||||
# Clock controller
|
||||
exy5422clk* at fdt? # Exynos5422 clock controller
|
||||
exy5410clk* at fdt? pass 3 # Exynos5410 clock controller
|
||||
exy5422clk* at fdt? pass 3 # Exynos5422 clock controller
|
||||
|
||||
# Integrated Samsung UARTs
|
||||
sscom* at fdt? # UART ?
|
||||
|
||||
# Exynos Watchdog Timer
|
||||
exyowdt* at fdt? # watchdog
|
||||
|
||||
# Exynos chip id
|
||||
chipid* at fdt?
|
||||
|
||||
# Exynos system MMUs
|
||||
sysmmu* at fdt?
|
||||
|
||||
# Exynos RTC
|
||||
exyortc* at fdt?
|
||||
|
||||
# Exynos Multi Core timer (MCT)
|
||||
mct* at fdt?
|
||||
|
||||
# GPIO
|
||||
exyopctl* at fdt?
|
||||
# GPIO controller
|
||||
exyopctl* at fdt? pass 2 # GPIO
|
||||
gpio* at gpiobus?
|
||||
|
||||
# On-board USB 2.0
|
||||
exyousbphy* at fdt?
|
||||
ohci* at fdt?
|
||||
ehci* at fdt?
|
||||
usb* at ohci?
|
||||
usb* at ehci?
|
||||
# Exynos SoC support
|
||||
chipid* at fdt?
|
||||
sysmmu* at fdt?
|
||||
|
||||
# On-board USB 3.0
|
||||
exyousb* at fdt?
|
||||
#xhci* at fdt?
|
||||
#usb* at xhci?
|
||||
# UART
|
||||
sscom* at fdt? # UART
|
||||
|
||||
# I2C devices
|
||||
exyoi2c* at fdt?
|
||||
#i2c* at exyoi2c?
|
||||
# I2C
|
||||
exyoi2c* at fdt? # I2C
|
||||
iic* at exyoi2c?
|
||||
|
||||
# SD/MMC
|
||||
dwcmmc* at fdt?
|
||||
# RTC
|
||||
#exyortc* at fdt? # RTC
|
||||
|
||||
# SDMMC
|
||||
dwcmmc* at fdt? # SDMMC
|
||||
sdmmc* at dwcmmc?
|
||||
ld0 at sdmmc0
|
||||
ld1 at sdmmc1
|
||||
ld2 at sdmmc2
|
||||
ld3 at sdmmc3
|
||||
ld* at sdmmc?
|
||||
|
||||
# MISSING SUPPORT
|
||||
# eMMC
|
||||
# uSD
|
||||
# SPI
|
||||
# ADC
|
||||
# PMIC (via I2C #4)
|
||||
# PWM for Cooling fan
|
||||
# HDMI
|
||||
# I2S
|
||||
# GPU
|
||||
# USB
|
||||
exyousbphy* at fdt?
|
||||
exyousb* at fdt?
|
||||
ohci* at fdt? # OUSB
|
||||
ehci* at fdt? # EUSB
|
||||
usb* at ohci?
|
||||
usb* at ehci?
|
||||
|
||||
# serial console connectivity
|
||||
options SSCOM2CONSOLE, CONSPEED=115200
|
||||
|
||||
# include all USB devices
|
||||
include "dev/usb/usbdevices.config"
|
||||
|
||||
midi* at midibus?
|
||||
|
||||
# Pseudo-Devices
|
||||
|
||||
# disk/mass storage pseudo-devices
|
||||
#pseudo-device md # memory disk device (ramdisk)
|
||||
#pseudo-device vnd # disk-like interface to files
|
||||
#pseudo-device fss # file system snapshot device
|
||||
#pseudo-device putter # for puffs and pud
|
||||
pseudo-device drvctl # driver control
|
||||
|
||||
# network pseudo-devices
|
||||
pseudo-device bpfilter # Berkeley packet filter
|
||||
pseudo-device loop # network loopback
|
||||
#pseudo-device kttcp # network loopback
|
||||
|
||||
# miscellaneous pseudo-devices
|
||||
pseudo-device pty # pseudo-terminals
|
||||
#options RND_COM
|
||||
#pseudo-device clockctl # user control of clock subsystem
|
||||
pseudo-device ksyms # /dev/ksyms
|
||||
#pseudo-device lockstat # lock profiling
|
||||
cinclude "arch/evbarm/conf/EXYNOS.local"
|
||||
|
|
|
@ -1,248 +0,0 @@
|
|||
#
|
||||
# $NetBSD: ODROID-U,v 1.20 2017/02/19 07:47:00 rin Exp $
|
||||
#
|
||||
# ODROID-U -- ODROID-U{2,3} series Exynos4x12(P) based kernel
|
||||
#
|
||||
|
||||
include "arch/evbarm/conf/std.odroid"
|
||||
|
||||
# estimated number of users
|
||||
|
||||
maxusers 32
|
||||
|
||||
# Standard system options
|
||||
|
||||
options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT
|
||||
#options NTP # NTP phase/frequency locked loop
|
||||
|
||||
# CPU options
|
||||
options CPU_CORTEX
|
||||
options CPU_CORTEXA9
|
||||
options EXYNOS4212
|
||||
options EXYNOS4412
|
||||
options EXYNOS4412P
|
||||
#options MULTIPROCESSOR
|
||||
|
||||
options PMAPCOUNTERS
|
||||
options BUSDMA_COUNTERS
|
||||
options EXYNOS_CONSOLE_EARLY
|
||||
#options UVMHIST
|
||||
#options UVMHIST_PRINT,KERNHIST_DELAY=0
|
||||
#options KERNHIST
|
||||
#options USB_DEBUG
|
||||
#options USBHIST_SIZE=100000
|
||||
options __HAVE_MM_MD_DIRECT_MAPPED_PHYS
|
||||
options PMAP_NEED_ALLOC_POOLPAGE
|
||||
|
||||
# Specify the memory size in megabytes (optional).
|
||||
#options MEMSIZE=2048
|
||||
|
||||
# File systems
|
||||
file-system FFS # UFS
|
||||
#file-system LFS # log-structured file system
|
||||
file-system MFS # memory file system
|
||||
file-system NFS # Network file system
|
||||
#file-system ADOSFS # AmigaDOS-compatible file system
|
||||
#file-system EXT2FS # second extended file system (linux)
|
||||
#file-system CD9660 # ISO 9660 + Rock Ridge file system
|
||||
file-system MSDOSFS # MS-DOS file system
|
||||
#file-system FDESC # /dev/fd
|
||||
file-system KERNFS # /kern
|
||||
#file-system NULLFS # loopback file system
|
||||
file-system PROCFS # /proc
|
||||
#file-system PUFFS # Userspace file systems (e.g. ntfs-3g & sshfs)
|
||||
#file-system UMAPFS # NULLFS + uid and gid remapping
|
||||
#file-system UNION # union file system
|
||||
file-system TMPFS # memory file system
|
||||
file-system PTYFS # /dev/pts/N support
|
||||
|
||||
# File system options
|
||||
#options QUOTA # legacy UFS quotas
|
||||
#options QUOTA2 # new, in-filesystem UFS quotas
|
||||
#options DISKLABEL_EI # disklabel Endian Independent support
|
||||
#options FFS_EI # FFS Endian Independent support
|
||||
#options NFSSERVER
|
||||
options WAPBL # File system journaling support
|
||||
#options FFS_NO_SNAPSHOT # No FFS snapshot support
|
||||
|
||||
# Networking options
|
||||
|
||||
#options GATEWAY # packet forwarding
|
||||
options INET # IP + ICMP + TCP + UDP
|
||||
options INET6 # IPV6
|
||||
#options IPSEC # IP security
|
||||
#options IPSEC_DEBUG # debug for IP security
|
||||
#options MROUTING # IP multicast routing
|
||||
#options PIM # Protocol Independent Multicast
|
||||
#options NETATALK # AppleTalk networking
|
||||
#options PPP_BSDCOMP # BSD-Compress compression support for PPP
|
||||
#options PPP_DEFLATE # Deflate compression support for PPP
|
||||
#options PPP_FILTER # Active filter support for PPP (requires bpf)
|
||||
#options TCP_DEBUG # Record last TCP_NDEBUG packets with SO_DEBUG
|
||||
|
||||
options NFS_BOOT_BOOTP
|
||||
options NFS_BOOT_DHCP
|
||||
#options NFS_BOOT_BOOTSTATIC
|
||||
#options NFS_BOOTSTATIC_MYIP="\"192.168.1.4\""
|
||||
#options NFS_BOOTSTATIC_GWIP="\"192.168.1.1\""
|
||||
#options NFS_BOOTSTATIC_MASK="\"255.255.255.0\""
|
||||
#options NFS_BOOTSTATIC_SERVADDR="\"192.168.1.1\""
|
||||
#options NFS_BOOTSTATIC_SERVER="\"192.168.1.1:/nfs/sdp2430\""
|
||||
|
||||
options NFS_BOOT_RWSIZE=1024
|
||||
|
||||
# Compatibility options
|
||||
|
||||
options COMPAT_NETBSD32 # allow running arm (e.g. non-earm) binaries
|
||||
#options COMPAT_43 # 4.3BSD compatibility.
|
||||
#options COMPAT_09 # NetBSD 0.9,
|
||||
#options COMPAT_10 # NetBSD 1.0,
|
||||
#options COMPAT_11 # NetBSD 1.1,
|
||||
#options COMPAT_12 # NetBSD 1.2,
|
||||
#options COMPAT_13 # NetBSD 1.3,
|
||||
#options COMPAT_14 # NetBSD 1.4,
|
||||
#options COMPAT_15 # NetBSD 1.5,
|
||||
#options COMPAT_16 # NetBSD 1.6,
|
||||
#options COMPAT_20 # NetBSD 2.0,
|
||||
options COMPAT_30 # NetBSD 3.0,
|
||||
options COMPAT_40 # NetBSD 4.0,
|
||||
options COMPAT_50 # NetBSD 5.0,
|
||||
options COMPAT_60 # NetBSD 6.0, and
|
||||
options COMPAT_70 # NetBSD 7.0 binary compatibility.
|
||||
#options TCP_COMPAT_42 # 4.2BSD TCP/IP bug compat. Not recommended.
|
||||
#options COMPAT_BSDPTY # /dev/[pt]ty?? ptys.
|
||||
|
||||
# Shared memory options
|
||||
|
||||
options SYSVMSG # System V-like message queues
|
||||
options SYSVSEM # System V-like semaphores
|
||||
options SYSVSHM # System V-like memory sharing
|
||||
|
||||
# Device options
|
||||
|
||||
#options MEMORY_DISK_HOOKS # boottime setup of ramdisk
|
||||
#options MEMORY_DISK_ROOT_SIZE=8192 # Size in blocks
|
||||
#options MEMORY_DISK_DYNAMIC
|
||||
#options MINIROOTSIZE=1000 # Size in blocks
|
||||
#options MEMORY_DISK_IS_ROOT # use memory disk as root
|
||||
|
||||
# Wedge support
|
||||
options DKWEDGE_AUTODISCOVER # Automatically add dk(4) instances
|
||||
options DKWEDGE_METHOD_GPT # Supports GPT partitions as wedges
|
||||
|
||||
# Miscellaneous kernel options
|
||||
options KTRACE # system call tracing, a la ktrace(1)
|
||||
#options SCSIVERBOSE # Verbose SCSI errors
|
||||
options MIIVERBOSE # Verbose MII autoconfuration messages
|
||||
#options DDB_KEYCODE=0x40
|
||||
#options USERCONF # userconf(4) support
|
||||
#options PIPE_SOCKETPAIR # smaller, but slower pipe(2)
|
||||
|
||||
# Development and Debugging options
|
||||
|
||||
#options PERFCTRS # performance counters
|
||||
options DIAGNOSTIC # internal consistency checks
|
||||
options DEBUG
|
||||
options LOCKDEBUG
|
||||
#options PMAP_DEBUG # Enable pmap_debug_level code
|
||||
#options IPKDB # remote kernel debugging
|
||||
options VERBOSE_INIT_ARM # verbose bootstraping messages
|
||||
options DDB # in-kernel debugger
|
||||
options DDB_ONPANIC=1
|
||||
options DDB_HISTORY_SIZE=100 # Enable history editing in DDB
|
||||
#options KGDB
|
||||
makeoptions DEBUG="-g" # compile full symbol table
|
||||
makeoptions COPY_SYMTAB=1
|
||||
|
||||
## USB Debugging options
|
||||
options USB_DEBUG
|
||||
options EHCI_DEBUG
|
||||
options OHCI_DEBUG
|
||||
options UHUB_DEBUG
|
||||
options USBVERBOSE
|
||||
|
||||
|
||||
# Valid options for BOOT_ARGS:
|
||||
# single Boot to single user only
|
||||
# kdb Give control to kernel debugger
|
||||
# ask Ask for file name to reboot from
|
||||
# memorydisk=<n> Set memorydisk size to <n> KB
|
||||
# quiet Show aprint_naive output
|
||||
# verbose Show aprint_normal and aprint_verbose output
|
||||
options BOOT_ARGS="\"verbose\""
|
||||
|
||||
config netbsd root on ? type ?
|
||||
|
||||
# The main bus device
|
||||
mainbus0 at root
|
||||
|
||||
# The boot cpu and secondary CPUs
|
||||
cpu0 at mainbus?
|
||||
#cpu? at mainbus? # Multiprocessor
|
||||
|
||||
# A9 core devices
|
||||
armperiph0 at mainbus?
|
||||
armgic0 at armperiph? # Interrupt Controller
|
||||
arml2cc0 at armperiph? # L2 Cache Controller
|
||||
|
||||
# Exynos SoC
|
||||
exyo0 at mainbus?
|
||||
|
||||
# Integrated Samsung devices
|
||||
mct0 at exyo0
|
||||
|
||||
# Integrated Samsung UARTs
|
||||
sscom0 at exyo0 port 0 # UART0, expansion
|
||||
sscom1 at exyo0 port 1 # UART1, console
|
||||
|
||||
# Exynos Watchdog Timer
|
||||
exyowdt0 at exyo0 flags 0 # watchdog
|
||||
|
||||
# GPIO
|
||||
exyogpio0 at exyo0
|
||||
gpio* at exyogpio?
|
||||
|
||||
# On-board USB
|
||||
exyousb* at exyo0
|
||||
ohci* at exyousb?
|
||||
ehci* at exyousb?
|
||||
usb* at ohci?
|
||||
usb* at ehci?
|
||||
|
||||
# Network phy for the LAN9730
|
||||
ukphy* at mii? phy ? # generic unknown PHYs
|
||||
|
||||
# I2C devices
|
||||
exyoiic0 at exyo0
|
||||
iic* at exyoiic?
|
||||
|
||||
# serial console connectivity
|
||||
options SSCOM1CONSOLE, CONSPEED=115200
|
||||
|
||||
# include all USB devices
|
||||
include "dev/usb/usbdevices.config"
|
||||
|
||||
midi* at midibus?
|
||||
|
||||
|
||||
# Pseudo-Devices
|
||||
|
||||
# disk/mass storage pseudo-devices
|
||||
#pseudo-device md # memory disk device (ramdisk)
|
||||
#pseudo-device vnd # disk-like interface to files
|
||||
#pseudo-device fss # file system snapshot device
|
||||
#pseudo-device putter # for puffs and pud
|
||||
pseudo-device drvctl # driver control
|
||||
|
||||
# network pseudo-devices
|
||||
pseudo-device bpfilter # Berkeley packet filter
|
||||
pseudo-device loop # network loopback
|
||||
#pseudo-device kttcp # network loopback
|
||||
|
||||
# miscellaneous pseudo-devices
|
||||
pseudo-device pty # pseudo-terminals
|
||||
#options RND_COM
|
||||
#pseudo-device clockctl # user control of clock subsystem
|
||||
pseudo-device ksyms # /dev/ksyms
|
||||
#pseudo-device lockstat # lock profiling
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
#
|
||||
# $NetBSD: ODROID-XU,v 1.7 2017/02/19 07:47:00 rin Exp $
|
||||
#
|
||||
# ODROID-XU -- ODROID-XU Exynos5410 based kernel
|
||||
#
|
||||
|
||||
include "arch/evbarm/conf/std.odroid"
|
||||
|
||||
# estimated number of users
|
||||
|
||||
maxusers 32
|
||||
|
||||
# Standard system options
|
||||
|
||||
options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT
|
||||
#options NTP # NTP phase/frequency locked loop
|
||||
|
||||
# CPU options
|
||||
options CPU_CORTEX
|
||||
options CPU_CORTEXA7
|
||||
options CPU_CORTEXA15
|
||||
options EXYNOS5410
|
||||
#options MULTIPROCESSOR
|
||||
|
||||
options PMAPCOUNTERS
|
||||
options BUSDMA_COUNTERS
|
||||
options EXYNOS_CONSOLE_EARLY
|
||||
#options UVMHIST
|
||||
options USB_DEBUG
|
||||
options USBHIST_SIZE=100000
|
||||
#options UVMHIST_PRINT,KERNHIST_DELAY=0
|
||||
options __HAVE_MM_MD_DIRECT_MAPPED_PHYS
|
||||
options PMAP_NEED_ALLOC_POOLPAGE
|
||||
|
||||
# Specify the memory size in megabytes (optional).
|
||||
#options MEMSIZE=2048
|
||||
|
||||
# File systems
|
||||
file-system FFS # UFS
|
||||
#file-system LFS # log-structured file system
|
||||
file-system MFS # memory file system
|
||||
file-system NFS # Network file system
|
||||
#file-system ADOSFS # AmigaDOS-compatible file system
|
||||
#file-system EXT2FS # second extended file system (linux)
|
||||
#file-system CD9660 # ISO 9660 + Rock Ridge file system
|
||||
file-system MSDOSFS # MS-DOS file system
|
||||
#file-system FDESC # /dev/fd
|
||||
file-system KERNFS # /kern
|
||||
#file-system NULLFS # loopback file system
|
||||
file-system PROCFS # /proc
|
||||
#file-system PUFFS # Userspace file systems (e.g. ntfs-3g & sshfs)
|
||||
#file-system UMAPFS # NULLFS + uid and gid remapping
|
||||
#file-system UNION # union file system
|
||||
file-system TMPFS # memory file system
|
||||
file-system PTYFS # /dev/pts/N support
|
||||
|
||||
# File system options
|
||||
#options QUOTA # legacy UFS quotas
|
||||
#options QUOTA2 # new, in-filesystem UFS quotas
|
||||
#options DISKLABEL_EI # disklabel Endian Independent support
|
||||
#options FFS_EI # FFS Endian Independent support
|
||||
#options NFSSERVER
|
||||
options WAPBL # File system journaling support
|
||||
#options FFS_NO_SNAPSHOT # No FFS snapshot support
|
||||
|
||||
# Networking options
|
||||
|
||||
#options GATEWAY # packet forwarding
|
||||
options INET # IP + ICMP + TCP + UDP
|
||||
options INET6 # IPV6
|
||||
#options IPSEC # IP security
|
||||
#options IPSEC_DEBUG # debug for IP security
|
||||
#options MROUTING # IP multicast routing
|
||||
#options PIM # Protocol Independent Multicast
|
||||
#options NETATALK # AppleTalk networking
|
||||
#options PPP_BSDCOMP # BSD-Compress compression support for PPP
|
||||
#options PPP_DEFLATE # Deflate compression support for PPP
|
||||
#options PPP_FILTER # Active filter support for PPP (requires bpf)
|
||||
#options TCP_DEBUG # Record last TCP_NDEBUG packets with SO_DEBUG
|
||||
|
||||
options NFS_BOOT_BOOTP
|
||||
options NFS_BOOT_DHCP
|
||||
#options NFS_BOOT_BOOTSTATIC
|
||||
#options NFS_BOOTSTATIC_MYIP="\"192.168.1.4\""
|
||||
#options NFS_BOOTSTATIC_GWIP="\"192.168.1.1\""
|
||||
#options NFS_BOOTSTATIC_MASK="\"255.255.255.0\""
|
||||
#options NFS_BOOTSTATIC_SERVADDR="\"192.168.1.1\""
|
||||
#options NFS_BOOTSTATIC_SERVER="\"192.168.1.1:/nfs/sdp2430\""
|
||||
|
||||
options NFS_BOOT_RWSIZE=1024
|
||||
|
||||
# Compatibility options
|
||||
|
||||
options COMPAT_NETBSD32 # allow running arm (e.g. non-earm) binaries
|
||||
#options COMPAT_43 # 4.3BSD compatibility.
|
||||
#options COMPAT_09 # NetBSD 0.9,
|
||||
#options COMPAT_10 # NetBSD 1.0,
|
||||
#options COMPAT_11 # NetBSD 1.1,
|
||||
#options COMPAT_12 # NetBSD 1.2,
|
||||
#options COMPAT_13 # NetBSD 1.3,
|
||||
#options COMPAT_14 # NetBSD 1.4,
|
||||
#options COMPAT_15 # NetBSD 1.5,
|
||||
#options COMPAT_16 # NetBSD 1.6,
|
||||
#options COMPAT_20 # NetBSD 2.0,
|
||||
options COMPAT_30 # NetBSD 3.0,
|
||||
options COMPAT_40 # NetBSD 4.0,
|
||||
options COMPAT_50 # NetBSD 5.0,
|
||||
options COMPAT_60 # NetBSD 6.0, and
|
||||
options COMPAT_70 # NetBSD 7.0 binary compatibility.
|
||||
#options TCP_COMPAT_42 # 4.2BSD TCP/IP bug compat. Not recommended.
|
||||
#options COMPAT_BSDPTY # /dev/[pt]ty?? ptys.
|
||||
|
||||
# Shared memory options
|
||||
|
||||
options SYSVMSG # System V-like message queues
|
||||
options SYSVSEM # System V-like semaphores
|
||||
options SYSVSHM # System V-like memory sharing
|
||||
|
||||
# Device options
|
||||
|
||||
#options MEMORY_DISK_HOOKS # boottime setup of ramdisk
|
||||
#options MEMORY_DISK_ROOT_SIZE=8192 # Size in blocks
|
||||
#options MEMORY_DISK_DYNAMIC
|
||||
#options MINIROOTSIZE=1000 # Size in blocks
|
||||
#options MEMORY_DISK_IS_ROOT # use memory disk as root
|
||||
|
||||
# Wedge support
|
||||
options DKWEDGE_AUTODISCOVER # Automatically add dk(4) instances
|
||||
options DKWEDGE_METHOD_GPT # Supports GPT partitions as wedges
|
||||
|
||||
# Miscellaneous kernel options
|
||||
options KTRACE # system call tracing, a la ktrace(1)
|
||||
#options SCSIVERBOSE # Verbose SCSI errors
|
||||
#options MIIVERBOSE # Verbose MII autoconfuration messages
|
||||
#options DDB_KEYCODE=0x40
|
||||
#options USERCONF # userconf(4) support
|
||||
#options PIPE_SOCKETPAIR # smaller, but slower pipe(2)
|
||||
|
||||
# Development and Debugging options
|
||||
|
||||
#options PERFCTRS # performance counters
|
||||
options DIAGNOSTIC # internal consistency checks
|
||||
options DEBUG
|
||||
options LOCKDEBUG
|
||||
#options PMAP_DEBUG # Enable pmap_debug_level code
|
||||
#options IPKDB # remote kernel debugging
|
||||
options VERBOSE_INIT_ARM # verbose bootstraping messages
|
||||
options DDB # in-kernel debugger
|
||||
options DDB_ONPANIC=1
|
||||
options DDB_HISTORY_SIZE=100 # Enable history editing in DDB
|
||||
#options KGDB
|
||||
makeoptions DEBUG="-g" # compile full symbol table
|
||||
makeoptions COPY_SYMTAB=1
|
||||
|
||||
## USB Debugging options
|
||||
options USB_DEBUG
|
||||
options EHCI_DEBUG
|
||||
options OHCI_DEBUG
|
||||
options UHUB_DEBUG
|
||||
options USBVERBOSE
|
||||
|
||||
|
||||
# Valid options for BOOT_ARGS:
|
||||
# single Boot to single user only
|
||||
# kdb Give control to kernel debugger
|
||||
# ask Ask for file name to reboot from
|
||||
# memorydisk=<n> Set memorydisk size to <n> KB
|
||||
# quiet Show aprint_naive output
|
||||
# verbose Show aprint_normal and aprint_verbose output
|
||||
#options BOOT_ARGS="\"\""
|
||||
options BOOT_ARGS="\"verbose\""
|
||||
|
||||
config netbsd root on ? type ?
|
||||
|
||||
# The main bus device
|
||||
mainbus0 at root
|
||||
|
||||
# The boot cpu and secondary CPUs
|
||||
cpu0 at mainbus?
|
||||
#cpu? at mainbus? # Multiprocessor
|
||||
|
||||
# A9 core devices
|
||||
armperiph0 at mainbus?
|
||||
armgic0 at armperiph? # Interrupt Controller
|
||||
armgtmr0 at armperiph? # Generic Timer
|
||||
|
||||
# Exynos SoC
|
||||
exyo0 at mainbus?
|
||||
|
||||
# Integrated Samsung UARTs
|
||||
#sscom* at exyo0 port ? # UART ?
|
||||
sscom2 at exyo0 port 2 # UART2
|
||||
|
||||
# Exynos Watchdog Timer
|
||||
#exyowdt0 at exyo0 # watchdog
|
||||
|
||||
# GPIO
|
||||
exyogpio0 at exyo0
|
||||
gpio* at exyogpio?
|
||||
|
||||
# On-board USB
|
||||
exyousb* at exyo0
|
||||
ohci* at exyousb?
|
||||
ehci* at exyousb?
|
||||
usb* at ohci?
|
||||
usb* at ehci?
|
||||
|
||||
# Network phy for the LAN9730
|
||||
ukphy* at mii? phy ? # generic unknown PHYs
|
||||
|
||||
# I2C devices
|
||||
exyoiic0 at exyo0
|
||||
iic* at exyoiic?
|
||||
|
||||
# SATA
|
||||
#ahcisata* at exyno0
|
||||
#atabus* at ata?
|
||||
#wd* at atabus? drive ?
|
||||
|
||||
|
||||
# serial console connectivity
|
||||
options SSCOM2CONSOLE, CONSPEED=115200
|
||||
|
||||
# include all USB devices
|
||||
include "dev/usb/usbdevices.config"
|
||||
|
||||
midi* at midibus?
|
||||
|
||||
|
||||
# Pseudo-Devices
|
||||
|
||||
# disk/mass storage pseudo-devices
|
||||
#pseudo-device md # memory disk device (ramdisk)
|
||||
#pseudo-device vnd # disk-like interface to files
|
||||
#pseudo-device fss # file system snapshot device
|
||||
#pseudo-device putter # for puffs and pud
|
||||
pseudo-device drvctl # driver control
|
||||
|
||||
# network pseudo-devices
|
||||
pseudo-device bpfilter # Berkeley packet filter
|
||||
pseudo-device loop # network loopback
|
||||
#pseudo-device kttcp # network loopback
|
||||
|
||||
# miscellaneous pseudo-devices
|
||||
pseudo-device pty # pseudo-terminals
|
||||
#options RND_COM
|
||||
#pseudo-device clockctl # user control of clock subsystem
|
||||
pseudo-device ksyms # /dev/ksyms
|
||||
#pseudo-device lockstat # lock profiling
|
|
@ -1,11 +0,0 @@
|
|||
# $NetBSD: ODROID-XU_INSTALL,v 1.1 2014/09/26 15:33:58 reinoud Exp $
|
||||
#
|
||||
# ODROID_INSTALL -- ODROID kernel with installation-sized
|
||||
# ramdisk
|
||||
#
|
||||
|
||||
include "arch/evbarm/conf/ODROID-XU"
|
||||
include "arch/evbarm/conf/INSTALL"
|
||||
|
||||
options BOOTHOWTO=RB_SINGLE
|
||||
no makeoptions DEBUG
|
|
@ -0,0 +1,131 @@
|
|||
#
|
||||
# $NetBSD: SUNXI,v 1.17.4.2 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# Allwinner sunxi family
|
||||
#
|
||||
|
||||
include "arch/evbarm/conf/std.sunxi"
|
||||
include "arch/evbarm/conf/GENERIC.common"
|
||||
|
||||
makeoptions DTS="
|
||||
sun6i-a31-app4-evb1.dts
|
||||
sun6i-a31-colombus.dts
|
||||
sun6i-a31-hummingbird.dts
|
||||
sun6i-a31-i7.dts
|
||||
sun6i-a31-m9.dts
|
||||
sun6i-a31-mele-a1000g-quad.dts
|
||||
|
||||
sun8i-h3-bananapi-m2-plus.dts
|
||||
sun8i-h3-beelink-x2.dts
|
||||
sun8i-h3-nanopi-m1.dts
|
||||
sun8i-h3-nanopi-neo.dts
|
||||
sun8i-h3-orangepi-2.dts
|
||||
sun8i-h3-orangepi-lite.dts
|
||||
sun8i-h3-orangepi-pc-plus.dts
|
||||
sun8i-h3-orangepi-pc.dts
|
||||
sun8i-h3-orangepi-plus.dts
|
||||
sun8i-h3-orangepi-plus2e.dts
|
||||
"
|
||||
|
||||
options CPU_CORTEXA7
|
||||
options SOC_SUN6I_A31
|
||||
options SOC_SUN8I_A83T
|
||||
options SOC_SUN8I_H3
|
||||
options MULTIPROCESSOR
|
||||
|
||||
pseudo-device openfirm # /dev/openfirm
|
||||
|
||||
#options DIAGNOSTIC # internal consistency checks
|
||||
#options DEBUG
|
||||
#options LOCKDEBUG
|
||||
#options PMAP_DEBUG # Enable pmap_debug_level code
|
||||
#options IPKDB # remote kernel debugging
|
||||
#options VERBOSE_INIT_ARM # verbose bootstrapping messages
|
||||
# CONSADDR is required for early init messages from VERBOSE_INIT_ARM.
|
||||
#options CONSADDR=0x01c28000
|
||||
|
||||
makeoptions DEBUG="-g" # compile full symbol table
|
||||
makeoptions COPY_SYMTAB=1
|
||||
|
||||
config netbsd root on ? type ?
|
||||
|
||||
# Device tree support
|
||||
armfdt0 at root
|
||||
fdt* at fdtbus?
|
||||
|
||||
# CPUs
|
||||
cpus* at fdt? pass 0
|
||||
cpu* at cpus?
|
||||
|
||||
# Power state coordination interface
|
||||
psci* at fdt?
|
||||
|
||||
# Clock and reset controllers
|
||||
sun6ia31ccu* at fdt? pass 4 # A31 CCU
|
||||
sun8ia83tccu* at fdt? pass 4 # A83T CCU
|
||||
sun8ih3ccu* at fdt? pass 4 # H3 CCU
|
||||
sunxiresets* at fdt? pass 1 # Misc. clock resets
|
||||
sunxigates* at fdt? pass 1 # Misc. clock gates
|
||||
|
||||
fclock* at fdt? pass 1
|
||||
ffclock* at fdt? pass 1
|
||||
fregulator* at fdt? pass 4
|
||||
gpiokeys* at fdt?
|
||||
gpioleds* at fdt?
|
||||
|
||||
# Timer
|
||||
gtmr* at fdt? pass 1 # ARM Generic Timer
|
||||
armgtmr0 at gtmr?
|
||||
|
||||
# Interrupt controller
|
||||
gic* at fdt? pass 1 # GIC
|
||||
armgic0 at gic?
|
||||
|
||||
# Memory controller
|
||||
|
||||
# DMA controller
|
||||
|
||||
# Clock and Reset controller
|
||||
|
||||
# GPIO controller
|
||||
sunxigpio* at fdt? pass 2 # GPIO
|
||||
gpio* at gpiobus?
|
||||
|
||||
# Ethernet
|
||||
sunxiemac* at fdt? # Allwinner Gigabit Ethernet
|
||||
rgephy* at mii? phy ?
|
||||
ukphy* at mii? phy ?
|
||||
|
||||
# UART
|
||||
com* at fdt? # UART
|
||||
options COM_AWIN # XXX this should be a driver flag
|
||||
|
||||
# I2C
|
||||
sunxitwi* at fdt? # TWI
|
||||
options GTTWSI_ALLWINNER # XXX this should be a driver flag
|
||||
sunxirsb* at fdt? # P2WI/RSB
|
||||
iic* at i2cbus?
|
||||
|
||||
# RTC
|
||||
sunxirtc* at fdt? # RTC
|
||||
|
||||
# SDMMC
|
||||
sunximmc* at fdt? # SDMMC
|
||||
sdmmc* at sunximmc?
|
||||
ld0 at sdmmc0
|
||||
ld1 at sdmmc1
|
||||
ld2 at sdmmc2
|
||||
ld3 at sdmmc3
|
||||
ld* at sdmmc?
|
||||
|
||||
# USB 2.0
|
||||
sunxiusbphy* at fdt? pass 9 # USB PHY
|
||||
ehci* at fdt? # EHCI
|
||||
ohci* at fdt? # OHCI
|
||||
usb* at ehci?
|
||||
usb* at ohci?
|
||||
|
||||
include "dev/usb/usbdevices.config"
|
||||
midi* at midibus?
|
||||
|
||||
cinclude "arch/evbarm/conf/SUNXI.local"
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# $NetBSD: TEGRA,v 1.23 2017/06/02 00:09:56 jmcneill Exp $
|
||||
# $NetBSD: TEGRA,v 1.23.2.1 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# NVIDIA Tegra K1 (T124)
|
||||
#
|
||||
|
@ -7,6 +7,14 @@
|
|||
include "arch/evbarm/conf/std.tegra"
|
||||
include "arch/evbarm/conf/GENERIC.common"
|
||||
|
||||
makeoptions DTS="
|
||||
tegra124-apalis-eval.dts
|
||||
tegra124-jetson-tk1.dts
|
||||
tegra124-nyan-big.dts
|
||||
tegra124-nyan-blaze.dts
|
||||
tegra124-venice2.dts
|
||||
"
|
||||
|
||||
options CPU_CORTEXA15
|
||||
options SOC_TEGRA124
|
||||
options MULTIPROCESSOR
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# $NetBSD: VEXPRESS_A15,v 1.12.2.3 2017/06/10 05:57:08 snj Exp $
|
||||
# $NetBSD: VEXPRESS_A15,v 1.12.2.4 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# ARM Versatile Express A15
|
||||
#
|
||||
|
@ -7,6 +7,8 @@
|
|||
include "arch/evbarm/conf/std.vexpress"
|
||||
include "arch/evbarm/conf/GENERIC.common"
|
||||
|
||||
makeoptions DTS="vexpress-v2p-ca15-tc1.dts"
|
||||
|
||||
options CPU_CORTEXA15
|
||||
options MULTIPROCESSOR
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.evbarm,v 1.25 2014/12/04 21:15:48 joerg Exp $
|
||||
# $NetBSD: files.evbarm,v 1.25.10.1 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# First try for arm-specific configuration info
|
||||
#
|
||||
|
@ -48,4 +48,9 @@ defflag opt_plcom.h PLCOM_DEBUG
|
|||
device plcom { }: tty
|
||||
file arch/evbarm/dev/plcom.c plcom needs-flag
|
||||
|
||||
#
|
||||
# Maximum number of memory ranges
|
||||
#
|
||||
defparam opt_machdep.h DRAM_BLOCKS
|
||||
|
||||
include "arch/arm/conf/majors.arm32"
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
# $NetBSD: files.exynos,v 1.2 2015/12/14 22:06:57 marty Exp $
|
||||
# $NetBSD: files.exynos,v 1.2.12.1 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# EXYNOS 5422 board configuration info
|
||||
# EXYNOS board configuration info
|
||||
#
|
||||
|
||||
file arch/evbarm/exynos/exynos_machdep.c
|
||||
include "arch/evbarm/conf/files.fdt"
|
||||
|
||||
# Kernel boot arguments
|
||||
defparam opt_machdep.h BOOT_ARGS
|
||||
|
||||
# FDT
|
||||
|
||||
include "dev/ofw/files.ofw"
|
||||
include "dev/fdt/files.fdt"
|
||||
include "arch/arm/fdt/files.fdt"
|
||||
|
||||
# Pull in Exynos SoC default
|
||||
include "arch/arm/samsung/files.exynos"
|
||||
include "arch/arm/samsung/files.exynos"
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# $NetBSD: files.sunxi,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# Allwinner sunxi configuration info
|
||||
#
|
||||
|
||||
include "arch/evbarm/conf/files.fdt"
|
||||
|
||||
include "arch/arm/sunxi/files.sunxi"
|
|
@ -0,0 +1,32 @@
|
|||
# $NetBSD: mk.sunxi,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $
|
||||
|
||||
SYSTEM_FIRST_OBJ= sunxi_start.o
|
||||
SYSTEM_FIRST_SFILE= ${THISARM}/sunxi/sunxi_start.S
|
||||
|
||||
AFLAGS.sunxi_start.S+= -Wa,-march=armv7-a+virt
|
||||
AFLAGS.psci_arm.S+= -Wa,-march=armv7-a+sec+virt
|
||||
|
||||
GENASSYM_EXTRAS+= ${THISARM}/sunxi/genassym.cf
|
||||
|
||||
_OSRELEASE!= ${HOST_SH} $S/conf/osrelease.sh
|
||||
|
||||
MKUBOOTIMAGEARGS= -A arm -T kernel -O linux
|
||||
MKUBOOTIMAGEARGS+= -a $(KERNEL_BASE_PHYS) -e $(KERNEL_BASE_PHYS)
|
||||
MKUBOOTIMAGEARGS+= -n "NetBSD/$(BOARDTYPE) ${_OSRELEASE}"
|
||||
MKUBOOTIMAGEARGS_NONE= ${MKUBOOTIMAGEARGS} -C none
|
||||
MKUBOOTIMAGEARGS_GZ= ${MKUBOOTIMAGEARGS} -C gz
|
||||
|
||||
SYSTEM_LD_TAIL_EXTRA+=; \
|
||||
echo ${OBJCOPY} -S -O binary $@ $@.bin; \
|
||||
${OBJCOPY} -S -O binary $@ $@.bin; \
|
||||
echo ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_NONE} $@.bin $@.ub; \
|
||||
${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_NONE} $@.bin $@.ub; \
|
||||
echo ${TOOL_GZIP} -c $@.bin > $@.bin.gz; \
|
||||
${TOOL_GZIP} -c $@.bin > $@.bin.gz; \
|
||||
echo ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_GZ} $@.bin.gz $@.gz.ub; \
|
||||
${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_GZ} $@.bin.gz $@.gz.ub
|
||||
|
||||
EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.bin@}
|
||||
EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.ub@}
|
||||
EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.bin.gz@}
|
||||
EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.gz.ub@}
|
|
@ -1,35 +1,36 @@
|
|||
# $NetBSD: std.exynos,v 1.1 2015/12/06 00:31:24 marty Exp $
|
||||
# $NetBSD: std.exynos,v 1.1.12.1 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# standard NetBSD/evbarm for EXYNOS options
|
||||
|
||||
machine evbarm arm
|
||||
include "arch/evbarm/conf/std.evbarm"
|
||||
|
||||
# Pull in EXYNOS config definitions
|
||||
include "arch/evbarm/conf/files.exynos"
|
||||
include "arch/evbarm/conf/files.exynos"
|
||||
|
||||
makeoptions CPUFLAGS="-march=armv7-a -mfpu=neon"
|
||||
makeoptions CPUFLAGS="-march=armv7-a -mfpu=neon"
|
||||
|
||||
# To support easy transit to ../arch/arm/arm32
|
||||
options MODULAR
|
||||
options MODULAR_DEFAULT_AUTOLOAD
|
||||
options ARM_HAS_VBAR
|
||||
options CORTEX_PMC
|
||||
options __HAVE_CPU_COUNTER
|
||||
options __HAVE_FAST_SOFTINTS # should be in types.h
|
||||
#options __HAVE_MM_MD_DIRECT_MAPPED_PHYS
|
||||
options TPIDRPRW_IS_CURCPU
|
||||
options KERNEL_BASE_EXT=0x80000000
|
||||
options FPU_VFP
|
||||
|
||||
# All shipped Samsung SoC's that are not Samsung products have this
|
||||
options ARM_TRUSTZONE_FIRMWARE
|
||||
options __NO_FIQ
|
||||
|
||||
makeoptions KERNEL_BASE_PHYS="0x80000000"
|
||||
options FDT # Flattened Device Tree support
|
||||
options DRAM_BLOCKS=256
|
||||
options MODULAR
|
||||
options MODULAR_DEFAULT_AUTOLOAD
|
||||
options __HAVE_CPU_COUNTER
|
||||
options __HAVE_FAST_SOFTINTS # should be in types.h
|
||||
options ARM_HAS_VBAR
|
||||
#options __HAVE_MM_MD_DIRECT_MAPPED_PHYS
|
||||
#options PMAP_NEED_ALLOC_POOLPAGE
|
||||
options TPIDRPRW_IS_CURCPU
|
||||
options KERNEL_BASE_EXT=0x80000000
|
||||
options FPU_VFP
|
||||
options PCI_NETBSD_CONFIGURE
|
||||
options __HAVE_PCI_CONF_HOOK
|
||||
options __BUS_SPACE_HAS_STREAM_METHODS
|
||||
|
||||
makeoptions KERNEL_BASE_PHYS="0x40000000"
|
||||
makeoptions KERNEL_BASE_VIRT="0x80000000"
|
||||
makeoptions BOARDTYPE="exynos"
|
||||
makeoptions BOARDMKFRAG="${THISARM}/conf/mk.exynos"
|
||||
|
||||
options ARM_INTR_IMPL="<arch/arm/samsung/exynos_intr.h>"
|
||||
options ARM_INTR_IMPL="<arch/arm/fdt/fdt_intr.h>"
|
||||
options ARM_GENERIC_TODR
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# $NetBSD: std.sunxi,v 1.3.4.2 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
|
||||
machine evbarm arm
|
||||
include "arch/evbarm/conf/std.evbarm"
|
||||
|
||||
include "arch/evbarm/conf/files.sunxi"
|
||||
|
||||
options FDT # Flattened Device Tree support
|
||||
options DRAM_BLOCKS=256
|
||||
options MODULAR
|
||||
options MODULAR_DEFAULT_AUTOLOAD
|
||||
options __HAVE_CPU_COUNTER
|
||||
options __HAVE_FAST_SOFTINTS # should be in types.h
|
||||
options __HAVE_CPU_UAREA_ALLOC_IDLELWP
|
||||
options ARM_HAS_VBAR
|
||||
#options __HAVE_MM_MD_DIRECT_MAPPED_PHYS
|
||||
#options PMAP_NEED_ALLOC_POOLPAGE
|
||||
options TPIDRPRW_IS_CURCPU
|
||||
options KERNEL_BASE_EXT=0x80000000
|
||||
options FPU_VFP
|
||||
options __BUS_SPACE_HAS_STREAM_METHODS
|
||||
|
||||
makeoptions KERNEL_BASE_PHYS="0x40008000"
|
||||
makeoptions KERNEL_BASE_VIRT="0x80008000"
|
||||
makeoptions BOARDTYPE="sunxi"
|
||||
makeoptions BOARDMKFRAG="${THISARM}/conf/mk.sunxi"
|
||||
makeoptions CPUFLAGS="-march=armv7-a -mfpu=neon"
|
||||
|
||||
options ARM_INTR_IMPL="<arch/arm/fdt/fdt_intr.h>"
|
||||
options ARM_GENERIC_TODR
|
||||
|
||||
# initrd support
|
||||
options MEMORY_DISK_HOOKS
|
||||
options MEMORY_DISK_DYNAMIC
|
||||
pseudo-device md
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: std.tegra,v 1.13.2.1 2017/07/05 19:57:46 snj Exp $
|
||||
# $NetBSD: std.tegra,v 1.13.2.2 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
|
||||
machine evbarm arm
|
||||
|
@ -7,6 +7,7 @@ include "arch/evbarm/conf/std.evbarm"
|
|||
include "arch/evbarm/conf/files.tegra"
|
||||
|
||||
options FDT # Flattened Device Tree support
|
||||
options DRAM_BLOCKS=256
|
||||
options MODULAR
|
||||
options MODULAR_DEFAULT_AUTOLOAD
|
||||
options __HAVE_CPU_COUNTER
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: std.vexpress,v 1.4 2017/06/02 15:22:47 jmcneill Exp $
|
||||
# $NetBSD: std.vexpress,v 1.4.2.1 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# standard NetBSD/evbarm for VEXPRESS options
|
||||
|
||||
|
@ -9,6 +9,7 @@ include "arch/evbarm/conf/std.evbarm"
|
|||
include "arch/evbarm/conf/files.vexpress"
|
||||
|
||||
options FDT # Flattened Device Tree support
|
||||
options DRAM_BLOCKS=256
|
||||
options MODULAR
|
||||
options MODULAR_DEFAULT_AUTOLOAD
|
||||
options ARM_HAS_VBAR
|
||||
|
|
|
@ -1,567 +0,0 @@
|
|||
/* $NetBSD: exynos_machdep.c,v 1.7 2015/12/21 04:58:50 marty Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Reinoud Zandijk.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this 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 <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: exynos_machdep.c,v 1.7 2015/12/21 04:58:50 marty Exp $");
|
||||
|
||||
#include "opt_evbarm_boardtype.h"
|
||||
#include "opt_exynos.h"
|
||||
#include "opt_machdep.h"
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_kgdb.h"
|
||||
#include "opt_ipkdb.h"
|
||||
#include "opt_md.h"
|
||||
#include "opt_sscom.h"
|
||||
#include "opt_arm_debug.h"
|
||||
|
||||
#include "ukbd.h"
|
||||
#include "arml2cc.h" // RPZ why is it not called opt_l2cc.h?
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/ksyms.h>
|
||||
#include <sys/msgbuf.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/gpio.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <sys/conf.h>
|
||||
#include <dev/cons.h>
|
||||
#include <dev/md.h>
|
||||
|
||||
#include <machine/db_machdep.h>
|
||||
#include <ddb/db_sym.h>
|
||||
#include <ddb/db_extern.h>
|
||||
#ifdef KGDB
|
||||
#include <sys/kgdb.h>
|
||||
#endif
|
||||
|
||||
#include <machine/bootconfig.h>
|
||||
#include <arm/armreg.h>
|
||||
#include <arm/undefined.h>
|
||||
#include <arm/cortex/pl310_var.h>
|
||||
|
||||
#include <arm/arm32/machdep.h>
|
||||
#include <arm/mainbus/mainbus.h>
|
||||
|
||||
#include <arm/samsung/exynos5_reg.h>
|
||||
#include <arm/samsung/exynos_var.h>
|
||||
|
||||
#include <evbarm/include/autoconf.h>
|
||||
#include <evbarm/exynos/platform.h>
|
||||
|
||||
#include <dev/i2c/i2cvar.h>
|
||||
#include <dev/i2c/ddcreg.h>
|
||||
|
||||
#include <dev/usb/ukbdvar.h>
|
||||
#include <net/if_ether.h>
|
||||
|
||||
/* serial console stuff */
|
||||
#include "sscom.h"
|
||||
#include "opt_sscom.h"
|
||||
|
||||
#include <arm/samsung/sscom_var.h>
|
||||
#include <arm/samsung/sscom_reg.h>
|
||||
|
||||
/* so we can load the device tree. NOTE: This requires the kernel to be
|
||||
* made into a linux (not netbsd) uboot image.
|
||||
*/
|
||||
#include <libfdt.h>
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
#define FDT_BUF_SIZE (128*1024)
|
||||
static uint8_t fdt_data[FDT_BUF_SIZE];
|
||||
|
||||
extern const int num_exynos_uarts_entries;
|
||||
extern const struct sscom_uart_info exynos_uarts[];
|
||||
|
||||
#ifndef CONSPEED
|
||||
#define CONSPEED 115200
|
||||
#endif /* CONSPEED */
|
||||
#ifndef CONMODE
|
||||
#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB | HUPCL)) | CS8) /* 8N1 */
|
||||
#endif /* CONMODE */
|
||||
|
||||
static const int conspeed = CONSPEED;
|
||||
static const int conmode = CONMODE;
|
||||
|
||||
/*
|
||||
* uboot passes 4 arguments to us.
|
||||
*
|
||||
* arg0 arg1 arg2 arg3 : the `bootargs' environment variable from the uboot
|
||||
* context (in PA!)
|
||||
*
|
||||
* Note that the storage has to be in .data and not in .bss. On kernel start
|
||||
* the .bss is cleared and this information would get lost.
|
||||
*/
|
||||
uintptr_t uboot_args[4] = { 0 };
|
||||
|
||||
/*
|
||||
* argument and boot configure storage
|
||||
*/
|
||||
BootConfig bootconfig; /* for pmap's sake */
|
||||
char bootargs[MAX_BOOT_STRING] = ""; /* copied string from uboot */
|
||||
char *boot_args = NULL; /* MI bootargs */
|
||||
char *boot_file = NULL; /* MI bootfile */
|
||||
uint8_t uboot_enaddr[ETHER_ADDR_LEN] = {};
|
||||
|
||||
|
||||
void
|
||||
odroid_device_register(device_t self, void *aux);
|
||||
|
||||
/*
|
||||
* kernel start and end from the linker
|
||||
*/
|
||||
extern char KERNEL_BASE_phys[]; /* physical start of kernel */
|
||||
extern char _end[]; /* physical end of kernel */
|
||||
#define KERNEL_BASE_PHYS ((paddr_t)KERNEL_BASE_phys)
|
||||
|
||||
#define EXYNOS_IOPHYSTOVIRT(a) \
|
||||
((vaddr_t)(((a) - EXYNOS_CORE_PBASE) + EXYNOS_CORE_VBASE))
|
||||
|
||||
static void exynos_reset(void);
|
||||
static void exynos_powerdown(void);
|
||||
/* XXX we have no framebuffer implementation yet so com is console XXX */
|
||||
int use_fb_console = false;
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void consinit(void);
|
||||
#ifdef KGDB
|
||||
static void kgdb_port_init(void);
|
||||
#endif
|
||||
static void exynos_extract_mac_adress(void);
|
||||
void exynos_device_register(device_t self, void *aux);
|
||||
void exynos_device_register_post_config(device_t self, void *aux);
|
||||
|
||||
/*
|
||||
* Our static device mappings at fixed virtual addresses so we can use them
|
||||
* while booting the kernel.
|
||||
*
|
||||
* Map the extents segment-aligned and segment-rounded in size to avoid L2
|
||||
* page tables
|
||||
*/
|
||||
|
||||
#define _A(a) ((a) & ~L1_S_OFFSET)
|
||||
#define _S(s) (((s) + L1_S_SIZE - 1) & (~(L1_S_SIZE-1)))
|
||||
|
||||
static const struct pmap_devmap e5_devmap[] = {
|
||||
{
|
||||
/* map in core IO space */
|
||||
.pd_va = _A(EXYNOS_CORE_VBASE),
|
||||
.pd_pa = _A(EXYNOS_CORE_PBASE),
|
||||
.pd_size = _S(EXYNOS5_CORE_SIZE),
|
||||
.pd_prot = VM_PROT_READ | VM_PROT_WRITE,
|
||||
.pd_cache = PTE_NOCACHE
|
||||
},
|
||||
{
|
||||
/* map in audiocore IO space */
|
||||
.pd_va = _A(EXYNOS5_AUDIOCORE_VBASE),
|
||||
.pd_pa = _A(EXYNOS5_AUDIOCORE_PBASE),
|
||||
.pd_size = _S(EXYNOS5_AUDIOCORE_SIZE),
|
||||
.pd_prot = VM_PROT_READ | VM_PROT_WRITE,
|
||||
.pd_cache = PTE_NOCACHE
|
||||
},
|
||||
{0}
|
||||
};
|
||||
#undef _A
|
||||
#undef _S
|
||||
|
||||
#ifdef PMAP_NEED_ALLOC_POOLPAGE
|
||||
static struct boot_physmem bp_highgig = {
|
||||
.bp_pages = (KERNEL_VM_BASE - KERNEL_BASE) / NBPG,
|
||||
.bp_freelist = VM_FREELIST_ISADMA,
|
||||
.bp_flags = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct gpio_pin_entry {
|
||||
const char *pin_name;
|
||||
const char *pin_user;
|
||||
} gpio_pin_entries[] = {
|
||||
/* mux@13400000 (muxa) */
|
||||
{ "gpx3-7", "hdmi-hpd-irq"},
|
||||
{ "gpx3-6", "hdmi_cec" },
|
||||
{ "gpx0-7", "dp_hpd_gpio" },
|
||||
{ "gpx0-4", "pmic-irq" },
|
||||
{ "gpx3-2", "audio-irq" },
|
||||
{ "gpx3-4", "b-sess1-irq" },
|
||||
{ "gpx3-5", "b-sess0-irq" },
|
||||
{ "gpx1-1", "id2-irq" },
|
||||
/* mux@134100000 (muxb) */
|
||||
{ "gpc0-0", "sd0-clk" },
|
||||
{ "gpc0-1", "sd0-cmd" },
|
||||
{ "gpc0-7", "sd0-rdqs" },
|
||||
{ "gpd1-3", "sd0-qrdy" },
|
||||
{ "gpc0-3", "sd0-bus-width1" },
|
||||
{ "gpc0-3", "sd0-bus-width4-bit1" },
|
||||
{ "gpc0-4", "sd0-bus-width4-bit2" },
|
||||
{ "gpc0-5", "sd0-bus-width4-bit3" },
|
||||
{ "gpc0-6", "sd0-bus-width4-bit4" },
|
||||
{ "gpc1-0", "sd1-clk" },
|
||||
{ "gpc1-1", "sd1-cmd" },
|
||||
{ "gpc1-3", "sd1-bus-width1" },
|
||||
{ "gpc1-3", "sd1-bus-width4-bit1" },
|
||||
{ "gpc1-4", "sd1-bus-width4-bit2" },
|
||||
{ "gpc1-5", "sd1-bus-width4-bit3" },
|
||||
{ "gpc1-6", "sd1-bus-width4-bit4" },
|
||||
/* TODO: muxc and muxd as needed */
|
||||
{ 0, 0}
|
||||
};
|
||||
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
extern void exynos_putchar(int);
|
||||
|
||||
static void
|
||||
exynos_putstr(const char *s)
|
||||
{
|
||||
for (const char *p = s; *p; p++) {
|
||||
exynos_putchar(*p);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_printn(u_int n, int base)
|
||||
{
|
||||
char *p, buf[(sizeof(u_int) * NBBY / 3) + 1 + 2 /* ALT + SIGN */];
|
||||
|
||||
p = buf;
|
||||
do {
|
||||
*p++ = hexdigits[n % base];
|
||||
} while (n /= base);
|
||||
|
||||
do {
|
||||
exynos_putchar(*--p);
|
||||
} while (p > buf);
|
||||
}
|
||||
#define DPRINTF(...) printf(__VA_ARGS__)
|
||||
#define DPRINT(x) exynos_putstr(x)
|
||||
#define DPRINTN(x,b) exynos_printn((x), (b))
|
||||
#else
|
||||
#define DPRINTF(...)
|
||||
#define DPRINT(x)
|
||||
#define DPRINTN(x,b)
|
||||
#endif
|
||||
|
||||
extern void cortex_mpstart(void);
|
||||
|
||||
/*
|
||||
* void init_gpio_dictionary(...)
|
||||
*
|
||||
* Setup the dictionary of gpio pin names for the drivers to use
|
||||
*/
|
||||
static void init_gpio_dictionary(struct gpio_pin_entry *pins,
|
||||
prop_dictionary_t dict)
|
||||
{
|
||||
while (pins->pin_name) {
|
||||
prop_dictionary_set_cstring(dict, pins->pin_user,
|
||||
pins->pin_name);
|
||||
pins++;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* u_int initarm(...)
|
||||
*
|
||||
* Our entry point from the assembly before main() is called.
|
||||
* - take a copy of the config we got from uboot
|
||||
* - init the physical console
|
||||
* - setting up page tables for the kernel
|
||||
*/
|
||||
|
||||
u_int
|
||||
initarm(void *arg)
|
||||
{
|
||||
const struct pmap_devmap const *devmap;
|
||||
bus_addr_t rambase;
|
||||
psize_t ram_size;
|
||||
DPRINT("initarm:");
|
||||
|
||||
DPRINT(" mpstart<0x");
|
||||
DPRINTN((uint32_t)cortex_mpstart, 16);
|
||||
DPRINT(">");
|
||||
|
||||
/* allocate/map our basic memory mapping */
|
||||
switch (EXYNOS_PRODUCT_FAMILY(exynos_soc_id)) {
|
||||
#if defined(EXYNOS5)
|
||||
case EXYNOS5_PRODUCT_FAMILY:
|
||||
devmap = e5_devmap;
|
||||
rambase = EXYNOS5_SDRAM_PBASE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* Won't work, but... */
|
||||
panic("Unknown product family %llx",
|
||||
EXYNOS_PRODUCT_FAMILY(exynos_soc_id));
|
||||
}
|
||||
pmap_devmap_register(devmap);
|
||||
|
||||
/* bootstrap soc. uart_address is determined in exynos_start */
|
||||
paddr_t uart_address = armreg_tpidruro_read();
|
||||
exynos_bootstrap(EXYNOS_CORE_VBASE, EXYNOS_IOPHYSTOVIRT(uart_address));
|
||||
|
||||
/* set up CPU / MMU / TLB functions */
|
||||
if (set_cpufuncs())
|
||||
panic("cpu not recognized!");
|
||||
|
||||
/* get normal console working */
|
||||
consinit();
|
||||
|
||||
#ifdef KGDB
|
||||
kgdb_port_init();
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf("\nuboot arg = %#"PRIxPTR", %#"PRIxPTR", %#"PRIxPTR", %#"PRIxPTR"\n",
|
||||
uboot_args[0], uboot_args[1], uboot_args[2], uboot_args[3]);
|
||||
printf("Exynos SoC ID %08x\n", exynos_soc_id);
|
||||
|
||||
printf("initarm: cbar=%#x\n", armreg_cbar_read());
|
||||
#endif
|
||||
|
||||
/* determine cpu0 clock rate */
|
||||
exynos_clocks_bootstrap();
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf("CPU0 now running on %"PRIu64" Mhz\n", exynos_get_cpufreq()/(1000*1000));
|
||||
#endif
|
||||
|
||||
cpu_reset_address = exynos_reset;
|
||||
cpu_powerdown_address = exynos_powerdown;
|
||||
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf("\nNetBSD/evbarm (Exynnos 5422) booting ...\n");
|
||||
#endif
|
||||
|
||||
#ifdef BOOT_ARGS
|
||||
char mi_bootargs[] = BOOT_ARGS;
|
||||
parse_mi_bootargs(mi_bootargs);
|
||||
#endif
|
||||
|
||||
boot_args = bootargs;
|
||||
parse_mi_bootargs(boot_args);
|
||||
exynos_extract_mac_adress();
|
||||
|
||||
/* Don't map the DMA reserved region */
|
||||
// ram_size = (psize_t) 0xC0000000 - 0x40000000;
|
||||
ram_size = (psize_t) 0xb0000000 - 0x40000000;
|
||||
|
||||
#ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
|
||||
const bool mapallmem_p = true;
|
||||
#ifndef PMAP_NEED_ALLOC_POOLPAGE
|
||||
if (ram_size > KERNEL_VM_BASE - KERNEL_BASE) {
|
||||
printf("%s: dropping RAM size from %luMB to %uMB\n",
|
||||
__func__, (unsigned long) (ram_size >> 20),
|
||||
(KERNEL_VM_BASE - KERNEL_BASE) >> 20);
|
||||
ram_size = KERNEL_VM_BASE - KERNEL_BASE;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
const bool mapallmem_p = false;
|
||||
#endif
|
||||
|
||||
/* Load the dtb */
|
||||
const uint8_t *fdt_addr_r = (const uint8_t *)uboot_args[2];
|
||||
printf("fdt addr 0x%08x\n", (uint)fdt_addr_r);
|
||||
int error = fdt_check_header(fdt_addr_r);
|
||||
printf("fdt check header returns %d\n", error);
|
||||
if (error == 0) {
|
||||
error = fdt_move(fdt_addr_r, fdt_data, sizeof(fdt_data));
|
||||
printf("fdt move returns %d\n", error);
|
||||
if (error != 0) {
|
||||
panic("fdt_move failed: %s", fdt_strerror(error));
|
||||
}
|
||||
fdtbus_set_data(fdt_data);
|
||||
} else {
|
||||
panic("fdt_check_header failed: %s", fdt_strerror(error));
|
||||
}
|
||||
|
||||
/* Fake bootconfig structure for the benefit of pmap.c. */
|
||||
bootconfig.dramblocks = 1;
|
||||
bootconfig.dram[0].address = rambase;
|
||||
bootconfig.dram[0].pages = ram_size / PAGE_SIZE;
|
||||
KASSERT((armreg_pfr1_read() & ARM_PFR1_SEC_MASK) != 0);
|
||||
|
||||
arm32_bootmem_init(bootconfig.dram[0].address, ram_size,
|
||||
KERNEL_BASE_PHYS);
|
||||
arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0, devmap,
|
||||
mapallmem_p);
|
||||
|
||||
/* we've a specific device_register routine */
|
||||
evbarm_device_register = odroid_device_register;
|
||||
// evbarm_device_register_post_config = exynos_device_register_post_config;
|
||||
/*
|
||||
* If we couldn't map all of memory via TTBR1, limit the memory the
|
||||
* kernel can allocate from to be from the highest available 1GB.
|
||||
*/
|
||||
#ifdef PMAP_NEED_ALLOC_POOLPAGE
|
||||
if (atop(ram_size) > bp_highgig.bp_pages) {
|
||||
arm_poolpage_vmfreelist = bp_highgig.bp_freelist;
|
||||
return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE,
|
||||
&bp_highgig, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
consinit(void)
|
||||
{
|
||||
static bool consinit_called;
|
||||
|
||||
if (consinit_called)
|
||||
return;
|
||||
consinit_called = true;
|
||||
|
||||
#if NSSCOM > 0
|
||||
bus_space_tag_t bst = &armv7_generic_bs_tag;
|
||||
bus_addr_t iobase = armreg_tpidruro_read();
|
||||
bus_space_handle_t bsh = EXYNOS_IOPHYSTOVIRT(iobase);
|
||||
u_int i;
|
||||
/*
|
||||
* No need to guess at the UART frequency since we can calculate it.
|
||||
*/
|
||||
uint32_t freq = conspeed
|
||||
* (16 * (bus_space_read_4(bst, bsh, SSCOM_UBRDIV) + 1)
|
||||
+ bus_space_read_4(bst, bsh, SSCOM_UFRACVAL));
|
||||
freq = (freq + conspeed / 2) / 1000;
|
||||
freq *= 1000;
|
||||
|
||||
/* go through all entries */
|
||||
for (i = 0; i < num_exynos_uarts_entries; i++) {
|
||||
/* attach console */
|
||||
if (exynos_uarts[i].iobase + EXYNOS_CORE_PBASE == iobase)
|
||||
break;
|
||||
}
|
||||
KASSERT(i < num_exynos_uarts_entries);
|
||||
printf("%s: attaching console @ %#"PRIxPTR" (%u HZ, %u bps)\n",
|
||||
__func__, iobase, freq, conspeed);
|
||||
if (sscom_cnattach(bst, exynos_core_bsh, &exynos_uarts[i],
|
||||
conspeed, freq, conmode))
|
||||
panic("Serial console can not be initialized");
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf("Console initialized\n");
|
||||
#endif
|
||||
#else
|
||||
#error only serial console is supported
|
||||
#if NUKBD > 0
|
||||
/* allow USB keyboards to become console */
|
||||
ukbd_cnattach();
|
||||
#endif /* NUKBD */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* extract ethernet mac address from bootargs */
|
||||
static void
|
||||
exynos_extract_mac_adress(void)
|
||||
{
|
||||
char *str, *ptr;
|
||||
int i, v1, v2, val;
|
||||
|
||||
#define EXPECT_COLON() {\
|
||||
v1 = *ptr++; \
|
||||
if (v1 != ':') break; \
|
||||
}
|
||||
#define EXPECT_HEX(v) {\
|
||||
(v) = (v) >= '0' && (v) <= '9'? (v) - '0' : \
|
||||
(v) >= 'a' && (v) <= 'f'? (v) - 'a' + 10 : \
|
||||
(v) >= 'A' && (v) <= 'F'? (v) - 'A' + 10 : -1; \
|
||||
if ((v) < 0) break; \
|
||||
}
|
||||
#define EXPECT_2HEX(val) {\
|
||||
v1 = *ptr++; EXPECT_HEX(v1); \
|
||||
v2 = *ptr++; EXPECT_HEX(v2); \
|
||||
val = (v1 << 4) | v2; \
|
||||
}
|
||||
if (get_bootconf_option(boot_args, "ethaddr",
|
||||
BOOTOPT_TYPE_STRING, &str)) {
|
||||
for (i = 0, ptr = str; i < sizeof(uboot_enaddr); i++) {
|
||||
if (i)
|
||||
EXPECT_COLON();
|
||||
EXPECT_2HEX(val);
|
||||
uboot_enaddr[i] = val;
|
||||
}
|
||||
if (i != sizeof(uboot_enaddr)) {
|
||||
printf( "Ignoring invalid MAC address '%s' passed "
|
||||
"as boot paramter `ethaddr'\n", str);
|
||||
memset((char *) uboot_enaddr, 0, sizeof(uboot_enaddr));
|
||||
}
|
||||
}
|
||||
#undef EXPECT_2HEX
|
||||
#undef EXPECT_HEX
|
||||
#undef EXPECT_COLON
|
||||
}
|
||||
|
||||
void
|
||||
odroid_device_register(device_t self, void *aux)
|
||||
{
|
||||
prop_dictionary_t dict = device_properties(self);
|
||||
exynos_device_register(self, aux);
|
||||
if (device_is_a(self, "exyogpio")) {
|
||||
init_gpio_dictionary(gpio_pin_entries, dict);
|
||||
} else if (device_is_a(self, "exyowdt")) {
|
||||
prop_dictionary_set_uint32(dict, "frequency",
|
||||
EXYNOS_F_IN_FREQ);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Exynos specific tweaks
|
||||
*/
|
||||
/*
|
||||
* The external USB devices are clocked trough the DEBUG clkout
|
||||
* XXX is this Odroid specific? XXX
|
||||
*/
|
||||
void
|
||||
exynos_init_clkout_for_usb(void)
|
||||
{
|
||||
/* Select XUSBXTI as source for CLKOUT */
|
||||
bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh,
|
||||
EXYNOS_PMU_DEBUG_CLKOUT, 0x1000);
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_powerdown(void)
|
||||
{
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exynos_start.S,v 1.3 2015/12/17 08:03:06 skrll Exp $ */
|
||||
/* $NetBSD: exynos_start.S,v 1.3.12.1 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
|
@ -45,7 +45,7 @@
|
|||
|
||||
#include <evbarm/exynos/platform.h>
|
||||
|
||||
RCSID("$NetBSD: exynos_start.S,v 1.3 2015/12/17 08:03:06 skrll Exp $")
|
||||
RCSID("$NetBSD: exynos_start.S,v 1.3.12.1 2017/07/18 19:13:09 snj Exp $")
|
||||
|
||||
|
||||
#if defined(VERBOSE_INIT_ARM)
|
||||
|
@ -68,7 +68,7 @@ RCSID("$NetBSD: exynos_start.S,v 1.3 2015/12/17 08:03:06 skrll Exp $")
|
|||
|
||||
#define TEMP_L1_TABLE (KERNEL_BASE - KERNEL_BASE_VOFFSET + INIT_MEMSIZE * L1_S_SIZE - L1_TABLE_SIZE)
|
||||
|
||||
#define MD_CPU_HATCH _C_LABEL(gtmr_init_cpu_clock)
|
||||
#define MD_CPU_HATCH _C_LABEL(arm_fdt_cpu_hatch)
|
||||
|
||||
/*
|
||||
* Kernel start routine for Exynos 5422 boards running on uboot firmware
|
||||
|
@ -100,6 +100,18 @@ _C_LABEL(exynos_start):
|
|||
#endif
|
||||
stmia r4, {r0-r3} // Save the arguments
|
||||
|
||||
/* Add DTB PA (1MB) from r2 to MMU init table */
|
||||
movw r3, #:lower16:(L1_S_SIZE - 1) /* align DTB PA to 1M */
|
||||
movt r3, #:upper16:(L1_S_SIZE - 1)
|
||||
bic r0, r2, r3
|
||||
orr r0, r0, #1 /* 1MB mapping */
|
||||
bic r1, r2, r3
|
||||
movw r3, #:lower16:(L1_S_PROTO_armv7|L1_S_APv7_KRW|L1_S_CACHEABLE)
|
||||
movt r3, #:upper16:(L1_S_PROTO_armv7|L1_S_APv7_KRW|L1_S_CACHEABLE)
|
||||
orr r1, r1, r3
|
||||
adrl r3, .Lmmu_init_table_dtb /* table entry addr */
|
||||
stmia r3, {r0-r1} /* patch table entry */
|
||||
|
||||
/*
|
||||
* For easy and early SoC / PoP dependency, retrieve the IDs
|
||||
*/
|
||||
|
@ -268,6 +280,11 @@ mmu_init_table:
|
|||
EXYNOS_CORE_SIZE / L1_S_SIZE,
|
||||
L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_V6_XN)
|
||||
|
||||
/* Map DTB location in SDRAM, patched in later */
|
||||
.Lmmu_init_table_dtb:
|
||||
MMU_INIT(0, 0, 0, 0)
|
||||
|
||||
|
||||
/* end of table */
|
||||
MMU_INIT(0, 0, 0, 0)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: platform.h,v 1.1 2015/12/06 00:33:44 marty Exp $ */
|
||||
/* $NetBSD: platform.h,v 1.1.12.1 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
|
@ -32,11 +32,7 @@
|
|||
#ifndef _ARM_EXYNOS_PLATFORM_H
|
||||
#define _ARM_EXYNOS_PLATFORM_H
|
||||
|
||||
/*
|
||||
* Kernel VM space 16Mb behind KERNEL_BASE upto 0xeff00000
|
||||
*/
|
||||
#define KERNEL_VM_BASE 0xc0000000
|
||||
#define KERNEL_VM_SIZE (EXYNOS_CORE_VBASE - KERNEL_VM_BASE)
|
||||
#include <arch/evbarm/fdt/platform.h>
|
||||
|
||||
/*
|
||||
* IO space
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fdt_machdep.c,v 1.4.2.2 2017/06/14 04:54:21 snj Exp $ */
|
||||
/* $NetBSD: fdt_machdep.c,v 1.4.2.3 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.4.2.2 2017/06/14 04:54:21 snj Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.4.2.3 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include "opt_machdep.h"
|
||||
#include "opt_ddb.h"
|
||||
|
@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.4.2.2 2017/06/14 04:54:21 snj Exp
|
|||
#include <sys/proc.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/extent.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
|
@ -70,6 +71,10 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.4.2.2 2017/06/14 04:54:21 snj Exp
|
|||
|
||||
#include <arm/fdt/arm_fdtvar.h>
|
||||
|
||||
#ifdef MEMORY_DISK_DYNAMIC
|
||||
#include <dev/md.h>
|
||||
#endif
|
||||
|
||||
#ifndef FDT_MAX_BOOT_STRING
|
||||
#define FDT_MAX_BOOT_STRING 1024
|
||||
#endif
|
||||
|
@ -79,6 +84,11 @@ char bootargs[FDT_MAX_BOOT_STRING] = "";
|
|||
char *boot_args = NULL;
|
||||
u_int uboot_args[4] = { 0 }; /* filled in by xxx_start.S (not in bss) */
|
||||
|
||||
static char fdt_memory_ext_storage[EXTENT_FIXED_STORAGE_SIZE(DRAM_BLOCKS)];
|
||||
static struct extent *fdt_memory_ext;
|
||||
|
||||
static uint64_t initrd_start, initrd_end;
|
||||
|
||||
#include <libfdt.h>
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
#define FDT_BUF_SIZE (128*1024)
|
||||
|
@ -167,6 +177,155 @@ fdt_get_memory(uint64_t *paddr, uint64_t *psize)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fdt_add_reserved_memory_range(uint64_t addr, uint64_t size)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = extent_free(fdt_memory_ext, addr, size, EX_NOWAIT);
|
||||
if (error != 0)
|
||||
printf("MEM ERROR: add %llx-%llx failed: %d\n",
|
||||
addr, size, error);
|
||||
DPRINTF("MEM: res %llx-%llx: %d\n", addr, size, error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exclude memory ranges from memory config from a /reserved-memory/ child
|
||||
*/
|
||||
static void
|
||||
fdt_add_reserved_memory(int phandle, uint64_t max_addr)
|
||||
{
|
||||
uint64_t addr, size;
|
||||
int index;
|
||||
|
||||
for (index = 0;
|
||||
fdtbus_get_reg64(phandle, index, &addr, &size) == 0;
|
||||
index++) {
|
||||
if (addr >= max_addr)
|
||||
continue;
|
||||
if (addr + size > max_addr)
|
||||
size = max_addr - addr;
|
||||
fdt_add_reserved_memory_range(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Define usable memory regions.
|
||||
*/
|
||||
static void
|
||||
fdt_build_bootconfig(uint64_t mem_addr, uint64_t mem_size)
|
||||
{
|
||||
const int memory = OF_finddevice("/memory");
|
||||
const uint64_t max_addr = mem_addr + mem_size;
|
||||
BootConfig *bc = &bootconfig;
|
||||
struct extent_region *er;
|
||||
uint64_t addr, size;
|
||||
int index, child, error;
|
||||
|
||||
fdt_memory_ext = extent_create("FDT Memory", mem_addr, max_addr,
|
||||
fdt_memory_ext_storage, sizeof(fdt_memory_ext_storage), 0);
|
||||
|
||||
for (index = 0;
|
||||
fdtbus_get_reg64(memory, index, &addr, &size) == 0;
|
||||
index++) {
|
||||
if (addr >= max_addr)
|
||||
continue;
|
||||
if (addr + size > max_addr)
|
||||
size = max_addr - addr;
|
||||
|
||||
error = extent_alloc_region(fdt_memory_ext, addr, size,
|
||||
EX_NOWAIT);
|
||||
if (error != 0)
|
||||
printf("MEM ERROR: add %llx-%llx failed: %d\n",
|
||||
addr, size, error);
|
||||
DPRINTF("MEM: add %llx-%llx\n", addr, size);
|
||||
}
|
||||
|
||||
const int reserved = OF_finddevice("/reserved-memory");
|
||||
if (reserved > 0)
|
||||
for (child = OF_child(reserved); child; child = OF_peer(child))
|
||||
fdt_add_reserved_memory(child, max_addr);
|
||||
|
||||
const uint64_t initrd_size = initrd_end - initrd_start;
|
||||
if (initrd_size > 0)
|
||||
fdt_add_reserved_memory_range(initrd_start, initrd_size);
|
||||
|
||||
DPRINTF("Usable memory:\n");
|
||||
bc->dramblocks = 0;
|
||||
LIST_FOREACH(er, &fdt_memory_ext->ex_regions, er_link) {
|
||||
DPRINTF(" %lx - %lx\n", er->er_start, er->er_end);
|
||||
bc->dram[bc->dramblocks].address = er->er_start;
|
||||
bc->dram[bc->dramblocks].pages =
|
||||
(er->er_end - er->er_start) / PAGE_SIZE;
|
||||
bc->dramblocks++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fdt_probe_initrd(uint64_t *pstart, uint64_t *pend)
|
||||
{
|
||||
*pstart = *pend = 0;
|
||||
|
||||
#ifdef MEMORY_DISK_DYNAMIC
|
||||
const int chosen = OF_finddevice("/chosen");
|
||||
if (chosen < 0)
|
||||
return;
|
||||
|
||||
int len;
|
||||
const void *start_data = fdtbus_get_prop(chosen,
|
||||
"linux,initrd-start", &len);
|
||||
const void *end_data = fdtbus_get_prop(chosen,
|
||||
"linux,initrd-end", NULL);
|
||||
if (start_data == NULL || end_data == NULL)
|
||||
return;
|
||||
|
||||
switch (len) {
|
||||
case 4:
|
||||
*pstart = be32dec(start_data);
|
||||
*pend = be32dec(end_data);
|
||||
break;
|
||||
case 8:
|
||||
*pstart = be64dec(start_data);
|
||||
*pend = be64dec(end_data);
|
||||
break;
|
||||
default:
|
||||
printf("Unsupported len %d for /chosen/initrd-start\n", len);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
fdt_setup_initrd(void)
|
||||
{
|
||||
#ifdef MEMORY_DISK_DYNAMIC
|
||||
const uint64_t initrd_size = initrd_end - initrd_start;
|
||||
paddr_t startpa = trunc_page(initrd_start);
|
||||
paddr_t endpa = round_page(initrd_end);
|
||||
paddr_t pa;
|
||||
vaddr_t va;
|
||||
void *md_start;
|
||||
|
||||
if (initrd_size == 0)
|
||||
return;
|
||||
|
||||
va = uvm_km_alloc(kernel_map, initrd_size, 0,
|
||||
UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
|
||||
if (va == 0) {
|
||||
printf("Failed to allocate VA for initrd\n");
|
||||
return;
|
||||
}
|
||||
|
||||
md_start = (void *)va;
|
||||
|
||||
for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE)
|
||||
pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE, 0);
|
||||
pmap_update(pmap_kernel());
|
||||
|
||||
md_root_setconf(md_start, initrd_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
u_int
|
||||
initarm(void *arg)
|
||||
{
|
||||
|
@ -251,8 +410,8 @@ initarm(void *arg)
|
|||
|
||||
#if !defined(_LP64)
|
||||
/* Cannot map memory above 4GB */
|
||||
if (memory_addr + memory_size > 0x100000000)
|
||||
memory_size = 0x100000000 - memory_addr;
|
||||
if (memory_addr + memory_size >= 0x100000000)
|
||||
memory_size = 0x100000000 - memory_addr - PAGE_SIZE;
|
||||
#endif
|
||||
|
||||
ram_size = (bus_size_t)memory_size;
|
||||
|
@ -271,10 +430,11 @@ initarm(void *arg)
|
|||
const bool mapallmem_p = false;
|
||||
#endif
|
||||
|
||||
/* Fake bootconfig structure for the benefit of pmap.c. */
|
||||
bootconfig.dramblocks = 1;
|
||||
bootconfig.dram[0].address = (bus_addr_t)memory_addr;
|
||||
bootconfig.dram[0].pages = ram_size / PAGE_SIZE;
|
||||
/* Parse ramdisk info */
|
||||
fdt_probe_initrd(&initrd_start, &initrd_end);
|
||||
|
||||
/* Populate bootconfig structure for the benefit of pmap.c. */
|
||||
fdt_build_bootconfig(memory_addr, memory_size);
|
||||
|
||||
arm32_bootmem_init(bootconfig.dram[0].address, ram_size,
|
||||
KERNEL_BASE_PHYS);
|
||||
|
@ -295,7 +455,6 @@ initarm(void *arg)
|
|||
#endif
|
||||
|
||||
return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -360,6 +519,9 @@ fdt_device_register(device_t self, void *aux)
|
|||
{
|
||||
const struct arm_platform *plat = arm_fdt_platform();
|
||||
|
||||
if (device_is_a(self, "armfdt"))
|
||||
fdt_setup_initrd();
|
||||
|
||||
if (plat && plat->device_register)
|
||||
plat->device_register(self, aux);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bootconfig.h,v 1.6 2006/02/06 14:03:22 hamajima Exp $ */
|
||||
/* $NetBSD: bootconfig.h,v 1.6.152.1 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Mark Brinicombe.
|
||||
|
@ -36,6 +36,8 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_machdep.h"
|
||||
|
||||
#include <arm/bootconfig.h>
|
||||
|
||||
typedef struct _PhysMem {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# $NetBSD: genassym.cf,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $
|
||||
|
||||
#-
|
||||
# Copyright (c) 2013 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to The NetBSD Foundation
|
||||
# by Matt Thomas of 3am Software Foundry.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this 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 <dev/ic/ns16550reg.h>
|
||||
include <dev/ic/comreg.h>
|
||||
|
||||
define LSR_TXRDY LSR_TXRDY
|
||||
define LSR_TSRE LSR_TSRE
|
||||
define COM_DATA com_data
|
||||
define COM_LSR com_lsr
|
|
@ -0,0 +1,192 @@
|
|||
/* $NetBSD: sunxi_start.S,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014, 2015 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Matt Thomas of 3am Software Foundry.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this 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 "opt_soc.h"
|
||||
#include "opt_cpuoptions.h"
|
||||
#include "opt_cputypes.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
#include "opt_arm_debug.h"
|
||||
#include "opt_fdt_arm.h"
|
||||
|
||||
#include <arm/asm.h>
|
||||
#include <arm/armreg.h>
|
||||
#include "assym.h"
|
||||
|
||||
#include <arch/arm/sunxi/sunxi_platform.h>
|
||||
|
||||
RCSID("$NetBSD: sunxi_start.S,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $")
|
||||
|
||||
#if defined(VERBOSE_INIT_ARM) && defined(CONSADDR)
|
||||
#define XPUTC(n) mov r0, n; bl xputc
|
||||
#if KERNEL_BASE_VOFFSET == 0
|
||||
#define XPUTC2(n) mov r0, n; bl xputc
|
||||
#else
|
||||
#define XPUTC2(n) mov r0, n; blx r11
|
||||
#endif
|
||||
#ifdef __ARMEB__
|
||||
#define COM_BSWAP
|
||||
#endif
|
||||
#define COM_MULT 4
|
||||
#define XPUTC_COM 1
|
||||
#else
|
||||
#define XPUTC(n)
|
||||
#define XPUTC2(n)
|
||||
#endif
|
||||
|
||||
#define INIT_MEMSIZE 64
|
||||
#define TEMP_L1_TABLE (KERNEL_BASE - KERNEL_BASE_VOFFSET + INIT_MEMSIZE * L1_S_SIZE - L1_TABLE_SIZE)
|
||||
|
||||
#define MD_CPU_HATCH _C_LABEL(arm_fdt_cpu_hatch)
|
||||
|
||||
/*
|
||||
* Kernel start routine for Allwinner sunxi SoCs
|
||||
* At this point, this code has been loaded into SDRAM
|
||||
* and the MMU maybe on or maybe off.
|
||||
*/
|
||||
#ifdef KERNEL_BASES_EQUAL
|
||||
.text
|
||||
#else
|
||||
.section .start,"ax",%progbits
|
||||
#endif
|
||||
|
||||
.global _C_LABEL(sunxi_start)
|
||||
_C_LABEL(sunxi_start):
|
||||
#ifdef __ARMEB__
|
||||
setend be /* force big endian */
|
||||
#endif
|
||||
mov r9, #0
|
||||
|
||||
/* Move into supervisor mode and disable IRQs/FIQs. */
|
||||
cpsid if, #PSR_SVC32_MODE
|
||||
|
||||
/*
|
||||
* Save any arguments passed to us.
|
||||
*/
|
||||
movw r4, #:lower16:uboot_args
|
||||
movt r4, #:upper16:uboot_args
|
||||
sub r4, r4, #KERNEL_BASE_VOFFSET
|
||||
|
||||
stmia r4, {r0-r3} // Save the arguments
|
||||
|
||||
/* Add DTB PA (1MB) from r2 to MMU init table */
|
||||
movw r3, #:lower16:(L1_S_SIZE - 1) /* align DTB PA to 1M */
|
||||
movt r3, #:upper16:(L1_S_SIZE - 1)
|
||||
bic r0, r2, r3
|
||||
orr r0, r0, #1 /* 1MB mapping */
|
||||
bic r1, r2, r3
|
||||
movw r3, #:lower16:(L1_S_PROTO_armv7|L1_S_APv7_KRW|L1_S_CACHEABLE)
|
||||
movt r3, #:upper16:(L1_S_PROTO_armv7|L1_S_APv7_KRW|L1_S_CACHEABLE)
|
||||
orr r1, r1, r3
|
||||
adr r3, .Lmmu_init_table_dtb /* table entry addr */
|
||||
stmia r3, {r0-r1} /* patch table entry */
|
||||
|
||||
/*
|
||||
* Turn on the SMP bit
|
||||
*/
|
||||
bl cortex_init
|
||||
|
||||
/*
|
||||
* Set up a preliminary mapping in the MMU to allow us to run
|
||||
* at KERNEL_BASE with caches on.
|
||||
*/
|
||||
movw r0, #:lower16:TEMP_L1_TABLE
|
||||
movt r0, #:upper16:TEMP_L1_TABLE
|
||||
movw r1, #:lower16:.Lmmu_init_table
|
||||
movt r1, #:upper16:.Lmmu_init_table
|
||||
bl arm_boot_l1pt_init
|
||||
XPUTC(#'D')
|
||||
|
||||
/*
|
||||
* Turn on the MMU, Caches, etc. Return to new enabled address space.
|
||||
*/
|
||||
movw r0, #:lower16:TEMP_L1_TABLE
|
||||
movt r0, #:upper16:TEMP_L1_TABLE
|
||||
#if KERNEL_BASE_VOFFSET == 0
|
||||
bl arm_cpuinit
|
||||
#else
|
||||
/*
|
||||
* After the MMU is on, we can execute in the normal .text segment
|
||||
* so setup the lr to be in .text. Cache the address for xputc
|
||||
* before we go.
|
||||
*/
|
||||
#if defined(VERBOSE_INIT_ARM)
|
||||
adr r11, xputc @ for XPUTC2
|
||||
#endif
|
||||
movw lr, #:lower16:1f
|
||||
movt lr, #:upper16:1f
|
||||
b arm_cpuinit
|
||||
.pushsection .text,"ax",%progbits
|
||||
1:
|
||||
#endif
|
||||
XPUTC2(#'Z')
|
||||
|
||||
/*
|
||||
* Jump to start in locore.S, which in turn will call initarm and main.
|
||||
*/
|
||||
b start
|
||||
|
||||
/* NOTREACHED */
|
||||
|
||||
#ifndef KERNEL_BASES_EQUAL
|
||||
.popsection
|
||||
#endif
|
||||
|
||||
#include <arm/cortex/a9_mpsubr.S>
|
||||
|
||||
.Lmmu_init_table:
|
||||
MMU_INIT(KERNEL_BASE, KERNEL_BASE - KERNEL_BASE_VOFFSET, INIT_MEMSIZE,
|
||||
L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_CACHEABLE)
|
||||
|
||||
#if KERNEL_BASE_VOFFSET != 0
|
||||
/* Map KERNEL_BASE VA to SDRAM PA, write-back cacheable, shareable */
|
||||
MMU_INIT(KERNEL_BASE - KERNEL_BASE_VOFFSET,
|
||||
KERNEL_BASE - KERNEL_BASE_VOFFSET, INIT_MEMSIZE,
|
||||
L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_CACHEABLE)
|
||||
#endif
|
||||
|
||||
/* Map CORE */
|
||||
MMU_INIT(SUNXI_CORE_VBASE, SUNXI_CORE_PBASE,
|
||||
(SUNXI_CORE_SIZE + L1_S_SIZE - 1) / L1_S_SIZE,
|
||||
L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_V6_XN)
|
||||
|
||||
/* Map CORE */
|
||||
MMU_INIT(SUNXI_CORE_PBASE, SUNXI_CORE_PBASE,
|
||||
(SUNXI_CORE_SIZE + L1_S_SIZE - 1) / L1_S_SIZE,
|
||||
L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_V6_XN)
|
||||
|
||||
.Lmmu_init_table_dtb:
|
||||
/* Map DTB from bootloader (patched in later) */
|
||||
MMU_INIT(0, 0, 0, 0)
|
||||
|
||||
/* end of table */
|
||||
MMU_INIT(0, 0, 0, 0)
|
||||
|
||||
END(_C_LABEL(sunxi_start))
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile.kern.inc,v 1.256 2017/01/11 12:19:43 joerg Exp $
|
||||
# $NetBSD: Makefile.kern.inc,v 1.256.8.1 2017/07/18 19:13:09 snj Exp $
|
||||
#
|
||||
# This file contains common `MI' targets and definitions and it is included
|
||||
# at the bottom of each `MD' ${MACHINE}/conf/Makefile.${MACHINE}.
|
||||
|
@ -534,6 +534,26 @@ build_kernel: .USE
|
|||
@${KCOMPILE.s} -pg
|
||||
.endif # ___USE_SUFFIX_RULES___
|
||||
|
||||
# Begin DTS handling
|
||||
|
||||
DTSINC?=$S/external/gpl2/dts/dist/include
|
||||
DTSPATH?=$S/external/gpl2/dts/dist/arch/${MACHINE_CPU}/boot/dts
|
||||
DTSPADDING?=1024
|
||||
|
||||
.SUFFIXES: .dtb .dts
|
||||
.dts.dtb:
|
||||
${CPP} -P -xassembler-with-cpp -I ${DTSINC} -I ${DTSPATH} \
|
||||
-include ${.IMPSRC} /dev/null | \
|
||||
${TOOL_DTC} -i ${DTSINC} -i ${DTSPATH} -I dts -O dtb \
|
||||
-p ${DTSPADDING} -b 0 -o ${.TARGET}
|
||||
|
||||
.PATH.dts: ${DTSPATH}
|
||||
|
||||
DTB= ${DTS:.dts=.dtb}
|
||||
all: ${DTB}
|
||||
|
||||
# End DTS handling
|
||||
|
||||
##
|
||||
## the end
|
||||
##
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# $NetBSD: files,v 1.1173.2.2 2017/06/10 05:57:08 snj Exp $
|
||||
# $NetBSD: files,v 1.1173.2.3 2017/07/18 19:13:09 snj Exp $
|
||||
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
|
||||
|
||||
version 20150846
|
||||
version 20170615
|
||||
|
||||
#
|
||||
# device classes
|
||||
|
@ -1505,6 +1505,9 @@ file dev/pud/pud_dev.c pud
|
|||
# device-mapper driver for LVM
|
||||
include "dev/dm/files.dm"
|
||||
|
||||
# LED framework
|
||||
file dev/led.c leds
|
||||
|
||||
#
|
||||
# File systems
|
||||
#
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/* $NetBSD: ehci_fdt.c,v 1.2.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ehci_fdt.c,v 1.2.4.2 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usbdi.h>
|
||||
#include <dev/usb/usbdivar.h>
|
||||
#include <dev/usb/usb_mem.h>
|
||||
#include <dev/usb/ehcireg.h>
|
||||
#include <dev/usb/ehcivar.h>
|
||||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
static int ehci_fdt_match(device_t, cfdata_t, void *);
|
||||
static void ehci_fdt_attach(device_t, device_t, void *);
|
||||
|
||||
CFATTACH_DECL2_NEW(ehci_fdt, sizeof(struct ehci_softc),
|
||||
ehci_fdt_match, ehci_fdt_attach, NULL,
|
||||
ehci_activate, NULL, ehci_childdet);
|
||||
|
||||
static int
|
||||
ehci_fdt_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
const char * const compatible[] = {
|
||||
"generic-ehci",
|
||||
NULL
|
||||
};
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_fdt_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct ehci_softc * const sc = device_private(self);
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
struct fdtbus_reset *rst;
|
||||
struct fdtbus_phy *phy;
|
||||
struct clk *clk;
|
||||
char intrstr[128];
|
||||
bus_addr_t addr;
|
||||
bus_size_t size;
|
||||
int error;
|
||||
void *ih;
|
||||
u_int n;
|
||||
|
||||
if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable clocks */
|
||||
for (n = 0; (clk = fdtbus_clock_get_index(phandle, n)) != NULL; n++)
|
||||
if (clk_enable(clk) != 0) {
|
||||
aprint_error(": couldn't enable clock #%d\n", n);
|
||||
return;
|
||||
}
|
||||
/* De-assert resets */
|
||||
for (n = 0; (rst = fdtbus_reset_get_index(phandle, n)) != NULL; n++)
|
||||
if (fdtbus_reset_deassert(rst) != 0) {
|
||||
aprint_error(": couldn't de-assert reset #%d\n", n);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable optional phy */
|
||||
phy = fdtbus_phy_get(phandle, "usb");
|
||||
if (phy && fdtbus_phy_enable(phy, true) != 0) {
|
||||
aprint_error(": couldn't enable phy\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_bus.ub_hcpriv = sc;
|
||||
sc->sc_bus.ub_dmatag = faa->faa_dmat;
|
||||
sc->sc_bus.ub_revision = USBREV_2_0;
|
||||
if (of_hasprop(phandle, "has-transaction-translator"))
|
||||
sc->sc_flags |= EHCIF_ETTF;
|
||||
else
|
||||
sc->sc_ncomp = 1;
|
||||
sc->sc_id_vendor = 0;
|
||||
strlcpy(sc->sc_vendor, "Generic", sizeof(sc->sc_vendor));
|
||||
sc->sc_size = size;
|
||||
sc->iot = faa->faa_bst;
|
||||
if (bus_space_map(sc->iot, addr, size, 0, &sc->ioh) != 0) {
|
||||
aprint_error(": couldn't map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": EHCI\n");
|
||||
|
||||
/* Disable interrupts */
|
||||
sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
|
||||
EOWRITE4(sc, EHCI_USBINTR, 0);
|
||||
|
||||
if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
|
||||
aprint_error_dev(self, "failed to decode interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ih = fdtbus_intr_establish(phandle, 0, IPL_USB, FDT_INTR_MPSAFE,
|
||||
ehci_intr, sc);
|
||||
if (ih == NULL) {
|
||||
aprint_error_dev(self, "couldn't establish interrupt on %s\n",
|
||||
intrstr);
|
||||
return;
|
||||
}
|
||||
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
|
||||
|
||||
error = ehci_init(sc);
|
||||
if (error) {
|
||||
aprint_error_dev(self, "init failed, error = %d\n", error);
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/* $NetBSD: fdt_phy.c,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015-2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdt_phy.c,v 1.1.4.2 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kmem.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
struct fdtbus_phy_controller {
|
||||
device_t pc_dev;
|
||||
int pc_phandle;
|
||||
const struct fdtbus_phy_controller_func *pc_funcs;
|
||||
|
||||
struct fdtbus_phy_controller *pc_next;
|
||||
};
|
||||
|
||||
static struct fdtbus_phy_controller *fdtbus_pc = NULL;
|
||||
|
||||
int
|
||||
fdtbus_register_phy_controller(device_t dev, int phandle,
|
||||
const struct fdtbus_phy_controller_func *funcs)
|
||||
{
|
||||
struct fdtbus_phy_controller *pc;
|
||||
|
||||
pc = kmem_alloc(sizeof(*pc), KM_SLEEP);
|
||||
pc->pc_dev = dev;
|
||||
pc->pc_phandle = phandle;
|
||||
pc->pc_funcs = funcs;
|
||||
|
||||
pc->pc_next = fdtbus_pc;
|
||||
fdtbus_pc = pc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fdtbus_phy_controller *
|
||||
fdtbus_get_phy_controller(int phandle)
|
||||
{
|
||||
struct fdtbus_phy_controller *pc;
|
||||
|
||||
for (pc = fdtbus_pc; pc; pc = pc->pc_next) {
|
||||
if (pc->pc_phandle == phandle) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct fdtbus_phy *
|
||||
fdtbus_phy_get_index(int phandle, u_int index)
|
||||
{
|
||||
struct fdtbus_phy_controller *pc;
|
||||
struct fdtbus_phy *phy = NULL;
|
||||
void *phy_priv = NULL;
|
||||
uint32_t *phys = NULL;
|
||||
uint32_t *p;
|
||||
u_int n, phy_cells;
|
||||
int len, resid;
|
||||
|
||||
len = OF_getproplen(phandle, "phys");
|
||||
if (len <= 0)
|
||||
return NULL;
|
||||
|
||||
phys = kmem_alloc(len, KM_SLEEP);
|
||||
if (OF_getprop(phandle, "phys", phys, len) != len) {
|
||||
kmem_free(phys, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = phys;
|
||||
for (n = 0, resid = len; resid > 0; n++) {
|
||||
const int pc_phandle =
|
||||
fdtbus_get_phandle_from_native(be32toh(p[0]));
|
||||
if (of_getprop_uint32(pc_phandle, "#phy-cells", &phy_cells))
|
||||
break;
|
||||
if (n == index) {
|
||||
pc = fdtbus_get_phy_controller(pc_phandle);
|
||||
if (pc == NULL)
|
||||
goto done;
|
||||
phy_priv = pc->pc_funcs->acquire(pc->pc_dev,
|
||||
phy_cells > 0 ? &p[1] : NULL, phy_cells * 4);
|
||||
if (phy_priv) {
|
||||
phy = kmem_alloc(sizeof(*phy), KM_SLEEP);
|
||||
phy->phy_pc = pc;
|
||||
phy->phy_priv = phy_priv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
resid -= (phy_cells + 1) * 4;
|
||||
p += phy_cells + 1;
|
||||
}
|
||||
|
||||
done:
|
||||
if (phys)
|
||||
kmem_free(phys, len);
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
||||
struct fdtbus_phy *
|
||||
fdtbus_phy_get(int phandle, const char *phyname)
|
||||
{
|
||||
struct fdtbus_phy *phy = NULL;
|
||||
char *phy_names = NULL;
|
||||
const char *p;
|
||||
u_int index;
|
||||
int len, resid;
|
||||
|
||||
len = OF_getproplen(phandle, "phy-names");
|
||||
if (len <= 0)
|
||||
return NULL;
|
||||
|
||||
phy_names = kmem_alloc(len, KM_SLEEP);
|
||||
if (OF_getprop(phandle, "phy-names", phy_names, len) != len) {
|
||||
kmem_free(phy_names, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = phy_names;
|
||||
for (index = 0, resid = len; resid > 0; index++) {
|
||||
if (strcmp(p, phyname) == 0) {
|
||||
phy = fdtbus_phy_get_index(phandle, index);
|
||||
break;
|
||||
}
|
||||
resid -= strlen(p);
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
|
||||
if (phy_names)
|
||||
kmem_free(phy_names, len);
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
||||
void
|
||||
fdtbus_phy_put(struct fdtbus_phy *phy)
|
||||
{
|
||||
struct fdtbus_phy_controller *pc = phy->phy_pc;
|
||||
|
||||
pc->pc_funcs->release(pc->pc_dev, phy->phy_priv);
|
||||
kmem_free(phy, sizeof(*phy));
|
||||
}
|
||||
|
||||
int
|
||||
fdtbus_phy_enable(struct fdtbus_phy *phy, bool enable)
|
||||
{
|
||||
struct fdtbus_phy_controller *pc = phy->phy_pc;
|
||||
|
||||
return pc->pc_funcs->enable(pc->pc_dev, phy->phy_priv, enable);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
/* $NetBSD: fdt_pinctrl.c,v 1.3 2016/10/11 13:04:57 maxv Exp $ */
|
||||
/* $NetBSD: fdt_pinctrl.c,v 1.3.8.1 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
|
||||
* Copyright (c) 2015 Martin Fouts
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -27,7 +28,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdt_pinctrl.c,v 1.3 2016/10/11 13:04:57 maxv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdt_pinctrl.c,v 1.3.8.1 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -37,8 +38,8 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_pinctrl.c,v 1.3 2016/10/11 13:04:57 maxv Exp $")
|
|||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
struct fdtbus_pinctrl_controller {
|
||||
device_t pc_dev;
|
||||
int pc_phandle;
|
||||
void *pc_cookie;
|
||||
const struct fdtbus_pinctrl_controller_func *pc_funcs;
|
||||
|
||||
struct fdtbus_pinctrl_controller *pc_next;
|
||||
|
@ -47,13 +48,13 @@ struct fdtbus_pinctrl_controller {
|
|||
static struct fdtbus_pinctrl_controller *fdtbus_pc = NULL;
|
||||
|
||||
int
|
||||
fdtbus_register_pinctrl_config(void *cookie, int phandle,
|
||||
fdtbus_register_pinctrl_config(device_t dev, int phandle,
|
||||
const struct fdtbus_pinctrl_controller_func *funcs)
|
||||
{
|
||||
struct fdtbus_pinctrl_controller *pc;
|
||||
|
||||
pc = kmem_alloc(sizeof(*pc), KM_SLEEP);
|
||||
pc->pc_cookie = cookie;
|
||||
pc->pc_dev = dev;
|
||||
pc->pc_phandle = phandle;
|
||||
pc->pc_funcs = funcs;
|
||||
|
||||
|
@ -78,57 +79,88 @@ fdtbus_pinctrl_lookup(int phandle)
|
|||
int
|
||||
fdtbus_pinctrl_set_config_index(int phandle, u_int index)
|
||||
{
|
||||
char buf[80];
|
||||
int len, handle;
|
||||
struct fdtbus_pinctrl_controller *pc;
|
||||
const u_int *pinctrl_data;
|
||||
char buf[16];
|
||||
u_int xref, pinctrl_cells;
|
||||
int len, error;
|
||||
|
||||
snprintf(buf, 80, "pinctrl-%d", index);
|
||||
snprintf(buf, sizeof(buf), "pinctrl-%u", index);
|
||||
|
||||
len = OF_getprop(phandle, buf, (char *)&handle,
|
||||
sizeof(handle));
|
||||
if (len != sizeof(int)) {
|
||||
printf("%s: couldn't get %s.\n", __func__, buf);
|
||||
return -1;
|
||||
}
|
||||
pinctrl_data = fdtbus_get_prop(phandle, buf, &len);
|
||||
if (pinctrl_data == NULL)
|
||||
return ENOENT;
|
||||
|
||||
handle = fdtbus_get_phandle_from_native(be32toh(handle));
|
||||
while (len > 0) {
|
||||
xref = fdtbus_get_phandle_from_native(be32toh(pinctrl_data[0]));
|
||||
pc = fdtbus_pinctrl_lookup(xref);
|
||||
if (pc == NULL)
|
||||
return ENXIO;
|
||||
|
||||
pc = fdtbus_pinctrl_lookup(handle);
|
||||
if (!pc) {
|
||||
printf("%s: Couldn't get handle %d for %s\n", __func__, handle,
|
||||
buf);
|
||||
return -1;
|
||||
if (of_getprop_uint32(OF_parent(xref), "#pinctrl-cells", &pinctrl_cells) != 0)
|
||||
pinctrl_cells = 1;
|
||||
|
||||
error = pc->pc_funcs->set_config(pc->pc_dev, pinctrl_data, pinctrl_cells * 4);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
pinctrl_data += pinctrl_cells;
|
||||
len -= (pinctrl_cells * 4);
|
||||
}
|
||||
|
||||
return pc->pc_funcs->set_config(pc->pc_cookie);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fdtbus_pinctrl_set_config(int phandle, const char *cfgname)
|
||||
{
|
||||
int index = 0;
|
||||
int len;
|
||||
char *result;
|
||||
char *next;
|
||||
const char *pinctrl_names, *name;
|
||||
int len, index;
|
||||
|
||||
len = OF_getproplen(phandle, "pinctrl-names");
|
||||
if (len <= 0)
|
||||
if ((len = OF_getproplen(phandle, "pinctrl-names")) < 0)
|
||||
return -1;
|
||||
result = kmem_zalloc(len, KM_SLEEP);
|
||||
OF_getprop(phandle, "pinctrl-names", result, len);
|
||||
|
||||
next = result;
|
||||
while (next - result < len) {
|
||||
if (!strcmp(next, cfgname)) {
|
||||
kmem_free(result, len);
|
||||
pinctrl_names = fdtbus_get_string(phandle, "pinctrl-names");
|
||||
|
||||
for (name = pinctrl_names, index = 0; len > 0;
|
||||
name += strlen(name) + 1, index++) {
|
||||
if (strcmp(name, cfgname) == 0)
|
||||
return fdtbus_pinctrl_set_config_index(phandle, index);
|
||||
}
|
||||
index++;
|
||||
while (*next)
|
||||
next++;
|
||||
next++;
|
||||
}
|
||||
|
||||
kmem_free(result, len);
|
||||
/* Not found */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
fdtbus_pinctrl_configure_node(int phandle)
|
||||
{
|
||||
char buf[256];
|
||||
int child, error;
|
||||
|
||||
for (child = OF_child(phandle); child; child = OF_peer(child)) {
|
||||
if (!fdtbus_status_okay(child))
|
||||
continue;
|
||||
|
||||
/* Configure child nodes */
|
||||
fdtbus_pinctrl_configure_node(child);
|
||||
|
||||
/*
|
||||
* Set configuration 0 for this node. This may fail if the
|
||||
* pinctrl provider is missing; that's OK, we will re-configure
|
||||
* when that provider attaches.
|
||||
*/
|
||||
fdtbus_get_path(child, buf, sizeof(buf));
|
||||
error = fdtbus_pinctrl_set_config_index(child, 0);
|
||||
if (error == 0)
|
||||
aprint_debug("pinctrl: set config pinctrl-0 for %s\n", buf);
|
||||
else if (error != ENOENT)
|
||||
aprint_debug("pinctrl: failed to set config pinctrl-0 for %s: %d\n", buf, error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fdtbus_pinctrl_configure(void)
|
||||
{
|
||||
fdtbus_pinctrl_configure_node(OF_finddevice("/"));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fdt_subr.c,v 1.13 2017/06/02 01:07:53 jmcneill Exp $ */
|
||||
/* $NetBSD: fdt_subr.c,v 1.13.2.1 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.13 2017/06/02 01:07:53 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.13.2.1 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -406,3 +406,39 @@ fdtbus_status_okay(int phandle)
|
|||
|
||||
return strncmp(prop, "ok", 2) == 0;
|
||||
}
|
||||
|
||||
const void *
|
||||
fdtbus_get_prop(int phandle, const char *prop, int *plen)
|
||||
{
|
||||
const int off = fdtbus_phandle2offset(phandle);
|
||||
|
||||
return fdt_getprop(fdtbus_get_data(), off, prop, plen);
|
||||
}
|
||||
|
||||
const char *
|
||||
fdtbus_get_string(int phandle, const char *prop)
|
||||
{
|
||||
const int off = fdtbus_phandle2offset(phandle);
|
||||
|
||||
return fdt_getprop(fdtbus_get_data(), off, prop, NULL);
|
||||
}
|
||||
|
||||
const char *
|
||||
fdtbus_get_string_index(int phandle, const char *prop, u_int index)
|
||||
{
|
||||
const char *names, *name;
|
||||
int len, cur;
|
||||
|
||||
if ((len = OF_getproplen(phandle, prop)) < 0)
|
||||
return NULL;
|
||||
|
||||
names = fdtbus_get_string(phandle, prop);
|
||||
|
||||
for (name = names, cur = 0; len > 0;
|
||||
name += strlen(name) + 1, cur++) {
|
||||
if (index == cur)
|
||||
return name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fdtbus.c,v 1.13 2017/05/28 00:28:17 jmcneill Exp $ */
|
||||
/* $NetBSD: fdtbus.c,v 1.13.2.1 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.13 2017/05/28 00:28:17 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.13.2.1 2017/07/18 19:13:09 snj Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -40,6 +40,8 @@ __KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.13 2017/05/28 00:28:17 jmcneill Exp $")
|
|||
|
||||
#include <dev/fdt/fdtvar.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include "locators.h"
|
||||
|
||||
#define FDT_MAX_PATH 256
|
||||
|
@ -82,13 +84,21 @@ static int
|
|||
fdt_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
const struct fdt_attach_args *faa = aux;
|
||||
const int phandle = faa->faa_phandle;
|
||||
int match;
|
||||
|
||||
match = of_match_compatible(faa->faa_phandle, fdtbus_compatible);
|
||||
/* Check compatible string */
|
||||
match = of_match_compatible(phandle, fdtbus_compatible);
|
||||
if (match)
|
||||
return match;
|
||||
|
||||
return OF_finddevice("/") == faa->faa_phandle;
|
||||
/* Some /clocks nodes have no compatible string */
|
||||
if (!of_hasprop(phandle, "compatible") &&
|
||||
OF_finddevice("/clocks") == phandle)
|
||||
return 1;
|
||||
|
||||
/* Always match the root node */
|
||||
return OF_finddevice("/") == phandle;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -275,6 +285,7 @@ fdtbus_print(void *aux, const char *pnp)
|
|||
const struct fdt_attach_args * const faa = aux;
|
||||
char buf[FDT_MAX_PATH];
|
||||
const char *name = buf;
|
||||
int len;
|
||||
|
||||
if (pnp && faa->faa_quiet)
|
||||
return QUIET;
|
||||
|
@ -286,9 +297,17 @@ fdtbus_print(void *aux, const char *pnp)
|
|||
if (!fdtbus_get_path(faa->faa_phandle, buf, sizeof(buf)))
|
||||
name = faa->faa_name;
|
||||
|
||||
if (pnp)
|
||||
if (pnp) {
|
||||
aprint_normal("%s at %s", name, pnp);
|
||||
else
|
||||
const char *compat = fdt_getprop(fdtbus_get_data(),
|
||||
fdtbus_phandle2offset(faa->faa_phandle), "compatible",
|
||||
&len);
|
||||
while (len > 0) {
|
||||
aprint_debug(" <%s>", compat);
|
||||
len -= (strlen(compat) + 1);
|
||||
compat += (strlen(compat) + 1);
|
||||
}
|
||||
} else
|
||||
aprint_debug(" (%s)", name);
|
||||
|
||||
return UNCONF;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fdtvar.h,v 1.20 2017/06/02 13:53:29 jmcneill Exp $ */
|
||||
/* $NetBSD: fdtvar.h,v 1.20.2.1 2017/07/18 19:13:09 snj Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -85,7 +85,7 @@ struct fdtbus_pinctrl_pin {
|
|||
};
|
||||
|
||||
struct fdtbus_pinctrl_controller_func {
|
||||
int (*set_config)(void *);
|
||||
int (*set_config)(device_t, const void *, size_t);
|
||||
};
|
||||
|
||||
struct fdtbus_regulator_controller;
|
||||
|
@ -172,6 +172,19 @@ struct fdtbus_power_controller_func {
|
|||
void (*poweroff)(device_t);
|
||||
};
|
||||
|
||||
struct fdtbus_phy_controller;
|
||||
|
||||
struct fdtbus_phy {
|
||||
struct fdtbus_phy_controller *phy_pc;
|
||||
void *phy_priv;
|
||||
};
|
||||
|
||||
struct fdtbus_phy_controller_func {
|
||||
void * (*acquire)(device_t, const void *, size_t);
|
||||
void (*release)(device_t, void *);
|
||||
int (*enable)(device_t, void *, bool);
|
||||
};
|
||||
|
||||
struct fdt_console {
|
||||
int (*match)(int);
|
||||
void (*consinit)(struct fdt_attach_args *, u_int);
|
||||
|
@ -198,7 +211,7 @@ int fdtbus_register_i2c_controller(device_t, int,
|
|||
const struct fdtbus_i2c_controller_func *);
|
||||
int fdtbus_register_gpio_controller(device_t, int,
|
||||
const struct fdtbus_gpio_controller_func *);
|
||||
int fdtbus_register_pinctrl_config(void *, int,
|
||||
int fdtbus_register_pinctrl_config(device_t, int,
|
||||
const struct fdtbus_pinctrl_controller_func *);
|
||||
int fdtbus_register_regulator_controller(device_t, int,
|
||||
const struct fdtbus_regulator_controller_func *);
|
||||
|
@ -210,6 +223,8 @@ int fdtbus_register_dma_controller(device_t, int,
|
|||
const struct fdtbus_dma_controller_func *);
|
||||
int fdtbus_register_power_controller(device_t, int,
|
||||
const struct fdtbus_power_controller_func *);
|
||||
int fdtbus_register_phy_controller(device_t, int,
|
||||
const struct fdtbus_phy_controller_func *);
|
||||
|
||||
int fdtbus_get_reg(int, u_int, bus_addr_t *, bus_size_t *);
|
||||
int fdtbus_get_reg64(int, u_int, uint64_t *, uint64_t *);
|
||||
|
@ -226,6 +241,7 @@ int fdtbus_gpio_read(struct fdtbus_gpio_pin *);
|
|||
void fdtbus_gpio_write(struct fdtbus_gpio_pin *, int);
|
||||
int fdtbus_gpio_read_raw(struct fdtbus_gpio_pin *);
|
||||
void fdtbus_gpio_write_raw(struct fdtbus_gpio_pin *, int);
|
||||
void fdtbus_pinctrl_configure(void);
|
||||
int fdtbus_pinctrl_set_config_index(int, u_int);
|
||||
int fdtbus_pinctrl_set_config(int, const char *);
|
||||
struct fdtbus_regulator *fdtbus_regulator_acquire(int, const char *);
|
||||
|
@ -254,6 +270,11 @@ void fdtbus_reset_put(struct fdtbus_reset *);
|
|||
int fdtbus_reset_assert(struct fdtbus_reset *);
|
||||
int fdtbus_reset_deassert(struct fdtbus_reset *);
|
||||
|
||||
struct fdtbus_phy *fdtbus_phy_get(int, const char *);
|
||||
struct fdtbus_phy *fdtbus_phy_get_index(int, u_int);
|
||||
void fdtbus_phy_put(struct fdtbus_phy *);
|
||||
int fdtbus_phy_enable(struct fdtbus_phy *, bool);
|
||||
|
||||
int fdtbus_todr_attach(device_t, int, todr_chip_handle_t);
|
||||
|
||||
void fdtbus_power_reset(void);
|
||||
|
@ -274,6 +295,10 @@ tcflag_t fdtbus_get_stdout_flags(void);
|
|||
|
||||
bool fdtbus_status_okay(int);
|
||||
|
||||
const void * fdtbus_get_prop(int, const char *, int *);
|
||||
const char * fdtbus_get_string(int, const char *);
|
||||
const char * fdtbus_get_string_index(int, const char *, u_int);
|
||||
|
||||
int fdtbus_print(void *, const char *);
|
||||
|
||||
#endif /* _DEV_FDT_FDTVAR_H */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.fdt,v 1.16 2017/06/03 14:48:03 jmcneill Exp $
|
||||
# $NetBSD: files.fdt,v 1.16.2.1 2017/07/18 19:13:09 snj Exp $
|
||||
|
||||
include "external/bsd/libfdt/conf/files.libfdt"
|
||||
|
||||
|
@ -18,10 +18,18 @@ device fclock: clk
|
|||
attach fclock at fdt
|
||||
file dev/fdt/fixedclock.c fclock
|
||||
|
||||
device ffclock: clk
|
||||
attach ffclock at fdt
|
||||
file dev/fdt/fixedfactorclock.c ffclock
|
||||
|
||||
device gpiokeys: sysmon_envsys, sysmon_power
|
||||
attach gpiokeys at fdt
|
||||
file dev/fdt/gpiokeys.c gpiokeys
|
||||
|
||||
device gpioleds: leds
|
||||
attach gpioleds at fdt
|
||||
file dev/fdt/gpioleds.c gpioleds
|
||||
|
||||
file dev/fdt/fdt_openfirm.c fdtbus
|
||||
file dev/fdt/fdt_subr.c fdtbus
|
||||
file dev/fdt/fdt_clock.c fdtbus
|
||||
|
@ -29,6 +37,7 @@ file dev/fdt/fdt_dma.c fdtbus
|
|||
file dev/fdt/fdt_gpio.c fdtbus
|
||||
file dev/fdt/fdt_i2c.c fdtbus
|
||||
file dev/fdt/fdt_intr.c fdtbus
|
||||
file dev/fdt/fdt_phy.c fdtbus
|
||||
file dev/fdt/fdt_power.c fdtbus
|
||||
file dev/fdt/fdt_regulator.c fdtbus
|
||||
file dev/fdt/fdt_reset.c fdtbus
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue