From owner-freebsd-arm@FreeBSD.ORG Sun Feb 1 23:47:10 2015 Return-Path: Delivered-To: freebsd-arm@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 46A4C3FE for ; Sun, 1 Feb 2015 23:47:10 +0000 (UTC) Received: from feith1.FEITH.COM (feith1.FEITH.COM [192.251.93.1]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 53FCF77F for ; Sun, 1 Feb 2015 23:47:09 +0000 (UTC) Received: from jwlab.FEITH.COM (jwlab.FEITH.COM [192.251.93.16]) by feith1.FEITH.COM (8.14.5+Sun/8.12.9) with ESMTP id t11NXS2Y014864; Sun, 1 Feb 2015 18:33:28 -0500 (EST) (envelope-from john@jwlab.FEITH.COM) Received: from jwlab.FEITH.COM (localhost [127.0.0.1]) by jwlab.FEITH.COM (8.14.5+Sun/8.14.5) with ESMTP id t11NXSxb028697; Sun, 1 Feb 2015 18:33:28 -0500 (EST) Received: (from john@localhost) by jwlab.FEITH.COM (8.14.5+Sun/8.14.5/Submit) id t11NXPOe028696; Sun, 1 Feb 2015 18:33:25 -0500 (EST) Date: Sun, 1 Feb 2015 18:33:25 -0500 (EST) From: John Wehle Message-Id: <201502012333.t11NXPOe028696@jwlab.FEITH.COM> To: ganbold@gmail.com Subject: Initial Amlogic aml8726-m6 and aml8726-m8 support files MIME-Version: 1.0 Content-Type: text/plain X-DCC-Etherboy-Metrics: feith1; whitelist X-Scanned-By: MIMEDefang 2.67 on 192.251.93.1 X-Mailman-Approved-At: Mon, 02 Feb 2015 03:13:09 +0000 Cc: freebsd-arm@freebsd.org X-BeenThere: freebsd-arm@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "Porting FreeBSD to ARM processors." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 01 Feb 2015 23:47:10 -0000 Here's the initial release of support for Amlogic ARM SoC devices. It supplies basic functionality, however it should by no means be considered production ready. Currently FreeBSD successfully boots to the login prompt on an aml8726-m6 board (the box seems to be some type of Visson ATV-102) as well as on an aml8726-m8b board (a Hardkernel ODROID-C1) using a SD card and a serial console. Unshar into your FreeBSD 11.0-current source tree, review the README, apply the patch, and have fun. -- John ----------------------8<---------------------------8<----------------- #!/bin/sh # This is a shell archive (produced by GNU sharutils 4.13.5). # To extract the files from this archive, save it to some FILE, remove # everything before the '#!/bin/sh' line above, then type 'sh FILE'. # lock_dir=_sh39871 # Made on 2015-02-01 18:04 EST by . # Source directory was '/usr/local/src/freebsd/src'. # # Existing files will *not* be overwritten, unless '-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 7202 -rw-r--r-- sys/boot/fdt/dts/arm/odroidc1.dts # 7657 -rw-r--r-- sys/boot/fdt/dts/arm/vsatv102-m6.dts # 4235 -rw-r--r-- sys/arm/conf/ODROIDC1 # 4242 -rw-r--r-- sys/arm/conf/VSATV102 # 2581 -rw-r--r-- sys/arm/amlogic/aml8726/README.txt # 3583 -rw-r--r-- sys/arm/amlogic/aml8726/PatchJLW01 # 7513 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_clkmsr.c # 1545 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_clkmsr.h # 12374 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_fb.c # 7953 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_fb.h # 9263 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_gpio.c # 4240 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_identsoc.c # 2574 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_l2cache.c # 5417 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_machdep.c # 1784 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_machdep.h # 22210 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mmc.c # 6226 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mmc.h # 17678 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mp.c # 7110 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_pic.c # 3976 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_rng.c # 12262 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_rtc.c # 2304 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_soc.h # 10833 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_timer.c # 4290 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_uart.h # 4389 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_uart_console.c # 10407 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c # 8749 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_wdt.c # 1260 -rw-r--r-- sys/arm/amlogic/aml8726/files.aml8726 # 82 -rw-r--r-- sys/arm/amlogic/aml8726/files.smp # 1038 -rwxr--r-- sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh # 398 -rw-r--r-- sys/arm/amlogic/aml8726/std.aml8726 # 530 -rw-r--r-- sys/arm/amlogic/aml8726/std.odroidc1 # 533 -rw-r--r-- sys/arm/amlogic/aml8726/std.vsatv102-m6 # 16704 -rw-r--r-- sys/arm/amlogic/aml8726/uart_dev_aml8726.c # MD5SUM=${MD5SUM-md5sum} f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'` test -n "${f}" && md5check=true || md5check=false ${md5check} || \ echo 'Note: not verifying md5sums. Consider installing GNU coreutils.' if test "X$1" = "X-c" then keep_file='' else keep_file=true fi echo=echo save_IFS="${IFS}" IFS="${IFS}:" gettext_dir= locale_dir= set_echo=false for dir in $PATH do if test -f $dir/gettext \ && ($dir/gettext --version >/dev/null 2>&1) then case `$dir/gettext --version 2>&1 | sed 1q` in *GNU*) gettext_dir=$dir set_echo=true break ;; esac fi done if ${set_echo} then set_echo=false for dir in $PATH do if test -f $dir/shar \ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) then locale_dir=`$dir/shar --print-text-domain-dir` set_echo=true break fi done if ${set_echo} then TEXTDOMAINDIR=$locale_dir export TEXTDOMAINDIR TEXTDOMAIN=sharutils export TEXTDOMAIN echo="$gettext_dir/gettext -s" fi fi IFS="$save_IFS" if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null then if (echo -n test; echo 1,2,3) | grep n >/dev/null then shar_n= shar_c=' ' else shar_n=-n shar_c= ; fi else shar_n= shar_c='\c' ; fi f=shar-touch.$$ st1=200112312359.59 st2=123123592001.59 st2tr=123123592001.5 # old SysV 14-char limit st3=1231235901 if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \ test ! -f ${st1} && test -f ${f}; then shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"' elif touch -am ${st2} ${f} >/dev/null 2>&1 && \ test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"' elif touch -am ${st3} ${f} >/dev/null 2>&1 && \ test ! -f ${st3} && test -f ${f}; then shar_touch='touch -am $3$4$5$6$2 "$8"' else shar_touch=: echo ${echo} 'WARNING: not restoring timestamps. Consider getting and installing GNU '\''touch'\'', distributed in GNU coreutils...' echo fi rm -f ${st1} ${st2} ${st2tr} ${st3} ${f} # if test ! -d ${lock_dir} ; then : else ${echo} "lock directory ${lock_dir} exists" exit 1 fi if mkdir ${lock_dir} then ${echo} "x - created lock directory ${lock_dir}." else ${echo} "x - failed to create lock directory ${lock_dir}." exit 1 fi # ============= sys/boot/fdt/dts/arm/odroidc1.dts ============== if test ! -d 'sys'; then mkdir 'sys' if test $? -eq 0 then ${echo} "x - created directory sys." else ${echo} "x - failed to create directory sys." exit 1 fi fi if test ! -d 'sys/boot'; then mkdir 'sys/boot' if test $? -eq 0 then ${echo} "x - created directory sys/boot." else ${echo} "x - failed to create directory sys/boot." exit 1 fi fi if test ! -d 'sys/boot/fdt'; then mkdir 'sys/boot/fdt' if test $? -eq 0 then ${echo} "x - created directory sys/boot/fdt." else ${echo} "x - failed to create directory sys/boot/fdt." exit 1 fi fi if test ! -d 'sys/boot/fdt/dts'; then mkdir 'sys/boot/fdt/dts' if test $? -eq 0 then ${echo} "x - created directory sys/boot/fdt/dts." else ${echo} "x - failed to create directory sys/boot/fdt/dts." exit 1 fi fi if test ! -d 'sys/boot/fdt/dts/arm'; then mkdir 'sys/boot/fdt/dts/arm' if test $? -eq 0 then ${echo} "x - created directory sys/boot/fdt/dts/arm." else ${echo} "x - failed to create directory sys/boot/fdt/dts/arm." exit 1 fi fi if test -n "${keep_file}" && test -f 'sys/boot/fdt/dts/arm/odroidc1.dts' then ${echo} "x - SKIPPING sys/boot/fdt/dts/arm/odroidc1.dts (file already exists)" else ${echo} "x - extracting sys/boot/fdt/dts/arm/odroidc1.dts (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/boot/fdt/dts/arm/odroidc1.dts' && /*- X * Copyright (c) 2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X /* X * The ordering of certain devices is significant (e.g. usb depends on X * usb-phy which depends on gpio, also the timer should appear early on X * to provide a reasonably accurate DELAY implementation). X * X * Both usb-phys devices must be configured to prevent the usb controller X * from hanging during initialization. X */ X /dts-v1/; X /memreserve/ 0x7900000 0x00600000; /* 6MB frame buffer */ X / { X model = "hardkernel,odroid-c1"; X compatible = "hardkernel,odroid-c1", "amlogic,s805"; X X #address-cells = <1>; X #size-cells = <1>; X X interrupt-parent = <&gic>; X X aliases { X soc = &soc; X screen = &screen; X uart0 = &uart0; X }; X X cpus { X #address-cells = <1>; X #size-cells = <0>; X X cpu@0 { X device_type = "cpu"; X compatible = "arm,cortex-a5"; X reg = <0x0>; X }; X X cpu@1 { X device_type = "cpu"; X compatible = "arm,cortex-a5"; X reg = <0x1>; X }; X X cpu@2 { X device_type = "cpu"; X compatible = "arm,cortex-a5"; X reg = <0x2>; X }; X X cpu@3 { X device_type = "cpu"; X compatible = "arm,cortex-a5"; X reg = <0x3>; X }; X }; X X memory { X device_type = "memory"; X reg = <0x0 0x40000000>; /* 1GB RAM */ X }; X X soc: soc@c0000000 { X device_type = "soc"; X compatible = "simple-bus"; X bus-frequency = <0>; X X #address-cells = <1>; X #size-cells = <1>; X X ranges = <0x0 0xc0000000 0x1a100000>; X X gic: gic@4301000 { X device_type = "interrupt-controller"; X compatible = "arm,gic"; X reg = <0x4301000 0x1000>, // distributer registers X <0x4300100 0x0100>; // CPU if registers X X interrupt-controller; X #interrupt-cells = <1>; X }; X X scu: scu@4300000 { X compatible = "arm,cortex-a5-scu"; X reg = <0x4300000 0x1000>; X }; X X cpuconfig: cpuconfig@1901ff80 { X compatible = "amlogic,aml8726-cpuconfig"; X reg = <0x1901ff80 16>; X }; X X pl310@4200000 { X compatible = "arm,pl310"; X reg = <0x4200000 0x1000>; X interrupts = <61>; /* AM_IRQ1(29) */ X interrupt-parent = <&gic>; X }; X X watchdog@1109900 { X compatible = "amlogic,aml8726-wdt"; X reg = <0x1109900 8>; /* cbus 0x2640 */ X interrupts = <0>; /* AM_IRQ0(0) */ X interrupt-parent = <&gic>; X }; X X timer@1109940 { X compatible = "amlogic,aml8726-timer"; X reg = <0x1109940 24>; /* cbus 0x2650 */ X interrupts = <10 /* AM_IRQ0(10) */ X 11 /* AM_IRQ0(11) */ X 6 /* AM_IRQ0(6) */ X 29>; /* AM_IRQ0(29) */ X interrupt-parent = <&gic>; X }; X X rtc@8100740 { X compatible = "amlogic,aml8726-rtc"; X reg = <0x8100740 20>; /* aobus 0x1d0 */ X interrupts = <72>; /* AM_IRQ2(8) */ X interrupt-parent = <&gic>; X X init-always = "false"; X xo-init = <0x180a>; X gpo-init = <0x500000>; X }; X X clkmsr: clkmsr@1108758 { X compatible = "amlogic,aml8726-clkmsr"; X reg = <0x1108758 16>; /* cbus 0x21d6 */ X }; X X uart0: uart@81004c0 { X /* uart-ao */ X device_type = "serial"; X compatible = "amlogic,aml8726-uart"; X clock-frequency = <0>; X current-speed = <115200>; X reg = <0x81004c0 20>; /* aobus 0x130 */ X interrupts = <90>; /* AM_IRQ2(26) */ X interrupt-parent = <&gic>; X }; X X gpioao: gpio@8100024 { X /* gpio unit 7 */ X compatible = "amlogic,aml8726-gpio"; X reg = <0x8100024 4>, /* oen aobus 0x9 */ X <0x8100024 4>, /* out */ X <0x8100028 4>; /* in */ X X gpio-controller; X #gpio-cells = <1>; X pin-count = <14>; X }; X X gpio5: gpio@110806c { X compatible = "amlogic,aml8726-gpio"; X reg = <0x110806c 4>, /* oen cbus 0x201b */ X <0x1108070 4>, /* out */ X <0x1108074 4>; /* in */ X X gpio-controller; X #gpio-cells = <1>; X pin-count = <32>; X }; X X mmc@1108c20 { X compatible = "amlogic,aml8726-mmc"; X reg = <0x1108c20 32>; /* cbus 0x2308 */ X interrupts = <28>; /* AM_IRQ0(28) */ X interrupt-parent = <&gic>; X X mmc-pwr-en = <&gpio5 31 0>; /* card8 */ X ins-detect = <&gpio5 29 0>; /* card6 */ X }; X X rng@1108100 { X compatible = "amlogic,aml8726-rng"; X reg = <0x1108100 8>; /* cbus 0x2040 */ X }; X X usb-phy@1108800 { X /* usb-a phy */ X compatible = "amlogic,aml8726-m8-usb-phy"; X reg = <0x1108800 32>; /* cbus 0x2200 */ X X usb-pwr-en = <&gpioao 5 1>; /* gpioao5 vbus */ X }; X X usb-phy@1108820 { X /* usb-b phy */ X compatible = "amlogic,aml8726-m8-usb-phy"; X reg = <0x1108820 32>; /* cbus 0x2208 */ X X force-aca = "true"; X usb-hub-rst = <&gpioao 4 0>; /* gpioao4 hub-rst */ X }; X X usb@9040000 { X /* usb-a */ X compatible = "synopsys,designware-hs-otg2"; X reg = <0x9040000 0x40000>; /* ahbbus 0x40000*/ X interrupts = <30>; /* AM_IRQ0(30) */ X interrupt-parent = <&gic>; X #address-cells = <1>; X #size-cells = <0>; X X dr_mode = "host"; X }; X X usb@90c0000 { X /* usb-b */ X compatible = "synopsys,designware-hs-otg2"; X reg = <0x90c0000 0x40000>; /* ahbbus 0xc0000 */ X interrupts = <31>; /* AM_IRQ0(31) */ X interrupt-parent = <&gic>; X #address-cells = <1>; X #size-cells = <0>; X X dr_mode = "host"; X }; X X eth@9410000 { X /* ethernet */ X compatible = "snps,dwmac"; X reg = <0x9410000 0x2000>; /* ahbbus 0x410000 */ X interrupts = <8>; /* AM_IRQ0(8) */ X interrupt-parent = <&gic>; X #address-cells = <1>; X #size-cells = <0>; X }; X X screen: fb@8006020 { X device_type = "display"; X compatible = "amlogic,aml8726-fb"; X reg = <0x8006048 12>, /* CANVAS */ X <0x1106800 1024>, /* VIU */ X <0x1107400 1024>; /* VPP */ X interrupts = <2 /* AM_IRQ0(2) */ X 3 /* AM_IRQ0(3) */ X 12 /* AM_IRQ0(12) */ X 13>; /* AM_IRQ0(13) */ X interrupt-parent = <&gic>; X /* status = "disabled"; */ X X address = <0x7900000>; /* match memreserve */ X width = <720>; X height = <480>; X depth = <24>; X linebytes = <2160>; X }; X }; X X leds { X compatible = "gpio-leds"; X X sys_led { X gpios = <&gpioao 13>; /* gpioao13 sys_led */ X label = "sys_led"; X }; X }; X X chosen { X stdin = "uart0"; X stdout = "uart0"; X }; }; SHAR_EOF (set 20 15 02 01 16 23 56 'sys/boot/fdt/dts/arm/odroidc1.dts' eval "${shar_touch}") && \ chmod 0644 'sys/boot/fdt/dts/arm/odroidc1.dts' if test $? -ne 0 then ${echo} "restore of sys/boot/fdt/dts/arm/odroidc1.dts failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/boot/fdt/dts/arm/odroidc1.dts': 'MD5 check failed' ) << \SHAR_EOF 74a1f989c00329a0fb627ec86940a97d sys/boot/fdt/dts/arm/odroidc1.dts SHAR_EOF else test `LC_ALL=C wc -c < 'sys/boot/fdt/dts/arm/odroidc1.dts'` -ne 7202 && \ ${echo} "restoration warning: size of 'sys/boot/fdt/dts/arm/odroidc1.dts' is not 7202" fi fi # ============= sys/boot/fdt/dts/arm/vsatv102-m6.dts ============== if test ! -d 'sys/boot/fdt/dts/arm'; then mkdir 'sys/boot/fdt/dts/arm' if test $? -eq 0 then ${echo} "x - created directory sys/boot/fdt/dts/arm." else ${echo} "x - failed to create directory sys/boot/fdt/dts/arm." exit 1 fi fi if test -n "${keep_file}" && test -f 'sys/boot/fdt/dts/arm/vsatv102-m6.dts' then ${echo} "x - SKIPPING sys/boot/fdt/dts/arm/vsatv102-m6.dts (file already exists)" else ${echo} "x - extracting sys/boot/fdt/dts/arm/vsatv102-m6.dts (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/boot/fdt/dts/arm/vsatv102-m6.dts' && /*- X * Copyright (c) 2013-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X /* X * The ordering of certain devices is significant (e.g. usb depends on X * usb-phy which depends on gpio, also the timer should appear early on X * to provide a reasonably accurate DELAY implementation). X * X * Both usb-phys devices must be configured to prevent the usb controller X * from hanging during initialization. X */ X /dts-v1/; X /memreserve/ 0x84900000 0x00600000; /* 6MB frame buffer */ X / { X /* X * My development unit visually appears to be a Visson ATV-102 X * and the specs for both my unit and the Visson ATV-102 say X * the SoC is an aml8726-m3. However the uboot prompt says X * m6_mbx_v1, the RTC is located on SECBUS2 instead of AOBUS, X * and there are two cores so it seems my unit is a newer X * version using the later processor. X */ X X model = "visson,atv-102"; X compatible = "visson,atv-102", "amlogic,aml8726-m6"; X X #address-cells = <1>; X #size-cells = <1>; X X interrupt-parent = <&gic>; X X aliases { X soc = &soc; X screen = &screen; X uart0 = &uart0; X }; X X cpus { X #address-cells = <1>; X #size-cells = <0>; X X cpu@0 { X device_type = "cpu"; X compatible = "arm,cortex-a9"; X reg = <0x0>; X }; X X cpu@1 { X device_type = "cpu"; X compatible = "arm,cortex-a9"; X reg = <0x1>; X }; X }; X X memory { X device_type = "memory"; X reg = <0x80000000 0x40000000>; /* 1GB RAM */ X }; X X soc: soc@c0000000 { X device_type = "soc"; X compatible = "simple-bus"; X bus-frequency = <0>; X X #address-cells = <1>; X #size-cells = <1>; X X ranges = <0x0 0xc0000000 0x1a100000>; X X pic: pic@1109a40 { X device_type = "interrupt-controller"; X compatible = "amlogic,aml8726-pic"; X reg = <0x1109a40 128>; /* cbus 0x2690 */ X X interrupt-controller; X #interrupt-cells = <1>; X }; X X gic: gic@4301000 { X device_type = "interrupt-controller"; X compatible = "arm,gic"; X reg = <0x4301000 0x1000>, // distributer registers X <0x4300100 0x0100>; // CPU if registers X X interrupt-controller; X #interrupt-cells = <1>; X }; X X scu: scu@4300000 { X compatible = "arm,cortex-a9-scu"; X reg = <0x4300000 0x1000>; X }; X X cpuconfig: cpuconfig@1901ff80 { X compatible = "amlogic,aml8726-cpuconfig"; X reg = <0x1901ff80 8>; X }; X X pl310@4200000 { X compatible = "arm,pl310"; X reg = <0x4200000 0x1000>; X interrupts = <61>; /* AM_IRQ1(29) */ X interrupt-parent = <&gic>; X }; X X watchdog@1109900 { X compatible = "amlogic,aml8726-wdt"; X reg = <0x1109900 8>; /* cbus 0x2640 */ X interrupts = <0>; /* AM_IRQ0(0) */ X interrupt-parent = <&gic>; X }; X X timer@1109940 { X compatible = "amlogic,aml8726-timer"; X reg = <0x1109940 24>; /* cbus 0x2650 */ X interrupts = <10 /* AM_IRQ0(10) */ X 11 /* AM_IRQ0(11) */ X 6 /* AM_IRQ0(6) */ X 29>; /* AM_IRQ0(29) */ X interrupt-parent = <&gic>; X }; X X rtc@1a004340 { X compatible = "amlogic,aml8726-rtc"; X reg = <0x1a004340 20>; /* secbus2 0xd0 */ X interrupts = <72>; /* AM_IRQ2(8) */ X interrupt-parent = <&gic>; X X init-always = "false"; X xo-init = <0x180a>; X gpo-init = <0x500000>; X }; X X clkmsr: clkmsr@1108758 { X compatible = "amlogic,aml8726-clkmsr"; X reg = <0x1108758 16>; /* cbus 0x21d6 */ X }; X X uart0: uart@81004c0 { X /* uart-ao */ X device_type = "serial"; X compatible = "amlogic,aml8726-uart"; X clock-frequency = <0>; X current-speed = <115200>; X reg = <0x81004c0 20>; /* aobus 0x130 */ X interrupts = <90>; /* AM_IRQ2(26) */ X interrupt-parent = <&gic>; X }; X X gpioao: gpio@8100024 { X /* gpio unit 7 */ X compatible = "amlogic,aml8726-gpio"; X reg = <0x8100024 4>, /* oen aobus 0x9 */ X <0x8100024 4>, /* out */ X <0x8100028 4>; /* in */ X X gpio-controller; X #gpio-cells = <1>; X pin-count = <12>; X }; X X gpio5: gpio@110806c { X compatible = "amlogic,aml8726-gpio"; X reg = <0x110806c 4>, /* oen cbus 0x201b */ X <0x1108070 4>, /* out */ X <0x1108074 4>; /* in */ X X gpio-controller; X #gpio-cells = <1>; X pin-count = <32>; X }; X X gpio6: gpio@1108020 { X compatible = "amlogic,aml8726-gpio"; X reg = <0x1108020 4>, /* oen cbus 0x2008 */ X <0x1108024 4>, /* out */ X <0x1108028 4>; /* in */ X X gpio-controller; X #gpio-cells = <1>; X pin-count = <29>; X }; X X mmc@1108c20 { X compatible = "amlogic,aml8726-mmc"; X reg = <0x1108c20 32>; /* cbus 0x2308 */ X interrupts = <28>; /* AM_IRQ0(28) */ X interrupt-parent = <&gic>; X X mmc-pwr-en = <&gpio5 31 0>; /* card8 */ X ins-detect = <&gpio5 29 0>; /* card6 */ X }; X X rng@1108100 { X compatible = "amlogic,aml8726-rng"; X reg = <0x1108100 8>; /* cbus 0x2040 */ X }; X X usb-phy@1108400 { X /* usb-a phy */ X compatible = "amlogic,aml8726-m6-usb-phy"; X reg = <0x1108400 32>; /* cbus 0x2100 */ X }; X X usb-phy@1108420 { X /* usb-b phy */ X compatible = "amlogic,aml8726-m6-usb-phy"; X reg = <0x1108420 32>; /* cbus 0x2108 */ X X usb-pwr-en = <&gpioao 3 1>, /* gpioao3 vbus */ X <&gpio6 11 0>; /* gpioe11 wifi */ X }; X X usb@9040000 { X /* usb-a */ X compatible = "synopsys,designware-hs-otg2"; X reg = <0x9040000 0x40000>; /* ahbbus 0x40000*/ X interrupts = <30>; /* AM_IRQ0(30) */ X interrupt-parent = <&gic>; X #address-cells = <1>; X #size-cells = <0>; X }; X X usb@90c0000 { X /* usb-b */ X compatible = "synopsys,designware-hs-otg2"; X reg = <0x90c0000 0x40000>; /* ahbbus 0xc0000 */ X interrupts = <31>; /* AM_IRQ0(31) */ X interrupt-parent = <&gic>; X #address-cells = <1>; X #size-cells = <0>; X X dr_mode = "host"; X }; X X eth@9410000 { X /* ethernet */ X compatible = "snps,dwmac"; X reg = <0x9410000 0x2000>; /* ahbbus 0x410000 */ X interrupts = <8>; /* AM_IRQ0(8) */ X interrupt-parent = <&gic>; X #address-cells = <1>; X #size-cells = <0>; X }; X X screen: fb@8006324 { X device_type = "display"; X compatible = "amlogic,aml8726-fb"; X reg = <0x8006324 12>, /* CANVAS */ X <0x1106800 1024>, /* VIU */ X <0x1107400 1024>; /* VPP */ X interrupts = <2 /* AM_IRQ0(2) */ X 3 /* AM_IRQ0(3) */ X 12 /* AM_IRQ0(12) */ X 13>; /* AM_IRQ0(13) */ X interrupt-parent = <&gic>; X /* status = "disabled"; */ X X address = <0x84900000>; /* match memreserve */ X width = <720>; X height = <480>; X depth = <24>; X linebytes = <2160>; X }; X }; X X chosen { X stdin = "uart0"; X stdout = "uart0"; X }; }; SHAR_EOF (set 20 15 02 01 16 23 26 'sys/boot/fdt/dts/arm/vsatv102-m6.dts' eval "${shar_touch}") && \ chmod 0644 'sys/boot/fdt/dts/arm/vsatv102-m6.dts' if test $? -ne 0 then ${echo} "restore of sys/boot/fdt/dts/arm/vsatv102-m6.dts failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/boot/fdt/dts/arm/vsatv102-m6.dts': 'MD5 check failed' ) << \SHAR_EOF 9887238fdfa88920899b8012eddcecfe sys/boot/fdt/dts/arm/vsatv102-m6.dts SHAR_EOF else test `LC_ALL=C wc -c < 'sys/boot/fdt/dts/arm/vsatv102-m6.dts'` -ne 7657 && \ ${echo} "restoration warning: size of 'sys/boot/fdt/dts/arm/vsatv102-m6.dts' is not 7657" fi fi # ============= sys/arm/conf/ODROIDC1 ============== if test ! -d 'sys/arm'; then mkdir 'sys/arm' if test $? -eq 0 then ${echo} "x - created directory sys/arm." else ${echo} "x - failed to create directory sys/arm." exit 1 fi fi if test ! -d 'sys/arm/conf'; then mkdir 'sys/arm/conf' if test $? -eq 0 then ${echo} "x - created directory sys/arm/conf." else ${echo} "x - failed to create directory sys/arm/conf." exit 1 fi fi if test -n "${keep_file}" && test -f 'sys/arm/conf/ODROIDC1' then ${echo} "x - SKIPPING sys/arm/conf/ODROIDC1 (file already exists)" else ${echo} "x - extracting sys/arm/conf/ODROIDC1 (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/conf/ODROIDC1' && # ODROIDC1 -- Custom configuration for the HardKernel ODROID-C1 SBC # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ X ident ODROIDC1 X include "../amlogic/aml8726/std.odroidc1" X options HZ=100 options SCHED_4BSD # 4BSD scheduler options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. options KBD_INSTALL_CDEV # install a CDEV entry in /dev options LINUX_BOOT_ABI options VFP # vfp/neon X # Debugging makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options ALT_BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages options BOOTVERBOSE=1 options KDB options DDB # Enable the kernel debugger options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS options WITNESS # Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC X # NFS support #options NFSCL # New Network Filesystem Client #options NFSLOCKD # Network Lock Manager #options NFS_ROOT # NFS usable as /, requires NFSCL X # NFS root from boopt/dhcp #options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=axe0 X # MMC/SD/SDIO card slot support device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards X # Boot device is 2nd slice on MMC/SD card options ROOTDEVNAME=\"ufs:mmcsd0s2\" X # GPIO device gpio device gpioled X # I2C support #device iicbb #device iicbus X # vt is the default console driver, resembling an SCO console device vt #device kbdmux X # Serial (COM) ports device uart # Generic UART driver X # Pseudo devices. device loop # Network loopback device random # Entropy device device ether # Ethernet support device pty # BSD-style compatibility pseudo ttys X # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. #device bpf # Berkeley packet filter X # USB support device usb # General USB code (mandatory for USB) device dwcotg # DWC OTG controller options USB_HOST_ALIGN=64 # Cacheline size is 64 options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE X #device ukbd # USB keyboard #device ums # USB mouse X device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device umass # Disks/Mass storage - Requires scbus and da X # Ethernet support device miibus # MII bus support X # SoC Ethernet, requires miibus #device dwc X # USB Ethernet, requires miibus device axe # ASIX Electronics USB Ethernet X # Flattened Device Tree options FDT options FDT_DTB_STATIC SHAR_EOF (set 20 15 02 01 17 26 05 'sys/arm/conf/ODROIDC1' eval "${shar_touch}") && \ chmod 0644 'sys/arm/conf/ODROIDC1' if test $? -ne 0 then ${echo} "restore of sys/arm/conf/ODROIDC1 failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/conf/ODROIDC1': 'MD5 check failed' ) << \SHAR_EOF ca28f6cc5a0f343ae42d2c3d5c166fd4 sys/arm/conf/ODROIDC1 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/conf/ODROIDC1'` -ne 4235 && \ ${echo} "restoration warning: size of 'sys/arm/conf/ODROIDC1' is not 4235" fi fi # ============= sys/arm/conf/VSATV102 ============== if test ! -d 'sys/arm/conf'; then mkdir 'sys/arm/conf' if test $? -eq 0 then ${echo} "x - created directory sys/arm/conf." else ${echo} "x - failed to create directory sys/arm/conf." exit 1 fi fi if test -n "${keep_file}" && test -f 'sys/arm/conf/VSATV102' then ${echo} "x - SKIPPING sys/arm/conf/VSATV102 (file already exists)" else ${echo} "x - extracting sys/arm/conf/VSATV102 (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/conf/VSATV102' && # VSATV102 -- Custom configuration for the Visson ATV-102 media player # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ X ident VSATV102 X include "../amlogic/aml8726/std.vsatv102-m6" X options HZ=100 options SCHED_4BSD # 4BSD scheduler options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. options KBD_INSTALL_CDEV # install a CDEV entry in /dev options LINUX_BOOT_ABI options VFP # vfp/neon X # Debugging makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options ALT_BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages options BOOTVERBOSE=1 options KDB options DDB # Enable the kernel debugger options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS options WITNESS # Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC X # NFS support #options NFSCL # New Network Filesystem Client #options NFSLOCKD # Network Lock Manager #options NFS_ROOT # NFS usable as /, requires NFSCL X # NFS root from boopt/dhcp #options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=axe0 X # MMC/SD/SDIO card slot support device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards X # Boot device is 2nd slice on MMC/SD card options ROOTDEVNAME=\"ufs:mmcsd0s2\" X # GPIO device gpio #device gpioled X # I2C support #device iicbb #device iicbus X # vt is the default console driver, resembling an SCO console device vt #device kbdmux X # Serial (COM) ports device uart # Generic UART driver X # Pseudo devices. device loop # Network loopback device random # Entropy device device ether # Ethernet support device pty # BSD-style compatibility pseudo ttys X # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. #device bpf # Berkeley packet filter X # USB support device usb # General USB code (mandatory for USB) device dwcotg # DWC OTG controller options USB_HOST_ALIGN=64 # Cacheline size is 64 options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE X #device ukbd # USB keyboard #device ums # USB mouse X device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device umass # Disks/Mass storage - Requires scbus and da X # Ethernet support device miibus # MII bus support X # SoC Ethernet, requires miibus #device dwc X # USB Ethernet, requires miibus device axe # ASIX Electronics USB Ethernet X # Flattened Device Tree options FDT options FDT_DTB_STATIC SHAR_EOF (set 20 15 02 01 17 25 57 'sys/arm/conf/VSATV102' eval "${shar_touch}") && \ chmod 0644 'sys/arm/conf/VSATV102' if test $? -ne 0 then ${echo} "restore of sys/arm/conf/VSATV102 failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/conf/VSATV102': 'MD5 check failed' ) << \SHAR_EOF 179b20ad75e9892a7a6c39811b401806 sys/arm/conf/VSATV102 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/conf/VSATV102'` -ne 4242 && \ ${echo} "restoration warning: size of 'sys/arm/conf/VSATV102' is not 4242" fi fi # ============= sys/arm/amlogic/aml8726/README.txt ============== if test ! -d 'sys/arm/amlogic'; then mkdir 'sys/arm/amlogic' if test $? -eq 0 then ${echo} "x - created directory sys/arm/amlogic." else ${echo} "x - failed to create directory sys/arm/amlogic." exit 1 fi fi if test ! -d 'sys/arm/amlogic/aml8726'; then mkdir 'sys/arm/amlogic/aml8726' if test $? -eq 0 then ${echo} "x - created directory sys/arm/amlogic/aml8726." else ${echo} "x - failed to create directory sys/arm/amlogic/aml8726." exit 1 fi fi if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/README.txt' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/README.txt (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/README.txt (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/README.txt' && PatchJLW01 provides the necessary changes to the FreeBSD 11.0-CURRENT r278021 source tree which along with the additional source code accompanying this file allows FreeBSD to be built for various Amlogic ARM based SoC devices. X Currently FreeBSD successfully boots to the login prompt on an aml8726-m6 board (the box seems to be some type of Visson ATV-102) as well as on an aml8726-m8b board (a Hardkernel ODROID-C1) using a SD card and a serial console. X The following support is included: X X Basic machdep code X X SMP X X Interrupt controller X X Timer X X Real time clock X X UART X X GPIO X X SD card X X USB X X Watchdog X X Random number generator X X PLL / Clock frequency measurement X X Frame buffer X There's also drivers for the I2C and the aml8726-m3 USB PHYS hardware in my private source tree which are currently untested ... I plan to release them at some point once I've actually tested them. X The MAC appears to be the DWC ... it shows slight signs of life on the Visson ATV-102, however fails to reset on the ODROID-C1. Further investigation is needed. X The u-boot sequence I use for the Visson ATV-102 is: X X video dev open 480p X mmc rescan 0 X fatload mmc 0 0x80100000 kernel.bin X go 0x80100000 X The u-boot sequence I use for the Hardkernel ODROID-C1 is: X X video dev open 480p X fatload mmc 0 0x100000 kernel.bin X go 0x100000 X The current FreeBSD driver doesn't program the video clocks so the u-boot video commands are necessary in order for the frame buffer to be useful (otherwise they can be skipped). X The SD card for the Visson ATV-102 doesn't need anything special beyond creating a FAT16 and a UFS filesystem. X The SD card for the ODROID-C1 also needs to contain the Hardkernel bootloader as well as u-boot ... sd_freebsd_odroidc1.sh can be used to prep the card. I obtained the bootloader and u-boot from the boot subdirectory of ArchLinuxARM-odroid-c1-latest.tar.gz which is available at: X X http://archlinuxarm.org/developers/downloads X The u-boot source code is available at: X X https://github.com/hardkernel/u-boot/tree/odroidc-v2011.03/ X which also contains a prebuilt bootloader in the sd_fuse subdirectory ... however currently there's no prebuilt u-boot present. X The frame buffer driver is very rudimentary. X Currently the MMC driver occasionally times out ... it may simply be due to the particular SD card I'm using or be due to a bug in the driver. The problem seems to go away when things are power cycled. X The RTC currently doesn't survive a reboot and on the ODROID-C1 requires the battery to be installed. X Enjoy, X John Wehle john@feith.com SHAR_EOF (set 20 15 02 01 17 33 01 'sys/arm/amlogic/aml8726/README.txt' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/README.txt' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/README.txt failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/README.txt': 'MD5 check failed' ) << \SHAR_EOF c50bb0f5959f490c79bbf6feacea5bc0 sys/arm/amlogic/aml8726/README.txt SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/README.txt'` -ne 2581 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/README.txt' is not 2581" fi fi # ============= sys/arm/amlogic/aml8726/PatchJLW01 ============== if test ! -d 'sys/arm/amlogic/aml8726'; then mkdir 'sys/arm/amlogic/aml8726' if test $? -eq 0 then ${echo} "x - created directory sys/arm/amlogic/aml8726." else ${echo} "x - failed to create directory sys/arm/amlogic/aml8726." exit 1 fi fi if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/PatchJLW01' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/PatchJLW01 (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/PatchJLW01 (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/PatchJLW01' && Index: sys/sys/random.h =================================================================== --- sys/sys/random.h (revision 278021) +++ sys/sys/random.h (working copy) @@ -65,6 +65,7 @@ X RANDOM_PURE_NEHEMIAH, X RANDOM_PURE_RNDTEST, X RANDOM_PURE_VIRTIO, + RANDOM_PURE_AML8726, X ENTROPYSOURCE X }; X void random_harvest(const void *, u_int, u_int, enum random_entropy_source); Index: sys/arm/arm/gic.c =================================================================== --- sys/arm/arm/gic.c (revision 278021) +++ sys/arm/arm/gic.c (working copy) @@ -98,6 +98,11 @@ X #define GICD_ICFGR_TRIG_EDGE (1 << 1) X #define GICD_ICFGR_TRIG_MASK 0x2 X +#ifndef GIC_DEFAULT_ICFGR_INIT +/* Set all global interrupts to be level triggered, active low. */ +# define GIC_DEFAULT_ICFGR_INIT 0x00000000 +#endif + X struct arm_gic_softc { X device_t gic_dev; X struct resource * gic_res[3]; @@ -278,9 +283,8 @@ X icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf, X (icciidr & 0xfff), sc->nirqs); X - /* Set all global interrupts to be level triggered, active low. */ X for (i = 32; i < sc->nirqs; i += 16) { - gic_d_write_4(sc, GICD_ICFGR(i >> 4), 0x00000000); + gic_d_write_4(sc, GICD_ICFGR(i >> 4), GIC_DEFAULT_ICFGR_INIT); X } X X /* Disable all interrupts. */ Index: sys/conf/options.arm =================================================================== --- sys/conf/options.arm (revision 278021) +++ sys/conf/options.arm (working copy) @@ -24,6 +24,7 @@ X CPU_XSCALE_IXP435 opt_global.h X CPU_XSCALE_PXA2X0 opt_global.h X FLASHADDR opt_global.h +GIC_DEFAULT_ICFGR_INIT opt_global.h X IPI_IRQ_START opt_smp.h X IPI_IRQ_END opt_smp.h X FREEBSD_BOOT_LOADER opt_global.h Index: sys/dev/mmc/mmc.c =================================================================== --- sys/dev/mmc/mmc.c (revision 278021) +++ sys/dev/mmc/mmc.c (working copy) @@ -1797,6 +1797,7 @@ X }; X static devclass_t mmc_devclass; X +DRIVER_MODULE(mmc, aml8726_mmc, mmc_driver, mmc_devclass, NULL, NULL); X DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL); X DRIVER_MODULE(mmc, sdhci_bcm, mmc_driver, mmc_devclass, NULL, NULL); X DRIVER_MODULE(mmc, sdhci_fdt, mmc_driver, mmc_devclass, NULL, NULL); Index: sys/dev/random/random_harvestq.c =================================================================== --- sys/dev/random/random_harvestq.c (revision 278021) +++ sys/dev/random/random_harvestq.c (working copy) @@ -218,6 +218,8 @@ X "PURE_RDRAND", X "PURE_NEHEMIAH", X "PURE_RNDTEST", + "PURE_VIRTIO", + "PURE_AML8726", X /* "ENTROPYSOURCE" */ X }; X Index: sys/dev/uart/uart.h =================================================================== --- sys/dev/uart/uart.h (revision 278021) +++ sys/dev/uart/uart.h (working copy) @@ -64,6 +64,7 @@ X */ X struct uart_class; X +extern struct uart_class uart_aml8726_class __attribute__((weak)); X extern struct uart_class uart_imx_class __attribute__((weak)); X extern struct uart_class uart_msm_class __attribute__((weak)); X extern struct uart_class uart_ns8250_class __attribute__((weak)); Index: sys/dev/uart/uart_bus_fdt.c =================================================================== --- sys/dev/uart/uart_bus_fdt.c (revision 278021) +++ sys/dev/uart/uart_bus_fdt.c (working copy) @@ -70,6 +70,7 @@ X * highest-numbers / most recent models should probably appear earlier. X */ X static struct ofw_compat_data compat_data[] = { + {"amlogic,aml8726-uart",(uintptr_t)&uart_aml8726_class}, X {"arm,pl011", (uintptr_t)&uart_pl011_class}, X {"atmel,at91rm9200-usart",(uintptr_t)&at91_usart_class}, X {"atmel,at91sam9260-usart",(uintptr_t)&at91_usart_class}, SHAR_EOF (set 20 15 02 01 00 46 36 'sys/arm/amlogic/aml8726/PatchJLW01' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/PatchJLW01' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/PatchJLW01 failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/PatchJLW01': 'MD5 check failed' ) << \SHAR_EOF db3e865088bb1b1226938a26e08edb75 sys/arm/amlogic/aml8726/PatchJLW01 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/PatchJLW01'` -ne 3583 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/PatchJLW01' is not 3583" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_clkmsr.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_clkmsr.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_clkmsr.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c' && /*- X * Copyright 2014-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X */ X /* X * Amlogic aml8726 clock measurement driver. X * X * This allows various clock rates to be determine at runtime. X * The measurements are done once and are not expected to change X * (i.e. FDT fixup provides clk81 as bus-frequency to the MMC X * and UART drivers which use the value when programming the X * hardware). X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include X #include #include #include X #include #include #include X #include X X static struct aml8726_clkmsr_clk { X const char * name; X uint32_t mux; } aml8726_clkmsr_clks[] = { { "sys pll", 2 }, { "ddr pll", 3 }, { "misc pll", 4 }, { "audio pll", 5 }, { "video pll", 6 }, { "clk81", 7 } }; X #define AML_CLKMSR_SYS_PLL 0 #define AML_CLKMSR_DDR_PLL 1 #define AML_CLKMSR_MISC_PLL 2 #define AML_CLKMSR_AUD_PLL 3 #define AML_CLKMSR_VID_PLL 4 #define AML_CLKMSR_CLK81 5 X #define AML_CLKMSR_NCLKS (sizeof(aml8726_clkmsr_clks) \ X / sizeof(aml8726_clkmsr_clks[0])) X struct aml8726_clkmsr_softc { X device_t dev; X struct resource * res[1]; }; X static struct resource_spec aml8726_clkmsr_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { -1, 0 } }; X /* X * Duration can range from 1uS to 65535 uS and should be chosen X * based on the expected frequency result so to maximize resolution X * and avoid overflowing the 16 bit result counter. X */ #define AML_CLKMSR_DURATION 32 X #define AML_CLKMSR_DUTY_REG 0 #define AML_CLKMSR_0_REG 4 # define AML_CLKMSR_0_BUSY (1U << 31) # define AML_CLKMSR_0_MUX_MASK (0x3f << 20) # define AML_CLKMSR_0_MUX_SHIFT 20 # define AML_CLKMSR_0_MUX_EN (1 << 19) # define AML_CLKMSR_0_MEASURE (1 << 16) # define AML_CLKMSR_0_DURATION_MASK 0xffff # define AML_CLKMSR_0_DURATION_SHIFT 0 #define AML_CLKMSR_1_REG 8 #define AML_CLKMSR_2_REG 12 # define AML_CLKMSR_2_RESULT_MASK 0xffff # define AML_CLKMSR_2_RESULT_SHIFT 0 X #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) #define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X X static int aml8726_clkmsr_clock_frequency(struct aml8726_clkmsr_softc *sc, unsigned clock) { X uint32_t value; X X if (clock >= AML_CLKMSR_NCLKS) X return (0); X X /* X * Locking is not used as this is only expected to be called from X * FDT fixup (which occurs prior to driver initialization) or attach. X */ X X CSR_WRITE_4(sc, AML_CLKMSR_0_REG, 0); X X CSR_BARRIER(sc, AML_CLKMSR_0_REG); X X value = (aml8726_clkmsr_clks[clock].mux << AML_CLKMSR_0_MUX_SHIFT) X | ((AML_CLKMSR_DURATION - 1) << AML_CLKMSR_0_DURATION_SHIFT) X | AML_CLKMSR_0_MUX_EN X | AML_CLKMSR_0_MEASURE; X CSR_WRITE_4(sc, AML_CLKMSR_0_REG, value); X X CSR_BARRIER(sc, AML_CLKMSR_0_REG); X X while ((CSR_READ_4(sc, AML_CLKMSR_0_REG) & AML_CLKMSR_0_BUSY) != 0) X cpu_spinwait(); X X value &= ~AML_CLKMSR_0_MEASURE; X CSR_WRITE_4(sc, AML_CLKMSR_0_REG, value); X X CSR_BARRIER(sc, AML_CLKMSR_0_REG); X X value = (((CSR_READ_4(sc, AML_CLKMSR_2_REG) & AML_CLKMSR_2_RESULT_MASK) X >> AML_CLKMSR_2_RESULT_SHIFT) + AML_CLKMSR_DURATION / 2) X / AML_CLKMSR_DURATION; X X return value; } X X static int aml8726_clkmsr_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-clkmsr")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 clkmsr"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_clkmsr_attach(device_t dev) { X struct aml8726_clkmsr_softc *sc = device_get_softc(dev); X int freq; X X sc->dev = dev; X X if (bus_alloc_resources(dev, aml8726_clkmsr_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X freq = aml8726_clkmsr_clock_frequency(sc, AML_CLKMSR_CLK81); X device_printf(sc->dev, "bus clock %u MHz\n", freq); X X return (0); } X X static int aml8726_clkmsr_detach(device_t dev) { X struct aml8726_clkmsr_softc *sc = device_get_softc(dev); X X bus_release_resources(dev, aml8726_clkmsr_spec, sc->res); X X return (0); } X X static device_method_t aml8726_clkmsr_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_clkmsr_probe), X DEVMETHOD(device_attach, aml8726_clkmsr_attach), X DEVMETHOD(device_detach, aml8726_clkmsr_detach), X X DEVMETHOD_END }; X static driver_t aml8726_clkmsr_driver = { X "clkmsr", X aml8726_clkmsr_methods, X sizeof(struct aml8726_clkmsr_softc), }; X static devclass_t aml8726_clkmsr_devclass; X DRIVER_MODULE(clkmsr, simplebus, aml8726_clkmsr_driver, aml8726_clkmsr_devclass, 0, 0); X X int aml8726_clkmsr_bus_frequency() { X phandle_t node; X u_long pbase, psize; X u_long start, size; X struct resource mem; X struct aml8726_clkmsr_softc sc; X int freq; X X /* X * Try to access the clkmsr node directly i.e. through /aliases/. X */ X X if ((node = OF_finddevice("clkmsr")) != 0) X if (fdt_is_compatible_strict(node, "amlogic,aml8726-clkmsr")) X goto moveon; X X /* X * Find the node the long way. X */ X if ((node = OF_finddevice("/soc")) == 0) X return (0); X X if ((node = fdt_find_compatible(node, X "amlogic,aml8726-clkmsr", 1)) == 0) X return (0); X moveon: X if (fdt_get_range(OF_parent(node), 0, &pbase, &psize) != 0 X || fdt_regsize(node, &start, &size) != 0) X return (0); X X start += pbase; X X memset(&mem, 0, sizeof(mem)); X X mem.r_bustag = fdtbus_bs_tag; X X if (bus_space_map(mem.r_bustag, start, size, 0, &mem.r_bushandle) != 0) X return (0); X X /* X * Build an incomplete (however sufficient for the purpose X * of calling aml8726_clkmsr_clock_frequency) softc. X */ X X memset(&sc, 0, sizeof(sc)); X X sc.res[0] = &mem; X X freq = aml8726_clkmsr_clock_frequency(&sc, AML_CLKMSR_CLK81) X * 1000000; X X bus_space_unmap(mem.r_bustag, mem.r_bushandle, size); X X return (freq); } SHAR_EOF (set 20 15 01 31 13 34 44 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_clkmsr.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c': 'MD5 check failed' ) << \SHAR_EOF 6c1e226807f9c0f86ac18c98376e5844 sys/arm/amlogic/aml8726/aml8726_clkmsr.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c'` -ne 7513 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c' is not 7513" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_clkmsr.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_clkmsr.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_clkmsr.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h' && /*- X * Copyright 2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X #ifndef _ARM_AMLOGIC_AML8726_CLKMSR_H #define _ARM_AMLOGIC_AML8726_CLKMSR_H X X int aml8726_clkmsr_bus_frequency(void); X X #endif /* _ARM_AMLOGIC_AML8726_CLKMSR_H */ SHAR_EOF (set 20 14 01 10 00 35 47 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_clkmsr.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h': 'MD5 check failed' ) << \SHAR_EOF 4621fea948d68056c474ca5547bdf8bf sys/arm/amlogic/aml8726/aml8726_clkmsr.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h'` -ne 1545 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h' is not 1545" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_fb.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_fb.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_fb.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_fb.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_fb.c' && /*- X * Copyright 2013-2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 frame buffer driver. X * X * The current implementation has limited flexibility. X * For example only progressive scan is supported when X * using HDMI and the resolution / frame rate is not X * negotiated. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include X #include X #include #include #include X #include #include #include X #include #include X #include X #include "fb_if.h" X X enum aml8726_fb_output { aml8726_unknown_fb_output, X aml8726_cvbs_fb_output, X aml8726_hdmi_fb_output, X aml8726_lcd_fb_output }; X struct aml8726_fb_clk { X uint32_t freq; X uint32_t video_pre; X uint32_t video_post; X uint32_t video_x; X uint32_t hdmi_tx; X uint32_t encp; X uint32_t enci; X uint32_t enct; X uint32_t encl; X uint32_t vdac0; X uint32_t vdac1; }; X struct aml8726_fb_softc { X device_t dev; X struct resource *res[4]; X struct mtx mtx; X void *ih_cookie; X struct fb_info info; X enum aml8726_fb_output output; X struct aml8726_fb_clk clk; }; X static struct resource_spec aml8726_fb_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* CANVAS */ X { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* VIU */ X { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* VPP */ X { SYS_RES_IRQ, 1, RF_ACTIVE }, /* INT_VIU_VSYNC */ X { -1, 0 } }; X #define AML_FB_LOCK(sc) mtx_lock(&(sc)->mtx) #define AML_FB_UNLOCK(sc) mtx_unlock(&(sc)->mtx) #define AML_FB_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "fb", MTX_DEF) #define AML_FB_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); X #define CAV_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define CAV_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) #define CAV_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X #define VIU_WRITE_4(sc, reg, val) bus_write_4((sc)->res[1], reg, (val)) #define VIU_READ_4(sc, reg) bus_read_4((sc)->res[1], reg) X #define VPP_WRITE_4(sc, reg, val) bus_write_4((sc)->res[2], reg, (val)) #define VPP_READ_4(sc, reg) bus_read_4((sc)->res[2], reg) X #define CLK_WRITE_4(sc, reg, val) bus_write_4((sc)->res[X], reg, (val)) #define CLK_READ_4(sc, reg) bus_read_4((sc)->res[X], reg) X #define AML_FB_CLK_FREQ_SD 1080 #define AML_FB_CLK_FREQ_HD 1488 X X static void aml8726_fb_cfg_output(struct aml8726_fb_softc *sc) { /* XXX */ } X X static void aml8726_fb_cfg_video(struct aml8726_fb_softc *sc) { X uint32_t value; X X /* X * basic initialization X * X * The fifo depth is in units of 8 so programming 32 X * sets the depth to 256. X */ X X value = (32 << AML_VIU_OSD_FIFO_CTRL_DEPTH_SHIFT); X value |= AML_VIU_OSD_FIFO_CTRL_BURST_LEN_64; X value |= (4 << AML_VIU_OSD_FIFO_CTRL_HOLD_LINES_SHIFT); X X VIU_WRITE_4(sc, AML_VIU_OSD1_FIFO_CTRL_REG, value); X VIU_WRITE_4(sc, AML_VIU_OSD2_FIFO_CTRL_REG, value); X X value = VPP_READ_4(sc, AML_VPP_MISC_REG); X X value &= ~AML_VPP_MISC_PREBLEND_EN; X value |= AML_VPP_MISC_POSTBLEND_EN; X value &= ~(AML_VPP_MISC_OSD1_POSTBLEND | AML_VPP_MISC_OSD2_POSTBLEND X | AML_VPP_MISC_VD1_POSTBLEND | AML_VPP_MISC_VD2_POSTBLEND); X X VPP_WRITE_4(sc, AML_VPP_MISC_REG, value); X X value = AML_VIU_OSD_CTRL_OSD_EN; X value |= (0xff << AML_VIU_OSD_CTRL_GLOBAL_ALPHA_SHIFT); X X VIU_WRITE_4(sc, AML_VIU_OSD1_CTRL_REG, value); X VIU_WRITE_4(sc, AML_VIU_OSD2_CTRL_REG, value); X X /* color mode for OSD1 block 0 */ X X value = (AML_CAV_OSD1_INDEX << AML_VIU_OSD_BLK_CFG_W0_INDEX_SHIFT) X | AML_VIU_OSD_BLK_CFG_W0_LITTLE_ENDIAN X | AML_VIU_OSD_BLK_CFG_W0_BLKMODE_24 X | AML_VIU_OSD_BLK_CFG_W0_RGB_EN X | AML_VIU_OSD_BLK_CFG_W0_CMATRIX_RGB; X X VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W0_REG, value); X X /* geometry / scaling for OSD1 block 0 */ X X value = ((sc->info.fb_width - 1) << AML_VIU_OSD_BLK_CFG_W1_X_END_SHIFT) X & AML_VIU_OSD_BLK_CFG_W1_X_END_MASK; X value |= (0 << AML_VIU_OSD_BLK_CFG_W1_X_START_SHIFT) X & AML_VIU_OSD_BLK_CFG_W1_X_START_MASK; X X VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W1_REG, value); X X value = ((sc->info.fb_height - 1) << AML_VIU_OSD_BLK_CFG_W2_Y_END_SHIFT) X & AML_VIU_OSD_BLK_CFG_W2_Y_END_MASK; X value |= (0 << AML_VIU_OSD_BLK_CFG_W2_Y_START_SHIFT) X & AML_VIU_OSD_BLK_CFG_W2_Y_START_MASK; X X VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W2_REG, value); X X value = ((sc->info.fb_width - 1) << AML_VIU_OSD_BLK_CFG_W3_H_END_SHIFT) X & AML_VIU_OSD_BLK_CFG_W3_H_END_MASK; X value |= (0 << AML_VIU_OSD_BLK_CFG_W3_H_START_SHIFT) X & AML_VIU_OSD_BLK_CFG_W3_H_START_MASK; X X VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W3_REG, value); X X value = ((sc->info.fb_height - 1) << AML_VIU_OSD_BLK_CFG_W4_V_END_SHIFT) X & AML_VIU_OSD_BLK_CFG_W4_V_END_MASK; X value |= (0 << AML_VIU_OSD_BLK_CFG_W4_V_START_SHIFT) X & AML_VIU_OSD_BLK_CFG_W4_V_START_MASK; X X VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W4_REG, value); X X /* Enable the OSD block now that it's fully configured */ X X value = VIU_READ_4(sc, AML_VIU_OSD1_CTRL_REG); X X value &= ~AML_VIU_OSD_CTRL_OSD_BLK_EN_MASK; X value |= 1 << AML_VIU_OSD_CTRL_OSD_BLK_EN_SHIFT; X X VIU_WRITE_4(sc, AML_VIU_OSD1_CTRL_REG, value); X X /* enable video processing of OSD1 */ X X value = VPP_READ_4(sc, AML_VPP_MISC_REG); X X value |= AML_VPP_MISC_OSD1_POSTBLEND; X X VPP_WRITE_4(sc, AML_VPP_MISC_REG, value); } X X static void aml8726_fb_cfg_canvas(struct aml8726_fb_softc *sc) { X uint32_t value; X uint32_t width; X X /* X * The frame buffer address and width are programmed in units of 8 X * (meaning they need to be aligned and the actual values divided X * by 8 prior to programming the hardware). X */ X X width = (uint32_t)sc->info.fb_stride / 8; X X /* lower bits of the width */ X value = (width << AML_CAV_LUT_DATAL_WIDTH_SHIFT) X & AML_CAV_LUT_DATAL_WIDTH_MASK; X X /* physical address */ X value |= (uint32_t)sc->info.fb_pbase / 8; X X CAV_WRITE_4(sc, AML_CAV_LUT_DATAL_REG, value); X X /* upper bits of the width */ X value = ((width >> AML_CAV_LUT_DATAL_WIDTH_WIDTH) X << AML_CAV_LUT_DATAH_WIDTH_SHIFT) X & AML_CAV_LUT_DATAH_WIDTH_MASK; X X /* height */ X value |= ((uint32_t)sc->info.fb_height X << AML_CAV_LUT_DATAH_HEIGHT_SHIFT) X & AML_CAV_LUT_DATAH_HEIGHT_MASK; X X /* mode */ X value |= AML_CAV_LUT_DATAH_BLKMODE_LINEAR; X X CAV_WRITE_4(sc, AML_CAV_LUT_DATAH_REG, value); X X CAV_WRITE_4(sc, AML_CAV_LUT_ADDR_REG, X (AML_CAV_LUT_ADDR_WR_EN X | (AML_CAV_OSD1_INDEX << AML_CAV_LUT_ADDR_INDEX_SHIFT))); X X CAV_BARRIER(sc, AML_CAV_LUT_ADDR_REG); } X X static void aml8726_fb_intr(void *arg) { X struct aml8726_fb_softc *sc = (struct aml8726_fb_softc *)arg; X X AML_FB_LOCK(sc); X X AML_FB_UNLOCK(sc); } X X static int aml8726_fb_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-fb")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 FB"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_fb_attach(device_t dev) { X struct aml8726_fb_softc *sc = device_get_softc(dev); X int error; X device_t child; X pcell_t prop; X phandle_t node; X X sc->dev = dev; X X sc->info.fb_name = device_get_nameunit(sc->dev); X X node = ofw_bus_get_node(dev); X X if (OF_getencprop(node, "width", &prop, sizeof(prop)) <= 0) { X device_printf(dev, "missing width attribute in FDT\n"); X return (ENXIO); X } X if ((prop % 8) != 0) { X device_printf(dev, X "width attribute in FDT must be a multiple of 8\n"); X return (ENXIO); X } X sc->info.fb_width = prop; X X if (OF_getencprop(node, "height", &prop, sizeof(prop)) <= 0) { X device_printf(dev, "missing height attribute in FDT\n"); X return (ENXIO); X } X sc->info.fb_height = prop; X X if (OF_getencprop(node, "depth", &prop, sizeof(prop)) <= 0) { X device_printf(dev, "missing depth attribute in FDT\n"); X return (ENXIO); X } X if (prop != 24) { X device_printf(dev, X "depth attribute in FDT is an unsupported value\n"); X return (ENXIO); X } X sc->info.fb_depth = prop; X sc->info.fb_bpp = prop; X X if (OF_getencprop(node, "linebytes", &prop, sizeof(prop)) <= 0) { X device_printf(dev, "missing linebytes attribute in FDT\n"); X return (ENXIO); X } X if ((prop % 8) != 0) { X device_printf(dev, X "linebytes attribute in FDT must be a multiple of 8\n"); X return (ENXIO); X } X if (prop < (sc->info.fb_width * 3)) { X device_printf(dev, X "linebytes attribute in FDT is too small\n"); X return (ENXIO); X } X sc->info.fb_stride = prop; X X if (OF_getencprop(node, "address", &prop, sizeof(prop)) <= 0) { X device_printf(dev, "missing address attribute in FDT\n"); X return (ENXIO); X } X if ((prop % 8) != 0) { X device_printf(dev, X "address attribute in FDT must be a multiple of 8\n"); X return (ENXIO); X } X sc->info.fb_pbase = prop; X sc->info.fb_size = sc->info.fb_height * sc->info.fb_stride; X sc->info.fb_vbase = (intptr_t)pmap_mapdev(sc->info.fb_pbase, sc->info.fb_size); X X if (bus_alloc_resources(dev, aml8726_fb_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size); X return (ENXIO); X } X X aml8726_fb_cfg_output(sc); X X aml8726_fb_cfg_video(sc); X X aml8726_fb_cfg_canvas(sc); X X AML_FB_LOCK_INIT(sc); X X error = bus_setup_intr(dev, sc->res[3], INTR_TYPE_MISC | INTR_MPSAFE, X NULL, aml8726_fb_intr, sc, &sc->ih_cookie); X X if (error) { X device_printf(dev, "could not setup interrupt handler\n"); X goto fail; X } X X child = device_add_child(dev, "fbd", device_get_unit(dev)); X X if (!child) { X device_printf(dev, "could not add fbd\n"); X error = ENXIO; X goto fail; X } X X error = device_probe_and_attach(child); X X if (error) { X device_printf(dev, "could not attach fbd\n"); X goto fail; X } X X return (0); X fail: X if (sc->ih_cookie) X bus_teardown_intr(dev, sc->res[3], sc->ih_cookie); X X AML_FB_LOCK_DESTROY(sc); X X bus_release_resources(dev, aml8726_fb_spec, sc->res); X X pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size); X X return (error); } X X static int aml8726_fb_detach(device_t dev) { X struct aml8726_fb_softc *sc = device_get_softc(dev); X X bus_generic_detach(dev); X X bus_teardown_intr(dev, sc->res[3], sc->ih_cookie); X X AML_FB_LOCK_DESTROY(sc); X X bus_release_resources(dev, aml8726_fb_spec, sc->res); X X pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size); X X return (0); } X X static struct fb_info * aml8726_fb_getinfo(device_t dev) { X struct aml8726_fb_softc *sc = device_get_softc(dev); X X return (&sc->info); } X X static device_method_t aml8726_fb_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_fb_probe), X DEVMETHOD(device_attach, aml8726_fb_attach), X DEVMETHOD(device_detach, aml8726_fb_detach), X X /* FB interface */ X DEVMETHOD(fb_getinfo, aml8726_fb_getinfo), X X DEVMETHOD_END }; X static driver_t aml8726_fb_driver = { X "fb", X aml8726_fb_methods, X sizeof(struct aml8726_fb_softc), }; X static devclass_t aml8726_fb_devclass; X DRIVER_MODULE(fb, simplebus, aml8726_fb_driver, aml8726_fb_devclass, 0, 0); SHAR_EOF (set 20 15 01 31 23 58 06 'sys/arm/amlogic/aml8726/aml8726_fb.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_fb.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_fb.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_fb.c': 'MD5 check failed' ) << \SHAR_EOF 9f3165d44a5cfbf7fc0dfa9346bd5be4 sys/arm/amlogic/aml8726/aml8726_fb.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_fb.c'` -ne 12374 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_fb.c' is not 12374" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_fb.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_fb.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_fb.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_fb.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_fb.h' && /*- X * Copyright 2013-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X #ifndef _ARM_AMLOGIC_AML8726_FB_H #define _ARM_AMLOGIC_AML8726_FB_H X X #define AML_CAV_OSD1_INDEX 0x40 X #define AML_CAV_LUT_DATAL_REG 0 # define AML_CAV_LUT_DATAL_WIDTH_MASK (7 << 29) # define AML_CAV_LUT_DATAL_WIDTH_SHIFT 29 # define AML_CAV_LUT_DATAL_WIDTH_WIDTH 3 # define AML_CAV_LUT_DATAL_ADDR_MASK 0x1fffffff # define AML_CAV_LUT_DATAL_ADDR_SHIFT 0 X #define AML_CAV_LUT_DATAH_REG 4 # define AML_CAV_LUT_DATAH_BLKMODE_MASK (3 << 24) # define AML_CAV_LUT_DATAH_BLKMODE_SHIFT 24 # define AML_CAV_LUT_DATAH_BLKMODE_LINEAR (0 << 24) # define AML_CAV_LUT_DATAH_BLKMODE_32x32 (1 << 24) # define AML_CAV_LUT_DATAH_BLKMODE_64x32 (2 << 24) # define AML_CAV_LUT_DATAH_WRAP_X (1 << 23) # define AML_CAV_LUT_DATAH_WRAP_Y (1 << 22) # define AML_CAV_LUT_DATAH_HEIGHT_MASK (0x1fff << 9) # define AML_CAV_LUT_DATAH_HEIGHT_SHIFT 9 # define AML_CAV_LUT_DATAH_WIDTH_MASK 0x1ff # define AML_CAV_LUT_DATAH_WIDTH_SHIFT 0 X #define AML_CAV_LUT_ADDR_REG 8 # define AML_CAV_LUT_ADDR_WR_EN (1 << 9) # define AML_CAV_LUT_ADDR_RD_EN (1 << 8) # define AML_CAV_LUT_ADDR_INDEX_MASK 0xff # define AML_CAV_LUT_ADDR_INDEX_SHIFT 0 X X #define AML_VIU_OSD1_CTRL_REG 64 # define AML_VIU_OSD_CTRL_OSD_EN (1 << 21) # define AML_VIU_OSD_CTRL_GLOBAL_ALPHA_MASK (0x1ff << 12) # define AML_VIU_OSD_CTRL_GLOBAL_ALPHA_SHIFT 12 # define AML_VIU_OSD_CTRL_OSD_BLK_EN_MASK (0xf << 0) # define AML_VIU_OSD_CTRL_OSD_BLK_EN_SHIFT 0 X #define AML_VIU_OSD1_BLK0_CFG_W0_REG 108 #define AML_VIU_OSD1_BLK1_CFG_W0_REG 124 #define AML_VIU_OSD1_BLK2_CFG_W0_REG 140 #define AML_VIU_OSD1_BLK3_CFG_W0_REG 156 # define AML_VIU_OSD_BLK_CFG_W0_INDEX_MASK (0xff << 16) # define AML_VIU_OSD_BLK_CFG_W0_INDEX_SHIFT 16 # define AML_VIU_OSD_BLK_CFG_W0_LITTLE_ENDIAN (1 << 15) # define AML_VIU_OSD_BLK_CFG_W0_BLKMODE_24 (7 << 8) # define AML_VIU_OSD_BLK_CFG_W0_RGB_EN (1 << 7) # define AML_VIU_OSD_BLK_CFG_W0_CMATRIX_RGB (0 << 2) X #define AML_VIU_OSD1_BLK0_CFG_W1_REG 112 #define AML_VIU_OSD1_BLK1_CFG_W1_REG 128 #define AML_VIU_OSD1_BLK2_CFG_W1_REG 144 #define AML_VIU_OSD1_BLK3_CFG_W1_REG 160 # define AML_VIU_OSD_BLK_CFG_W1_X_END_MASK (0x1fff << 16) # define AML_VIU_OSD_BLK_CFG_W1_X_END_SHIFT 16 # define AML_VIU_OSD_BLK_CFG_W1_X_START_MASK 0x1fff # define AML_VIU_OSD_BLK_CFG_W1_X_START_SHIFT 0 X #define AML_VIU_OSD1_BLK0_CFG_W2_REG 116 #define AML_VIU_OSD1_BLK1_CFG_W2_REG 132 #define AML_VIU_OSD1_BLK2_CFG_W2_REG 148 #define AML_VIU_OSD1_BLK3_CFG_W2_REG 164 # define AML_VIU_OSD_BLK_CFG_W2_Y_END_MASK (0x1fff << 16) # define AML_VIU_OSD_BLK_CFG_W2_Y_END_SHIFT 16 # define AML_VIU_OSD_BLK_CFG_W2_Y_START_MASK 0x1fff # define AML_VIU_OSD_BLK_CFG_W2_Y_START_SHIFT 0 X #define AML_VIU_OSD1_BLK0_CFG_W3_REG 120 #define AML_VIU_OSD1_BLK1_CFG_W3_REG 136 #define AML_VIU_OSD1_BLK2_CFG_W3_REG 152 #define AML_VIU_OSD1_BLK3_CFG_W3_REG 168 # define AML_VIU_OSD_BLK_CFG_W3_H_END_MASK (0xfff << 16) # define AML_VIU_OSD_BLK_CFG_W3_H_END_SHIFT 16 # define AML_VIU_OSD_BLK_CFG_W3_H_START_MASK 0xfff # define AML_VIU_OSD_BLK_CFG_W3_H_START_SHIFT 0 X #define AML_VIU_OSD1_BLK0_CFG_W4_REG 76 #define AML_VIU_OSD1_BLK1_CFG_W4_REG 80 #define AML_VIU_OSD1_BLK2_CFG_W4_REG 84 #define AML_VIU_OSD1_BLK3_CFG_W4_REG 88 # define AML_VIU_OSD_BLK_CFG_W4_V_END_MASK (0xfff << 16) # define AML_VIU_OSD_BLK_CFG_W4_V_END_SHIFT 16 # define AML_VIU_OSD_BLK_CFG_W4_V_START_MASK 0xfff # define AML_VIU_OSD_BLK_CFG_W4_V_START_SHIFT 0 X #define AML_VIU_OSD1_FIFO_CTRL_REG 172 # define AML_VIU_OSD_FIFO_CTRL_DEPTH_MASK (0x3f << 12) # define AML_VIU_OSD_FIFO_CTRL_DEPTH_SHIFT 12 # define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_MASK (3 << 10) # define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_24 (0 << 10) # define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_32 (1 << 10) # define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_48 (2 << 10) # define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_64 (3 << 10) # define AML_VIU_OSD_FIFO_CTRL_HOLD_LINES_MASK (0x1f << 5) # define AML_VIU_OSD_FIFO_CTRL_HOLD_LINES_SHIFT 5 # define AML_VIU_OSD_FIFO_CTRL_URGENT (1 << 0) X /* OSD2 field meanings are the same as OSD1 */ #define AML_VIU_OSD2_CTRL_REG 192 #define AML_VIU_OSD2_BLK0_CFG_W0_REG 236 #define AML_VIU_OSD2_BLK1_CFG_W0_REG 252 #define AML_VIU_OSD2_BLK2_CFG_W0_REG 268 #define AML_VIU_OSD2_BLK3_CFG_W0_REG 284 #define AML_VIU_OSD2_BLK0_CFG_W1_REG 240 #define AML_VIU_OSD2_BLK1_CFG_W1_REG 256 #define AML_VIU_OSD2_BLK2_CFG_W1_REG 272 #define AML_VIU_OSD2_BLK3_CFG_W1_REG 288 #define AML_VIU_OSD2_BLK0_CFG_W2_REG 244 #define AML_VIU_OSD2_BLK1_CFG_W2_REG 260 #define AML_VIU_OSD2_BLK2_CFG_W2_REG 276 #define AML_VIU_OSD2_BLK3_CFG_W2_REG 292 #define AML_VIU_OSD2_BLK0_CFG_W3_REG 248 #define AML_VIU_OSD2_BLK1_CFG_W3_REG 264 #define AML_VIU_OSD2_BLK2_CFG_W3_REG 280 #define AML_VIU_OSD2_BLK3_CFG_W3_REG 296 #define AML_VIU_OSD2_BLK0_CFG_W4_REG 400 #define AML_VIU_OSD2_BLK1_CFG_W4_REG 404 #define AML_VIU_OSD2_BLK2_CFG_W4_REG 408 #define AML_VIU_OSD2_BLK3_CFG_W4_REG 412 #define AML_VIU_OSD2_FIFO_CTRL_REG 300 X X #define AML_VPP_MISC_REG 152 # define AML_VPP_MISC_OSD2_PREBLEND (1 << 17) # define AML_VPP_MISC_OSD1_PREBLEND (1 << 16) # define AML_VPP_MISC_VD2_PREBLEND (1 << 15) # define AML_VPP_MISC_VD1_PREBLEND (1 << 14) # define AML_VPP_MISC_OSD2_POSTBLEND (1 << 13) # define AML_VPP_MISC_OSD1_POSTBLEND (1 << 12) # define AML_VPP_MISC_VD2_POSTBLEND (1 << 11) # define AML_VPP_MISC_VD1_POSTBLEND (1 << 10) # define AML_VPP_MISC_POSTBLEND_EN (1 << 7) # define AML_VPP_MISC_PREBLEND_EN (1 << 6) X X #endif /* _ARM_AMLOGIC_AML8726_FB_H */ SHAR_EOF (set 20 15 01 27 00 24 04 'sys/arm/amlogic/aml8726/aml8726_fb.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_fb.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_fb.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_fb.h': 'MD5 check failed' ) << \SHAR_EOF 6178aab540480a82269cab1be884a456 sys/arm/amlogic/aml8726/aml8726_fb.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_fb.h'` -ne 7953 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_fb.h' is not 7953" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_gpio.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_gpio.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_gpio.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_gpio.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_gpio.c' && /*- X * Copyright 2013-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 GPIO driver. X * X * Note: The OEN register is active * low *. Setting a bit to zero X * enables the output driver, setting a bit to one disables the driver. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include X #include X #include X #include #include #include X #include X #include "gpio_if.h" X X struct aml8726_gpio_softc { X device_t dev; X struct resource *res[3]; X struct mtx mtx; X uint32_t npins; X device_t busdev; }; X static struct resource_spec aml8726_gpio_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE }, /* oen */ X { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_SHAREABLE }, /* output */ X { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* input */ X { -1, 0 } }; X #define AML_GPIO_LOCK(sc) mtx_lock(&(sc)->mtx) #define AML_GPIO_UNLOCK(sc) mtx_unlock(&(sc)->mtx) #define AML_GPIO_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "gpio", MTX_DEF) #define AML_GPIO_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); X #define AML_GPIO_OE_N_REG 0 #define AML_GPIO_OUT_REG 1 #define AML_GPIO_IN_REG 2 X #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[reg], 0, (val)) #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[reg], 0) X X static int aml8726_gpio_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-gpio")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 GPIO"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_gpio_attach(device_t dev) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X phandle_t node; X pcell_t prop; X X sc->dev = dev; X X node = ofw_bus_get_node(dev); X X if (OF_getencprop(node, "pin-count", X &prop, sizeof(prop)) <= 0) { X device_printf(dev, "missing pin-count attribute in FDT\n"); X return (ENXIO); X } X sc->npins = prop; X X if (sc->npins > 32) X return (ENXIO); X X if (bus_alloc_resources(dev, aml8726_gpio_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X /* X * The GPIOAO OUT bits occupy the upper word of the OEN register. X */ X if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0])) X if (sc->npins > 16) { X device_printf(dev, X "too many pins for overlapping OEN and OUT\n"); X bus_release_resources(dev, aml8726_gpio_spec, sc->res); X return (ENXIO); X } X X AML_GPIO_LOCK_INIT(sc); X X sc->busdev = gpiobus_attach_bus(dev); X if (sc->busdev == NULL) { X AML_GPIO_LOCK_DESTROY(sc); X bus_release_resources(dev, aml8726_gpio_spec, sc->res); X return (ENXIO); X } X X OF_device_register_xref(OF_xref_from_node(node), dev); X X return (0); } X X static int aml8726_gpio_detach(device_t dev) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X phandle_t node; X X node = ofw_bus_get_node(dev); X OF_device_register_xref(OF_xref_from_node(node), NULL); X X gpiobus_detach_bus(dev); X X AML_GPIO_LOCK_DESTROY(sc); X X bus_release_resources(dev, aml8726_gpio_spec, sc->res); X X return (0); } X X static device_t aml8726_gpio_get_bus(device_t dev) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X X return (sc->busdev); } X X static int aml8726_gpio_pin_max(device_t dev, int *maxpin) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X X *maxpin = (int)sc->npins; X X return (0); } X X /* Get a specific pin's capabilities. */ static int aml8726_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X X if (pin >= sc->npins) X return (EINVAL); X X *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT); X X return (0); } X X /* Get a specific pin's name. */ static int aml8726_gpio_pin_getname(device_t dev, uint32_t pin, char *name) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X X if (pin >= sc->npins) X return (EINVAL); X X snprintf(name, GPIOMAXNAME, "%s.%u", ofw_bus_get_name(dev), pin); X X return (0); } X X /* Get a specific pin's current in/out state. */ static int aml8726_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X uint32_t mask = 1U << pin; X X if (pin >= sc->npins) X return (EINVAL); X X if ((CSR_READ_4(sc, AML_GPIO_OE_N_REG) & mask) == 0) { X /* output */ X *flags = GPIO_PIN_OUTPUT; X } else X /* input */ X *flags = GPIO_PIN_INPUT; X X return (0); } X X /* Set a specific pin's in/out state. */ static int aml8726_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X uint32_t mask = 1U << pin; X X if (pin >= sc->npins) X return (EINVAL); X X AML_GPIO_LOCK(sc); X X if ((flags & GPIO_PIN_OUTPUT) != 0) { X /* Output. Turn on driver. */ X CSR_WRITE_4(sc, AML_GPIO_OE_N_REG, X (CSR_READ_4(sc, AML_GPIO_OE_N_REG) & ~mask)); X } else { X /* Input. Turn off driver. */ X CSR_WRITE_4(sc, AML_GPIO_OE_N_REG, X (CSR_READ_4(sc, AML_GPIO_OE_N_REG) | mask)); X } X X AML_GPIO_UNLOCK(sc); X X return (0); } X X /* Set a specific output pin's value. */ static int aml8726_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X uint32_t mask; X X if (pin >= sc->npins || value > 1) X return (EINVAL); X X /* X * The GPIOAO OUT bits occupy the upper word of the OEN register. X */ X if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0])) X pin += 16; X X mask = 1U << pin; X X AML_GPIO_LOCK(sc); X X CSR_WRITE_4(sc, AML_GPIO_OUT_REG, X ((CSR_READ_4(sc, AML_GPIO_OUT_REG) & ~mask) X | (value << pin))); X X AML_GPIO_UNLOCK(sc); X X return (0); } X X /* Get a specific pin's input value. */ static int aml8726_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X uint32_t mask = 1U << pin; X X if (pin >= sc->npins) X return (EINVAL); X X *value = (CSR_READ_4(sc, AML_GPIO_IN_REG) & mask) ? 1 : 0; X X return (0); } X X /* Toggle a pin's output value. */ static int aml8726_gpio_pin_toggle(device_t dev, uint32_t pin) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); X uint32_t mask; X X if (pin >= sc->npins) X return (EINVAL); X X /* X * The GPIOAO OUT bits occupy the upper word of the OEN register. X */ X if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0])) X pin += 16; X X mask = 1U << pin; X X AML_GPIO_LOCK(sc); X X CSR_WRITE_4(sc, AML_GPIO_OUT_REG, X CSR_READ_4(sc, AML_GPIO_OUT_REG) ^ mask); X X AML_GPIO_UNLOCK(sc); X X return (0); } X X static phandle_t aml8726_gpio_get_node(device_t bus, device_t dev) { X X /* We only have one child, the GPIO bus, which needs our own node. */ X return (ofw_bus_get_node(bus)); } X X static device_method_t aml8726_gpio_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_gpio_probe), X DEVMETHOD(device_attach, aml8726_gpio_attach), X DEVMETHOD(device_detach, aml8726_gpio_detach), X X /* GPIO interface */ X DEVMETHOD(gpio_get_bus, aml8726_gpio_get_bus), X DEVMETHOD(gpio_pin_max, aml8726_gpio_pin_max), X DEVMETHOD(gpio_pin_getname, aml8726_gpio_pin_getname), X DEVMETHOD(gpio_pin_getflags, aml8726_gpio_pin_getflags), X DEVMETHOD(gpio_pin_getcaps, aml8726_gpio_pin_getcaps), X DEVMETHOD(gpio_pin_setflags, aml8726_gpio_pin_setflags), X DEVMETHOD(gpio_pin_get, aml8726_gpio_pin_get), X DEVMETHOD(gpio_pin_set, aml8726_gpio_pin_set), X DEVMETHOD(gpio_pin_toggle, aml8726_gpio_pin_toggle), X X /* ofw_bus interface */ X DEVMETHOD(ofw_bus_get_node, aml8726_gpio_get_node), X X DEVMETHOD_END }; X static driver_t aml8726_gpio_driver = { X "gpio", X aml8726_gpio_methods, X sizeof(struct aml8726_gpio_softc), }; X static devclass_t aml8726_gpio_devclass; X DRIVER_MODULE(aml8726_gpio, simplebus, aml8726_gpio_driver, aml8726_gpio_devclass, 0, 0); SHAR_EOF (set 20 15 01 31 21 59 01 'sys/arm/amlogic/aml8726/aml8726_gpio.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_gpio.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_gpio.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_gpio.c': 'MD5 check failed' ) << \SHAR_EOF d2e37f869f8d947a2b5ed9b9eee5a036 sys/arm/amlogic/aml8726/aml8726_gpio.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_gpio.c'` -ne 9263 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_gpio.c' is not 9263" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_identsoc.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_identsoc.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_identsoc.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_identsoc.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_identsoc.c' && /*- X * Copyright 2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X */ X /* X * Amlogic aml8726 SoC identification. X * X * The SoC identification is used by some of the drivers in order to X * handle hardware differences so the identification needs to happen X * early in the boot process (e.g. before SMP startup). X * X * It's expected that the register addresses for identifying the SoC X * are set in stone. X * X * Currently missing an entry for the aml8726-m and doesn't distinguish X * between the m801, m802, m805, s802, s805, and s812 which are all X * variations of the aml8726-m8. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include X #include #include X #include X X uint32_t aml8726_soc_hw_rev = 0xffffffff; uint32_t aml8726_soc_metal_rev = 0xffffffff; X static const struct { X uint32_t hw_rev; X char *desc; } aml8726_soc_desc[] = { X { AML_SOC_HW_REV_M3, "aml8726-m3" }, X { AML_SOC_HW_REV_M6, "aml8726-m6" }, X { AML_SOC_HW_REV_M6TV, "aml8726-m6tv" }, X { AML_SOC_HW_REV_M6TVL, "aml8726-m6tvl" }, X { AML_SOC_HW_REV_M8, "aml8726-m8" }, X { AML_SOC_HW_REV_M6TVD, "aml8726-m6tvd" }, X { AML_SOC_HW_REV_M8B, "aml8726-m8b" }, X { 0xff, NULL } }; X static const struct { X uint32_t metal_rev; X char *desc; } aml8726_m8_soc_rev[] = { X { AML_SOC_M8_METAL_REV_A, "A" }, X { AML_SOC_M8_METAL_REV_M2_A, "MarkII A" }, X { AML_SOC_M8_METAL_REV_B, "B" }, X { AML_SOC_M8_METAL_REV_C, "C" }, X { 0xff, NULL } }; X X static void aml8726_identify_soc(void *dummy) { X int err; X int i; X struct resource res; X X memset(&res, 0, sizeof(res)); X X res.r_bustag = fdtbus_bs_tag; X X err = bus_space_map(res.r_bustag, AML_SOC_CBUS_BASE_ADDR, 0x100000, X 0, &res.r_bushandle); X X if (err) X panic("Could not allocate resource for SoC identification\n"); X X aml8726_soc_hw_rev = bus_read_4(&res, AML_SOC_HW_REV_REG); X X aml8726_soc_metal_rev = bus_read_4(&res, AML_SOC_METAL_REV_REG); X X bus_space_unmap(res.r_bustag, res.r_bushandle, 0x100000); X X for (i = 0; aml8726_soc_desc[i].desc; i++) X if (aml8726_soc_desc[i].hw_rev == aml8726_soc_hw_rev) X break; X X if (aml8726_soc_desc[i].desc == NULL) X panic("Amlogic unknown aml8726 SoC %#x\n", aml8726_soc_hw_rev); X X printf("Amlogic %s SoC", aml8726_soc_desc[i].desc); X X if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8) { X for (i = 0; aml8726_m8_soc_rev[i].desc; i++) X if (aml8726_m8_soc_rev[i].metal_rev X == aml8726_soc_metal_rev) X break; X X if (aml8726_m8_soc_rev[i].desc == NULL) X printf(", unknown rev %#x", aml8726_soc_metal_rev); X else X printf(", rev %s", aml8726_m8_soc_rev[i].desc); X } X X printf("\n"); } X X SYSINIT(aml8726_identify_soc, X SI_SUB_CPU, SI_ORDER_SECOND, aml8726_identify_soc, NULL); SHAR_EOF (set 20 15 01 27 01 41 50 'sys/arm/amlogic/aml8726/aml8726_identsoc.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_identsoc.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_identsoc.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_identsoc.c': 'MD5 check failed' ) << \SHAR_EOF 05e687c4bd594c040df0019f195c3257 sys/arm/amlogic/aml8726/aml8726_identsoc.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_identsoc.c'` -ne 4240 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_identsoc.c' is not 4240" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_l2cache.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_l2cache.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_l2cache.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_l2cache.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_l2cache.c' && /*- X * Copyright 2013-2015 John Wehle X * All rights reserved. X * X * Based on omap4_l2cache.c by Olivier Houchard X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include X #include #include X X void platform_pl310_init(struct pl310_softc *sc) { X uint32_t aux; X X aux = pl310_read4(sc, PL310_AUX_CTRL); X X /* X * The Amlogic Linux platform code enables via AUX: X * X * Early BRESP X * Full Line of Zero (which must match processor setting) X * Data Prefetch X * X * and additionally on the m6 enables: X * X * Instruction Prefetch X * X * For the moment we only enable Data Prefetch ... X * further refinements can happen as things mature. X */ X X /* X * Disable instruction prefetch. X */ X aux &= ~AUX_CTRL_INSTR_PREFETCH; X X /* X * Enable data prefetch. X */ X aux |= AUX_CTRL_DATA_PREFETCH; X X pl310_write4(sc, PL310_AUX_CTRL, aux); } X X void platform_pl310_write_ctrl(struct pl310_softc *sc, uint32_t val) { X X pl310_write4(sc, PL310_CTRL, val); } X X void platform_pl310_write_debug(struct pl310_softc *sc, uint32_t val) { X X pl310_write4(sc, PL310_DEBUG_CTRL, val); } SHAR_EOF (set 20 15 01 07 15 08 56 'sys/arm/amlogic/aml8726/aml8726_l2cache.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_l2cache.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_l2cache.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_l2cache.c': 'MD5 check failed' ) << \SHAR_EOF 956bf918f06524d8b4a8be2259b42e1d sys/arm/amlogic/aml8726/aml8726_l2cache.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_l2cache.c'` -ne 2574 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_l2cache.c' is not 2574" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_machdep.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_machdep.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_machdep.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_machdep.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_machdep.c' && /*- X * Copyright 2013-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X #include "opt_global.h" X #include __FBSDID("$FreeBSD$"); X #define _ARM32_BUS_DMA_PRIVATE #include #include #include X #include #include X #include #include #include #include X #include X #include X X #if defined(SOCDEV_PA) && defined(SOCDEV_VA) vm_offset_t aml8726_aobus_kva_base = SOCDEV_VA; #else vm_offset_t aml8726_aobus_kva_base; #endif X X static void aml8726_fixup_busfreq() { X phandle_t node, child; X pcell_t freq, prop; X ssize_t len; X X /* X * Set the bus-frequency for any top level SoC simple-bus which X * needs updating (meaning the current frequency is zero). X */ X X if ((freq = aml8726_clkmsr_bus_frequency()) == 0 X || (node = OF_finddevice("/soc")) == 0 X || fdt_is_compatible_strict(node, "simple-bus") == 0) X while (1); X X freq = cpu_to_fdt32(freq); X X len = OF_getencprop(node, "bus-frequency", &prop, sizeof(prop)); X if ((len / sizeof(prop)) == 1 && prop == 0) X OF_setprop(node, "bus-frequency", (void *)&freq, sizeof(freq)); X X for (child = OF_child(node); child != 0; child = OF_peer(child)) X if (fdt_is_compatible_strict(child, "simple-bus")) { X len = OF_getencprop(child, "bus-frequency", X &prop, sizeof(prop)); X if ((len / sizeof(prop)) == 1 && prop == 0) X OF_setprop(child, "bus-frequency", X (void *)&freq, sizeof(freq)); X } } X X vm_offset_t platform_lastaddr(void) { X X return (arm_devmap_lastaddr()); } X X void platform_probe_and_attach(void) { X } X X void platform_gpio_init(void) { X X /* X * The UART console driver used for debugging early boot code X * needs to know the virtual base address of the aobus. It's X * expected to equal SOCDEV_VA prior to initarm calling setttb X * ... afterwards it needs to be updated due to the new page X * tables. X * X * This means there's a deadzone in initarm between setttb X * and platform_gpio_init during which printf can't be used. X */ X aml8726_aobus_kva_base X = (vm_offset_t)arm_devmap_ptov(0xc8100000, 0x100000); X X /* X * This FDT fixup should arguably be called through fdt_fixup_table, X * however currently there's no mechanism to specify a fixup which X * should always be invoked. X * X * It needs to be called prior to the console being initialized which X * is why it's called here, rather than from platform_late_init. X */ X aml8726_fixup_busfreq(); } X X void platform_late_init(void) { X } X X /* X * Construct static devmap entries to map out the core X * peripherals using 1mb section mappings. X */ int platform_devmap_init(void) { X X arm_devmap_add_entry(0xc1100000, 0x200000); /* cbus */ X arm_devmap_add_entry(0xc4200000, 0x100000); /* pl310 */ X arm_devmap_add_entry(0xc4300000, 0x100000); /* periph */ X arm_devmap_add_entry(0xc8000000, 0x100000); /* apbbus */ X arm_devmap_add_entry(0xc8100000, 0x100000); /* aobus */ X arm_devmap_add_entry(0xc9000000, 0x800000); /* ahbbus */ X arm_devmap_add_entry(0xd9000000, 0x100000); /* ahb */ X arm_devmap_add_entry(0xda000000, 0x100000); /* secbus */ X X return (0); } X X struct arm32_dma_range * bus_dma_get_range(void) { X X return (NULL); } X X int bus_dma_get_range_nb(void) { X X return (0); } X X struct fdt_fixup_entry fdt_fixup_table[] = { X { NULL, NULL } }; X X static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, X int *interrupt, int *trig, int *pol) { X X /* X * The single core chips have just an Amlogic PIC. However the X * multi core chips also have a GIC. X */ X if ( #ifdef SMP X !fdt_is_compatible_strict(node, "arm,gic") #else X !fdt_is_compatible_strict(node, "amlogic,aml8726-pic") #endif X ) X return (ENXIO); X X *interrupt = fdt32_to_cpu(intr[0]); X *trig = INTR_TRIGGER_EDGE; X *pol = INTR_POLARITY_HIGH; X X switch (*interrupt) { X case 30: /* INT_USB_A */ X case 31: /* INT_USB_B */ X *trig = INTR_TRIGGER_LEVEL; X break; X default: X break; X } X #ifdef SMP X *interrupt += 32; #endif X X return (0); } X X fdt_pic_decode_t fdt_pic_table[] = { X &fdt_pic_decode_ic, X NULL }; SHAR_EOF (set 20 15 01 31 13 34 32 'sys/arm/amlogic/aml8726/aml8726_machdep.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_machdep.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_machdep.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_machdep.c': 'MD5 check failed' ) << \SHAR_EOF a9622bce52d36b10c2d44f13196b8568 sys/arm/amlogic/aml8726/aml8726_machdep.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_machdep.c'` -ne 5417 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_machdep.c' is not 5417" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_machdep.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_machdep.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_machdep.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_machdep.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_machdep.h' && /*- X * Copyright 2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X #ifndef _ARM_AMLOGIC_AML8726_MACHDEP_H #define _ARM_AMLOGIC_AML8726_MACHDEP_H X X /* X * The aobus kvm base is supplied as a global variable * only * X * for the convience of the aml8726 UART console driver which X * is available for use to debug early boot code. X * X * This variable should not be used elsewhere. X */ extern vm_offset_t aml8726_aobus_kva_base; X X #endif /* _ARM_AMLOGIC_AML8726_MACHDEP_H */ SHAR_EOF (set 20 14 02 12 23 07 12 'sys/arm/amlogic/aml8726/aml8726_machdep.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_machdep.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_machdep.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_machdep.h': 'MD5 check failed' ) << \SHAR_EOF 94f5a11a7c1231b6756d3837120124b6 sys/arm/amlogic/aml8726/aml8726_machdep.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_machdep.h'` -ne 1784 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_machdep.h' is not 1784" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_mmc.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_mmc.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_mmc.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_mmc.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_mmc.c' && /*- X * Copyright 2013-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 MMC host controller driver. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include X #include X #include #include X #include #include #include X #include #include #include X #include X #include "gpio_if.h" #include "mmcbr_if.h" X X struct aml8726_mmc_gpio { X device_t dev; X uint32_t pin; X uint32_t pol; }; X struct aml8726_mmc_softc { X device_t dev; X struct resource *res[2]; X struct mtx mtx; X unsigned int ref_freq; X struct aml8726_mmc_gpio pwr_en; X bus_dma_tag_t dmatag; X bus_dmamap_t dmamap; X void *ih_cookie; X struct mmc_host host; X int bus_busy; X struct mmc_command *cmd; X unsigned int timeout_remaining; }; X static struct resource_spec aml8726_mmc_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { SYS_RES_IRQ, 0, RF_ACTIVE }, X { -1, 0 } }; X #define AML_MMC_LOCK(sc) mtx_lock(&(sc)->mtx) #define AML_MMC_UNLOCK(sc) mtx_unlock(&(sc)->mtx) #define AML_MMC_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "mmc", MTX_DEF) #define AML_MMC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); X #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) #define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X #define PWR_ON_FLAG(pol) ((pol) == 0 \ X ? GPIO_PIN_LOW : GPIO_PIN_HIGH) #define PWR_OFF_FLAG(pol) ((pol) == 0 \ X ? GPIO_PIN_HIGH : GPIO_PIN_LOW) X X static void aml8726_mmc_mapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error) { X bus_addr_t *busaddrp; X X /* X * There should only be one bus space address since X * bus_dma_tag_create was called with nsegments = 1. X */ X X busaddrp = (bus_addr_t *)arg; X *busaddrp = segs->ds_addr; } X X static int aml8726_mmc_restart_timer(struct aml8726_mmc_softc *sc) { X uint32_t count; X uint32_t isr; X X if (sc->cmd == NULL || sc->timeout_remaining == 0) X return (0); X X count = (sc->timeout_remaining > 0x1fff) X ? 0x1fff : sc->timeout_remaining; X sc->timeout_remaining -= count; X X isr = (count << AML_MMC_IRQ_STATUS_TIMER_CNT_SHIFT) X | AML_MMC_IRQ_STATUS_TIMER_EN X | AML_MMC_IRQ_STATUS_TIMEOUT_IRQ; X X CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, isr); X X return (1); } X X static int aml8726_mmc_start_command(struct aml8726_mmc_softc *sc, struct mmc_command *cmd) { X struct mmc_ios *ios = &sc->host.ios; X bus_addr_t baddr; X uint32_t block_size; X uint32_t bus_width; X uint32_t cmdr; X uint32_t cycles_per_usec; X uint32_t extr; X uint32_t mcfgr; X uint32_t nbits_per_pkg; X uint32_t timeout; X int error; X struct mmc_data *data; X X if (cmd->opcode > 0x3f) X return (MMC_ERR_INVALID); X X /* X * Ensure the hardware state machine is in a known state, X * the command done interrupt is enabled, and previous X * IRQ status bits have been cleared. X */ X CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, X (AML_MMC_IRQ_CONFIG_SOFT_RESET X | AML_MMC_IRQ_CONFIG_CMD_DONE_EN)); X CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ); X X /* X * Start and transmission bits are per section 4.7.2 of the: X * X * SD Specifications Part 1 X * Physicaly Layer Simplified Specification X * Version 4.10 X */ X cmdr = AML_MMC_CMD_START_BIT | AML_MMC_CMD_TRANS_BIT_HOST | cmd->opcode; X baddr = 0; X extr = 0; X mcfgr = CSR_READ_4(sc, AML_MMC_MULT_CONFIG_REG) X & AML_MMC_MULT_CONFIG_PORT_MASK; X timeout = AML_MMC_CMD_TIMEOUT; X X if ((cmd->flags & MMC_RSP_136) != 0) { X cmdr |= AML_MMC_CMD_RESP_CRC7_FROM_8; X cmdr |= (133 << AML_MMC_CMD_RESP_BITS_SHIFT); X } else if ((cmd->flags & MMC_RSP_PRESENT) != 0) X cmdr |= (45 << AML_MMC_CMD_RESP_BITS_SHIFT); X X switch (cmd->opcode) { X case MMC_STOP_TRANSMISSION: X cmdr |= AML_MMC_CMD_CHECK_DAT0_BUSY; X break; X case MMC_SEND_OP_COND: X case ACMD_SD_SEND_OP_COND: X cmdr |= AML_MMC_CMD_RESP_NO_CRC7; X break; X default: X break; X } X X data = cmd->data; X X if (data && data->len X && (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) { X block_size = data->len; X X if ((data->flags & MMC_DATA_MULTI) != 0) { X block_size = MMC_SECTOR_SIZE; X if ((data->len % block_size) != 0) X return (MMC_ERR_INVALID); X } X X cmdr |= (((data->len / block_size) - 1) X << AML_MMC_CMD_REP_PKG_CNT_SHIFT); X X mcfgr |= (data->flags & MMC_DATA_STREAM) X ? AML_MMC_MULT_CONFIG_STREAM_EN : 0; X X /* X * The number of bits per package equals the number X * of data bits + the number of CRC bits. There are X * 16 bits of CRC calculate per bus line. X * X * A completed package appears to be detected by when X * a counter decremented by the width underflows, thus X * a value of zero always transfers 1 (or 4 bits depending X * on the mode) which is why bus_width is subtracted. X */ X bus_width = (ios->bus_width == bus_width_4) ? 4 : 1; X nbits_per_pkg = block_size * 8 + 16 * bus_width - bus_width; X if (nbits_per_pkg > 0x3fff) X return (MMC_ERR_INVALID); X X extr |= (nbits_per_pkg << AML_MMC_EXTENSION_PKT_SIZE_SHIFT); X X X error = bus_dmamap_load(sc->dmatag, sc->dmamap, X data->data, data->len, X aml8726_mmc_mapmem, &baddr, X BUS_DMA_NOWAIT); X if (error) X return (MMC_ERR_NO_MEMORY); X X if ((data->flags & MMC_DATA_READ) != 0) { X cmdr |= AML_MMC_CMD_RESP_HAS_DATA; X bus_dmamap_sync(sc->dmatag, sc->dmamap, X BUS_DMASYNC_PREREAD); X timeout = AML_MMC_READ_TIMEOUT X * (data->len / block_size); X } else { X cmdr |= AML_MMC_CMD_CMD_HAS_DATA; X bus_dmamap_sync(sc->dmatag, sc->dmamap, X BUS_DMASYNC_PREWRITE); X timeout = AML_MMC_WRITE_TIMEOUT X * (data->len / block_size); X } X } X X sc->cmd = cmd; X X cmd->error = MMC_ERR_NONE; X X /* X * Round up while calculating the number of cycles which X * correspond to a microsecond. Use that to determine X * the count from the desired timeout in microseconds. X * X * The counter has a limited range which is not sufficient X * for directly implementing worst case timeouts at high clock X * rates so a 32 bit counter is implemented in software. X * X * The documentation isn't clear on when the timer starts X * so add 48 cycles for the command and 136 cycles for the X * response (the values are from the previously mentioned X * standard). X */ X cycles_per_usec = (ios->clock + 1000000 - 1) / 1000000; X sc->timeout_remaining = 48 + 136 + timeout * cycles_per_usec; X X aml8726_mmc_restart_timer(sc); X X CSR_WRITE_4(sc, AML_MMC_CMD_ARGUMENT_REG, cmd->arg); X CSR_WRITE_4(sc, AML_MMC_MULT_CONFIG_REG, mcfgr); X CSR_WRITE_4(sc, AML_MMC_EXTENSION_REG, extr); X CSR_WRITE_4(sc, AML_MMC_DMA_ADDR_REG, (uint32_t)baddr); X CSR_WRITE_4(sc, AML_MMC_CMD_SEND_REG, cmdr); X X return (MMC_ERR_NONE); } X X static void aml8726_mmc_intr(void *arg) { X struct aml8726_mmc_softc *sc = (struct aml8726_mmc_softc *)arg; X uint32_t cmdr; X uint32_t icr; X uint32_t isr; X uint32_t mcfgr; X uint32_t previous_byte; X uint32_t resp; X int mmc_error; X int mmc_stop_error; X unsigned int i; X struct mmc_command *cmd; X struct mmc_command *stop_cmd; X struct mmc_data *data; X X X AML_MMC_LOCK(sc); X X isr = CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG); X X mmc_error = MMC_ERR_NONE; X cmdr = CSR_READ_4(sc, AML_MMC_CMD_SEND_REG); X X if ((isr & AML_MMC_IRQ_STATUS_CMD_DONE_IRQ) != 0) { X /* Check for CRC errors if the command has completed. */ X if ((cmdr & AML_MMC_CMD_RESP_NO_CRC7) == 0 X && (isr & AML_MMC_IRQ_STATUS_RESP_CRC7_OK) == 0) X mmc_error = MMC_ERR_BADCRC; X if ((cmdr & AML_MMC_CMD_RESP_HAS_DATA) != 0 X && (isr & AML_MMC_IRQ_STATUS_RD_CRC16_OK) == 0) X mmc_error = MMC_ERR_BADCRC; X if ((cmdr & AML_MMC_CMD_CMD_HAS_DATA) != 0 X && (isr & AML_MMC_IRQ_STATUS_WR_CRC16_OK) == 0) X mmc_error = MMC_ERR_BADCRC; X } else if ((isr & AML_MMC_IRQ_STATUS_TIMEOUT_IRQ) != 0) { X if (aml8726_mmc_restart_timer(sc) != 0) { X AML_MMC_UNLOCK(sc); X return; X } X mmc_error = MMC_ERR_TIMEOUT; X } else { X X /* X * Clear spurious interrupts while leaving intacted any X * interrupts that may have occurred after we read the X * interrupt status register. X */ X X CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, X (AML_MMC_IRQ_STATUS_CLEAR_IRQ & isr)); X AML_MMC_UNLOCK(sc); X return; X } X X if ((isr & AML_MMC_IRQ_STATUS_CMD_BUSY) != 0) { X if (mmc_error != MMC_ERR_TIMEOUT) X mmc_error = MMC_ERR_FAILED; X X /* X * Issue a soft reset (while leaving the command complete X * interrupt enabled) to terminate the command. X * X * Ensure the command has terminated before continuing on X * to things such as bus_dmamap_sync / bus_dmamap_unload. X */ X X icr = AML_MMC_IRQ_CONFIG_SOFT_RESET X | AML_MMC_IRQ_CONFIG_CMD_DONE_EN; X X CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, icr); X X while ((CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG) X & AML_MMC_IRQ_STATUS_CMD_BUSY) != 0) X cpu_spinwait(); X } X X /* Clear all interrupts since the request is no longer in flight. */ X CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ); X X CSR_BARRIER(sc, AML_MMC_IRQ_STATUS_REG); X X cmd = sc->cmd; X sc->cmd = NULL; X X if (cmd == NULL) { X AML_MMC_UNLOCK(sc); X return; X } X X cmd->error = mmc_error; X X if ((cmd->flags & MMC_RSP_PRESENT) != 0 X && mmc_error == MMC_ERR_NONE) { X mcfgr = CSR_READ_4(sc, AML_MMC_MULT_CONFIG_REG) X & AML_MMC_MULT_CONFIG_PORT_MASK; X mcfgr |= AML_MMC_MULT_CONFIG_RESP_READOUT_EN; X CSR_WRITE_4(sc, AML_MMC_MULT_CONFIG_REG, mcfgr); X X if ((cmd->flags & MMC_RSP_136) != 0) { X X /* X * Controller supplies 135:8 instead of X * 127:0 so discard the leading 8 bits X * and provide a trailing 8 zero bits X * where the CRC belongs. X */ X X previous_byte = 0; X X for (i = 0; i < 4; i++) { X resp = CSR_READ_4(sc, AML_MMC_CMD_ARGUMENT_REG); X cmd->resp[3 - i] = (resp << 8) | previous_byte; X previous_byte = (resp >> 24) & 0xff; X } X } else X cmd->resp[0] = CSR_READ_4(sc, AML_MMC_CMD_ARGUMENT_REG); X } X X data = cmd->data; X X if (data && data->len X && (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) { X if ((data->flags & MMC_DATA_READ) != 0) X bus_dmamap_sync(sc->dmatag, sc->dmamap, X BUS_DMASYNC_POSTREAD); X else X bus_dmamap_sync(sc->dmatag, sc->dmamap, X BUS_DMASYNC_POSTWRITE); X bus_dmamap_unload(sc->dmatag, sc->dmamap); X } X X /* X * If this command was successfully executed and there's X * a linked stop command, then start the stop command. X */ X X stop_cmd = (cmd->mrq->stop != cmd) ? cmd->mrq->stop : NULL; X X if (stop_cmd != NULL && mmc_error == MMC_ERR_NONE) { X mmc_stop_error = aml8726_mmc_start_command(sc, stop_cmd); X if (mmc_stop_error == MMC_ERR_NONE) { X AML_MMC_UNLOCK(sc); X return; X } X stop_cmd->error = mmc_stop_error; X } X X AML_MMC_UNLOCK(sc); X X /* Execute the callback after dropping the lock. */ X if (cmd->mrq) { X cmd->mrq->done(cmd->mrq); X } } X X static int aml8726_mmc_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-mmc")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 MMC"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_mmc_attach(device_t dev) { X struct aml8726_mmc_softc *sc = device_get_softc(dev); X pcell_t prop[3]; X phandle_t node; X ssize_t len; X int error; X device_t child; X X sc->dev = dev; X X node = ofw_bus_get_node(dev); X X len = OF_getencprop(OF_parent(node), "bus-frequency", X prop, sizeof(prop)); X if ((len / sizeof(prop[0])) != 1 || prop[0] == 0) { X device_printf(dev, "missing bus-frequency attribute in FDT\n"); X return (ENXIO); X } X X sc->ref_freq = prop[0]; X X len = OF_getencprop(node, "mmc-pwr-en", prop, sizeof(prop)); X if ((len / sizeof(prop[0])) != 3 X || (sc->pwr_en.dev = OF_device_from_xref(prop[0])) == NULL) { X device_printf(dev, "missing mmc-pwr-en attribute in FDT\n"); X return (ENXIO); X } X X sc->pwr_en.pin = prop[1]; X sc->pwr_en.pol = prop[2]; X X if (bus_alloc_resources(dev, aml8726_mmc_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X /* Turn off power by setting pin and then configuring output driver. */ X if (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PWR_OFF_FLAG(sc->pwr_en.pol)) != 0 X || GPIO_PIN_SETFLAGS(sc->pwr_en.dev, sc->pwr_en.pin, X GPIO_PIN_OUTPUT) != 0) { X device_printf(dev, "could not use gpio to control power\n"); X bus_release_resources(dev, aml8726_mmc_spec, sc->res); X return (ENXIO); X } X X AML_MMC_LOCK_INIT(sc); X X error = bus_dma_tag_create(bus_get_dma_tag(dev), AML_MMC_ALIGN_DMA, 0, X BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, X NULL, NULL, AML_MMC_MAX_DMA, 1, X AML_MMC_MAX_DMA, 0, NULL, NULL, &sc->dmatag); X if (error) X goto fail; X X error = bus_dmamap_create(sc->dmatag, 0, &sc->dmamap); X X if (error) X goto fail; X X error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE, X NULL, aml8726_mmc_intr, sc, &sc->ih_cookie); X if (error) { X device_printf(dev, "could not setup interrupt handler\n"); X goto fail; X } X X sc->host.f_min = 200000; X sc->host.f_max = 50000000; X sc->host.host_ocr = MMC_OCR_330_340; X sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_HSPEED; X X child = device_add_child(dev, "mmc", device_get_unit(dev)); X X if (!child) { X device_printf(dev, "could not add mmc\n"); X error = ENXIO; X goto fail; X } X X error = device_probe_and_attach(child); X X if (error) { X device_printf(dev, "could not attach mmc\n"); X goto fail; X } X X return (0); X fail: X if (sc->ih_cookie) X bus_teardown_intr(dev, sc->res[1], sc->ih_cookie); X X if (sc->dmamap) X bus_dmamap_destroy(sc->dmatag, sc->dmamap); X X if (sc->dmatag) X bus_dma_tag_destroy(sc->dmatag); X X AML_MMC_LOCK_DESTROY(sc); X X (void)GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PWR_OFF_FLAG(sc->pwr_en.pol)); X X bus_release_resources(dev, aml8726_mmc_spec, sc->res); X X return (error); } X X static int aml8726_mmc_detach(device_t dev) { X struct aml8726_mmc_softc *sc = device_get_softc(dev); X X AML_MMC_LOCK(sc); X X if (sc->cmd != NULL) { X AML_MMC_UNLOCK(sc); X return (EBUSY); X } X X /* X * Turn off the power, reset the hardware state machine, X * disable the interrupts, and clear the interrupts. X */ X (void)GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PWR_OFF_FLAG(sc->pwr_en.pol)); X CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, AML_MMC_IRQ_CONFIG_SOFT_RESET); X CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ); X X AML_MMC_UNLOCK(sc); X X bus_generic_detach(dev); X X bus_teardown_intr(dev, sc->res[1], sc->ih_cookie); X X bus_dmamap_destroy(sc->dmatag, sc->dmamap); X X bus_dma_tag_destroy(sc->dmatag); X X AML_MMC_LOCK_DESTROY(sc); X X bus_release_resources(dev, aml8726_mmc_spec, sc->res); X X return (0); } X X static int aml8726_mmc_shutdown(device_t dev) { X struct aml8726_mmc_softc *sc = device_get_softc(dev); X X /* X * Turn off the power, reset the hardware state machine, X * disable the interrupts, and clear the interrupts. X */ X (void)GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PWR_OFF_FLAG(sc->pwr_en.pol)); X CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, AML_MMC_IRQ_CONFIG_SOFT_RESET); X CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ); X X return (0); } X X static int aml8726_mmc_update_ios(device_t bus, device_t child) { X struct aml8726_mmc_softc *sc = device_get_softc(bus); X struct mmc_ios *ios = &sc->host.ios; X int divisor; X int error; X uint32_t cfgr; X X cfgr = (2 << AML_MMC_CONFIG_WR_CRC_STAT_SHIFT) X | (2 << AML_MMC_CONFIG_WR_DELAY_SHIFT) X | AML_MMC_CONFIG_DMA_ENDIAN_SBW X | (39 << AML_MMC_CONFIG_CMD_ARG_BITS_SHIFT); X X switch (ios->bus_width) { X case bus_width_4: X cfgr |= AML_MMC_CONFIG_BUS_WIDTH_4; X break; X case bus_width_1: X cfgr |= AML_MMC_CONFIG_BUS_WIDTH_1; X break; X default: X return (EINVAL); X } X X divisor = sc->ref_freq / (ios->clock * 2) - 1; X if (divisor == 0 || divisor == -1) X divisor = 1; X if ((sc->ref_freq / ((divisor + 1) * 2)) > ios->clock) X divisor += 1; X if (divisor > 0x3ff) X divisor = 0x3ff; X X cfgr |= divisor; X X CSR_WRITE_4(sc, AML_MMC_CONFIG_REG, cfgr); X X error = 0; X X switch (ios->power_mode) { X case power_up: X /* X * This is a NOP since there's no separate regulator to X * configure and power on in advance so that the voltage X * stabilizes prior to powering on the card. X */ X break; X case power_on: X error = GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PWR_ON_FLAG(sc->pwr_en.pol)); X break; X case power_off: X error = GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PWR_OFF_FLAG(sc->pwr_en.pol)); X break; X default: X return (EINVAL); X } X X return (error); } X X static int aml8726_mmc_request(device_t bus, device_t child, struct mmc_request *req) { X struct aml8726_mmc_softc *sc = device_get_softc(bus); X int mmc_error; X X AML_MMC_LOCK(sc); X X if (sc->cmd != NULL) { X AML_MMC_UNLOCK(sc); X return (EBUSY); X } X X mmc_error = aml8726_mmc_start_command(sc, req->cmd); X X AML_MMC_UNLOCK(sc); X X /* Execute the callback after dropping the lock. */ X if (mmc_error != MMC_ERR_NONE) { X req->cmd->error = mmc_error; X req->done(req); X } X X return (0); } X X static int aml8726_mmc_read_ivar(device_t bus, device_t child, X int which, uintptr_t *result) { X struct aml8726_mmc_softc *sc = device_get_softc(bus); X X switch (which) { X case MMCBR_IVAR_BUS_MODE: X *(int *)result = sc->host.ios.bus_mode; X break; X case MMCBR_IVAR_BUS_WIDTH: X *(int *)result = sc->host.ios.bus_width; X break; X case MMCBR_IVAR_CHIP_SELECT: X *(int *)result = sc->host.ios.chip_select; X break; X case MMCBR_IVAR_CLOCK: X *(int *)result = sc->host.ios.clock; X break; X case MMCBR_IVAR_F_MIN: X *(int *)result = sc->host.f_min; X break; X case MMCBR_IVAR_F_MAX: X *(int *)result = sc->host.f_max; X break; X case MMCBR_IVAR_HOST_OCR: X *(int *)result = sc->host.host_ocr; X break; X case MMCBR_IVAR_MODE: X *(int *)result = sc->host.mode; X break; X case MMCBR_IVAR_OCR: X *(int *)result = sc->host.ocr; X break; X case MMCBR_IVAR_POWER_MODE: X *(int *)result = sc->host.ios.power_mode; X break; X case MMCBR_IVAR_VDD: X *(int *)result = sc->host.ios.vdd; X break; X case MMCBR_IVAR_CAPS: X *(int *)result = sc->host.caps; X break; X case MMCBR_IVAR_MAX_DATA: X *(int *)result = AML_MMC_MAX_DMA / MMC_SECTOR_SIZE; X break; X default: X return (EINVAL); X } X X return (0); } X X static int aml8726_mmc_write_ivar(device_t bus, device_t child, X int which, uintptr_t value) { X struct aml8726_mmc_softc *sc = device_get_softc(bus); X X switch (which) { X case MMCBR_IVAR_BUS_MODE: X sc->host.ios.bus_mode = value; X break; X case MMCBR_IVAR_BUS_WIDTH: X sc->host.ios.bus_width = value; X break; X case MMCBR_IVAR_CHIP_SELECT: X sc->host.ios.chip_select = value; X break; X case MMCBR_IVAR_CLOCK: X sc->host.ios.clock = value; X break; X case MMCBR_IVAR_MODE: X sc->host.mode = value; X break; X case MMCBR_IVAR_OCR: X sc->host.ocr = value; X break; X case MMCBR_IVAR_POWER_MODE: X sc->host.ios.power_mode = value; X break; X case MMCBR_IVAR_VDD: X sc->host.ios.vdd = value; X break; X /* These are read-only */ X case MMCBR_IVAR_CAPS: X case MMCBR_IVAR_HOST_OCR: X case MMCBR_IVAR_F_MIN: X case MMCBR_IVAR_F_MAX: X case MMCBR_IVAR_MAX_DATA: X default: X return (EINVAL); X } X X return (0); } X X static int aml8726_mmc_get_ro(device_t bus, device_t child) { X X return (0); } X X static int aml8726_mmc_acquire_host(device_t bus, device_t child) { X struct aml8726_mmc_softc *sc = device_get_softc(bus); X X AML_MMC_LOCK(sc); X X while (sc->bus_busy) X mtx_sleep(sc, &sc->mtx, PZERO, "mmc", hz / 5); X sc->bus_busy++; X X AML_MMC_UNLOCK(sc); X X return (0); } X X static int aml8726_mmc_release_host(device_t bus, device_t child) { X struct aml8726_mmc_softc *sc = device_get_softc(bus); X X AML_MMC_LOCK(sc); X X sc->bus_busy--; X wakeup(sc); X X AML_MMC_UNLOCK(sc); X X return (0); } X X static device_method_t aml8726_mmc_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_mmc_probe), X DEVMETHOD(device_attach, aml8726_mmc_attach), X DEVMETHOD(device_detach, aml8726_mmc_detach), X DEVMETHOD(device_shutdown, aml8726_mmc_shutdown), X X /* Bus interface */ X DEVMETHOD(bus_read_ivar, aml8726_mmc_read_ivar), X DEVMETHOD(bus_write_ivar, aml8726_mmc_write_ivar), X X /* MMC bridge interface */ X DEVMETHOD(mmcbr_update_ios, aml8726_mmc_update_ios), X DEVMETHOD(mmcbr_request, aml8726_mmc_request), X DEVMETHOD(mmcbr_get_ro, aml8726_mmc_get_ro), X DEVMETHOD(mmcbr_acquire_host, aml8726_mmc_acquire_host), X DEVMETHOD(mmcbr_release_host, aml8726_mmc_release_host), X X DEVMETHOD_END }; X static driver_t aml8726_mmc_driver = { X "aml8726_mmc", X aml8726_mmc_methods, X sizeof(struct aml8726_mmc_softc), }; X static devclass_t aml8726_mmc_devclass; X DRIVER_MODULE(aml8726_mmc, simplebus, aml8726_mmc_driver, aml8726_mmc_devclass, 0, 0); MODULE_DEPEND(aml8726_mmc, aml8726_gpio, 1, 1, 1); SHAR_EOF (set 20 15 01 07 00 57 31 'sys/arm/amlogic/aml8726/aml8726_mmc.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_mmc.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_mmc.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_mmc.c': 'MD5 check failed' ) << \SHAR_EOF 5d7161e26539fe1c846e395ab29f81fc sys/arm/amlogic/aml8726/aml8726_mmc.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mmc.c'` -ne 22210 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_mmc.c' is not 22210" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_mmc.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_mmc.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_mmc.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_mmc.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_mmc.h' && /*- X * Copyright 2013-2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X #ifndef _ARM_AMLOGIC_AML8726_MMC_H #define _ARM_AMLOGIC_AML8726_MMC_H X X #define AML_MMC_ALIGN_DMA 4 #define AML_MMC_MAX_DMA 4096 X /* X * Timeouts are in microseconds X * X * Read and write are per section 4.6.2 of the: X * X * SD Specifications Part 1 X * Physicaly Layer Simplified Specification X * Version 4.10 X */ #define AML_MMC_CMD_TIMEOUT 50000 #define AML_MMC_READ_TIMEOUT 100000 #define AML_MMC_WRITE_TIMEOUT 500000 X /* X * Internally the timeout is implemented by counting clock cycles. X * X * Since the hardware implements timeouts by counting cycles X * the minimum read / write timeout (assuming the minimum X * conversion factor of 1 cycle per usec) is: X * X * (8 bits * 512 bytes per block + 16 bits CRC) = 4112 usec X */ #if (AML_MMC_READ_TIMEOUT < 4112 || AML_MMC_WRITE_TIMEOUT < 4112) # error "Single block timeout is smaller than supported" #endif X /* X * Ensure that the worst case timeout can be handled by a 32 bit X * counter assuming a maximum MMC clock of 50 MHz. X */ #if (AML_MMC_MAX_DMA / 512ULL * AML_MMC_READ_TIMEOUT * 50) > 0xffffffffULL \ X || (AML_MMC_MAX_DMA / 512ULL * AML_MMC_WRITE_TIMEOUT * 50) > 0xffffffffULL # error "Multiblock timeout is larger than supported" #endif X #define AML_MMC_CMD_ARGUMENT_REG 0 X #define AML_MMC_CMD_SEND_REG 4 # define AML_MMC_CMD_REP_PKG_CNT_MASK (0xffU << 24) # define AML_MMC_CMD_REP_PKG_CNT_SHIFT 24 # define AML_MMC_CMD_CMD_HAS_DATA (1 << 20) # define AML_MMC_CMD_CHECK_DAT0_BUSY (1 << 19) # define AML_MMC_CMD_RESP_CRC7_FROM_8 (1 << 18) # define AML_MMC_CMD_RESP_HAS_DATA (1 << 17) # define AML_MMC_CMD_RESP_NO_CRC7 (1 << 16) # define AML_MMC_CMD_RESP_BITS_MASK (0xff << 8) # define AML_MMC_CMD_RESP_BITS_SHIFT 8 # define AML_MMC_CMD_START_BIT (0 << 7) # define AML_MMC_CMD_TRANS_BIT_HOST (1 << 6) # define AML_MMC_CMD_INDEX_MASK 0x3f # define AML_MMC_CMD_INDEX_SHIFT 0 X #define AML_MMC_CONFIG_REG 8 # define AML_MMC_CONFIG_WR_CRC_STAT_MASK (7U << 29) # define AML_MMC_CONFIG_WR_CRC_STAT_SHIFT 29 # define AML_MMC_CONFIG_WR_DELAY_MASK (0x3f << 23) # define AML_MMC_CONFIG_WR_DELAY_SHIFT 23 # define AML_MMC_CONFIG_DMA_ENDIAN_MASK (3 << 21) # define AML_MMC_CONFIG_DMA_ENDIAN_NC (0 << 21) # define AML_MMC_CONFIG_DMA_ENDIAN_SB (1 << 21) # define AML_MMC_CONFIG_DMA_ENDIAN_SW (2 << 21) # define AML_MMC_CONFIG_DMA_ENDIAN_SBW (3 << 21) # define AML_MMC_CONFIG_BUS_WIDTH_MASK (1 << 20) # define AML_MMC_CONFIG_BUS_WIDTH_1 (0 << 20) # define AML_MMC_CONFIG_BUS_WIDTH_4 (1 << 20) # define AML_MMC_CONFIG_DATA_NEG_EDGE (1 << 19) # define AML_MMC_CONFIG_DONT_DELAY_DATA (1 << 18) # define AML_MMC_CONFIG_CMD_ARG_BITS_MASK (0x3f << 12) # define AML_MMC_CONFIG_CMD_ARG_BITS_SHIFT 12 # define AML_MMC_CONFIG_CMD_POS_EDGE (1 << 11) # define AML_MMC_CONFIG_CMD_NO_CRC (1 << 10) # define AML_MMC_CONFIG_CMD_CLK_DIV_MASK 0x3ff # define AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT 0 X #define AML_MMC_IRQ_STATUS_REG 12 # define AML_MMC_IRQ_STATUS_TIMER_CNT_MASK (0x1fffU << 19) # define AML_MMC_IRQ_STATUS_TIMER_CNT_SHIFT 19 # define AML_MMC_IRQ_STATUS_TIMER_EN (1 << 18) # define AML_MMC_IRQ_STATUS_TIMEOUT_IRQ (1 << 16) # define AML_MMC_IRQ_STATUS_CMD_DONE_IRQ (1 << 9) # define AML_MMC_IRQ_STATUS_WR_CRC16_OK (1 << 7) # define AML_MMC_IRQ_STATUS_RD_CRC16_OK (1 << 6) # define AML_MMC_IRQ_STATUS_RESP_CRC7_OK (1 << 5) # define AML_MMC_IRQ_STATUS_CMD_BUSY (1 << 4) # define AML_MMC_IRQ_STATUS_CLEAR_IRQ 0x10700 X #define AML_MMC_IRQ_CONFIG_REG 16 # define AML_MMC_IRQ_CONFIG_SOFT_RESET (1 << 15) # define AML_MMC_IRQ_CONFIG_CMD_DONE_EN (1 << 4) X #define AML_MMC_MULT_CONFIG_REG 20 # define AML_MMC_MULT_CONFIG_RESP_INDEX_MASK (0xf << 12) # define AML_MMC_MULT_CONFIG_RESP_INDEX_SHIFT 12 # define AML_MMC_MULT_CONFIG_RESP_READOUT_EN (1 << 8) # define AML_MMC_MULT_CONFIG_STREAM_8_MODE (1 << 5) # define AML_MMC_MULT_CONFIG_STREAM_EN (1 << 4) # define AML_MMC_MULT_CONFIG_PORT_MASK 3 # define AML_MMC_MULT_CONFIG_PORT_A 0 # define AML_MMC_MULT_CONFIG_PORT_B 1 X #define AML_MMC_DMA_ADDR_REG 24 X #define AML_MMC_EXTENSION_REG 28 # define AML_MMC_EXTENSION_NO_CRC16 (1 << 30) # define AML_MMC_EXTENSION_PKT_SIZE_MASK (0x3fff << 16) # define AML_MMC_EXTENSION_PKT_SIZE_SHIFT 16 X X #endif /* _ARM_AMLOGIC_AML8726_MMC_H */ SHAR_EOF (set 20 15 01 27 00 25 00 'sys/arm/amlogic/aml8726/aml8726_mmc.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_mmc.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_mmc.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_mmc.h': 'MD5 check failed' ) << \SHAR_EOF ed9e2b07284232ac4d3a8d47b0fb0b89 sys/arm/amlogic/aml8726/aml8726_mmc.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mmc.h'` -ne 6226 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_mmc.h' is not 6226" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_mp.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_mp.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_mp.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_mp.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_mp.c' && /*- X * Copyright 2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 multiprocessor support. X * X * Some processors require powering on which involves poking registers on X * the aobus and cbus ... it's expected that the location of the aobus and X * cbus is set in stone. X * X * Locking is not used as these routines should only be called by the BP X * during startup and should complete prior to the APs being released (the X * issue being to ensure that a register such as AML_SOC_CPU_CLK_CNTL_REG X * is not concurrently modified). X */ X #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include X #include #include #include #include X #include #include #include X #include X X static const char *scu_compatible[] = { X "arm,cortex-a5-scu", X "arm,cortex-a9-scu", X NULL }; X static const char *scu_errata_764369[] = { X "arm,cortex-a9-scu", X NULL }; X static const char *cpucfg_compatible[] = { X "amlogic,aml8726-cpuconfig", X NULL }; X static struct { X boolean_t errata_764369; X u_long scu_size; X struct resource scu_res; X u_long cpucfg_size; X struct resource cpucfg_res; X struct resource aobus_res; X struct resource cbus_res; } aml8726_smp; X #define AML_SCU_CONTROL_REG 0 # define AML_SCU_CONTROL_ENABLE 1 #define AML_SCU_CONFIG_REG 4 # define AML_SCU_CONFIG_NCPU_MASK 0x3 #define AML_SCU_CPU_PWR_STATUS_REG 8 # define AML_SCU_CPU_PWR_STATUS_CPU3_MASK (3 << 24) # define AML_SCU_CPU_PWR_STATUS_CPU2_MASK (3 << 16) # define AML_SCU_CPU_PWR_STATUS_CPU1_MASK (3 << 8) # define AML_SCU_CPU_PWR_STATUS_CPU0_MASK 3 #define AML_SCU_INV_TAGS_REG 12 #define AML_SCU_DIAG_CONTROL_REG 48 # define AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT 1 X #define AML_CPUCONF_CONTROL_REG 0 #define AML_CPUCONF_CPU1_ADDR_REG 4 #define AML_CPUCONF_CPU2_ADDR_REG 8 #define AML_CPUCONF_CPU3_ADDR_REG 12 X /* aobus */ X #define AML_M8_CPU_PWR_CNTL0_REG 0xe0 # define AML_M8B_CPU_PWR_CNTL0_MODE_CPU3_MASK (3 << 22) # define AML_M8B_CPU_PWR_CNTL0_MODE_CPU2_MASK (3 << 20) # define AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK (3 << 18) X # define AML_M8_CPU_PWR_CNTL0_ISO_CPU3 (1 << 3) # define AML_M8_CPU_PWR_CNTL0_ISO_CPU2 (1 << 2) # define AML_M8_CPU_PWR_CNTL0_ISO_CPU1 (1 << 1) X #define AML_M8_CPU_PWR_CNTL1_REG 0xe4 # define AML_M8B_CPU_PWR_CNTL1_PWR_CPU3 (1 << 19) # define AML_M8B_CPU_PWR_CNTL1_PWR_CPU2 (1 << 18) # define AML_M8B_CPU_PWR_CNTL1_PWR_CPU1 (1 << 17) X # define AML_M8_CPU_PWR_CNTL1_MODE_CPU3_MASK (3 << 8) # define AML_M8_CPU_PWR_CNTL1_MODE_CPU2_MASK (3 << 6) # define AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK (3 << 4) X #define AML_M8B_CPU_PWR_MEM_PD0_REG 0xf4 # define AML_M8B_CPU_PWR_MEM_PD0_CPU3 (0xf << 20) # define AML_M8B_CPU_PWR_MEM_PD0_CPU2 (0xf << 24) # define AML_M8B_CPU_PWR_MEM_PD0_CPU1 (0xf << 28) X /* cbus */ X #define AML_SOC_CPU_CLK_CNTL_REG 0x419c # define AML_M8_CPU_CLK_CNTL_RESET_CPU3 (1 << 27) # define AML_M8_CPU_CLK_CNTL_RESET_CPU2 (1 << 26) # define AML_M8_CPU_CLK_CNTL_RESET_CPU1 (1 << 25) X #define SCU_WRITE_4(reg, value) bus_write_4(&aml8726_smp.scu_res, \ X (reg), (value)) #define SCU_READ_4(reg) bus_read_4(&aml8726_smp.scu_res, (reg)) #define SCU_BARRIER(reg) bus_barrier(&aml8726_smp.scu_res, \ X (reg), 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X #define CPUCONF_WRITE_4(reg, value) bus_write_4(&aml8726_smp.cpucfg_res, \ X (reg), (value)) #define CPUCONF_READ_4(reg) bus_read_4(&aml8726_smp.cpucfg_res, \ X (reg)) #define CPUCONF_BARRIER(reg) bus_barrier(&aml8726_smp.cpucfg_res, \ X (reg), 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X #define AOBUS_WRITE_4(reg, value) bus_write_4(&aml8726_smp.aobus_res, \ X (reg), (value)) #define AOBUS_READ_4(reg) bus_read_4(&aml8726_smp.aobus_res, \ X (reg)) #define AOBUS_BARRIER(reg) bus_barrier(&aml8726_smp.aobus_res, \ X (reg), 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X #define CBUS_WRITE_4(reg, value) bus_write_4(&aml8726_smp.cbus_res, \ X (reg), (value)) #define CBUS_READ_4(reg) bus_read_4(&aml8726_smp.cbus_res, \ X (reg)) #define CBUS_BARRIER(reg) bus_barrier(&aml8726_smp.cbus_res, \ X (reg), 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X X static phandle_t find_node_for_device(const char *device, const char **compatible) { X int i; X phandle_t node; X X /* X * Try to access the node directly i.e. through /aliases/. X */ X X if ((node = OF_finddevice(device)) != 0) X for (i = 0; compatible[i]; i++) X if (fdt_is_compatible_strict(node, compatible[i])) X return node; X X /* X * Find the node the long way. X */ X X for (i = 0; compatible[i]; i++) { X if ((node = OF_finddevice("/soc")) == 0) X return (0); X X if ((node = fdt_find_compatible(node, compatible[i], 1)) != 0) X return node; X } X X return (0); } X X static int alloc_resource_for_node(phandle_t node, struct resource *res, u_long *size) { X int err; X u_long pbase, psize; X u_long start; X X if ((err = fdt_get_range(OF_parent(node), 0, &pbase, &psize)) != 0 X || (err = fdt_regsize(node, &start, size)) != 0) X return (err); X X start += pbase; X X memset(res, 0, sizeof(*res)); X X res->r_bustag = fdtbus_bs_tag; X X err = bus_space_map(res->r_bustag, start, *size, 0, &res->r_bushandle); X X return (err); } X X static void power_on_cpu(int cpu) { X uint32_t scpsr; X uint32_t value; X X if (cpu <= 0) X return; X X /* X * Power on the CPU if the intricate details are known, otherwise X * just hope for the best (it may have already be powered on by X * the hardware / firmware). X */ X X switch (aml8726_soc_hw_rev) { X case AML_SOC_HW_REV_M8: X case AML_SOC_HW_REV_M8B: X /* X * Set the SCU power status for the CPU to normal mode. X */ X scpsr = SCU_READ_4(AML_SCU_CPU_PWR_STATUS_REG); X scpsr &= ~(AML_SCU_CPU_PWR_STATUS_CPU1_MASK X << ((cpu - 1) * 8)); X SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr); X SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG); X X if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { X /* X * Reset may cause the current power status from the X * actual CPU to be written to the SCU (over-writing X * the value we've just written) so set it to normal X * mode as well. X */ X value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG); X value &= ~(AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK X << ((cpu - 1) * 2)); X AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value); X AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG); X } X X DELAY(5); X X /* X * Assert reset. X */ X value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG); X value |= AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1); X CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value); X CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG); X X if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { X /* X * Release RAM pull-down. X */ X value = AOBUS_READ_4(AML_M8B_CPU_PWR_MEM_PD0_REG); X value &= ~((uint32_t)AML_M8B_CPU_PWR_MEM_PD0_CPU1 X >> ((cpu - 1) * 4)); X AOBUS_WRITE_4(AML_M8B_CPU_PWR_MEM_PD0_REG, value); X AOBUS_BARRIER(AML_M8B_CPU_PWR_MEM_PD0_REG); X } X X /* X * Power on CPU. X */ X value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG); X value &= ~(AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK X << ((cpu - 1) * 2)); X AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL1_REG, value); X AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL1_REG); X X DELAY(10); X X if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { X /* X * Wait for power on confirmation. X */ X for ( ; ; ) { X value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG); X value &= AML_M8B_CPU_PWR_CNTL1_PWR_CPU1 X << (cpu - 1); X if (value) X break; X DELAY(10); X } X } X X /* X * Release peripheral clamp. X */ X value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG); X value &= ~(AML_M8_CPU_PWR_CNTL0_ISO_CPU1 << (cpu - 1)); X AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value); X AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG); X X /* X * Release reset. X */ X value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG); X value &= ~(AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1)); X CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value); X CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG); X X if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { X /* X * The Amlogic Linux platform code sets the SCU power X * status for the CPU again for some reason so we X * follow suit (perhaps in case the reset caused X * a stale power status from the actual CPU to be X * written to the SCU). X */ X SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr); X SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG); X } X break; X default: X break; X } } X X void platform_mp_init_secondary(void) { X X /* X * Consider modifying the timer driver to support X * per-cpu timers and then enabling the timer for X * each AP. X */ X X arm_init_secondary_ic(); } X X void platform_mp_setmaxid(void) { X int err; X int i; X int ncpu; X phandle_t cpucfg_node; X phandle_t scu_node; X uint32_t value; X X if (mp_ncpus != 0) X return; X X ncpu = 1; X X /* X * Is the hardware necessary for SMP present? X */ X X if ((scu_node = find_node_for_device("scu", scu_compatible)) == 0) X goto moveon; X X if ((cpucfg_node = find_node_for_device("cpuconfig", X cpucfg_compatible)) == 0) X goto moveon; X X if (alloc_resource_for_node(scu_node, &aml8726_smp.scu_res, X &aml8726_smp.scu_size) != 0) X panic("Could not allocate resource for SCU"); X X if (alloc_resource_for_node(cpucfg_node, &aml8726_smp.cpucfg_res, X &aml8726_smp.cpucfg_size) != 0) X panic("Could not allocate resource for CPUCONFIG"); X X X /* X * Strictly speaking the aobus and cbus may not be required in X * order to start an AP (it depends on the processor), however X * always mapping them in simplifies the code. X */ X X aml8726_smp.aobus_res.r_bustag = fdtbus_bs_tag; X X err = bus_space_map(aml8726_smp.aobus_res.r_bustag, X AML_SOC_AOBUS_BASE_ADDR, 0x100000, X 0, &aml8726_smp.aobus_res.r_bushandle); X X if (err) X panic("Could not allocate resource for AOBUS"); X X aml8726_smp.cbus_res.r_bustag = fdtbus_bs_tag; X X err = bus_space_map(aml8726_smp.cbus_res.r_bustag, X AML_SOC_CBUS_BASE_ADDR, 0x100000, X 0, &aml8726_smp.cbus_res.r_bushandle); X X if (err) X panic("Could not allocate resource for CBUS"); X X aml8726_smp.errata_764369 = false; X for (i = 0; scu_errata_764369[i]; i++) X if (fdt_is_compatible_strict(scu_node, scu_errata_764369[i])) { X aml8726_smp.errata_764369 = true; X break; X } X X /* X * Read the number of CPUs present. X */ X value = SCU_READ_4(AML_SCU_CONFIG_REG); X ncpu = (value & AML_SCU_CONFIG_NCPU_MASK) + 1; X moveon: X mp_ncpus = ncpu; X mp_maxid = ncpu - 1; } X X int platform_mp_probe(void) { X X if (mp_ncpus == 0) X platform_mp_setmaxid(); X X return (mp_ncpus > 1); } X X void platform_mp_start_ap(void) { X int i; X uint32_t reg; X uint32_t value; X vm_paddr_t paddr; X X if (mp_ncpus < 2) X return; X X /* X * Invalidate SCU cache tags. The 0x0000ffff constant invalidates X * all ways on all cores 0-3. Per the ARM docs, it's harmless to X * write to the bits for cores that are not present. X */ X SCU_WRITE_4(AML_SCU_INV_TAGS_REG, 0x0000ffff); X X if (aml8726_smp.errata_764369) { X /* X * Erratum ARM/MP: 764369 (problems with cache maintenance). X * Setting the "disable-migratory bit" in the undocumented SCU X * Diagnostic Control Register helps work around the problem. X */ X value = SCU_READ_4(AML_SCU_DIAG_CONTROL_REG); X value |= AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT; X SCU_WRITE_4(AML_SCU_DIAG_CONTROL_REG, value); X } X X /* X * Enable the SCU, then clean the cache on this core. After these X * two operations the cache tag ram in the SCU is coherent with X * the contents of the cache on this core. The other cores aren't X * running yet so their caches can't contain valid data yet, however X * we've initialized their SCU tag ram above, so they will be X * coherent from startup. X */ X value = SCU_READ_4(AML_SCU_CONTROL_REG); X value |= AML_SCU_CONTROL_ENABLE; X SCU_WRITE_4(AML_SCU_CONTROL_REG, value); X SCU_BARRIER(AML_SCU_CONTROL_REG); X cpu_idcache_wbinv_all(); X X /* Set the boot address and power on each AP. */ X paddr = pmap_kextract((vm_offset_t)mpentry); X for (i = 1; i < mp_ncpus; i++) { X reg = AML_CPUCONF_CPU1_ADDR_REG + ((i - 1) * 4); X CPUCONF_WRITE_4(reg, paddr); X CPUCONF_BARRIER(reg); X X power_on_cpu(i); X } X X /* X * Enable the APs. X * X * The Amlogic Linux platform code sets the lsb for some reason X * in addition to the enable bit for each AP so we follow suit X * (the lsb may be the enable bit for the BP, though in that case X * it should already be set since it's currently running). X */ X value = CPUCONF_READ_4(AML_CPUCONF_CONTROL_REG); X value |= 1; X for (i = 1; i < mp_ncpus; i++) X value |= (1 << i); X CPUCONF_WRITE_4(AML_CPUCONF_CONTROL_REG, value); X CPUCONF_BARRIER(AML_CPUCONF_CONTROL_REG); X X /* Wakeup the now enabled APs */ X armv7_sev(); X X /* X * Free the resources which are not needed after startup. X */ X bus_space_unmap(aml8726_smp.scu_res.r_bustag, X aml8726_smp.scu_res.r_bushandle, X aml8726_smp.scu_size); X bus_space_unmap(aml8726_smp.cpucfg_res.r_bustag, X aml8726_smp.cpucfg_res.r_bushandle, X aml8726_smp.cpucfg_size); X bus_space_unmap(aml8726_smp.aobus_res.r_bustag, X aml8726_smp.aobus_res.r_bushandle, X 0x100000); X bus_space_unmap(aml8726_smp.cbus_res.r_bustag, X aml8726_smp.cbus_res.r_bushandle, X 0x100000); X memset(&aml8726_smp, 0, sizeof(aml8726_smp)); } X X void platform_ipi_send(cpuset_t cpus, u_int ipi) { X X pic_ipi_send(cpus, ipi); } X X /* X * Stub drivers for cosmetic purposes. X */ X X struct aml8726_scu_softc { X device_t dev; }; X X static int aml8726_scu_probe(device_t dev) { X int i; X X for (i = 0; scu_compatible[i]; i++) X if (ofw_bus_is_compatible(dev, scu_compatible[i])) X break; X X if (!scu_compatible[i]) X return (ENXIO); X X device_set_desc(dev, "ARM Snoop Control Unit"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_scu_attach(device_t dev) { X struct aml8726_scu_softc *sc = device_get_softc(dev); X X sc->dev = dev; X X return (0); } X X static int aml8726_scu_detach(device_t dev) { X X return (0); } X X static device_method_t aml8726_scu_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_scu_probe), X DEVMETHOD(device_attach, aml8726_scu_attach), X DEVMETHOD(device_detach, aml8726_scu_detach), X X DEVMETHOD_END }; X static driver_t aml8726_scu_driver = { X "scu", X aml8726_scu_methods, X sizeof(struct aml8726_scu_softc), }; X static devclass_t aml8726_scu_devclass; X EARLY_DRIVER_MODULE(scu, simplebus, X aml8726_scu_driver, aml8726_scu_devclass, X 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); X X struct aml8726_cpucfg_softc { X device_t dev; }; X X static int aml8726_cpucfg_probe(device_t dev) { X int i; X X for (i = 0; cpucfg_compatible[i]; i++) X if (ofw_bus_is_compatible(dev, cpucfg_compatible[i])) X break; X X if (!cpucfg_compatible[i]) X return (ENXIO); X X device_set_desc(dev, "Amlogic CPU Config"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_cpucfg_attach(device_t dev) { X struct aml8726_cpucfg_softc *sc = device_get_softc(dev); X X sc->dev = dev; X X return (0); } X X static int aml8726_cpucfg_detach(device_t dev) { X X return (0); } X X static device_method_t aml8726_cpucfg_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_cpucfg_probe), X DEVMETHOD(device_attach, aml8726_cpucfg_attach), X DEVMETHOD(device_detach, aml8726_cpucfg_detach), X X DEVMETHOD_END }; X static driver_t aml8726_cpucfg_driver = { X "cpuconfig", X aml8726_cpucfg_methods, X sizeof(struct aml8726_cpucfg_softc), }; X static devclass_t aml8726_cpucfg_devclass; X EARLY_DRIVER_MODULE(cpuconfig, simplebus, X aml8726_cpucfg_driver, aml8726_cpucfg_devclass, X 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_LATE); SHAR_EOF (set 20 15 01 31 17 22 53 'sys/arm/amlogic/aml8726/aml8726_mp.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_mp.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_mp.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_mp.c': 'MD5 check failed' ) << \SHAR_EOF 40f4b7a22022dac6fa61a414edab8997 sys/arm/amlogic/aml8726/aml8726_mp.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mp.c'` -ne 17678 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_mp.c' is not 17678" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_pic.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_pic.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_pic.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_pic.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_pic.c' && /*- X * Copyright 2013-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 PIC driver. X * X * The current implementation doesn't include support for FIQ. X * X * There is a set of four interrupt controllers per cpu located in adjacent X * memory addresses (the set for cpu 1 starts right after the set for cpu 0) X * ... this allows for interrupt handling to be spread across the cpus. X * X * The multicore chips also have a GIC ... typically they run SMP kernels X * which include the GIC driver in which case this driver is simply used X * to disable the PIC. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include X #include #include X #include #include #include X X struct aml8726_pic_softc { X device_t dev; X struct resource * res[1]; }; X static struct resource_spec aml8726_pic_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { -1, 0 } }; X X /* X * devclass_get_device / device_get_softc could be used X * to dynamically locate this, however the pic is a X * required device which can't be unloaded so there's X * no need for the overhead. X */ static struct aml8726_pic_softc *aml8726_pic_sc = NULL; X #define AML_PIC_NCNTRLS 4 #define AML_PIC_IRQS_PER_CNTRL 32 X #define AML_PIC_NIRQS (AML_PIC_NCNTRLS * AML_PIC_IRQS_PER_CNTRL) X #define AML_PIC_0_STAT_REG 0 #define AML_PIC_0_STAT_CLR_REG 4 #define AML_PIC_0_MASK_REG 8 #define AML_PIC_0_FIRQ_SEL 12 X #define AML_PIC_1_STAT_REG 16 #define AML_PIC_1_STAT_CLR_REG 20 #define AML_PIC_1_MASK_REG 24 #define AML_PIC_1_FIRQ_SEL 28 X #define AML_PIC_2_STAT_REG 32 #define AML_PIC_2_STAT_CLR_REG 36 #define AML_PIC_2_MASK_REG 40 #define AML_PIC_2_FIRQ_SEL 44 X #define AML_PIC_3_STAT_REG 48 #define AML_PIC_3_STAT_CLR_REG 52 #define AML_PIC_3_MASK_REG 56 #define AML_PIC_3_FIRQ_SEL 60 X #define AML_PIC_CTRL(x) ((x) >> 5) #define AML_PIC_BIT(x) (1 << ((x) & 0x1f)) X #define AML_PIC_STAT_REG(x) (AML_PIC_0_STAT_REG + AML_PIC_CTRL(x) * 16) #define AML_PIC_STAT_CLR_REG(x) (AML_PIC_0_STAT_CLR_REG + AML_PIC_CTRL(x) * 16) #define AML_PIC_MASK_REG(x) (AML_PIC_0_MASK_REG + AML_PIC_CTRL(x) * 16) #define AML_PIC_FIRQ_SEL(x) (AML_PIC_0_FIRQ_REG + AML_PIC_CTRL(x) * 16) X #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) #define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X X static void aml8726_pic_eoi(void *arg) { X uintptr_t nb = (uintptr_t) arg; X X if (nb >= AML_PIC_NIRQS) X return; X X CSR_WRITE_4(aml8726_pic_sc, AML_PIC_STAT_CLR_REG(nb), AML_PIC_BIT(nb)); X X CSR_BARRIER(aml8726_pic_sc, AML_PIC_STAT_CLR_REG(nb)); } X X static int aml8726_pic_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-pic")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 PIC"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_pic_attach(device_t dev) { X struct aml8726_pic_softc *sc = device_get_softc(dev); X int i; X X /* There should be exactly one instance. */ X if (aml8726_pic_sc != NULL) X return (ENXIO); X X sc->dev = dev; X X if (bus_alloc_resources(dev, aml8726_pic_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X /* X * Disable, clear, and set the interrupts to normal mode. X */ X for (i = 0; i < AML_PIC_NCNTRLS; i++) { X CSR_WRITE_4(sc, AML_PIC_0_MASK_REG + i * 16, 0); X CSR_WRITE_4(sc, AML_PIC_0_STAT_CLR_REG + i * 16, ~0u); X CSR_WRITE_4(sc, AML_PIC_0_FIRQ_SEL + i * 16, 0); X } X #ifndef SMP X arm_post_filter = aml8726_pic_eoi; #else X device_printf(dev, "disabled in favor of gic\n"); #endif X X aml8726_pic_sc = sc; X X return (0); } X X static int aml8726_pic_detach(device_t dev) { X X return (EBUSY); } X X static device_method_t aml8726_pic_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_pic_probe), X DEVMETHOD(device_attach, aml8726_pic_attach), X DEVMETHOD(device_detach, aml8726_pic_detach), X X DEVMETHOD_END }; X static driver_t aml8726_pic_driver = { X "pic", X aml8726_pic_methods, X sizeof(struct aml8726_pic_softc), }; X static devclass_t aml8726_pic_devclass; X EARLY_DRIVER_MODULE(pic, simplebus, X aml8726_pic_driver, aml8726_pic_devclass, X 0, 0, BUS_PASS_INTERRUPT); X X #ifndef SMP int arm_get_next_irq(int last) { X uint32_t value; X int irq; X int start; X X /* X * The extra complexity is simply so that all IRQs are checked X * round robin so a particularly busy interrupt can't prevent X * other interrupts from being serviced. X */ X X start = (last + 1) % AML_PIC_NIRQS; X irq = start; X X for ( ; ; ) { X value = CSR_READ_4(aml8726_pic_sc, AML_PIC_STAT_REG(irq)); X X for ( ; ; ) { X if ((value & AML_PIC_BIT(irq)) != 0) X return (irq); X X irq = (irq + 1) % AML_PIC_NIRQS; X X if (irq == start) X return (-1); X X if ((irq % AML_PIC_IRQS_PER_CNTRL) == 0) X break; X } X } } X X void arm_mask_irq(uintptr_t nb) { X uint32_t mask; X X if (nb >= AML_PIC_NIRQS) X return; X X mask = CSR_READ_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb)); X mask &= ~AML_PIC_BIT(nb); X CSR_WRITE_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb), mask); X X CSR_BARRIER(aml8726_pic_sc, AML_PIC_MASK_REG(nb)); X X aml8726_pic_eoi((void *)nb); } X X void arm_unmask_irq(uintptr_t nb) { X uint32_t mask; X X if (nb >= AML_PIC_NIRQS) X return; X X mask = CSR_READ_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb)); X mask |= AML_PIC_BIT(nb); X CSR_WRITE_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb), mask); } #endif SHAR_EOF (set 20 15 01 10 01 46 23 'sys/arm/amlogic/aml8726/aml8726_pic.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_pic.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_pic.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_pic.c': 'MD5 check failed' ) << \SHAR_EOF 592568bdf693d1572e01f95e9da20ed5 sys/arm/amlogic/aml8726/aml8726_pic.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_pic.c'` -ne 7110 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_pic.c' is not 7110" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_rng.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_rng.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_rng.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_rng.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_rng.c' && /*- X * Copyright 2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 random number generator driver. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include #include X #include X #include #include #include X X struct aml8726_rng_softc { X device_t dev; X struct resource *res[1]; X struct callout co; X int ticks; }; X static struct resource_spec aml8726_rng_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { -1, 0 } }; X #define AML_RNG_0_REG 0 #define AML_RNG_1_REG 4 X #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) X X static void aml8726_rng_harvest(void *arg) { X struct aml8726_rng_softc *sc = arg; X uint32_t rn[2]; X X rn[0] = CSR_READ_4(sc, AML_RNG_0_REG); X rn[1] = CSR_READ_4(sc, AML_RNG_1_REG); X X random_harvest(rn, sizeof(rn), sizeof(rn) * NBBY / 2, X RANDOM_PURE_AML8726); X X callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc); } X X static int aml8726_rng_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rng")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 RNG"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_rng_attach(device_t dev) { X struct aml8726_rng_softc *sc = device_get_softc(dev); X X sc->dev = dev; X X if (bus_alloc_resources(dev, aml8726_rng_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X /* Install a periodic collector for the RNG */ X if (hz > 100) X sc->ticks = hz / 100; X else X sc->ticks = 1; X X callout_init(&sc->co, CALLOUT_MPSAFE); X callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc); X X return (0); } X X static int aml8726_rng_detach(device_t dev) { X struct aml8726_rng_softc *sc = device_get_softc(dev); X X callout_drain(&sc->co); X X bus_release_resources(dev, aml8726_rng_spec, sc->res); X X return (0); } X X static device_method_t aml8726_rng_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_rng_probe), X DEVMETHOD(device_attach, aml8726_rng_attach), X DEVMETHOD(device_detach, aml8726_rng_detach), X X DEVMETHOD_END }; X static driver_t aml8726_rng_driver = { X "rng", X aml8726_rng_methods, X sizeof(struct aml8726_rng_softc), }; X static devclass_t aml8726_rng_devclass; X DRIVER_MODULE(aml8726_rng, simplebus, aml8726_rng_driver, aml8726_rng_devclass, 0, 0); MODULE_DEPEND(aml8726_rng, random, 1, 1, 1); SHAR_EOF (set 20 14 04 15 23 46 43 'sys/arm/amlogic/aml8726/aml8726_rng.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_rng.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_rng.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_rng.c': 'MD5 check failed' ) << \SHAR_EOF 90f9547099363261f2e568a362a8cd35 sys/arm/amlogic/aml8726/aml8726_rng.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_rng.c'` -ne 3976 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_rng.c' is not 3976" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_rtc.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_rtc.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_rtc.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_rtc.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_rtc.c' && /*- X * Copyright 2013-2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 RTC driver. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include X #include X #include #include X #include #include #include X #include "clock_if.h" X X /* X * The RTC initialization various slightly between the different chips. X * X * aml8726-m1 aml8726-m3 aml8726-m6 (and later) X * init-always true true false X * xo-init 0x0004 0x3c0a 0x180a X * gpo-init 0x100000 0x100000 0x500000 X */ X struct aml8726_rtc_init { X boolean_t always; X uint16_t xo; X uint32_t gpo; }; X struct aml8726_rtc_softc { X device_t dev; X struct aml8726_rtc_init init; X struct resource * res[2]; X struct mtx mtx; }; X static struct resource_spec aml8726_rtc_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { SYS_RES_IRQ, 0, RF_ACTIVE }, X { -1, 0 } }; X #define AML_RTC_LOCK(sc) mtx_lock_spin(&(sc)->mtx) #define AML_RTC_UNLOCK(sc) mtx_unlock_spin(&(sc)->mtx) #define AML_RTC_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "rtc", MTX_SPIN) #define AML_RTC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); X #define AML_RTC_0_REG 0 # define AML_RTC_SCLK (1 << 0) # define AML_RTC_SDI (1 << 2) # define AML_RTC_SEN (1 << 1) # define AML_RTC_AS (1 << 17) # define AML_RTC_ABSY (1 << 22) # define AML_RTC_IRQ_DIS (1 << 12) #define AML_RTC_1_REG 4 # define AML_RTC_SDO (1 << 0) # define AML_RTC_SRDY (1 << 1) #define AML_RTC_2_REG 8 #define AML_RTC_3_REG 12 # define AML_RTC_MSR_BUSY (1 << 20) # define AML_RTC_MSR_CA (1 << 17) # define AML_RTC_MSR_DURATION_EN (1 << 16) # define AML_RTC_MSR_DURATION_MASK 0xffff # define AML_RTC_MSR_DURATION_SHIFT 0 #define AML_RTC_4_REG 16 X #define AML_RTC_TIME_SREG 0 #define AML_RTC_GPO_SREG 1 # define AML_RTC_GPO_LEVEL (1 << 24) # define AML_RTC_GPO_BUSY (1 << 23) # define AML_RTC_GPO_ACTIVE_HIGH (1 << 22) # define AML_RTC_GPO_CMD_MASK (3 << 20) # define AML_RTC_GPO_CMD_SHIFT 20 # define AML_RTC_GPO_CMD_NOW (1 << 20) # define AML_RTC_GPO_CMD_COUNT (2 << 20) # define AML_RTC_GPO_CMD_PULSE (3 << 20) # define AML_RTC_GPO_CNT_MASK 0xfffff # define AML_RTC_GPO_CNT_SHIFT 0 X #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) #define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X X static int aml8726_rtc_start_transfer(struct aml8726_rtc_softc *sc) { X unsigned i; X X /* idle the serial interface */ X CSR_WRITE_4(sc, AML_RTC_0_REG, X (CSR_READ_4(sc, AML_RTC_0_REG) X & ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI))); X X CSR_BARRIER(sc, AML_RTC_0_REG); X X /* see if it is ready for a new cycle */ X for (i = 40; i; i--) { X DELAY(5); X if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) ) X break; X } X X if (i == 0) X return (EIO); X X /* start the cycle */ X CSR_WRITE_4(sc, AML_RTC_0_REG, X (CSR_READ_4(sc, AML_RTC_0_REG) | AML_RTC_SEN)); X X return (0); } X X static inline void aml8726_rtc_sclk_pulse(struct aml8726_rtc_softc *sc) { X X DELAY(5); X X CSR_WRITE_4(sc, AML_RTC_0_REG, X (CSR_READ_4(sc, AML_RTC_0_REG) | AML_RTC_SCLK)); X X CSR_BARRIER(sc, AML_RTC_0_REG); X X DELAY(5); X X CSR_WRITE_4(sc, AML_RTC_0_REG, X (CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SCLK)); X X CSR_BARRIER(sc, AML_RTC_0_REG); } X X static inline void aml8726_rtc_send_bit(struct aml8726_rtc_softc *sc, unsigned bit) { X X if (bit) { X CSR_WRITE_4(sc, AML_RTC_0_REG, X (CSR_READ_4(sc, AML_RTC_0_REG) | AML_RTC_SDI)); X } else { X CSR_WRITE_4(sc, AML_RTC_0_REG, X (CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SDI)); X } X X aml8726_rtc_sclk_pulse(sc); } X X static inline void aml8726_rtc_send_addr(struct aml8726_rtc_softc *sc, u_char addr) { X unsigned mask; X X for (mask = 1 << 3; mask; mask >>= 1) { X if (mask == 1) { X /* final bit indicates read / write mode */ X CSR_WRITE_4(sc, AML_RTC_0_REG, X (CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SEN)); X } X aml8726_rtc_send_bit(sc, (addr & mask)); X } } X X static inline void aml8726_rtc_send_data(struct aml8726_rtc_softc *sc, uint32_t data) { X unsigned mask; X X for (mask = 1U << 31; mask; mask >>= 1) X aml8726_rtc_send_bit(sc, (data && mask)); } X X static inline void aml8726_rtc_recv_data(struct aml8726_rtc_softc *sc, uint32_t *dp) { X uint32_t data; X unsigned i; X X data = 0; X X for (i = 0; i < 32; i++) { X aml8726_rtc_sclk_pulse(sc); X data <<= 1; X data |= (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SDO) ? 1 : 0; X } X X *dp = data; } X X static int aml8726_rtc_sreg_read(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t *val) { X u_char addr; X int error; X X /* read is indicated by lsb = 0 */ X addr = (sreg << 1) | 0; X X error = aml8726_rtc_start_transfer(sc); X X if (error) X return (error); X X aml8726_rtc_send_addr(sc, addr); X aml8726_rtc_recv_data(sc, val); X X return (0); } X X static int aml8726_rtc_sreg_write(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t val) { X u_char addr; X int error; X X /* write is indicated by lsb = 1 */ X addr = (sreg << 1) | 1; X X error = aml8726_rtc_start_transfer(sc); X X if (error) X return (error); X X aml8726_rtc_send_data(sc, val); X aml8726_rtc_send_addr(sc, addr); X X return (0); } X X static int aml8726_rtc_initialize(struct aml8726_rtc_softc *sc) { X int error; X unsigned i; X X /* idle the serial interface */ X CSR_WRITE_4(sc, AML_RTC_0_REG, X (CSR_READ_4(sc, AML_RTC_0_REG) X & ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI))); X X CSR_BARRIER(sc, AML_RTC_0_REG); X X /* see if it is ready for a new cycle */ X for (i = 40; i; i--) { X DELAY(5); X if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) ) X break; X } X X if (sc->init.always == TRUE X || (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) == 0) { X X /* X * The RTC has a 16 bit initialization register. The upper X * bits can be written directly. The lower bits are written X * through a shift register. X */ X X CSR_WRITE_4(sc, AML_RTC_4_REG, ((sc->init.xo >> 8) & 0xff)); X X CSR_WRITE_4(sc, AML_RTC_0_REG, X ((CSR_READ_4(sc, AML_RTC_0_REG) & 0xffffff) X | ((uint32_t)(sc->init.xo & 0xff) << 24) X | AML_RTC_AS | AML_RTC_IRQ_DIS)); X X while ((CSR_READ_4(sc, AML_RTC_0_REG) & AML_RTC_ABSY) != 0) X cpu_spinwait(); X X DELAY(2); X X error = aml8726_rtc_sreg_write(sc, AML_RTC_GPO_SREG, X sc->init.gpo); X X if (error) X return (error); X } X X return (0); } X X static int aml8726_rtc_check_xo(struct aml8726_rtc_softc *sc) { X uint32_t now, previous; X int i; X X /* X * The RTC is driven by a 32.768khz clock meaning it's period X * is roughly 30.5 us. Check that it's working (implying the X * RTC could contain a valid value) by enabling count always X * and seeing if the value changes after 200 us (per RTC User X * Guide ... presumably the extra time is to cover XO startup). X */ X X CSR_WRITE_4(sc, AML_RTC_3_REG, X (CSR_READ_4(sc, AML_RTC_3_REG) | AML_RTC_MSR_CA)); X X previous = CSR_READ_4(sc, AML_RTC_2_REG); X X for (i = 0; i < 4; i++) { X DELAY(50); X now = CSR_READ_4(sc, AML_RTC_2_REG); X if (now != previous) X break; X } X X CSR_WRITE_4(sc, AML_RTC_3_REG, X (CSR_READ_4(sc, AML_RTC_3_REG) & ~AML_RTC_MSR_CA)); X X if (now == previous) X return (EINVAL); X X return (0); } X X static int aml8726_rtc_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rtc")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 RTC"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_rtc_attach(device_t dev) { X struct aml8726_rtc_softc *sc = device_get_softc(dev); X boolean_t init_always_valid; X char *init_always; X pcell_t prop; X phandle_t node; X ssize_t len; X X sc->dev = dev; X X node = ofw_bus_get_node(dev); X X len = OF_getprop_alloc(node, "init-always", X sizeof(char), (void **)&init_always); X sc->init.always = FALSE; X init_always_valid = FALSE; X if (len > 0) { X if (strncmp(init_always, "true", len) == 0) { X sc->init.always = TRUE; X init_always_valid = TRUE; X } else if (strncmp(init_always, "false", len) == 0) X init_always_valid = TRUE; X free(init_always, M_OFWPROP); X } X if (init_always_valid == FALSE) { X device_printf(dev, "missing init-always attribute in FDT\n"); X return (ENXIO); X } X X if (OF_getencprop(node, "xo-init", &prop, sizeof(prop)) <= 0) { X device_printf(dev, "missing xo-init attribute in FDT\n"); X return (ENXIO); X } X sc->init.xo = prop; X X if (OF_getencprop(node, "gpo-init", &prop, sizeof(prop)) <= 0) { X device_printf(dev, "missing gpo-init attribute in FDT\n"); X return (ENXIO); X } X sc->init.gpo = prop; X X if (bus_alloc_resources(dev, aml8726_rtc_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X aml8726_rtc_initialize(sc); X X if (aml8726_rtc_check_xo(sc) != 0) { X device_printf(dev, "crystal oscillator check failed\n"); X X bus_release_resources(dev, aml8726_rtc_spec, sc->res); X X return (ENXIO); X } X X AML_RTC_LOCK_INIT(sc); X X clock_register(dev, 1000000); X X return (0); } X X static int aml8726_rtc_detach(device_t dev) { X X return (EBUSY); } X X static int aml8726_rtc_gettime(device_t dev, struct timespec *ts) { X struct aml8726_rtc_softc *sc = device_get_softc(dev); X uint32_t sec; X int error; X X AML_RTC_LOCK(sc); X X error = aml8726_rtc_sreg_read(sc, AML_RTC_TIME_SREG, &sec); X X AML_RTC_UNLOCK(sc); X X ts->tv_sec = sec; X ts->tv_nsec = 0; X X return (error); } X X static int aml8726_rtc_settime(device_t dev, struct timespec *ts) { X struct aml8726_rtc_softc *sc = device_get_softc(dev); X uint32_t sec; X int error; X X sec = ts->tv_sec; X X /* Accuracy is only one second. */ X if (ts->tv_nsec >= 500000000) X sec++; X X AML_RTC_LOCK(sc); X X error = aml8726_rtc_sreg_write(sc, AML_RTC_TIME_SREG, sec); X X AML_RTC_UNLOCK(sc); X X return (error); } X X static device_method_t aml8726_rtc_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_rtc_probe), X DEVMETHOD(device_attach, aml8726_rtc_attach), X DEVMETHOD(device_detach, aml8726_rtc_detach), X X /* Clock interface */ X DEVMETHOD(clock_gettime, aml8726_rtc_gettime), X DEVMETHOD(clock_settime, aml8726_rtc_settime), X X DEVMETHOD_END }; X static driver_t aml8726_rtc_driver = { X "rtc", X aml8726_rtc_methods, X sizeof(struct aml8726_rtc_softc), }; X static devclass_t aml8726_rtc_devclass; X DRIVER_MODULE(rtc, simplebus, aml8726_rtc_driver, aml8726_rtc_devclass, 0, 0); SHAR_EOF (set 20 15 02 01 16 31 29 'sys/arm/amlogic/aml8726/aml8726_rtc.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_rtc.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_rtc.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_rtc.c': 'MD5 check failed' ) << \SHAR_EOF de7cdc3ddcaa59c4b0e2322cbd85f19f sys/arm/amlogic/aml8726/aml8726_rtc.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_rtc.c'` -ne 12262 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_rtc.c' is not 12262" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_soc.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_soc.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_soc.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_soc.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_soc.h' && /*- X * Copyright 2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X #ifndef _ARM_AMLOGIC_AML8726_SOC_H #define _ARM_AMLOGIC_AML8726_SOC_H X X #define AML_SOC_AOBUS_BASE_ADDR 0xc8100000 #define AML_SOC_CBUS_BASE_ADDR 0xc1100000 X /* cbus */ X #define AML_SOC_HW_REV_REG 0x7d4c # define AML_SOC_HW_REV_M3 0x15 # define AML_SOC_HW_REV_M6 0x16 # define AML_SOC_HW_REV_M6TV 0x17 # define AML_SOC_HW_REV_M6TVL 0x18 # define AML_SOC_HW_REV_M8 0x19 # define AML_SOC_HW_REV_M6TVD 0x1a # define AML_SOC_HW_REV_M8B 0x1b X #define AML_SOC_METAL_REV_REG 0x81a8 # define AML_SOC_M8_METAL_REV_A 0x11111111 # define AML_SOC_M8_METAL_REV_M2_A 0x11111112 # define AML_SOC_M8_METAL_REV_B 0x11111113 # define AML_SOC_M8_METAL_REV_C 0x11111133 # define AML_SOC_M8B_METAL_REV_A 0x11111111 X extern uint32_t aml8726_soc_hw_rev; extern uint32_t aml8726_soc_metal_rev; X X #endif /* _ARM_AMLOGIC_AML8726_SOC_H */ SHAR_EOF (set 20 15 01 27 01 22 48 'sys/arm/amlogic/aml8726/aml8726_soc.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_soc.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_soc.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_soc.h': 'MD5 check failed' ) << \SHAR_EOF 9b8bf3579704dd1f23dcff36563fdbeb sys/arm/amlogic/aml8726/aml8726_soc.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_soc.h'` -ne 2304 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_soc.h' is not 2304" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_timer.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_timer.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_timer.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_timer.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_timer.c' && /*- X * Copyright 2013-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X */ X /* X * Amlogic aml8726 timer driver. X * X * 16 bit Timer A is used for the event timer / hard clock. X * 32 bit Timer E is used for the timecounter / DELAY. X * X * The current implementation doesn't use Timers B-D. Another approach is X * to split the timers between the cores implementing per cpu event timers. X * X * The timers all share the MUX register which requires a mutex to serialize X * access. The mutex is also used to avoid potential problems between the X * interrupt handler and timer_start / timer_stop. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include X #include #include X #include #include #include X X struct aml8726_timer_softc { X device_t dev; X struct resource * res[2]; X struct mtx mtx; X void * ih_cookie; X struct eventtimer et; X uint32_t first_ticks; X uint32_t period_ticks; X struct timecounter tc; }; X static struct resource_spec aml8726_timer_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { SYS_RES_IRQ, 0, RF_ACTIVE }, /* INT_TIMER_A */ X { -1, 0 } }; X /* X * devclass_get_device / device_get_softc could be used X * to dynamically locate this, however the timers are a X * required device which can't be unloaded so there's X * no need for the overhead. X */ static struct aml8726_timer_softc *aml8726_timer_sc = NULL; X #define AML_TIMER_LOCK(sc) mtx_lock_spin(&(sc)->mtx) #define AML_TIMER_UNLOCK(sc) mtx_unlock_spin(&(sc)->mtx) #define AML_TIMER_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "timer", MTX_SPIN) #define AML_TIMER_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); X #define AML_TIMER_MUX_REG 0 # define AML_TIMER_INPUT_1us 0 # define AML_TIMER_INPUT_10us 1 # define AML_TIMER_INPUT_100us 2 # define AML_TIMER_INPUT_1ms 3 # define AML_TIMER_INPUT_MASK 3 # define AML_TIMER_A_INPUT_MASK 3 # define AML_TIMER_A_INPUT_SHIFT 0 # define AML_TIMER_B_INPUT_MASK (3 << 2) # define AML_TIMER_B_INPUT_SHIFT 2 # define AML_TIMER_C_INPUT_MASK (3 << 4) # define AML_TIMER_C_INPUT_SHIFT 4 # define AML_TIMER_D_INPUT_MASK (3 << 6) # define AML_TIMER_D_INPUT_SHIFT 6 # define AML_TIMER_E_INPUT_SYS 0 # define AML_TIMER_E_INPUT_1us 1 # define AML_TIMER_E_INPUT_10us 2 # define AML_TIMER_E_INPUT_100us 3 # define AML_TIMER_E_INPUT_1ms 4 # define AML_TIMER_E_INPUT_MASK (7 << 8) # define AML_TIMER_E_INPUT_SHIFT 8 # define AML_TIMER_A_PERIODIC (1 << 12) # define AML_TIMER_B_PERIODIC (1 << 13) # define AML_TIMER_C_PERIODIC (1 << 14) # define AML_TIMER_D_PERIODIC (1 << 15) # define AML_TIMER_A_EN (1 << 16) # define AML_TIMER_B_EN (1 << 17) # define AML_TIMER_C_EN (1 << 18) # define AML_TIMER_D_EN (1 << 19) # define AML_TIMER_E_EN (1 << 20) #define AML_TIMER_A_REG 4 #define AML_TIMER_B_REG 8 #define AML_TIMER_C_REG 12 #define AML_TIMER_D_REG 16 #define AML_TIMER_E_REG 20 X #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) X X static unsigned aml8726_get_timecount(struct timecounter *tc) { X struct aml8726_timer_softc *sc X = (struct aml8726_timer_softc *)tc->tc_priv; X X return CSR_READ_4(sc, AML_TIMER_E_REG); } X X static int aml8726_hardclock(void *arg) { X struct aml8726_timer_softc *sc = (struct aml8726_timer_softc *)arg; X X AML_TIMER_LOCK(sc); X X if (sc->first_ticks != 0 && sc->period_ticks != 0) { X sc->first_ticks = 0; X X CSR_WRITE_4(sc, AML_TIMER_A_REG, sc->period_ticks); X CSR_WRITE_4(sc, AML_TIMER_MUX_REG, X (CSR_READ_4(sc, AML_TIMER_MUX_REG) X | AML_TIMER_A_PERIODIC | AML_TIMER_A_EN)); X } X X AML_TIMER_UNLOCK(sc); X X if (sc->et.et_active) X sc->et.et_event_cb(&sc->et, sc->et.et_arg); X X return (FILTER_HANDLED); } X X static int aml8726_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) { X struct aml8726_timer_softc *sc X = (struct aml8726_timer_softc *)et->et_priv; X uint32_t first_ticks; X uint32_t period_ticks; X uint32_t periodic; X uint32_t ticks; X X first_ticks = (first * et->et_frequency) / SBT_1S; X period_ticks = (period * et->et_frequency) / SBT_1S; X X if (first_ticks != 0) { X ticks = first_ticks; X periodic = 0; X X } else { X ticks = period_ticks; X periodic = AML_TIMER_A_PERIODIC; X } X X if (ticks == 0) X return (EINVAL); X X AML_TIMER_LOCK(sc); X X sc->first_ticks = first_ticks; X sc->period_ticks = period_ticks; X X CSR_WRITE_4(sc, AML_TIMER_A_REG, ticks); X CSR_WRITE_4(sc, AML_TIMER_MUX_REG, X ((CSR_READ_4(sc, AML_TIMER_MUX_REG) & ~AML_TIMER_A_PERIODIC) X | AML_TIMER_A_EN | periodic)); X X AML_TIMER_UNLOCK(sc); X X return (0); } X X static int aml8726_timer_stop(struct eventtimer *et) { X struct aml8726_timer_softc *sc X = (struct aml8726_timer_softc *)et->et_priv; X X AML_TIMER_LOCK(sc); X X CSR_WRITE_4(sc, AML_TIMER_MUX_REG, X (CSR_READ_4(sc, AML_TIMER_MUX_REG) & ~AML_TIMER_A_EN)); X X AML_TIMER_UNLOCK(sc); X X return (0); } X X static int aml8726_timer_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-timer")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 timer"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_timer_attach(device_t dev) { X struct aml8726_timer_softc *sc = device_get_softc(dev); X X /* There should be exactly one instance. */ X if (aml8726_timer_sc != NULL) X return (ENXIO); X X sc->dev = dev; X X if (bus_alloc_resources(dev, aml8726_timer_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X /* X * Disable the timers, select the input for each timer, X * clear timer E, and then enable timer E. X */ X CSR_WRITE_4(sc, AML_TIMER_MUX_REG, X ((CSR_READ_4(sc, AML_TIMER_MUX_REG) X & ~(AML_TIMER_A_EN | AML_TIMER_A_INPUT_MASK X | AML_TIMER_E_EN | AML_TIMER_E_INPUT_MASK)) X | (AML_TIMER_INPUT_1us << AML_TIMER_A_INPUT_SHIFT) X | (AML_TIMER_E_INPUT_1us << AML_TIMER_E_INPUT_SHIFT))); X X CSR_WRITE_4(sc, AML_TIMER_E_REG, 0); X X CSR_WRITE_4(sc, AML_TIMER_MUX_REG, X (CSR_READ_4(sc, AML_TIMER_MUX_REG) | AML_TIMER_E_EN)); X X /* X * Initialize the mutex prior to installing the interrupt handler X * in case of a spurious interrupt. X */ X AML_TIMER_LOCK_INIT(sc); X X if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, X aml8726_hardclock, NULL, sc, &sc->ih_cookie)) { X device_printf(dev, "could not setup interrupt handler\n"); X bus_release_resources(dev, aml8726_timer_spec, sc->res); X AML_TIMER_LOCK_DESTROY(sc); X return (ENXIO); X } X X aml8726_timer_sc = sc; X X sc->et.et_name = "aml8726 timer A"; X sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; X sc->et.et_frequency = 1000000; X sc->et.et_quality = 1000; X sc->et.et_min_period = (0x00000002LLU * SBT_1S) / sc->et.et_frequency; X sc->et.et_max_period = (0x0000fffeLLU * SBT_1S) / sc->et.et_frequency; X sc->et.et_start = aml8726_timer_start; X sc->et.et_stop = aml8726_timer_stop; X sc->et.et_priv = sc; X X et_register(&sc->et); X X sc->tc.tc_get_timecount = aml8726_get_timecount; X sc->tc.tc_name = "aml8726 timer E"; X sc->tc.tc_frequency = 1000000; X sc->tc.tc_counter_mask = ~0u; X sc->tc.tc_quality = 1000; X sc->tc.tc_priv = sc; X X tc_init(&sc->tc); X X return (0); } X X static int aml8726_timer_detach(device_t dev) { X X return (EBUSY); } X X static device_method_t aml8726_timer_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_timer_probe), X DEVMETHOD(device_attach, aml8726_timer_attach), X DEVMETHOD(device_detach, aml8726_timer_detach), X X DEVMETHOD_END }; X static driver_t aml8726_timer_driver = { X "timer", X aml8726_timer_methods, X sizeof(struct aml8726_timer_softc), }; X static devclass_t aml8726_timer_devclass; X EARLY_DRIVER_MODULE(timer, simplebus, X aml8726_timer_driver, aml8726_timer_devclass, X 0, 0, BUS_PASS_TIMER); X X void DELAY(int usec) { X uint32_t counter; X uint32_t delta, now, previous, remaining; X X /* Timer has not yet been initialized */ X if (aml8726_timer_sc == NULL) { X for (; usec > 0; usec--) X for (counter = 200; counter > 0; counter--) { X /* Prevent gcc from optimizing out the loop */ X cpufunc_nullop(); X } X return; X } X X /* X * Some of the other timers in the source tree do this calculation as: X * X * usec * ((sc->tc.tc_frequency / 1000000) + 1) X * X * which gives a fairly pessimistic result when tc_frequency is an exact X * multiple of 1000000. Given the data type and typical values for X * tc_frequency adding 999999 shouldn't overflow. X */ X remaining = usec * ((aml8726_timer_sc->tc.tc_frequency + 999999) X / 1000000); X X /* X * We add one since the first iteration may catch the counter just X * as it is changing. X */ X remaining += 1; X X previous = aml8726_get_timecount(&aml8726_timer_sc->tc); X X for ( ; ; ) { X now = aml8726_get_timecount(&aml8726_timer_sc->tc); X X /* X * If the timer has rolled over, then we have the case: X * X * if (previous > now) { X * delta = (0 - previous) + now X * } X * X * which is really no different then the normal case. X * Both cases are simply: X * X * delta = now - previous. X */ X delta = now - previous; X X if (delta >= remaining) X break; X X previous = now; X remaining -= delta; X } } SHAR_EOF (set 20 15 01 08 23 17 26 'sys/arm/amlogic/aml8726/aml8726_timer.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_timer.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_timer.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_timer.c': 'MD5 check failed' ) << \SHAR_EOF 9a6dd55696c0030ec800dc34dac0ad2b sys/arm/amlogic/aml8726/aml8726_timer.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_timer.c'` -ne 10833 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_timer.c' is not 10833" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_uart.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_uart.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_uart.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_uart.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_uart.h' && /*- X * Copyright 2013-2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD$ X */ X #ifndef _ARM_AMLOGIC_AML8726_UART_H #define _ARM_AMLOGIC_AML8726_UART_H X X #define AML_UART_WFIFO_REG 0 X #define AML_UART_RFIFO_REG 4 X #define AML_UART_CONTROL_REG 8 # define AML_UART_CONTROL_TX_INT_EN (1 << 28) # define AML_UART_CONTROL_RX_INT_EN (1 << 27) # define AML_UART_CONTROL_CLR_ERR (1 << 24) # define AML_UART_CONTROL_RX_RST (1 << 23) # define AML_UART_CONTROL_TX_RST (1 << 22) # define AML_UART_CONTROL_DB_MASK (3 << 20) # define AML_UART_CONTROL_8_DB (0 << 20) # define AML_UART_CONTROL_7_DB (1 << 20) # define AML_UART_CONTROL_6_DB (2 << 20) # define AML_UART_CONTROL_5_DB (3 << 20) # define AML_UART_CONTROL_P_MASK (3 << 18) # define AML_UART_CONTROL_P_EN (1 << 19) # define AML_UART_CONTROL_P_EVEN (0 << 18) # define AML_UART_CONTROL_P_ODD (1 << 18) # define AML_UART_CONTROL_SB_MASK (3 << 16) # define AML_UART_CONTROL_1_SB (0 << 16) # define AML_UART_CONTROL_2_SB (1 << 16) # define AML_UART_CONTROL_RX_EN (1 << 13) # define AML_UART_CONTROL_TX_EN (1 << 12) # define AML_UART_CONTROL_BAUD_MASK 0xfff # define AML_UART_CONTROL_BAUD_WIDTH 12 X #define AML_UART_STATUS_REG 12 # define AML_UART_STATUS_RECV_BUSY (1 << 26) # define AML_UART_STATUS_XMIT_BUSY (1 << 25) # define AML_UART_STATUS_RX_FIFO_OVERFLOW (1 << 24) # define AML_UART_STATUS_TX_FIFO_EMPTY (1 << 22) # define AML_UART_STATUS_TX_FIFO_FULL (1 << 21) # define AML_UART_STATUS_RX_FIFO_EMPTY (1 << 20) # define AML_UART_STATUS_RX_FIFO_FULL (1 << 19) # define AML_UART_STATUS_TX_FIFO_WRITE_ERR (1 << 18) # define AML_UART_STATUS_FRAME_ERR (1 << 17) # define AML_UART_STATUS_PARITY_ERR (1 << 16) # define AML_UART_STATUS_TX_FIFO_CNT_MASK (0x7f << 8) # define AML_UART_STATUS_TX_FIFO_CNT_SHIFT 8 # define AML_UART_STATUS_RX_FIFO_CNT_MASK (0x7f << 0) # define AML_UART_STATUS_RX_FIFO_CNT_SHIFT 0 X #define AML_UART_MISC_REG 16 # define AML_UART_MISC_OLD_RX_BAUD (1 << 30) # define AML_UART_MISC_BAUD_EXT_MASK (0xf << 20) # define AML_UART_MISC_BAUD_EXT_SHIFT 20 /* X * The documentation appears to be incorrect as the X * IRQ is actually generated when TX FIFO count is X * * equal to * or less than the selected threshold. X */ # define AML_UART_MISC_XMIT_IRQ_CNT_MASK (0xff << 8) # define AML_UART_MISC_XMIT_IRQ_CNT_SHIFT 8 /* X * The documentation appears to be incorrect as the X * IRQ is actually generated when RX FIFO count is X * * equal to * or greater than the selected threshold. X */ # define AML_UART_MISC_RECV_IRQ_CNT_MASK 0xff # define AML_UART_MISC_RECV_IRQ_CNT_SHIFT 0 X X #endif /* _ARM_AMLOGIC_AML8726_UART_H */ SHAR_EOF (set 20 15 01 27 00 25 54 'sys/arm/amlogic/aml8726/aml8726_uart.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_uart.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_uart.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_uart.h': 'MD5 check failed' ) << \SHAR_EOF cd262f8617e6caf5955a136e9abc73bb sys/arm/amlogic/aml8726/aml8726_uart.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_uart.h'` -ne 4290 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_uart.h' is not 4290" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_uart_console.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_uart_console.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_uart_console.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_uart_console.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_uart_console.c' && /*- X * Copyright 2013-2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 UART console driver. X * X * This is only necessary to use when debugging early boot code. X * The standard uart driver is available for use later in the boot. X * X * It's assumed the SoC uart is mapped into AML_UART_KVM_BASE meaning X * when using EARLY_PRINTF you'll need to define SOCDEV_VA to be X * 0xd8100000 and SOCDEV_PA to be 0xc8100000 in your config file. X */ X #include "opt_global.h" X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include X #include #include X #include #include X X #define AML_UART_KVM_BASE (aml8726_aobus_kva_base + 0x130 * 4) X X static uint32_t ub_getreg(uint32_t off) { X return *((volatile uint32_t *)(AML_UART_KVM_BASE + off)); } X X static void ub_setreg(uint32_t off, uint32_t val) { X *((volatile uint32_t *)(AML_UART_KVM_BASE + off)) = val; } X X static void uart_cnprobe(struct consdev *cp) { X X sprintf(cp->cn_name, "uart"); X cp->cn_pri = CN_REMOTE; } X X static void uart_cngrab(struct consdev *cp) { X } X X static void uart_cnungrab(struct consdev *cp) { X } X X static void uart_cninit(struct consdev *cp) { X uint32_t cr; X uint32_t mr; X #ifdef EARLY_PRINTF X if (early_putc != NULL) { X printf("Early printf yielding control to the real console.\n"); X early_putc = NULL; X } X X /* X * Give pending characters a chance to drain. X */ X DELAY(4000); #endif X X cr = ub_getreg(AML_UART_CONTROL_REG); X /* Disable all interrupt sources. */ X cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); X /* Reset the transmitter and receiver. */ X cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); X /* Enable the transmitter and receiver. */ X cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN); X ub_setreg(AML_UART_CONTROL_REG, cr); X X /* Clear RX FIFO level for generating interrupts. */ X mr = ub_getreg(AML_UART_MISC_REG); X mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; X ub_setreg(AML_UART_MISC_REG, mr); X X /* Ensure the reset bits are clear. */ X cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); X ub_setreg(AML_UART_CONTROL_REG, cr); } X X static void uart_cnterm(struct consdev * cp) { X } X X static void uart_cnputc(struct consdev *cp, int c) { X X while ((ub_getreg(AML_UART_STATUS_REG) X & AML_UART_STATUS_TX_FIFO_FULL) != 0) X cpu_spinwait(); X X ub_setreg(AML_UART_WFIFO_REG, c); } X X static int uart_cngetc(struct consdev * cp) { X int c; X X if ((ub_getreg(AML_UART_STATUS_REG) X & AML_UART_STATUS_RX_FIFO_EMPTY) != 0) X return (-1); X X c = ub_getreg(AML_UART_RFIFO_REG) & 0xff; X X return (c); } X X CONSOLE_DRIVER(uart); X X #ifdef EARLY_PRINTF X #if !(defined(SOCDEV_PA) && defined(SOCDEV_VA)) # error SOCDEV_PA and SOCDEV_VA must be defined. #endif X static void eputc(int c) { X X if (c == '\n') X eputc('\r'); X X uart_cnputc(NULL, c); } X early_putc_t *early_putc = eputc; #endif SHAR_EOF (set 20 14 04 09 02 17 14 'sys/arm/amlogic/aml8726/aml8726_uart_console.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_uart_console.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_uart_console.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_uart_console.c': 'MD5 check failed' ) << \SHAR_EOF afd3735784742a84702533676b9f3ddb sys/arm/amlogic/aml8726/aml8726_uart_console.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_uart_console.c'` -ne 4389 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_uart_console.c' is not 4389" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c' && /*- X * Copyright 2014-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726-m6 (and later) USB physical layer driver. X * X * Each USB physical interface has a dedicated register block. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include X #include X #include #include X #include #include #include X #include X #include "gpio_if.h" X X struct aml8726_usb_phy_gpio { X device_t dev; X uint32_t pin; X uint32_t pol; }; X struct aml8726_usb_phy_softc { X device_t dev; X struct resource *res[1]; X uint32_t npwr_en; X struct aml8726_usb_phy_gpio *pwr_en; X boolean_t force_aca; X struct aml8726_usb_phy_gpio hub_rst; }; X static struct resource_spec aml8726_usb_phy_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { -1, 0 } }; X #define AML_USB_PHY_CFG_REG 0 # define AML_USB_PHY_CFG_CLK_SEL_32K_ALT (1 << 15) # define AML_USB_PHY_CFG_CLK_DIV_MASK (0x7f << 4) # define AML_USB_PHY_CFG_CLK_DIV_SHIFT 4 # define AML_USB_PHY_CFG_CLK_SEL_MASK (7 << 1) # define AML_USB_PHY_CFG_CLK_SEL_XTAL (0 << 1) # define AML_USB_PHY_CFG_CLK_SEL_XTAL_DIV2 (1 << 1) # define AML_USB_PHY_CFG_CLK_EN (1 << 0) X #define AML_USB_PHY_CTRL_REG 4 # define AML_USB_PHY_CTRL_FSEL_MASK (7 << 22) # define AML_USB_PHY_CTRL_FSEL_12M (2 << 22) # define AML_USB_PHY_CTRL_FSEL_24M (5 << 22) # define AML_USB_PHY_CTRL_POR (1 << 15) # define AML_USB_PHY_CTRL_CLK_DETECTED (1 << 8) X #define AML_USB_PHY_ADP_BC_REG 12 # define AML_USB_PHY_ADP_BC_ACA_FLOATING (1 << 26) # define AML_USB_PHY_ADP_BC_ACA_EN (1 << 16) X #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) #define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X #define PIN_ON_FLAG(pol) ((pol) == 0 \ X ? GPIO_PIN_LOW : GPIO_PIN_HIGH) #define PIN_OFF_FLAG(pol) ((pol) == 0 \ X ? GPIO_PIN_HIGH : GPIO_PIN_LOW) X X static int aml8726_usb_phy_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-m6-usb-phy") X && !ofw_bus_is_compatible(dev, "amlogic,aml8726-m8-usb-phy")) X return (ENXIO); X X switch (aml8726_soc_hw_rev) { X case AML_SOC_HW_REV_M8: X case AML_SOC_HW_REV_M8B: X device_set_desc(dev, "Amlogic aml8726-m8 USB PHY"); X break; X default: X device_set_desc(dev, "Amlogic aml8726-m6 USB PHY"); X break; X } X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_usb_phy_attach(device_t dev) { X struct aml8726_usb_phy_softc *sc = device_get_softc(dev); X char *force_aca; X int err; X int npwr_en; X pcell_t *prop; X phandle_t node; X ssize_t len; X uint32_t div; X uint32_t i; X uint32_t value; X X sc->dev = dev; X X if (bus_alloc_resources(dev, aml8726_usb_phy_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X node = ofw_bus_get_node(dev); X X err = 0; X X len = OF_getencprop_alloc(node, "usb-pwr-en", X 3 * sizeof(pcell_t), (void **)&prop); X npwr_en = (len > 0) ? len : 0; X X sc->npwr_en = 0; X sc->pwr_en = (struct aml8726_usb_phy_gpio *) X malloc(npwr_en * sizeof (*sc->pwr_en), M_DEVBUF, M_WAITOK); X X for (i = 0; i < npwr_en; i++) { X sc->pwr_en[i].dev = OF_device_from_xref(prop[i * 3]); X sc->pwr_en[i].pin = prop[i * 3 + 1]; X sc->pwr_en[i].pol = prop[i * 3 + 2]; X X if (sc->pwr_en[i].dev == NULL) X err = 1; X } X X free(prop, M_OFWPROP); X X len = OF_getprop_alloc(node, "force-aca", X sizeof(char), (void **)&force_aca); X X sc->force_aca = FALSE; X X if (len > 0) { X if (strncmp(force_aca, "true", len) == 0) X sc->force_aca = TRUE; X } X X free(force_aca, M_OFWPROP); X X len = OF_getencprop_alloc(node, "usb-hub-rst", X 3 * sizeof(pcell_t), (void **)&prop); X if (len > 0) { X sc->hub_rst.dev = OF_device_from_xref(prop[0]); X sc->hub_rst.pin = prop[1]; X sc->hub_rst.pol = prop[2]; X X if (len > 1 || sc->hub_rst.dev == NULL) X err = 1; X } X X free(prop, M_OFWPROP); X X if (err) { X device_printf(dev, "unable to parse gpio\n"); X goto fail; X } X X /* Turn on power by setting pin and then enabling output driver. */ X for (i = 0; i < npwr_en; i++) { X if (GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, X PIN_ON_FLAG(sc->pwr_en[i].pol)) != 0 X || GPIO_PIN_SETFLAGS(sc->pwr_en[i].dev, sc->pwr_en[i].pin, X GPIO_PIN_OUTPUT) != 0) { X device_printf(dev, X "could not use gpio to control power\n"); X goto fail; X } X X sc->npwr_en++; X } X X /* X * Configure the clock source and divider. X */ X X value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG); X X value &= ~(AML_USB_PHY_CFG_CLK_SEL_32K_ALT X | AML_USB_PHY_CFG_CLK_DIV_MASK X | AML_USB_PHY_CFG_CLK_SEL_MASK X | AML_USB_PHY_CFG_CLK_EN); X X switch (aml8726_soc_hw_rev) { X case AML_SOC_HW_REV_M8: X case AML_SOC_HW_REV_M8B: X value |= AML_USB_PHY_CFG_CLK_SEL_32K_ALT; X break; X default: X div = 2; X value |= AML_USB_PHY_CFG_CLK_SEL_XTAL; X value |= ((div - 1) << AML_USB_PHY_CFG_CLK_DIV_SHIFT) X & AML_USB_PHY_CFG_CLK_DIV_MASK; X value |= AML_USB_PHY_CFG_CLK_EN; X break; X } X X CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); X X CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); X X /* X * Configure the clock frequency and issue a power on reset. X */ X X value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG); X X value &= ~AML_USB_PHY_CTRL_FSEL_MASK; X X switch (aml8726_soc_hw_rev) { X case AML_SOC_HW_REV_M8: X case AML_SOC_HW_REV_M8B: X value |= AML_USB_PHY_CTRL_FSEL_24M; X break; X default: X value |= AML_USB_PHY_CTRL_FSEL_12M; X break; X } X X value |= AML_USB_PHY_CTRL_POR; X X CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value); X X CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG); X X DELAY(500); X X /* X * Enable by clearing the power on reset. X */ X X value &= ~AML_USB_PHY_CTRL_POR; X X CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value); X X CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG); X X DELAY(1000); X X /* X * Check if the clock was detected. X */ X value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG); X if ((value & AML_USB_PHY_CTRL_CLK_DETECTED) == 0) X device_printf(dev, "PHY Clock not detected\n"); X X /* X * If necessary enabled Accessory Charger Adaptor detection X * so that the port knows what mode to operate in. X */ X if (sc->force_aca) { X value = CSR_READ_4(sc, AML_USB_PHY_ADP_BC_REG); X X value |= AML_USB_PHY_ADP_BC_ACA_EN; X X CSR_WRITE_4(sc, AML_USB_PHY_ADP_BC_REG, value); X X CSR_BARRIER(sc, AML_USB_PHY_ADP_BC_REG); X X DELAY(50); X X value = CSR_READ_4(sc, AML_USB_PHY_ADP_BC_REG); X X if ((value & AML_USB_PHY_ADP_BC_ACA_FLOATING) != 0) { X device_printf(dev, X "force-aca requires newer silicon\n"); X goto fail; X } X } X X /* X * Reset the hub. X */ X if (sc->hub_rst.dev != NULL) { X err = 0; X X if (GPIO_PIN_SET(sc->hub_rst.dev, sc->hub_rst.pin, X PIN_ON_FLAG(sc->hub_rst.pol)) != 0 X || GPIO_PIN_SETFLAGS(sc->hub_rst.dev, sc->hub_rst.pin, X GPIO_PIN_OUTPUT) != 0) X err = 1; X X DELAY(30); X X if (GPIO_PIN_SET(sc->hub_rst.dev, sc->hub_rst.pin, X PIN_OFF_FLAG(sc->hub_rst.pol)) != 0) X err = 1; X X DELAY(60000); X X if (err) { X device_printf(dev, X "could not use gpio to reset hub\n"); X goto fail; X } X } X X return (0); X fail: X /* In the event of problems attempt to turn things back off. */ X i = sc->npwr_en; X while (i-- != 0) { X (void)GPIO_PIN_SET(sc->pwr_en[i].dev, X sc->pwr_en[i].pin, X PIN_OFF_FLAG(sc->pwr_en[i].pol)); X } X X free (sc->pwr_en, M_DEVBUF); X sc->pwr_en = NULL; X X bus_release_resources(dev, aml8726_usb_phy_spec, sc->res); X X return (ENXIO); } X X static int aml8726_usb_phy_detach(device_t dev) { X struct aml8726_usb_phy_softc *sc = device_get_softc(dev); X uint32_t i; X uint32_t value; X X /* X * Disable by issuing a power on reset. X */ X X value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG); X X value |= AML_USB_PHY_CTRL_POR; X X CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value); X X CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG); X X /* Turn off power */ X i = sc->npwr_en; X while (i-- != 0) { X (void)GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, X PIN_OFF_FLAG(sc->pwr_en[i].pol)); X } X free (sc->pwr_en, M_DEVBUF); X sc->pwr_en = NULL; X X bus_release_resources(dev, aml8726_usb_phy_spec, sc->res); X X return (0); } X X static device_method_t aml8726_usb_phy_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_usb_phy_probe), X DEVMETHOD(device_attach, aml8726_usb_phy_attach), X DEVMETHOD(device_detach, aml8726_usb_phy_detach), X X DEVMETHOD_END }; X static driver_t aml8726_usb_phy_driver = { X "usbphy", X aml8726_usb_phy_methods, X sizeof(struct aml8726_usb_phy_softc), }; X static devclass_t aml8726_usb_phy_devclass; X DRIVER_MODULE(aml8726_m6usbphy, simplebus, aml8726_usb_phy_driver, aml8726_usb_phy_devclass, 0, 0); MODULE_DEPEND(aml8726_m6usbphy, aml8726_gpio, 1, 1, 1); SHAR_EOF (set 20 15 01 30 22 54 58 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c': 'MD5 check failed' ) << \SHAR_EOF 57e80d4af71a7caa4e55e6ce28f786bd sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c'` -ne 10407 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c' is not 10407" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_wdt.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_wdt.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_wdt.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_wdt.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_wdt.c' && /*- X * Copyright 2013-2015 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X */ X /* X * Amlogic aml8726 watchdog driver. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include X #include X #include #include X #include #include #include X #include X X struct aml8726_wdt_softc { X device_t dev; X struct resource * res[2]; X struct mtx mtx; X void * ih_cookie; }; X static struct resource_spec aml8726_wdt_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { SYS_RES_IRQ, 0, RF_ACTIVE }, X { -1, 0 } }; X static struct { X uint32_t ctrl_cpu_mask; X uint32_t ctrl_en; X uint32_t term_cnt_mask; X uint32_t reset_cnt_mask; } aml8726_wdt_soc_params; X /* X * devclass_get_device / device_get_softc could be used X * to dynamically locate this, however the wdt is a X * required device which can't be unloaded so there's X * no need for the overhead. X */ static struct aml8726_wdt_softc *aml8726_wdt_sc = NULL; X #define AML_WDT_LOCK(sc) mtx_lock_spin(&(sc)->mtx) #define AML_WDT_UNLOCK(sc) mtx_unlock_spin(&(sc)->mtx) #define AML_WDT_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "wdt", MTX_SPIN) #define AML_WDT_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); X #define AML_WDT_CTRL_REG 0 # define AML_WDT_CTRL_CPU_WDRESET_MASK aml8726_wdt_soc_params.ctrl_cpu_mask # define AML_WDT_CTRL_CPU_WDRESET_SHIFT 24 # define AML_WDT_CTRL_IRQ_EN (1 << 23) # define AML_WDT_CTRL_EN aml8726_wdt_soc_params.ctrl_en # define AML_WDT_CTRL_TERMINAL_CNT_MASK aml8726_wdt_soc_params.term_cnt_mask # define AML_WDT_CTRL_TERMINAL_CNT_SHIFT 0 #define AML_WDT_RESET_REG 4 # define AML_WDT_RESET_CNT_MASK aml8726_wdt_soc_params.reset_cnt_mask # define AML_WDT_RESET_CNT_SHIFT 0 X #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) #define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ X (BUS_SPACE_BARRIER_READ \ X | BUS_SPACE_BARRIER_WRITE)) X X static void aml8726_wdt_watchdog(void *private, u_int cmd, int *error) { X struct aml8726_wdt_softc *sc = (struct aml8726_wdt_softc *)private; X uint32_t wcr; X uint64_t tens_of_usec; X X AML_WDT_LOCK(sc); X X tens_of_usec = (((uint64_t)1 << (cmd & WD_INTERVAL)) + 9999) / 10000; X X if (cmd != 0 && tens_of_usec <= (AML_WDT_CTRL_TERMINAL_CNT_MASK X >> AML_WDT_CTRL_TERMINAL_CNT_SHIFT)) { X X wcr = AML_WDT_CTRL_CPU_WDRESET_MASK X | AML_WDT_CTRL_EN X | ((uint32_t)tens_of_usec X << AML_WDT_CTRL_TERMINAL_CNT_SHIFT); X X CSR_WRITE_4(sc, AML_WDT_RESET_REG, 0); X CSR_WRITE_4(sc, AML_WDT_CTRL_REG, wcr); X X *error = 0; X } else X CSR_WRITE_4(sc, AML_WDT_CTRL_REG, X (CSR_READ_4(sc, AML_WDT_CTRL_REG) X & ~(AML_WDT_CTRL_IRQ_EN | AML_WDT_CTRL_EN))); X X AML_WDT_UNLOCK(sc); } X X static int aml8726_wdt_intr(void *arg) { X struct aml8726_wdt_softc *sc = (struct aml8726_wdt_softc *)arg; X X /* X * Normally a timeout causes a hardware reset, however X * the watchdog timer can be configured to cause an X * interrupt instead by setting AML_WDT_CTRL_IRQ_EN X * and clearing AML_WDT_CTRL_CPU_WDRESET_MASK. X */ X X AML_WDT_LOCK(sc); X X CSR_WRITE_4(sc, AML_WDT_CTRL_REG, X (CSR_READ_4(sc, AML_WDT_CTRL_REG) X & ~(AML_WDT_CTRL_IRQ_EN | AML_WDT_CTRL_EN))); X X CSR_BARRIER(sc, AML_WDT_CTRL_REG); X X AML_WDT_UNLOCK(sc); X X device_printf(sc->dev, "timeout expired\n"); X X return (FILTER_HANDLED); } X X static int aml8726_wdt_probe(device_t dev) { X X if (!ofw_bus_status_okay(dev)) X return (ENXIO); X X if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-wdt")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 WDT"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_wdt_attach(device_t dev) { X struct aml8726_wdt_softc *sc = device_get_softc(dev); X X /* There should be exactly one instance. */ X if (aml8726_wdt_sc != NULL) X return (ENXIO); X X sc->dev = dev; X X if (bus_alloc_resources(dev, aml8726_wdt_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X /* X * Certain bitfields are dependant on the hardware revision. X */ X switch (aml8726_soc_hw_rev) { X case AML_SOC_HW_REV_M8: X aml8726_wdt_soc_params.ctrl_cpu_mask X = 0xf << AML_WDT_CTRL_CPU_WDRESET_SHIFT; X switch (aml8726_soc_metal_rev) { X case AML_SOC_M8_METAL_REV_M2_A: X aml8726_wdt_soc_params.ctrl_en = 1 << 19; X aml8726_wdt_soc_params.term_cnt_mask X = 0x07ffff << AML_WDT_CTRL_TERMINAL_CNT_SHIFT; X aml8726_wdt_soc_params.reset_cnt_mask X = 0x07ffff << AML_WDT_RESET_CNT_SHIFT; X break; X default: X aml8726_wdt_soc_params.ctrl_en = 1 << 22; X aml8726_wdt_soc_params.term_cnt_mask X = 0x3fffff << AML_WDT_CTRL_TERMINAL_CNT_SHIFT; X aml8726_wdt_soc_params.reset_cnt_mask X = 0x3fffff << AML_WDT_RESET_CNT_SHIFT; X break; X } X break; X case AML_SOC_HW_REV_M8B: X aml8726_wdt_soc_params.ctrl_cpu_mask X = 0xf << AML_WDT_CTRL_CPU_WDRESET_SHIFT; X aml8726_wdt_soc_params.ctrl_en = 1 << 19; X aml8726_wdt_soc_params.term_cnt_mask X = 0x07ffff << AML_WDT_CTRL_TERMINAL_CNT_SHIFT; X aml8726_wdt_soc_params.reset_cnt_mask X = 0x07ffff << AML_WDT_RESET_CNT_SHIFT; X break; X default: X aml8726_wdt_soc_params.ctrl_cpu_mask X = 3 << AML_WDT_CTRL_CPU_WDRESET_SHIFT; X aml8726_wdt_soc_params.ctrl_en = 1 << 22; X aml8726_wdt_soc_params.term_cnt_mask X = 0x3fffff << AML_WDT_CTRL_TERMINAL_CNT_SHIFT; X aml8726_wdt_soc_params.reset_cnt_mask X = 0x3fffff << AML_WDT_RESET_CNT_SHIFT; X break; X } X X /* X * Disable the watchdog. X */ X CSR_WRITE_4(sc, AML_WDT_CTRL_REG, X (CSR_READ_4(sc, AML_WDT_CTRL_REG) X & ~(AML_WDT_CTRL_IRQ_EN | AML_WDT_CTRL_EN))); X X /* X * Initialize the mutex prior to installing the interrupt handler X * in case of a spurious interrupt. X */ X AML_WDT_LOCK_INIT(sc); X X if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE, X aml8726_wdt_intr, NULL, sc, &sc->ih_cookie)) { X device_printf(dev, "could not setup interrupt handler\n"); X bus_release_resources(dev, aml8726_wdt_spec, sc->res); X AML_WDT_LOCK_DESTROY(sc); X return (ENXIO); X } X X aml8726_wdt_sc = sc; X X EVENTHANDLER_REGISTER(watchdog_list, aml8726_wdt_watchdog, sc, 0); X X return (0); } X X static int aml8726_wdt_detach(device_t dev) { X X return (EBUSY); } X X static device_method_t aml8726_wdt_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_wdt_probe), X DEVMETHOD(device_attach, aml8726_wdt_attach), X DEVMETHOD(device_detach, aml8726_wdt_detach), X X DEVMETHOD_END }; X static driver_t aml8726_wdt_driver = { X "wdt", X aml8726_wdt_methods, X sizeof(struct aml8726_wdt_softc), }; X static devclass_t aml8726_wdt_devclass; X EARLY_DRIVER_MODULE(wdt, simplebus, X aml8726_wdt_driver, aml8726_wdt_devclass, X 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); X X void cpu_reset() { X X /* Watchdog has not yet been initialized */ X if (aml8726_wdt_sc == NULL) X printf("Reset hardware has not yet been initialized.\n"); X else { X CSR_WRITE_4(aml8726_wdt_sc, AML_WDT_RESET_REG, 0); X CSR_WRITE_4(aml8726_wdt_sc, AML_WDT_CTRL_REG, X (AML_WDT_CTRL_CPU_WDRESET_MASK X | AML_WDT_CTRL_EN X | (10 << AML_WDT_CTRL_TERMINAL_CNT_SHIFT))); X } X X while (1); } SHAR_EOF (set 20 15 01 27 01 36 54 'sys/arm/amlogic/aml8726/aml8726_wdt.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_wdt.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_wdt.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_wdt.c': 'MD5 check failed' ) << \SHAR_EOF 54b23d50f3a8b957b0b9a3bca2560a83 sys/arm/amlogic/aml8726/aml8726_wdt.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_wdt.c'` -ne 8749 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_wdt.c' is not 8749" fi fi # ============= sys/arm/amlogic/aml8726/files.aml8726 ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/files.aml8726' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/files.aml8726 (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/files.aml8726 (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/files.aml8726' && #$FreeBSD$ X kern/kern_clocksource.c standard X arm/arm/bus_space_base.c standard arm/arm/bus_space_generic.c standard arm/arm/bus_space_asm_generic.S standard arm/arm/cpufunc_asm_armv5.S standard arm/arm/cpufunc_asm_arm11.S standard arm/arm/cpufunc_asm_armv7.S standard X arm/arm/pl310.c standard arm/amlogic/aml8726/aml8726_l2cache.c standard X arm/amlogic/aml8726/aml8726_machdep.c standard arm/amlogic/aml8726/aml8726_identsoc.c standard arm/amlogic/aml8726/aml8726_clkmsr.c standard arm/amlogic/aml8726/aml8726_pic.c standard arm/amlogic/aml8726/aml8726_rtc.c standard arm/amlogic/aml8726/aml8726_timer.c standard arm/amlogic/aml8726/aml8726_wdt.c standard X # serial console for debugging early boot code #arm/amlogic/aml8726/aml8726_uart_console.c standard X arm/amlogic/aml8726/aml8726_fb.c optional vt arm/amlogic/aml8726/aml8726_gpio.c optional gpio #arm/amlogic/aml8726/aml8726_i2c.c optional iicbus arm/amlogic/aml8726/aml8726_mmc.c optional mmc gpio arm/amlogic/aml8726/aml8726_rng.c optional random arm/amlogic/aml8726/uart_dev_aml8726.c optional uart #arm/amlogic/aml8726/aml8726_usb_phy-m3.c optional dwcotg usb gpio arm/amlogic/aml8726/aml8726_usb_phy-m6.c optional dwcotg usb gpio X dev/dwc/if_dwc.c optional dwc SHAR_EOF (set 20 15 02 01 17 35 33 'sys/arm/amlogic/aml8726/files.aml8726' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/files.aml8726' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/files.aml8726 failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/files.aml8726': 'MD5 check failed' ) << \SHAR_EOF 9058db7c10868e7706f9f89a64683c60 sys/arm/amlogic/aml8726/files.aml8726 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/files.aml8726'` -ne 1260 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/files.aml8726' is not 1260" fi fi # ============= sys/arm/amlogic/aml8726/files.smp ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/files.smp' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/files.smp (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/files.smp (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/files.smp' && #$FreeBSD$ X arm/arm/gic.c standard arm/amlogic/aml8726/aml8726_mp.c standard SHAR_EOF (set 20 15 01 11 23 06 21 'sys/arm/amlogic/aml8726/files.smp' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/files.smp' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/files.smp failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/files.smp': 'MD5 check failed' ) << \SHAR_EOF 7bce7bea551c79b1fd8b529c7fa168ae sys/arm/amlogic/aml8726/files.smp SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/files.smp'` -ne 82 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/files.smp' is not 82" fi fi # ============= sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh' && #!/bin/sh X BL1=bl1.bin.hardkernel UBOOT=u-boot.bin X if [ -z $1 ]; then X echo "usage ./sd_freebsd.sh " X exit 0 fi X if [ ! -f $BL1 ]; then X echo "Error: $BL1 does not exist." X exit 0 fi X if [ ! -f $UBOOT ]; then X echo "Error: $UBOOT does not exist." X exit 0 fi X # Write BL1 / MBR dd if=$BL1 of=$1 bs=512 # Write U-boot dd if=$UBOOT of=$1 bs=512 seek=64 conv=sync # Zero out U-boot Environment dd if=/dev/zero of=$1 bs=512 seek=1024 count=64 X # Create MBR GEOM gpart create -s mbr `basename $1` # Add MSDOS partition to contain kernel.bin gpart add -t fat16 -b 1134 -s 64M `basename $1` # Add FreeBSD partition gpart add -t freebsd -b 132174 `basename $1` X # Creating the MBR GEOM may have cleared the # MBR bootcode in block zero so refresh it. dd if=$BL1 bs=512 count=1 of=bl1-mbr.tmp gpart bootcode -b bl1-mbr.tmp `basename $1` rm -f bl1-mbr.tmp X # Format filesystems newfs_msdos -F 16 ${1}s1 newfs ${1}s2 X echo "Successfully partitioned and wrote boot code to $1" SHAR_EOF (set 20 15 02 01 00 56 08 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh' eval "${shar_touch}") && \ chmod 0744 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh': 'MD5 check failed' ) << \SHAR_EOF ea983939d2569d176845df70251eb8b4 sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh'` -ne 1038 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh' is not 1038" fi fi # ============= sys/arm/amlogic/aml8726/std.aml8726 ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/std.aml8726' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/std.aml8726 (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/std.aml8726 (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/std.aml8726' && # $FreeBSD$ X cpu CPU_CORTEXA machine arm armv6 makeoptions CONF_CFLAGS="-march=armv7a" X files "../amlogic/aml8726/files.aml8726" X options ARM_L2_PIPT X # Set all global interrupts to be edge triggered, active high. options GIC_DEFAULT_ICFGR_INIT=0xffffffff X options IPI_IRQ_START=0 options IPI_IRQ_END=15 X #options EARLY_PRINTF #options SOCDEV_PA=0xc8100000 #options SOCDEV_VA=0xd8100000 SHAR_EOF (set 20 15 01 31 22 33 24 'sys/arm/amlogic/aml8726/std.aml8726' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/std.aml8726' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/std.aml8726 failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/std.aml8726': 'MD5 check failed' ) << \SHAR_EOF b1e78e25e579de09bafa7fab6f449200 sys/arm/amlogic/aml8726/std.aml8726 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/std.aml8726'` -ne 398 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/std.aml8726' is not 398" fi fi # ============= sys/arm/amlogic/aml8726/std.odroidc1 ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/std.odroidc1' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/std.odroidc1 (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/std.odroidc1 (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/std.odroidc1' && # $FreeBSD$ X include "../amlogic/aml8726/std.aml8726" X makeoptions FDT_DTS_FILE=odroidc1.dts X options SMP # Enable multiple cores files "../amlogic/aml8726/files.smp" X # Physical memory starts at 0x00000000. We assume the kernel is loaded # at 0x00100000 by u-boot (which doesn't support ubldr since it's missing # CONFIG_API). The kernel must be supplied as a binary since u-boot is # also missing CONFIG_CMD_ELF. # # options KERNVIRTADDR=0xc0100000 # Used in ldscript.arm makeoptions KERNVIRTADDR=0xc0100000 SHAR_EOF (set 20 15 01 13 00 29 22 'sys/arm/amlogic/aml8726/std.odroidc1' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/std.odroidc1' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/std.odroidc1 failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/std.odroidc1': 'MD5 check failed' ) << \SHAR_EOF 2cd2a2e81baf9d719c04129a35a18929 sys/arm/amlogic/aml8726/std.odroidc1 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/std.odroidc1'` -ne 530 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/std.odroidc1' is not 530" fi fi # ============= sys/arm/amlogic/aml8726/std.vsatv102-m6 ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/std.vsatv102-m6' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/std.vsatv102-m6 (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/std.vsatv102-m6 (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/std.vsatv102-m6' && # $FreeBSD$ X include "../amlogic/aml8726/std.aml8726" X makeoptions FDT_DTS_FILE=vsatv102-m6.dts X options SMP # Enable multiple cores files "../amlogic/aml8726/files.smp" X # Physical memory starts at 0x80000000. We assume the kernel is loaded # at 0x80100000 by u-boot (which doesn't support ubldr since it's missing # CONFIG_API). The kernel must be supplied as a binary since u-boot is # also missing CONFIG_CMD_ELF. # # options KERNVIRTADDR=0xc0100000 # Used in ldscript.arm makeoptions KERNVIRTADDR=0xc0100000 SHAR_EOF (set 20 15 01 11 23 13 30 'sys/arm/amlogic/aml8726/std.vsatv102-m6' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/std.vsatv102-m6' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/std.vsatv102-m6 failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/std.vsatv102-m6': 'MD5 check failed' ) << \SHAR_EOF 56e580601bca10751e1fe18b6e3ded7f sys/arm/amlogic/aml8726/std.vsatv102-m6 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/std.vsatv102-m6'` -ne 533 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/std.vsatv102-m6' is not 533" fi fi # ============= sys/arm/amlogic/aml8726/uart_dev_aml8726.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/uart_dev_aml8726.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/uart_dev_aml8726.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c' && /*- X * Copyright 2013-2014 John Wehle X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X /* X * Amlogic aml8726 UART driver. X * X * The current implementation only targets features common to all X * uarts. For example ... though the aml8726-m3 has RTS / CTS, the X * aml8726-mx doesn't. Likewise though UART A as a 128 byte FIFO, X * the others only have a 64 byte FIFO. X * X * Also, it's assumed that register 5 (the new baud rate register X * present on the aml8726-mx) has not been activated. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include X #include #include X #include #include #include X #include X #include "uart_if.h" X X #undef uart_getreg #undef uart_setreg X #define uart_getreg(bas, reg) \ X bus_space_read_4((bas)->bst, (bas)->bsh, reg) #define uart_setreg(bas, reg, value) \ X bus_space_write_4((bas)->bst, (bas)->bsh, reg, value) X #define SIGCHG(c, i, s, d) \ X do { \ X if (c) { \ X i |= (i & s) ? s : s | d; \ X } else { \ X i = (i & s) ? (i & ~s) | d : i; \ X } \ X } while (0) X X static int aml8726_uart_divisor(int rclk, int baudrate) { X int actual_baud, divisor; X int error; X X if (baudrate == 0) X return (0); X X /* integer version of (rclk / baudrate + .5) */ X divisor = ((rclk << 1) + baudrate) / (baudrate << 1); X if (divisor == 0 || divisor >= 65536) X return (0); X actual_baud = rclk / divisor; X X /* 10 times error in percent: */ X error = (((actual_baud - baudrate) * 2000) / baudrate + 1) >> 1; X X /* 3.0% maximum error tolerance: */ X if (error < -30 || error > 30) X return (0); X X return (divisor); } X X static int aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, X int parity) { X uint32_t cr; X uint32_t mr; X int divisor; X X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X X cr &= ~(AML_UART_CONTROL_DB_MASK | AML_UART_CONTROL_SB_MASK X | AML_UART_CONTROL_P_MASK); X X switch (databits) { X case 5: cr |= AML_UART_CONTROL_5_DB; break; X case 6: cr |= AML_UART_CONTROL_6_DB; break; X case 7: cr |= AML_UART_CONTROL_7_DB; break; X case 8: cr |= AML_UART_CONTROL_8_DB; break; X default: return (EINVAL); X } X X switch (stopbits) { X case 1: cr |= AML_UART_CONTROL_1_SB; break; X case 2: cr |= AML_UART_CONTROL_2_SB; break; X default: return (EINVAL); X } X X switch (parity) { X case UART_PARITY_EVEN: cr |= AML_UART_CONTROL_P_EVEN; X cr |= AML_UART_CONTROL_P_EN; X break; X X case UART_PARITY_ODD: cr |= AML_UART_CONTROL_P_ODD; X cr |= AML_UART_CONTROL_P_EN; X break; X X case UART_PARITY_NONE: break; X X default: return (EINVAL); X } X X /* Set baudrate. */ X if (baudrate > 0 && bas->rclk != 0) { X divisor = aml8726_uart_divisor(bas->rclk / 4, baudrate) - 1; X if (divisor > 0xffff) X return (EINVAL); X X cr &= ~AML_UART_CONTROL_BAUD_MASK; X cr |= (divisor & AML_UART_CONTROL_BAUD_MASK); X X divisor >>= AML_UART_CONTROL_BAUD_WIDTH; X X mr = uart_getreg(bas, AML_UART_MISC_REG); X mr &= ~(AML_UART_MISC_OLD_RX_BAUD X | AML_UART_MISC_BAUD_EXT_MASK); X mr |= ((divisor << AML_UART_MISC_BAUD_EXT_SHIFT) X & AML_UART_MISC_BAUD_EXT_MASK); X uart_setreg(bas, AML_UART_MISC_REG, mr); X } X X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X return (0); } X X /* X * Low-level UART interface. X */ X static int aml8726_uart_probe(struct uart_bas *bas) { X X return (0); } X X static void aml8726_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, X int parity) { X uint32_t cr; X uint32_t mr; X X aml8726_uart_param(bas, baudrate, databits, stopbits, parity); X X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X /* Disable all interrupt sources. */ X cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); X /* Reset the transmitter and receiver. */ X cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); X /* Enable the transmitter and receiver. */ X cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN); X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X /* Clear RX FIFO level for generating interrupts. */ X mr = uart_getreg(bas, AML_UART_MISC_REG); X mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; X uart_setreg(bas, AML_UART_MISC_REG, mr); X uart_barrier(bas); X X /* Ensure the reset bits are clear. */ X cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); } X X static void aml8726_uart_term(struct uart_bas *bas) { X } X X static void aml8726_uart_putc(struct uart_bas *bas, int c) { X X while ((uart_getreg(bas, AML_UART_STATUS_REG) X & AML_UART_STATUS_TX_FIFO_FULL) != 0) X cpu_spinwait(); X X uart_setreg(bas, AML_UART_WFIFO_REG, c); X uart_barrier(bas); } X X static int aml8726_uart_rxready(struct uart_bas *bas) { X X return ((uart_getreg(bas, AML_UART_STATUS_REG) X & AML_UART_STATUS_RX_FIFO_EMPTY) == 0 ? 1 : 0); } X X static int aml8726_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) { X int c; X X uart_lock(hwmtx); X X while ((uart_getreg(bas, AML_UART_STATUS_REG) X & AML_UART_STATUS_RX_FIFO_EMPTY) != 0) { X uart_unlock(hwmtx); X DELAY(4); X uart_lock(hwmtx); X } X X c = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff; X X uart_unlock(hwmtx); X X return (c); } X X struct uart_ops aml8726_uart_ops = { X .probe = aml8726_uart_probe, X .init = aml8726_uart_init, X .term = aml8726_uart_term, X .putc = aml8726_uart_putc, X .rxready = aml8726_uart_rxready, X .getc = aml8726_uart_getc, }; X X static int aml8726_uart_bus_probe(struct uart_softc *sc) { X int error; X X error = aml8726_uart_probe(&sc->sc_bas); X if (error) X return (error); X X sc->sc_rxfifosz = 64; X sc->sc_txfifosz = 64; X sc->sc_hwiflow = 0; X sc->sc_hwoflow = 0; X X device_set_desc(sc->sc_dev, "Amlogic aml8726 UART"); X X return (0); } X X static int aml8726_uart_bus_getsig(struct uart_softc *sc) { X uint32_t new, old, sig; X X /* X * Treat DSR, DCD, and CTS as always on. X */ X X do { X old = sc->sc_hwsig; X sig = old; X SIGCHG(1, sig, SER_DSR, SER_DDSR); X SIGCHG(1, sig, SER_DCD, SER_DDCD); X SIGCHG(1, sig, SER_CTS, SER_DCTS); X new = sig & ~SER_MASK_DELTA; X } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); X X return (sig); } X X static int aml8726_uart_bus_setsig(struct uart_softc *sc, int sig) { X uint32_t new, old; X X do { X old = sc->sc_hwsig; X new = old; X if (sig & SER_DDTR) { X SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); X } X if (sig & SER_DRTS) { X SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); X } X } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); X X return (0); } X X static int aml8726_uart_bus_attach(struct uart_softc *sc) { X struct uart_bas *bas; X uint32_t cr; X uint32_t mr; X X bas = &sc->sc_bas; X X if (bas->rclk == 0) { X device_printf(sc->sc_dev, "missing clock attribute in FDT\n"); X return (ENXIO); X } X X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X /* Disable all interrupt sources. */ X cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); X /* Ensure the reset bits are clear. */ X cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); X X /* X * Reset the transmitter and receiver only if not acting as a X * console, otherwise it means that: X * X * 1) aml8726_uart_init was already called which did the reset X * X * 2) there may be console bytes sitting in the transmit fifo X */ X if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) X ; X else X cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); X X /* Enable the transmitter and receiver. */ X cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN); X /* Reset error bits. */ X cr |= AML_UART_CONTROL_CLR_ERR; X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X /* Set FIFO levels for generating interrupts. */ X mr = uart_getreg(bas, AML_UART_MISC_REG); X mr &= ~AML_UART_MISC_XMIT_IRQ_CNT_MASK; X mr |= (0 << AML_UART_MISC_XMIT_IRQ_CNT_SHIFT); X mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; X mr |= (1 << AML_UART_MISC_RECV_IRQ_CNT_SHIFT); X uart_setreg(bas, AML_UART_MISC_REG, mr); X uart_barrier(bas); X X aml8726_uart_bus_getsig(sc); X X /* Ensure the reset bits are clear. */ X cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); X cr &= ~AML_UART_CONTROL_CLR_ERR; X /* Enable the receive interrupt. */ X cr |= AML_UART_CONTROL_RX_INT_EN; X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X return (0); } X static int aml8726_uart_bus_detach(struct uart_softc *sc) { X struct uart_bas *bas; X uint32_t cr; X uint32_t mr; X X bas = &sc->sc_bas; X X /* Disable all interrupt sources. */ X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X /* Clear RX FIFO level for generating interrupts. */ X mr = uart_getreg(bas, AML_UART_MISC_REG); X mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; X uart_setreg(bas, AML_UART_MISC_REG, mr); X uart_barrier(bas); X X return (0); } X X static int aml8726_uart_bus_flush(struct uart_softc *sc, int what) { X struct uart_bas *bas; X uint32_t cr; X X bas = &sc->sc_bas; X uart_lock(sc->sc_hwmtx); X X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X if (what & UART_FLUSH_TRANSMITTER) X cr |= AML_UART_CONTROL_TX_RST; X if (what & UART_FLUSH_RECEIVER) X cr |= AML_UART_CONTROL_RX_RST; X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X /* Ensure the reset bits are clear. */ X cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X uart_unlock(sc->sc_hwmtx); X X return (0); } X X static int aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { X struct uart_bas *bas; X int baudrate, divisor, error; X uint32_t cr, mr; X X bas = &sc->sc_bas; X uart_lock(sc->sc_hwmtx); X X error = 0; X switch (request) { X case UART_IOCTL_BAUD: X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X cr &= AML_UART_CONTROL_BAUD_MASK; X X mr = uart_getreg(bas, AML_UART_MISC_REG); X mr &= AML_UART_MISC_BAUD_EXT_MASK; X X divisor = ((mr >> AML_UART_MISC_BAUD_EXT_SHIFT) X << AML_UART_CONTROL_BAUD_WIDTH) | cr; X X baudrate = bas->rclk / 4 / (divisor + 1); X if (baudrate > 0) X *(int*)data = baudrate; X else X error = ENXIO; X break; X X default: X error = EINVAL; X break; X } X X uart_unlock(sc->sc_hwmtx); X X return (error); } X X static int aml8726_uart_bus_ipend(struct uart_softc *sc) { X struct uart_bas *bas; X int ipend; X uint32_t sr; X uint32_t cr; X X bas = &sc->sc_bas; X uart_lock(sc->sc_hwmtx); X X ipend = 0; X sr = uart_getreg(bas, AML_UART_STATUS_REG); X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X X if ((sr & AML_UART_STATUS_RX_FIFO_OVERFLOW) != 0) X ipend |= SER_INT_OVERRUN; X X if ((sr & AML_UART_STATUS_TX_FIFO_EMPTY) != 0 X && (cr & AML_UART_CONTROL_TX_INT_EN) != 0) { X ipend |= SER_INT_TXIDLE; X X cr &= ~AML_UART_CONTROL_TX_INT_EN; X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X } X X if ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) X ipend |= SER_INT_RXREADY; X X uart_unlock(sc->sc_hwmtx); X X return (ipend); } X X static int aml8726_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, X int stopbits, int parity) { X struct uart_bas *bas; X int error; X X bas = &sc->sc_bas; X uart_lock(sc->sc_hwmtx); X X error = aml8726_uart_param(bas, baudrate, databits, stopbits, parity); X X uart_unlock(sc->sc_hwmtx); X X return (error); } X X static int aml8726_uart_bus_receive(struct uart_softc *sc) { X struct uart_bas *bas; X int xc; X uint32_t sr; X X bas = &sc->sc_bas; X uart_lock(sc->sc_hwmtx); X X sr = uart_getreg(bas, AML_UART_STATUS_REG); X while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) { X if (uart_rx_full(sc)) { X sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; X break; X } X xc = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff; X if (sr & AML_UART_STATUS_FRAME_ERR) X xc |= UART_STAT_FRAMERR; X if (sr & AML_UART_STATUS_PARITY_ERR) X xc |= UART_STAT_PARERR; X uart_rx_put(sc, xc); X sr = uart_getreg(bas, AML_UART_STATUS_REG); X } X /* Discard everything left in the RX FIFO. */ X while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) { X (void)uart_getreg(bas, AML_UART_RFIFO_REG); X sr = uart_getreg(bas, AML_UART_STATUS_REG); X } X /* Reset error bits */ X if ((sr & (AML_UART_STATUS_FRAME_ERR | AML_UART_STATUS_PARITY_ERR)) != 0) { X uart_setreg(bas, AML_UART_CONTROL_REG, X (uart_getreg(bas, AML_UART_CONTROL_REG) X | AML_UART_CONTROL_CLR_ERR)); X uart_barrier(bas); X uart_setreg(bas, AML_UART_CONTROL_REG, X (uart_getreg(bas, AML_UART_CONTROL_REG) X & ~AML_UART_CONTROL_CLR_ERR)); X uart_barrier(bas); X } X X uart_unlock(sc->sc_hwmtx); X X return (0); } X X static int aml8726_uart_bus_transmit(struct uart_softc *sc) { X struct uart_bas *bas; X int i; X uint32_t cr; X X bas = &sc->sc_bas; X uart_lock(sc->sc_hwmtx); X X /* X * Wait for sufficient space since aml8726_uart_putc X * may have been called after SER_INT_TXIDLE occurred. X */ X while ((uart_getreg(bas, AML_UART_STATUS_REG) X & AML_UART_STATUS_TX_FIFO_EMPTY) == 0) X cpu_spinwait(); X X for (i = 0; i < sc->sc_txdatasz; i++) { X uart_setreg(bas, AML_UART_WFIFO_REG, sc->sc_txbuf[i]); X uart_barrier(bas); X } X X sc->sc_txbusy = 1; X X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X cr |= AML_UART_CONTROL_TX_INT_EN; X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X uart_unlock(sc->sc_hwmtx); X X return (0); } X X static void aml8726_uart_bus_grab(struct uart_softc *sc) { X struct uart_bas *bas; X uint32_t cr; X X /* X * Disable the receive interrupt to avoid a race between X * aml8726_uart_getc and aml8726_uart_bus_receive which X * can trigger: X * X * panic: bad stray interrupt X * X * due to the RX FIFO receiving a character causing an X * interrupt which gets serviced after aml8726_uart_getc X * has been called (meaning the RX FIFO is now empty). X */ X X bas = &sc->sc_bas; X uart_lock(sc->sc_hwmtx); X X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X cr &= ~AML_UART_CONTROL_RX_INT_EN; X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X X uart_unlock(sc->sc_hwmtx); } X X static void aml8726_uart_bus_ungrab(struct uart_softc *sc) { X struct uart_bas *bas; X uint32_t cr; X uint32_t mr; X X /* X * The RX FIFO level being set indicates that the device X * is currently attached meaning the receive interrupt X * should be enabled. X */ X X bas = &sc->sc_bas; X uart_lock(sc->sc_hwmtx); X X mr = uart_getreg(bas, AML_UART_MISC_REG); X mr &= AML_UART_MISC_RECV_IRQ_CNT_MASK; X X if (mr != 0) { X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X cr |= AML_UART_CONTROL_RX_INT_EN; X uart_setreg(bas, AML_UART_CONTROL_REG, cr); X uart_barrier(bas); X } X X uart_unlock(sc->sc_hwmtx); } X X static kobj_method_t aml8726_uart_methods[] = { X KOBJMETHOD(uart_probe, aml8726_uart_bus_probe), X KOBJMETHOD(uart_attach, aml8726_uart_bus_attach), X KOBJMETHOD(uart_detach, aml8726_uart_bus_detach), X KOBJMETHOD(uart_flush, aml8726_uart_bus_flush), X KOBJMETHOD(uart_getsig, aml8726_uart_bus_getsig), X KOBJMETHOD(uart_setsig, aml8726_uart_bus_setsig), X KOBJMETHOD(uart_ioctl, aml8726_uart_bus_ioctl), X KOBJMETHOD(uart_ipend, aml8726_uart_bus_ipend), X KOBJMETHOD(uart_param, aml8726_uart_bus_param), X KOBJMETHOD(uart_receive, aml8726_uart_bus_receive), X KOBJMETHOD(uart_transmit, aml8726_uart_bus_transmit), X KOBJMETHOD(uart_grab, aml8726_uart_bus_grab), X KOBJMETHOD(uart_ungrab, aml8726_uart_bus_ungrab), X { 0, 0 } }; X struct uart_class uart_aml8726_class = { X "uart", X aml8726_uart_methods, X sizeof(struct uart_softc), X .uc_ops = &aml8726_uart_ops, X .uc_range = 24, X .uc_rclk = 0 }; SHAR_EOF (set 20 14 02 19 00 25 31 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/uart_dev_aml8726.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c': 'MD5 check failed' ) << \SHAR_EOF 6604236035c33da69d47dd973b0531e3 sys/arm/amlogic/aml8726/uart_dev_aml8726.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c'` -ne 16704 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c' is not 16704" fi fi if rm -fr ${lock_dir} then ${echo} "x - removed lock directory ${lock_dir}." else ${echo} "x - failed to remove lock directory ${lock_dir}." exit 1 fi exit 0 ------------------------------------------------------------------------- | Feith Systems | Voice: 1-215-646-8000 | Email: john@feith.com | | John Wehle | Fax: 1-215-540-5495 | | -------------------------------------------------------------------------