#!/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=_sh36266 # Made on 2015-03-11 00:37 EDT 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 # ------ ---------- ------------------------------------------ # 11593 -rw-r--r-- sys/boot/fdt/dts/arm/odroidc1.dts # 10320 -rw-r--r-- sys/boot/fdt/dts/arm/vsatv102-m6.dts # 4241 -rw-r--r-- sys/arm/conf/ODROIDC1 # 4247 -rw-r--r-- sys/arm/conf/VSATV102 # 2474 -rw-r--r-- sys/arm/amlogic/aml8726/README.txt # 222 -rw-r--r-- sys/arm/amlogic/aml8726/Changes.txt # 2601 -rw-r--r-- sys/arm/amlogic/aml8726/PatchJLW01 # 5695 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_ccm.c # 7169 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_ccm.h # 7269 -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 # 9100 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_gpio.c # 7239 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_i2c.c # 4195 -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 # 25894 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mmc.c # 5999 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mmc.h # 17662 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mp.c # 7110 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_pic.c # 11267 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_pinctrl.c # 35044 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_pinctrl.h # 3976 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_rng.c # 12261 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_rtc.c # 33444 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c # 10812 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h # 2262 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_soc.h # 10833 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_timer.c # 4344 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_uart.h # 4452 -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 # 1406 -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 # 419 -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 # 17167 -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>; X interrupt-parent = <&gic>; X }; X X ccm@1104140 { X compatible = "amlogic,aml8726-ccm"; X reg = <0x1104140 20>; /* cbus 0x1050 */ X X functions = "ethernet", "i2c", "rng", "sdio", "sdxc", X "uart-a", "uart-b", "uart-c", X "usb-a", "usb-b"; X }; X X pinctrl@11080b0 { X compatible = "amlogic,aml8726-pinctrl"; X reg = <0x11080b0 40>, /* mux */ X <0x11080e8 24>, /* pu/pd */ X <0x1108120 24>, /* pull enable */ X <0x8100014 4>, /* ao mux */ X <0x810002c 4>, /* ao pu/pd */ X <0x810002c 4>; /* ao pull enable */ X X /* X * Currently only pin muxing that deviates X * from the power on default of gpio is X * specified here. X */ X X pinctrl-names = "default"; X pinctrl-0 = <&pins_uartao &pins_ethernet &pins_hdmi>; X X pins_ethernet: ethernet { X amlogic,pins = "ref_clk", X "tx_clk", "tx_en", X "tx_d0", "tx_d1", X "tx_d2", "tx_d3", X "rx_clk", "rx_dv", X "rx_d0", "rx_d1", X "rx_d2", "rx_d3", X "mdc", "mdio"; X amlogic,function = "ethernet"; X }; X X pins_hdmi: hdmi { X amlogic,pins = "cec", "hpd", X "scl", "sda"; X amlogic,function = "hdmi"; X }; X X pins_sdio_b: sdio_b { X amlogic,pins = "clk", "cmd", X "d0", "d1", X "d2", "d3"; X amlogic,function = "sdio-b"; X amlogic,pull = "up"; X }; X X pins_sdxc_b: sdxc_b { X amlogic,pins = "clk", "cmd", X "d0", "d1", X "d2", "d3"; X amlogic,function = "sdxc-b"; X amlogic,pull = "up"; X }; X X pins_sdio_c: sdio_c { X amlogic,pins = "clk", "cmd", X "d0", "d1", X "d2", "d3"; X amlogic,function = "sdio-c"; X amlogic,pull = "up"; X }; X X pins_sdxc_c: sdxc_c { X amlogic,pins = "clk", "cmd", X "d0", "d1", X "d2", "d3", X "d4", "d5", X "d6", "d7"; X amlogic,function = "sdxc-c"; X amlogic,pull = "up"; X }; X X pins_i2c_a: i2c_a { X amlogic,pins = "scl", "sda"; X amlogic,function = "i2c-a"; X }; X X pins_i2c_b: i2c_b { X amlogic,pins = "scl", "sda"; X amlogic,function = "i2c-b"; X }; X X pins_uarta: uarta { X amlogic,pins = "tx", "rx", "cts", "rts"; X amlogic,function = "uart-a"; X }; X X pins_uartb: uartb { X X /* X * gpiox18 appears to have special X * meaning to the bootloader making X * hardware handshaking unavailable. X */ X X amlogic,pins = "tx", "rx"; X amlogic,function = "uart-b"; X }; X X pins_uartc: uartc { X amlogic,pins = "tx", "rx", "cts", "rts"; X amlogic,function = "uart-c"; X }; X X pins_uartao: uartao { X amlogic,pins = "tx", "rx"; X amlogic,function = "uart-ao"; X }; X }; X X watchdog@1109900 { X compatible = "amlogic,aml8726-wdt"; X reg = <0x1109900 8>; /* cbus 0x2640 */ X interrupts = <0>; X interrupt-parent = <&gic>; X }; X X timer@1109940 { X compatible = "amlogic,aml8726-timer"; X reg = <0x1109940 24>; /* cbus 0x2650 */ X interrupts = <10 11 6 29>; X interrupt-parent = <&gic>; X }; X X rtc@8100740 { X compatible = "amlogic,aml8726-rtc"; X reg = <0x8100740 20>; /* aobus 0x1d0 */ X interrupts = <72>; 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>; 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 gpio3: gpio@1108054 { X compatible = "amlogic,aml8726-gpio"; X reg = <0x1108054 4>, /* oen cbus 0x2015 */ X <0x1108058 4>, /* out */ X <0x110805c 4>; /* in */ X X gpio-controller; X #gpio-cells = <1>; X pin-count = <32>; 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>; X interrupt-parent = <&gic>; X X pinctrl-names = "default"; X pinctrl-0 = <&pins_sdio_b>; X X /* X * Ordering is significant. X * X * mmc-vselect low sets first voltage X * mmc-vselect high sets second voltage X * X * If mmc-vselect is not present, then X * only one voltage should be specified. X */ X mmc-voltages = "3.3", "1.8"; X mmc-vselect = <&gpioao 3>; /* gpioao_3 */ X X mmc-pwr-en = <&gpio5 31 0>; /* card_8 */ X ins-detect = <&gpio5 29 0>; /* card_6 */ X }; X X sdxc@1108e00 { X compatible = "amlogic,aml8726-sdxc-m8"; X clock-frequency = <1275000000>; X reg = <0x1108e00 60>; /* cbus 0x2380 */ X interrupts = <78>; X interrupt-parent = <&gic>; X X pinctrl-names = "default"; X pinctrl-0 = <&pins_sdxc_c>; X X mmc-voltages = "1.8"; X X mmc-rst = <&gpio3 9 0>; /* boot_9 emmc-rst */ X }; X X rng@1108100 { X compatible = "amlogic,aml8726-rng"; X reg = <0x1108100 8>; /* cbus 0x2040 */ X }; X X i2c@1108500 { X /* i2c-a */ X compatible = "amlogic,aml8726-i2c"; X reg = <0x1108500 32>; /* cbus 0x2140 */ X interrupts = <21>; X interrupt-parent = <&gic>; X }; X X i2c@11087c0 { X /* i2c-b */ X compatible = "amlogic,aml8726-i2c"; X reg = <0x11087c0 32>; /* cbus 0x21f0 */ X interrupts = <128>; X interrupt-parent = <&gic>; X }; X X uart@11084c0 { X /* uart-a */ X device_type = "serial"; X compatible = "amlogic,aml8726-uart"; X clock-frequency = <0>; X current-speed = <115200>; X reg = <0x11084c0 20>; /* cbus 0x2130 */ X interrupts = <26>; X interrupt-parent = <&gic>; X }; X X uart@11084dc { X /* uart-b */ X device_type = "serial"; X compatible = "amlogic,aml8726-uart"; X clock-frequency = <0>; X current-speed = <115200>; X reg = <0x11084dc 20>; /* cbus 0x2137 */ X interrupts = <75>; X interrupt-parent = <&gic>; X }; X X uart@1108700 { X /* uart-c */ X device_type = "serial"; X compatible = "amlogic,aml8726-uart"; X clock-frequency = <0>; X current-speed = <115200>; X reg = <0x1108700 20>; /* cbus 0x21c0 */ X interrupts = <93>; X interrupt-parent = <&gic>; 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>; /* gpioao_5 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>; /* gpioao_4 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>; 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>; 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>; X interrupt-parent = <&gic>; X #address-cells = <1>; X #size-cells = <0>; X X eth-phy-rst = <&gpio3 23 0>; /* gpioh_4 phy-rst */ 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 3 12 13>; X interrupt-parent = <&gic>; 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>; /* gpioao_13 sys_led */ X label = "sys_led"; X }; X }; X X chosen { X stdin = "uart0"; X stdout = "uart0"; X }; }; SHAR_EOF (set 20 15 03 11 00 13 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 096e3dbb9e4bc289377576d78f33cd6d sys/boot/fdt/dts/arm/odroidc1.dts SHAR_EOF else test `LC_ALL=C wc -c < 'sys/boot/fdt/dts/arm/odroidc1.dts'` -ne 11593 && \ ${echo} "restoration warning: size of 'sys/boot/fdt/dts/arm/odroidc1.dts' is not 11593" 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 ccm@1104140 { X compatible = "amlogic,aml8726-ccm"; X reg = <0x1104140 20>; /* cbus 0x1050 */ X X functions = "ethernet", "i2c", "rng", "sdio", X "uart-a", "uart-b", "uart-c", X "usb-a", "usb-b"; X }; X X pinctrl: pinctrl@11080b0 { X compatible = "amlogic,aml8726-pinctrl"; X reg = <0x11080b0 40>, /* mux */ X <0x11080e8 24>, /* pu/pd */ X <0x11080e8 24>, /* pull enable */ X <0x8100014 4>, /* ao mux */ X <0x810002c 4>, /* ao pu/pd */ X <0x810002c 4>; /* ao pull enable */ X X /* X * Currently only pin muxing that deviates X * from the power on default of gpio is X * specified here. X */ X X pinctrl-names = "default"; X pinctrl-0 = <&pins_uartao &pins_ethernet &pins_hdmi>; X X pins_ethernet: ethernet { X amlogic,pins = "ref_clk_in", X "tx_clk", "tx_en", X "tx_d0", "tx_d1", X "tx_d2", "tx_d3", X "rx_clk", "rx_dv", X "rx_d0", "rx_d1", X "rx_d2", "rx_d3", X "mdc", "mdio"; X amlogic,function = "ethernet"; X }; X X pins_hdmi: hdmi { X amlogic,pins = "cec", "hpd", X "scl", "sda"; X amlogic,function = "hdmi"; X }; X X pins_sdio_b: sdio_b { X amlogic,pins = "clk", "cmd", X "d0", "d1", X "d2", "d3"; X amlogic,function = "sdio-b"; X }; X X pins_uartao: uartao { X amlogic,pins = "tx", "rx"; X amlogic,function = "uart-ao"; X }; 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 pinctrl-names = "default"; X pinctrl-0 = <&pins_sdio_b>; X X mmc-voltages = "3.3"; X X mmc-pwr-en = <&gpio5 31 0>; /* card_8 */ X ins-detect = <&gpio5 29 0>; /* card_6 */ X }; X X rng@1108100 { X compatible = "amlogic,aml8726-rng"; X reg = <0x1108100 8>; /* cbus 0x2040 */ X }; X X i2c@1108500 { X /* i2c-a */ X compatible = "amlogic,aml8726-i2c"; X reg = <0x1108500 32>; /* cbus 0x2140 */ X interrupts = <21>; X interrupt-parent = <&gic>; X }; X X i2c@11087c0 { X /* i2c-b */ X compatible = "amlogic,aml8726-i2c"; X reg = <0x11087c0 32>; /* cbus 0x21f0 */ X interrupts = <128>; X interrupt-parent = <&gic>; X }; X X uart@11084c0 { X /* uart-a */ X device_type = "serial"; X compatible = "amlogic,aml8726-uart"; X clock-frequency = <0>; X current-speed = <115200>; X reg = <0x11084c0 20>; /* cbus 0x2130 */ X interrupts = <26>; X interrupt-parent = <&gic>; X }; X X uart@11084dc { X /* uart-b */ X device_type = "serial"; X compatible = "amlogic,aml8726-uart"; X clock-frequency = <0>; X current-speed = <115200>; X reg = <0x11084dc 20>; /* cbus 0x2137 */ X interrupts = <75>; X interrupt-parent = <&gic>; X }; X X uart@1108700 { X /* uart-c */ X device_type = "serial"; X compatible = "amlogic,aml8726-uart"; X clock-frequency = <0>; X current-speed = <115200>; X reg = <0x1108700 20>; /* cbus 0x21c0 */ X interrupts = <93>; X interrupt-parent = <&gic>; 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>, /* gpioao_3 vbus */ X <&gpio6 11 0>; /* gpioe_11 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 eth-phy-rst = <&gpio5 15 0>; /* gpioy_15 phy-rst */ 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 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 03 11 00 14 12 '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 9bb8d4659ed313dcb9a0dded792de9f3 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 10320 && \ ${echo} "restoration warning: size of 'sys/boot/fdt/dts/arm/vsatv102-m6.dts' is not 10320" 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_ULE # ULE 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 iicbus device iicbb device iic 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 03 07 22 51 37 '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 e875a4e390d5fc906abd3ce066010b22 sys/arm/conf/ODROIDC1 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/conf/ODROIDC1'` -ne 4241 && \ ${echo} "restoration warning: size of 'sys/arm/conf/ODROIDC1' is not 4241" 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_ULE # ULE 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 iicbus device iicbb device iic 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 03 11 00 02 47 '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 c79c6652bb48b8b6ea17524265cd955d sys/arm/conf/VSATV102 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/conf/VSATV102'` -ne 4247 && \ ${echo} "restoration warning: size of 'sys/arm/conf/VSATV102' is not 4247" 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 Clock clock (aka gate) X X Pinctrl X X Timer X X Real time clock X X UART X X GPIO X X I2C X X SD controller X X SDXC controller X X USB X X Watchdog X X Random number generator X X PLL / Clock frequency measurement X X Frame buffer X The MAC appears to be the DWC ... it shows signs of life, however needs additional work to support the Amlogic platform. 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 The Pinctrl driver contains just a basic set of entries ... additional pins can be added as necessary. X The RTC on the ODROID-C1 requires the battery to be installed. X The SDXC driver works fine when controlling a SD card, it also seems talk to the eMMC on the ODROID-C1, however more work is necessary (some possibly at the MMC driver level) in order to support eMMC. X Enjoy, X John Wehle john@feith.com SHAR_EOF (set 20 15 03 11 00 12 53 '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 2d64a31961782bdd2116575c3564fa4e sys/arm/amlogic/aml8726/README.txt SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/README.txt'` -ne 2474 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/README.txt' is not 2474" fi fi # ============= sys/arm/amlogic/aml8726/Changes.txt ============== 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/Changes.txt' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/Changes.txt (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/Changes.txt (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/Changes.txt' && Recent changes: X X clock control (aka gate) driver has been added X X pinctrl driver has been added X X i2c driver has been added X X rtc now survives a reboot X X SDXC driver has been added X X uart driver now support rts/cts SHAR_EOF (set 20 15 03 11 00 12 45 'sys/arm/amlogic/aml8726/Changes.txt' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/Changes.txt' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/Changes.txt failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/Changes.txt': 'MD5 check failed' ) << \SHAR_EOF a06e0bd5e523707edfa4730eb0d93fdd sys/arm/amlogic/aml8726/Changes.txt SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/Changes.txt'` -ne 222 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/Changes.txt' is not 222" fi fi # ============= sys/arm/amlogic/aml8726/PatchJLW01 ============== 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/conf/options.arm =================================================================== --- sys/conf/options.arm (revision 279839) +++ 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/sys/random.h =================================================================== --- sys/sys/random.h (revision 279839) +++ 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 279839) +++ 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/dev/mmc/mmc.c =================================================================== --- sys/dev/mmc/mmc.c (revision 279839) +++ sys/dev/mmc/mmc.c (working copy) @@ -1797,6 +1797,8 @@ X }; X static devclass_t mmc_devclass; X +DRIVER_MODULE(mmc, aml8726_mmc, mmc_driver, mmc_devclass, NULL, NULL); +DRIVER_MODULE(mmc, aml8726_sdxc, 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 279839) +++ 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 SHAR_EOF (set 20 15 03 11 00 22 48 '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 6d0d6cb48c2f2ecd1c94fd5d9962d250 sys/arm/amlogic/aml8726/PatchJLW01 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/PatchJLW01'` -ne 2601 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/PatchJLW01' is not 2601" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_ccm.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_ccm.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_ccm.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_ccm.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_ccm.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 clock control module driver. X * 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 X X struct aml8726_ccm_softc { X device_t dev; X struct aml8726_ccm_function *soc; X struct resource *res[1]; X struct mtx mtx; }; X static struct resource_spec aml8726_ccm_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { -1, 0 } }; X #define AML_CCM_LOCK(sc) mtx_lock(&(sc)->mtx) #define AML_CCM_UNLOCK(sc) mtx_unlock(&(sc)->mtx) #define AML_CCM_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "ccm", MTX_DEF) #define AML_CCM_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) X X static int aml8726_ccm_configure_gates(struct aml8726_ccm_softc *sc) { X char *function_name; X char *functions; X phandle_t node; X ssize_t len; X uint32_t value; X struct aml8726_ccm_function *f; X struct aml8726_ccm_gate *g; X X node = ofw_bus_get_node(sc->dev); X X len = OF_getprop_alloc(node, "functions", X sizeof(char), (void **)&functions); X X if (len < 0) { X device_printf(sc->dev, X "missing functions attribute in FDT\n"); X return (ENXIO); X } X X function_name = functions; X X while (len) { X for (f = sc->soc; f->name != NULL; f++) X if (strncmp(f->name, function_name, len) == 0) X break; X X if (f->name == NULL) { X /* display message prior to queuing up next string */ X device_printf(sc->dev, X "unknown function attribute %.*s in FDT\n", X len, function_name); X } X X /* queue up next string */ X while (*function_name && len) { X function_name++; X len--; X } X if (len) { X function_name++; X len--; X } X X if (f->name == NULL) X continue; X X AML_CCM_LOCK(sc); X X /* X * Enable the clock gates necessary for the function. X * X * In some cases a clock may be shared across functions X * (meaning don't disable a clock without ensuring that X * it's not required by someone else). X */ X for (g = f->gates; g->bits != 0x00000000; g++) { X value = CSR_READ_4(sc, g->addr); X value |= g->bits; X CSR_WRITE_4(sc, g->addr, value); X } X X AML_CCM_UNLOCK(sc); X } X X free(functions, M_OFWPROP); X X return (0); } X X static int aml8726_ccm_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-ccm")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 ccm"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_ccm_attach(device_t dev) { X struct aml8726_ccm_softc *sc = device_get_softc(dev); X X sc->dev = dev; X X switch (aml8726_soc_hw_rev) { X case AML_SOC_HW_REV_M3: X sc->soc = aml8726_m3_ccm; X break; X case AML_SOC_HW_REV_M6: X sc->soc = aml8726_m6_ccm; X break; X case AML_SOC_HW_REV_M8: X sc->soc = aml8726_m8_ccm; X break; X case AML_SOC_HW_REV_M8B: X sc->soc = aml8726_m8b_ccm; X break; X default: X device_printf(dev, "unsupported SoC\n"); X return (ENXIO); X /* NOTREACHED */ X break; X } X X if (bus_alloc_resources(dev, aml8726_ccm_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X AML_CCM_LOCK_INIT(sc); X X return (aml8726_ccm_configure_gates(sc)); } X X static int aml8726_ccm_detach(device_t dev) { X struct aml8726_ccm_softc *sc = device_get_softc(dev); X X AML_CCM_LOCK_DESTROY(sc); X X bus_release_resources(dev, aml8726_ccm_spec, sc->res); X X return (0); } X X static device_method_t aml8726_ccm_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_ccm_probe), X DEVMETHOD(device_attach, aml8726_ccm_attach), X DEVMETHOD(device_detach, aml8726_ccm_detach), X X DEVMETHOD_END }; X static driver_t aml8726_ccm_driver = { X "ccm", X aml8726_ccm_methods, X sizeof(struct aml8726_ccm_softc), }; X static devclass_t aml8726_ccm_devclass; X EARLY_DRIVER_MODULE(ccm, simplebus, X aml8726_ccm_driver, aml8726_ccm_devclass, X 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_LATE); SHAR_EOF (set 20 15 03 05 00 35 07 'sys/arm/amlogic/aml8726/aml8726_ccm.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_ccm.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_ccm.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_ccm.c': 'MD5 check failed' ) << \SHAR_EOF bda662cd6b68a85557e492703de968aa sys/arm/amlogic/aml8726/aml8726_ccm.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_ccm.c'` -ne 5695 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_ccm.c' is not 5695" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_ccm.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_ccm.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_ccm.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_ccm.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_ccm.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_CCM_H #define _ARM_AMLOGIC_AML8726_CCM_H X X struct aml8726_ccm_gate { X uint32_t addr; X uint32_t bits; }; X struct aml8726_ccm_function { X const char *name; X struct aml8726_ccm_gate *gates; }; X X /* X * aml8726-m3 X */ X static struct aml8726_ccm_gate aml8726_m3_ethernet[] = { { 4, 0x00000008 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_i2c[] = { { 0, 0x00000200 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_rng[] = { { 0, 0x00001000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_sdio[] = { { 0, 0x00020000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_sdxc[] = { { 0, 0x00004000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_uart_a[] = { { 0, 0x00002000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_uart_b[] = { { 4, 0x00010000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_uart_c[] = { { 8, 0x00008000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_usb_a[] = { { 4, 0x00200000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m3_usb_b[] = { { 4, 0x00400000 }, { 0, 0x00000000 } }; X struct aml8726_ccm_function aml8726_m3_ccm[] = { { "ethernet", aml8726_m3_ethernet }, { "i2c", aml8726_m3_i2c }, { "rng", aml8726_m3_rng }, { "sdio", aml8726_m3_sdio }, { "sdxc", aml8726_m3_sdxc }, { "uart-a", aml8726_m3_uart_a }, { "uart-b", aml8726_m3_uart_b }, { "uart-c", aml8726_m3_uart_c }, { "usb-a", aml8726_m3_usb_a }, { "usb-b", aml8726_m3_usb_b }, { NULL } }; X X /* X * aml8726-m6 X */ X static struct aml8726_ccm_gate aml8726_m6_ethernet[] = { { 4, 0x00000008 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_i2c[] = { { 0, 0x00000200 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_rng[] = { { 0, 0x00001000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_sdio[] = { { 0, 0x00020000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_sdxc[] = { { 0, 0x00004000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_uart_a[] = { { 0, 0x00002000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_uart_b[] = { { 4, 0x00010000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_uart_c[] = { { 8, 0x00008000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_usb_a[] = { { 4, 0x00200000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m6_usb_b[] = { { 4, 0x00400000 }, { 0, 0x00000000 } }; X struct aml8726_ccm_function aml8726_m6_ccm[] = { { "ethernet", aml8726_m6_ethernet }, { "i2c", aml8726_m6_i2c }, { "rng", aml8726_m6_rng }, { "sdio", aml8726_m6_sdio }, { "sdxc", aml8726_m6_sdxc }, { "uart-a", aml8726_m6_uart_a }, { "uart-b", aml8726_m6_uart_b }, { "uart-c", aml8726_m6_uart_c }, { "usb-a", aml8726_m6_usb_a }, { "usb-b", aml8726_m6_usb_b }, { NULL } }; X X /* X * aml8726-m8 X */ X static struct aml8726_ccm_gate aml8726_m8_ethernet[] = { { 4, 0x00000008 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_i2c[] = { { 0, 0x00000200 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_rng[] = { { 0, 0x00001000 }, { 16, 0x00200000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_sdio[] = { { 0, 0x00020000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_sdxc[] = { { 0, 0x00004000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_uart_a[] = { { 0, 0x00002000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_uart_b[] = { { 4, 0x00010000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_uart_c[] = { { 8, 0x00008000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_usb_a[] = { { 4, 0x00200000 }, { 4, 0x04000000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8_usb_b[] = { { 4, 0x00400000 }, { 4, 0x04000000 }, { 0, 0x00000000 } }; X struct aml8726_ccm_function aml8726_m8_ccm[] = { { "ethernet", aml8726_m8_ethernet }, { "i2c", aml8726_m8_i2c }, { "rng", aml8726_m8_rng }, { "sdio", aml8726_m8_sdio }, { "sdxc", aml8726_m8_sdxc }, { "uart-a", aml8726_m8_uart_a }, { "uart-b", aml8726_m8_uart_b }, { "uart-c", aml8726_m8_uart_c }, { "usb-a", aml8726_m8_usb_a }, { "usb-b", aml8726_m8_usb_b }, { NULL } }; X X /* X * aml8726-m8b X */ X static struct aml8726_ccm_gate aml8726_m8b_ethernet[] = { { 4, 0x00000008 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_i2c[] = { { 0, 0x00000200 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_rng[] = { { 0, 0x00001000 }, { 16, 0x00200000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_sdio[] = { { 0, 0x00020000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_sdxc[] = { { 0, 0x00004000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_uart_a[] = { { 0, 0x00002000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_uart_b[] = { { 4, 0x00010000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_uart_c[] = { { 8, 0x00008000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_usb_a[] = { { 4, 0x00200000 }, { 4, 0x04000000 }, { 0, 0x00000000 } }; X static struct aml8726_ccm_gate aml8726_m8b_usb_b[] = { { 4, 0x00400000 }, { 4, 0x04000000 }, { 0, 0x00000000 } }; X struct aml8726_ccm_function aml8726_m8b_ccm[] = { { "ethernet", aml8726_m8b_ethernet }, { "i2c", aml8726_m8b_i2c }, { "rng", aml8726_m8b_rng }, { "sdio", aml8726_m8b_sdio }, { "sdxc", aml8726_m8b_sdxc }, { "uart-a", aml8726_m8b_uart_a }, { "uart-b", aml8726_m8b_uart_b }, { "uart-c", aml8726_m8b_uart_c }, { "usb-a", aml8726_m8b_usb_a }, { "usb-b", aml8726_m8b_usb_b }, { NULL } }; X X #endif /* _ARM_AMLOGIC_AML8726_CCM_H */ SHAR_EOF (set 20 15 03 10 00 12 47 'sys/arm/amlogic/aml8726/aml8726_ccm.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_ccm.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_ccm.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_ccm.h': 'MD5 check failed' ) << \SHAR_EOF 58239843bc0e1ef976b4c7c6d9bffd0c sys/arm/amlogic/aml8726/aml8726_ccm.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_ccm.h'` -ne 7169 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_ccm.h' is not 7169" 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[] = { { "clk81", 7 }, }; X #define AML_CLKMSR_CLK81 0 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 03 05 02 12 17 '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 c046ceaa9125b8c5a1fa68d6db8086ea sys/arm/amlogic/aml8726/aml8726_clkmsr.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c'` -ne 7269 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c' is not 7269" 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 15 03 05 02 12 23 '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 return (0); } X X static int aml8726_gpio_detach(device_t dev) { X struct aml8726_gpio_softc *sc = device_get_softc(dev); 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 02 20 22 07 43 '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 556953ec937c19e5b7618428a686ff39 sys/arm/amlogic/aml8726/aml8726_gpio.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_gpio.c'` -ne 9100 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_gpio.c' is not 9100" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_i2c.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_i2c.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_i2c.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_i2c.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_i2c.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 I2C driver. X * X * Currently this implementation doesn't take full advantage of the hardware. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include #include X #include X #include #include #include X #include #include X #include "iicbb_if.h" X X struct aml8726_iic_softc { X device_t dev; X struct resource *res[1]; X struct mtx mtx; X device_t iicbb; }; X static struct resource_spec aml8726_iic_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { -1, 0 } }; X #define AML_I2C_LOCK(sc) mtx_lock(&(sc)->mtx) #define AML_I2C_UNLOCK(sc) mtx_unlock(&(sc)->mtx) #define AML_I2C_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "i2c", MTX_DEF) #define AML_I2C_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); X #define AML_I2C_CTRL_REG 0 # define AML_I2C_MANUAL_SDA_I (1 << 26) # define AML_I2C_MANUAL_SCL_I (1 << 25) # define AML_I2C_MANUAL_SDA_O (1 << 24) # define AML_I2C_MANUAL_SCL_O (1 << 23) # define AML_I2C_MANUAL_EN (1 << 22) 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 int aml8726_iic_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-i2c")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 I2C"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_iic_attach(device_t dev) { X struct aml8726_iic_softc *sc = device_get_softc(dev); X int error; X X sc->dev = dev; X X if (bus_alloc_resources(dev, aml8726_iic_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X AML_I2C_LOCK_INIT(sc); X X sc->iicbb = device_add_child(dev, "iicbb", -1); X X if (sc->iicbb == NULL) { X device_printf(dev, "could not add iicbb\n"); X error = ENXIO; X goto fail; X } X X error = device_probe_and_attach(sc->iicbb); X X if (error) { X device_printf(dev, "could not attach iicbb\n"); X goto fail; X } X X return (0); X fail: X AML_I2C_LOCK_DESTROY(sc); X bus_release_resources(dev, aml8726_iic_spec, sc->res); X X return (error); } X X static int aml8726_iic_detach(device_t dev) { X struct aml8726_iic_softc *sc = device_get_softc(dev); X device_t child; X X /* X * Detach the children before recursively deleting X * in case a child has a pointer to a grandchild X * which is used by the child's detach routine. X * X * Remember the child before detaching so we can X * delete it (bus_generic_detach indirectly zeroes X * sc->child_dev). X */ X child = sc->iicbb; X bus_generic_detach(dev); X if (child) X device_delete_child(dev, child); X X AML_I2C_LOCK_DESTROY(sc); X X bus_release_resources(dev, aml8726_iic_spec, sc->res); X X return (0); } X X static void aml8726_iic_child_detached(device_t dev, device_t child) { X struct aml8726_iic_softc *sc = device_get_softc(dev); X X if (child == sc->iicbb) X sc->iicbb = NULL; } X X static int aml8726_iic_callback(device_t dev, int index, caddr_t data) { X return (0); } X X static int aml8726_iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { X struct aml8726_iic_softc *sc = device_get_softc(dev); X X AML_I2C_LOCK(sc); X X CSR_WRITE_4(sc, AML_I2C_CTRL_REG, X (CSR_READ_4(sc, AML_I2C_CTRL_REG) X | AML_I2C_MANUAL_SDA_O | AML_I2C_MANUAL_SCL_O X | AML_I2C_MANUAL_EN)); X X AML_I2C_UNLOCK(sc); X X /* Wait for 10 usec */ X DELAY(10); X X return (IIC_ENOADDR); } X X static int aml8726_iic_getscl(device_t dev) { X struct aml8726_iic_softc *sc = device_get_softc(dev); X X return (CSR_READ_4(sc, AML_I2C_CTRL_REG) & AML_I2C_MANUAL_SCL_I); } X X static int aml8726_iic_getsda(device_t dev) { X struct aml8726_iic_softc *sc = device_get_softc(dev); X X return (CSR_READ_4(sc, AML_I2C_CTRL_REG) & AML_I2C_MANUAL_SDA_I); } X X static void aml8726_iic_setscl(device_t dev, int val) { X struct aml8726_iic_softc *sc = device_get_softc(dev); X X AML_I2C_LOCK(sc); X X CSR_WRITE_4(sc, AML_I2C_CTRL_REG, X ((CSR_READ_4(sc, AML_I2C_CTRL_REG) & ~AML_I2C_MANUAL_SCL_O) X | (val ? AML_I2C_MANUAL_SCL_O : 0) | AML_I2C_MANUAL_EN)); X X AML_I2C_UNLOCK(sc); } X X static void aml8726_iic_setsda(device_t dev, int val) { X struct aml8726_iic_softc *sc = device_get_softc(dev); X X AML_I2C_LOCK(sc); X X CSR_WRITE_4(sc, AML_I2C_CTRL_REG, X ((CSR_READ_4(sc, AML_I2C_CTRL_REG) & ~AML_I2C_MANUAL_SDA_O) X | (val ? AML_I2C_MANUAL_SDA_O : 0) | AML_I2C_MANUAL_EN)); X X AML_I2C_UNLOCK(sc); } X X static device_method_t aml8726_iic_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_iic_probe), X DEVMETHOD(device_attach, aml8726_iic_attach), X DEVMETHOD(device_detach, aml8726_iic_detach), X X /* bus interface */ X DEVMETHOD(bus_child_detached, aml8726_iic_child_detached), X DEVMETHOD(bus_print_child, bus_generic_print_child), X DEVMETHOD(bus_driver_added, bus_generic_driver_added), X X /* IICBB interface */ X DEVMETHOD(iicbb_callback, aml8726_iic_callback), X DEVMETHOD(iicbb_reset, aml8726_iic_reset), X X DEVMETHOD(iicbb_getscl, aml8726_iic_getscl), X DEVMETHOD(iicbb_getsda, aml8726_iic_getsda), X DEVMETHOD(iicbb_setscl, aml8726_iic_setscl), X DEVMETHOD(iicbb_setsda, aml8726_iic_setsda), X X DEVMETHOD_END }; X static driver_t aml8726_iic_driver = { X "aml8726_iic", X aml8726_iic_methods, X sizeof(struct aml8726_iic_softc), }; X static devclass_t aml8726_iic_devclass; X DRIVER_MODULE(aml8726_iic, simplebus, aml8726_iic_driver, aml8726_iic_devclass, 0, 0); DRIVER_MODULE(iicbb, aml8726_iic, iicbb_driver, iicbb_devclass, 0, 0); MODULE_DEPEND(aml8726_iic, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); MODULE_VERSION(aml8726_iic, 1); SHAR_EOF (set 20 15 02 26 15 17 19 'sys/arm/amlogic/aml8726/aml8726_i2c.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_i2c.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_i2c.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_i2c.c': 'MD5 check failed' ) << \SHAR_EOF 5b3c5fa8a2c350ed216090cafa280220 sys/arm/amlogic/aml8726/aml8726_i2c.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_i2c.c'` -ne 7239 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_i2c.c' is not 7239" 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_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 03 06 01 10 30 '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 b8040f9e801abe912f6a8301b443c5dd sys/arm/amlogic/aml8726/aml8726_identsoc.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_identsoc.c'` -ne 4195 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_identsoc.c' is not 4195" 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 uint32_t port; X unsigned int ref_freq; X struct aml8726_mmc_gpio pwr_en; X int voltages[2]; X struct aml8726_mmc_gpio vselect; 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_power_off(struct aml8726_mmc_softc *sc) { X X if (sc->pwr_en.dev == NULL) X return (0); X X return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PWR_OFF_FLAG(sc->pwr_en.pol))); } X X static int aml8726_mmc_power_on(struct aml8726_mmc_softc *sc) { X X if (sc->pwr_en.dev == NULL) X return (0); X X return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PWR_ON_FLAG(sc->pwr_en.pol))); } 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_msec; 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_BARRIER(sc, AML_MMC_IRQ_CONFIG_REG); 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 = sc->port; 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 if ((cmd->flags & MMC_RSP_CRC) == 0) X cmdr |= AML_MMC_CMD_RESP_NO_CRC7; X X if ((cmd->flags & MMC_RSP_BUSY) != 0) X cmdr |= AML_MMC_CMD_CHECK_DAT0_BUSY; 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 millisecond. Use that to determine X * the count from the desired timeout in milliseconds. 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 if (timeout > AML_MMC_MAX_TIMEOUT) X timeout = AML_MMC_MAX_TIMEOUT; X cycles_per_msec = (ios->clock + 1000 - 1) / 1000; X sc->timeout_remaining = 48 + 136 + timeout * cycles_per_msec; 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 X CSR_WRITE_4(sc, AML_MMC_CMD_SEND_REG, cmdr); X CSR_BARRIER(sc, AML_MMC_CMD_SEND_REG); 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 AML_MMC_LOCK(sc); X X isr = CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG); X cmdr = CSR_READ_4(sc, AML_MMC_CMD_SEND_REG); X X if (sc->cmd == NULL) X goto spurious; X X mmc_error = MMC_ERR_NONE; 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 { spurious: 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 CSR_BARRIER(sc, AML_MMC_IRQ_STATUS_REG); X AML_MMC_UNLOCK(sc); X return; X } X X if ((isr & AML_MMC_IRQ_STATUS_CMD_BUSY) != 0 X /* X * A multiblock operation may keep the hardware X * busy until stop transmission is executed. X */ X && (isr & AML_MMC_IRQ_STATUS_CMD_DONE_IRQ) == 0) { X if (mmc_error == MMC_ERR_NONE) 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 CSR_BARRIER(sc, AML_MMC_IRQ_STATUS_REG); X X cmd = sc->cmd; X sc->cmd = NULL; X X cmd->error = mmc_error; X X if ((cmd->flags & MMC_RSP_PRESENT) != 0 X && mmc_error == MMC_ERR_NONE) { X mcfgr = sc->port; 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 there's a linked stop command, then start the stop command. X * In order to establish a known state attempt the stop command X * even if the original request encountered an error. X */ X X stop_cmd = (cmd->mrq->stop != cmd) ? cmd->mrq->stop : NULL; X X if (stop_cmd != NULL) { 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 char *function_name; X char *voltages; X char *voltage; X int error; X int nvoltages; X pcell_t prop[3]; X phandle_t node; X ssize_t len; 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 /* X * The pins must be specified as part of the device in order X * to know which port to used. X */ X X len = OF_getencprop(node, "pinctrl-0", prop, sizeof(prop)); X X if ((len / sizeof(prop[0])) != 1 || prop[0] == 0) { X device_printf(dev, "missing pinctrl-0 attribute in FDT\n"); X return (ENXIO); X } X X len = OF_getprop_alloc(OF_node_from_xref(prop[0]), "amlogic,function", X sizeof(char), (void **)&function_name); X X if (len < 0) { X device_printf(dev, X "missing amlogic,function attribute in FDT\n"); X return (ENXIO); X } X X if (strncmp("sdio-a", function_name, len) == 0) X sc->port = AML_MMC_MULT_CONFIG_PORT_A; X else if (strncmp("sdio-b", function_name, len) == 0) X sc->port = AML_MMC_MULT_CONFIG_PORT_B; X else if (strncmp("sdio-c", function_name, len) == 0) X sc->port = AML_MMC_MULT_CONFIG_PORT_C; X else { X device_printf(dev, "unknown function attribute %.*s in FDT\n", X len, function_name); X free(function_name, M_OFWPROP); X return (ENXIO); X } X X free(function_name, M_OFWPROP); X X sc->pwr_en.dev = NULL; X X len = OF_getencprop(node, "mmc-pwr-en", prop, sizeof(prop)); X if (len > 0) { X if ((len / sizeof(prop[0])) == 3) { X sc->pwr_en.dev = OF_device_from_xref(prop[0]); X sc->pwr_en.pin = prop[1]; X sc->pwr_en.pol = prop[2]; X } X X if (sc->pwr_en.dev == NULL) { X device_printf(dev, X "unable to process mmc-pwr-en attribute in FDT\n"); X return (ENXIO); X } X X /* Turn off power and then configure the output driver. */ X if (aml8726_mmc_power_off(sc) != 0 X || GPIO_PIN_SETFLAGS(sc->pwr_en.dev, sc->pwr_en.pin, X GPIO_PIN_OUTPUT) != 0) { X device_printf(dev, X "could not use gpio to control power\n"); X return (ENXIO); X } X } X X len = OF_getprop_alloc(node, "mmc-voltages", X sizeof(char), (void **)&voltages); X X if (len < 0) { X device_printf(dev, "missing mmc-voltages attribute in FDT\n"); X return (ENXIO); X } X X sc->voltages[0] = 0; X sc->voltages[1] = 0; X X voltage = voltages; X nvoltages = 0; X X while (len && nvoltages < 2) { X if (strncmp("1.8", voltage, len) == 0) X sc->voltages[nvoltages] = MMC_OCR_LOW_VOLTAGE; X else if (strncmp("3.3", voltage, len) == 0) X sc->voltages[nvoltages] = MMC_OCR_320_330 X | MMC_OCR_330_340; X else { X device_printf(dev, X "unknown voltage attribute %.*s in FDT\n", X len, voltage); X free(voltages, M_OFWPROP); X return (ENXIO); X } X X nvoltages++; X X /* queue up next string */ X while (*voltage && len) { X voltage++; X len--; X } X if (len) { X voltage++; X len--; X } X } X X free(voltages, M_OFWPROP); X X sc->vselect.dev = NULL; X X len = OF_getencprop(node, "mmc-vselect", prop, sizeof(prop)); X if (len > 0) { X if ((len / sizeof(prop[0])) == 2) { X sc->vselect.dev = OF_device_from_xref(prop[0]); X sc->vselect.pin = prop[1]; X sc->vselect.pol = 1; X } X X if (sc->vselect.dev == NULL) { X device_printf(dev, X "unable to process mmc-vselect attribute in FDT\n"); X return (ENXIO); X } X X /* X * With the power off select voltage 0 and then X * configure the output driver. X */ X if (GPIO_PIN_SET(sc->vselect.dev, sc->vselect.pin, 0) != 0 X || GPIO_PIN_SETFLAGS(sc->vselect.dev, sc->vselect.pin, X GPIO_PIN_OUTPUT) != 0) { X device_printf(dev, X "could not use gpio to set voltage\n"); X return (ENXIO); X } X } X X if (nvoltages == 0) { X device_printf(dev, "no voltages in FDT\n"); X return (ENXIO); X } else if (nvoltages == 1 && sc->vselect.dev != NULL) { X device_printf(dev, "only one voltage in FDT\n"); X return (ENXIO); X } else if (nvoltages == 2 && sc->vselect.dev == NULL) { X device_printf(dev, "too many voltages in FDT\n"); X return (ENXIO); X } 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 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 = sc->voltages[0] | sc->voltages[1]; X sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_HSPEED; X X child = device_add_child(dev, "mmc", -1); 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)aml8726_mmc_power_off(sc); 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)aml8726_mmc_power_off(sc); X CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, AML_MMC_IRQ_CONFIG_SOFT_RESET); X CSR_BARRIER(sc, AML_MMC_IRQ_CONFIG_REG); 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)aml8726_mmc_power_off(sc); X CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, AML_MMC_IRQ_CONFIG_SOFT_RESET); X CSR_BARRIER(sc, AML_MMC_IRQ_CONFIG_REG); 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 unsigned int divisor; X int error; X int i; 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 * Configure and power on the regulator so that the X * voltage stabilizes prior to powering on the card. X */ X if (sc->vselect.dev != NULL) { X for (i = 0; i < 2; i++) X if ((sc->voltages[i] & (1 << ios->vdd)) != 0) X break; X if (i >= 2) X return (EINVAL); X error = GPIO_PIN_SET(sc->vselect.dev, X sc->vselect.pin, i); X } X break; X case power_on: X error = aml8726_mmc_power_on(sc); X break; X case power_off: X error = aml8726_mmc_power_off(sc); 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 03 09 13 00 03 '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 7cea1ea884b82691dba0cbf8eb2e0b9f sys/arm/amlogic/aml8726/aml8726_mmc.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mmc.c'` -ne 25894 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_mmc.c' is not 25894" 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-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_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 milliseconds 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 50 #define AML_MMC_READ_TIMEOUT 100 #define AML_MMC_WRITE_TIMEOUT 500 #define AML_MMC_MAX_TIMEOUT 5000 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 * 1000) < 4112 \ X || (AML_MMC_WRITE_TIMEOUT * 1000) < 4112) # error "Single block timeout is smaller 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 # define AML_MMC_MULT_CONFIG_PORT_C 2 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 03 07 22 35 31 '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 42a574da34b07d29e625474d538433b0 sys/arm/amlogic/aml8726/aml8726_mmc.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mmc.h'` -ne 5999 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_mmc.h' is not 5999" 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 X * on the aobus and cbus ... it's expected that these locations are set X * 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_MIDDLE); SHAR_EOF (set 20 15 02 19 03 30 09 '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 c6c2543a9df1f98e1154c3c4c04d93bc sys/arm/amlogic/aml8726/aml8726_mp.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mp.c'` -ne 17662 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_mp.c' is not 17662" 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_pinctrl.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_pinctrl.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_pinctrl.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_pinctrl.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_pinctrl.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 pinctrl driver. X * X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include #include #include #include #include X #include X #include #include #include #include X #include #include X X struct aml8726_pinctrl_softc { X device_t dev; X struct { X struct aml8726_pinctrl_function *func; X struct aml8726_pinctrl_pkg_pin *ppin; X boolean_t pud_ctrl; X } soc; X struct resource *res[6]; X struct mtx mtx; }; X static struct resource_spec aml8726_pinctrl_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* mux */ X { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_SHAREABLE }, /* pu/pd */ X { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_SHAREABLE }, /* pull enable */ X { SYS_RES_MEMORY, 3, RF_ACTIVE }, /* ao mux */ X { SYS_RES_MEMORY, 4, RF_ACTIVE | RF_SHAREABLE }, /* ao pu/pd */ X { SYS_RES_MEMORY, 5, RF_ACTIVE | RF_SHAREABLE }, /* ao pull enable */ X { -1, 0 } }; X #define AML_PINCTRL_LOCK(sc) mtx_lock(&(sc)->mtx) #define AML_PINCTRL_UNLOCK(sc) mtx_unlock(&(sc)->mtx) #define AML_PINCTRL_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "pinctrl", MTX_DEF) #define AML_PINCTRL_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); X #define MUX_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) #define MUX_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) X #define PUD_WRITE_4(sc, reg, val) bus_write_4((sc)->res[1], reg, (val)) #define PUD_READ_4(sc, reg) bus_read_4((sc)->res[1], reg) X #define PEN_WRITE_4(sc, reg, val) bus_write_4((sc)->res[2], reg, (val)) #define PEN_READ_4(sc, reg) bus_read_4((sc)->res[2], reg) X #define AOMUX_WRITE_4(sc, reg, val) bus_write_4((sc)->res[3], reg, (val)) #define AOMUX_READ_4(sc, reg) bus_read_4((sc)->res[3], reg) X #define AOPUD_WRITE_4(sc, reg, val) bus_write_4((sc)->res[4], reg, (val)) #define AOPUD_READ_4(sc, reg) bus_read_4((sc)->res[4], reg) X #define AOPEN_WRITE_4(sc, reg, val) bus_write_4((sc)->res[5], reg, (val)) #define AOPEN_READ_4(sc, reg) bus_read_4((sc)->res[5], reg) X X static int aml8726_pinctrl_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-pinctrl")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726 pinctrl"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_pinctrl_attach(device_t dev) { X struct aml8726_pinctrl_softc *sc = device_get_softc(dev); X X sc->dev = dev; X X sc->soc.pud_ctrl = false; X X switch (aml8726_soc_hw_rev) { X case AML_SOC_HW_REV_M3: X sc->soc.func = aml8726_m3_pinctrl; X sc->soc.ppin = aml8726_m3_pkg_pin; X break; X case AML_SOC_HW_REV_M6: X sc->soc.func = aml8726_m6_pinctrl; X sc->soc.ppin = aml8726_m6_pkg_pin; X break; X case AML_SOC_HW_REV_M8: X sc->soc.func = aml8726_m8_pinctrl; X sc->soc.ppin = aml8726_m8_pkg_pin; X sc->soc.pud_ctrl = true; X break; X case AML_SOC_HW_REV_M8B: X sc->soc.func = aml8726_m8b_pinctrl; X sc->soc.ppin = aml8726_m8b_pkg_pin; X sc->soc.pud_ctrl = true; X break; X default: X device_printf(dev, "unsupported SoC\n"); X return (ENXIO); X /* NOTREACHED */ X break; X } X X if (bus_alloc_resources(dev, aml8726_pinctrl_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X AML_PINCTRL_LOCK_INIT(sc); X X fdt_pinctrl_register(dev, "amlogic,pins"); X fdt_pinctrl_configure_tree(dev); X X return (0); } X X static int aml8726_pinctrl_detach(device_t dev) { X struct aml8726_pinctrl_softc *sc = device_get_softc(dev); X X AML_PINCTRL_LOCK_DESTROY(sc); X X bus_release_resources(dev, aml8726_pinctrl_spec, sc->res); X X return (0); } X X static int aml8726_pinctrl_configure_pins(device_t dev, phandle_t cfgxref) { X struct aml8726_pinctrl_softc *sc = device_get_softc(dev); X char *function_name; X char *pins; X char *pin_name; X char *pull; X phandle_t node; X ssize_t len; X uint32_t value; X enum aml8726_pinctrl_pull_mode pm; X struct aml8726_pinctrl_function *cf; X struct aml8726_pinctrl_function *f; X struct aml8726_pinctrl_pkg_pin *pp; X struct aml8726_pinctrl_pin *cp; X struct aml8726_pinctrl_pin *p; X X node = OF_node_from_xref(cfgxref); X X len = OF_getprop_alloc(node, "amlogic,function", X sizeof(char), (void **)&function_name); X X if (len < 0) { X device_printf(dev, X "missing amlogic,function attribute in FDT\n"); X return (ENXIO); X } X X for (f = sc->soc.func; f->name != NULL; f++) X if (strncmp(f->name, function_name, len) == 0) X break; X X if (f->name == NULL) { X device_printf(dev, "unknown function attribute %.*s in FDT\n", X len, function_name); X free(function_name, M_OFWPROP); X return (ENXIO); X } X X free(function_name, M_OFWPROP); X X len = OF_getprop_alloc(node, "amlogic,pull", X sizeof(char), (void **)&pull); X X pm = aml8726_unknown_pm; X X if (len > 0) { X if (strncmp(pull, "enable", len) == 0) X pm = aml8726_enable_pm; X else if (strncmp(pull, "disable", len) == 0) X pm = aml8726_disable_pm; X else if (strncmp(pull, "down", len) == 0) X pm = aml8726_enable_down_pm; X else if (strncmp(pull, "up", len) == 0) X pm = aml8726_enable_up_pm; X else { X device_printf(dev, X "unknown pull attribute %.*s in FDT\n", X len, pull); X free(pull, M_OFWPROP); X return (ENXIO); X } X } X X free(pull, M_OFWPROP); X X /* X * Setting the pull direction isn't supported on all SoC. X */ X switch (pm) { X case aml8726_enable_down_pm: X case aml8726_enable_up_pm: X if (sc->soc.pud_ctrl == false) { X device_printf(dev, X "SoC doesn't support setting pull direction.\n"); X return (ENXIO); X } X break; X default: X break; X } X X len = OF_getprop_alloc(node, "amlogic,pins", X sizeof(char), (void **)&pins); X X if (len < 0) { X device_printf(dev, "missing amlogic,pins attribute in FDT\n"); X return (ENXIO); X } X X pin_name = pins; X X while (len) { X for (p = f->pins; p->name != NULL; p++) X if (strncmp(p->name, pin_name, len) == 0) X break; X X if (p->name == NULL) { X /* display message prior to queuing up next string */ X device_printf(dev, "unknown pin attribute %.*s in FDT\n", X len, pin_name); X } X X /* queue up next string */ X while (*pin_name && len) { X pin_name++; X len--; X } X if (len) { X pin_name++; X len--; X } X X if (p->name == NULL) X continue; X X for (pp = sc->soc.ppin; pp->pkg_name != NULL; pp++) X if (strcmp(pp->pkg_name, p->pkg_name) == 0) X break; X X if (pp->pkg_name == NULL) { X device_printf(dev, X "missing entry for package pin %s\n", X p->pkg_name); X continue; X } X X if (pm != aml8726_unknown_pm && pp->pull_bits == 0x00000000) { X device_printf(dev, X "missing pull info for package pin %s\n", X p->pkg_name); X continue; X } X X AML_PINCTRL_LOCK(sc); X X /* X * First clear all other mux bits associated with this X * package pin. This may briefly configure the pin as X * GPIO ... however this should be fine since after X * reset the default GPIO mode is input. X */ X X for (cf = sc->soc.func; cf->name != NULL; cf++) X for (cp = cf->pins; cp->name != NULL; cp++) { X if (cp == p) X continue; X if (strcmp(cp->pkg_name, p->pkg_name) != 0) X continue; X if (cp->mux_bits == 0) X continue; X if (pp->aobus == false) { X value = MUX_READ_4(sc, cp->mux_addr); X value &= ~cp->mux_bits; X MUX_WRITE_4(sc, cp->mux_addr, value); X } else { X value = AOMUX_READ_4(sc, cp->mux_addr); X value &= ~cp->mux_bits; X AOMUX_WRITE_4(sc, cp->mux_addr, value); X } X } X X /* X * Now set the desired mux bits. X * X * In the case of GPIO there's no bits to set. X */ X X if (p->mux_bits != 0) { X if (pp->aobus == false) { X value = MUX_READ_4(sc, p->mux_addr); X value |= p->mux_bits; X MUX_WRITE_4(sc, p->mux_addr, value); X } else { X value = AOMUX_READ_4(sc, p->mux_addr); X value |= p->mux_bits; X AOMUX_WRITE_4(sc, p->mux_addr, value); X } X } X X /* X * Finally set the pull mode if it was specified. X */ X X switch (pm) { X case aml8726_enable_down_pm: X case aml8726_enable_up_pm: X if (pp->aobus == false) { X value = PUD_READ_4(sc, pp->pull_addr); X if (pm == aml8726_enable_down_pm) X value &= ~pp->pull_bits; X else X value |= pp->pull_bits; X PUD_WRITE_4(sc, pp->pull_addr, value); X } else { X value = AOPUD_READ_4(sc, pp->pull_addr); X if (pm == aml8726_enable_down_pm) X value &= ~(pp->pull_bits << 16); X else X value |= (pp->pull_bits << 16); X AOPUD_WRITE_4(sc, pp->pull_addr, value); X } X /* FALLTHROUGH */ X case aml8726_disable_pm: X case aml8726_enable_pm: X if (pp->aobus == false) { X value = PEN_READ_4(sc, pp->pull_addr); X if (pm == aml8726_disable_pm) X value &= ~pp->pull_bits; X else X value |= pp->pull_bits; X PEN_WRITE_4(sc, pp->pull_addr, value); X } else { X value = AOPEN_READ_4(sc, pp->pull_addr); X if (pm == aml8726_disable_pm) X value &= ~pp->pull_bits; X else X value |= pp->pull_bits; X AOPEN_WRITE_4(sc, pp->pull_addr, value); X } X break; X default: X break; X } X X AML_PINCTRL_UNLOCK(sc); X } X X free(pins, M_OFWPROP); X X return (0); } X X static device_method_t aml8726_pinctrl_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_pinctrl_probe), X DEVMETHOD(device_attach, aml8726_pinctrl_attach), X DEVMETHOD(device_detach, aml8726_pinctrl_detach), X X /* fdt_pinctrl interface */ X DEVMETHOD(fdt_pinctrl_configure,aml8726_pinctrl_configure_pins), X X DEVMETHOD_END }; X static driver_t aml8726_pinctrl_driver = { X "pinctrl", X aml8726_pinctrl_methods, X sizeof(struct aml8726_pinctrl_softc), }; X static devclass_t aml8726_pinctrl_devclass; X EARLY_DRIVER_MODULE(pinctrl, simplebus, X aml8726_pinctrl_driver, aml8726_pinctrl_devclass, X 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_LATE); SHAR_EOF (set 20 15 03 09 00 15 48 'sys/arm/amlogic/aml8726/aml8726_pinctrl.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_pinctrl.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_pinctrl.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_pinctrl.c': 'MD5 check failed' ) << \SHAR_EOF bc923d0a36fe720ae5e65c792a07e5ed sys/arm/amlogic/aml8726/aml8726_pinctrl.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_pinctrl.c'` -ne 11267 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_pinctrl.c' is not 11267" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_pinctrl.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_pinctrl.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_pinctrl.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_pinctrl.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_pinctrl.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 /* X * In addition to supplying entries for pins which need to be configured X * by the operating system it's also necessary to supply entries for pins X * which may have been configured by the firmware for a different purpose. X */ X #ifndef _ARM_AMLOGIC_AML8726_PINCTRL_H #define _ARM_AMLOGIC_AML8726_PINCTRL_H X X enum aml8726_pinctrl_pull_mode { aml8726_unknown_pm, X aml8726_disable_pm, aml8726_enable_pm, X aml8726_enable_down_pm, aml8726_enable_up_pm }; X struct aml8726_pinctrl_pkg_pin { X const char *pkg_name; X boolean_t aobus; X uint32_t pull_addr; X uint32_t pull_bits; }; X struct aml8726_pinctrl_pin { X const char *name; X const char *pkg_name; X uint32_t mux_addr; X uint32_t mux_bits; }; X struct aml8726_pinctrl_function { X const char *name; X struct aml8726_pinctrl_pin *pins; }; X X /* X * aml8726-m3 X * X * start size X * cbus mux 0x202c 36 X * cbus pu_pd 0x203a 24 X * cbus pull_en 0x203a 24 X * aobus mux 0x0005 4 X * aobus pu_pd 0x000b 4 X * aobus pull_en 0x000b 4 X */ X static struct aml8726_pinctrl_pkg_pin aml8726_m3_pkg_pin[] = { { "card_0", false, 0, 0x00000000 }, { "card_1", false, 0, 0x00000000 }, { "card_2", false, 0, 0x00000000 }, { "card_3", false, 0, 0x00000000 }, { "card_4", false, 0, 0x00000000 }, { "card_5", false, 0, 0x00000000 }, { "card_6", false, 0, 0x00000000 }, X { "gpioc_10", false, 0, 0x00000000 }, { "gpioc_11", false, 0, 0x00000000 }, { "gpioc_12", false, 0, 0x00000000 }, { "gpioc_13", false, 0, 0x00000000 }, X { "gpiox_13", false, 0, 0x00000000 }, { "gpiox_14", false, 0, 0x00000000 }, { "gpiox_15", false, 0, 0x00000000 }, { "gpiox_16", false, 0, 0x00000000 }, { "gpiox_17", false, 0, 0x00000000 }, { "gpiox_18", false, 0, 0x00000000 }, { "gpiox_19", false, 0, 0x00000000 }, { "gpiox_20", false, 0, 0x00000000 }, { "gpiox_21", false, 0, 0x00000000 }, { "gpiox_22", false, 0, 0x00000000 }, { "gpiox_23", false, 0, 0x00000000 }, { "gpiox_24", false, 0, 0x00000000 }, { "gpiox_25", false, 0, 0x00000000 }, { "gpiox_26", false, 0, 0x00000000 }, { "gpiox_27", false, 0, 0x00000000 }, { "gpiox_28", false, 0, 0x00000000 }, X { "gpioy_0", false, 0, 0x00000000 }, { "gpioy_1", false, 0, 0x00000000 }, { "gpioy_2", false, 0, 0x00000000 }, { "gpioy_3", false, 0, 0x00000000 }, { "gpioy_4", false, 0, 0x00000000 }, { "gpioy_5", false, 0, 0x00000000 }, { "gpioy_6", false, 0, 0x00000000 }, { "gpioy_7", false, 0, 0x00000000 }, { "gpioy_8", false, 0, 0x00000000 }, { "gpioy_9", false, 0, 0x00000000 }, X { "gpioao_0", true, 0, 0x00000000 }, { "gpioao_1", true, 0, 0x00000000 }, { "gpioao_2", true, 0, 0x00000000 }, { "gpioao_3", true, 0, 0x00000000 }, { "gpioao_4", true, 0, 0x00000000 }, { "gpioao_5", true, 0, 0x00000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_gpio[] = { { "card_0", "card_0", 0, 0x00000000 }, { "card_1", "card_1", 0, 0x00000000 }, { "card_2", "card_2", 0, 0x00000000 }, { "card_3", "card_3", 0, 0x00000000 }, { "card_4", "card_4", 0, 0x00000000 }, { "card_5", "card_5", 0, 0x00000000 }, { "card_6", "card_6", 0, 0x00000000 }, X { "gpioc_10", "gpioc_10", 0, 0x00000000 }, { "gpioc_11", "gpioc_11", 0, 0x00000000 }, { "gpioc_12", "gpioc_12", 0, 0x00000000 }, { "gpioc_13", "gpioc_13", 0, 0x00000000 }, X { "gpiox_13", "gpiox_13", 0, 0x00000000 }, { "gpiox_14", "gpiox_14", 0, 0x00000000 }, { "gpiox_15", "gpiox_15", 0, 0x00000000 }, { "gpiox_16", "gpiox_16", 0, 0x00000000 }, { "gpiox_17", "gpiox_17", 0, 0x00000000 }, { "gpiox_18", "gpiox_18", 0, 0x00000000 }, { "gpiox_19", "gpiox_19", 0, 0x00000000 }, { "gpiox_20", "gpiox_20", 0, 0x00000000 }, { "gpiox_21", "gpiox_21", 0, 0x00000000 }, { "gpiox_22", "gpiox_22", 0, 0x00000000 }, { "gpiox_23", "gpiox_23", 0, 0x00000000 }, { "gpiox_24", "gpiox_24", 0, 0x00000000 }, { "gpiox_25", "gpiox_25", 0, 0x00000000 }, { "gpiox_26", "gpiox_26", 0, 0x00000000 }, { "gpiox_27", "gpiox_27", 0, 0x00000000 }, { "gpiox_28", "gpiox_28", 0, 0x00000000 }, X { "gpioy_0", "gpioy_0", 0, 0x00000000 }, { "gpioy_1", "gpioy_1", 0, 0x00000000 }, { "gpioy_2", "gpioy_2", 0, 0x00000000 }, { "gpioy_3", "gpioy_3", 0, 0x00000000 }, { "gpioy_4", "gpioy_4", 0, 0x00000000 }, { "gpioy_5", "gpioy_5", 0, 0x00000000 }, { "gpioy_6", "gpioy_6", 0, 0x00000000 }, { "gpioy_7", "gpioy_7", 0, 0x00000000 }, { "gpioy_8", "gpioy_8", 0, 0x00000000 }, { "gpioy_9", "gpioy_9", 0, 0x00000000 }, X { "gpioao_0", "gpioao_0", 0, 0x00000000 }, { "gpioao_1", "gpioao_1", 0, 0x00000000 }, { "gpioao_2", "gpioao_2", 0, 0x00000000 }, { "gpioao_3", "gpioao_3", 0, 0x00000000 }, { "gpioao_4", "gpioao_4", 0, 0x00000000 }, { "gpioao_5", "gpioao_5", 0, 0x00000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_ethernet[] = { { "clk50_in", "gpioy_0", 24, 0x00040000 }, { "clk_out", "gpioy_0", 24, 0x00020000 }, { "tx_en", "gpioy_5", 24, 0x00001000 }, { "tx_d0", "gpioy_7", 24, 0x00000400 }, { "tx_d1", "gpioy_6", 24, 0x00000800 }, { "crs_dv", "gpioy_2", 24, 0x00008000 }, { "rx_err", "gpioy_1", 24, 0x00010000 }, { "rx_d0", "gpioy_4", 24, 0x00002000 }, { "rx_d1", "gpioy_3", 24, 0x00004000 }, { "mdc", "gpioy_8", 24, 0x00000200 }, { "mdio", "gpioy_9", 24, 0x00000100 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_hdmi[] = { { "cec", "gpioc_13", 4, 0x02000000 }, { "hpd", "gpioc_10", 4, 0x00400000 }, { "scl", "gpioc_12", 4, 0x01000000 }, { "sda", "gpioc_11", 4, 0x00800000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_i2c_a[] = { { "scl", "gpiox_26", 20, 0x04000000 }, { "sda", "gpiox_25", 20, 0x08000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_i2c_b[] = { { "scl", "gpiox_28", 20, 0x40000000 }, { "sda", "gpiox_27", 20, 0x80000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_sdio_b[] = { { "clk", "card_4", 8, 0x00000800 }, { "cmd", "card_5", 8, 0x00000400 }, { "d0", "card_0", 8, 0x00008000 }, { "d1", "card_1", 8, 0x00004000 }, { "d2", "card_2", 8, 0x00002000 }, { "d3", "card_3", 8, 0x00001000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_sdxc_b[] = { { "clk", "card_4", 8, 0x00000020 }, { "cmd", "card_5", 8, 0x00000010 }, { "d0", "card_0", 8, 0x00000080 }, { "d1", "card_1", 8, 0x00000040 }, { "d2", "card_2", 8, 0x00000040 }, { "d3", "card_3", 8, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_uart_a[] = { { "tx", "gpiox_13", 16, 0x00002000 }, { "rx", "gpiox_14", 16, 0x00001000 }, { "cts", "gpiox_15", 16, 0x00000800 }, { "rts", "gpiox_16", 16, 0x00000400 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_uart_b[] = { { "tx", "gpiox_17", 16, 0x00000200 }, { "rx", "gpiox_18", 16, 0x00000100 }, { "cts", "gpiox_19", 16, 0x00000080 }, { "rts", "gpiox_20", 16, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_uart_c[] = { { "tx", "gpiox_21", 16, 0x00000008 }, { "rx", "gpiox_22", 16, 0x00000004 }, { "cts", "gpiox_23", 16, 0x00000002 }, { "rts", "gpiox_24", 16, 0x00000001 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_i2c_ao[] = { { "scl", "gpioao_4", 0, 0x00000400 }, { "sda", "gpioao_5", 0, 0x00000200 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m3_uart_ao[] = { { "tx", "gpioao_0", 0, 0x00001000 }, { "rx", "gpioao_1", 0, 0x00000800 }, { "cts", "gpioao_2", 0, 0x00000400 }, { "rts", "gpioao_3", 0, 0x00000200 }, { NULL } }; X struct aml8726_pinctrl_function aml8726_m3_pinctrl[] = { { "gpio", aml8726_m3_gpio }, { "ethernet", aml8726_m3_ethernet }, { "hdmi", aml8726_m3_hdmi }, { "i2c-a", aml8726_m3_i2c_a }, { "i2c-b", aml8726_m3_i2c_b }, { "sdio-b", aml8726_m3_sdio_b }, { "sdxc-b", aml8726_m3_sdxc_b }, { "uart-a", aml8726_m3_uart_a }, { "uart-b", aml8726_m3_uart_b }, { "uart-c", aml8726_m3_uart_c }, { "i2c-ao", aml8726_m3_i2c_ao }, { "uart-ao", aml8726_m3_uart_ao }, { NULL } }; X X /* X * aml8726-m6 X * X * start size X * cbus mux 0x202c 40 X * cbus pu_pd 0x203a 24 X * cbus pull_en 0x203a 24 X * aobus mux 0x0005 4 X * aobus pu_pd 0x000b 4 X * aobus pull_en 0x000b 4 X * X * For simplicity we don't support setting pull for gpioe and gpioz. X */ X static struct aml8726_pinctrl_pkg_pin aml8726_m6_pkg_pin[] = { { "card_0", false, 12, 0x00100000 }, { "card_1", false, 12, 0x00200000 }, { "card_2", false, 12, 0x00400000 }, { "card_3", false, 12, 0x00800000 }, { "card_4", false, 12, 0x01000000 }, { "card_5", false, 12, 0x02000000 }, { "card_6", false, 12, 0x04000000 }, X { "gpioc_10", false, 8, 0x00000400 }, { "gpioc_11", false, 8, 0x00000800 }, { "gpioc_12", false, 8, 0x00001000 }, { "gpioc_13", false, 8, 0x00002000 }, X { "gpiox_13", false, 16, 0x00002000 }, { "gpiox_14", false, 16, 0x00004000 }, { "gpiox_15", false, 16, 0x00008000 }, { "gpiox_16", false, 16, 0x00010000 }, { "gpiox_17", false, 16, 0x00020000 }, { "gpiox_18", false, 16, 0x00040000 }, { "gpiox_19", false, 16, 0x00080000 }, { "gpiox_20", false, 16, 0x00100000 }, { "gpiox_21", false, 16, 0x00200000 }, { "gpiox_22", false, 16, 0x00400000 }, { "gpiox_23", false, 16, 0x00800000 }, { "gpiox_24", false, 16, 0x01000000 }, { "gpiox_25", false, 16, 0x02000000 }, { "gpiox_26", false, 16, 0x04000000 }, { "gpiox_27", false, 16, 0x08000000 }, { "gpiox_28", false, 16, 0x10000000 }, X { "gpioy_0", false, 20, 0x00000010 }, { "gpioy_1", false, 20, 0x00000020 }, { "gpioy_2", false, 20, 0x00000040 }, { "gpioy_3", false, 20, 0x00000080 }, { "gpioy_4", false, 20, 0x00000100 }, { "gpioy_5", false, 20, 0x00000200 }, { "gpioy_6", false, 20, 0x00000400 }, { "gpioy_7", false, 20, 0x00000800 }, { "gpioy_8", false, 20, 0x00001000 }, { "gpioy_9", false, 20, 0x00002000 }, { "gpioy_10", false, 20, 0x00004000 }, { "gpioy_11", false, 20, 0x00008000 }, { "gpioy_12", false, 20, 0x00010000 }, { "gpioy_13", false, 20, 0x00020000 }, { "gpioy_14", false, 20, 0x00040000 }, X { "gpioao_0", true, 0, 0x00000001 }, { "gpioao_1", true, 0, 0x00000002 }, { "gpioao_2", true, 0, 0x00000004 }, { "gpioao_3", true, 0, 0x00000008 }, { "gpioao_4", true, 0, 0x00000010 }, { "gpioao_5", true, 0, 0x00000020 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_gpio[] = { { "card_0", "card_0", 0, 0x00000000 }, { "card_1", "card_1", 0, 0x00000000 }, { "card_2", "card_2", 0, 0x00000000 }, { "card_3", "card_3", 0, 0x00000000 }, { "card_4", "card_4", 0, 0x00000000 }, { "card_5", "card_5", 0, 0x00000000 }, { "card_6", "card_6", 0, 0x00000000 }, X { "gpioc_10", "gpioc_10", 0, 0x00000000 }, { "gpioc_11", "gpioc_11", 0, 0x00000000 }, { "gpioc_12", "gpioc_12", 0, 0x00000000 }, { "gpioc_13", "gpioc_13", 0, 0x00000000 }, X { "gpiox_13", "gpiox_13", 0, 0x00000000 }, { "gpiox_14", "gpiox_14", 0, 0x00000000 }, { "gpiox_15", "gpiox_15", 0, 0x00000000 }, { "gpiox_16", "gpiox_16", 0, 0x00000000 }, { "gpiox_17", "gpiox_17", 0, 0x00000000 }, { "gpiox_18", "gpiox_18", 0, 0x00000000 }, { "gpiox_19", "gpiox_19", 0, 0x00000000 }, { "gpiox_20", "gpiox_20", 0, 0x00000000 }, { "gpiox_21", "gpiox_21", 0, 0x00000000 }, { "gpiox_22", "gpiox_22", 0, 0x00000000 }, { "gpiox_23", "gpiox_23", 0, 0x00000000 }, { "gpiox_24", "gpiox_24", 0, 0x00000000 }, { "gpiox_25", "gpiox_25", 0, 0x00000000 }, { "gpiox_26", "gpiox_26", 0, 0x00000000 }, { "gpiox_27", "gpiox_27", 0, 0x00000000 }, { "gpiox_28", "gpiox_28", 0, 0x00000000 }, X { "gpioy_0", "gpioy_0", 0, 0x00000000 }, { "gpioy_1", "gpioy_1", 0, 0x00000000 }, { "gpioy_2", "gpioy_2", 0, 0x00000000 }, { "gpioy_3", "gpioy_3", 0, 0x00000000 }, { "gpioy_4", "gpioy_4", 0, 0x00000000 }, { "gpioy_5", "gpioy_5", 0, 0x00000000 }, { "gpioy_6", "gpioy_6", 0, 0x00000000 }, { "gpioy_7", "gpioy_7", 0, 0x00000000 }, { "gpioy_8", "gpioy_8", 0, 0x00000000 }, { "gpioy_9", "gpioy_9", 0, 0x00000000 }, { "gpioy_10", "gpioy_10", 0, 0x00000000 }, { "gpioy_11", "gpioy_11", 0, 0x00000000 }, { "gpioy_12", "gpioy_12", 0, 0x00000000 }, { "gpioy_13", "gpioy_13", 0, 0x00000000 }, { "gpioy_14", "gpioy_14", 0, 0x00000000 }, X { "gpioao_0", "gpioao_0", 0, 0x00000000 }, { "gpioao_1", "gpioao_1", 0, 0x00000000 }, { "gpioao_2", "gpioao_2", 0, 0x00000000 }, { "gpioao_3", "gpioao_3", 0, 0x00000000 }, { "gpioao_4", "gpioao_4", 0, 0x00000000 }, { "gpioao_5", "gpioao_5", 0, 0x00000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_ethernet[] = { { "ref_clk_in", "gpioy_0", 24, 0x80000000 }, { "ref_clk_out", "gpioy_0", 24, 0x40000000 }, { "tx_clk", "gpioy_1", 24, 0x00040000 }, { "tx_en", "gpioy_2", 24, 0x00020000 }, { "tx_d0", "gpioy_6", 24, 0x00002000 }, { "tx_d1", "gpioy_5", 24, 0x00004000 }, { "tx_d2", "gpioy_4", 24, 0x00008000 }, { "tx_d3", "gpioy_3", 24, 0x00010000 }, { "rx_clk", "gpioy_7", 24, 0x00001000 }, { "rx_dv", "gpioy_8", 24, 0x00000800 }, { "rx_d0", "gpioy_12", 24, 0x00000080 }, { "rx_d1", "gpioy_11", 24, 0x00000100 }, { "rx_d2", "gpioy_10", 24, 0x00000200 }, { "rx_d3", "gpioy_9", 24, 0x00000400 }, { "mdc", "gpioy_14", 24, 0x00000020 }, { "mdio", "gpioy_13", 24, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_hdmi[] = { { "cec", "gpioc_13", 4, 0x02000000 }, { "hpd", "gpioc_10", 4, 0x00400000 }, { "scl", "gpioc_12", 4, 0x01000000 }, { "sda", "gpioc_11", 4, 0x00800000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_i2c_a[] = { { "scl", "gpiox_26", 20, 0x04000000 }, { "sda", "gpiox_25", 20, 0x08000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_i2c_b[] = { { "scl", "gpiox_28", 20, 0x40000000 }, { "sda", "gpiox_27", 20, 0x80000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_sdio_b[] = { { "clk", "card_4", 8, 0x00000800 }, { "cmd", "card_5", 8, 0x00000400 }, { "d0", "card_0", 8, 0x00008000 }, { "d1", "card_1", 8, 0x00004000 }, { "d2", "card_2", 8, 0x00002000 }, { "d3", "card_3", 8, 0x00001000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_sdxc_b[] = { { "clk", "card_4", 8, 0x00000020 }, { "cmd", "card_5", 8, 0x00000010 }, { "d0", "card_0", 8, 0x00000080 }, { "d1", "card_1", 8, 0x00000040 }, { "d2", "card_2", 8, 0x00000040 }, { "d3", "card_3", 8, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_uart_a[] = { { "tx", "gpiox_13", 16, 0x00002000 }, { "rx", "gpiox_14", 16, 0x00001000 }, { "cts", "gpiox_15", 16, 0x00000800 }, { "rts", "gpiox_16", 16, 0x00000400 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_uart_b[] = { { "tx", "gpiox_17", 16, 0x00000200 }, { "rx", "gpiox_18", 16, 0x00000100 }, { "cts", "gpiox_19", 16, 0x00000080 }, { "rts", "gpiox_20", 16, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_uart_c[] = { { "tx", "gpiox_21", 16, 0x00000008 }, { "rx", "gpiox_22", 16, 0x00000004 }, { "cts", "gpiox_23", 16, 0x00000002 }, { "rts", "gpiox_24", 16, 0x00000001 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_i2c_ao[] = { { "scl", "gpioao_4", 0, 0x00000400 }, { "sda", "gpioao_5", 0, 0x00000200 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m6_uart_ao[] = { { "tx", "gpioao_0", 0, 0x00001000 }, { "rx", "gpioao_1", 0, 0x00000800 }, { "cts", "gpioao_2", 0, 0x00000400 }, { "rts", "gpioao_3", 0, 0x00000200 }, { NULL } }; X struct aml8726_pinctrl_function aml8726_m6_pinctrl[] = { { "gpio", aml8726_m6_gpio }, { "ethernet", aml8726_m6_ethernet }, { "hdmi", aml8726_m6_hdmi }, { "i2c-a", aml8726_m6_i2c_a }, { "i2c-b", aml8726_m6_i2c_b }, { "sdio-b", aml8726_m6_sdio_b }, { "sdxc-b", aml8726_m6_sdxc_b }, { "uart-a", aml8726_m6_uart_a }, { "uart-b", aml8726_m6_uart_b }, { "uart-c", aml8726_m6_uart_c }, { "i2c-ao", aml8726_m6_i2c_ao }, { "uart-ao", aml8726_m6_uart_ao }, { NULL } }; X X /* X * aml8726-m8 X * X * start size X * cbus mux 0x202c 40 X * cbus pu_pd 0x203a 20 X * cbus pull_en 0x2048 20 X * aobus mux 0x0005 4 X * aobus pu_pd 0x000b 4 X * aobus pull_en 0x000b 4 X */ X static struct aml8726_pinctrl_pkg_pin aml8726_m8_pkg_pin[] = { { "boot_0", false, 8, 0x00000001 }, { "boot_1", false, 8, 0x00000002 }, { "boot_2", false, 8, 0x00000004 }, { "boot_3", false, 8, 0x00000008 }, { "boot_4", false, 8, 0x00000010 }, { "boot_5", false, 8, 0x00000020 }, { "boot_6", false, 8, 0x00000040 }, { "boot_7", false, 8, 0x00000080 }, X { "boot_16", false, 8, 0x00010000 }, { "boot_17", false, 8, 0x00020000 }, X { "card_0", false, 8, 0x00100000 }, { "card_1", false, 8, 0x00200000 }, { "card_2", false, 8, 0x00400000 }, { "card_3", false, 8, 0x00800000 }, { "card_4", false, 8, 0x01000000 }, { "card_5", false, 8, 0x02000000 }, { "card_6", false, 8, 0x04000000 }, X { "gpioh_0", false, 4, 0x00001000 }, { "gpioh_1", false, 4, 0x00002000 }, { "gpioh_2", false, 4, 0x00004000 }, { "gpioh_3", false, 4, 0x00008000 }, X { "gpiox_12", false, 16, 0x00001000 }, { "gpiox_13", false, 16, 0x00002000 }, { "gpiox_14", false, 16, 0x00004000 }, { "gpiox_15", false, 16, 0x00008000 }, { "gpiox_16", false, 16, 0x00010000 }, { "gpiox_17", false, 16, 0x00020000 }, { "gpiox_18", false, 16, 0x00040000 }, { "gpiox_19", false, 16, 0x00080000 }, X { "gpioy_0", false, 12, 0x00000001 }, { "gpioy_1", false, 12, 0x00000002 }, { "gpioy_2", false, 12, 0x00000004 }, { "gpioy_3", false, 12, 0x00000008 }, X { "gpioz_2", false, 4, 0x00000004 }, { "gpioz_3", false, 4, 0x00000008 }, { "gpioz_4", false, 4, 0x00000010 }, { "gpioz_5", false, 4, 0x00000020 }, { "gpioz_6", false, 4, 0x00000040 }, { "gpioz_7", false, 4, 0x00000080 }, { "gpioz_8", false, 4, 0x00000100 }, { "gpioz_9", false, 4, 0x00000200 }, { "gpioz_10", false, 4, 0x00000400 }, { "gpioz_11", false, 4, 0x00000800 }, { "gpioz_12", false, 4, 0x00001000 }, { "gpioz_13", false, 4, 0x00002000 }, X { "gpioao_0", true, 0, 0x00000001 }, { "gpioao_1", true, 0, 0x00000002 }, { "gpioao_2", true, 0, 0x00000004 }, { "gpioao_3", true, 0, 0x00000008 }, { "gpioao_4", true, 0, 0x00000010 }, { "gpioao_5", true, 0, 0x00000020 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_gpio[] = { { "boot_0", "boot_0", 0, 0x00000000 }, { "boot_1", "boot_1", 0, 0x00000000 }, { "boot_2", "boot_2", 0, 0x00000000 }, { "boot_3", "boot_3", 0, 0x00000000 }, { "boot_4", "boot_4", 0, 0x00000000 }, { "boot_5", "boot_5", 0, 0x00000000 }, { "boot_6", "boot_6", 0, 0x00000000 }, { "boot_7", "boot_7", 0, 0x00000000 }, X { "boot_16", "boot_16", 0, 0x00000000 }, { "boot_17", "boot_17", 0, 0x00000000 }, X { "card_0", "card_0", 0, 0x00000000 }, { "card_1", "card_1", 0, 0x00000000 }, { "card_2", "card_2", 0, 0x00000000 }, { "card_3", "card_3", 0, 0x00000000 }, { "card_4", "card_4", 0, 0x00000000 }, { "card_5", "card_5", 0, 0x00000000 }, { "card_6", "card_6", 0, 0x00000000 }, X { "gpioh_0", "gpioh_0", 0, 0x00000000 }, { "gpioh_1", "gpioh_1", 0, 0x00000000 }, { "gpioh_2", "gpioh_2", 0, 0x00000000 }, { "gpioh_3", "gpioh_3", 0, 0x00000000 }, X { "gpiox_12", "gpiox_12", 0, 0x00000000 }, { "gpiox_13", "gpiox_13", 0, 0x00000000 }, { "gpiox_14", "gpiox_14", 0, 0x00000000 }, { "gpiox_15", "gpiox_15", 0, 0x00000000 }, { "gpiox_16", "gpiox_16", 0, 0x00000000 }, { "gpiox_17", "gpiox_17", 0, 0x00000000 }, { "gpiox_18", "gpiox_18", 0, 0x00000000 }, { "gpiox_19", "gpiox_19", 0, 0x00000000 }, X { "gpioy_0", "gpioy_0", 0, 0x00000000 }, { "gpioy_1", "gpioy_1", 0, 0x00000000 }, { "gpioy_2", "gpioy_2", 0, 0x00000000 }, { "gpioy_3", "gpioy_3", 0, 0x00000000 }, X { "gpioz_2", "gpioz_2", 0, 0x00000000 }, { "gpioz_3", "gpioz_3", 0, 0x00000000 }, { "gpioz_4", "gpioz_4", 0, 0x00000000 }, { "gpioz_5", "gpioz_5", 0, 0x00000000 }, { "gpioz_6", "gpioz_6", 0, 0x00000000 }, { "gpioz_7", "gpioz_7", 0, 0x00000000 }, { "gpioz_8", "gpioz_8", 0, 0x00000000 }, { "gpioz_9", "gpioz_9", 0, 0x00000000 }, { "gpioz_10", "gpioz_10", 0, 0x00000000 }, { "gpioz_11", "gpioz_11", 0, 0x00000000 }, { "gpioz_12", "gpioz_12", 0, 0x00000000 }, { "gpioz_13", "gpioz_13", 0, 0x00000000 }, X { "gpioao_0", "gpioao_0", 0, 0x00000000 }, { "gpioao_1", "gpioao_1", 0, 0x00000000 }, { "gpioao_2", "gpioao_2", 0, 0x00000000 }, { "gpioao_3", "gpioao_3", 0, 0x00000000 }, { "gpioao_4", "gpioao_4", 0, 0x00000000 }, { "gpioao_5", "gpioao_5", 0, 0x00000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_ethernet[] = { { "tx_clk", "gpioz_4", 24, 0x00008000 }, { "tx_en", "gpioz_5", 24, 0x00004000 }, { "tx_d0", "gpioz_7", 24, 0x00001000 }, { "tx_d1", "gpioz_6", 24, 0x00002000 }, { "rx_clk_in", "gpioz_8", 24, 0x00000400 }, { "rx_clk_out", "gpioz_8", 24, 0x00000200 }, { "rx_dv", "gpioz_9", 24, 0x00000800 }, { "rx_d0", "gpioz_11", 24, 0x00000080 }, { "rx_d1", "gpioz_10", 24, 0x00000100 }, { "mdc", "gpioz_13", 24, 0x00000020 }, { "mdio", "gpioz_12", 24, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_hdmi[] = { { "cec", "gpioh_3", 4, 0x00800000 }, { "hpd", "gpioh_0", 4, 0x04000000 }, { "scl", "gpioh_2", 4, 0x01000000 }, { "sda", "gpioh_1", 4, 0x02000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_i2c_a[] = { { "scl", "gpioz_12", 20, 0x00000040 }, { "sda", "gpioz_11", 20, 0x00000080 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_i2c_b[] = { { "scl", "gpioz_3", 20, 0x04000000 }, { "sda", "gpioz_2", 20, 0x08000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_sdio_b[] = { { "clk", "card_2", 8, 0x00000800 }, { "cmd", "card_3", 8, 0x00000400 }, { "d0", "card_1", 8, 0x00008000 }, { "d1", "card_0", 8, 0x00004000 }, { "d2", "card_5", 8, 0x00002000 }, { "d3", "card_4", 8, 0x00001000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_sdxc_b[] = { { "clk", "card_2", 8, 0x00000020 }, { "cmd", "card_3", 8, 0x00000010 }, { "d0", "card_1", 8, 0x00000080 }, { "d1", "card_0", 8, 0x00000040 }, { "d2", "card_5", 8, 0x00000040 }, { "d3", "card_4", 8, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_sdio_c[] = { { "clk", "boot_17", 24, 0x01000000 }, { "cmd", "boot_16", 24, 0x02000000 }, { "d0", "boot_0", 24, 0x20000000 }, { "d1", "boot_1", 24, 0x10000000 }, { "d2", "boot_2", 24, 0x08000000 }, { "d3", "boot_3", 24, 0x04000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_sdxc_c[] = { { "clk", "boot_17", 16, 0x04000000 }, { "cmd", "boot_16", 16, 0x08000000 }, { "d0", "boot_0", 16, 0x40000000 }, { "d1", "boot_1", 16, 0x20000000 }, { "d2", "boot_2", 16, 0x20000000 }, { "d3", "boot_3", 16, 0x20000000 }, { "d4", "boot_4", 16, 0x10000000 }, { "d5", "boot_5", 16, 0x10000000 }, { "d6", "boot_6", 16, 0x10000000 }, { "d7", "boot_7", 16, 0x10000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_uart_a[] = { { "tx", "gpiox_4", 16, 0x00020000 }, { "rx", "gpiox_5", 16, 0x00010000 }, { "cts", "gpiox_6", 16, 0x00008000 }, { "rts", "gpiox_7", 16, 0x00004000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_uart_b[] = { { "tx", "gpiox_16", 16, 0x00000200 }, { "rx", "gpiox_17", 16, 0x00000100 }, { "cts", "gpiox_18", 16, 0x00000080 }, { "rts", "gpiox_19", 16, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_uart_c[] = { { "tx", "gpioy_0", 4, 0x00080000 }, { "rx", "gpioy_1", 4, 0x00040000 }, { "cts", "gpioy_2", 4, 0x00020000 }, { "rts", "gpioy_3", 4, 0x00010000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_i2c_ao[] = { { "scl", "gpioao_4", 0, 0x00000400 }, { "sda", "gpioao_5", 0, 0x00000200 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8_uart_ao[] = { { "tx", "gpioao_0", 0, 0x00001000 }, { "rx", "gpioao_1", 0, 0x00000800 }, { "cts", "gpioao_2", 0, 0x00000400 }, { "rts", "gpioao_3", 0, 0x00000200 }, { NULL } }; X struct aml8726_pinctrl_function aml8726_m8_pinctrl[] = { { "gpio", aml8726_m8_gpio }, { "ethernet", aml8726_m8_ethernet }, { "hdmi", aml8726_m8_hdmi }, { "i2c-a", aml8726_m8_i2c_a }, { "i2c-b", aml8726_m8_i2c_b }, { "sdio-b", aml8726_m8_sdio_b }, { "sdxc-b", aml8726_m8_sdxc_b }, { "sdio-c", aml8726_m8_sdio_c }, { "sdxc-c", aml8726_m8_sdxc_c }, { "uart-a", aml8726_m8_uart_a }, { "uart-b", aml8726_m8_uart_b }, { "uart-c", aml8726_m8_uart_c }, { "i2c-ao", aml8726_m8_i2c_ao }, { "uart-ao", aml8726_m8_uart_ao }, { NULL } }; X X /* X * aml8726-m8b X * X * start size X * cbus mux 0x202c 40 X * cbus pu_pd 0x203a 24 X * cbus pull_en 0x2048 24 X * aobus mux 0x0005 4 X * aobus pu_pd 0x000b 4 X * aobus pull_en 0x000b 4 X */ X static struct aml8726_pinctrl_pkg_pin aml8726_m8b_pkg_pin[] = { { "boot_0", false, 8, 0x00000001 }, { "boot_1", false, 8, 0x00000002 }, { "boot_2", false, 8, 0x00000004 }, { "boot_3", false, 8, 0x00000008 }, { "boot_4", false, 8, 0x00000010 }, { "boot_5", false, 8, 0x00000020 }, { "boot_6", false, 8, 0x00000040 }, { "boot_7", false, 8, 0x00000080 }, { "boot_8", false, 8, 0x00000100 }, { "boot_9", false, 8, 0x00000200 }, { "boot_10", false, 8, 0x00000400 }, X { "card_0", false, 8, 0x00100000 }, { "card_1", false, 8, 0x00200000 }, { "card_2", false, 8, 0x00400000 }, { "card_3", false, 8, 0x00800000 }, { "card_4", false, 8, 0x01000000 }, { "card_5", false, 8, 0x02000000 }, { "card_6", false, 8, 0x04000000 }, X { "dif_0p", false, 20, 0x00000100 }, { "dif_0n", false, 20, 0x00000200 }, { "dif_1p", false, 20, 0x00000400 }, { "dif_1n", false, 20, 0x00000800 }, { "dif_2p", false, 20, 0x00001000 }, { "dif_2n", false, 20, 0x00002000 }, { "dif_3p", false, 20, 0x00004000 }, { "dif_3n", false, 20, 0x00008000 }, { "dif_4p", false, 20, 0x00010000 }, { "dif_4n", false, 20, 0x00020000 }, X { "gpiodv_24", false, 0, 0x01000000 }, { "gpiodv_25", false, 0, 0x02000000 }, { "gpiodv_26", false, 0, 0x04000000 }, { "gpiodv_27", false, 0, 0x08000000 }, X { "gpioh_0", false, 4, 0x00010000 }, { "gpioh_1", false, 4, 0x00020000 }, { "gpioh_2", false, 4, 0x00040000 }, { "gpioh_3", false, 4, 0x00080000 }, { "gpioh_4", false, 4, 0x00100000 }, { "gpioh_5", false, 4, 0x00200000 }, { "gpioh_6", false, 4, 0x00400000 }, { "gpioh_7", false, 4, 0x00800000 }, { "gpioh_8", false, 4, 0x01000000 }, { "gpioh_9", false, 4, 0x02000000 }, X { "gpiox_4", false, 16, 0x00000010 }, { "gpiox_5", false, 16, 0x00000020 }, { "gpiox_6", false, 16, 0x00000040 }, { "gpiox_7", false, 16, 0x00000080 }, { "gpiox_16", false, 16, 0x00010000 }, { "gpiox_17", false, 16, 0x00020000 }, { "gpiox_18", false, 16, 0x00040000 }, { "gpiox_19", false, 16, 0x00080000 }, X { "gpioao_0", true, 0, 0x00000001 }, { "gpioao_1", true, 0, 0x00000002 }, { "gpioao_2", true, 0, 0x00000004 }, { "gpioao_3", true, 0, 0x00000008 }, { "gpioao_4", true, 0, 0x00000010 }, { "gpioao_5", true, 0, 0x00000020 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_gpio[] = { { "boot_0", "boot_0", 0, 0x00000000 }, { "boot_1", "boot_1", 0, 0x00000000 }, { "boot_2", "boot_2", 0, 0x00000000 }, { "boot_3", "boot_3", 0, 0x00000000 }, { "boot_4", "boot_4", 0, 0x00000000 }, { "boot_5", "boot_5", 0, 0x00000000 }, { "boot_6", "boot_6", 0, 0x00000000 }, { "boot_7", "boot_7", 0, 0x00000000 }, { "boot_8", "boot_8", 0, 0x00000000 }, { "boot_9", "boot_9", 0, 0x00000000 }, { "boot_10", "boot_10", 0, 0x00000000 }, X { "card_0", "card_0", 0, 0x00000000 }, { "card_1", "card_1", 0, 0x00000000 }, { "card_2", "card_2", 0, 0x00000000 }, { "card_3", "card_3", 0, 0x00000000 }, { "card_4", "card_4", 0, 0x00000000 }, { "card_5", "card_5", 0, 0x00000000 }, { "card_6", "card_6", 0, 0x00000000 }, X { "dif_0p", "dif_0p", 0, 0x00000000 }, { "dif_0n", "dif_0n", 0, 0x00000000 }, { "dif_1p", "dif_1p", 0, 0x00000000 }, { "dif_1n", "dif_1n", 0, 0x00000000 }, { "dif_2p", "dif_2p", 0, 0x00000000 }, { "dif_2n", "dif_2n", 0, 0x00000000 }, { "dif_3p", "dif_3p", 0, 0x00000000 }, { "dif_3n", "dif_3n", 0, 0x00000000 }, { "dif_4p", "dif_4p", 0, 0x00000000 }, { "dif_4n", "dif_4n", 0, 0x00000000 }, X { "gpiodv_24", "gpiodv_24", 0, 0x00000000 }, { "gpiodv_25", "gpiodv_25", 0, 0x00000000 }, { "gpiodv_26", "gpiodv_26", 0, 0x00000000 }, { "gpiodv_27", "gpiodv_27", 0, 0x00000000 }, X { "gpioh_0", "gpioh_0", 0, 0x00000000 }, { "gpioh_1", "gpioh_1", 0, 0x00000000 }, { "gpioh_2", "gpioh_2", 0, 0x00000000 }, { "gpioh_3", "gpioh_3", 0, 0x00000000 }, { "gpioh_4", "gpioh_4", 0, 0x00000000 }, { "gpioh_5", "gpioh_5", 0, 0x00000000 }, { "gpioh_6", "gpioh_6", 0, 0x00000000 }, { "gpioh_7", "gpioh_7", 0, 0x00000000 }, { "gpioh_8", "gpioh_8", 0, 0x00000000 }, { "gpioh_9", "gpioh_9", 0, 0x00000000 }, X { "gpiox_4", "gpiox_4", 0, 0x00000000 }, { "gpiox_5", "gpiox_5", 0, 0x00000000 }, { "gpiox_6", "gpiox_6", 0, 0x00000000 }, { "gpiox_7", "gpiox_7", 0, 0x00000000 }, { "gpiox_16", "gpiox_16", 0, 0x00000000 }, { "gpiox_17", "gpiox_17", 0, 0x00000000 }, { "gpiox_18", "gpiox_18", 0, 0x00000000 }, { "gpiox_19", "gpiox_19", 0, 0x00000000 }, X { "gpioao_0", "gpioao_0", 0, 0x00000000 }, { "gpioao_1", "gpioao_1", 0, 0x00000000 }, { "gpioao_2", "gpioao_2", 0, 0x00000000 }, { "gpioao_3", "gpioao_3", 0, 0x00000000 }, { "gpioao_4", "gpioao_4", 0, 0x00000000 }, { "gpioao_5", "gpioao_5", 0, 0x00000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_ethernet[] = { { "ref_clk", "dif_3n", 24, 0x00000100 }, { "tx_clk", "gpioh_9", 24, 0x00000800 }, { "tx_en", "dif_3p", 24, 0x00000040 }, { "tx_d0", "gpioh_6", 28, 0x00100000 }, { "tx_d1", "gpioh_5", 28, 0x00200000 }, { "tx_d2", "gpioh_8", 24, 0x00001000 }, { "tx_d3", "gpioh_7", 24, 0x00002000 }, { "rx_clk", "dif_1n", 24, 0x00000008 }, { "rx_dv", "dif_1p", 24, 0x00000004 }, { "rx_d0", "dif_0n", 24, 0x00000002 }, { "rx_d1", "dif_0p", 24, 0x00000001 }, { "rx_d2", "dif_2n", 28, 0x00800000 }, { "rx_d3", "dif_2p", 28, 0x00400000 }, { "mdc", "dif_4p", 24, 0x00000200 }, { "mdio", "dif_4n", 24, 0x00000400 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_hdmi[] = { { "cec", "gpioh_3", 4, 0x00800000 }, { "hpd", "gpioh_0", 4, 0x04000000 }, { "scl", "gpioh_2", 4, 0x01000000 }, { "sda", "gpioh_1", 4, 0x02000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_i2c_a[] = { { "scl", "gpiodv_25", 36, 0x40000000 }, { "sda", "gpiodv_24", 36, 0x80000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_i2c_b[] = { { "scl", "gpiodv_27", 36, 0x10000000 }, { "sda", "gpiodv_26", 36, 0x20000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_sdio_b[] = { { "clk", "card_2", 8, 0x00000800 }, { "cmd", "card_3", 8, 0x00000400 }, { "d0", "card_1", 8, 0x00008000 }, { "d1", "card_0", 8, 0x00004000 }, { "d2", "card_5", 8, 0x00002000 }, { "d3", "card_4", 8, 0x00001000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_sdxc_b[] = { { "clk", "card_2", 8, 0x00000020 }, { "cmd", "card_3", 8, 0x00000010 }, { "d0", "card_1", 8, 0x00000080 }, { "d1", "card_0", 8, 0x00000040 }, { "d2", "card_5", 8, 0x00000040 }, { "d3", "card_4", 8, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_sdio_c[] = { { "clk", "boot_8", 24, 0x80000000 }, { "cmd", "boot_10", 24, 0x40000000 }, { "d0", "boot_0", 24, 0x20000000 }, { "d1", "boot_1", 24, 0x10000000 }, { "d2", "boot_2", 24, 0x08000000 }, { "d3", "boot_3", 24, 0x04000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_sdxc_c[] = { { "clk", "boot_8", 28, 0x00080000 }, { "cmd", "boot_10", 28, 0x00040000 }, { "d0", "boot_0", 16, 0x40000000 }, { "d1", "boot_1", 16, 0x20000000 }, { "d2", "boot_2", 16, 0x20000000 }, { "d3", "boot_3", 16, 0x20000000 }, { "d4", "boot_4", 16, 0x10000000 }, { "d5", "boot_5", 16, 0x10000000 }, { "d6", "boot_6", 16, 0x10000000 }, { "d7", "boot_7", 16, 0x10000000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_uart_a[] = { { "tx", "gpiox_4", 16, 0x00020000 }, { "rx", "gpiox_5", 16, 0x00010000 }, { "cts", "gpiox_6", 16, 0x00008000 }, { "rts", "gpiox_7", 16, 0x00004000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_uart_b[] = { { "tx", "gpiox_16", 16, 0x00000200 }, { "rx", "gpiox_17", 16, 0x00000100 }, { "cts", "gpiox_18", 16, 0x00000080 }, { "rts", "gpiox_19", 16, 0x00000040 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_uart_c[] = { { "tx", "gpiodv_24", 24, 0x00800000 }, { "rx", "gpiodv_25", 24, 0x00400000 }, { "cts", "gpiodv_26", 24, 0x00200000 }, { "rts", "gpiodv_27", 24, 0x00100000 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_i2c_ao[] = { { "scl", "gpioao_4", 0, 0x00000400 }, { "sda", "gpioao_5", 0, 0x00000200 }, { NULL } }; X static struct aml8726_pinctrl_pin aml8726_m8b_uart_ao[] = { { "tx", "gpioao_0", 0, 0x00001000 }, { "rx", "gpioao_1", 0, 0x00000800 }, { "cts", "gpioao_2", 0, 0x00000400 }, { "rts", "gpioao_3", 0, 0x00000200 }, { NULL } }; X struct aml8726_pinctrl_function aml8726_m8b_pinctrl[] = { { "gpio", aml8726_m8b_gpio }, { "ethernet", aml8726_m8b_ethernet }, { "hdmi", aml8726_m8b_hdmi }, { "i2c-a", aml8726_m8b_i2c_a }, { "i2c-b", aml8726_m8b_i2c_b }, { "sdio-b", aml8726_m8b_sdio_b }, { "sdxc-b", aml8726_m8b_sdxc_b }, { "sdio-c", aml8726_m8b_sdio_c }, { "sdxc-c", aml8726_m8b_sdxc_c }, { "uart-a", aml8726_m8b_uart_a }, { "uart-b", aml8726_m8b_uart_b }, { "uart-c", aml8726_m8b_uart_c }, { "i2c-ao", aml8726_m8b_i2c_ao }, { "uart-ao", aml8726_m8b_uart_ao }, { NULL } }; X X #endif /* _ARM_AMLOGIC_AML8726_PINCTRL_H */ SHAR_EOF (set 20 15 02 28 19 15 03 'sys/arm/amlogic/aml8726/aml8726_pinctrl.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_pinctrl.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_pinctrl.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_pinctrl.h': 'MD5 check failed' ) << \SHAR_EOF 05d5bd037290e94bd5d3a4c66a9e9289 sys/arm/amlogic/aml8726/aml8726_pinctrl.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_pinctrl.h'` -ne 35044 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_pinctrl.h' is not 35044" 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-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 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 25 22 25 56 '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 c156618bd76d87e6260cc7178a039ad9 sys/arm/amlogic/aml8726/aml8726_rtc.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_rtc.c'` -ne 12261 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_rtc.c' is not 12261" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.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-m8 (and later) SDXC 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 #include X #include "gpio_if.h" #include "mmcbr_if.h" X X /* X * The table is sorted from highest to lowest and X * last entry in the table is mark by freq == 0. X */ struct { X uint32_t voltage; X uint32_t freq; X uint32_t rx_phase; } aml8726_sdxc_clk_phases[] = { { MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, 100000000, 1 }, { MMC_OCR_320_330 | MMC_OCR_330_340, 45000000, 15 }, { MMC_OCR_LOW_VOLTAGE, 45000000, 11 }, { MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, 24999999, 15 }, { MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, 5000000, 23 }, { MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, 1000000, 55 }, { MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, 0, 1061 }, }; X struct aml8726_sdxc_gpio { X device_t dev; X uint32_t pin; X uint32_t pol; }; X struct aml8726_sdxc_softc { X device_t dev; X boolean_t auto_fill_flush; X struct resource *res[2]; X struct mtx mtx; X struct callout ch; X unsigned int ref_freq; X struct aml8726_sdxc_gpio pwr_en; X int voltages[2]; X struct aml8726_sdxc_gpio vselect; X struct aml8726_sdxc_gpio card_rst; 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 { X uint32_t time; X uint32_t error; X } busy; X struct mmc_command *cmd; }; X static struct resource_spec aml8726_sdxc_spec[] = { X { SYS_RES_MEMORY, 0, RF_ACTIVE }, X { SYS_RES_IRQ, 0, RF_ACTIVE }, X { -1, 0 } }; X #define AML_SDXC_LOCK(sc) mtx_lock(&(sc)->mtx) #define AML_SDXC_UNLOCK(sc) mtx_unlock(&(sc)->mtx) #define AML_SDXC_LOCK_ASSERT(sc) mtx_assert(&(sc)->mtx, MA_OWNED) #define AML_SDXC_LOCK_INIT(sc) \ X mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ X "sdxc", MTX_DEF) #define AML_SDXC_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 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 #define msecs_to_ticks(ms) (((ms)*hz)/1000 + 1) X X static void aml8726_sdxc_timeout(void *arg); X X static void aml8726_sdxc_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_sdxc_power_off(struct aml8726_sdxc_softc *sc) { X X if (sc->pwr_en.dev == NULL) X return (0); X X return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PIN_OFF_FLAG(sc->pwr_en.pol))); } X X static int aml8726_sdxc_power_on(struct aml8726_sdxc_softc *sc) { X X if (sc->pwr_en.dev == NULL) X return (0); X X return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, X PIN_ON_FLAG(sc->pwr_en.pol))); } X X static void aml8726_sdxc_soft_reset(struct aml8726_sdxc_softc *sc) { X X CSR_WRITE_4(sc, AML_SDXC_SOFT_RESET_REG, AML_SDXC_SOFT_RESET); X CSR_BARRIER(sc, AML_SDXC_SOFT_RESET_REG); X DELAY(5); } X X static void aml8726_sdxc_engage_dma(struct aml8726_sdxc_softc *sc) { X int i; X uint32_t pdmar; X uint32_t sr; X struct mmc_data *data; X X data = sc->cmd->data; X X if (data == NULL || data->len == 0) X return; X X /* X * Engaging the DMA hardware is recommended before writing X * to AML_SDXC_SEND_REG so that the FIFOs are ready to go. X * X * Presumably AML_SDXC_CNTRL_REG and AML_SDXC_DMA_ADDR_REG X * must be set up prior to this happening. X */ X X pdmar = CSR_READ_4(sc, AML_SDXC_PDMA_REG); X X pdmar &= ~AML_SDXC_PDMA_RX_FLUSH_MODE_SW; X pdmar |= AML_SDXC_PDMA_DMA_EN; X X if (sc->auto_fill_flush == true) { X CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); X CSR_BARRIER(sc, AML_SDXC_PDMA_REG); X return; X } X X if ((data->flags & MMC_DATA_READ) != 0) { X pdmar |= AML_SDXC_PDMA_RX_FLUSH_MODE_SW; X CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); X CSR_BARRIER(sc, AML_SDXC_PDMA_REG); X } else { X pdmar |= AML_SDXC_PDMA_TX_FILL; X CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); X CSR_BARRIER(sc, AML_SDXC_PDMA_REG); X X /* X * Wait up to 100us for data to show up. X */ X for (i = 0; i < 100; i++) { X sr = CSR_READ_4(sc, AML_SDXC_STATUS_REG); X if ((sr & AML_SDXC_STATUS_TX_CNT_MASK) != 0) X break; X DELAY(1); X } X if (i >= 100) X device_printf(sc->dev, "TX FIFO fill timeout\n"); X } } X X static void aml8726_sdxc_disengage_dma(struct aml8726_sdxc_softc *sc) { X int i; X uint32_t pdmar; X uint32_t sr; X struct mmc_data *data; X X data = sc->cmd->data; X X if (data == NULL || data->len == 0) X return; X X pdmar = CSR_READ_4(sc, AML_SDXC_PDMA_REG); X X if (sc->auto_fill_flush == true) { X pdmar &= ~AML_SDXC_PDMA_DMA_EN; X CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); X CSR_BARRIER(sc, AML_SDXC_PDMA_REG); X return; X } X X if ((data->flags & MMC_DATA_READ) != 0) { X pdmar |= AML_SDXC_PDMA_RX_FLUSH_NOW; X CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); X CSR_BARRIER(sc, AML_SDXC_PDMA_REG); X X /* X * Wait up to 100us for data to drain. X */ X for (i = 0; i < 100; i++) { X sr = CSR_READ_4(sc, AML_SDXC_STATUS_REG); X if ((sr & AML_SDXC_STATUS_RX_CNT_MASK) == 0) X break; X DELAY(1); X } X if (i >= 100) X device_printf(sc->dev, "RX FIFO drain timeout\n"); X } X X pdmar &= ~(AML_SDXC_PDMA_DMA_EN | AML_SDXC_PDMA_RX_FLUSH_MODE_SW); X X CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); X CSR_BARRIER(sc, AML_SDXC_PDMA_REG); } X X static int aml8726_sdxc_start_command(struct aml8726_sdxc_softc *sc, X struct mmc_command *cmd) { X bus_addr_t baddr; X uint32_t block_size; X uint32_t ctlr; X uint32_t ier; X uint32_t sndr; X uint32_t timeout; X int error; X struct mmc_data *data; X X AML_SDXC_LOCK_ASSERT(sc); 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 */ X aml8726_sdxc_soft_reset(sc); X X sndr = cmd->opcode; X X if ((cmd->flags & MMC_RSP_136) != 0) { X sndr |= AML_SDXC_SEND_CMD_HAS_RESP; X sndr |= AML_SDXC_SEND_RESP_136; X /* X * According to the SD spec the 136 bit response is X * used for getting the CID or CSD in which case the X * CRC7 is embedded in the contents rather than being X * calculated over the entire response (the controller X * always checks the CRC7 over the entire response). X */ X sndr |= AML_SDXC_SEND_RESP_NO_CRC7_CHECK; X } else if ((cmd->flags & MMC_RSP_PRESENT) != 0) X sndr |= AML_SDXC_SEND_CMD_HAS_RESP; X X if ((cmd->flags & MMC_RSP_CRC) == 0) X sndr |= AML_SDXC_SEND_RESP_NO_CRC7_CHECK; X X if (cmd->opcode == MMC_STOP_TRANSMISSION) X sndr |= AML_SDXC_SEND_DATA_STOP; X X data = cmd->data; X X baddr = 0; X ctlr = CSR_READ_4(sc, AML_SDXC_CNTRL_REG); X ier = AML_SDXC_IRQ_ENABLE_STANDARD; X timeout = AML_SDXC_CMD_TIMEOUT; X X ctlr &= ~AML_SDXC_CNTRL_PKG_LEN_MASK; 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 if (block_size > 512) X return (MMC_ERR_INVALID); X X sndr |= AML_SDXC_SEND_CMD_HAS_DATA; X sndr |= ((data->flags & MMC_DATA_WRITE) != 0) X ? AML_SDXC_SEND_DATA_WRITE : 0; X sndr |= (((data->len / block_size) - 1) X << AML_SDXC_SEND_REP_PKG_CNT_SHIFT); X X ctlr |= ((block_size < 512) ? block_size : 0) X << AML_SDXC_CNTRL_PKG_LEN_SHIFT; X X ier &= ~AML_SDXC_IRQ_ENABLE_RESP_OK; X ier |= (sc->auto_fill_flush == true X || (data->flags & MMC_DATA_WRITE) != 0) X ? AML_SDXC_IRQ_ENABLE_DMA_DONE X : AML_SDXC_IRQ_ENABLE_TRANSFER_DONE_OK; X X error = bus_dmamap_load(sc->dmatag, sc->dmamap, X data->data, data->len, X aml8726_sdxc_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 bus_dmamap_sync(sc->dmatag, sc->dmamap, X BUS_DMASYNC_PREREAD); X timeout = AML_SDXC_READ_TIMEOUT X * (data->len / block_size); X } else { X bus_dmamap_sync(sc->dmatag, sc->dmamap, X BUS_DMASYNC_PREWRITE); X timeout = AML_SDXC_WRITE_TIMEOUT X * (data->len / block_size); X } X } X X sc->cmd = cmd; X X cmd->error = MMC_ERR_NONE; X X sc->busy.time = 0; X sc->busy.error = MMC_ERR_NONE; X X if (timeout > AML_SDXC_MAX_TIMEOUT) X timeout = AML_SDXC_MAX_TIMEOUT; X X callout_reset(&sc->ch, msecs_to_ticks(timeout), X aml8726_sdxc_timeout, sc); X X CSR_WRITE_4(sc, AML_SDXC_IRQ_ENABLE_REG, ier); X X CSR_WRITE_4(sc, AML_SDXC_CNTRL_REG, ctlr); X CSR_WRITE_4(sc, AML_SDXC_DMA_ADDR_REG, (uint32_t)baddr); X CSR_WRITE_4(sc, AML_SDXC_CMD_ARGUMENT_REG, cmd->arg); X X aml8726_sdxc_engage_dma(sc); X X CSR_WRITE_4(sc, AML_SDXC_SEND_REG, sndr); X CSR_BARRIER(sc, AML_SDXC_SEND_REG); X X return (MMC_ERR_NONE); } X X static void aml8726_sdxc_finish_command(struct aml8726_sdxc_softc *sc, int mmc_error) { X int mmc_stop_error; X struct mmc_command *cmd; X struct mmc_command *stop_cmd; X struct mmc_data *data; X X AML_SDXC_LOCK_ASSERT(sc); X X /* Clear all interrupts since the request is no longer in flight. */ X CSR_WRITE_4(sc, AML_SDXC_IRQ_STATUS_REG, AML_SDXC_IRQ_STATUS_CLEAR); X CSR_BARRIER(sc, AML_SDXC_IRQ_STATUS_REG); X X /* In some cases (e.g. finish called via timeout) this is a NOP. */ X callout_stop(&sc->ch); X X cmd = sc->cmd; X sc->cmd = NULL; X X cmd->error = mmc_error; 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 there's a linked stop command, then start the stop command. X * In order to establish a known state attempt the stop command X * even if the original request encountered an error. X */ X X stop_cmd = (cmd->mrq->stop != cmd) ? cmd->mrq->stop : NULL; X X if (stop_cmd != NULL) { X X /* X * If the original command executed successfuly, then X * the hardware will also have automatically executed X * a stop command so don't bother with the one supplied X * with the original request. X */ X X if (mmc_error == MMC_ERR_NONE) { X stop_cmd->error = MMC_ERR_NONE; X stop_cmd->resp[0] = cmd->resp[0]; X stop_cmd->resp[1] = cmd->resp[1]; X stop_cmd->resp[2] = cmd->resp[2]; X stop_cmd->resp[3] = cmd->resp[3]; X } else { X mmc_stop_error X = aml8726_sdxc_start_command(sc, stop_cmd); X if (mmc_stop_error == MMC_ERR_NONE) { X AML_SDXC_UNLOCK(sc); X return; X } X stop_cmd->error = mmc_stop_error; X } X } X X AML_SDXC_UNLOCK(sc); X X /* Execute the callback after dropping the lock. */ X if (cmd->mrq != NULL) X cmd->mrq->done(cmd->mrq); } X X static void aml8726_sdxc_timeout(void *arg) { X struct aml8726_sdxc_softc *sc = (struct aml8726_sdxc_softc *)arg; X X /* X * The command failed to complete in time so forcefully X * terminate it. X */ X aml8726_sdxc_soft_reset(sc); X X /* X * Ensure the command has terminated before continuing on X * to things such as bus_dmamap_sync / bus_dmamap_unload. X */ X while ((CSR_READ_4(sc, AML_SDXC_STATUS_REG) X & AML_SDXC_STATUS_BUSY) != 0) X cpu_spinwait(); X X aml8726_sdxc_finish_command(sc, MMC_ERR_TIMEOUT); } X X static void aml8726_sdxc_busy_check(void *arg) { X struct aml8726_sdxc_softc *sc = (struct aml8726_sdxc_softc *)arg; X uint32_t sr; X X sc->busy.time += AML_SDXC_BUSY_POLL_INTVL; X X sr = CSR_READ_4(sc, AML_SDXC_STATUS_REG); X X if ((sr & AML_SDXC_STATUS_DAT0) == 0) { X if (sc->busy.time < AML_SDXC_BUSY_TIMEOUT) { X callout_reset(&sc->ch, X msecs_to_ticks(AML_SDXC_BUSY_POLL_INTVL), X aml8726_sdxc_busy_check, sc); X AML_SDXC_UNLOCK(sc); X return; X } X if (sc->busy.error == MMC_ERR_NONE) X sc->busy.error = MMC_ERR_TIMEOUT; X } X X aml8726_sdxc_finish_command(sc, sc->busy.error); } X X static void aml8726_sdxc_intr(void *arg) { X struct aml8726_sdxc_softc *sc = (struct aml8726_sdxc_softc *)arg; X uint32_t isr; X uint32_t pdmar; X uint32_t sndr; X uint32_t sr; X int i; X int mmc_error; X int start; X int stop; X X AML_SDXC_LOCK(sc); X X isr = CSR_READ_4(sc, AML_SDXC_IRQ_STATUS_REG); X sndr = CSR_READ_4(sc, AML_SDXC_SEND_REG); X sr = CSR_READ_4(sc, AML_SDXC_STATUS_REG); X X if (sc->cmd == NULL) X goto spurious; X X mmc_error = MMC_ERR_NONE; X X if ((isr & (AML_SDXC_IRQ_STATUS_TX_FIFO_EMPTY X | AML_SDXC_IRQ_STATUS_RX_FIFO_FULL)) != 0) X mmc_error = MMC_ERR_FIFO; X else if ((isr & (AML_SDXC_IRQ_ENABLE_A_PKG_CRC_ERR X | AML_SDXC_IRQ_ENABLE_RESP_CRC_ERR)) != 0) X mmc_error = MMC_ERR_BADCRC; X else if ((isr & (AML_SDXC_IRQ_ENABLE_A_PKG_TIMEOUT_ERR X | AML_SDXC_IRQ_ENABLE_RESP_TIMEOUT_ERR)) != 0) X mmc_error = MMC_ERR_TIMEOUT; X else if ((isr & (AML_SDXC_IRQ_STATUS_RESP_OK X | AML_SDXC_IRQ_STATUS_DMA_DONE X | AML_SDXC_IRQ_STATUS_TRANSFER_DONE_OK)) != 0) { X ; X } X else { spurious: 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_SDXC_IRQ_STATUS_REG, X (AML_SDXC_IRQ_STATUS_CLEAR & isr)); X CSR_BARRIER(sc, AML_SDXC_IRQ_STATUS_REG); X AML_SDXC_UNLOCK(sc); X return; X } X X aml8726_sdxc_disengage_dma(sc); X X if ((sndr & AML_SDXC_SEND_CMD_HAS_RESP) != 0) { X start = 0; X stop = 1; X if ((sndr & AML_SDXC_SEND_RESP_136) != 0) { X start = 1; X stop = start + 4;; X } X for (i = start; i < stop; i++) { X pdmar = CSR_READ_4(sc, AML_SDXC_PDMA_REG); X pdmar &= ~(AML_SDXC_PDMA_DMA_EN X | AML_SDXC_PDMA_RESP_INDEX_MASK); X pdmar |= i << AML_SDXC_PDMA_RESP_INDEX_SHIFT; X CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); X sc->cmd->resp[(stop - 1) - i] X = CSR_READ_4(sc, AML_SDXC_CMD_ARGUMENT_REG); X } X } X X if ((sr & AML_SDXC_STATUS_BUSY) != 0 X /* X * A multiblock operation may keep the hardware X * busy until stop transmission is executed. X */ X && (isr & (AML_SDXC_IRQ_STATUS_DMA_DONE X | AML_SDXC_IRQ_STATUS_TRANSFER_DONE_OK)) == 0) { X if (mmc_error == MMC_ERR_NONE) X mmc_error = MMC_ERR_FAILED; X X /* X * Issue a soft reset 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 aml8726_sdxc_soft_reset(sc); X X while ((CSR_READ_4(sc, AML_SDXC_STATUS_REG) X & AML_SDXC_STATUS_BUSY) != 0) X cpu_spinwait(); X } X X /* X * The stop command can be generated either manually or X * automatically by the hardware if MISC_MANUAL_STOP_MODE X * has not been set. In either case check for busy. X */ X X if (((sc->cmd->flags & MMC_RSP_BUSY) != 0 X || (sndr & AML_SDXC_SEND_INDEX_MASK) == MMC_STOP_TRANSMISSION) X && (sr & AML_SDXC_STATUS_DAT0) == 0) { X sc->busy.error = mmc_error; X callout_reset(&sc->ch, X msecs_to_ticks(AML_SDXC_BUSY_POLL_INTVL), X aml8726_sdxc_busy_check, sc); X CSR_WRITE_4(sc, AML_SDXC_IRQ_STATUS_REG, X (AML_SDXC_IRQ_STATUS_CLEAR & isr)); X CSR_BARRIER(sc, AML_SDXC_IRQ_STATUS_REG); X AML_SDXC_UNLOCK(sc); X return; X } X X aml8726_sdxc_finish_command(sc, mmc_error); } X X static int aml8726_sdxc_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-sdxc-m8")) X return (ENXIO); X X device_set_desc(dev, "Amlogic aml8726-m8 SDXC"); X X return (BUS_PROBE_DEFAULT); } X X static int aml8726_sdxc_attach(device_t dev) { X struct aml8726_sdxc_softc *sc = device_get_softc(dev); X char *voltages; X char *voltage; X int error; X int nvoltages; X pcell_t prop[3]; X phandle_t node; X ssize_t len; X device_t child; X uint32_t ectlr; X uint32_t miscr; X uint32_t pdmar; X X sc->dev = dev; X X sc->auto_fill_flush = false; X X pdmar = AML_SDXC_PDMA_DMA_URGENT X | (49 << AML_SDXC_PDMA_TX_THOLD_SHIFT) X | (7 << AML_SDXC_PDMA_RX_THOLD_SHIFT) X | (15 << AML_SDXC_PDMA_RD_BURST_SHIFT) X | (7 << AML_SDXC_PDMA_WR_BURST_SHIFT); X X miscr = (2 << AML_SDXC_MISC_WCRC_OK_PAT_SHIFT) X | (5 << AML_SDXC_MISC_WCRC_ERR_PAT_SHIFT); X X ectlr = (12 << AML_SDXC_ENH_CNTRL_SDIO_IRQ_PERIOD_SHIFT); X X /* X * Certain bitfields are dependent on the hardware revision. X */ X switch (aml8726_soc_hw_rev) { X case AML_SOC_HW_REV_M8: X switch (aml8726_soc_metal_rev) { X case AML_SOC_M8_METAL_REV_M2_A: X sc->auto_fill_flush = true; X miscr |= (6 << AML_SDXC_MISC_TXSTART_THOLD_SHIFT); X ectlr |= (64 << AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_SHIFT) X | AML_SDXC_ENH_CNTRL_WR_RESP_MODE_SKIP_M8M2; X break; X default: X miscr |= (7 << AML_SDXC_MISC_TXSTART_THOLD_SHIFT); X ectlr |= (63 << AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_SHIFT) X | AML_SDXC_ENH_CNTRL_DMA_NO_WR_RESP_CHECK_M8 X | (255 X << AML_SDXC_ENH_CNTRL_RX_TIMEOUT_SHIFT_M8); X X break; X } X break; X case AML_SOC_HW_REV_M8B: X miscr |= (7 << AML_SDXC_MISC_TXSTART_THOLD_SHIFT); X ectlr |= (63 << AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_SHIFT) X | AML_SDXC_ENH_CNTRL_DMA_NO_WR_RESP_CHECK_M8 X | (255 << AML_SDXC_ENH_CNTRL_RX_TIMEOUT_SHIFT_M8); X break; X default: X device_printf(dev, "unsupported SoC\n"); X return (ENXIO); X /* NOTREACHED */ X break; X } X X node = ofw_bus_get_node(dev); X X len = OF_getencprop(node, "clock-frequency", prop, sizeof(prop)); X if ((len / sizeof(prop[0])) != 1 || prop[0] == 0) { X device_printf(dev, X "missing clock-frequency attribute in FDT\n"); X return (ENXIO); X } X X sc->ref_freq = prop[0]; X X sc->pwr_en.dev = NULL; X X len = OF_getencprop(node, "mmc-pwr-en", prop, sizeof(prop)); X if (len > 0) { X if ((len / sizeof(prop[0])) == 3) { X sc->pwr_en.dev = OF_device_from_xref(prop[0]); X sc->pwr_en.pin = prop[1]; X sc->pwr_en.pol = prop[2]; X } X X if (sc->pwr_en.dev == NULL) { X device_printf(dev, X "unable to process mmc-pwr-en attribute in FDT\n"); X return (ENXIO); X } X X /* Turn off power and then configure the output driver. */ X if (aml8726_sdxc_power_off(sc) != 0 X || GPIO_PIN_SETFLAGS(sc->pwr_en.dev, sc->pwr_en.pin, X GPIO_PIN_OUTPUT) != 0) { X device_printf(dev, X "could not use gpio to control power\n"); X return (ENXIO); X } X } X X len = OF_getprop_alloc(node, "mmc-voltages", X sizeof(char), (void **)&voltages); X X if (len < 0) { X device_printf(dev, "missing mmc-voltages attribute in FDT\n"); X return (ENXIO); X } X X sc->voltages[0] = 0; X sc->voltages[1] = 0; X X voltage = voltages; X nvoltages = 0; X X while (len && nvoltages < 2) { X if (strncmp("1.8", voltage, len) == 0) X sc->voltages[nvoltages] = MMC_OCR_LOW_VOLTAGE; X else if (strncmp("3.3", voltage, len) == 0) X sc->voltages[nvoltages] = MMC_OCR_320_330 X | MMC_OCR_330_340; X else { X device_printf(dev, X "unknown voltage attribute %.*s in FDT\n", X len, voltage); X free(voltages, M_OFWPROP); X return (ENXIO); X } X X nvoltages++; X X /* queue up next string */ X while (*voltage && len) { X voltage++; X len--; X } X if (len) { X voltage++; X len--; X } X } X X free(voltages, M_OFWPROP); X X sc->vselect.dev = NULL; X X len = OF_getencprop(node, "mmc-vselect", prop, sizeof(prop)); X if (len > 0) { X if ((len / sizeof(prop[0])) == 2) { X sc->vselect.dev = OF_device_from_xref(prop[0]); X sc->vselect.pin = prop[1]; X sc->vselect.pol = 1; X } X X if (sc->vselect.dev == NULL) { X device_printf(dev, X "unable to process mmc-vselect attribute in FDT\n"); X return (ENXIO); X } X X /* X * With the power off select voltage 0 and then X * configure the output driver. X */ X if (GPIO_PIN_SET(sc->vselect.dev, sc->vselect.pin, 0) != 0 X || GPIO_PIN_SETFLAGS(sc->vselect.dev, sc->vselect.pin, X GPIO_PIN_OUTPUT) != 0) { X device_printf(dev, X "could not use gpio to set voltage\n"); X return (ENXIO); X } X } X X if (nvoltages == 0) { X device_printf(dev, "no voltages in FDT\n"); X return (ENXIO); X } else if (nvoltages == 1 && sc->vselect.dev != NULL) { X device_printf(dev, "only one voltage in FDT\n"); X return (ENXIO); X } else if (nvoltages == 2 && sc->vselect.dev == NULL) { X device_printf(dev, "too many voltages in FDT\n"); X return (ENXIO); X } X X sc->card_rst.dev = NULL; X X len = OF_getencprop(node, "mmc-rst", prop, sizeof(prop)); X if (len > 0) { X if ((len / sizeof(prop[0])) == 3) { X sc->card_rst.dev = OF_device_from_xref(prop[0]); X sc->card_rst.pin = prop[1]; X sc->card_rst.pol = prop[2]; X } X X if (sc->card_rst.dev == NULL) { X device_printf(dev, X "unable to process mmc-rst attribute in FDT\n"); X return (ENXIO); X } X } X X if (bus_alloc_resources(dev, aml8726_sdxc_spec, sc->res)) { X device_printf(dev, "could not allocate resources for device\n"); X return (ENXIO); X } X X AML_SDXC_LOCK_INIT(sc); X X error = bus_dma_tag_create(bus_get_dma_tag(dev), AML_SDXC_ALIGN_DMA, 0, X BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, X NULL, NULL, AML_SDXC_MAX_DMA, 1, X AML_SDXC_MAX_DMA, 0, NULL, NULL, X &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_sdxc_intr, sc, &sc->ih_cookie); X if (error) { X device_printf(dev, "could not setup interrupt handler\n"); X goto fail; X } X X callout_init_mtx(&sc->ch, &sc->mtx, CALLOUT_RETURNUNLOCKED); X X sc->host.f_min = 200000; X sc->host.f_max = 100000000; X sc->host.host_ocr = sc->voltages[0] | sc->voltages[1]; X sc->host.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA X | MMC_CAP_HSPEED; X X aml8726_sdxc_soft_reset(sc); X X CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); X X CSR_WRITE_4(sc, AML_SDXC_MISC_REG, miscr); X X CSR_WRITE_4(sc, AML_SDXC_ENH_CNTRL_REG, ectlr); X X child = device_add_child(dev, "mmc", -1); 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_SDXC_LOCK_DESTROY(sc); X X (void)aml8726_sdxc_power_off(sc); X X bus_release_resources(dev, aml8726_sdxc_spec, sc->res); X X return (error); } X X static int aml8726_sdxc_detach(device_t dev) { X struct aml8726_sdxc_softc *sc = device_get_softc(dev); X X AML_SDXC_LOCK(sc); X X if (sc->cmd != NULL) { X AML_SDXC_UNLOCK(sc); X return (EBUSY); X } X X /* X * Turn off the power, reset the hardware state machine, X * and disable the interrupts. X */ X (void)aml8726_sdxc_power_off(sc); X aml8726_sdxc_soft_reset(sc); X CSR_WRITE_4(sc, AML_SDXC_IRQ_ENABLE_REG, 0); X X AML_SDXC_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_SDXC_LOCK_DESTROY(sc); X X bus_release_resources(dev, aml8726_sdxc_spec, sc->res); X X return (0); } X X static int aml8726_sdxc_shutdown(device_t dev) { X struct aml8726_sdxc_softc *sc = device_get_softc(dev); X X /* X * Turn off the power, reset the hardware state machine, X * and disable the interrupts. X */ X (void)aml8726_sdxc_power_off(sc); X aml8726_sdxc_soft_reset(sc); X CSR_WRITE_4(sc, AML_SDXC_IRQ_ENABLE_REG, 0); X X return (0); } X X static int aml8726_sdxc_update_ios(device_t bus, device_t child) { X struct aml8726_sdxc_softc *sc = device_get_softc(bus); X struct mmc_ios *ios = &sc->host.ios; X unsigned int divisor; X int error; X int i; X uint32_t cctlr; X uint32_t clk2r; X uint32_t ctlr; X uint32_t freq; X X ctlr = (7 << AML_SDXC_CNTRL_TX_ENDIAN_SHIFT) X | (7 << AML_SDXC_CNTRL_RX_ENDIAN_SHIFT) X | (0xf << AML_SDXC_CNTRL_RX_PERIOD_SHIFT) X | (0x7f << AML_SDXC_CNTRL_RX_TIMEOUT_SHIFT); X X switch (ios->bus_width) { X case bus_width_8: X ctlr |= AML_SDXC_CNTRL_BUS_WIDTH_8; X break; X case bus_width_4: X ctlr |= AML_SDXC_CNTRL_BUS_WIDTH_4; X break; X case bus_width_1: X ctlr |= AML_SDXC_CNTRL_BUS_WIDTH_1; X break; X default: X return (EINVAL); X } X X CSR_WRITE_4(sc, AML_SDXC_CNTRL_REG, ctlr); X X /* X * Disable clocks and then clock module prior to setting desired values. X */ X cctlr = CSR_READ_4(sc, AML_SDXC_CLK_CNTRL_REG); X cctlr &= ~(AML_SDXC_CLK_CNTRL_TX_CLK_EN | AML_SDXC_CLK_CNTRL_RX_CLK_EN X | AML_SDXC_CLK_CNTRL_SD_CLK_EN); X CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); X CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); X cctlr &= ~AML_SDXC_CLK_CNTRL_CLK_MODULE_EN; X CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); X CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); X X /* X * aml8726-m8 X * X * Clock select 1 fclk_div2 (1.275 GHz) X */ X cctlr &= ~AML_SDXC_CLK_CNTRL_CLK_SEL_MASK; X cctlr |= (1 << AML_SDXC_CLK_CNTRL_CLK_SEL_SHIFT); X X divisor = sc->ref_freq / ios->clock - 1; X if (divisor == 0 || divisor == -1) X divisor = 1; X if ((sc->ref_freq / (divisor + 1)) > ios->clock) X divisor += 1; X if (divisor > (AML_SDXC_CLK_CNTRL_CLK_DIV_MASK X >> AML_SDXC_CLK_CNTRL_CLK_DIV_SHIFT)) X divisor = AML_SDXC_CLK_CNTRL_CLK_DIV_MASK X >> AML_SDXC_CLK_CNTRL_CLK_DIV_SHIFT; X X cctlr &= ~AML_SDXC_CLK_CNTRL_CLK_DIV_MASK; X cctlr |= divisor << AML_SDXC_CLK_CNTRL_CLK_DIV_SHIFT; X X cctlr &= ~AML_SDXC_CLK_CNTRL_MEM_PWR_MASK; X cctlr |= AML_SDXC_CLK_CNTRL_MEM_PWR_ON; X X CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); X CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); X X /* X * Enable clock module and then clocks after setting desired values. X */ X cctlr |= AML_SDXC_CLK_CNTRL_CLK_MODULE_EN; X CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); X CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); X cctlr |= AML_SDXC_CLK_CNTRL_TX_CLK_EN | AML_SDXC_CLK_CNTRL_RX_CLK_EN X | AML_SDXC_CLK_CNTRL_SD_CLK_EN; X CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); X CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); X X freq = sc->ref_freq / divisor; X X for (i = 0; aml8726_sdxc_clk_phases[i].voltage; i++) { X if ((aml8726_sdxc_clk_phases[i].voltage & (1 << ios->vdd)) != 0 X && freq > aml8726_sdxc_clk_phases[i].freq) X break; X if (aml8726_sdxc_clk_phases[i].freq == 0) X break; X } X X clk2r = (1 << AML_SDXC_CLK2_SD_PHASE_SHIFT) X | (aml8726_sdxc_clk_phases[i].rx_phase X << AML_SDXC_CLK2_RX_PHASE_SHIFT); X CSR_WRITE_4(sc, AML_SDXC_CLK2_REG, clk2r); X CSR_BARRIER(sc, AML_SDXC_CLK2_REG); X X error = 0; X X switch (ios->power_mode) { X case power_up: X /* X * Configure and power on the regulator so that the X * voltage stabilizes prior to powering on the card. X */ X if (sc->vselect.dev != NULL) { X for (i = 0; i < 2; i++) X if ((sc->voltages[i] & (1 << ios->vdd)) != 0) X break; X if (i >= 2) X return (EINVAL); X error = GPIO_PIN_SET(sc->vselect.dev, X sc->vselect.pin, i); X } X break; X case power_on: X error = aml8726_sdxc_power_on(sc); X if (error) X break; X X if (sc->card_rst.dev != NULL) { X if (GPIO_PIN_SET(sc->card_rst.dev, sc->card_rst.pin, X PIN_ON_FLAG(sc->card_rst.pol)) != 0 X || GPIO_PIN_SETFLAGS(sc->card_rst.dev, X sc->card_rst.pin, X GPIO_PIN_OUTPUT) != 0) X error = ENXIO; X X DELAY(5); X X if (GPIO_PIN_SET(sc->card_rst.dev, sc->card_rst.pin, X PIN_OFF_FLAG(sc->card_rst.pol)) != 0) X error = ENXIO; X X DELAY(5); X X if (error) { X device_printf(sc->dev, X "could not use gpio to reset card\n"); X break; X } X } X break; X case power_off: X error = aml8726_sdxc_power_off(sc); X break; X default: X return (EINVAL); X } X X return (error); } X X static int aml8726_sdxc_request(device_t bus, device_t child, struct mmc_request *req) { X struct aml8726_sdxc_softc *sc = device_get_softc(bus); X int mmc_error; X X AML_SDXC_LOCK(sc); X X if (sc->cmd != NULL) { X AML_SDXC_UNLOCK(sc); X return (EBUSY); X } X X mmc_error = aml8726_sdxc_start_command(sc, req->cmd); X X AML_SDXC_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_sdxc_read_ivar(device_t bus, device_t child, X int which, uintptr_t *result) { X struct aml8726_sdxc_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_SDXC_MAX_DMA / MMC_SECTOR_SIZE; X break; X default: X return (EINVAL); X } X X return (0); } X X static int aml8726_sdxc_write_ivar(device_t bus, device_t child, X int which, uintptr_t value) { X struct aml8726_sdxc_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_sdxc_get_ro(device_t bus, device_t child) { X X return (0); } X X static int aml8726_sdxc_acquire_host(device_t bus, device_t child) { X struct aml8726_sdxc_softc *sc = device_get_softc(bus); X X AML_SDXC_LOCK(sc); X X while (sc->bus_busy) X mtx_sleep(sc, &sc->mtx, PZERO, "sdxc", hz / 5); X sc->bus_busy++; X X AML_SDXC_UNLOCK(sc); X X return (0); } X X static int aml8726_sdxc_release_host(device_t bus, device_t child) { X struct aml8726_sdxc_softc *sc = device_get_softc(bus); X X AML_SDXC_LOCK(sc); X X sc->bus_busy--; X wakeup(sc); X X AML_SDXC_UNLOCK(sc); X X return (0); } X X static device_method_t aml8726_sdxc_methods[] = { X /* Device interface */ X DEVMETHOD(device_probe, aml8726_sdxc_probe), X DEVMETHOD(device_attach, aml8726_sdxc_attach), X DEVMETHOD(device_detach, aml8726_sdxc_detach), X DEVMETHOD(device_shutdown, aml8726_sdxc_shutdown), X X /* Bus interface */ X DEVMETHOD(bus_read_ivar, aml8726_sdxc_read_ivar), X DEVMETHOD(bus_write_ivar, aml8726_sdxc_write_ivar), X X /* MMC bridge interface */ X DEVMETHOD(mmcbr_update_ios, aml8726_sdxc_update_ios), X DEVMETHOD(mmcbr_request, aml8726_sdxc_request), X DEVMETHOD(mmcbr_get_ro, aml8726_sdxc_get_ro), X DEVMETHOD(mmcbr_acquire_host, aml8726_sdxc_acquire_host), X DEVMETHOD(mmcbr_release_host, aml8726_sdxc_release_host), X X DEVMETHOD_END }; X static driver_t aml8726_sdxc_driver = { X "aml8726_sdxc", X aml8726_sdxc_methods, X sizeof(struct aml8726_sdxc_softc), }; X static devclass_t aml8726_sdxc_devclass; X DRIVER_MODULE(aml8726_sdxc, simplebus, X aml8726_sdxc_driver, aml8726_sdxc_devclass, 0, 0); MODULE_DEPEND(aml8726_sdxc, aml8726_gpio, 1, 1, 1); SHAR_EOF (set 20 15 03 10 23 49 11 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c': 'MD5 check failed' ) << \SHAR_EOF 42d0e39b64cc1d4342e99f8d239661a7 sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c'` -ne 33444 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c' is not 33444" fi fi # ============= sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h ============== if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h' then ${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h (file already exists)" else ${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h (text)" sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.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_SDXC_M8_H #define _ARM_AMLOGIC_AML8726_SDXC_M8_H X X #define AML_SDXC_ALIGN_DMA 4 #define AML_SDXC_MAX_DMA 4096 X /* X * Timeouts are in milliseconds 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_SDXC_CMD_TIMEOUT 50 #define AML_SDXC_READ_TIMEOUT 100 #define AML_SDXC_WRITE_TIMEOUT 500 #define AML_SDXC_MAX_TIMEOUT 5000 X #define AML_SDXC_BUSY_POLL_INTVL 1 #define AML_SDXC_BUSY_TIMEOUT 1000 X /* X * There's some disagreements between the S805 documentation X * and the Amlogic Linux platform code regarding the exact X * layout of various registers ... when in doubt we follow X * the platform code. X */ X #define AML_SDXC_CMD_ARGUMENT_REG 0 X #define AML_SDXC_SEND_REG 4 # define AML_SDXC_SEND_REP_PKG_CNT_MASK (0xffffU << 16) # define AML_SDXC_SEND_REP_PKG_CNT_SHIFT 16 # define AML_SDXC_SEND_DATA_STOP (1 << 11) # define AML_SDXC_SEND_DATA_WRITE (1 << 10) # define AML_SDXC_SEND_RESP_NO_CRC7_CHECK (1 << 9) # define AML_SDXC_SEND_RESP_136 (1 << 8) # define AML_SDXC_SEND_CMD_HAS_DATA (1 << 7) # define AML_SDXC_SEND_CMD_HAS_RESP (1 << 6) # define AML_SDXC_SEND_INDEX_MASK 0x3f # define AML_SDXC_SEND_INDEX_SHIFT 0 X #define AML_SDXC_CNTRL_REG 8 # define AML_SDXC_CNTRL_TX_ENDIAN_MASK (7 << 29) # define AML_SDXC_CNTRL_TX_ENDIAN_SHIFT 29 # define AML_SDXC_CNTRL_RX_ENDIAN_MASK (7 << 24) # define AML_SDXC_CNTRL_RX_ENDIAN_SHIFT 24 # define AML_SDXC_CNTRL_RX_PERIOD_SHIFT 20 # define AML_SDXC_CNTRL_RX_TIMEOUT_SHIFT 13 # define AML_SDXC_CNTRL_PKG_LEN_MASK (0x1ff << 4) # define AML_SDXC_CNTRL_PKG_LEN_SHIFT 4 # define AML_SDXC_CNTRL_BUS_WIDTH_MASK (3 << 0) # define AML_SDXC_CNTRL_BUS_WIDTH_1 (0 << 0) # define AML_SDXC_CNTRL_BUS_WIDTH_4 (1 << 0) # define AML_SDXC_CNTRL_BUS_WIDTH_8 (2 << 0) X #define AML_SDXC_STATUS_REG 12 # define AML_SDXC_STATUS_TX_CNT_MASK (0x7f << 13) # define AML_SDXC_STATUS_TX_CNT_SHIFT 13 # define AML_SDXC_STATUS_RX_CNT_MASK (0x7f << 6) # define AML_SDXC_STATUS_RX_CNT_SHIFT 6 # define AML_SDXC_STATUS_CMD (1 << 5) # define AML_SDXC_STATUS_DAT3 (1 << 4) # define AML_SDXC_STATUS_DAT2 (1 << 3) # define AML_SDXC_STATUS_DAT1 (1 << 2) # define AML_SDXC_STATUS_DAT0 (1 << 1) # define AML_SDXC_STATUS_BUSY (1 << 0) X #define AML_SDXC_CLK_CNTRL_REG 16 # define AML_SDXC_CLK_CNTRL_MEM_PWR_MASK (3 << 25) # define AML_SDXC_CLK_CNTRL_MEM_PWR_OFF (3 << 25) # define AML_SDXC_CLK_CNTRL_MEM_PWR_ON (0 << 25) # define AML_SDXC_CLK_CNTRL_CLK_SEL_MASK (3 << 16) # define AML_SDXC_CLK_CNTRL_CLK_SEL_SHIFT 16 # define AML_SDXC_CLK_CNTRL_CLK_MODULE_EN (1 << 15) # define AML_SDXC_CLK_CNTRL_SD_CLK_EN (1 << 14) # define AML_SDXC_CLK_CNTRL_RX_CLK_EN (1 << 13) # define AML_SDXC_CLK_CNTRL_TX_CLK_EN (1 << 12) # define AML_SDXC_CLK_CNTRL_CLK_DIV_MASK 0x0fff # define AML_SDXC_CLK_CNTRL_CLK_DIV_SHIFT 0 X #define AML_SDXC_DMA_ADDR_REG 20 X #define AML_SDXC_PDMA_REG 24 # define AML_SDXC_PDMA_TX_FILL (1U << 31) # define AML_SDXC_PDMA_RX_FLUSH_NOW (1 << 30) # define AML_SDXC_PDMA_RX_FLUSH_MODE_SW (1 << 29) # define AML_SDXC_PDMA_TX_THOLD_MASK (0x3f << 22) # define AML_SDXC_PDMA_TX_THOLD_SHIFT 22 # define AML_SDXC_PDMA_RX_THOLD_MASK (0x3f << 15) # define AML_SDXC_PDMA_RX_THOLD_SHIFT 15 # define AML_SDXC_PDMA_RD_BURST_MASK (0x1f << 10) # define AML_SDXC_PDMA_RD_BURST_SHIFT 10 # define AML_SDXC_PDMA_WR_BURST_MASK (0x1f << 5) # define AML_SDXC_PDMA_WR_BURST_SHIFT 5 # define AML_SDXC_PDMA_DMA_URGENT (1 << 4) # define AML_SDXC_PDMA_RESP_INDEX_MASK (7 << 1) # define AML_SDXC_PDMA_RESP_INDEX_SHIFT 1 # define AML_SDXC_PDMA_DMA_EN (1 << 0) X #define AML_SDXC_MISC_REG 28 # define AML_SDXC_MISC_TXSTART_THOLD_MASK (7U << 29) # define AML_SDXC_MISC_TXSTART_THOLD_SHIFT 29 # define AML_SDXC_MISC_MANUAL_STOP_MODE (1 << 28) # define AML_SDXC_MISC_WCRC_OK_PAT_MASK (7 << 7) # define AML_SDXC_MISC_WCRC_OK_PAT_SHIFT 7 # define AML_SDXC_MISC_WCRC_ERR_PAT_MASK (7 << 4) # define AML_SDXC_MISC_WCRC_ERR_PAT_SHIFT 4 X #define AML_SDXC_DATA_REG 32 X #define AML_SDXC_IRQ_ENABLE_REG 36 # define AML_SDXC_IRQ_ENABLE_TX_FIFO_EMPTY (1 << 13) # define AML_SDXC_IRQ_ENABLE_RX_FIFO_FULL (1 << 12) # define AML_SDXC_IRQ_ENABLE_DMA_DONE (1 << 11) # define AML_SDXC_IRQ_ENABLE_TRANSFER_DONE_OK (1 << 7) # define AML_SDXC_IRQ_ENABLE_A_PKG_CRC_ERR (1 << 6) # define AML_SDXC_IRQ_ENABLE_A_PKG_TIMEOUT_ERR (1 << 5) # define AML_SDXC_IRQ_ENABLE_A_PKG_DONE_OK (1 << 4) # define AML_SDXC_IRQ_ENABLE_RESP_CRC_ERR (1 << 2) # define AML_SDXC_IRQ_ENABLE_RESP_TIMEOUT_ERR (1 << 1) # define AML_SDXC_IRQ_ENABLE_RESP_OK (1 << 0) X # define AML_SDXC_IRQ_ENABLE_STANDARD \ X (AML_SDXC_IRQ_ENABLE_TX_FIFO_EMPTY \ X | AML_SDXC_IRQ_ENABLE_RX_FIFO_FULL \ X | AML_SDXC_IRQ_ENABLE_A_PKG_CRC_ERR \ X | AML_SDXC_IRQ_ENABLE_A_PKG_TIMEOUT_ERR \ X | AML_SDXC_IRQ_ENABLE_RESP_CRC_ERR \ X | AML_SDXC_IRQ_ENABLE_RESP_TIMEOUT_ERR \ X | AML_SDXC_IRQ_ENABLE_RESP_OK) X #define AML_SDXC_IRQ_STATUS_REG 40 # define AML_SDXC_IRQ_STATUS_TX_FIFO_EMPTY (1 << 13) # define AML_SDXC_IRQ_STATUS_RX_FIFO_FULL (1 << 12) # define AML_SDXC_IRQ_STATUS_DMA_DONE (1 << 11) # define AML_SDXC_IRQ_STATUS_TRANSFER_DONE_OK (1 << 7) # define AML_SDXC_IRQ_STATUS_A_PKG_CRC_ERR (1 << 6) # define AML_SDXC_IRQ_STATUS_A_PKG_TIMEOUT_ERR (1 << 5) # define AML_SDXC_IRQ_STATUS_A_PKG_DONE_OK (1 << 4) # define AML_SDXC_IRQ_STATUS_RESP_CRC_ERR (1 << 2) # define AML_SDXC_IRQ_STATUS_RESP_TIMEOUT_ERR (1 << 1) # define AML_SDXC_IRQ_STATUS_RESP_OK (1 << 0) X # define AML_SDXC_IRQ_STATUS_CLEAR \ X (AML_SDXC_IRQ_STATUS_TX_FIFO_EMPTY \ X | AML_SDXC_IRQ_STATUS_RX_FIFO_FULL \ X | AML_SDXC_IRQ_STATUS_DMA_DONE \ X | AML_SDXC_IRQ_STATUS_TRANSFER_DONE_OK \ X | AML_SDXC_IRQ_STATUS_A_PKG_CRC_ERR \ X | AML_SDXC_IRQ_STATUS_A_PKG_TIMEOUT_ERR \ X | AML_SDXC_IRQ_STATUS_RESP_CRC_ERR \ X | AML_SDXC_IRQ_STATUS_RESP_TIMEOUT_ERR \ X | AML_SDXC_IRQ_STATUS_RESP_OK) X #define AML_SDXC_SOFT_RESET_REG 44 # define AML_SDXC_SOFT_RESET_DMA (1 << 5) # define AML_SDXC_SOFT_RESET_TX_PHY (1 << 4) # define AML_SDXC_SOFT_RESET_RX_PHY (1 << 3) # define AML_SDXC_SOFT_RESET_TX_FIFO (1 << 2) # define AML_SDXC_SOFT_RESET_RX_FIFO (1 << 1) # define AML_SDXC_SOFT_RESET_MAIN (1 << 0) X # define AML_SDXC_SOFT_RESET \ X (AML_SDXC_SOFT_RESET_DMA \ X | AML_SDXC_SOFT_RESET_TX_FIFO \ X | AML_SDXC_SOFT_RESET_RX_FIFO \ X | AML_SDXC_SOFT_RESET_MAIN) X #define AML_SDXC_ENH_CNTRL_REG 52 # define AML_SDXC_ENH_CNTRL_TX_EMPTY_THOLD_MASK (0x7f << 25) # define AML_SDXC_ENH_CNTRL_TX_EMPTY_THOLD_SHIFT 25 # define AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_MASK (0x7f << 18) # define AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_SHIFT 18 # define AML_SDXC_ENH_CNTRL_SDIO_IRQ_PERIOD_MASK (0xff << 8) # define AML_SDXC_ENH_CNTRL_SDIO_IRQ_PERIOD_SHIFT 8 X # define AML_SDXC_ENH_CNTRL_DMA_NO_WR_RESP_CHECK_M8 (1 << 17) # define AML_SDXC_ENH_CNTRL_DMA_NO_RD_RESP_CHECK_M8 (1 << 16) # define AML_SDXC_ENH_CNTRL_RX_TIMEOUT_MASK_M8 (0xff << 0) # define AML_SDXC_ENH_CNTRL_RX_TIMEOUT_SHIFT_M8 0 X # define AML_SDXC_ENH_CNTRL_NO_DMA_CHECK_M8M2 (1 << 2) # define AML_SDXC_ENH_CNTRL_NO_WR_RESP_CHECK_M8M2 (1 << 1) # define AML_SDXC_ENH_CNTRL_WR_RESP_MODE_SKIP_M8M2 (1 << 0) X X #define AML_SDXC_CLK2_REG 56 # define AML_SDXC_CLK2_SD_PHASE_MASK (0x3ff << 12) # define AML_SDXC_CLK2_SD_PHASE_SHIFT 12 # define AML_SDXC_CLK2_RX_PHASE_MASK (0x3ff << 0) # define AML_SDXC_CLK2_RX_PHASE_SHIFT 0 X X #endif /* _ARM_AMLOGIC_AML8726_SDXC_M8_H */ SHAR_EOF (set 20 15 03 10 23 32 20 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h' eval "${shar_touch}") && \ chmod 0644 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h' if test $? -ne 0 then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h': 'MD5 check failed' ) << \SHAR_EOF d9208202370810e7b17550755db9cecd sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h'` -ne 10812 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h' is not 10812" 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_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 03 06 01 10 42 '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 96feec25c9c7f9fdf0e23ebd49836102 sys/arm/amlogic/aml8726/aml8726_soc.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_soc.h'` -ne 2262 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_soc.h' is not 2262" 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 03 10 02 58 25 '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-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_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_TWO_WIRE_EN (1 << 15) # 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 02 25 23 03 57 '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 9850dc7ed0b7678e868d3974fc95bcff sys/arm/amlogic/aml8726/aml8726_uart.h SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_uart.h'` -ne 4344 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_uart.h' is not 4344" 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-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 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 /* Use two wire mode. */ X cr |= AML_UART_CONTROL_TWO_WIRE_EN; 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 15 02 25 23 21 49 '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 327e1e70bbf0e4b235783acc26ba9f01 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 4452 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/aml8726_uart_console.c' is not 4452" 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 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 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_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 02 28 12 24 47 '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 5d70db9c554616e4090c9a818a8a5726 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 dependent 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 03 08 22 04 39 '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 cfada5fe64b2ced63649f72c738a3ece 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_ccm.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 # also define SOCDEV_PA and SOCDEV_VA in std.aml8726 #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_sdxc-m8.c optional mmc gpio arm/amlogic/aml8726/aml8726_pinctrl.c optional fdt_pinctrl arm/amlogic/aml8726/aml8726_rng.c optional random arm/amlogic/aml8726/uart_dev_aml8726.c optional uart 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 03 10 23 42 37 '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 6f8812b5ec2609c35828829651cde70b sys/arm/amlogic/aml8726/files.aml8726 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/files.aml8726'` -ne 1406 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/files.aml8726' is not 1406" 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 device fdt_pinctrl 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 03 10 23 42 17 '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 6ef080a978bfd0b64d4bd24019bd1040 sys/arm/amlogic/aml8726/std.aml8726 SHAR_EOF else test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/std.aml8726'` -ne 419 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/std.aml8726' is not 419" 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-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 UART driver. X * X * The current implementation only targets features common to all X * uarts. For example ... though UART A as a 128 byte FIFO, the X * 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-m6) has not been activated. X */ X #include __FBSDID("$FreeBSD$"); X #include #include #include #include #include #include X #include #include X #include #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 = 1; X sc->sc_hwoflow = 1; 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 /* Default to two wire mode. */ X cr |= AML_UART_CONTROL_TWO_WIRE_EN; 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 case UART_IOCTL_IFLOW: X case UART_IOCTL_OFLOW: X cr = uart_getreg(bas, AML_UART_CONTROL_REG); X if (data) X cr &= ~AML_UART_CONTROL_TWO_WIRE_EN; X else X cr |= AML_UART_CONTROL_TWO_WIRE_EN; X uart_setreg(bas, AML_UART_CONTROL_REG, cr); 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 }; X static struct ofw_compat_data compat_data[] = { X { "amlogic,aml8726-uart", (uintptr_t)&uart_aml8726_class }, X { NULL, (uintptr_t)NULL } }; UART_FDT_CLASS_AND_DEVICE(compat_data); SHAR_EOF (set 20 15 03 10 22 12 17 '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 927b4ce40522939c0dd031ae5d104e52 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 17167 && \ ${echo} "restoration warning: size of 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c' is not 17167" 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