Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Feb 2015 18:33:25 -0500 (EST)
From:      John Wehle <john@feith.com>
To:        ganbold@gmail.com
Cc:        freebsd-arm@freebsd.org
Subject:   Initial Amlogic aml8726-m6 and aml8726-m8 support files
Message-ID:  <201502012333.t11NXPOe028696@jwlab.FEITH.COM>

next in thread | raw e-mail | index | archive | help
Here's the initial release of support for Amlogic ARM SoC devices.  It
supplies basic functionality, however it should by no means be considered
production ready.

Currently FreeBSD successfully boots to the login prompt on an aml8726-m6
board (the box seems to be some type of Visson ATV-102) as well as on an
aml8726-m8b board (a Hardkernel ODROID-C1) using a SD card and a serial
console.

Unshar into your FreeBSD 11.0-current source tree, review the README,
apply the patch, and have fun.

-- John
----------------------8<---------------------------8<-----------------
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.13.5).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh39871
# Made on 2015-02-01 18:04 EST by <john@wagner.FEITH.COM>.
# Source directory was '/usr/local/src/freebsd/src'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#   7202 -rw-r--r-- sys/boot/fdt/dts/arm/odroidc1.dts
#   7657 -rw-r--r-- sys/boot/fdt/dts/arm/vsatv102-m6.dts
#   4235 -rw-r--r-- sys/arm/conf/ODROIDC1
#   4242 -rw-r--r-- sys/arm/conf/VSATV102
#   2581 -rw-r--r-- sys/arm/amlogic/aml8726/README.txt
#   3583 -rw-r--r-- sys/arm/amlogic/aml8726/PatchJLW01
#   7513 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_clkmsr.c
#   1545 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_clkmsr.h
#  12374 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_fb.c
#   7953 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_fb.h
#   9263 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_gpio.c
#   4240 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_identsoc.c
#   2574 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_l2cache.c
#   5417 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_machdep.c
#   1784 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_machdep.h
#  22210 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mmc.c
#   6226 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mmc.h
#  17678 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_mp.c
#   7110 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_pic.c
#   3976 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_rng.c
#  12262 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_rtc.c
#   2304 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_soc.h
#  10833 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_timer.c
#   4290 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_uart.h
#   4389 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_uart_console.c
#  10407 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c
#   8749 -rw-r--r-- sys/arm/amlogic/aml8726/aml8726_wdt.c
#   1260 -rw-r--r-- sys/arm/amlogic/aml8726/files.aml8726
#     82 -rw-r--r-- sys/arm/amlogic/aml8726/files.smp
#   1038 -rwxr--r-- sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh
#    398 -rw-r--r-- sys/arm/amlogic/aml8726/std.aml8726
#    530 -rw-r--r-- sys/arm/amlogic/aml8726/std.odroidc1
#    533 -rw-r--r-- sys/arm/amlogic/aml8726/std.vsatv102-m6
#  16704 -rw-r--r-- sys/arm/amlogic/aml8726/uart_dev_aml8726.c
#
MD5SUM=${MD5SUM-md5sum}
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
test -n "${f}" && md5check=true || md5check=false
${md5check} || \
  echo 'Note: not verifying md5sums.  Consider installing GNU coreutils.'
if test "X$1" = "X-c"
then keep_file=''
else keep_file=true
fi
echo=echo
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=
locale_dir=
set_echo=false

for dir in $PATH
do
  if test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    case `$dir/gettext --version 2>&1 | sed 1q` in
      *GNU*) gettext_dir=$dir
      set_echo=true
      break ;;
    esac
  fi
done

if ${set_echo}
then
  set_echo=false
  for dir in $PATH
  do
    if test -f $dir/shar \
       && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
    then
      locale_dir=`$dir/shar --print-text-domain-dir`
      set_echo=true
      break
    fi
  done

  if ${set_echo}
  then
    TEXTDOMAINDIR=$locale_dir
    export TEXTDOMAINDIR
    TEXTDOMAIN=sharutils
    export TEXTDOMAIN
    echo="$gettext_dir/gettext -s"
  fi
fi
IFS="$save_IFS"
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null
then if (echo -n test; echo 1,2,3) | grep n >/dev/null
     then shar_n= shar_c='
'
     else shar_n=-n shar_c= ; fi
else shar_n= shar_c='\c' ; fi
f=shar-touch.$$
st1=200112312359.59
st2=123123592001.59
st2tr=123123592001.5 # old SysV 14-char limit
st3=1231235901

if   touch -am -t ${st1} ${f} >/dev/null 2>&1 && \
     test ! -f ${st1} && test -f ${f}; then
  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'

elif touch -am ${st2} ${f} >/dev/null 2>&1 && \
     test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then
  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'

elif touch -am ${st3} ${f} >/dev/null 2>&1 && \
     test ! -f ${st3} && test -f ${f}; then
  shar_touch='touch -am $3$4$5$6$2 "$8"'

else
  shar_touch=:
  echo
  ${echo} 'WARNING: not restoring timestamps.  Consider getting and
installing GNU '\''touch'\'', distributed in GNU coreutils...'
  echo
fi
rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}
#
if test ! -d ${lock_dir} ; then :
else ${echo} "lock directory ${lock_dir} exists"
     exit 1
fi
if mkdir ${lock_dir}
then ${echo} "x - created lock directory ${lock_dir}."
else ${echo} "x - failed to create lock directory ${lock_dir}."
     exit 1
fi
# ============= sys/boot/fdt/dts/arm/odroidc1.dts ==============
if test ! -d 'sys'; then
  mkdir 'sys'
if test $? -eq 0
then ${echo} "x - created directory sys."
else ${echo} "x - failed to create directory sys."
     exit 1
fi
fi
if test ! -d 'sys/boot'; then
  mkdir 'sys/boot'
if test $? -eq 0
then ${echo} "x - created directory sys/boot."
else ${echo} "x - failed to create directory sys/boot."
     exit 1
fi
fi
if test ! -d 'sys/boot/fdt'; then
  mkdir 'sys/boot/fdt'
if test $? -eq 0
then ${echo} "x - created directory sys/boot/fdt."
else ${echo} "x - failed to create directory sys/boot/fdt."
     exit 1
fi
fi
if test ! -d 'sys/boot/fdt/dts'; then
  mkdir 'sys/boot/fdt/dts'
if test $? -eq 0
then ${echo} "x - created directory sys/boot/fdt/dts."
else ${echo} "x - failed to create directory sys/boot/fdt/dts."
     exit 1
fi
fi
if test ! -d 'sys/boot/fdt/dts/arm'; then
  mkdir 'sys/boot/fdt/dts/arm'
if test $? -eq 0
then ${echo} "x - created directory sys/boot/fdt/dts/arm."
else ${echo} "x - failed to create directory sys/boot/fdt/dts/arm."
     exit 1
fi
fi
if test -n "${keep_file}" && test -f 'sys/boot/fdt/dts/arm/odroidc1.dts'
then
${echo} "x - SKIPPING sys/boot/fdt/dts/arm/odroidc1.dts (file already exists)"

else
${echo} "x - extracting sys/boot/fdt/dts/arm/odroidc1.dts (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/boot/fdt/dts/arm/odroidc1.dts' &&
/*-
X * Copyright (c) 2015 John Wehle <john@feith.com>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X * 
X * $FreeBSD$
X */
X
/*
X * The ordering of certain devices is significant (e.g. usb depends on
X * usb-phy which depends on gpio, also the timer should appear early on
X * to provide a reasonably accurate DELAY implementation).
X *
X * Both usb-phys devices must be configured to prevent the usb controller
X * from hanging during initialization.
X */
X
/dts-v1/;
X
/memreserve/ 0x7900000 0x00600000;		         /* 6MB frame buffer */
X
/ {
X	model = "hardkernel,odroid-c1";
X	compatible = "hardkernel,odroid-c1", "amlogic,s805";
X
X	#address-cells = <1>;
X	#size-cells = <1>;
X
X	interrupt-parent = <&gic>;
X
X	aliases {
X		soc = &soc;
X		screen = &screen;
X		uart0 = &uart0;
X	};
X
X	cpus {
X		#address-cells = <1>;
X		#size-cells = <0>;
X
X		cpu@0 {
X			device_type = "cpu";
X			compatible = "arm,cortex-a5";
X			reg = <0x0>;
X		};
X
X		cpu@1 {
X			device_type = "cpu";
X			compatible = "arm,cortex-a5";
X			reg = <0x1>;
X		};
X
X		cpu@2 {
X			device_type = "cpu";
X			compatible = "arm,cortex-a5";
X			reg = <0x2>;
X		};
X
X		cpu@3 {
X			device_type = "cpu";
X			compatible = "arm,cortex-a5";
X			reg = <0x3>;
X		};
X	};
X
X	memory {
X		device_type = "memory";
X		reg = <0x0 0x40000000>;        /* 1GB RAM */
X	};
X
X	soc: soc@c0000000 {
X		device_type = "soc";
X		compatible = "simple-bus";
X		bus-frequency = <0>;
X
X		#address-cells = <1>;
X		#size-cells = <1>;
X
X		ranges = <0x0 0xc0000000 0x1a100000>;
X
X		gic: gic@4301000 {
X			device_type = "interrupt-controller";
X			compatible = "arm,gic";
X			reg = <0x4301000 0x1000>, // distributer registers
X			      <0x4300100 0x0100>; // CPU if registers
X
X			interrupt-controller;
X			#interrupt-cells = <1>;
X		};
X
X		scu: scu@4300000 {
X			compatible = "arm,cortex-a5-scu";
X			reg = <0x4300000 0x1000>;
X		};
X
X		cpuconfig: cpuconfig@1901ff80 {
X			compatible = "amlogic,aml8726-cpuconfig";
X			reg = <0x1901ff80 16>;
X		};
X
X		pl310@4200000 {
X			compatible = "arm,pl310";
X			reg = <0x4200000 0x1000>;
X			interrupts = <61>; /* AM_IRQ1(29) */
X			interrupt-parent = <&gic>;
X		};
X
X		watchdog@1109900 {
X			compatible = "amlogic,aml8726-wdt";
X			reg = <0x1109900 8>;  /* cbus 0x2640 */
X			interrupts = <0>;  /* AM_IRQ0(0) */
X			interrupt-parent = <&gic>;
X		};
X
X		timer@1109940 {
X			compatible = "amlogic,aml8726-timer";
X			reg = <0x1109940 24>; /* cbus 0x2650 */
X			interrupts = <10   /* AM_IRQ0(10) */
X				      11   /* AM_IRQ0(11) */
X				      6    /* AM_IRQ0(6)  */
X				      29>; /* AM_IRQ0(29) */
X			interrupt-parent = <&gic>;
X		};
X
X		rtc@8100740 {
X			compatible = "amlogic,aml8726-rtc";
X			reg = <0x8100740 20>; /* aobus 0x1d0 */
X			interrupts = <72>; /* AM_IRQ2(8) */
X			interrupt-parent = <&gic>;
X
X			init-always = "false";
X			xo-init = <0x180a>;
X			gpo-init = <0x500000>;
X		};
X
X		clkmsr: clkmsr@1108758 {
X			compatible = "amlogic,aml8726-clkmsr";
X			reg = <0x1108758 16>; /* cbus 0x21d6 */
X		};
X
X		uart0: uart@81004c0 {
X			/* uart-ao */
X			device_type = "serial";
X			compatible = "amlogic,aml8726-uart";
X			clock-frequency = <0>;
X			current-speed = <115200>;
X			reg = <0x81004c0 20>; /* aobus 0x130 */
X			interrupts = <90>; /* AM_IRQ2(26) */
X			interrupt-parent = <&gic>;
X		};
X
X		gpioao: gpio@8100024 {
X			/* gpio unit 7 */
X			compatible = "amlogic,aml8726-gpio";
X			reg = <0x8100024 4>, /* oen aobus 0x9 */
X			      <0x8100024 4>, /* out */
X			      <0x8100028 4>; /* in */
X
X			gpio-controller;
X			#gpio-cells = <1>;
X			pin-count = <14>;
X		};
X
X		gpio5: gpio@110806c {
X			compatible = "amlogic,aml8726-gpio";
X			reg = <0x110806c 4>, /* oen cbus 0x201b */
X			      <0x1108070 4>, /* out */
X			      <0x1108074 4>; /* in */
X
X			gpio-controller;
X			#gpio-cells = <1>;
X			pin-count = <32>;
X		};
X
X		mmc@1108c20 {
X			compatible = "amlogic,aml8726-mmc";
X			reg = <0x1108c20 32>; /* cbus 0x2308 */
X			interrupts = <28>; /* AM_IRQ0(28) */
X			interrupt-parent = <&gic>;
X
X			mmc-pwr-en = <&gpio5 31 0>; /* card8 */
X			ins-detect = <&gpio5 29 0>; /* card6 */
X		};
X
X		rng@1108100 {
X			compatible = "amlogic,aml8726-rng";
X			reg = <0x1108100 8>; /* cbus 0x2040 */
X		};
X
X		usb-phy@1108800 {
X			/* usb-a phy */
X			compatible = "amlogic,aml8726-m8-usb-phy";
X			reg = <0x1108800 32>; /* cbus 0x2200 */
X
X			usb-pwr-en = <&gpioao 5 1>; /* gpioao5 vbus */
X		};
X
X		usb-phy@1108820 {
X			/* usb-b phy */
X			compatible = "amlogic,aml8726-m8-usb-phy";
X			reg = <0x1108820 32>; /* cbus 0x2208 */
X
X			force-aca = "true";
X			usb-hub-rst = <&gpioao 4 0>; /* gpioao4 hub-rst */
X		};
X
X		usb@9040000 {
X			/* usb-a */
X			compatible = "synopsys,designware-hs-otg2";
X			reg = <0x9040000 0x40000>; /* ahbbus 0x40000*/
X			interrupts = <30>; /* AM_IRQ0(30) */
X			interrupt-parent = <&gic>;
X			#address-cells = <1>;
X			#size-cells = <0>;
X
X			dr_mode = "host";
X		};
X
X		usb@90c0000 {
X			/* usb-b */
X			compatible = "synopsys,designware-hs-otg2";
X			reg = <0x90c0000 0x40000>; /* ahbbus 0xc0000 */
X			interrupts = <31>; /* AM_IRQ0(31) */
X			interrupt-parent = <&gic>;
X			#address-cells = <1>;
X			#size-cells = <0>;
X
X			dr_mode = "host";
X		};
X
X		eth@9410000 {
X			/* ethernet */
X			compatible = "snps,dwmac";
X			reg = <0x9410000 0x2000>; /* ahbbus 0x410000 */
X			interrupts = <8>; /* AM_IRQ0(8) */
X			interrupt-parent = <&gic>;
X			#address-cells = <1>;
X			#size-cells = <0>;
X		};
X
X		screen: fb@8006020 {
X			device_type = "display";
X			compatible = "amlogic,aml8726-fb";
X			reg = <0x8006048 12>,   /* CANVAS */
X			      <0x1106800 1024>, /* VIU */
X			      <0x1107400 1024>; /* VPP */
X			interrupts = <2    /* AM_IRQ0(2) */
X				      3    /* AM_IRQ0(3) */
X				      12   /* AM_IRQ0(12) */
X				      13>; /* AM_IRQ0(13) */
X			interrupt-parent = <&gic>;
X			/* status = "disabled"; */
X
X			address = <0x7900000>; /* match memreserve */
X			width = <720>;
X			height = <480>;
X			depth = <24>;
X			linebytes = <2160>;
X		};
X	};
X
X	leds {
X		compatible = "gpio-leds";
X
X		sys_led {
X			gpios = <&gpioao 13>; /* gpioao13 sys_led */
X			label = "sys_led";
X		};
X	};
X
X	chosen {
X		stdin = "uart0";
X		stdout = "uart0";
X	};
};
SHAR_EOF
  (set 20 15 02 01 16 23 56 'sys/boot/fdt/dts/arm/odroidc1.dts'
   eval "${shar_touch}") && \
  chmod 0644 'sys/boot/fdt/dts/arm/odroidc1.dts'
if test $? -ne 0
then ${echo} "restore of sys/boot/fdt/dts/arm/odroidc1.dts failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/boot/fdt/dts/arm/odroidc1.dts': 'MD5 check failed'
       ) << \SHAR_EOF
74a1f989c00329a0fb627ec86940a97d  sys/boot/fdt/dts/arm/odroidc1.dts
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/boot/fdt/dts/arm/odroidc1.dts'` -ne 7202 && \
  ${echo} "restoration warning:  size of 'sys/boot/fdt/dts/arm/odroidc1.dts' is not 7202"
  fi
fi
# ============= sys/boot/fdt/dts/arm/vsatv102-m6.dts ==============
if test ! -d 'sys/boot/fdt/dts/arm'; then
  mkdir 'sys/boot/fdt/dts/arm'
if test $? -eq 0
then ${echo} "x - created directory sys/boot/fdt/dts/arm."
else ${echo} "x - failed to create directory sys/boot/fdt/dts/arm."
     exit 1
fi
fi
if test -n "${keep_file}" && test -f 'sys/boot/fdt/dts/arm/vsatv102-m6.dts'
then
${echo} "x - SKIPPING sys/boot/fdt/dts/arm/vsatv102-m6.dts (file already exists)"

else
${echo} "x - extracting sys/boot/fdt/dts/arm/vsatv102-m6.dts (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/boot/fdt/dts/arm/vsatv102-m6.dts' &&
/*-
X * Copyright (c) 2013-2015 John Wehle <john@feith.com>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X * 
X * $FreeBSD$
X */
X
/*
X * The ordering of certain devices is significant (e.g. usb depends on
X * usb-phy which depends on gpio, also the timer should appear early on
X * to provide a reasonably accurate DELAY implementation).
X *
X * Both usb-phys devices must be configured to prevent the usb controller
X * from hanging during initialization.
X */
X
/dts-v1/;
X
/memreserve/ 0x84900000 0x00600000;		         /* 6MB frame buffer */
X
/ {
X	/*
X	 * My development unit visually appears to be a Visson ATV-102
X	 * and the specs for both my unit and the Visson ATV-102 say
X	 * the SoC is an aml8726-m3.  However the uboot prompt says
X	 * m6_mbx_v1, the RTC is located on SECBUS2 instead of AOBUS,
X	 * and there are two cores so it seems my unit is a newer
X	 * version using the later processor.
X	 */
X
X	model = "visson,atv-102";
X	compatible = "visson,atv-102", "amlogic,aml8726-m6";
X
X	#address-cells = <1>;
X	#size-cells = <1>;
X
X	interrupt-parent = <&gic>;
X
X	aliases {
X		soc = &soc;
X		screen = &screen;
X		uart0 = &uart0;
X	};
X
X	cpus {
X		#address-cells = <1>;
X		#size-cells = <0>;
X
X		cpu@0 {
X			device_type = "cpu";
X			compatible = "arm,cortex-a9";
X			reg = <0x0>;
X		};
X
X		cpu@1 {
X			device_type = "cpu";
X			compatible = "arm,cortex-a9";
X			reg = <0x1>;
X		};
X	};
X
X	memory {
X		device_type = "memory";
X		reg = <0x80000000 0x40000000>;        /* 1GB RAM */
X	};
X
X	soc: soc@c0000000 {
X		device_type = "soc";
X		compatible = "simple-bus";
X		bus-frequency = <0>;
X
X		#address-cells = <1>;
X		#size-cells = <1>;
X
X		ranges = <0x0 0xc0000000 0x1a100000>;
X
X		pic: pic@1109a40 {
X			device_type = "interrupt-controller";
X			compatible = "amlogic,aml8726-pic";
X			reg = <0x1109a40 128>; /* cbus 0x2690 */
X
X			interrupt-controller;
X			#interrupt-cells = <1>;
X		};
X
X		gic: gic@4301000 {
X			device_type = "interrupt-controller";
X			compatible = "arm,gic";
X			reg = <0x4301000 0x1000>, // distributer registers
X			      <0x4300100 0x0100>; // CPU if registers
X
X			interrupt-controller;
X			#interrupt-cells = <1>;
X		};
X
X		scu: scu@4300000 {
X			compatible = "arm,cortex-a9-scu";
X			reg = <0x4300000 0x1000>;
X		};
X
X		cpuconfig: cpuconfig@1901ff80 {
X			compatible = "amlogic,aml8726-cpuconfig";
X			reg = <0x1901ff80 8>;
X		};
X
X		pl310@4200000 {
X			compatible = "arm,pl310";
X			reg = <0x4200000 0x1000>;
X			interrupts = <61>; /* AM_IRQ1(29) */
X			interrupt-parent = <&gic>;
X		};
X
X		watchdog@1109900 {
X			compatible = "amlogic,aml8726-wdt";
X			reg = <0x1109900 8>;  /* cbus 0x2640 */
X			interrupts = <0>;  /* AM_IRQ0(0) */
X			interrupt-parent = <&gic>;
X		};
X
X		timer@1109940 {
X			compatible = "amlogic,aml8726-timer";
X			reg = <0x1109940 24>; /* cbus 0x2650 */
X			interrupts = <10   /* AM_IRQ0(10) */
X				      11   /* AM_IRQ0(11) */
X				      6    /* AM_IRQ0(6)  */
X				      29>; /* AM_IRQ0(29) */
X			interrupt-parent = <&gic>;
X		};
X
X		rtc@1a004340 {
X			compatible = "amlogic,aml8726-rtc";
X			reg = <0x1a004340 20>; /* secbus2 0xd0 */
X			interrupts = <72>; /* AM_IRQ2(8) */
X			interrupt-parent = <&gic>;
X
X			init-always = "false";
X			xo-init = <0x180a>;
X			gpo-init = <0x500000>;
X		};
X
X		clkmsr: clkmsr@1108758 {
X			compatible = "amlogic,aml8726-clkmsr";
X			reg = <0x1108758 16>; /* cbus 0x21d6 */
X		};
X
X		uart0: uart@81004c0 {
X			/* uart-ao */
X			device_type = "serial";
X			compatible = "amlogic,aml8726-uart";
X			clock-frequency = <0>;
X			current-speed = <115200>;
X			reg = <0x81004c0 20>; /* aobus 0x130 */
X			interrupts = <90>; /* AM_IRQ2(26) */
X			interrupt-parent = <&gic>;
X		};
X
X		gpioao: gpio@8100024 {
X			/* gpio unit 7 */
X			compatible = "amlogic,aml8726-gpio";
X			reg = <0x8100024 4>, /* oen aobus 0x9 */
X			      <0x8100024 4>, /* out */
X			      <0x8100028 4>; /* in */
X
X			gpio-controller;
X			#gpio-cells = <1>;
X			pin-count = <12>;
X		};
X
X		gpio5: gpio@110806c {
X			compatible = "amlogic,aml8726-gpio";
X			reg = <0x110806c 4>, /* oen cbus 0x201b */
X			      <0x1108070 4>, /* out */
X			      <0x1108074 4>; /* in */
X
X			gpio-controller;
X			#gpio-cells = <1>;
X			pin-count = <32>;
X		};
X
X		gpio6: gpio@1108020 {
X			compatible = "amlogic,aml8726-gpio";
X			reg = <0x1108020 4>, /* oen cbus 0x2008 */
X			      <0x1108024 4>, /* out */
X			      <0x1108028 4>; /* in */
X
X			gpio-controller;
X			#gpio-cells = <1>;
X			pin-count = <29>;
X		};
X
X		mmc@1108c20 {
X			compatible = "amlogic,aml8726-mmc";
X			reg = <0x1108c20 32>; /* cbus 0x2308 */
X			interrupts = <28>; /* AM_IRQ0(28) */
X			interrupt-parent = <&gic>;
X
X			mmc-pwr-en = <&gpio5 31 0>; /* card8 */
X			ins-detect = <&gpio5 29 0>; /* card6 */
X		};
X
X		rng@1108100 {
X			compatible = "amlogic,aml8726-rng";
X			reg = <0x1108100 8>; /* cbus 0x2040 */
X		};
X
X		usb-phy@1108400 {
X			/* usb-a phy */
X			compatible = "amlogic,aml8726-m6-usb-phy";
X			reg = <0x1108400 32>; /* cbus 0x2100 */
X		};
X
X		usb-phy@1108420 {
X			/* usb-b phy */
X			compatible = "amlogic,aml8726-m6-usb-phy";
X			reg = <0x1108420 32>; /* cbus 0x2108 */
X
X			usb-pwr-en = <&gpioao 3 1>, /* gpioao3 vbus */
X				     <&gpio6 11 0>; /* gpioe11 wifi */
X		};
X
X		usb@9040000 {
X			/* usb-a */
X			compatible = "synopsys,designware-hs-otg2";
X			reg = <0x9040000 0x40000>; /* ahbbus 0x40000*/
X			interrupts = <30>; /* AM_IRQ0(30) */
X			interrupt-parent = <&gic>;
X			#address-cells = <1>;
X			#size-cells = <0>;
X		};
X
X		usb@90c0000 {
X			/* usb-b */
X			compatible = "synopsys,designware-hs-otg2";
X			reg = <0x90c0000 0x40000>; /* ahbbus 0xc0000 */
X			interrupts = <31>; /* AM_IRQ0(31) */
X			interrupt-parent = <&gic>;
X			#address-cells = <1>;
X			#size-cells = <0>;
X
X			dr_mode = "host";
X		};
X
X		eth@9410000 {
X			/* ethernet */
X			compatible = "snps,dwmac";
X			reg = <0x9410000 0x2000>; /* ahbbus 0x410000 */
X			interrupts = <8>; /* AM_IRQ0(8) */
X			interrupt-parent = <&gic>;
X			#address-cells = <1>;
X			#size-cells = <0>;
X		};
X
X		screen: fb@8006324 {
X			device_type = "display";
X			compatible = "amlogic,aml8726-fb";
X			reg = <0x8006324 12>,   /* CANVAS */
X			      <0x1106800 1024>, /* VIU */
X			      <0x1107400 1024>; /* VPP */
X			interrupts = <2    /* AM_IRQ0(2) */
X				      3    /* AM_IRQ0(3) */
X				      12   /* AM_IRQ0(12) */
X				      13>; /* AM_IRQ0(13) */
X			interrupt-parent = <&gic>;
X			/* status = "disabled"; */
X
X			address = <0x84900000>; /* match memreserve */
X			width = <720>;
X			height = <480>;
X			depth = <24>;
X			linebytes = <2160>;
X		};
X	};
X
X	chosen {
X		stdin = "uart0";
X		stdout = "uart0";
X	};
};
SHAR_EOF
  (set 20 15 02 01 16 23 26 'sys/boot/fdt/dts/arm/vsatv102-m6.dts'
   eval "${shar_touch}") && \
  chmod 0644 'sys/boot/fdt/dts/arm/vsatv102-m6.dts'
if test $? -ne 0
then ${echo} "restore of sys/boot/fdt/dts/arm/vsatv102-m6.dts failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/boot/fdt/dts/arm/vsatv102-m6.dts': 'MD5 check failed'
       ) << \SHAR_EOF
9887238fdfa88920899b8012eddcecfe  sys/boot/fdt/dts/arm/vsatv102-m6.dts
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/boot/fdt/dts/arm/vsatv102-m6.dts'` -ne 7657 && \
  ${echo} "restoration warning:  size of 'sys/boot/fdt/dts/arm/vsatv102-m6.dts' is not 7657"
  fi
fi
# ============= sys/arm/conf/ODROIDC1 ==============
if test ! -d 'sys/arm'; then
  mkdir 'sys/arm'
if test $? -eq 0
then ${echo} "x - created directory sys/arm."
else ${echo} "x - failed to create directory sys/arm."
     exit 1
fi
fi
if test ! -d 'sys/arm/conf'; then
  mkdir 'sys/arm/conf'
if test $? -eq 0
then ${echo} "x - created directory sys/arm/conf."
else ${echo} "x - failed to create directory sys/arm/conf."
     exit 1
fi
fi
if test -n "${keep_file}" && test -f 'sys/arm/conf/ODROIDC1'
then
${echo} "x - SKIPPING sys/arm/conf/ODROIDC1 (file already exists)"

else
${echo} "x - extracting sys/arm/conf/ODROIDC1 (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/conf/ODROIDC1' &&
# ODROIDC1 -- Custom configuration for the HardKernel ODROID-C1 SBC
#
# For more information on this file, please read the handbook section on
# Kernel Configuration Files:
#
#    http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
X
ident		ODROIDC1
X
include		"../amlogic/aml8726/std.odroidc1"
X
options 	HZ=100
options 	SCHED_4BSD		# 4BSD scheduler
options 	PREEMPTION		# Enable kernel thread preemption
options 	INET			# InterNETworking
options 	INET6			# IPv6 communications protocols
options 	FFS			# Berkeley Fast Filesystem
options 	SOFTUPDATES		# Enable FFS soft updates support
options 	UFS_ACL			# Support for access control lists
options 	UFS_DIRHASH		# Improve performance on big directories
options 	PROCFS			# Process filesystem (requires PSEUDOFS)
options 	PSEUDOFS		# Pseudo-filesystem framework
options 	GEOM_PART_BSD		# BSD partition scheme
options 	GEOM_PART_MBR		# MBR partition scheme
options 	SCSI_DELAY=5000		# Delay (in ms) before probing SCSI
options 	KTRACE			# ktrace(1) support
options 	SYSVSHM			# SYSV-style shared memory
options 	SYSVMSG			# SYSV-style message queues
options 	SYSVSEM			# SYSV-style semaphores
options 	_KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
options 	PRINTF_BUFR_SIZE=128	# Prevent printf output being interspersed.
options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
options		LINUX_BOOT_ABI
options 	VFP			# vfp/neon
X
# Debugging
makeoptions	DEBUG=-g		# Build kernel with gdb(1) debug symbols
options 	ALT_BREAK_TO_DEBUGGER
#options 	VERBOSE_SYSINIT		# Enable verbose sysinit messages
options		BOOTVERBOSE=1
options 	KDB
options 	DDB			# Enable the kernel debugger
options 	INVARIANTS		# Enable calls of extra sanity checking
options 	INVARIANT_SUPPORT	# Extra sanity checks of internal structures, required by INVARIANTS
options 	WITNESS			# Enable checks to detect deadlocks and cycles
options 	WITNESS_SKIPSPIN	# Don't run witness on spinlocks for speed
#options 	DIAGNOSTIC
X
# NFS support
#options 	NFSCL			# New Network Filesystem Client
#options 	NFSLOCKD		# Network Lock Manager
#options 	NFS_ROOT		# NFS usable as /, requires NFSCL
X
# NFS root from boopt/dhcp
#options 	BOOTP
#options 	BOOTP_NFSROOT
#options 	BOOTP_COMPAT
#options 	BOOTP_NFSV3
#options 	BOOTP_WIRED_TO=axe0
X
# MMC/SD/SDIO card slot support
device		mmc			# mmc/sd bus
device		mmcsd			# mmc/sd flash cards
X
# Boot device is 2nd slice on MMC/SD card
options 	ROOTDEVNAME=\"ufs:mmcsd0s2\"
X
# GPIO
device		gpio
device		gpioled
X
# I2C support
#device		iicbb
#device		iicbus
X
# vt is the default console driver, resembling an SCO console
device		vt
#device		kbdmux
X
# Serial (COM) ports
device		uart			# Generic UART driver
X
# Pseudo devices.
device		loop			# Network loopback
device		random			# Entropy device
device		ether			# Ethernet support
device		pty			# BSD-style compatibility pseudo ttys
X
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
# Note that 'bpf' is required for DHCP.
#device		bpf			# Berkeley packet filter
X
# USB support
device		usb			# General USB code (mandatory for USB)
device		dwcotg			# DWC OTG controller
options 	USB_HOST_ALIGN=64	# Cacheline size is 64
options 	USB_DEBUG
#options 	USB_REQ_DEBUG
#options 	USB_VERBOSE
X
#device		ukbd			# USB keyboard
#device		ums			# USB mouse
X
device		scbus			# SCSI bus (required for ATA/SCSI)
device		da			# Direct Access (disks)
device		umass			# Disks/Mass storage - Requires scbus and da
X
# Ethernet support
device		miibus			# MII bus support
X
# SoC Ethernet, requires miibus
#device		dwc
X
# USB Ethernet, requires miibus
device		axe			# ASIX Electronics USB Ethernet
X
# Flattened Device Tree
options         FDT
options         FDT_DTB_STATIC
SHAR_EOF
  (set 20 15 02 01 17 26 05 'sys/arm/conf/ODROIDC1'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/conf/ODROIDC1'
if test $? -ne 0
then ${echo} "restore of sys/arm/conf/ODROIDC1 failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/conf/ODROIDC1': 'MD5 check failed'
       ) << \SHAR_EOF
ca28f6cc5a0f343ae42d2c3d5c166fd4  sys/arm/conf/ODROIDC1
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/conf/ODROIDC1'` -ne 4235 && \
  ${echo} "restoration warning:  size of 'sys/arm/conf/ODROIDC1' is not 4235"
  fi
fi
# ============= sys/arm/conf/VSATV102 ==============
if test ! -d 'sys/arm/conf'; then
  mkdir 'sys/arm/conf'
if test $? -eq 0
then ${echo} "x - created directory sys/arm/conf."
else ${echo} "x - failed to create directory sys/arm/conf."
     exit 1
fi
fi
if test -n "${keep_file}" && test -f 'sys/arm/conf/VSATV102'
then
${echo} "x - SKIPPING sys/arm/conf/VSATV102 (file already exists)"

else
${echo} "x - extracting sys/arm/conf/VSATV102 (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/conf/VSATV102' &&
# VSATV102 -- Custom configuration for the Visson ATV-102 media player
#
# For more information on this file, please read the handbook section on
# Kernel Configuration Files:
#
#    http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
X
ident		VSATV102
X
include		"../amlogic/aml8726/std.vsatv102-m6"
X
options 	HZ=100
options 	SCHED_4BSD		# 4BSD scheduler
options 	PREEMPTION		# Enable kernel thread preemption
options 	INET			# InterNETworking
options 	INET6			# IPv6 communications protocols
options 	FFS			# Berkeley Fast Filesystem
options 	SOFTUPDATES		# Enable FFS soft updates support
options 	UFS_ACL			# Support for access control lists
options 	UFS_DIRHASH		# Improve performance on big directories
options 	PROCFS			# Process filesystem (requires PSEUDOFS)
options 	PSEUDOFS		# Pseudo-filesystem framework
options 	GEOM_PART_BSD		# BSD partition scheme
options 	GEOM_PART_MBR		# MBR partition scheme
options 	SCSI_DELAY=5000		# Delay (in ms) before probing SCSI
options 	KTRACE			# ktrace(1) support
options 	SYSVSHM			# SYSV-style shared memory
options 	SYSVMSG			# SYSV-style message queues
options 	SYSVSEM			# SYSV-style semaphores
options 	_KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
options 	PRINTF_BUFR_SIZE=128	# Prevent printf output being interspersed.
options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
options		LINUX_BOOT_ABI
options 	VFP			# vfp/neon
X
# Debugging
makeoptions	DEBUG=-g		# Build kernel with gdb(1) debug symbols
options 	ALT_BREAK_TO_DEBUGGER
#options 	VERBOSE_SYSINIT		# Enable verbose sysinit messages
options		BOOTVERBOSE=1
options 	KDB
options 	DDB			# Enable the kernel debugger
options 	INVARIANTS		# Enable calls of extra sanity checking
options 	INVARIANT_SUPPORT	# Extra sanity checks of internal structures, required by INVARIANTS
options 	WITNESS			# Enable checks to detect deadlocks and cycles
options 	WITNESS_SKIPSPIN	# Don't run witness on spinlocks for speed
#options 	DIAGNOSTIC
X
# NFS support
#options 	NFSCL			# New Network Filesystem Client
#options 	NFSLOCKD		# Network Lock Manager
#options 	NFS_ROOT		# NFS usable as /, requires NFSCL
X
# NFS root from boopt/dhcp
#options 	BOOTP
#options 	BOOTP_NFSROOT
#options 	BOOTP_COMPAT
#options 	BOOTP_NFSV3
#options 	BOOTP_WIRED_TO=axe0
X
# MMC/SD/SDIO card slot support
device		mmc			# mmc/sd bus
device		mmcsd			# mmc/sd flash cards
X
# Boot device is 2nd slice on MMC/SD card
options 	ROOTDEVNAME=\"ufs:mmcsd0s2\"
X
# GPIO
device		gpio
#device		gpioled
X
# I2C support
#device		iicbb
#device		iicbus
X
# vt is the default console driver, resembling an SCO console
device		vt
#device		kbdmux
X
# Serial (COM) ports
device		uart			# Generic UART driver
X
# Pseudo devices.
device		loop			# Network loopback
device		random			# Entropy device
device		ether			# Ethernet support
device		pty			# BSD-style compatibility pseudo ttys
X
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
# Note that 'bpf' is required for DHCP.
#device		bpf			# Berkeley packet filter
X
# USB support
device		usb			# General USB code (mandatory for USB)
device		dwcotg			# DWC OTG controller
options 	USB_HOST_ALIGN=64	# Cacheline size is 64
options 	USB_DEBUG
#options 	USB_REQ_DEBUG
#options 	USB_VERBOSE
X
#device		ukbd			# USB keyboard
#device		ums			# USB mouse
X
device		scbus			# SCSI bus (required for ATA/SCSI)
device		da			# Direct Access (disks)
device		umass			# Disks/Mass storage - Requires scbus and da
X
# Ethernet support
device		miibus			# MII bus support
X
# SoC Ethernet, requires miibus
#device		dwc
X
# USB Ethernet, requires miibus
device		axe			# ASIX Electronics USB Ethernet
X
# Flattened Device Tree
options         FDT
options         FDT_DTB_STATIC
SHAR_EOF
  (set 20 15 02 01 17 25 57 'sys/arm/conf/VSATV102'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/conf/VSATV102'
if test $? -ne 0
then ${echo} "restore of sys/arm/conf/VSATV102 failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/conf/VSATV102': 'MD5 check failed'
       ) << \SHAR_EOF
179b20ad75e9892a7a6c39811b401806  sys/arm/conf/VSATV102
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/conf/VSATV102'` -ne 4242 && \
  ${echo} "restoration warning:  size of 'sys/arm/conf/VSATV102' is not 4242"
  fi
fi
# ============= sys/arm/amlogic/aml8726/README.txt ==============
if test ! -d 'sys/arm/amlogic'; then
  mkdir 'sys/arm/amlogic'
if test $? -eq 0
then ${echo} "x - created directory sys/arm/amlogic."
else ${echo} "x - failed to create directory sys/arm/amlogic."
     exit 1
fi
fi
if test ! -d 'sys/arm/amlogic/aml8726'; then
  mkdir 'sys/arm/amlogic/aml8726'
if test $? -eq 0
then ${echo} "x - created directory sys/arm/amlogic/aml8726."
else ${echo} "x - failed to create directory sys/arm/amlogic/aml8726."
     exit 1
fi
fi
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/README.txt'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/README.txt (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/README.txt (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/README.txt' &&
PatchJLW01 provides the necessary changes to the FreeBSD 11.0-CURRENT r278021
source tree which along with the additional source code accompanying this file
allows FreeBSD to be built for various Amlogic ARM based SoC devices.
X
Currently FreeBSD successfully boots to the login prompt on an aml8726-m6
board (the box seems to be some type of Visson ATV-102) as well as on an
aml8726-m8b board (a Hardkernel ODROID-C1) using a SD card and a serial
console.
X
The following support is included:
X
X  Basic machdep code
X
X  SMP
X
X  Interrupt controller
X
X  Timer
X
X  Real time clock
X
X  UART
X
X  GPIO
X
X  SD card
X
X  USB
X
X  Watchdog
X
X  Random number generator
X
X  PLL / Clock frequency measurement
X
X  Frame buffer
X
There's also drivers for the I2C and the aml8726-m3 USB PHYS hardware in my
private source tree which are currently untested ... I plan to release them
at some point once I've actually tested them.
X
The MAC appears to be the DWC ... it shows slight signs of life on the Visson
ATV-102, however fails to reset on the ODROID-C1.  Further investigation is
needed.
X
The u-boot sequence I use for the Visson ATV-102 is:
X
X  video dev open 480p
X  mmc rescan 0
X  fatload mmc 0 0x80100000 kernel.bin
X  go 0x80100000
X
The u-boot sequence I use for the Hardkernel ODROID-C1 is:
X
X  video dev open 480p
X  fatload mmc 0 0x100000 kernel.bin
X  go 0x100000
X
The current FreeBSD driver doesn't program the video clocks so the u-boot
video commands are necessary in order for the frame buffer to be useful
(otherwise they can be skipped).
X
The SD card for the Visson ATV-102 doesn't need anything special beyond
creating a FAT16 and a UFS filesystem.
X
The SD card for the ODROID-C1 also needs to contain the Hardkernel bootloader
as well as u-boot ... sd_freebsd_odroidc1.sh can be used to prep the card.
I obtained the bootloader and u-boot from the boot subdirectory of
ArchLinuxARM-odroid-c1-latest.tar.gz which is available at:
X
X  http://archlinuxarm.org/developers/downloads
X
The u-boot source code is available at:
X
X  https://github.com/hardkernel/u-boot/tree/odroidc-v2011.03/
X
which also contains a prebuilt bootloader in the sd_fuse subdirectory ...
however currently there's no prebuilt u-boot present.
X
The frame buffer driver is very rudimentary.
X
Currently the MMC driver occasionally times out ... it may simply be
due to the particular SD card I'm using or be due to a bug in the driver.
The problem seems to go away when things are power cycled.
X
The RTC currently doesn't survive a reboot and on the ODROID-C1 requires
the battery to be installed.
X
Enjoy,
X
John Wehle
john@feith.com
SHAR_EOF
  (set 20 15 02 01 17 33 01 'sys/arm/amlogic/aml8726/README.txt'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/README.txt'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/README.txt failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/README.txt': 'MD5 check failed'
       ) << \SHAR_EOF
c50bb0f5959f490c79bbf6feacea5bc0  sys/arm/amlogic/aml8726/README.txt
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/README.txt'` -ne 2581 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/README.txt' is not 2581"
  fi
fi
# ============= sys/arm/amlogic/aml8726/PatchJLW01 ==============
if test ! -d 'sys/arm/amlogic/aml8726'; then
  mkdir 'sys/arm/amlogic/aml8726'
if test $? -eq 0
then ${echo} "x - created directory sys/arm/amlogic/aml8726."
else ${echo} "x - failed to create directory sys/arm/amlogic/aml8726."
     exit 1
fi
fi
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/PatchJLW01'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/PatchJLW01 (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/PatchJLW01 (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/PatchJLW01' &&
Index: sys/sys/random.h
===================================================================
--- sys/sys/random.h	(revision 278021)
+++ sys/sys/random.h	(working copy)
@@ -65,6 +65,7 @@
X 	RANDOM_PURE_NEHEMIAH,
X 	RANDOM_PURE_RNDTEST,
X 	RANDOM_PURE_VIRTIO,
+	RANDOM_PURE_AML8726,
X 	ENTROPYSOURCE
X };
X void random_harvest(const void *, u_int, u_int, enum random_entropy_source);
Index: sys/arm/arm/gic.c
===================================================================
--- sys/arm/arm/gic.c	(revision 278021)
+++ sys/arm/arm/gic.c	(working copy)
@@ -98,6 +98,11 @@
X #define GICD_ICFGR_TRIG_EDGE	(1 << 1)
X #define GICD_ICFGR_TRIG_MASK	0x2
X 
+#ifndef GIC_DEFAULT_ICFGR_INIT
+/* Set all global interrupts to be level triggered, active low. */
+#  define GIC_DEFAULT_ICFGR_INIT 0x00000000
+#endif
+
X struct arm_gic_softc {
X 	device_t		gic_dev;
X 	struct resource *	gic_res[3];
@@ -278,9 +283,8 @@
X 			icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,
X 			(icciidr & 0xfff), sc->nirqs);
X 
-	/* Set all global interrupts to be level triggered, active low. */
X 	for (i = 32; i < sc->nirqs; i += 16) {
-		gic_d_write_4(sc, GICD_ICFGR(i >> 4), 0x00000000);
+		gic_d_write_4(sc, GICD_ICFGR(i >> 4), GIC_DEFAULT_ICFGR_INIT);
X 	}
X 
X 	/* Disable all interrupts. */
Index: sys/conf/options.arm
===================================================================
--- sys/conf/options.arm	(revision 278021)
+++ sys/conf/options.arm	(working copy)
@@ -24,6 +24,7 @@
X CPU_XSCALE_IXP435	opt_global.h
X CPU_XSCALE_PXA2X0	opt_global.h
X FLASHADDR		opt_global.h
+GIC_DEFAULT_ICFGR_INIT	opt_global.h
X IPI_IRQ_START		opt_smp.h
X IPI_IRQ_END		opt_smp.h
X FREEBSD_BOOT_LOADER	opt_global.h
Index: sys/dev/mmc/mmc.c
===================================================================
--- sys/dev/mmc/mmc.c	(revision 278021)
+++ sys/dev/mmc/mmc.c	(working copy)
@@ -1797,6 +1797,7 @@
X };
X static devclass_t mmc_devclass;
X 
+DRIVER_MODULE(mmc, aml8726_mmc, mmc_driver, mmc_devclass, NULL, NULL);
X DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
X DRIVER_MODULE(mmc, sdhci_bcm, mmc_driver, mmc_devclass, NULL, NULL);
X DRIVER_MODULE(mmc, sdhci_fdt, mmc_driver, mmc_devclass, NULL, NULL);
Index: sys/dev/random/random_harvestq.c
===================================================================
--- sys/dev/random/random_harvestq.c	(revision 278021)
+++ sys/dev/random/random_harvestq.c	(working copy)
@@ -218,6 +218,8 @@
X 	"PURE_RDRAND",
X 	"PURE_NEHEMIAH",
X 	"PURE_RNDTEST",
+	"PURE_VIRTIO",
+	"PURE_AML8726",
X 	/* "ENTROPYSOURCE" */
X };
X 
Index: sys/dev/uart/uart.h
===================================================================
--- sys/dev/uart/uart.h	(revision 278021)
+++ sys/dev/uart/uart.h	(working copy)
@@ -64,6 +64,7 @@
X  */
X struct uart_class;
X 
+extern struct uart_class uart_aml8726_class __attribute__((weak));
X extern struct uart_class uart_imx_class __attribute__((weak));
X extern struct uart_class uart_msm_class __attribute__((weak));
X extern struct uart_class uart_ns8250_class __attribute__((weak));
Index: sys/dev/uart/uart_bus_fdt.c
===================================================================
--- sys/dev/uart/uart_bus_fdt.c	(revision 278021)
+++ sys/dev/uart/uart_bus_fdt.c	(working copy)
@@ -70,6 +70,7 @@
X  * highest-numbers / most recent models should probably appear earlier.
X  */
X static struct ofw_compat_data compat_data[] = {
+	{"amlogic,aml8726-uart",(uintptr_t)&uart_aml8726_class},
X 	{"arm,pl011",		(uintptr_t)&uart_pl011_class},
X 	{"atmel,at91rm9200-usart",(uintptr_t)&at91_usart_class},
X 	{"atmel,at91sam9260-usart",(uintptr_t)&at91_usart_class},
SHAR_EOF
  (set 20 15 02 01 00 46 36 'sys/arm/amlogic/aml8726/PatchJLW01'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/PatchJLW01'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/PatchJLW01 failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/PatchJLW01': 'MD5 check failed'
       ) << \SHAR_EOF
db3e865088bb1b1226938a26e08edb75  sys/arm/amlogic/aml8726/PatchJLW01
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/PatchJLW01'` -ne 3583 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/PatchJLW01' is not 3583"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_clkmsr.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_clkmsr.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_clkmsr.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c' &&
/*-
X * Copyright 2014-2015 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timetc.h>
#include <sys/timeet.h>
X
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/fdt.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
#include <arm/amlogic/aml8726/aml8726_clkmsr.h>
X
X
static struct aml8726_clkmsr_clk {
X	const char *		name;
X	uint32_t		mux;
} aml8726_clkmsr_clks[] = {
{ "sys pll", 2 },
{ "ddr pll", 3 },
{ "misc pll", 4 },
{ "audio pll", 5 },
{ "video pll", 6 },
{ "clk81", 7 }
};
X
#define AML_CLKMSR_SYS_PLL  0
#define AML_CLKMSR_DDR_PLL  1
#define AML_CLKMSR_MISC_PLL 2
#define AML_CLKMSR_AUD_PLL  3
#define AML_CLKMSR_VID_PLL  4
#define AML_CLKMSR_CLK81    5
X
#define AML_CLKMSR_NCLKS    (sizeof(aml8726_clkmsr_clks) \
X			     / sizeof(aml8726_clkmsr_clks[0]))
X
struct aml8726_clkmsr_softc {
X	device_t		dev;
X	struct resource	*	res[1];
};
X
static struct resource_spec aml8726_clkmsr_spec[] = {
X	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
X	{ -1, 0 }
};
X
/*
X * Duration can range from 1uS to 65535 uS and should be chosen
X * based on the expected frequency result so to maximize resolution
X * and avoid overflowing the 16 bit result counter.
X */
#define AML_CLKMSR_DURATION           32
X
#define AML_CLKMSR_DUTY_REG           0
#define AML_CLKMSR_0_REG              4
#  define AML_CLKMSR_0_BUSY           (1U << 31)
#  define AML_CLKMSR_0_MUX_MASK       (0x3f << 20)
#  define AML_CLKMSR_0_MUX_SHIFT      20
#  define AML_CLKMSR_0_MUX_EN         (1 << 19)
#  define AML_CLKMSR_0_MEASURE        (1 << 16)
#  define AML_CLKMSR_0_DURATION_MASK  0xffff
#  define AML_CLKMSR_0_DURATION_SHIFT 0
#define AML_CLKMSR_1_REG              8
#define AML_CLKMSR_2_REG              12
#  define AML_CLKMSR_2_RESULT_MASK    0xffff
#  define AML_CLKMSR_2_RESULT_SHIFT   0
X
#define CSR_WRITE_4(sc, reg, val)	bus_write_4((sc)->res[0], reg, (val))
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[0], reg)
#define CSR_BARRIER(sc, reg)		bus_barrier((sc)->res[0], reg, 4, \
X					  (BUS_SPACE_BARRIER_READ         \
X					   | BUS_SPACE_BARRIER_WRITE))
X
X
static int
aml8726_clkmsr_clock_frequency(struct aml8726_clkmsr_softc *sc, unsigned clock)
{
X	uint32_t value;
X
X	if (clock >= AML_CLKMSR_NCLKS)
X		return (0);
X
X	/*
X	 * Locking is not used as this is only expected to be called from
X	 * FDT fixup (which occurs prior to driver initialization) or attach.
X	 */
X
X	CSR_WRITE_4(sc, AML_CLKMSR_0_REG, 0);
X
X	CSR_BARRIER(sc, AML_CLKMSR_0_REG);
X
X	value = (aml8726_clkmsr_clks[clock].mux << AML_CLKMSR_0_MUX_SHIFT)
X		| ((AML_CLKMSR_DURATION - 1) << AML_CLKMSR_0_DURATION_SHIFT)
X		| AML_CLKMSR_0_MUX_EN
X		| AML_CLKMSR_0_MEASURE;
X	CSR_WRITE_4(sc, AML_CLKMSR_0_REG, value);
X
X	CSR_BARRIER(sc, AML_CLKMSR_0_REG);
X
X	while ((CSR_READ_4(sc, AML_CLKMSR_0_REG) & AML_CLKMSR_0_BUSY) != 0)
X		cpu_spinwait();
X
X	value &= ~AML_CLKMSR_0_MEASURE;
X	CSR_WRITE_4(sc, AML_CLKMSR_0_REG, value);
X
X	CSR_BARRIER(sc, AML_CLKMSR_0_REG);
X
X	value = (((CSR_READ_4(sc, AML_CLKMSR_2_REG) & AML_CLKMSR_2_RESULT_MASK)
X		  >> AML_CLKMSR_2_RESULT_SHIFT) + AML_CLKMSR_DURATION / 2)
X		/ AML_CLKMSR_DURATION;
X
X	return value;
}
X
X
static int
aml8726_clkmsr_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-clkmsr"))
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic aml8726 clkmsr");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_clkmsr_attach(device_t dev)
{
X	struct aml8726_clkmsr_softc *sc = device_get_softc(dev);
X	int freq;
X
X	sc->dev = dev;
X
X	if (bus_alloc_resources(dev, aml8726_clkmsr_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	freq = aml8726_clkmsr_clock_frequency(sc, AML_CLKMSR_CLK81);
X	device_printf(sc->dev, "bus clock %u MHz\n", freq);
X
X	return (0);
}
X
X
static int
aml8726_clkmsr_detach(device_t dev)
{
X	struct aml8726_clkmsr_softc *sc = device_get_softc(dev);
X
X	bus_release_resources(dev, aml8726_clkmsr_spec, sc->res);
X
X	return (0);
}
X
X
static device_method_t aml8726_clkmsr_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe,		aml8726_clkmsr_probe),
X	DEVMETHOD(device_attach,	aml8726_clkmsr_attach),
X	DEVMETHOD(device_detach,	aml8726_clkmsr_detach),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_clkmsr_driver = {
X	"clkmsr",
X	aml8726_clkmsr_methods,
X	sizeof(struct aml8726_clkmsr_softc),
};
X
static devclass_t aml8726_clkmsr_devclass;
X
DRIVER_MODULE(clkmsr, simplebus, aml8726_clkmsr_driver, aml8726_clkmsr_devclass, 0, 0);
X
X
int
aml8726_clkmsr_bus_frequency()
{
X	phandle_t node;
X	u_long pbase, psize;
X	u_long start, size;
X	struct resource mem;
X	struct aml8726_clkmsr_softc sc;
X	int freq;
X
X	/*
X	 * Try to access the clkmsr node directly i.e. through /aliases/.
X	 */
X
X	if ((node = OF_finddevice("clkmsr")) != 0)
X		if (fdt_is_compatible_strict(node, "amlogic,aml8726-clkmsr"))
X			 goto moveon;
X
X	/*
X	 * Find the node the long way.
X	 */
X	if ((node = OF_finddevice("/soc")) == 0)
X		return (0);
X
X	if ((node = fdt_find_compatible(node,
X					"amlogic,aml8726-clkmsr", 1)) == 0)
X		return (0);
X
moveon:
X	if (fdt_get_range(OF_parent(node), 0, &pbase, &psize) != 0
X	    || fdt_regsize(node, &start, &size) != 0)
X		return (0);
X
X	start += pbase;
X
X	memset(&mem, 0, sizeof(mem));
X
X	mem.r_bustag = fdtbus_bs_tag;
X
X	if (bus_space_map(mem.r_bustag, start, size, 0, &mem.r_bushandle) != 0)
X		return (0);
X
X	/*
X	 * Build an incomplete (however sufficient for the purpose
X	 * of calling aml8726_clkmsr_clock_frequency) softc.
X	 */
X
X	memset(&sc, 0, sizeof(sc));
X
X	sc.res[0] = &mem;
X
X	freq = aml8726_clkmsr_clock_frequency(&sc, AML_CLKMSR_CLK81)
X	       * 1000000;
X
X	bus_space_unmap(mem.r_bustag, mem.r_bushandle, size);
X
X	return (freq);
}
SHAR_EOF
  (set 20 15 01 31 13 34 44 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_clkmsr.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c': 'MD5 check failed'
       ) << \SHAR_EOF
6c1e226807f9c0f86ac18c98376e5844  sys/arm/amlogic/aml8726/aml8726_clkmsr.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c'` -ne 7513 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_clkmsr.c' is not 7513"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_clkmsr.h ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_clkmsr.h (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_clkmsr.h (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h' &&
/*-
X * Copyright 2014 John Wehle <john@feith.com>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD$
X */
X
#ifndef _ARM_AMLOGIC_AML8726_CLKMSR_H
#define _ARM_AMLOGIC_AML8726_CLKMSR_H
X
X
int aml8726_clkmsr_bus_frequency(void);
X
X
#endif /* _ARM_AMLOGIC_AML8726_CLKMSR_H */
SHAR_EOF
  (set 20 14 01 10 00 35 47 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_clkmsr.h failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h': 'MD5 check failed'
       ) << \SHAR_EOF
4621fea948d68056c474ca5547bdf8bf  sys/arm/amlogic/aml8726/aml8726_clkmsr.h
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h'` -ne 1545 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_clkmsr.h' is not 1545"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_fb.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_fb.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_fb.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_fb.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_fb.c' &&
/*-
X * Copyright 2013-2014 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/resource.h>
#include <sys/rman.h>
X
#include <sys/fbio.h>
X
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/fdt.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
#include <dev/fb/fbreg.h>
#include <dev/vt/vt.h>
X
#include <arm/amlogic/aml8726/aml8726_fb.h>
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 <john@feith.com>
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 <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/resource.h>
#include <sys/rman.h>
X
#include <sys/gpio.h>
X
#include <machine/bus.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
#include <dev/gpio/gpiobusvar.h>
X
#include "gpio_if.h"
X
X
struct aml8726_gpio_softc {
X	device_t	dev;
X	struct resource *res[3];
X	struct mtx	mtx;
X	uint32_t	npins;
X	device_t	busdev;
};
X
static struct resource_spec aml8726_gpio_spec[] = {
X	{ SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE }, /* oen */
X	{ SYS_RES_MEMORY, 1, RF_ACTIVE | RF_SHAREABLE }, /* output */
X	{ SYS_RES_MEMORY, 2, RF_ACTIVE }, /* input */
X	{ -1, 0 }
};
X
#define AML_GPIO_LOCK(sc)		mtx_lock(&(sc)->mtx)
#define	AML_GPIO_UNLOCK(sc)		mtx_unlock(&(sc)->mtx)
#define AML_GPIO_LOCK_INIT(sc) \
X	mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),	\
X	    "gpio", MTX_DEF)
#define AML_GPIO_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->mtx);
X
#define AML_GPIO_OE_N_REG 0
#define AML_GPIO_OUT_REG  1
#define AML_GPIO_IN_REG   2
X
#define CSR_WRITE_4(sc, reg, val)	bus_write_4((sc)->res[reg], 0, (val))
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[reg], 0)
X
X
static int
aml8726_gpio_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-gpio"))
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic aml8726 GPIO");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_gpio_attach(device_t dev)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X	phandle_t node;
X	pcell_t prop;
X
X	sc->dev = dev;
X
X	node = ofw_bus_get_node(dev);
X
X	if (OF_getencprop(node, "pin-count",
X			  &prop, sizeof(prop)) <= 0) {
X		device_printf(dev, "missing pin-count attribute in FDT\n");
X		return (ENXIO);
X	}
X	sc->npins = prop;
X
X	if (sc->npins > 32)
X		return (ENXIO);
X
X	if (bus_alloc_resources(dev, aml8726_gpio_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	/*
X	 * The GPIOAO OUT bits occupy the upper word of the OEN register.
X	 */
X	if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0]))
X	  if (sc->npins > 16) {
X		device_printf(dev,
X			      "too many pins for overlapping OEN and OUT\n");
X		bus_release_resources(dev, aml8726_gpio_spec, sc->res);
X		return (ENXIO);
X		}
X
X	AML_GPIO_LOCK_INIT(sc);
X
X	sc->busdev = gpiobus_attach_bus(dev);
X	if (sc->busdev == NULL) {
X		AML_GPIO_LOCK_DESTROY(sc);
X		bus_release_resources(dev, aml8726_gpio_spec, sc->res);
X		return (ENXIO);
X	}
X
X	OF_device_register_xref(OF_xref_from_node(node), dev);
X
X	return (0);
}
X
X
static int
aml8726_gpio_detach(device_t dev)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X	phandle_t node;
X
X	node = ofw_bus_get_node(dev);
X	OF_device_register_xref(OF_xref_from_node(node), NULL);
X
X	gpiobus_detach_bus(dev);
X
X	AML_GPIO_LOCK_DESTROY(sc);
X
X	bus_release_resources(dev, aml8726_gpio_spec, sc->res);
X
X	return (0);
}
X
X
static device_t
aml8726_gpio_get_bus(device_t dev)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X
X	return (sc->busdev);
}
X
X
static int
aml8726_gpio_pin_max(device_t dev, int *maxpin)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X
X	*maxpin = (int)sc->npins;
X
X	return (0);
}
X
X
/* Get a specific pin's capabilities. */
static int
aml8726_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X
X	if (pin >= sc->npins)
X		return (EINVAL);
X
X	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
X
X	return (0);
}
X
X
/* Get a specific pin's name. */
static int
aml8726_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X
X	if (pin >= sc->npins)
X		return (EINVAL);
X
X	snprintf(name, GPIOMAXNAME, "%s.%u", ofw_bus_get_name(dev), pin);
X
X	return (0);
}
X
X
/* Get a specific pin's current in/out state. */
static int
aml8726_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X	uint32_t mask = 1U << pin;
X
X	if (pin >= sc->npins)
X		return (EINVAL);
X
X	if ((CSR_READ_4(sc, AML_GPIO_OE_N_REG) & mask) == 0) {
X		/* output */
X		*flags = GPIO_PIN_OUTPUT;
X	} else
X		/* input */
X		*flags = GPIO_PIN_INPUT;
X
X	return (0);
}
X
X
/* Set a specific pin's in/out state. */
static int
aml8726_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X	uint32_t mask = 1U << pin;
X
X	if (pin >= sc->npins)
X		return (EINVAL);
X
X	AML_GPIO_LOCK(sc);
X
X	if ((flags & GPIO_PIN_OUTPUT) != 0) {
X		/* Output.  Turn on driver.  */
X		CSR_WRITE_4(sc, AML_GPIO_OE_N_REG,
X			    (CSR_READ_4(sc, AML_GPIO_OE_N_REG) & ~mask));
X	} else {
X		/* Input.  Turn off driver. */
X		CSR_WRITE_4(sc, AML_GPIO_OE_N_REG,
X			    (CSR_READ_4(sc, AML_GPIO_OE_N_REG) | mask));
X	}
X		
X	AML_GPIO_UNLOCK(sc);
X
X	return (0);
}
X
X
/* Set a specific output pin's value. */
static int
aml8726_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X	uint32_t mask;
X
X	if (pin >= sc->npins || value > 1)
X		return (EINVAL);
X
X	/*
X	 * The GPIOAO OUT bits occupy the upper word of the OEN register.
X	 */
X	if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0]))
X	  pin += 16;
X
X	mask = 1U << pin;
X
X	AML_GPIO_LOCK(sc);
X
X	CSR_WRITE_4(sc, AML_GPIO_OUT_REG,
X		    ((CSR_READ_4(sc, AML_GPIO_OUT_REG) & ~mask)
X		     | (value << pin)));
X
X	AML_GPIO_UNLOCK(sc);
X
X	return (0);
}
X
X
/* Get a specific pin's input value. */
static int
aml8726_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X	uint32_t mask = 1U << pin;
X
X	if (pin >= sc->npins)
X		return (EINVAL);
X
X	*value = (CSR_READ_4(sc, AML_GPIO_IN_REG) & mask) ? 1 : 0;
X
X	return (0);
}
X
X
/* Toggle a pin's output value. */
static int
aml8726_gpio_pin_toggle(device_t dev, uint32_t pin)
{
X	struct aml8726_gpio_softc *sc = device_get_softc(dev);
X	uint32_t mask;
X
X	if (pin >= sc->npins)
X		return (EINVAL);
X
X	/*
X	 * The GPIOAO OUT bits occupy the upper word of the OEN register.
X	 */
X	if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0]))
X	  pin += 16;
X
X	mask = 1U << pin;
X
X	AML_GPIO_LOCK(sc);
X
X	CSR_WRITE_4(sc, AML_GPIO_OUT_REG,
X		    CSR_READ_4(sc, AML_GPIO_OUT_REG) ^ mask);
X
X	AML_GPIO_UNLOCK(sc);
X
X	return (0);
}
X
X
static phandle_t
aml8726_gpio_get_node(device_t bus, device_t dev)
{
X
X	/* We only have one child, the GPIO bus, which needs our own node. */
X	return (ofw_bus_get_node(bus));
}
X
X
static device_method_t aml8726_gpio_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe, 	aml8726_gpio_probe),
X	DEVMETHOD(device_attach, 	aml8726_gpio_attach),
X	DEVMETHOD(device_detach, 	aml8726_gpio_detach),
X
X	/* GPIO interface */
X	DEVMETHOD(gpio_get_bus, 	aml8726_gpio_get_bus),
X	DEVMETHOD(gpio_pin_max, 	aml8726_gpio_pin_max),
X	DEVMETHOD(gpio_pin_getname, 	aml8726_gpio_pin_getname),
X	DEVMETHOD(gpio_pin_getflags, 	aml8726_gpio_pin_getflags),
X	DEVMETHOD(gpio_pin_getcaps, 	aml8726_gpio_pin_getcaps),
X	DEVMETHOD(gpio_pin_setflags, 	aml8726_gpio_pin_setflags),
X	DEVMETHOD(gpio_pin_get, 	aml8726_gpio_pin_get),
X	DEVMETHOD(gpio_pin_set, 	aml8726_gpio_pin_set),
X	DEVMETHOD(gpio_pin_toggle, 	aml8726_gpio_pin_toggle),
X
X	/* ofw_bus interface */
X	DEVMETHOD(ofw_bus_get_node, 	aml8726_gpio_get_node),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_gpio_driver = {
X	"gpio",
X	aml8726_gpio_methods,
X	sizeof(struct aml8726_gpio_softc),
};
X
static devclass_t aml8726_gpio_devclass;
X
DRIVER_MODULE(aml8726_gpio, simplebus, aml8726_gpio_driver, aml8726_gpio_devclass, 0, 0);
SHAR_EOF
  (set 20 15 01 31 21 59 01 'sys/arm/amlogic/aml8726/aml8726_gpio.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_gpio.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_gpio.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_gpio.c': 'MD5 check failed'
       ) << \SHAR_EOF
d2e37f869f8d947a2b5ed9b9eee5a036  sys/arm/amlogic/aml8726/aml8726_gpio.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_gpio.c'` -ne 9263 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_gpio.c' is not 9263"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_identsoc.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_identsoc.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_identsoc.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_identsoc.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_identsoc.c' &&
/*-
X * Copyright 2015 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/clock.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/resource.h>
#include <sys/rman.h>
X
#include <machine/bus.h>
#include <machine/fdt.h>
X
#include <arm/amlogic/aml8726/aml8726_soc.h>
X
X
uint32_t aml8726_soc_hw_rev = 0xffffffff;
uint32_t aml8726_soc_metal_rev = 0xffffffff;
X
static const struct {
X	uint32_t hw_rev;
X	char *desc;
} aml8726_soc_desc[] = {
X	{ AML_SOC_HW_REV_M3,     "aml8726-m3" },
X	{ AML_SOC_HW_REV_M6,     "aml8726-m6" },
X	{ AML_SOC_HW_REV_M6TV,   "aml8726-m6tv" },
X	{ AML_SOC_HW_REV_M6TVL,  "aml8726-m6tvl" },
X	{ AML_SOC_HW_REV_M8,     "aml8726-m8" },
X	{ AML_SOC_HW_REV_M6TVD,  "aml8726-m6tvd" },
X	{ AML_SOC_HW_REV_M8B,    "aml8726-m8b" },
X	{ 0xff, NULL }
};
X
static const struct {
X	uint32_t metal_rev;
X	char *desc;
} aml8726_m8_soc_rev[] = {
X	{ AML_SOC_M8_METAL_REV_A,    "A" },
X	{ AML_SOC_M8_METAL_REV_M2_A, "MarkII A" },
X	{ AML_SOC_M8_METAL_REV_B,    "B" },
X	{ AML_SOC_M8_METAL_REV_C,    "C" },
X	{ 0xff, NULL }
};
X
X
static void
aml8726_identify_soc(void *dummy)
{
X	int err;
X	int i;
X	struct resource res;
X
X	memset(&res, 0, sizeof(res));
X
X	res.r_bustag = fdtbus_bs_tag;
X
X	err = bus_space_map(res.r_bustag, AML_SOC_CBUS_BASE_ADDR, 0x100000,
X			    0, &res.r_bushandle);
X
X	if (err)
X		panic("Could not allocate resource for SoC identification\n");
X
X	aml8726_soc_hw_rev = bus_read_4(&res, AML_SOC_HW_REV_REG);
X
X	aml8726_soc_metal_rev = bus_read_4(&res, AML_SOC_METAL_REV_REG);
X
X	bus_space_unmap(res.r_bustag, res.r_bushandle, 0x100000);
X
X	for (i = 0; aml8726_soc_desc[i].desc; i++)
X		if (aml8726_soc_desc[i].hw_rev == aml8726_soc_hw_rev)
X			break;
X
X	if (aml8726_soc_desc[i].desc == NULL)
X		panic("Amlogic unknown aml8726 SoC %#x\n", aml8726_soc_hw_rev);
X
X	printf("Amlogic %s SoC", aml8726_soc_desc[i].desc);
X
X	if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8) {
X		for (i = 0; aml8726_m8_soc_rev[i].desc; i++)
X			if (aml8726_m8_soc_rev[i].metal_rev
X			    == aml8726_soc_metal_rev)
X				break;
X
X		if (aml8726_m8_soc_rev[i].desc == NULL)
X			printf(", unknown rev %#x", aml8726_soc_metal_rev);
X		else
X			printf(", rev %s", aml8726_m8_soc_rev[i].desc);
X	}
X
X	printf("\n");
}
X
X
SYSINIT(aml8726_identify_soc,
X	SI_SUB_CPU, SI_ORDER_SECOND, aml8726_identify_soc, NULL);
SHAR_EOF
  (set 20 15 01 27 01 41 50 'sys/arm/amlogic/aml8726/aml8726_identsoc.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_identsoc.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_identsoc.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_identsoc.c': 'MD5 check failed'
       ) << \SHAR_EOF
05e687c4bd594c040df0019f195c3257  sys/arm/amlogic/aml8726/aml8726_identsoc.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_identsoc.c'` -ne 4240 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_identsoc.c' is not 4240"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_l2cache.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_l2cache.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_l2cache.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_l2cache.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_l2cache.c' &&
/*-
X * Copyright 2013-2015 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <sys/mutex.h>
X
#include <machine/bus.h>
#include <machine/pl310.h>
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 <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#define _ARM32_BUS_DMA_PRIVATE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
X
#include <vm/vm.h>
#include <vm/pmap.h>
X
#include <machine/bus.h>
#include <machine/devmap.h>
#include <machine/machdep.h>
#include <machine/platform.h>
X
#include <dev/fdt/fdt_common.h>
X
#include <arm/amlogic/aml8726/aml8726_clkmsr.h>
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 <john@feith.com>
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 <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/resource.h>
#include <sys/rman.h>
X
#include <sys/gpio.h>
X
#include <machine/bus.h>
#include <machine/cpu.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
#include <dev/mmc/bridge.h>
#include <dev/mmc/mmcreg.h>
#include <dev/mmc/mmcbrvar.h>
X
#include <arm/amlogic/aml8726/aml8726_mmc.h>
X
#include "gpio_if.h"
#include "mmcbr_if.h"
X
X
struct aml8726_mmc_gpio {
X	device_t	dev;
X	uint32_t	pin;
X	uint32_t	pol;
};
X
struct aml8726_mmc_softc {
X	device_t		dev;
X	struct resource		*res[2];
X	struct mtx		mtx;
X	unsigned int		ref_freq;
X	struct aml8726_mmc_gpio pwr_en;
X	bus_dma_tag_t		dmatag;
X	bus_dmamap_t		dmamap;
X	void			*ih_cookie;
X	struct mmc_host		host;
X	int			bus_busy;
X	struct mmc_command 	*cmd;
X	unsigned int		timeout_remaining;
};
X
static struct resource_spec aml8726_mmc_spec[] = {
X	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
X	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
X	{ -1, 0 }
};
X
#define AML_MMC_LOCK(sc)		mtx_lock(&(sc)->mtx)
#define	AML_MMC_UNLOCK(sc)		mtx_unlock(&(sc)->mtx)
#define AML_MMC_LOCK_INIT(sc) \
X	mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),	\
X	    "mmc", MTX_DEF)
#define AML_MMC_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->mtx);
X
#define CSR_WRITE_4(sc, reg, val)	bus_write_4((sc)->res[0], reg, (val))
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[0], reg)
#define CSR_BARRIER(sc, reg)		bus_barrier((sc)->res[0], reg, 4, \
X					  (BUS_SPACE_BARRIER_READ         \
X					   | BUS_SPACE_BARRIER_WRITE))
X
#define PWR_ON_FLAG(pol)		((pol) == 0 \
X					 ? GPIO_PIN_LOW : GPIO_PIN_HIGH)
#define PWR_OFF_FLAG(pol)		((pol) == 0 \
X					 ? GPIO_PIN_HIGH : GPIO_PIN_LOW)
X
X
static void
aml8726_mmc_mapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
X	bus_addr_t *busaddrp;
X
X	/*
X	 * There should only be one bus space address since
X	 * bus_dma_tag_create was called with nsegments = 1.
X	 */
X
X	 busaddrp = (bus_addr_t *)arg;
X	 *busaddrp = segs->ds_addr;
}
X
X
static int
aml8726_mmc_restart_timer(struct aml8726_mmc_softc *sc)
{
X	uint32_t count;
X	uint32_t isr;
X
X	if (sc->cmd == NULL || sc->timeout_remaining == 0)
X		return (0);
X
X	count = (sc->timeout_remaining > 0x1fff)
X		? 0x1fff : sc->timeout_remaining;
X	sc->timeout_remaining -= count;
X
X	isr = (count << AML_MMC_IRQ_STATUS_TIMER_CNT_SHIFT)
X	      |  AML_MMC_IRQ_STATUS_TIMER_EN
X	      |  AML_MMC_IRQ_STATUS_TIMEOUT_IRQ;
X
X	CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, isr);
X
X	return (1);
}
X
X
static int
aml8726_mmc_start_command(struct aml8726_mmc_softc *sc, struct mmc_command *cmd)
{
X	struct mmc_ios *ios = &sc->host.ios;
X	bus_addr_t baddr;
X	uint32_t block_size;
X	uint32_t bus_width;
X	uint32_t cmdr;
X	uint32_t cycles_per_usec;
X	uint32_t extr;
X	uint32_t mcfgr;
X	uint32_t nbits_per_pkg;
X	uint32_t timeout;
X	int error;
X	struct mmc_data *data;
X
X	if (cmd->opcode > 0x3f)
X		return (MMC_ERR_INVALID);
X
X	/*
X	 * Ensure the hardware state machine is in a known state,
X	 * the command done interrupt is enabled, and previous
X	 * IRQ status bits have been cleared.
X	 */
X	CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG,
X		    (AML_MMC_IRQ_CONFIG_SOFT_RESET
X		     | AML_MMC_IRQ_CONFIG_CMD_DONE_EN));
X	CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ);
X
X	/*
X	 * Start and transmission bits are per section 4.7.2 of the:
X	 *
X	 *   SD Specifications Part 1
X	 *   Physicaly Layer Simplified Specification
X	 *   Version 4.10
X	 */
X	cmdr = AML_MMC_CMD_START_BIT | AML_MMC_CMD_TRANS_BIT_HOST | cmd->opcode;
X	baddr = 0;
X	extr = 0;
X	mcfgr = CSR_READ_4(sc, AML_MMC_MULT_CONFIG_REG)
X		& AML_MMC_MULT_CONFIG_PORT_MASK;
X	timeout = AML_MMC_CMD_TIMEOUT;
X
X	if ((cmd->flags & MMC_RSP_136) != 0) {
X		cmdr |= AML_MMC_CMD_RESP_CRC7_FROM_8;
X		cmdr |= (133 << AML_MMC_CMD_RESP_BITS_SHIFT);
X	} else if ((cmd->flags & MMC_RSP_PRESENT) != 0)
X		cmdr |= (45 << AML_MMC_CMD_RESP_BITS_SHIFT);
X
X	switch (cmd->opcode) {
X	case MMC_STOP_TRANSMISSION:
X		cmdr |= AML_MMC_CMD_CHECK_DAT0_BUSY;
X		break;
X	case MMC_SEND_OP_COND:
X	case ACMD_SD_SEND_OP_COND:
X		cmdr |= AML_MMC_CMD_RESP_NO_CRC7;
X		break;
X	default:
X		break;
X	}
X
X	data = cmd->data;
X
X	if (data && data->len
X	    && (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) {
X		block_size = data->len;
X
X		if ((data->flags & MMC_DATA_MULTI) != 0) {
X			block_size = MMC_SECTOR_SIZE;
X			if ((data->len % block_size) != 0)
X				return (MMC_ERR_INVALID);
X		}
X
X		cmdr |= (((data->len / block_size) - 1)
X			<< AML_MMC_CMD_REP_PKG_CNT_SHIFT);
X
X		mcfgr |= (data->flags & MMC_DATA_STREAM)
X			 ? AML_MMC_MULT_CONFIG_STREAM_EN : 0;
X
X		/*
X		 * The number of bits per package equals the number
X		 * of data bits + the number of CRC bits.  There are
X		 * 16 bits of CRC calculate per bus line.
X		 *
X		 * A completed package appears to be detected by when
X		 * a counter decremented by the width underflows, thus
X		 * a value of zero always transfers 1 (or 4 bits depending
X		 * on the mode) which is why bus_width is subtracted.
X		 */
X		bus_width = (ios->bus_width == bus_width_4) ? 4 : 1;
X		nbits_per_pkg = block_size * 8 + 16 * bus_width - bus_width;
X		if (nbits_per_pkg > 0x3fff)
X			return (MMC_ERR_INVALID);
X
X		extr |= (nbits_per_pkg << AML_MMC_EXTENSION_PKT_SIZE_SHIFT);
X
X
X		error = bus_dmamap_load(sc->dmatag, sc->dmamap,
X					data->data, data->len,
X					aml8726_mmc_mapmem, &baddr,
X					BUS_DMA_NOWAIT);
X		if (error)
X			return (MMC_ERR_NO_MEMORY);
X
X		if ((data->flags & MMC_DATA_READ) != 0) {
X			cmdr |= AML_MMC_CMD_RESP_HAS_DATA;
X			bus_dmamap_sync(sc->dmatag, sc->dmamap,
X					BUS_DMASYNC_PREREAD);
X			timeout = AML_MMC_READ_TIMEOUT
X				       * (data->len / block_size);
X		} else {
X			cmdr |= AML_MMC_CMD_CMD_HAS_DATA;
X			bus_dmamap_sync(sc->dmatag, sc->dmamap,
X					BUS_DMASYNC_PREWRITE);
X			timeout = AML_MMC_WRITE_TIMEOUT
X				       * (data->len / block_size);
X		}
X	}
X
X	sc->cmd = cmd;
X
X	cmd->error = MMC_ERR_NONE;
X
X	/*
X	 * Round up while calculating the number of cycles which
X	 * correspond to a microsecond.  Use that to determine
X	 * the count from the desired timeout in microseconds.
X	 *
X	 * The counter has a limited range which is not sufficient
X	 * for directly implementing worst case timeouts at high clock
X	 * rates so a 32 bit counter is implemented in software.
X	 *
X	 * The documentation isn't clear on when the timer starts
X	 * so add 48 cycles for the command and 136 cycles for the
X	 * response (the values are from the previously mentioned
X	 * standard).
X	 */
X	cycles_per_usec = (ios->clock + 1000000 - 1) / 1000000;
X	sc->timeout_remaining = 48 + 136 + timeout * cycles_per_usec;
X
X	aml8726_mmc_restart_timer(sc);
X
X	CSR_WRITE_4(sc, AML_MMC_CMD_ARGUMENT_REG, cmd->arg);
X	CSR_WRITE_4(sc, AML_MMC_MULT_CONFIG_REG, mcfgr);
X	CSR_WRITE_4(sc, AML_MMC_EXTENSION_REG, extr);
X	CSR_WRITE_4(sc, AML_MMC_DMA_ADDR_REG, (uint32_t)baddr);
X	CSR_WRITE_4(sc, AML_MMC_CMD_SEND_REG, cmdr);
X
X	return (MMC_ERR_NONE);
}
X
X
static void
aml8726_mmc_intr(void *arg)
{
X	struct aml8726_mmc_softc *sc = (struct aml8726_mmc_softc *)arg;
X	uint32_t cmdr;
X	uint32_t icr;
X	uint32_t isr;
X	uint32_t mcfgr;
X	uint32_t previous_byte;
X	uint32_t resp;
X	int mmc_error;
X	int mmc_stop_error;
X	unsigned int i;
X	struct mmc_command *cmd;
X	struct mmc_command *stop_cmd;
X	struct mmc_data *data;
X
X
X	AML_MMC_LOCK(sc);
X
X	isr = CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG);
X
X	mmc_error = MMC_ERR_NONE;
X	cmdr = CSR_READ_4(sc, AML_MMC_CMD_SEND_REG);
X
X	if ((isr & AML_MMC_IRQ_STATUS_CMD_DONE_IRQ) != 0) {
X		/* Check for CRC errors if the command has completed. */
X		if ((cmdr & AML_MMC_CMD_RESP_NO_CRC7) == 0
X		    && (isr & AML_MMC_IRQ_STATUS_RESP_CRC7_OK) == 0)
X			mmc_error = MMC_ERR_BADCRC;
X		if ((cmdr & AML_MMC_CMD_RESP_HAS_DATA) != 0
X		    && (isr & AML_MMC_IRQ_STATUS_RD_CRC16_OK) == 0)
X			mmc_error = MMC_ERR_BADCRC;
X		if ((cmdr & AML_MMC_CMD_CMD_HAS_DATA) != 0
X		    && (isr & AML_MMC_IRQ_STATUS_WR_CRC16_OK) == 0)
X			mmc_error = MMC_ERR_BADCRC;
X	} else if ((isr & AML_MMC_IRQ_STATUS_TIMEOUT_IRQ) != 0) {
X		if (aml8726_mmc_restart_timer(sc) != 0) {
X			AML_MMC_UNLOCK(sc);
X			return;
X		}
X		mmc_error = MMC_ERR_TIMEOUT;
X	} else {
X
X		/*
X		 * Clear spurious interrupts while leaving intacted any
X		 * interrupts that may have occurred after we read the
X		 * interrupt status register.
X		 */
X
X		CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG,
X			    (AML_MMC_IRQ_STATUS_CLEAR_IRQ & isr));
X		AML_MMC_UNLOCK(sc);
X		return;
X	}
X
X	if ((isr & AML_MMC_IRQ_STATUS_CMD_BUSY) != 0) {
X		if (mmc_error != MMC_ERR_TIMEOUT)
X			mmc_error = MMC_ERR_FAILED;
X
X		/*
X		 * Issue a soft reset (while leaving the command complete
X		 * interrupt enabled) to terminate the command.
X		 *
X		 * Ensure the command has terminated before continuing on
X		 * to things such as bus_dmamap_sync / bus_dmamap_unload.
X		 */
X
X		icr = AML_MMC_IRQ_CONFIG_SOFT_RESET
X		      | AML_MMC_IRQ_CONFIG_CMD_DONE_EN;
X
X		CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, icr);
X
X		while ((CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG)
X			& AML_MMC_IRQ_STATUS_CMD_BUSY) != 0)
X			cpu_spinwait();
X	}
X
X	/* Clear all interrupts since the request is no longer in flight. */
X	CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ);
X
X	CSR_BARRIER(sc, AML_MMC_IRQ_STATUS_REG);
X
X	cmd = sc->cmd;
X	sc->cmd = NULL;
X
X	if (cmd == NULL) {
X		AML_MMC_UNLOCK(sc);
X		return;
X	}
X
X	cmd->error = mmc_error;
X
X	if ((cmd->flags & MMC_RSP_PRESENT) != 0
X	    && mmc_error == MMC_ERR_NONE) {
X		mcfgr = CSR_READ_4(sc, AML_MMC_MULT_CONFIG_REG)
X			& AML_MMC_MULT_CONFIG_PORT_MASK;
X		mcfgr |= AML_MMC_MULT_CONFIG_RESP_READOUT_EN;
X		CSR_WRITE_4(sc, AML_MMC_MULT_CONFIG_REG, mcfgr);
X
X		if ((cmd->flags & MMC_RSP_136) != 0) {
X
X			/*
X			 * Controller supplies 135:8 instead of
X			 * 127:0 so discard the leading 8 bits
X			 * and provide a trailing 8 zero bits
X			 * where the CRC belongs.
X			 */
X
X			previous_byte = 0;
X
X			for (i = 0; i < 4; i++) {
X				resp = CSR_READ_4(sc, AML_MMC_CMD_ARGUMENT_REG);
X				cmd->resp[3 - i] = (resp << 8) | previous_byte;
X				previous_byte = (resp >> 24) & 0xff;
X			}
X		} else
X			cmd->resp[0] = CSR_READ_4(sc, AML_MMC_CMD_ARGUMENT_REG);
X	}
X
X	data = cmd->data;
X
X	if (data && data->len
X	    && (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) {
X		if ((data->flags & MMC_DATA_READ) != 0)
X			bus_dmamap_sync(sc->dmatag, sc->dmamap,
X					BUS_DMASYNC_POSTREAD);
X		else
X			bus_dmamap_sync(sc->dmatag, sc->dmamap,
X					BUS_DMASYNC_POSTWRITE);
X		bus_dmamap_unload(sc->dmatag, sc->dmamap);
X	}
X
X	/*
X	 * If this command was successfully executed and there's
X	 * a linked stop command, then start the stop command.
X	 */
X
X	stop_cmd = (cmd->mrq->stop != cmd) ? cmd->mrq->stop : NULL;
X
X	if (stop_cmd != NULL && mmc_error == MMC_ERR_NONE) {
X		mmc_stop_error = aml8726_mmc_start_command(sc, stop_cmd);
X		if (mmc_stop_error == MMC_ERR_NONE) {
X			AML_MMC_UNLOCK(sc);
X			return;
X		}
X		stop_cmd->error = mmc_stop_error;
X	}
X
X	AML_MMC_UNLOCK(sc);
X
X	/* Execute the callback after dropping the lock. */
X	if (cmd->mrq) {
X		cmd->mrq->done(cmd->mrq);
X	}
}
X
X
static int
aml8726_mmc_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-mmc"))
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic aml8726 MMC");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_mmc_attach(device_t dev)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(dev);
X	pcell_t prop[3];
X	phandle_t node;
X	ssize_t len;
X	int error;
X	device_t child;
X
X	sc->dev = dev;
X
X	node = ofw_bus_get_node(dev);
X
X	len = OF_getencprop(OF_parent(node), "bus-frequency",
X			    prop, sizeof(prop));
X	if ((len / sizeof(prop[0])) != 1 || prop[0] == 0) {
X		device_printf(dev, "missing bus-frequency attribute in FDT\n");
X		return (ENXIO);
X	}
X
X	sc->ref_freq = prop[0];
X
X	len = OF_getencprop(node, "mmc-pwr-en", prop, sizeof(prop));
X	if ((len / sizeof(prop[0])) != 3
X	    || (sc->pwr_en.dev = OF_device_from_xref(prop[0])) == NULL) {
X		device_printf(dev, "missing mmc-pwr-en attribute in FDT\n");
X		return (ENXIO);
X	}
X
X	sc->pwr_en.pin = prop[1];
X	sc->pwr_en.pol = prop[2];
X
X	if (bus_alloc_resources(dev, aml8726_mmc_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	/* Turn off power by setting pin and then configuring output driver. */
X	if (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin,
X			 PWR_OFF_FLAG(sc->pwr_en.pol)) != 0
X	    || GPIO_PIN_SETFLAGS(sc->pwr_en.dev, sc->pwr_en.pin,
X				 GPIO_PIN_OUTPUT) != 0) {
X		device_printf(dev, "could not use gpio to control power\n");
X		bus_release_resources(dev, aml8726_mmc_spec, sc->res);
X		return (ENXIO);
X	}
X
X	AML_MMC_LOCK_INIT(sc);
X
X	error = bus_dma_tag_create(bus_get_dma_tag(dev), AML_MMC_ALIGN_DMA, 0,
X				   BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
X				   NULL, NULL, AML_MMC_MAX_DMA, 1,
X				   AML_MMC_MAX_DMA, 0, NULL, NULL, &sc->dmatag);
X	if (error)
X		goto fail;
X
X	error = bus_dmamap_create(sc->dmatag, 0, &sc->dmamap);
X
X	if (error)
X		goto fail;
X
X	error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
X			       NULL, aml8726_mmc_intr, sc, &sc->ih_cookie);
X	if (error) {
X		device_printf(dev, "could not setup interrupt handler\n");
X		goto fail;
X	}
X
X	sc->host.f_min = 200000;
X	sc->host.f_max = 50000000;
X	sc->host.host_ocr = MMC_OCR_330_340;
X	sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_HSPEED;
X
X	child = device_add_child(dev, "mmc", device_get_unit(dev));
X
X	if (!child) {
X		device_printf(dev, "could not add mmc\n");
X		error = ENXIO;
X		goto fail;
X	}
X
X	error = device_probe_and_attach(child);
X
X	if (error) {
X		device_printf(dev, "could not attach mmc\n");
X		goto fail;
X	}
X
X	return (0);
X
fail:
X	if (sc->ih_cookie)
X		bus_teardown_intr(dev, sc->res[1], sc->ih_cookie);
X
X	if (sc->dmamap)
X		bus_dmamap_destroy(sc->dmatag, sc->dmamap);
X
X	if (sc->dmatag)
X		bus_dma_tag_destroy(sc->dmatag);
X
X	AML_MMC_LOCK_DESTROY(sc);
X
X	(void)GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin,
X			   PWR_OFF_FLAG(sc->pwr_en.pol));
X
X	bus_release_resources(dev, aml8726_mmc_spec, sc->res);
X
X	return (error);
}
X
X
static int
aml8726_mmc_detach(device_t dev)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(dev);
X
X	AML_MMC_LOCK(sc);
X
X	if (sc->cmd != NULL) {
X		AML_MMC_UNLOCK(sc);
X		return (EBUSY);
X	}
X
X	/*
X	 * Turn off the power, reset the hardware state machine,
X	 * disable the interrupts, and clear the interrupts.
X	 */
X	(void)GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin,
X			   PWR_OFF_FLAG(sc->pwr_en.pol));
X	CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, AML_MMC_IRQ_CONFIG_SOFT_RESET);
X	CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ);
X
X	AML_MMC_UNLOCK(sc);
X
X	bus_generic_detach(dev);
X
X	bus_teardown_intr(dev, sc->res[1], sc->ih_cookie);
X
X	bus_dmamap_destroy(sc->dmatag, sc->dmamap);
X
X	bus_dma_tag_destroy(sc->dmatag);
X
X	AML_MMC_LOCK_DESTROY(sc);
X
X	bus_release_resources(dev, aml8726_mmc_spec, sc->res);
X
X	return (0);
}
X
X
static int
aml8726_mmc_shutdown(device_t dev)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(dev);
X
X	/*
X	 * Turn off the power, reset the hardware state machine,
X	 * disable the interrupts, and clear the interrupts.
X	 */
X	(void)GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin,
X			   PWR_OFF_FLAG(sc->pwr_en.pol));
X	CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, AML_MMC_IRQ_CONFIG_SOFT_RESET);
X	CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ);
X
X	return (0);
}
X
X
static int
aml8726_mmc_update_ios(device_t bus, device_t child)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(bus);
X	struct mmc_ios *ios = &sc->host.ios;
X	int divisor;
X	int error;
X	uint32_t cfgr;
X
X	cfgr = (2 << AML_MMC_CONFIG_WR_CRC_STAT_SHIFT)
X	       | (2 << AML_MMC_CONFIG_WR_DELAY_SHIFT)
X	       | AML_MMC_CONFIG_DMA_ENDIAN_SBW
X	       | (39 << AML_MMC_CONFIG_CMD_ARG_BITS_SHIFT);
X
X	switch (ios->bus_width) {
X	case bus_width_4:
X		cfgr |= AML_MMC_CONFIG_BUS_WIDTH_4;
X		break;
X	case bus_width_1:
X		cfgr |= AML_MMC_CONFIG_BUS_WIDTH_1;
X		break;
X	default:
X		return (EINVAL);
X	}
X
X	divisor = sc->ref_freq  / (ios->clock * 2) - 1;
X	if (divisor == 0 || divisor == -1)
X		divisor = 1;
X	if ((sc->ref_freq / ((divisor + 1) * 2)) > ios->clock)
X		divisor += 1;
X	if (divisor > 0x3ff)
X		divisor = 0x3ff;
X
X	cfgr |= divisor;
X
X	CSR_WRITE_4(sc, AML_MMC_CONFIG_REG, cfgr);
X
X	error = 0;
X
X	switch (ios->power_mode) {
X	case power_up:
X		/*
X		 * This is a NOP since there's no separate regulator to
X		 * configure and power on in advance so that the voltage
X		 * stabilizes prior to powering on the card.
X		 */
X		 break;
X	case power_on:
X		error = GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin,
X				     PWR_ON_FLAG(sc->pwr_en.pol));
X		break;
X	case power_off:
X		error = GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin,
X				     PWR_OFF_FLAG(sc->pwr_en.pol));
X		break;
X	default:
X		return (EINVAL);
X	}
X
X	return (error);
}
X
X
static int
aml8726_mmc_request(device_t bus, device_t child, struct mmc_request *req)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(bus);
X	int mmc_error;
X
X	AML_MMC_LOCK(sc);
X
X	if (sc->cmd != NULL) {
X		AML_MMC_UNLOCK(sc);
X		return (EBUSY);
X	}
X
X	mmc_error = aml8726_mmc_start_command(sc, req->cmd);
X
X	AML_MMC_UNLOCK(sc);
X
X	/* Execute the callback after dropping the lock. */
X	if (mmc_error != MMC_ERR_NONE) {
X		req->cmd->error = mmc_error;
X		req->done(req);
X	}
X
X	return (0);
}
X
X
static int
aml8726_mmc_read_ivar(device_t bus, device_t child,
X	int which, uintptr_t *result)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(bus);
X
X	switch (which) {
X	case MMCBR_IVAR_BUS_MODE:
X		*(int *)result = sc->host.ios.bus_mode;
X		break;
X	case MMCBR_IVAR_BUS_WIDTH:
X		*(int *)result = sc->host.ios.bus_width;
X		break;
X	case MMCBR_IVAR_CHIP_SELECT:
X		*(int *)result = sc->host.ios.chip_select;
X		break;
X	case MMCBR_IVAR_CLOCK:
X		*(int *)result = sc->host.ios.clock;
X		break;
X	case MMCBR_IVAR_F_MIN:
X		*(int *)result = sc->host.f_min;
X		break;
X	case MMCBR_IVAR_F_MAX:
X		*(int *)result = sc->host.f_max;
X		break;
X	case MMCBR_IVAR_HOST_OCR:
X		*(int *)result = sc->host.host_ocr;
X		break;
X	case MMCBR_IVAR_MODE:
X		*(int *)result = sc->host.mode;
X		break;
X	case MMCBR_IVAR_OCR:
X		*(int *)result = sc->host.ocr;
X		break;
X	case MMCBR_IVAR_POWER_MODE:
X		*(int *)result = sc->host.ios.power_mode;
X		break;
X	case MMCBR_IVAR_VDD:
X		*(int *)result = sc->host.ios.vdd;
X		break;
X	case MMCBR_IVAR_CAPS:
X		*(int *)result = sc->host.caps;
X		break;
X	case MMCBR_IVAR_MAX_DATA:
X		*(int *)result = AML_MMC_MAX_DMA / MMC_SECTOR_SIZE;
X		break;
X	default:
X		return (EINVAL);
X	}
X
X	return (0);
}
X
X
static int
aml8726_mmc_write_ivar(device_t bus, device_t child,
X	int which, uintptr_t value)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(bus);
X
X	switch (which) {
X	case MMCBR_IVAR_BUS_MODE:
X		sc->host.ios.bus_mode = value;
X		break;
X	case MMCBR_IVAR_BUS_WIDTH:
X		sc->host.ios.bus_width = value;
X		break;
X	case MMCBR_IVAR_CHIP_SELECT:
X		sc->host.ios.chip_select = value;
X		break;
X	case MMCBR_IVAR_CLOCK:
X		sc->host.ios.clock = value;
X		break;
X	case MMCBR_IVAR_MODE:
X		sc->host.mode = value;
X		break;
X	case MMCBR_IVAR_OCR:
X		sc->host.ocr = value;
X		break;
X	case MMCBR_IVAR_POWER_MODE:
X		sc->host.ios.power_mode = value;
X		break;
X	case MMCBR_IVAR_VDD:
X		sc->host.ios.vdd = value;
X		break;
X	/* These are read-only */
X	case MMCBR_IVAR_CAPS:
X	case MMCBR_IVAR_HOST_OCR:
X	case MMCBR_IVAR_F_MIN:
X	case MMCBR_IVAR_F_MAX:
X	case MMCBR_IVAR_MAX_DATA:
X	default:
X		return (EINVAL);
X	}
X
X	return (0);
}
X
X
static int
aml8726_mmc_get_ro(device_t bus, device_t child)
{
X
X	return (0);
}
X
X
static int
aml8726_mmc_acquire_host(device_t bus, device_t child)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(bus);
X
X	AML_MMC_LOCK(sc);
X
X	while (sc->bus_busy)
X		mtx_sleep(sc, &sc->mtx, PZERO, "mmc", hz / 5);
X	sc->bus_busy++;
X
X	AML_MMC_UNLOCK(sc);
X
X	return (0);
}
X
X
static int
aml8726_mmc_release_host(device_t bus, device_t child)
{
X	struct aml8726_mmc_softc *sc = device_get_softc(bus);
X
X	AML_MMC_LOCK(sc);
X
X	sc->bus_busy--;
X	wakeup(sc);
X
X	AML_MMC_UNLOCK(sc);
X
X	return (0);
}
X
X
static device_method_t aml8726_mmc_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe, 	aml8726_mmc_probe),
X	DEVMETHOD(device_attach, 	aml8726_mmc_attach),
X	DEVMETHOD(device_detach, 	aml8726_mmc_detach),
X	DEVMETHOD(device_shutdown, 	aml8726_mmc_shutdown),
X
X	/* Bus interface */
X	DEVMETHOD(bus_read_ivar,	aml8726_mmc_read_ivar),
X	DEVMETHOD(bus_write_ivar,	aml8726_mmc_write_ivar),
X
X	/* MMC bridge interface */
X	DEVMETHOD(mmcbr_update_ios, 	aml8726_mmc_update_ios),
X	DEVMETHOD(mmcbr_request, 	aml8726_mmc_request),
X	DEVMETHOD(mmcbr_get_ro, 	aml8726_mmc_get_ro),
X	DEVMETHOD(mmcbr_acquire_host, 	aml8726_mmc_acquire_host),
X	DEVMETHOD(mmcbr_release_host, 	aml8726_mmc_release_host),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_mmc_driver = {
X	"aml8726_mmc",
X	aml8726_mmc_methods,
X	sizeof(struct aml8726_mmc_softc),
};
X
static devclass_t aml8726_mmc_devclass;
X
DRIVER_MODULE(aml8726_mmc, simplebus, aml8726_mmc_driver, aml8726_mmc_devclass, 0, 0);
MODULE_DEPEND(aml8726_mmc, aml8726_gpio, 1, 1, 1);
SHAR_EOF
  (set 20 15 01 07 00 57 31 'sys/arm/amlogic/aml8726/aml8726_mmc.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_mmc.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_mmc.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_mmc.c': 'MD5 check failed'
       ) << \SHAR_EOF
5d7161e26539fe1c846e395ab29f81fc  sys/arm/amlogic/aml8726/aml8726_mmc.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mmc.c'` -ne 22210 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_mmc.c' is not 22210"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_mmc.h ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_mmc.h'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_mmc.h (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_mmc.h (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_mmc.h' &&
/*-
X * Copyright 2013-2014 John Wehle <john@feith.com>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD$
X */
X
#ifndef _ARM_AMLOGIC_AML8726_MMC_H
#define _ARM_AMLOGIC_AML8726_MMC_H
X
X
#define AML_MMC_ALIGN_DMA                    4
#define AML_MMC_MAX_DMA                      4096
X
/*
X * Timeouts are in microseconds
X *
X * Read and write are per section 4.6.2 of the:
X *
X *   SD Specifications Part 1
X *   Physicaly Layer Simplified Specification
X *   Version 4.10
X */
#define AML_MMC_CMD_TIMEOUT                  50000
#define AML_MMC_READ_TIMEOUT                 100000
#define AML_MMC_WRITE_TIMEOUT                500000
X
/*
X * Internally the timeout is implemented by counting clock cycles.
X *
X * Since the hardware implements timeouts by counting cycles
X * the minimum read / write timeout (assuming the minimum
X * conversion factor of 1 cycle per usec) is:
X *
X *   (8 bits * 512 bytes per block + 16 bits CRC) = 4112 usec
X */
#if (AML_MMC_READ_TIMEOUT < 4112 || AML_MMC_WRITE_TIMEOUT < 4112)
#  error "Single block timeout is smaller than supported"
#endif
X
/*
X * Ensure that the worst case timeout can be handled by a 32 bit
X * counter assuming a maximum MMC clock of 50 MHz.
X */
#if (AML_MMC_MAX_DMA / 512ULL * AML_MMC_READ_TIMEOUT * 50) > 0xffffffffULL \
X    || (AML_MMC_MAX_DMA / 512ULL * AML_MMC_WRITE_TIMEOUT * 50) > 0xffffffffULL
#  error "Multiblock timeout is larger than supported"
#endif
X
#define	AML_MMC_CMD_ARGUMENT_REG               0
X
#define AML_MMC_CMD_SEND_REG                   4
#  define AML_MMC_CMD_REP_PKG_CNT_MASK         (0xffU << 24)
#  define AML_MMC_CMD_REP_PKG_CNT_SHIFT        24
#  define AML_MMC_CMD_CMD_HAS_DATA             (1 << 20)
#  define AML_MMC_CMD_CHECK_DAT0_BUSY          (1 << 19)
#  define AML_MMC_CMD_RESP_CRC7_FROM_8         (1 << 18)
#  define AML_MMC_CMD_RESP_HAS_DATA            (1 << 17)
#  define AML_MMC_CMD_RESP_NO_CRC7             (1 << 16)
#  define AML_MMC_CMD_RESP_BITS_MASK           (0xff << 8)
#  define AML_MMC_CMD_RESP_BITS_SHIFT          8
#  define AML_MMC_CMD_START_BIT                (0 << 7)
#  define AML_MMC_CMD_TRANS_BIT_HOST           (1 << 6)
#  define AML_MMC_CMD_INDEX_MASK               0x3f
#  define AML_MMC_CMD_INDEX_SHIFT              0
X
#define AML_MMC_CONFIG_REG                     8
#  define AML_MMC_CONFIG_WR_CRC_STAT_MASK      (7U << 29)
#  define AML_MMC_CONFIG_WR_CRC_STAT_SHIFT     29
#  define AML_MMC_CONFIG_WR_DELAY_MASK         (0x3f << 23)
#  define AML_MMC_CONFIG_WR_DELAY_SHIFT        23
#  define AML_MMC_CONFIG_DMA_ENDIAN_MASK       (3 << 21)
#  define AML_MMC_CONFIG_DMA_ENDIAN_NC         (0 << 21)
#  define AML_MMC_CONFIG_DMA_ENDIAN_SB         (1 << 21)
#  define AML_MMC_CONFIG_DMA_ENDIAN_SW         (2 << 21)
#  define AML_MMC_CONFIG_DMA_ENDIAN_SBW        (3 << 21)
#  define AML_MMC_CONFIG_BUS_WIDTH_MASK        (1 << 20)
#  define AML_MMC_CONFIG_BUS_WIDTH_1           (0 << 20)
#  define AML_MMC_CONFIG_BUS_WIDTH_4           (1 << 20)
#  define AML_MMC_CONFIG_DATA_NEG_EDGE         (1 << 19)
#  define AML_MMC_CONFIG_DONT_DELAY_DATA       (1 << 18)
#  define AML_MMC_CONFIG_CMD_ARG_BITS_MASK     (0x3f << 12)
#  define AML_MMC_CONFIG_CMD_ARG_BITS_SHIFT    12
#  define AML_MMC_CONFIG_CMD_POS_EDGE          (1 << 11)
#  define AML_MMC_CONFIG_CMD_NO_CRC            (1 << 10)
#  define AML_MMC_CONFIG_CMD_CLK_DIV_MASK      0x3ff
#  define AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT     0
X
#define AML_MMC_IRQ_STATUS_REG                 12
#  define AML_MMC_IRQ_STATUS_TIMER_CNT_MASK    (0x1fffU << 19)
#  define AML_MMC_IRQ_STATUS_TIMER_CNT_SHIFT   19
#  define AML_MMC_IRQ_STATUS_TIMER_EN          (1 << 18)
#  define AML_MMC_IRQ_STATUS_TIMEOUT_IRQ       (1 << 16)
#  define AML_MMC_IRQ_STATUS_CMD_DONE_IRQ      (1 << 9)
#  define AML_MMC_IRQ_STATUS_WR_CRC16_OK       (1 << 7)
#  define AML_MMC_IRQ_STATUS_RD_CRC16_OK       (1 << 6)
#  define AML_MMC_IRQ_STATUS_RESP_CRC7_OK      (1 << 5)
#  define AML_MMC_IRQ_STATUS_CMD_BUSY          (1 << 4)
#  define AML_MMC_IRQ_STATUS_CLEAR_IRQ         0x10700
X
#define AML_MMC_IRQ_CONFIG_REG                 16
#  define AML_MMC_IRQ_CONFIG_SOFT_RESET        (1 << 15)
#  define AML_MMC_IRQ_CONFIG_CMD_DONE_EN       (1 << 4)
X
#define AML_MMC_MULT_CONFIG_REG                20
#  define AML_MMC_MULT_CONFIG_RESP_INDEX_MASK  (0xf << 12)
#  define AML_MMC_MULT_CONFIG_RESP_INDEX_SHIFT 12
#  define AML_MMC_MULT_CONFIG_RESP_READOUT_EN  (1 << 8)
#  define AML_MMC_MULT_CONFIG_STREAM_8_MODE    (1 << 5)
#  define AML_MMC_MULT_CONFIG_STREAM_EN        (1 << 4)
#  define AML_MMC_MULT_CONFIG_PORT_MASK        3
#  define AML_MMC_MULT_CONFIG_PORT_A           0
#  define AML_MMC_MULT_CONFIG_PORT_B           1
X
#define AML_MMC_DMA_ADDR_REG                   24
X
#define AML_MMC_EXTENSION_REG                  28
#  define AML_MMC_EXTENSION_NO_CRC16           (1 << 30)
#  define AML_MMC_EXTENSION_PKT_SIZE_MASK      (0x3fff << 16)
#  define AML_MMC_EXTENSION_PKT_SIZE_SHIFT     16
X
X
#endif /* _ARM_AMLOGIC_AML8726_MMC_H */
SHAR_EOF
  (set 20 15 01 27 00 25 00 'sys/arm/amlogic/aml8726/aml8726_mmc.h'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_mmc.h'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_mmc.h failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_mmc.h': 'MD5 check failed'
       ) << \SHAR_EOF
ed9e2b07284232ac4d3a8d47b0fb0b89  sys/arm/amlogic/aml8726/aml8726_mmc.h
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mmc.h'` -ne 6226 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_mmc.h' is not 6226"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_mp.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_mp.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_mp.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_mp.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_mp.c' &&
/*-
X * Copyright 2015 John Wehle <john@feith.com>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
/*
X * Amlogic aml8726 multiprocessor support.
X *
X * Some processors require powering on which involves poking registers on
X * the aobus and cbus ... it's expected that the location of the aobus and
X * cbus is set in stone.
X *
X * Locking is not used as these routines should only be called by the BP
X * during startup and should complete prior to the APs being released (the
X * issue being to ensure that a register such as AML_SOC_CPU_CLK_CNTL_REG
X * is not concurrently modified).
X */
X
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/resource.h>
#include <sys/rman.h>
#include <sys/smp.h>
X
#include <machine/bus.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
#include <arm/amlogic/aml8726/aml8726_soc.h>
X
X
static const char *scu_compatible[] = {
X	"arm,cortex-a5-scu",
X	"arm,cortex-a9-scu",
X	NULL
};
X
static const char *scu_errata_764369[] = {
X	"arm,cortex-a9-scu",
X	NULL
};
X
static const char *cpucfg_compatible[] = {
X	"amlogic,aml8726-cpuconfig",
X	NULL
};
X
static struct {
X	boolean_t errata_764369;
X	u_long scu_size;
X	struct resource scu_res;
X	u_long cpucfg_size;
X	struct resource cpucfg_res;
X	struct resource aobus_res;
X	struct resource cbus_res;
} aml8726_smp;
X
#define AML_SCU_CONTROL_REG                     0
#  define AML_SCU_CONTROL_ENABLE                1
#define AML_SCU_CONFIG_REG                      4
#  define AML_SCU_CONFIG_NCPU_MASK              0x3
#define AML_SCU_CPU_PWR_STATUS_REG              8
#  define AML_SCU_CPU_PWR_STATUS_CPU3_MASK      (3 << 24)
#  define AML_SCU_CPU_PWR_STATUS_CPU2_MASK      (3 << 16)
#  define AML_SCU_CPU_PWR_STATUS_CPU1_MASK      (3 << 8)
#  define AML_SCU_CPU_PWR_STATUS_CPU0_MASK      3
#define AML_SCU_INV_TAGS_REG                    12
#define AML_SCU_DIAG_CONTROL_REG                48
#  define AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT   1
X
#define AML_CPUCONF_CONTROL_REG                 0
#define AML_CPUCONF_CPU1_ADDR_REG               4
#define AML_CPUCONF_CPU2_ADDR_REG               8
#define AML_CPUCONF_CPU3_ADDR_REG               12
X
/* aobus */
X
#define AML_M8_CPU_PWR_CNTL0_REG                0xe0
#  define AML_M8B_CPU_PWR_CNTL0_MODE_CPU3_MASK  (3 << 22)
#  define AML_M8B_CPU_PWR_CNTL0_MODE_CPU2_MASK  (3 << 20)
#  define AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK  (3 << 18)
X
#  define AML_M8_CPU_PWR_CNTL0_ISO_CPU3         (1 << 3)
#  define AML_M8_CPU_PWR_CNTL0_ISO_CPU2         (1 << 2)
#  define AML_M8_CPU_PWR_CNTL0_ISO_CPU1         (1 << 1)
X
#define AML_M8_CPU_PWR_CNTL1_REG                0xe4
#  define AML_M8B_CPU_PWR_CNTL1_PWR_CPU3        (1 << 19)
#  define AML_M8B_CPU_PWR_CNTL1_PWR_CPU2        (1 << 18)
#  define AML_M8B_CPU_PWR_CNTL1_PWR_CPU1        (1 << 17)
X
#  define AML_M8_CPU_PWR_CNTL1_MODE_CPU3_MASK   (3 << 8)
#  define AML_M8_CPU_PWR_CNTL1_MODE_CPU2_MASK   (3 << 6)
#  define AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK   (3 << 4)
X
#define AML_M8B_CPU_PWR_MEM_PD0_REG             0xf4
#  define AML_M8B_CPU_PWR_MEM_PD0_CPU3          (0xf << 20)
#  define AML_M8B_CPU_PWR_MEM_PD0_CPU2          (0xf << 24)
#  define AML_M8B_CPU_PWR_MEM_PD0_CPU1          (0xf << 28)
X
/* cbus */
X
#define AML_SOC_CPU_CLK_CNTL_REG                0x419c
#  define AML_M8_CPU_CLK_CNTL_RESET_CPU3        (1 << 27)
#  define AML_M8_CPU_CLK_CNTL_RESET_CPU2        (1 << 26)
#  define AML_M8_CPU_CLK_CNTL_RESET_CPU1        (1 << 25)
X
#define SCU_WRITE_4(reg, value)		bus_write_4(&aml8726_smp.scu_res,     \
X						    (reg), (value))
#define SCU_READ_4(reg)			bus_read_4(&aml8726_smp.scu_res, (reg))
#define SCU_BARRIER(reg)		bus_barrier(&aml8726_smp.scu_res,     \
X					  (reg), 4,                           \
X					  (BUS_SPACE_BARRIER_READ             \
X					   | BUS_SPACE_BARRIER_WRITE))
X
#define CPUCONF_WRITE_4(reg, value)	bus_write_4(&aml8726_smp.cpucfg_res,  \
X						    (reg), (value))
#define CPUCONF_READ_4(reg)		bus_read_4(&aml8726_smp.cpucfg_res,   \
X						   (reg))
#define CPUCONF_BARRIER(reg)		bus_barrier(&aml8726_smp.cpucfg_res,  \
X					  (reg), 4,                           \
X					  (BUS_SPACE_BARRIER_READ             \
X					   | BUS_SPACE_BARRIER_WRITE))
X
#define AOBUS_WRITE_4(reg, value)	bus_write_4(&aml8726_smp.aobus_res,   \
X						    (reg), (value))
#define AOBUS_READ_4(reg)		bus_read_4(&aml8726_smp.aobus_res,    \
X						   (reg))
#define AOBUS_BARRIER(reg)		bus_barrier(&aml8726_smp.aobus_res,   \
X					  (reg), 4,                           \
X					  (BUS_SPACE_BARRIER_READ             \
X					   | BUS_SPACE_BARRIER_WRITE))
X
#define CBUS_WRITE_4(reg, value)	bus_write_4(&aml8726_smp.cbus_res,    \
X						    (reg), (value))
#define CBUS_READ_4(reg)		bus_read_4(&aml8726_smp.cbus_res,     \
X						   (reg))
#define CBUS_BARRIER(reg)		bus_barrier(&aml8726_smp.cbus_res,    \
X					  (reg), 4,                           \
X					  (BUS_SPACE_BARRIER_READ             \
X					   | BUS_SPACE_BARRIER_WRITE))
X
X
static phandle_t
find_node_for_device(const char *device, const char **compatible)
{
X	int i;
X	phandle_t node;
X
X	/*
X	 * Try to access the node directly i.e. through /aliases/.
X	 */
X
X	if ((node = OF_finddevice(device)) != 0)
X		for (i = 0; compatible[i]; i++)
X			if (fdt_is_compatible_strict(node, compatible[i]))
X				return node;
X
X	/*
X	 * Find the node the long way.
X	 */
X
X	for (i = 0; compatible[i]; i++) {
X		if ((node = OF_finddevice("/soc")) == 0)
X			return (0);
X
X		if ((node = fdt_find_compatible(node, compatible[i], 1)) != 0)
X			return node;
X	}
X
X	return (0);
}
X
X
static int
alloc_resource_for_node(phandle_t node, struct resource *res, u_long *size)
{
X	int err;
X	u_long pbase, psize;
X	u_long start;
X
X	if ((err = fdt_get_range(OF_parent(node), 0, &pbase, &psize)) != 0
X	    || (err = fdt_regsize(node, &start, size)) != 0)
X		return (err);
X
X	start += pbase;
X
X	memset(res, 0, sizeof(*res));
X
X	res->r_bustag = fdtbus_bs_tag;
X
X	err = bus_space_map(res->r_bustag, start, *size, 0, &res->r_bushandle);
X
X	return (err);
}
X
X
static void
power_on_cpu(int cpu)
{
X	uint32_t scpsr;
X	uint32_t value;
X
X	if (cpu <= 0)
X		return;
X
X	/*
X	 * Power on the CPU if the intricate details are known, otherwise
X	 * just hope for the best (it may have already be powered on by
X	 * the hardware / firmware).
X	 */
X
X	switch (aml8726_soc_hw_rev) {
X	case AML_SOC_HW_REV_M8:
X	case AML_SOC_HW_REV_M8B:
X		/*
X		 * Set the SCU power status for the CPU to normal mode.
X		 */
X		scpsr = SCU_READ_4(AML_SCU_CPU_PWR_STATUS_REG);
X		scpsr &= ~(AML_SCU_CPU_PWR_STATUS_CPU1_MASK
X			   << ((cpu - 1) * 8));
X		SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr);
X		SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG);
X
X		if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) {
X			/*
X			 * Reset may cause the current power status from the
X			 * actual CPU to be written to the SCU (over-writing
X			 * the value  we've just written) so set it to normal
X			 * mode as well.
X			 */
X			 value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG);
X			 value &= ~(AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK
X				    << ((cpu - 1) * 2));
X			 AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value);
X			 AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG);
X		 }
X
X		DELAY(5);
X
X		/*
X		 * Assert reset.
X		 */
X		value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG);
X		value |= AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1); 
X		CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value);
X		CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG);
X
X		if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) {
X			/*
X			 * Release RAM pull-down.
X			 */
X			 value = AOBUS_READ_4(AML_M8B_CPU_PWR_MEM_PD0_REG);
X			 value &= ~((uint32_t)AML_M8B_CPU_PWR_MEM_PD0_CPU1
X				    >> ((cpu - 1) * 4));
X			 AOBUS_WRITE_4(AML_M8B_CPU_PWR_MEM_PD0_REG, value);
X			 AOBUS_BARRIER(AML_M8B_CPU_PWR_MEM_PD0_REG);
X		 }
X
X		/*
X		 * Power on CPU.
X		 */
X		value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG);
X		value &= ~(AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK
X			   << ((cpu - 1) * 2));
X		AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL1_REG, value);
X		AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL1_REG);
X
X		DELAY(10);
X
X		if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) {
X			/*
X			 * Wait for power on confirmation.
X			 */
X			for ( ; ; ) {
X				value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG);
X				value &= AML_M8B_CPU_PWR_CNTL1_PWR_CPU1
X					 << (cpu - 1);
X				if (value)
X					break;
X				DELAY(10);
X			}
X		}
X
X		/*
X		 * Release peripheral clamp.
X		 */
X		value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG);
X		value &= ~(AML_M8_CPU_PWR_CNTL0_ISO_CPU1 << (cpu - 1));
X		AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value);
X		AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG);
X
X		/*
X		 * Release reset.
X		 */
X		value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG);
X		value &= ~(AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1));
X		CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value);
X		CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG);
X
X		if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) {
X			/*
X			 * The Amlogic Linux platform code sets the SCU power
X			 * status for the CPU again for some reason so we
X			 * follow suit (perhaps in case the reset caused
X			 * a stale power status from the actual CPU to be
X			 * written to the SCU).
X			 */
X			SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr);
X			SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG);
X		}
X		break;
X	default:
X		break;
X	}
}
X
X
void
platform_mp_init_secondary(void)
{
X
X	/*
X	 * Consider modifying the timer driver to support
X	 * per-cpu timers and then enabling the timer for
X	 * each AP.
X	 */
X
X	 arm_init_secondary_ic();
}
X
X
void
platform_mp_setmaxid(void)
{
X	int err;
X	int i;
X	int ncpu;
X	phandle_t cpucfg_node;
X	phandle_t scu_node;
X	uint32_t value;
X
X	if (mp_ncpus != 0)
X		return;
X
X	ncpu = 1;
X
X	/*
X	 * Is the hardware necessary for SMP present?
X	 */
X
X	if ((scu_node = find_node_for_device("scu", scu_compatible)) == 0)
X		goto moveon;
X
X	if ((cpucfg_node = find_node_for_device("cpuconfig",
X						cpucfg_compatible)) == 0)
X		goto moveon;
X
X	if (alloc_resource_for_node(scu_node, &aml8726_smp.scu_res,
X				    &aml8726_smp.scu_size) != 0)
X		panic("Could not allocate resource for SCU");
X
X	if (alloc_resource_for_node(cpucfg_node, &aml8726_smp.cpucfg_res,
X				    &aml8726_smp.cpucfg_size) != 0)
X		panic("Could not allocate resource for CPUCONFIG");
X
X
X	/*
X	 * Strictly speaking the aobus and cbus may not be required in
X	 * order to start an AP (it depends on the processor), however
X	 * always mapping them in simplifies the code.
X	 */
X
X	aml8726_smp.aobus_res.r_bustag = fdtbus_bs_tag;
X
X	err = bus_space_map(aml8726_smp.aobus_res.r_bustag,
X			    AML_SOC_AOBUS_BASE_ADDR, 0x100000,
X			    0, &aml8726_smp.aobus_res.r_bushandle);
X
X	if (err)
X		panic("Could not allocate resource for AOBUS");
X
X	aml8726_smp.cbus_res.r_bustag = fdtbus_bs_tag;
X
X	err = bus_space_map(aml8726_smp.cbus_res.r_bustag,
X			    AML_SOC_CBUS_BASE_ADDR, 0x100000,
X			    0, &aml8726_smp.cbus_res.r_bushandle);
X
X	if (err)
X		panic("Could not allocate resource for CBUS");
X
X	aml8726_smp.errata_764369 = false;
X	for (i = 0; scu_errata_764369[i]; i++)
X		if (fdt_is_compatible_strict(scu_node, scu_errata_764369[i])) {
X			aml8726_smp.errata_764369 = true;
X			break;
X		}
X
X	/*
X	 * Read the number of CPUs present.
X	 */
X	value = SCU_READ_4(AML_SCU_CONFIG_REG);
X	ncpu = (value & AML_SCU_CONFIG_NCPU_MASK) + 1;
X
moveon:
X	mp_ncpus = ncpu;
X	mp_maxid = ncpu - 1;
}
X
X
int
platform_mp_probe(void)
{
X
X	if (mp_ncpus == 0)
X		platform_mp_setmaxid();
X
X	return (mp_ncpus > 1);
}
X
X
void
platform_mp_start_ap(void)
{
X	int i;
X	uint32_t reg;
X	uint32_t value;
X	vm_paddr_t paddr;
X
X	if (mp_ncpus < 2)
X		return;
X
X	/*
X	 * Invalidate SCU cache tags.  The 0x0000ffff constant invalidates
X	 * all ways on all cores 0-3.  Per the ARM docs, it's harmless to
X	 * write to the bits for cores that are not present.
X	 */
X	SCU_WRITE_4(AML_SCU_INV_TAGS_REG, 0x0000ffff);
X
X	if (aml8726_smp.errata_764369) {
X		/*
X		 * Erratum ARM/MP: 764369 (problems with cache maintenance).
X		 * Setting the "disable-migratory bit" in the undocumented SCU
X		 * Diagnostic Control Register helps work around the problem.
X		 */
X		value = SCU_READ_4(AML_SCU_DIAG_CONTROL_REG);
X		value |= AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT;
X		SCU_WRITE_4(AML_SCU_DIAG_CONTROL_REG, value);
X	}
X
X	/*
X	 * Enable the SCU, then clean the cache on this core.  After these
X	 * two operations the cache tag ram in the SCU is coherent with
X	 * the contents of the cache on this core.  The other cores aren't
X	 * running yet so their caches can't contain valid data yet, however
X	 * we've initialized their SCU tag ram above, so they will be
X	 * coherent from startup.
X	 */
X	value = SCU_READ_4(AML_SCU_CONTROL_REG);
X	value |= AML_SCU_CONTROL_ENABLE;
X	SCU_WRITE_4(AML_SCU_CONTROL_REG, value);
X	SCU_BARRIER(AML_SCU_CONTROL_REG);
X	cpu_idcache_wbinv_all();
X
X	/* Set the boot address and power on each AP. */
X	paddr = pmap_kextract((vm_offset_t)mpentry);
X	for (i = 1; i < mp_ncpus; i++) {
X		reg = AML_CPUCONF_CPU1_ADDR_REG + ((i - 1) * 4);
X		CPUCONF_WRITE_4(reg, paddr);
X		CPUCONF_BARRIER(reg);
X
X		power_on_cpu(i);
X	}
X
X	/*
X	 * Enable the APs.
X	 *
X	 * The Amlogic Linux platform code sets the lsb for some reason
X	 * in addition to the enable bit for each AP so we follow suit
X	 * (the lsb may be the enable bit for the BP, though in that case
X	 * it should already be set since it's currently running).
X	 */
X	value = CPUCONF_READ_4(AML_CPUCONF_CONTROL_REG);
X	value |= 1;
X	for (i = 1; i < mp_ncpus; i++)
X		value |= (1 << i);
X	CPUCONF_WRITE_4(AML_CPUCONF_CONTROL_REG, value);
X	CPUCONF_BARRIER(AML_CPUCONF_CONTROL_REG);
X
X	/* Wakeup the now enabled APs */
X	armv7_sev();
X
X	/*
X	 * Free the resources which are not needed after startup.
X	 */
X	bus_space_unmap(aml8726_smp.scu_res.r_bustag,
X			aml8726_smp.scu_res.r_bushandle,
X			aml8726_smp.scu_size);
X	bus_space_unmap(aml8726_smp.cpucfg_res.r_bustag,
X			aml8726_smp.cpucfg_res.r_bushandle,
X			aml8726_smp.cpucfg_size);
X	bus_space_unmap(aml8726_smp.aobus_res.r_bustag,
X			aml8726_smp.aobus_res.r_bushandle,
X			0x100000);
X	bus_space_unmap(aml8726_smp.cbus_res.r_bustag,
X			aml8726_smp.cbus_res.r_bushandle,
X			0x100000);
X	memset(&aml8726_smp, 0, sizeof(aml8726_smp));
}
X
X
void
platform_ipi_send(cpuset_t cpus, u_int ipi)
{
X
X	pic_ipi_send(cpus, ipi);
}
X
X
/*
X * Stub drivers for cosmetic purposes.
X */
X
X
struct aml8726_scu_softc {
X	device_t		dev;
};
X
X
static int
aml8726_scu_probe(device_t dev)
{
X	int i;
X
X	for (i = 0; scu_compatible[i]; i++)
X		if (ofw_bus_is_compatible(dev, scu_compatible[i]))
X			break;
X
X	if (!scu_compatible[i])
X		return (ENXIO);
X
X	device_set_desc(dev, "ARM Snoop Control Unit");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_scu_attach(device_t dev)
{
X	struct aml8726_scu_softc *sc = device_get_softc(dev);
X
X	sc->dev = dev;
X
X	return (0);
}
X
X
static int
aml8726_scu_detach(device_t dev)
{
X
X	return (0);
}
X
X
static device_method_t aml8726_scu_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe,		aml8726_scu_probe),
X	DEVMETHOD(device_attach,	aml8726_scu_attach),
X	DEVMETHOD(device_detach,	aml8726_scu_detach),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_scu_driver = {
X	"scu",
X	aml8726_scu_methods,
X	sizeof(struct aml8726_scu_softc),
};
X
static devclass_t aml8726_scu_devclass;
X
EARLY_DRIVER_MODULE(scu, simplebus,
X		    aml8726_scu_driver, aml8726_scu_devclass,
X		    0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE);
X
X
struct aml8726_cpucfg_softc {
X	device_t		dev;
};
X
X
static int
aml8726_cpucfg_probe(device_t dev)
{
X	int i;
X
X	for (i = 0; cpucfg_compatible[i]; i++)
X		if (ofw_bus_is_compatible(dev, cpucfg_compatible[i]))
X			break;
X
X	if (!cpucfg_compatible[i])
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic CPU Config");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_cpucfg_attach(device_t dev)
{
X	struct aml8726_cpucfg_softc *sc = device_get_softc(dev);
X
X	sc->dev = dev;
X
X	return (0);
}
X
X
static int
aml8726_cpucfg_detach(device_t dev)
{
X
X	return (0);
}
X
X
static device_method_t aml8726_cpucfg_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe,		aml8726_cpucfg_probe),
X	DEVMETHOD(device_attach,	aml8726_cpucfg_attach),
X	DEVMETHOD(device_detach,	aml8726_cpucfg_detach),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_cpucfg_driver = {
X	"cpuconfig",
X	aml8726_cpucfg_methods,
X	sizeof(struct aml8726_cpucfg_softc),
};
X
static devclass_t aml8726_cpucfg_devclass;
X
EARLY_DRIVER_MODULE(cpuconfig, simplebus,
X		    aml8726_cpucfg_driver, aml8726_cpucfg_devclass,
X		    0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_LATE);
SHAR_EOF
  (set 20 15 01 31 17 22 53 'sys/arm/amlogic/aml8726/aml8726_mp.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_mp.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_mp.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_mp.c': 'MD5 check failed'
       ) << \SHAR_EOF
40f4b7a22022dac6fa61a414edab8997  sys/arm/amlogic/aml8726/aml8726_mp.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_mp.c'` -ne 17678 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_mp.c' is not 17678"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_pic.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_pic.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_pic.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_pic.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_pic.c' &&
/*-
X * Copyright 2013-2015 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/resource.h>
#include <sys/rman.h>
X
#include <machine/bus.h>
#include <machine/intr.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
X
struct aml8726_pic_softc {
X	device_t		dev;
X	struct resource *	res[1];
};
X
static struct resource_spec aml8726_pic_spec[] = {
X	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
X	{ -1, 0 }
};
X
X
/*
X * devclass_get_device / device_get_softc could be used
X * to dynamically locate this, however the pic is a
X * required device which can't be unloaded so there's
X * no need for the overhead.
X */
static struct aml8726_pic_softc *aml8726_pic_sc = NULL;
X
#define AML_PIC_NCNTRLS         4
#define AML_PIC_IRQS_PER_CNTRL  32
X
#define AML_PIC_NIRQS           (AML_PIC_NCNTRLS * AML_PIC_IRQS_PER_CNTRL)
X
#define AML_PIC_0_STAT_REG      0
#define AML_PIC_0_STAT_CLR_REG  4
#define AML_PIC_0_MASK_REG      8
#define AML_PIC_0_FIRQ_SEL      12
X
#define AML_PIC_1_STAT_REG      16
#define AML_PIC_1_STAT_CLR_REG  20
#define AML_PIC_1_MASK_REG      24
#define AML_PIC_1_FIRQ_SEL      28
X
#define AML_PIC_2_STAT_REG      32
#define AML_PIC_2_STAT_CLR_REG  36
#define AML_PIC_2_MASK_REG      40
#define AML_PIC_2_FIRQ_SEL      44
X
#define AML_PIC_3_STAT_REG      48
#define AML_PIC_3_STAT_CLR_REG  52
#define AML_PIC_3_MASK_REG      56
#define AML_PIC_3_FIRQ_SEL      60
X
#define AML_PIC_CTRL(x)         ((x) >> 5)
#define AML_PIC_BIT(x)          (1 << ((x) & 0x1f))
X
#define AML_PIC_STAT_REG(x)     (AML_PIC_0_STAT_REG + AML_PIC_CTRL(x) * 16)
#define AML_PIC_STAT_CLR_REG(x) (AML_PIC_0_STAT_CLR_REG + AML_PIC_CTRL(x) * 16)
#define AML_PIC_MASK_REG(x)     (AML_PIC_0_MASK_REG + AML_PIC_CTRL(x) * 16)
#define AML_PIC_FIRQ_SEL(x)     (AML_PIC_0_FIRQ_REG + AML_PIC_CTRL(x) * 16)
X
#define CSR_WRITE_4(sc, reg, val)	bus_write_4((sc)->res[0], reg, (val))
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[0], reg)
#define CSR_BARRIER(sc, reg)		bus_barrier((sc)->res[0], reg, 4, \
X					  (BUS_SPACE_BARRIER_READ         \
X					   | BUS_SPACE_BARRIER_WRITE))
X
X
static void
aml8726_pic_eoi(void *arg)
{
X	uintptr_t nb = (uintptr_t) arg;
X
X	if (nb >= AML_PIC_NIRQS)
X		return;
X
X	CSR_WRITE_4(aml8726_pic_sc, AML_PIC_STAT_CLR_REG(nb), AML_PIC_BIT(nb));
X
X	CSR_BARRIER(aml8726_pic_sc, AML_PIC_STAT_CLR_REG(nb));
}
X
X
static int
aml8726_pic_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-pic"))
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic aml8726 PIC");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_pic_attach(device_t dev)
{
X	struct aml8726_pic_softc *sc = device_get_softc(dev);
X	int i;
X
X	/* There should be exactly one instance. */
X	if (aml8726_pic_sc != NULL)
X		return (ENXIO);
X
X	sc->dev = dev;
X
X	if (bus_alloc_resources(dev, aml8726_pic_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	/*
X	 * Disable, clear, and set the interrupts to normal mode.
X	 */
X	for (i = 0; i < AML_PIC_NCNTRLS; i++) {
X		CSR_WRITE_4(sc, AML_PIC_0_MASK_REG + i * 16, 0);
X		CSR_WRITE_4(sc, AML_PIC_0_STAT_CLR_REG + i * 16, ~0u);
X		CSR_WRITE_4(sc, AML_PIC_0_FIRQ_SEL + i * 16, 0);
X	}
X
#ifndef SMP
X	arm_post_filter = aml8726_pic_eoi;
#else
X	device_printf(dev, "disabled in favor of gic\n");
#endif
X
X	aml8726_pic_sc = sc;
X
X	return (0);
}
X
X
static int
aml8726_pic_detach(device_t dev)
{
X
X	return (EBUSY);
}
X
X
static device_method_t aml8726_pic_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe,		aml8726_pic_probe),
X	DEVMETHOD(device_attach,	aml8726_pic_attach),
X	DEVMETHOD(device_detach,	aml8726_pic_detach),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_pic_driver = {
X	"pic",
X	aml8726_pic_methods,
X	sizeof(struct aml8726_pic_softc),
};
X
static devclass_t aml8726_pic_devclass;
X
EARLY_DRIVER_MODULE(pic, simplebus,
X		    aml8726_pic_driver, aml8726_pic_devclass,
X		    0, 0, BUS_PASS_INTERRUPT);
X
X
#ifndef SMP
int
arm_get_next_irq(int last)
{
X	uint32_t value;
X	int irq;
X	int start;
X
X	/*
X	 * The extra complexity is simply so that all IRQs are checked
X	 * round robin so a particularly busy interrupt can't prevent
X	 * other interrupts from being serviced.
X	 */
X
X	start = (last + 1) % AML_PIC_NIRQS;
X	irq = start;
X
X	for ( ; ; ) {
X		value = CSR_READ_4(aml8726_pic_sc, AML_PIC_STAT_REG(irq));
X
X		for ( ; ; ) {
X			if ((value & AML_PIC_BIT(irq)) != 0)
X				return (irq);
X
X			irq = (irq + 1) % AML_PIC_NIRQS;
X
X			if (irq == start)
X				return (-1);
X
X			if ((irq % AML_PIC_IRQS_PER_CNTRL) == 0)
X				break;
X		}
X	}
}
X
X
void
arm_mask_irq(uintptr_t nb)
{
X	uint32_t mask;
X
X	if (nb >= AML_PIC_NIRQS)
X		return;
X
X	mask = CSR_READ_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb));
X	mask &= ~AML_PIC_BIT(nb);
X	CSR_WRITE_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb), mask);
X
X	CSR_BARRIER(aml8726_pic_sc, AML_PIC_MASK_REG(nb));
X
X	aml8726_pic_eoi((void *)nb);
}
X
X
void
arm_unmask_irq(uintptr_t nb)
{
X	uint32_t mask;
X
X	if (nb >= AML_PIC_NIRQS)
X		return;
X
X	mask = CSR_READ_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb));
X	mask |= AML_PIC_BIT(nb);
X	CSR_WRITE_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb), mask);
}
#endif
SHAR_EOF
  (set 20 15 01 10 01 46 23 'sys/arm/amlogic/aml8726/aml8726_pic.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_pic.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_pic.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_pic.c': 'MD5 check failed'
       ) << \SHAR_EOF
592568bdf693d1572e01f95e9da20ed5  sys/arm/amlogic/aml8726/aml8726_pic.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_pic.c'` -ne 7110 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_pic.c' is not 7110"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_rng.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_rng.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_rng.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_rng.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_rng.c' &&
/*-
X * Copyright 2014 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/resource.h>
#include <sys/rman.h>
#include <sys/random.h>
X
#include <machine/bus.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
X
struct aml8726_rng_softc {
X	device_t		dev;
X	struct resource		*res[1];
X	struct callout		co;
X	int			ticks;
};
X
static struct resource_spec aml8726_rng_spec[] = {
X	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
X	{ -1, 0 }
};
X
#define AML_RNG_0_REG			0
#define AML_RNG_1_REG			4
X
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[0], reg)
X
X
static void
aml8726_rng_harvest(void *arg)
{
X	struct aml8726_rng_softc *sc = arg;
X	uint32_t rn[2];
X
X	rn[0] = CSR_READ_4(sc, AML_RNG_0_REG);
X	rn[1] = CSR_READ_4(sc, AML_RNG_1_REG);
X
X	random_harvest(rn, sizeof(rn), sizeof(rn) * NBBY / 2,
X		       RANDOM_PURE_AML8726);
X
X	callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc);
}
X
X
static int
aml8726_rng_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rng"))
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic aml8726 RNG");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_rng_attach(device_t dev)
{
X	struct aml8726_rng_softc *sc = device_get_softc(dev);
X
X	sc->dev = dev;
X
X	if (bus_alloc_resources(dev, aml8726_rng_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	/* Install a periodic collector for the RNG */
X	if (hz > 100)
X		sc->ticks = hz / 100;
X	else
X		sc->ticks = 1;
X
X	callout_init(&sc->co, CALLOUT_MPSAFE);
X	callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc);
X
X	return (0);
}
X
X
static int
aml8726_rng_detach(device_t dev)
{
X	struct aml8726_rng_softc *sc = device_get_softc(dev);
X
X	callout_drain(&sc->co);
X
X	bus_release_resources(dev, aml8726_rng_spec, sc->res);
X
X	return (0);
}
X
X
static device_method_t aml8726_rng_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe, 	aml8726_rng_probe),
X	DEVMETHOD(device_attach, 	aml8726_rng_attach),
X	DEVMETHOD(device_detach, 	aml8726_rng_detach),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_rng_driver = {
X	"rng",
X	aml8726_rng_methods,
X	sizeof(struct aml8726_rng_softc),
};
X
static devclass_t aml8726_rng_devclass;
X
DRIVER_MODULE(aml8726_rng, simplebus, aml8726_rng_driver, aml8726_rng_devclass, 0, 0);
MODULE_DEPEND(aml8726_rng, random, 1, 1, 1);
SHAR_EOF
  (set 20 14 04 15 23 46 43 'sys/arm/amlogic/aml8726/aml8726_rng.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_rng.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_rng.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_rng.c': 'MD5 check failed'
       ) << \SHAR_EOF
90f9547099363261f2e568a362a8cd35  sys/arm/amlogic/aml8726/aml8726_rng.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_rng.c'` -ne 3976 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_rng.c' is not 3976"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_rtc.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_rtc.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_rtc.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_rtc.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_rtc.c' &&
/*-
X * Copyright 2013-2014 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/clock.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/resource.h>
#include <sys/rman.h>
X
#include <sys/time.h>
X
#include <machine/bus.h>
#include <machine/cpu.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
#include "clock_if.h"
X
X
/*
X * The RTC initialization various slightly between the different chips.
X *
X *                 aml8726-m1     aml8726-m3     aml8726-m6 (and later)
X *  init-always    true           true           false
X *  xo-init        0x0004         0x3c0a         0x180a
X *  gpo-init       0x100000       0x100000       0x500000
X */
X
struct aml8726_rtc_init {
X	boolean_t	always;
X	uint16_t	xo;
X	uint32_t	gpo;
};
X
struct aml8726_rtc_softc {
X	device_t		dev;
X	struct aml8726_rtc_init	init;
X	struct resource	*	res[2];
X	struct mtx		mtx;
};
X
static struct resource_spec aml8726_rtc_spec[] = {
X	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
X	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
X	{ -1, 0 }
};
X
#define AML_RTC_LOCK(sc)		mtx_lock_spin(&(sc)->mtx)
#define AML_RTC_UNLOCK(sc)		mtx_unlock_spin(&(sc)->mtx)
#define AML_RTC_LOCK_INIT(sc) \
X	mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
X	    "rtc", MTX_SPIN)
#define AML_RTC_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->mtx);
X
#define AML_RTC_0_REG                0
#  define AML_RTC_SCLK               (1 << 0)
#  define AML_RTC_SDI                (1 << 2)
#  define AML_RTC_SEN                (1 << 1)
#  define AML_RTC_AS                 (1 << 17)
#  define AML_RTC_ABSY               (1 << 22)
#  define AML_RTC_IRQ_DIS            (1 << 12)
#define AML_RTC_1_REG                4
#  define AML_RTC_SDO                (1 << 0)
#  define AML_RTC_SRDY               (1 << 1)
#define AML_RTC_2_REG                8
#define AML_RTC_3_REG                12
#  define AML_RTC_MSR_BUSY           (1 << 20)
#  define AML_RTC_MSR_CA             (1 << 17)
#  define AML_RTC_MSR_DURATION_EN    (1 << 16)
#  define AML_RTC_MSR_DURATION_MASK  0xffff
#  define AML_RTC_MSR_DURATION_SHIFT 0
#define AML_RTC_4_REG                16
X
#define AML_RTC_TIME_SREG         0
#define AML_RTC_GPO_SREG          1
#  define AML_RTC_GPO_LEVEL       (1 << 24)
#  define AML_RTC_GPO_BUSY        (1 << 23)
#  define AML_RTC_GPO_ACTIVE_HIGH (1 << 22)
#  define AML_RTC_GPO_CMD_MASK    (3 << 20)
#  define AML_RTC_GPO_CMD_SHIFT   20
#  define AML_RTC_GPO_CMD_NOW     (1 << 20)
#  define AML_RTC_GPO_CMD_COUNT   (2 << 20)
#  define AML_RTC_GPO_CMD_PULSE   (3 << 20)
#  define AML_RTC_GPO_CNT_MASK    0xfffff
#  define AML_RTC_GPO_CNT_SHIFT   0
X
#define CSR_WRITE_4(sc, reg, val)	bus_write_4((sc)->res[0], reg, (val))
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[0], reg)
#define CSR_BARRIER(sc, reg)		bus_barrier((sc)->res[0], reg, 4, \
X					  (BUS_SPACE_BARRIER_READ         \
X					   | BUS_SPACE_BARRIER_WRITE))
X
X
static int
aml8726_rtc_start_transfer(struct aml8726_rtc_softc *sc)
{
X	unsigned i;
X
X	/* idle the serial interface */
X	CSR_WRITE_4(sc, AML_RTC_0_REG,
X		    (CSR_READ_4(sc, AML_RTC_0_REG)
X		     & ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI)));
X
X	CSR_BARRIER(sc, AML_RTC_0_REG);
X
X	/* see if it is ready for a new cycle */
X	for (i = 40; i; i--) {
X		DELAY(5);
X		if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) )
X			break;
X	}
X
X	if (i == 0)
X		return (EIO);
X
X	/* start the cycle */
X	CSR_WRITE_4(sc, AML_RTC_0_REG,
X		    (CSR_READ_4(sc, AML_RTC_0_REG) | AML_RTC_SEN));
X
X	return (0);
}
X
X
static inline void
aml8726_rtc_sclk_pulse(struct aml8726_rtc_softc *sc)
{
X
X	DELAY(5);
X
X	CSR_WRITE_4(sc, AML_RTC_0_REG,
X		    (CSR_READ_4(sc, AML_RTC_0_REG) | AML_RTC_SCLK));
X
X	CSR_BARRIER(sc, AML_RTC_0_REG);
X
X	DELAY(5);
X
X	CSR_WRITE_4(sc, AML_RTC_0_REG,
X		    (CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SCLK));
X	
X	CSR_BARRIER(sc, AML_RTC_0_REG);
}
X
X
static inline void
aml8726_rtc_send_bit(struct aml8726_rtc_softc *sc, unsigned bit)
{
X
X	if (bit) {
X	    CSR_WRITE_4(sc, AML_RTC_0_REG,
X			(CSR_READ_4(sc, AML_RTC_0_REG) | AML_RTC_SDI));
X	} else {
X	    CSR_WRITE_4(sc, AML_RTC_0_REG,
X			(CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SDI));
X	}
X
X	aml8726_rtc_sclk_pulse(sc);
}
X
X
static inline void
aml8726_rtc_send_addr(struct aml8726_rtc_softc *sc, u_char addr)
{
X	unsigned mask;
X
X	for (mask = 1 << 3; mask; mask >>= 1) {
X		if (mask == 1) {
X		    /* final bit indicates read / write mode */
X		    CSR_WRITE_4(sc, AML_RTC_0_REG,
X				(CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SEN));
X		}
X		aml8726_rtc_send_bit(sc, (addr & mask));
X	}
}
X
X
static inline void
aml8726_rtc_send_data(struct aml8726_rtc_softc *sc, uint32_t data)
{
X	unsigned mask;
X
X	for (mask = 1U << 31; mask; mask >>= 1)
X		aml8726_rtc_send_bit(sc, (data && mask));
}
X
X
static inline void
aml8726_rtc_recv_data(struct aml8726_rtc_softc *sc, uint32_t *dp)
{
X	uint32_t data;
X	unsigned i;
X
X	data = 0;
X
X	for (i = 0; i < 32; i++) {
X		aml8726_rtc_sclk_pulse(sc);
X		data <<= 1;
X		data |= (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SDO) ? 1 : 0;
X	}
X
X	*dp = data;
}
X
X
static int
aml8726_rtc_sreg_read(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t *val)
{
X	u_char addr;
X	int error;
X
X	/* read is indicated by lsb = 0 */
X	addr = (sreg << 1) | 0;
X
X	error = aml8726_rtc_start_transfer(sc);
X
X	if (error)
X		return (error);
X
X	aml8726_rtc_send_addr(sc, addr);
X	aml8726_rtc_recv_data(sc, val);
X
X	return (0);
}
X
X
static int
aml8726_rtc_sreg_write(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t val)
{
X	u_char addr;
X	int error;
X
X	/* write is indicated by lsb = 1 */
X	addr = (sreg << 1) | 1;
X
X	error = aml8726_rtc_start_transfer(sc);
X
X	if (error)
X		return (error);
X
X	aml8726_rtc_send_data(sc, val);
X	aml8726_rtc_send_addr(sc, addr);
X
X	return (0);
}
X
X
static int
aml8726_rtc_initialize(struct aml8726_rtc_softc *sc)
{
X	int error;
X	unsigned i;
X
X	/* idle the serial interface */
X	CSR_WRITE_4(sc, AML_RTC_0_REG,
X		    (CSR_READ_4(sc, AML_RTC_0_REG)
X		     & ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI)));
X
X	CSR_BARRIER(sc, AML_RTC_0_REG);
X
X	/* see if it is ready for a new cycle */
X	for (i = 40; i; i--) {
X		DELAY(5);
X		if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) )
X			break;
X	}
X
X	if (sc->init.always == TRUE
X	    || (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) == 0) {
X
X		/*
X		 * The RTC has a 16 bit initialization register.  The upper
X		 * bits can be written directly.  The lower bits are written
X		 * through a shift register.
X		 */
X
X		CSR_WRITE_4(sc, AML_RTC_4_REG, ((sc->init.xo >> 8) & 0xff));
X
X		CSR_WRITE_4(sc, AML_RTC_0_REG,
X			    ((CSR_READ_4(sc, AML_RTC_0_REG) & 0xffffff)
X			     | ((uint32_t)(sc->init.xo & 0xff) << 24)
X			     | AML_RTC_AS | AML_RTC_IRQ_DIS));
X
X		while ((CSR_READ_4(sc, AML_RTC_0_REG) & AML_RTC_ABSY) != 0)
X		    cpu_spinwait();
X
X		DELAY(2);
X
X		error = aml8726_rtc_sreg_write(sc, AML_RTC_GPO_SREG,
X					       sc->init.gpo);
X
X		if (error)
X			return (error);
X	}
X
X	return (0);
}
X
X
static int
aml8726_rtc_check_xo(struct aml8726_rtc_softc *sc)
{
X	uint32_t now, previous;
X	int i;
X
X	/*
X	 * The RTC is driven by a 32.768khz clock meaning it's period
X	 * is roughly 30.5 us.  Check that it's working (implying the
X	 * RTC could contain a valid value) by enabling count always
X	 * and seeing if the value changes after 200 us (per RTC User
X	 * Guide ... presumably the extra time is to cover XO startup).
X	 */
X
X	CSR_WRITE_4(sc, AML_RTC_3_REG,
X		    (CSR_READ_4(sc, AML_RTC_3_REG) | AML_RTC_MSR_CA));
X
X	previous = CSR_READ_4(sc, AML_RTC_2_REG);
X
X	for (i = 0; i < 4; i++) {
X		DELAY(50);
X		now = CSR_READ_4(sc, AML_RTC_2_REG);
X		if (now != previous)
X			break;
X	}
X
X	CSR_WRITE_4(sc, AML_RTC_3_REG,
X		    (CSR_READ_4(sc, AML_RTC_3_REG) & ~AML_RTC_MSR_CA));
X
X	if (now == previous)
X		return (EINVAL);
X
X	return (0);
}
X
X
static int
aml8726_rtc_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rtc"))
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic aml8726 RTC");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_rtc_attach(device_t dev)
{
X	struct aml8726_rtc_softc *sc = device_get_softc(dev);
X	boolean_t init_always_valid;
X	char *init_always;
X	pcell_t prop;
X	phandle_t node;
X	ssize_t len;
X
X	sc->dev = dev;
X
X	node = ofw_bus_get_node(dev);
X
X	len = OF_getprop_alloc(node, "init-always",
X			       sizeof(char), (void **)&init_always);
X	sc->init.always = FALSE;
X	init_always_valid = FALSE;
X	if (len > 0) {
X		if (strncmp(init_always, "true", len) == 0) {
X			sc->init.always = TRUE;
X			init_always_valid = TRUE;
X		} else if (strncmp(init_always, "false", len) == 0)
X			init_always_valid = TRUE;
X		free(init_always, M_OFWPROP);
X	}
X	if (init_always_valid == FALSE) {
X		device_printf(dev, "missing init-always attribute in FDT\n");
X		return (ENXIO);
X	}
X
X	if (OF_getencprop(node, "xo-init", &prop, sizeof(prop)) <= 0) {
X		device_printf(dev, "missing xo-init attribute in FDT\n");
X		return (ENXIO);
X	}
X	sc->init.xo = prop;
X
X	if (OF_getencprop(node, "gpo-init", &prop, sizeof(prop)) <= 0) {
X		device_printf(dev, "missing gpo-init attribute in FDT\n");
X		return (ENXIO);
X	}
X	sc->init.gpo = prop;
X
X	if (bus_alloc_resources(dev, aml8726_rtc_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	aml8726_rtc_initialize(sc);
X
X	if (aml8726_rtc_check_xo(sc) != 0) {
X		device_printf(dev, "crystal oscillator check failed\n");
X
X		bus_release_resources(dev, aml8726_rtc_spec, sc->res);
X
X		return (ENXIO);
X	}
X
X	AML_RTC_LOCK_INIT(sc);
X
X	clock_register(dev, 1000000);
X
X	return (0);
}
X
X
static int
aml8726_rtc_detach(device_t dev)
{
X
X	return (EBUSY);
}
X
X
static int
aml8726_rtc_gettime(device_t dev, struct timespec *ts)
{
X	struct aml8726_rtc_softc *sc = device_get_softc(dev);
X	uint32_t sec;
X	int error;
X
X	AML_RTC_LOCK(sc);
X
X	error = aml8726_rtc_sreg_read(sc, AML_RTC_TIME_SREG, &sec);
X
X	AML_RTC_UNLOCK(sc);
X
X	ts->tv_sec = sec;
X	ts->tv_nsec = 0;
X
X	return (error);
}
X
X
static int
aml8726_rtc_settime(device_t dev, struct timespec *ts)
{
X	struct aml8726_rtc_softc *sc = device_get_softc(dev);
X	uint32_t sec;
X	int error;
X
X	sec = ts->tv_sec;
X
X	/* Accuracy is only one second. */
X	if (ts->tv_nsec >= 500000000)
X	    sec++;
X
X	AML_RTC_LOCK(sc);
X
X	error = aml8726_rtc_sreg_write(sc, AML_RTC_TIME_SREG, sec);
X
X	AML_RTC_UNLOCK(sc);
X
X	return (error);	
}
X
X
static device_method_t aml8726_rtc_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe,		aml8726_rtc_probe),
X	DEVMETHOD(device_attach,	aml8726_rtc_attach),
X	DEVMETHOD(device_detach,	aml8726_rtc_detach),
X
X	/* Clock interface */
X	DEVMETHOD(clock_gettime,	aml8726_rtc_gettime),
X	DEVMETHOD(clock_settime,	aml8726_rtc_settime),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_rtc_driver = {
X	"rtc",
X	aml8726_rtc_methods,
X	sizeof(struct aml8726_rtc_softc),
};
X
static devclass_t aml8726_rtc_devclass;
X
DRIVER_MODULE(rtc, simplebus, aml8726_rtc_driver, aml8726_rtc_devclass, 0, 0);
SHAR_EOF
  (set 20 15 02 01 16 31 29 'sys/arm/amlogic/aml8726/aml8726_rtc.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_rtc.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_rtc.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_rtc.c': 'MD5 check failed'
       ) << \SHAR_EOF
de7cdc3ddcaa59c4b0e2322cbd85f19f  sys/arm/amlogic/aml8726/aml8726_rtc.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_rtc.c'` -ne 12262 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_rtc.c' is not 12262"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_soc.h ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_soc.h'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_soc.h (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_soc.h (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_soc.h' &&
/*-
X * Copyright 2015 John Wehle <john@feith.com>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD$
X */
X
#ifndef _ARM_AMLOGIC_AML8726_SOC_H
#define _ARM_AMLOGIC_AML8726_SOC_H
X
X
#define AML_SOC_AOBUS_BASE_ADDR      0xc8100000
#define AML_SOC_CBUS_BASE_ADDR       0xc1100000
X
/* cbus */
X
#define AML_SOC_HW_REV_REG           0x7d4c
#  define AML_SOC_HW_REV_M3          0x15
#  define AML_SOC_HW_REV_M6          0x16
#  define AML_SOC_HW_REV_M6TV        0x17
#  define AML_SOC_HW_REV_M6TVL       0x18
#  define AML_SOC_HW_REV_M8          0x19
#  define AML_SOC_HW_REV_M6TVD       0x1a
#  define AML_SOC_HW_REV_M8B         0x1b
X
#define AML_SOC_METAL_REV_REG        0x81a8
#  define AML_SOC_M8_METAL_REV_A     0x11111111
#  define AML_SOC_M8_METAL_REV_M2_A  0x11111112
#  define AML_SOC_M8_METAL_REV_B     0x11111113
#  define AML_SOC_M8_METAL_REV_C     0x11111133
#  define AML_SOC_M8B_METAL_REV_A    0x11111111
X
extern uint32_t aml8726_soc_hw_rev;
extern uint32_t aml8726_soc_metal_rev;
X
X
#endif /* _ARM_AMLOGIC_AML8726_SOC_H */
SHAR_EOF
  (set 20 15 01 27 01 22 48 'sys/arm/amlogic/aml8726/aml8726_soc.h'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_soc.h'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_soc.h failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_soc.h': 'MD5 check failed'
       ) << \SHAR_EOF
9b8bf3579704dd1f23dcff36563fdbeb  sys/arm/amlogic/aml8726/aml8726_soc.h
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_soc.h'` -ne 2304 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_soc.h' is not 2304"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_timer.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_timer.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_timer.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_timer.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_timer.c' &&
/*-
X * Copyright 2013-2015 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timetc.h>
#include <sys/timeet.h>
X
#include <machine/bus.h>
#include <machine/cpu.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
X
struct aml8726_timer_softc {
X	device_t		dev;
X	struct resource	*	res[2];
X	struct mtx		mtx;
X	void *			ih_cookie;
X	struct eventtimer	et;
X	uint32_t		first_ticks;
X	uint32_t		period_ticks;
X	struct timecounter	tc;
};
X
static struct resource_spec aml8726_timer_spec[] = {
X	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
X	{ SYS_RES_IRQ,		0,	RF_ACTIVE },	/* INT_TIMER_A */
X	{ -1, 0 }
};
X
/*
X * devclass_get_device / device_get_softc could be used
X * to dynamically locate this, however the timers are a
X * required device which can't be unloaded so there's
X * no need for the overhead.
X */
static struct aml8726_timer_softc *aml8726_timer_sc = NULL;
X
#define AML_TIMER_LOCK(sc)		mtx_lock_spin(&(sc)->mtx)
#define AML_TIMER_UNLOCK(sc)		mtx_unlock_spin(&(sc)->mtx)
#define AML_TIMER_LOCK_INIT(sc) \
X	mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
X	    "timer", MTX_SPIN)
#define AML_TIMER_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->mtx);
X
#define AML_TIMER_MUX_REG         0
#  define AML_TIMER_INPUT_1us     0
#  define AML_TIMER_INPUT_10us    1
#  define AML_TIMER_INPUT_100us   2
#  define AML_TIMER_INPUT_1ms     3
#  define AML_TIMER_INPUT_MASK    3
#  define AML_TIMER_A_INPUT_MASK  3
#  define AML_TIMER_A_INPUT_SHIFT 0
#  define AML_TIMER_B_INPUT_MASK  (3 << 2)
#  define AML_TIMER_B_INPUT_SHIFT 2
#  define AML_TIMER_C_INPUT_MASK  (3 << 4)
#  define AML_TIMER_C_INPUT_SHIFT 4
#  define AML_TIMER_D_INPUT_MASK  (3 << 6)
#  define AML_TIMER_D_INPUT_SHIFT 6
#  define AML_TIMER_E_INPUT_SYS   0
#  define AML_TIMER_E_INPUT_1us   1
#  define AML_TIMER_E_INPUT_10us  2
#  define AML_TIMER_E_INPUT_100us 3
#  define AML_TIMER_E_INPUT_1ms   4
#  define AML_TIMER_E_INPUT_MASK  (7 << 8)
#  define AML_TIMER_E_INPUT_SHIFT 8
#  define AML_TIMER_A_PERIODIC    (1 << 12)
#  define AML_TIMER_B_PERIODIC    (1 << 13)
#  define AML_TIMER_C_PERIODIC    (1 << 14)
#  define AML_TIMER_D_PERIODIC    (1 << 15)
#  define AML_TIMER_A_EN          (1 << 16)
#  define AML_TIMER_B_EN          (1 << 17)
#  define AML_TIMER_C_EN          (1 << 18)
#  define AML_TIMER_D_EN          (1 << 19)
#  define AML_TIMER_E_EN          (1 << 20)
#define AML_TIMER_A_REG           4
#define AML_TIMER_B_REG           8
#define AML_TIMER_C_REG           12
#define AML_TIMER_D_REG           16
#define AML_TIMER_E_REG           20
X
#define CSR_WRITE_4(sc, reg, val)	bus_write_4((sc)->res[0], reg, (val))
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[0], reg)
X
X
static unsigned
aml8726_get_timecount(struct timecounter *tc)
{
X	struct aml8726_timer_softc *sc
X	    = (struct aml8726_timer_softc *)tc->tc_priv;
X
X	return CSR_READ_4(sc, AML_TIMER_E_REG);
}
X
X
static int
aml8726_hardclock(void *arg)
{
X	struct aml8726_timer_softc *sc = (struct aml8726_timer_softc *)arg;
X
X	AML_TIMER_LOCK(sc);
X
X	if (sc->first_ticks != 0 && sc->period_ticks != 0) {
X		sc->first_ticks = 0;
X
X		CSR_WRITE_4(sc, AML_TIMER_A_REG, sc->period_ticks);
X		CSR_WRITE_4(sc, AML_TIMER_MUX_REG,
X			    (CSR_READ_4(sc, AML_TIMER_MUX_REG)
X			     | AML_TIMER_A_PERIODIC | AML_TIMER_A_EN));
X	}
X
X	AML_TIMER_UNLOCK(sc);
X
X	if (sc->et.et_active)
X		sc->et.et_event_cb(&sc->et, sc->et.et_arg);
X
X	return (FILTER_HANDLED);
}
X
X
static int
aml8726_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
X	struct aml8726_timer_softc *sc
X	    = (struct aml8726_timer_softc *)et->et_priv;
X	uint32_t first_ticks;
X	uint32_t period_ticks;
X	uint32_t periodic;
X	uint32_t ticks;
X
X	first_ticks = (first * et->et_frequency) / SBT_1S;
X	period_ticks = (period * et->et_frequency) / SBT_1S;
X
X	if (first_ticks != 0) {
X		ticks = first_ticks;
X		periodic = 0;
X
X	} else {
X		ticks = period_ticks;
X		periodic = AML_TIMER_A_PERIODIC;
X	}
X
X	if (ticks == 0)
X		return (EINVAL);
X
X	AML_TIMER_LOCK(sc);
X
X	sc->first_ticks = first_ticks;
X	sc->period_ticks = period_ticks;
X
X	CSR_WRITE_4(sc, AML_TIMER_A_REG, ticks);
X	CSR_WRITE_4(sc, AML_TIMER_MUX_REG,
X		    ((CSR_READ_4(sc, AML_TIMER_MUX_REG) & ~AML_TIMER_A_PERIODIC)
X		     | AML_TIMER_A_EN | periodic));
X
X	AML_TIMER_UNLOCK(sc);
X
X	return (0);
}
X
X
static int
aml8726_timer_stop(struct eventtimer *et)
{
X	struct aml8726_timer_softc *sc
X	    = (struct aml8726_timer_softc *)et->et_priv;
X
X	AML_TIMER_LOCK(sc);
X
X	CSR_WRITE_4(sc, AML_TIMER_MUX_REG,
X		    (CSR_READ_4(sc, AML_TIMER_MUX_REG) & ~AML_TIMER_A_EN));
X
X	AML_TIMER_UNLOCK(sc);
X
X	return (0);
}
X
X
static int
aml8726_timer_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-timer"))
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic aml8726 timer");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_timer_attach(device_t dev)
{
X	struct aml8726_timer_softc *sc = device_get_softc(dev);
X
X	/* There should be exactly one instance. */
X	if (aml8726_timer_sc != NULL)
X		return (ENXIO);
X
X	sc->dev = dev;
X
X	if (bus_alloc_resources(dev, aml8726_timer_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	/*
X	 * Disable the timers, select the input for each timer,
X	 * clear timer E, and then enable timer E.
X	 */
X	CSR_WRITE_4(sc, AML_TIMER_MUX_REG,
X		    ((CSR_READ_4(sc, AML_TIMER_MUX_REG)
X		      & ~(AML_TIMER_A_EN | AML_TIMER_A_INPUT_MASK
X			  | AML_TIMER_E_EN | AML_TIMER_E_INPUT_MASK))
X		     | (AML_TIMER_INPUT_1us << AML_TIMER_A_INPUT_SHIFT)
X		     | (AML_TIMER_E_INPUT_1us << AML_TIMER_E_INPUT_SHIFT)));
X
X	CSR_WRITE_4(sc, AML_TIMER_E_REG, 0);
X
X	CSR_WRITE_4(sc, AML_TIMER_MUX_REG,
X		    (CSR_READ_4(sc, AML_TIMER_MUX_REG) | AML_TIMER_E_EN));
X
X	/*
X	 * Initialize the mutex prior to installing the interrupt handler
X	 * in case of a spurious interrupt.
X	 */
X	AML_TIMER_LOCK_INIT(sc);
X
X	if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK,
X			   aml8726_hardclock, NULL, sc, &sc->ih_cookie)) {
X		device_printf(dev, "could not setup interrupt handler\n");
X		bus_release_resources(dev, aml8726_timer_spec, sc->res);
X		AML_TIMER_LOCK_DESTROY(sc);
X		return (ENXIO);
X	}
X
X	aml8726_timer_sc = sc;
X
X	sc->et.et_name = "aml8726 timer A";
X	sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
X	sc->et.et_frequency = 1000000;
X	sc->et.et_quality = 1000;
X	sc->et.et_min_period = (0x00000002LLU * SBT_1S) / sc->et.et_frequency;
X	sc->et.et_max_period = (0x0000fffeLLU * SBT_1S) / sc->et.et_frequency;
X	sc->et.et_start = aml8726_timer_start;
X	sc->et.et_stop = aml8726_timer_stop;
X	sc->et.et_priv = sc;
X
X	et_register(&sc->et);
X
X	sc->tc.tc_get_timecount = aml8726_get_timecount;
X	sc->tc.tc_name = "aml8726 timer E";
X	sc->tc.tc_frequency = 1000000;
X	sc->tc.tc_counter_mask = ~0u;
X	sc->tc.tc_quality = 1000;
X	sc->tc.tc_priv = sc;
X
X	tc_init(&sc->tc);
X
X	return (0);
}
X
X
static int
aml8726_timer_detach(device_t dev)
{
X
X	return (EBUSY);
}
X
X
static device_method_t aml8726_timer_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe,		aml8726_timer_probe),
X	DEVMETHOD(device_attach,	aml8726_timer_attach),
X	DEVMETHOD(device_detach,	aml8726_timer_detach),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_timer_driver = {
X	"timer",
X	aml8726_timer_methods,
X	sizeof(struct aml8726_timer_softc),
};
X
static devclass_t aml8726_timer_devclass;
X
EARLY_DRIVER_MODULE(timer, simplebus,
X		    aml8726_timer_driver, aml8726_timer_devclass,
X		    0, 0, BUS_PASS_TIMER);
X
X
void
DELAY(int usec)
{
X	uint32_t counter;
X	uint32_t delta, now, previous, remaining;
X
X	/* Timer has not yet been initialized */
X	if (aml8726_timer_sc == NULL) {
X		for (; usec > 0; usec--)
X			for (counter = 200; counter > 0; counter--) {
X				/* Prevent gcc from optimizing out the loop */
X				cpufunc_nullop();
X			}
X		return;
X	}
X
X	/*
X	 * Some of the other timers in the source tree do this calculation as:
X	 *
X	 *   usec * ((sc->tc.tc_frequency / 1000000) + 1)
X	 *
X	 * which gives a fairly pessimistic result when tc_frequency is an exact
X	 * multiple of 1000000.  Given the data type and typical values for
X	 * tc_frequency adding 999999 shouldn't overflow.
X	 */
X	remaining = usec * ((aml8726_timer_sc->tc.tc_frequency + 999999)
X			    / 1000000);
X
X	/*
X	 * We add one since the first iteration may catch the counter just
X	 * as it is changing.
X	 */
X	remaining += 1;
X
X	previous = aml8726_get_timecount(&aml8726_timer_sc->tc);
X
X	for ( ; ; ) {
X		now = aml8726_get_timecount(&aml8726_timer_sc->tc);
X
X		/*
X		 * If the timer has rolled over, then we have the case:
X		 *
X		 *   if (previous > now) {
X		 *     delta = (0 - previous) + now
X		 *   }
X		 *
X		 * which is really no different then the normal case.
X		 * Both cases are simply:
X		 *
X		 *   delta = now - previous.
X		 */
X		delta = now - previous;
X		
X		if (delta >= remaining)
X			break;
X
X		previous = now;
X		remaining -= delta;
X	}
}
SHAR_EOF
  (set 20 15 01 08 23 17 26 'sys/arm/amlogic/aml8726/aml8726_timer.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_timer.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_timer.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_timer.c': 'MD5 check failed'
       ) << \SHAR_EOF
9a6dd55696c0030ec800dc34dac0ad2b  sys/arm/amlogic/aml8726/aml8726_timer.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_timer.c'` -ne 10833 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_timer.c' is not 10833"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_uart.h ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_uart.h'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_uart.h (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_uart.h (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_uart.h' &&
/*-
X * Copyright 2013-2014 John Wehle <john@feith.com>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD$
X */
X
#ifndef _ARM_AMLOGIC_AML8726_UART_H
#define _ARM_AMLOGIC_AML8726_UART_H
X
X
#define	AML_UART_WFIFO_REG                  0
X
#define AML_UART_RFIFO_REG                  4
X
#define AML_UART_CONTROL_REG                8
#  define AML_UART_CONTROL_TX_INT_EN        (1 << 28)
#  define AML_UART_CONTROL_RX_INT_EN        (1 << 27)
#  define AML_UART_CONTROL_CLR_ERR          (1 << 24)
#  define AML_UART_CONTROL_RX_RST           (1 << 23)
#  define AML_UART_CONTROL_TX_RST           (1 << 22)
#  define AML_UART_CONTROL_DB_MASK          (3 << 20)
#  define AML_UART_CONTROL_8_DB             (0 << 20)
#  define AML_UART_CONTROL_7_DB             (1 << 20)
#  define AML_UART_CONTROL_6_DB             (2 << 20)
#  define AML_UART_CONTROL_5_DB             (3 << 20)
#  define AML_UART_CONTROL_P_MASK           (3 << 18)
#  define AML_UART_CONTROL_P_EN             (1 << 19)
#  define AML_UART_CONTROL_P_EVEN           (0 << 18)
#  define AML_UART_CONTROL_P_ODD            (1 << 18)
#  define AML_UART_CONTROL_SB_MASK          (3 << 16)
#  define AML_UART_CONTROL_1_SB             (0 << 16)
#  define AML_UART_CONTROL_2_SB             (1 << 16)
#  define AML_UART_CONTROL_RX_EN            (1 << 13)
#  define AML_UART_CONTROL_TX_EN            (1 << 12)
#  define AML_UART_CONTROL_BAUD_MASK        0xfff
#  define AML_UART_CONTROL_BAUD_WIDTH       12
X
#define AML_UART_STATUS_REG                 12
#  define AML_UART_STATUS_RECV_BUSY         (1 << 26)
#  define AML_UART_STATUS_XMIT_BUSY         (1 << 25)
#  define AML_UART_STATUS_RX_FIFO_OVERFLOW  (1 << 24)
#  define AML_UART_STATUS_TX_FIFO_EMPTY     (1 << 22)
#  define AML_UART_STATUS_TX_FIFO_FULL      (1 << 21)
#  define AML_UART_STATUS_RX_FIFO_EMPTY     (1 << 20)
#  define AML_UART_STATUS_RX_FIFO_FULL      (1 << 19)
#  define AML_UART_STATUS_TX_FIFO_WRITE_ERR (1 << 18)
#  define AML_UART_STATUS_FRAME_ERR         (1 << 17)
#  define AML_UART_STATUS_PARITY_ERR        (1 << 16)
#  define AML_UART_STATUS_TX_FIFO_CNT_MASK  (0x7f << 8)
#  define AML_UART_STATUS_TX_FIFO_CNT_SHIFT 8
#  define AML_UART_STATUS_RX_FIFO_CNT_MASK  (0x7f << 0)
#  define AML_UART_STATUS_RX_FIFO_CNT_SHIFT 0
X
#define AML_UART_MISC_REG                   16
#  define AML_UART_MISC_OLD_RX_BAUD         (1 << 30)
#  define AML_UART_MISC_BAUD_EXT_MASK       (0xf << 20)
#  define AML_UART_MISC_BAUD_EXT_SHIFT      20
/*
X * The documentation appears to be incorrect as the
X * IRQ is actually generated when TX FIFO count is
X * * equal to * or less than the selected threshold.
X */
#  define AML_UART_MISC_XMIT_IRQ_CNT_MASK   (0xff << 8)
#  define AML_UART_MISC_XMIT_IRQ_CNT_SHIFT  8
/*
X * The documentation appears to be incorrect as the
X * IRQ is actually generated when RX FIFO count is
X * * equal to * or greater than the selected threshold.
X */
#  define AML_UART_MISC_RECV_IRQ_CNT_MASK   0xff
#  define AML_UART_MISC_RECV_IRQ_CNT_SHIFT  0
X
X
#endif /* _ARM_AMLOGIC_AML8726_UART_H */
SHAR_EOF
  (set 20 15 01 27 00 25 54 'sys/arm/amlogic/aml8726/aml8726_uart.h'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_uart.h'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_uart.h failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_uart.h': 'MD5 check failed'
       ) << \SHAR_EOF
cd262f8617e6caf5955a136e9abc73bb  sys/arm/amlogic/aml8726/aml8726_uart.h
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_uart.h'` -ne 4290 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_uart.h' is not 4290"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_uart_console.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_uart_console.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_uart_console.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_uart_console.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_uart_console.c' &&
/*-
X * Copyright 2013-2014 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/cons.h>
#include <sys/consio.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
X
#include <machine/bus.h>
#include <machine/cpu.h>
X
#include <arm/amlogic/aml8726/aml8726_machdep.h>
#include <arm/amlogic/aml8726/aml8726_uart.h>
X
X
#define AML_UART_KVM_BASE        (aml8726_aobus_kva_base + 0x130 * 4)
X
X
static uint32_t
ub_getreg(uint32_t off)
{
X	return *((volatile uint32_t *)(AML_UART_KVM_BASE + off));
}
X
X
static void
ub_setreg(uint32_t off, uint32_t val)
{
X	*((volatile uint32_t *)(AML_UART_KVM_BASE + off)) = val;
}
X
X
static void
uart_cnprobe(struct consdev *cp)
{
X
X	sprintf(cp->cn_name, "uart");
X	cp->cn_pri = CN_REMOTE;
}
X
X
static void
uart_cngrab(struct consdev *cp)
{
X
}
X
X
static void
uart_cnungrab(struct consdev *cp)
{
X
}
X
X
static void
uart_cninit(struct consdev *cp)
{
X	uint32_t cr;
X	uint32_t mr;
X
#ifdef EARLY_PRINTF
X	if (early_putc != NULL) {
X		printf("Early printf yielding control to the real console.\n");
X		early_putc = NULL;
X	}
X
X	/*
X	 * Give pending characters a chance to drain.
X	 */
X	DELAY(4000);
#endif
X
X	cr = ub_getreg(AML_UART_CONTROL_REG);
X	/* Disable all interrupt sources. */
X	cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN);
X	/* Reset the transmitter and receiver. */
X	cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
X	/* Enable the transmitter and receiver. */
X	cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN);
X	ub_setreg(AML_UART_CONTROL_REG, cr);
X
X	/* Clear RX FIFO level for generating interrupts. */
X	mr = ub_getreg(AML_UART_MISC_REG);
X	mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK;
X	ub_setreg(AML_UART_MISC_REG, mr);
X
X	/* Ensure the reset bits are clear. */
X	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
X	ub_setreg(AML_UART_CONTROL_REG, cr);
}
X
X
static void
uart_cnterm(struct consdev * cp)
{
X
}
X
X
static void
uart_cnputc(struct consdev *cp, int c)
{
X
X	while ((ub_getreg(AML_UART_STATUS_REG)
X		& AML_UART_STATUS_TX_FIFO_FULL) != 0)
X		cpu_spinwait();
X
X	ub_setreg(AML_UART_WFIFO_REG, c);
}
X
X
static int
uart_cngetc(struct consdev * cp)
{
X	int c;
X
X	if ((ub_getreg(AML_UART_STATUS_REG)
X	    & AML_UART_STATUS_RX_FIFO_EMPTY) != 0)
X		return (-1);
X
X	c = ub_getreg(AML_UART_RFIFO_REG) & 0xff;
X
X	return (c);
}
X
X
CONSOLE_DRIVER(uart);
X
X
#ifdef EARLY_PRINTF
X
#if !(defined(SOCDEV_PA) && defined(SOCDEV_VA))
# error SOCDEV_PA and SOCDEV_VA must be defined.
#endif
X
static void
eputc(int c)
{
X
X	if (c == '\n')
X		eputc('\r');
X
X	uart_cnputc(NULL, c);
}
X
early_putc_t *early_putc = eputc;
#endif
SHAR_EOF
  (set 20 14 04 09 02 17 14 'sys/arm/amlogic/aml8726/aml8726_uart_console.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_uart_console.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_uart_console.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_uart_console.c': 'MD5 check failed'
       ) << \SHAR_EOF
afd3735784742a84702533676b9f3ddb  sys/arm/amlogic/aml8726/aml8726_uart_console.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_uart_console.c'` -ne 4389 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_uart_console.c' is not 4389"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c' &&
/*-
X * Copyright 2014-2015 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/resource.h>
#include <sys/rman.h>
X
#include <sys/gpio.h>
X
#include <machine/bus.h>
#include <machine/cpu.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
#include <arm/amlogic/aml8726/aml8726_soc.h>
X
#include "gpio_if.h"
X
X
struct aml8726_usb_phy_gpio {
X	device_t	dev;
X	uint32_t	pin;
X	uint32_t	pol;
};
X
struct aml8726_usb_phy_softc {
X	device_t			dev;
X	struct resource			*res[1];
X	uint32_t			npwr_en;
X	struct aml8726_usb_phy_gpio	*pwr_en;
X	boolean_t			force_aca;
X	struct aml8726_usb_phy_gpio	hub_rst;
};
X
static struct resource_spec aml8726_usb_phy_spec[] = {
X	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
X	{ -1, 0 }
};
X
#define AML_USB_PHY_CFG_REG                 0
#  define AML_USB_PHY_CFG_CLK_SEL_32K_ALT   (1 << 15)
#  define AML_USB_PHY_CFG_CLK_DIV_MASK      (0x7f << 4)
#  define AML_USB_PHY_CFG_CLK_DIV_SHIFT     4
#  define AML_USB_PHY_CFG_CLK_SEL_MASK      (7 << 1)
#  define AML_USB_PHY_CFG_CLK_SEL_XTAL      (0 << 1)
#  define AML_USB_PHY_CFG_CLK_SEL_XTAL_DIV2 (1 << 1)
#  define AML_USB_PHY_CFG_CLK_EN            (1 << 0)
X
#define AML_USB_PHY_CTRL_REG                4
#  define AML_USB_PHY_CTRL_FSEL_MASK        (7 << 22)
#  define AML_USB_PHY_CTRL_FSEL_12M         (2 << 22)
#  define AML_USB_PHY_CTRL_FSEL_24M         (5 << 22)
#  define AML_USB_PHY_CTRL_POR              (1 << 15)
#  define AML_USB_PHY_CTRL_CLK_DETECTED     (1 << 8)
X
#define AML_USB_PHY_ADP_BC_REG              12
#  define AML_USB_PHY_ADP_BC_ACA_FLOATING   (1 << 26)
#  define AML_USB_PHY_ADP_BC_ACA_EN         (1 << 16)
X
#define CSR_WRITE_4(sc, reg, val)	bus_write_4((sc)->res[0], reg, (val))
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[0], reg)
#define CSR_BARRIER(sc, reg)		bus_barrier((sc)->res[0], reg, 4, \
X					  (BUS_SPACE_BARRIER_READ         \
X					   | BUS_SPACE_BARRIER_WRITE))
X
#define PIN_ON_FLAG(pol)		((pol) == 0 \
X					 ? GPIO_PIN_LOW : GPIO_PIN_HIGH)
#define PIN_OFF_FLAG(pol)		((pol) == 0 \
X					 ? GPIO_PIN_HIGH : GPIO_PIN_LOW)
X
X
static int
aml8726_usb_phy_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-m6-usb-phy")
X	    && !ofw_bus_is_compatible(dev, "amlogic,aml8726-m8-usb-phy"))
X		return (ENXIO);
X
X	switch (aml8726_soc_hw_rev) {
X	case AML_SOC_HW_REV_M8:
X	case AML_SOC_HW_REV_M8B:
X		device_set_desc(dev, "Amlogic aml8726-m8 USB PHY");
X		break;
X	default:
X		device_set_desc(dev, "Amlogic aml8726-m6 USB PHY");
X		break;
X	}
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_usb_phy_attach(device_t dev)
{
X	struct aml8726_usb_phy_softc *sc = device_get_softc(dev);
X	char *force_aca;
X	int err;
X	int npwr_en;
X	pcell_t *prop;
X	phandle_t node;
X	ssize_t len;
X	uint32_t div;
X	uint32_t i;
X	uint32_t value;
X
X	sc->dev = dev;
X
X	if (bus_alloc_resources(dev, aml8726_usb_phy_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	node = ofw_bus_get_node(dev);
X
X	err = 0;
X
X	len = OF_getencprop_alloc(node, "usb-pwr-en",
X				  3 * sizeof(pcell_t), (void **)&prop);
X	npwr_en = (len > 0) ? len : 0;
X
X	sc->npwr_en = 0;
X	sc->pwr_en = (struct aml8726_usb_phy_gpio *)
X		     malloc(npwr_en * sizeof (*sc->pwr_en), M_DEVBUF, M_WAITOK);
X
X	for (i = 0; i < npwr_en; i++) {
X		sc->pwr_en[i].dev = OF_device_from_xref(prop[i * 3]);
X		sc->pwr_en[i].pin = prop[i * 3 + 1];
X		sc->pwr_en[i].pol = prop[i * 3 + 2];
X
X		if (sc->pwr_en[i].dev == NULL)
X			err = 1;
X	}
X
X	free(prop, M_OFWPROP);
X
X	len = OF_getprop_alloc(node, "force-aca",
X			       sizeof(char), (void **)&force_aca);
X
X	sc->force_aca = FALSE;
X
X	if (len > 0) {
X		if (strncmp(force_aca, "true", len) == 0)
X			sc->force_aca = TRUE;
X	}
X
X	free(force_aca, M_OFWPROP);
X
X	len = OF_getencprop_alloc(node, "usb-hub-rst",
X				  3 * sizeof(pcell_t), (void **)&prop);
X	if (len > 0) {
X		sc->hub_rst.dev = OF_device_from_xref(prop[0]);
X		sc->hub_rst.pin = prop[1];
X		sc->hub_rst.pol = prop[2];
X
X		if (len > 1 || sc->hub_rst.dev == NULL)
X			err = 1;
X	}
X
X	free(prop, M_OFWPROP);
X
X	if (err) {
X		device_printf(dev, "unable to parse gpio\n");
X		goto fail;
X	}
X
X	/* Turn on power by setting pin and then enabling output driver. */
X	for (i = 0; i < npwr_en; i++) {
X		if (GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
X				 PIN_ON_FLAG(sc->pwr_en[i].pol)) != 0
X		    || GPIO_PIN_SETFLAGS(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
X					 GPIO_PIN_OUTPUT) != 0) {
X			device_printf(dev,
X				      "could not use gpio to control power\n");
X			goto fail;
X		}
X
X		sc->npwr_en++;
X	}
X
X	/*
X	 * Configure the clock source and divider.
X	 */
X
X	value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG);
X
X	value &= ~(AML_USB_PHY_CFG_CLK_SEL_32K_ALT
X		   | AML_USB_PHY_CFG_CLK_DIV_MASK
X		   | AML_USB_PHY_CFG_CLK_SEL_MASK
X		   | AML_USB_PHY_CFG_CLK_EN);
X
X	switch (aml8726_soc_hw_rev) {
X	case AML_SOC_HW_REV_M8:
X	case AML_SOC_HW_REV_M8B:
X		value |= AML_USB_PHY_CFG_CLK_SEL_32K_ALT;
X		break;
X	default:
X		div = 2;
X		value |= AML_USB_PHY_CFG_CLK_SEL_XTAL;
X		value |= ((div - 1) << AML_USB_PHY_CFG_CLK_DIV_SHIFT)
X			 & AML_USB_PHY_CFG_CLK_DIV_MASK;
X		value |= AML_USB_PHY_CFG_CLK_EN;
X		break;
X	}
X
X	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
X
X	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);
X
X	/*
X	 * Configure the clock frequency and issue a power on reset.
X	 */
X
X	value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG);
X
X	value &= ~AML_USB_PHY_CTRL_FSEL_MASK;
X
X	switch (aml8726_soc_hw_rev) {
X	case AML_SOC_HW_REV_M8:
X	case AML_SOC_HW_REV_M8B:
X		value |= AML_USB_PHY_CTRL_FSEL_24M;
X		break;
X	default:
X		value |= AML_USB_PHY_CTRL_FSEL_12M;
X		break;
X	}
X
X	value |= AML_USB_PHY_CTRL_POR;
X
X	CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value);
X
X	CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG);
X
X	DELAY(500);
X
X	/*
X	 * Enable by clearing the power on reset.
X	 */
X
X	value &= ~AML_USB_PHY_CTRL_POR;
X
X	CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value);
X
X	CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG);
X
X	DELAY(1000);
X
X	/*
X	 * Check if the clock was detected.
X	 */
X	value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG);
X	if ((value & AML_USB_PHY_CTRL_CLK_DETECTED) == 0)
X		device_printf(dev, "PHY Clock not detected\n");
X
X	/*
X	 * If necessary enabled Accessory Charger Adaptor detection
X	 * so that the port knows what mode to operate in.
X	 */
X	if (sc->force_aca) {
X		value = CSR_READ_4(sc, AML_USB_PHY_ADP_BC_REG);
X
X		value |= AML_USB_PHY_ADP_BC_ACA_EN;
X
X		CSR_WRITE_4(sc, AML_USB_PHY_ADP_BC_REG, value);
X
X		CSR_BARRIER(sc, AML_USB_PHY_ADP_BC_REG);
X
X		DELAY(50);
X
X		value = CSR_READ_4(sc, AML_USB_PHY_ADP_BC_REG);
X
X		if ((value & AML_USB_PHY_ADP_BC_ACA_FLOATING) != 0) {
X			device_printf(dev,
X				      "force-aca requires newer silicon\n");
X			goto fail;
X		}
X	}
X
X	/*
X	 * Reset the hub.
X	 */
X	if (sc->hub_rst.dev != NULL) {
X		err = 0;
X
X		if (GPIO_PIN_SET(sc->hub_rst.dev, sc->hub_rst.pin,
X				 PIN_ON_FLAG(sc->hub_rst.pol)) != 0
X		    || GPIO_PIN_SETFLAGS(sc->hub_rst.dev, sc->hub_rst.pin,
X					 GPIO_PIN_OUTPUT) != 0)
X			err = 1;
X
X		DELAY(30);
X
X		if (GPIO_PIN_SET(sc->hub_rst.dev, sc->hub_rst.pin,
X				 PIN_OFF_FLAG(sc->hub_rst.pol)) != 0)
X			err = 1;
X
X		DELAY(60000);
X
X		if (err) {
X			device_printf(dev,
X				      "could not use gpio to reset hub\n");
X			goto fail;
X		}
X	}
X
X	return (0);
X
fail:
X	/* In the event of problems attempt to turn things back off. */
X	i = sc->npwr_en;
X	while (i-- != 0) {
X		(void)GPIO_PIN_SET(sc->pwr_en[i].dev,
X				   sc->pwr_en[i].pin,
X				   PIN_OFF_FLAG(sc->pwr_en[i].pol));
X	}
X
X	free (sc->pwr_en, M_DEVBUF);
X	sc->pwr_en = NULL;
X
X	bus_release_resources(dev, aml8726_usb_phy_spec, sc->res);
X
X	return (ENXIO);
}
X
X
static int
aml8726_usb_phy_detach(device_t dev)
{
X	struct aml8726_usb_phy_softc *sc = device_get_softc(dev);
X	uint32_t i;
X	uint32_t value;
X
X	/*
X	 * Disable by issuing a power on reset.
X	 */
X
X	value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG);
X
X	value |= AML_USB_PHY_CTRL_POR;
X
X	CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value);
X
X	CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG);
X
X	/* Turn off power */
X	i = sc->npwr_en;
X	while (i-- != 0) {
X		(void)GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
X				   PIN_OFF_FLAG(sc->pwr_en[i].pol));
X	}
X	free (sc->pwr_en, M_DEVBUF);
X	sc->pwr_en = NULL;
X
X	bus_release_resources(dev, aml8726_usb_phy_spec, sc->res);
X
X	return (0);
}
X
X
static device_method_t aml8726_usb_phy_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe, 	aml8726_usb_phy_probe),
X	DEVMETHOD(device_attach, 	aml8726_usb_phy_attach),
X	DEVMETHOD(device_detach, 	aml8726_usb_phy_detach),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_usb_phy_driver = {
X	"usbphy",
X	aml8726_usb_phy_methods,
X	sizeof(struct aml8726_usb_phy_softc),
};
X
static devclass_t aml8726_usb_phy_devclass;
X
DRIVER_MODULE(aml8726_m6usbphy, simplebus, aml8726_usb_phy_driver, aml8726_usb_phy_devclass, 0, 0);
MODULE_DEPEND(aml8726_m6usbphy, aml8726_gpio, 1, 1, 1);
SHAR_EOF
  (set 20 15 01 30 22 54 58 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c': 'MD5 check failed'
       ) << \SHAR_EOF
57e80d4af71a7caa4e55e6ce28f786bd  sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c'` -ne 10407 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c' is not 10407"
  fi
fi
# ============= sys/arm/amlogic/aml8726/aml8726_wdt.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/aml8726_wdt.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/aml8726_wdt.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/aml8726_wdt.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/aml8726_wdt.c' &&
/*-
X * Copyright 2013-2015 John Wehle <john@feith.com>
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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
X
#include <sys/watchdog.h>
X
#include <machine/bus.h>
#include <machine/cpufunc.h>
X
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
X
#include <arm/amlogic/aml8726/aml8726_soc.h>
X
X
struct aml8726_wdt_softc {
X	device_t		dev;
X	struct resource	*	res[2];
X	struct mtx		mtx;
X	void *			ih_cookie;
};
X
static struct resource_spec aml8726_wdt_spec[] = {
X	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
X	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
X	{ -1, 0 }
};
X
static struct {
X	uint32_t ctrl_cpu_mask;
X	uint32_t ctrl_en;
X	uint32_t term_cnt_mask;
X	uint32_t reset_cnt_mask;
} aml8726_wdt_soc_params;
X
/*
X * devclass_get_device / device_get_softc could be used
X * to dynamically locate this, however the wdt is a
X * required device which can't be unloaded so there's
X * no need for the overhead.
X */
static struct aml8726_wdt_softc *aml8726_wdt_sc = NULL;
X
#define AML_WDT_LOCK(sc)		mtx_lock_spin(&(sc)->mtx)
#define AML_WDT_UNLOCK(sc)		mtx_unlock_spin(&(sc)->mtx)
#define AML_WDT_LOCK_INIT(sc) \
X	mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
X	    "wdt", MTX_SPIN)
#define AML_WDT_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->mtx);
X
#define AML_WDT_CTRL_REG                  0
#  define AML_WDT_CTRL_CPU_WDRESET_MASK   aml8726_wdt_soc_params.ctrl_cpu_mask
#  define AML_WDT_CTRL_CPU_WDRESET_SHIFT  24
#  define AML_WDT_CTRL_IRQ_EN             (1 << 23)
#  define AML_WDT_CTRL_EN                 aml8726_wdt_soc_params.ctrl_en
#  define AML_WDT_CTRL_TERMINAL_CNT_MASK  aml8726_wdt_soc_params.term_cnt_mask
#  define AML_WDT_CTRL_TERMINAL_CNT_SHIFT 0
#define AML_WDT_RESET_REG                 4
#  define AML_WDT_RESET_CNT_MASK          aml8726_wdt_soc_params.reset_cnt_mask
#  define AML_WDT_RESET_CNT_SHIFT         0
X
#define CSR_WRITE_4(sc, reg, val)	bus_write_4((sc)->res[0], reg, (val))
#define CSR_READ_4(sc, reg)		bus_read_4((sc)->res[0], reg)
#define CSR_BARRIER(sc, reg)		bus_barrier((sc)->res[0], reg, 4, \
X					  (BUS_SPACE_BARRIER_READ         \
X					   | BUS_SPACE_BARRIER_WRITE))
X
X
static void
aml8726_wdt_watchdog(void *private, u_int cmd, int *error)
{
X	struct aml8726_wdt_softc *sc = (struct aml8726_wdt_softc *)private;
X	uint32_t wcr;
X	uint64_t tens_of_usec;
X
X	AML_WDT_LOCK(sc);
X
X	tens_of_usec = (((uint64_t)1 << (cmd & WD_INTERVAL)) + 9999) / 10000;
X
X	if (cmd != 0 && tens_of_usec <= (AML_WDT_CTRL_TERMINAL_CNT_MASK
X					 >> AML_WDT_CTRL_TERMINAL_CNT_SHIFT)) {
X
X		wcr = AML_WDT_CTRL_CPU_WDRESET_MASK
X		      | AML_WDT_CTRL_EN
X		      | ((uint32_t)tens_of_usec
X			 << AML_WDT_CTRL_TERMINAL_CNT_SHIFT);
X
X		CSR_WRITE_4(sc, AML_WDT_RESET_REG, 0);
X		CSR_WRITE_4(sc, AML_WDT_CTRL_REG, wcr);
X
X		*error = 0;
X	} else
X		CSR_WRITE_4(sc, AML_WDT_CTRL_REG,
X			    (CSR_READ_4(sc, AML_WDT_CTRL_REG)
X			     & ~(AML_WDT_CTRL_IRQ_EN | AML_WDT_CTRL_EN)));
X
X	AML_WDT_UNLOCK(sc);
}
X
X
static int
aml8726_wdt_intr(void *arg)
{
X	struct aml8726_wdt_softc *sc = (struct aml8726_wdt_softc *)arg;
X
X	/*
X	 * Normally a timeout causes a hardware reset, however
X	 * the watchdog timer can be configured to cause an
X	 * interrupt instead by setting AML_WDT_CTRL_IRQ_EN
X	 * and clearing AML_WDT_CTRL_CPU_WDRESET_MASK.
X	 */
X
X	AML_WDT_LOCK(sc);
X
X	CSR_WRITE_4(sc, AML_WDT_CTRL_REG,
X		    (CSR_READ_4(sc, AML_WDT_CTRL_REG)
X		     & ~(AML_WDT_CTRL_IRQ_EN | AML_WDT_CTRL_EN)));
X
X	CSR_BARRIER(sc, AML_WDT_CTRL_REG);
X
X	AML_WDT_UNLOCK(sc);
X
X	device_printf(sc->dev, "timeout expired\n");
X
X	return (FILTER_HANDLED);
}
X
X
static int
aml8726_wdt_probe(device_t dev)
{
X
X	if (!ofw_bus_status_okay(dev))
X		return (ENXIO);
X
X	if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-wdt"))
X		return (ENXIO);
X
X	device_set_desc(dev, "Amlogic aml8726 WDT");
X
X	return (BUS_PROBE_DEFAULT);
}
X
X
static int
aml8726_wdt_attach(device_t dev)
{
X	struct aml8726_wdt_softc *sc = device_get_softc(dev);
X
X	/* There should be exactly one instance. */
X	if (aml8726_wdt_sc != NULL)
X		return (ENXIO);
X
X	sc->dev = dev;
X
X	if (bus_alloc_resources(dev, aml8726_wdt_spec, sc->res)) {
X		device_printf(dev, "could not allocate resources for device\n");
X		return (ENXIO);
X	}
X
X	/*
X	 * Certain bitfields are dependant on the hardware revision.
X	 */
X	switch (aml8726_soc_hw_rev) {
X	case AML_SOC_HW_REV_M8:
X		aml8726_wdt_soc_params.ctrl_cpu_mask
X			= 0xf << AML_WDT_CTRL_CPU_WDRESET_SHIFT;
X		switch (aml8726_soc_metal_rev) {
X		case AML_SOC_M8_METAL_REV_M2_A:
X			aml8726_wdt_soc_params.ctrl_en = 1 << 19;
X			aml8726_wdt_soc_params.term_cnt_mask
X				= 0x07ffff << AML_WDT_CTRL_TERMINAL_CNT_SHIFT;
X			aml8726_wdt_soc_params.reset_cnt_mask
X				= 0x07ffff << AML_WDT_RESET_CNT_SHIFT;
X			break;
X		default:
X			aml8726_wdt_soc_params.ctrl_en = 1 << 22;
X			aml8726_wdt_soc_params.term_cnt_mask
X				= 0x3fffff << AML_WDT_CTRL_TERMINAL_CNT_SHIFT;
X			aml8726_wdt_soc_params.reset_cnt_mask
X				= 0x3fffff << AML_WDT_RESET_CNT_SHIFT;
X			break;
X		}
X		break;
X	case AML_SOC_HW_REV_M8B:
X		aml8726_wdt_soc_params.ctrl_cpu_mask
X			= 0xf << AML_WDT_CTRL_CPU_WDRESET_SHIFT;
X		aml8726_wdt_soc_params.ctrl_en = 1 << 19;
X		aml8726_wdt_soc_params.term_cnt_mask
X				= 0x07ffff << AML_WDT_CTRL_TERMINAL_CNT_SHIFT;
X		aml8726_wdt_soc_params.reset_cnt_mask
X				= 0x07ffff << AML_WDT_RESET_CNT_SHIFT;
X		break;
X	default:
X		aml8726_wdt_soc_params.ctrl_cpu_mask
X			= 3 << AML_WDT_CTRL_CPU_WDRESET_SHIFT;
X		aml8726_wdt_soc_params.ctrl_en = 1 << 22;
X		aml8726_wdt_soc_params.term_cnt_mask
X			= 0x3fffff << AML_WDT_CTRL_TERMINAL_CNT_SHIFT;
X		aml8726_wdt_soc_params.reset_cnt_mask
X			= 0x3fffff << AML_WDT_RESET_CNT_SHIFT;
X		break;
X	}
X
X	/*
X	 * Disable the watchdog.
X	 */
X	CSR_WRITE_4(sc, AML_WDT_CTRL_REG,
X		    (CSR_READ_4(sc, AML_WDT_CTRL_REG)
X		     & ~(AML_WDT_CTRL_IRQ_EN | AML_WDT_CTRL_EN)));
X
X	/*
X	 * Initialize the mutex prior to installing the interrupt handler
X	 * in case of a spurious interrupt.
X	 */
X	AML_WDT_LOCK_INIT(sc);
X
X	if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
X			   aml8726_wdt_intr, NULL, sc, &sc->ih_cookie)) {
X		device_printf(dev, "could not setup interrupt handler\n");
X		bus_release_resources(dev, aml8726_wdt_spec, sc->res);
X		AML_WDT_LOCK_DESTROY(sc);
X		return (ENXIO);
X	}
X
X	aml8726_wdt_sc = sc;
X
X	EVENTHANDLER_REGISTER(watchdog_list, aml8726_wdt_watchdog, sc, 0);
X
X	return (0);
}
X
X
static int
aml8726_wdt_detach(device_t dev)
{
X
X	return (EBUSY);
}
X
X
static device_method_t aml8726_wdt_methods[] = {
X	/* Device interface */
X	DEVMETHOD(device_probe,		aml8726_wdt_probe),
X	DEVMETHOD(device_attach,	aml8726_wdt_attach),
X	DEVMETHOD(device_detach,	aml8726_wdt_detach),
X
X	DEVMETHOD_END
};
X
static driver_t aml8726_wdt_driver = {
X	"wdt",
X	aml8726_wdt_methods,
X	sizeof(struct aml8726_wdt_softc),
};
X
static devclass_t aml8726_wdt_devclass;
X
EARLY_DRIVER_MODULE(wdt, simplebus,
X		    aml8726_wdt_driver, aml8726_wdt_devclass,
X		    0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
X
X
void
cpu_reset()
{
X
X	/* Watchdog has not yet been initialized */
X	if (aml8726_wdt_sc == NULL)
X		printf("Reset hardware has not yet been initialized.\n");
X	else {
X		CSR_WRITE_4(aml8726_wdt_sc, AML_WDT_RESET_REG, 0);
X		CSR_WRITE_4(aml8726_wdt_sc, AML_WDT_CTRL_REG,
X			    (AML_WDT_CTRL_CPU_WDRESET_MASK
X			     | AML_WDT_CTRL_EN
X			     | (10 << AML_WDT_CTRL_TERMINAL_CNT_SHIFT)));
X	}
X
X	while (1);
}
SHAR_EOF
  (set 20 15 01 27 01 36 54 'sys/arm/amlogic/aml8726/aml8726_wdt.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/aml8726_wdt.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/aml8726_wdt.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/aml8726_wdt.c': 'MD5 check failed'
       ) << \SHAR_EOF
54b23d50f3a8b957b0b9a3bca2560a83  sys/arm/amlogic/aml8726/aml8726_wdt.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/aml8726_wdt.c'` -ne 8749 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/aml8726_wdt.c' is not 8749"
  fi
fi
# ============= sys/arm/amlogic/aml8726/files.aml8726 ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/files.aml8726'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/files.aml8726 (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/files.aml8726 (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/files.aml8726' &&
#$FreeBSD$
X
kern/kern_clocksource.c				standard
X
arm/arm/bus_space_base.c			standard
arm/arm/bus_space_generic.c			standard
arm/arm/bus_space_asm_generic.S			standard
arm/arm/cpufunc_asm_armv5.S			standard
arm/arm/cpufunc_asm_arm11.S			standard
arm/arm/cpufunc_asm_armv7.S			standard
X
arm/arm/pl310.c					standard
arm/amlogic/aml8726/aml8726_l2cache.c		standard
X
arm/amlogic/aml8726/aml8726_machdep.c		standard
arm/amlogic/aml8726/aml8726_identsoc.c		standard
arm/amlogic/aml8726/aml8726_clkmsr.c		standard
arm/amlogic/aml8726/aml8726_pic.c		standard
arm/amlogic/aml8726/aml8726_rtc.c		standard
arm/amlogic/aml8726/aml8726_timer.c		standard
arm/amlogic/aml8726/aml8726_wdt.c		standard
X
# serial console for debugging early boot code
#arm/amlogic/aml8726/aml8726_uart_console.c	standard
X
arm/amlogic/aml8726/aml8726_fb.c		optional	vt
arm/amlogic/aml8726/aml8726_gpio.c		optional	gpio
#arm/amlogic/aml8726/aml8726_i2c.c		optional	iicbus
arm/amlogic/aml8726/aml8726_mmc.c		optional	mmc gpio
arm/amlogic/aml8726/aml8726_rng.c		optional	random
arm/amlogic/aml8726/uart_dev_aml8726.c		optional	uart
#arm/amlogic/aml8726/aml8726_usb_phy-m3.c	optional	dwcotg usb gpio
arm/amlogic/aml8726/aml8726_usb_phy-m6.c	optional	dwcotg usb gpio
X
dev/dwc/if_dwc.c				optional	dwc
SHAR_EOF
  (set 20 15 02 01 17 35 33 'sys/arm/amlogic/aml8726/files.aml8726'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/files.aml8726'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/files.aml8726 failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/files.aml8726': 'MD5 check failed'
       ) << \SHAR_EOF
9058db7c10868e7706f9f89a64683c60  sys/arm/amlogic/aml8726/files.aml8726
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/files.aml8726'` -ne 1260 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/files.aml8726' is not 1260"
  fi
fi
# ============= sys/arm/amlogic/aml8726/files.smp ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/files.smp'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/files.smp (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/files.smp (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/files.smp' &&
#$FreeBSD$
X
arm/arm/gic.c					standard
arm/amlogic/aml8726/aml8726_mp.c		standard
SHAR_EOF
  (set 20 15 01 11 23 06 21 'sys/arm/amlogic/aml8726/files.smp'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/files.smp'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/files.smp failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/files.smp': 'MD5 check failed'
       ) << \SHAR_EOF
7bce7bea551c79b1fd8b529c7fa168ae  sys/arm/amlogic/aml8726/files.smp
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/files.smp'` -ne 82 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/files.smp' is not 82"
  fi
fi
# ============= sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh' &&
#!/bin/sh
X
BL1=bl1.bin.hardkernel
UBOOT=u-boot.bin
X
if [ -z $1 ]; then
X        echo "usage ./sd_freebsd.sh <SD card reader's device file>"
X        exit 0
fi
X
if [ ! -f $BL1 ]; then
X        echo "Error: $BL1 does not exist."
X        exit 0
fi
X
if [ ! -f $UBOOT ]; then
X        echo "Error: $UBOOT does not exist."
X        exit 0
fi
X
# Write BL1 / MBR
dd if=$BL1 of=$1 bs=512
# Write U-boot
dd if=$UBOOT of=$1 bs=512 seek=64 conv=sync
# Zero out U-boot Environment 
dd if=/dev/zero of=$1 bs=512 seek=1024 count=64
X
# Create MBR GEOM
gpart create -s mbr `basename $1`
# Add MSDOS partition to contain kernel.bin
gpart add -t fat16 -b 1134 -s 64M `basename $1`
# Add FreeBSD partition
gpart add -t freebsd -b 132174 `basename $1`
X
# Creating the MBR GEOM may have cleared the
# MBR bootcode in block zero so refresh it.
dd if=$BL1 bs=512 count=1 of=bl1-mbr.tmp
gpart bootcode -b bl1-mbr.tmp `basename $1`
rm -f bl1-mbr.tmp
X
# Format filesystems
newfs_msdos -F 16 ${1}s1
newfs ${1}s2
X
echo "Successfully partitioned and wrote boot code to $1"
SHAR_EOF
  (set 20 15 02 01 00 56 08 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh'
   eval "${shar_touch}") && \
  chmod 0744 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh': 'MD5 check failed'
       ) << \SHAR_EOF
ea983939d2569d176845df70251eb8b4  sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh'` -ne 1038 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/sd_freebsd_odroidc1.sh' is not 1038"
  fi
fi
# ============= sys/arm/amlogic/aml8726/std.aml8726 ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/std.aml8726'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/std.aml8726 (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/std.aml8726 (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/std.aml8726' &&
# $FreeBSD$
X
cpu		CPU_CORTEXA
machine		arm armv6
makeoptions	CONF_CFLAGS="-march=armv7a"
X
files		"../amlogic/aml8726/files.aml8726"
X
options		ARM_L2_PIPT
X
# Set all global interrupts to be edge triggered, active high.
options		GIC_DEFAULT_ICFGR_INIT=0xffffffff
X
options		IPI_IRQ_START=0
options		IPI_IRQ_END=15
X
#options 	EARLY_PRINTF
#options  	SOCDEV_PA=0xc8100000
#options 	SOCDEV_VA=0xd8100000
SHAR_EOF
  (set 20 15 01 31 22 33 24 'sys/arm/amlogic/aml8726/std.aml8726'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/std.aml8726'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/std.aml8726 failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/std.aml8726': 'MD5 check failed'
       ) << \SHAR_EOF
b1e78e25e579de09bafa7fab6f449200  sys/arm/amlogic/aml8726/std.aml8726
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/std.aml8726'` -ne 398 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/std.aml8726' is not 398"
  fi
fi
# ============= sys/arm/amlogic/aml8726/std.odroidc1 ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/std.odroidc1'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/std.odroidc1 (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/std.odroidc1 (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/std.odroidc1' &&
# $FreeBSD$
X
include	"../amlogic/aml8726/std.aml8726"
X
makeoptions     FDT_DTS_FILE=odroidc1.dts
X
options 	SMP				# Enable multiple cores
files		"../amlogic/aml8726/files.smp"
X
# Physical memory starts at 0x00000000.  We assume the kernel is loaded
# at 0x00100000 by u-boot (which doesn't support ubldr since it's missing
# CONFIG_API).  The kernel must be supplied as a binary since u-boot is
# also missing CONFIG_CMD_ELF.
#
#
options		KERNVIRTADDR=0xc0100000         # Used in ldscript.arm
makeoptions	KERNVIRTADDR=0xc0100000
SHAR_EOF
  (set 20 15 01 13 00 29 22 'sys/arm/amlogic/aml8726/std.odroidc1'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/std.odroidc1'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/std.odroidc1 failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/std.odroidc1': 'MD5 check failed'
       ) << \SHAR_EOF
2cd2a2e81baf9d719c04129a35a18929  sys/arm/amlogic/aml8726/std.odroidc1
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/std.odroidc1'` -ne 530 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/std.odroidc1' is not 530"
  fi
fi
# ============= sys/arm/amlogic/aml8726/std.vsatv102-m6 ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/std.vsatv102-m6'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/std.vsatv102-m6 (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/std.vsatv102-m6 (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/std.vsatv102-m6' &&
# $FreeBSD$
X
include	"../amlogic/aml8726/std.aml8726"
X
makeoptions     FDT_DTS_FILE=vsatv102-m6.dts
X
options 	SMP				# Enable multiple cores
files		"../amlogic/aml8726/files.smp"
X
# Physical memory starts at 0x80000000.  We assume the kernel is loaded
# at 0x80100000 by u-boot (which doesn't support ubldr since it's missing
# CONFIG_API).  The kernel must be supplied as a binary since u-boot is
# also missing CONFIG_CMD_ELF.
#
#
options		KERNVIRTADDR=0xc0100000         # Used in ldscript.arm
makeoptions	KERNVIRTADDR=0xc0100000
SHAR_EOF
  (set 20 15 01 11 23 13 30 'sys/arm/amlogic/aml8726/std.vsatv102-m6'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/std.vsatv102-m6'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/std.vsatv102-m6 failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/std.vsatv102-m6': 'MD5 check failed'
       ) << \SHAR_EOF
56e580601bca10751e1fe18b6e3ded7f  sys/arm/amlogic/aml8726/std.vsatv102-m6
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/std.vsatv102-m6'` -ne 533 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/std.vsatv102-m6' is not 533"
  fi
fi
# ============= sys/arm/amlogic/aml8726/uart_dev_aml8726.c ==============
if test -n "${keep_file}" && test -f 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c'
then
${echo} "x - SKIPPING sys/arm/amlogic/aml8726/uart_dev_aml8726.c (file already exists)"

else
${echo} "x - extracting sys/arm/amlogic/aml8726/uart_dev_aml8726.c (text)"
  sed 's/^X//' << 'SHAR_EOF' > 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c' &&
/*-
X * Copyright 2013-2014 John Wehle <john@feith.com>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
/*
X * Amlogic aml8726 UART driver.
X *
X * The current implementation only targets features common to all
X * uarts.  For example ... though the aml8726-m3 has RTS / CTS, the
X * aml8726-mx doesn't.  Likewise though UART A as a 128 byte FIFO,
X * the others only have a 64 byte FIFO.
X *
X * Also, it's assumed that register 5 (the new baud rate register
X * present on the aml8726-mx) has not been activated.
X */
X
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
X
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
X
#include <machine/bus.h>
#include <machine/cpu.h>
X
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
X
#include <arm/amlogic/aml8726/aml8726_uart.h>
X
#include "uart_if.h"
X
X
#undef uart_getreg
#undef uart_setreg
X
#define	uart_getreg(bas, reg)		\
X	bus_space_read_4((bas)->bst, (bas)->bsh, reg)
#define	uart_setreg(bas, reg, value)	\
X	bus_space_write_4((bas)->bst, (bas)->bsh, reg, value)
X
#define SIGCHG(c, i, s, d)				\
X	do {						\
X		if (c) {				\
X			i |= (i & s) ? s : s | d;	\
X		} else {				\
X			i = (i & s) ? (i & ~s) | d : i;	\
X		}					\
X	} while (0)
X
X
static int
aml8726_uart_divisor(int rclk, int baudrate)
{
X	int actual_baud, divisor;
X	int error;
X
X	if (baudrate == 0)
X		return (0);
X
X	/* integer version of (rclk / baudrate + .5) */
X	divisor = ((rclk << 1) + baudrate) / (baudrate << 1);
X	if (divisor == 0 || divisor >= 65536)
X		return (0);
X	actual_baud = rclk / divisor;
X
X	/* 10 times error in percent: */
X	error = (((actual_baud - baudrate) * 2000) / baudrate + 1) >> 1;
X
X	/* 3.0% maximum error tolerance: */
X	if (error < -30 || error > 30)
X		return (0);
X
X	return (divisor);
}
X
X
static int
aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
X    int parity)
{
X	uint32_t cr;
X	uint32_t mr;
X	int divisor;
X
X	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X
X	cr &= ~(AML_UART_CONTROL_DB_MASK | AML_UART_CONTROL_SB_MASK
X		| AML_UART_CONTROL_P_MASK);
X
X	switch (databits) {
X	case 5:		cr |= AML_UART_CONTROL_5_DB; break;
X	case 6:		cr |= AML_UART_CONTROL_6_DB; break;
X	case 7:		cr |= AML_UART_CONTROL_7_DB; break;
X	case 8:		cr |= AML_UART_CONTROL_8_DB; break;
X	default:	return (EINVAL);
X	}
X
X	switch (stopbits) {
X	case 1:		cr |= AML_UART_CONTROL_1_SB; break;
X	case 2:		cr |= AML_UART_CONTROL_2_SB; break;
X	default:	return (EINVAL);
X	}
X
X	switch (parity) {
X	case UART_PARITY_EVEN:	cr |= AML_UART_CONTROL_P_EVEN;
X				cr |= AML_UART_CONTROL_P_EN;
X				break;
X
X	case UART_PARITY_ODD:	cr |= AML_UART_CONTROL_P_ODD;
X				cr |= AML_UART_CONTROL_P_EN;
X				break;
X
X	case UART_PARITY_NONE:	break;
X
X	default:	return (EINVAL);
X	}
X
X	/* Set baudrate. */
X	if (baudrate > 0 && bas->rclk != 0) {
X		divisor = aml8726_uart_divisor(bas->rclk / 4, baudrate) - 1;
X		if (divisor > 0xffff)
X			return (EINVAL);
X
X		cr &= ~AML_UART_CONTROL_BAUD_MASK;
X		cr |= (divisor & AML_UART_CONTROL_BAUD_MASK);
X
X		divisor >>= AML_UART_CONTROL_BAUD_WIDTH;
X
X		mr = uart_getreg(bas, AML_UART_MISC_REG);
X		mr &= ~(AML_UART_MISC_OLD_RX_BAUD
X			| AML_UART_MISC_BAUD_EXT_MASK);
X		mr |= ((divisor << AML_UART_MISC_BAUD_EXT_SHIFT)
X		       & AML_UART_MISC_BAUD_EXT_MASK);
X		uart_setreg(bas, AML_UART_MISC_REG, mr);
X	}
X
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	return (0);
}
X
X
/*
X * Low-level UART interface.
X */
X
static int
aml8726_uart_probe(struct uart_bas *bas)
{
X
X	return (0);
}
X
X
static void
aml8726_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
X    int parity)
{
X	uint32_t cr;
X	uint32_t mr;
X
X	aml8726_uart_param(bas, baudrate, databits, stopbits, parity);
X
X	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X	/* Disable all interrupt sources. */
X	cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN);
X	/* Reset the transmitter and receiver. */
X	cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
X	/* Enable the transmitter and receiver. */
X	cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN);
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	/* Clear RX FIFO level for generating interrupts. */
X	mr = uart_getreg(bas, AML_UART_MISC_REG);
X	mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK;
X	uart_setreg(bas, AML_UART_MISC_REG, mr);
X	uart_barrier(bas);
X
X	/* Ensure the reset bits are clear. */
X	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
}
X
X
static void
aml8726_uart_term(struct uart_bas *bas)
{
X
}
X
X
static void
aml8726_uart_putc(struct uart_bas *bas, int c)
{
X
X	while ((uart_getreg(bas, AML_UART_STATUS_REG)
X		& AML_UART_STATUS_TX_FIFO_FULL) != 0)
X		cpu_spinwait();
X
X	uart_setreg(bas, AML_UART_WFIFO_REG, c);
X	uart_barrier(bas);
}
X
X
static int
aml8726_uart_rxready(struct uart_bas *bas)
{
X
X	return ((uart_getreg(bas, AML_UART_STATUS_REG)
X		 & AML_UART_STATUS_RX_FIFO_EMPTY) == 0 ? 1 : 0);
}
X
X
static int
aml8726_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
X	int c;
X
X	uart_lock(hwmtx);
X
X	while ((uart_getreg(bas, AML_UART_STATUS_REG)
X		& AML_UART_STATUS_RX_FIFO_EMPTY) != 0) {
X		uart_unlock(hwmtx);
X		DELAY(4);
X		uart_lock(hwmtx);
X	}
X
X	c = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff;
X
X	uart_unlock(hwmtx);
X
X	return (c);
}
X
X
struct uart_ops aml8726_uart_ops = {
X	.probe = aml8726_uart_probe,
X	.init = aml8726_uart_init,
X	.term = aml8726_uart_term,
X	.putc = aml8726_uart_putc,
X	.rxready = aml8726_uart_rxready,
X	.getc = aml8726_uart_getc,
};
X
X
static int
aml8726_uart_bus_probe(struct uart_softc *sc)
{
X	int error;
X
X	error = aml8726_uart_probe(&sc->sc_bas);
X	if (error)
X		return (error);
X
X	sc->sc_rxfifosz = 64;
X	sc->sc_txfifosz = 64;
X	sc->sc_hwiflow = 0;
X	sc->sc_hwoflow = 0;
X
X	device_set_desc(sc->sc_dev, "Amlogic aml8726 UART");
X
X	return (0);
}
X
X
static int
aml8726_uart_bus_getsig(struct uart_softc *sc)
{
X	uint32_t new, old, sig;
X
X	/*
X	 * Treat DSR, DCD, and CTS as always on.
X	 */
X
X	do {
X		old = sc->sc_hwsig;
X		sig = old;
X		SIGCHG(1, sig, SER_DSR, SER_DDSR);
X		SIGCHG(1, sig, SER_DCD, SER_DDCD);
X		SIGCHG(1, sig, SER_CTS, SER_DCTS);
X		new = sig & ~SER_MASK_DELTA;
X	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
X
X	return (sig);
}
X
X
static int
aml8726_uart_bus_setsig(struct uart_softc *sc, int sig)
{
X	uint32_t new, old;
X
X	do {
X		old = sc->sc_hwsig;
X		new = old;
X		if (sig & SER_DDTR) {
X			SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR);
X		}
X		if (sig & SER_DRTS) {
X			SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS);
X		}
X	 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
X
X	return (0);
}
X
X
static int
aml8726_uart_bus_attach(struct uart_softc *sc)
{
X	struct uart_bas *bas;
X	uint32_t cr;
X	uint32_t mr;
X
X	bas = &sc->sc_bas;
X
X	if (bas->rclk == 0) {
X		device_printf(sc->sc_dev, "missing clock attribute in FDT\n");
X		return (ENXIO);
X	}
X
X	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X	/* Disable all interrupt sources. */
X	cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN);
X	/* Ensure the reset bits are clear. */
X	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
X
X	/*
X	 * Reset the transmitter and receiver only if not acting as a
X	 * console, otherwise it means that:
X	 *
X	 * 1) aml8726_uart_init was already called which did the reset
X	 *
X	 * 2) there may be console bytes sitting in the transmit fifo
X	 */
X	if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE)
X		;
X	else
X		cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
X
X	/* Enable the transmitter and receiver. */
X	cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN);
X	/* Reset error bits. */
X	cr |= AML_UART_CONTROL_CLR_ERR;
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	/* Set FIFO levels for generating interrupts. */
X	mr = uart_getreg(bas, AML_UART_MISC_REG);
X	mr &= ~AML_UART_MISC_XMIT_IRQ_CNT_MASK;
X	mr |= (0 << AML_UART_MISC_XMIT_IRQ_CNT_SHIFT);
X	mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK;
X	mr |= (1 << AML_UART_MISC_RECV_IRQ_CNT_SHIFT);
X	uart_setreg(bas, AML_UART_MISC_REG, mr);
X	uart_barrier(bas);
X
X	aml8726_uart_bus_getsig(sc);
X
X	/* Ensure the reset bits are clear. */
X	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
X	cr &= ~AML_UART_CONTROL_CLR_ERR;
X	/* Enable the receive interrupt. */
X	cr |= AML_UART_CONTROL_RX_INT_EN;
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	return (0);
}
X
static int
aml8726_uart_bus_detach(struct uart_softc *sc)
{
X	struct uart_bas *bas;
X	uint32_t cr;
X	uint32_t mr;
X
X	bas = &sc->sc_bas;
X
X	/* Disable all interrupt sources. */
X	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X	cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN);
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	/* Clear RX FIFO level for generating interrupts. */
X	mr = uart_getreg(bas, AML_UART_MISC_REG);
X	mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK;
X	uart_setreg(bas, AML_UART_MISC_REG, mr);
X	uart_barrier(bas);
X
X	return (0);
}
X
X
static int
aml8726_uart_bus_flush(struct uart_softc *sc, int what)
{
X	struct uart_bas *bas;
X	uint32_t cr;
X
X	bas = &sc->sc_bas;
X	uart_lock(sc->sc_hwmtx);
X
X	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X	if (what & UART_FLUSH_TRANSMITTER)
X		cr |= AML_UART_CONTROL_TX_RST;
X	if (what & UART_FLUSH_RECEIVER)
X		cr |= AML_UART_CONTROL_RX_RST;
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	/* Ensure the reset bits are clear. */
X	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	uart_unlock(sc->sc_hwmtx);
X
X	return (0);
}
X
X
static int
aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
X	struct uart_bas *bas;
X	int baudrate, divisor, error;
X	uint32_t cr, mr;
X
X	bas = &sc->sc_bas;
X	uart_lock(sc->sc_hwmtx);
X
X	error = 0;
X	switch (request) {
X	case UART_IOCTL_BAUD:
X		cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X		cr &= AML_UART_CONTROL_BAUD_MASK;
X
X		mr = uart_getreg(bas, AML_UART_MISC_REG);
X		mr &= AML_UART_MISC_BAUD_EXT_MASK;
X
X		divisor = ((mr >> AML_UART_MISC_BAUD_EXT_SHIFT)
X			   << AML_UART_CONTROL_BAUD_WIDTH) | cr;
X
X		baudrate = bas->rclk / 4 / (divisor + 1);
X		if (baudrate > 0)
X			*(int*)data = baudrate;
X		else
X			error = ENXIO;
X		break;
X
X	default:
X		error = EINVAL;
X		break;
X	}
X
X	uart_unlock(sc->sc_hwmtx);
X
X	return (error);
}
X
X
static int
aml8726_uart_bus_ipend(struct uart_softc *sc)
{
X	struct uart_bas *bas;
X	int ipend;
X	uint32_t sr;
X	uint32_t cr;
X
X	bas = &sc->sc_bas;
X	uart_lock(sc->sc_hwmtx);
X
X	ipend = 0;
X	sr = uart_getreg(bas, AML_UART_STATUS_REG);
X	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X
X	if ((sr & AML_UART_STATUS_RX_FIFO_OVERFLOW) != 0)
X		ipend |= SER_INT_OVERRUN;
X
X	if ((sr & AML_UART_STATUS_TX_FIFO_EMPTY) != 0
X	    && (cr & AML_UART_CONTROL_TX_INT_EN) != 0) {
X		ipend |= SER_INT_TXIDLE;
X
X		cr &= ~AML_UART_CONTROL_TX_INT_EN;
X		uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X		uart_barrier(bas);
X	}
X
X	if ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0)
X		ipend |= SER_INT_RXREADY;
X
X	uart_unlock(sc->sc_hwmtx);
X
X	return (ipend);
}
X
X
static int
aml8726_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
X    int stopbits, int parity)
{
X	struct uart_bas *bas;
X	int error;
X
X	bas = &sc->sc_bas;
X	uart_lock(sc->sc_hwmtx);
X
X	error = aml8726_uart_param(bas, baudrate, databits, stopbits, parity);
X
X	uart_unlock(sc->sc_hwmtx);
X
X	return (error);
}
X
X
static int
aml8726_uart_bus_receive(struct uart_softc *sc)
{
X	struct uart_bas *bas;
X	int xc;
X	uint32_t sr;
X
X	bas = &sc->sc_bas;
X	uart_lock(sc->sc_hwmtx);
X
X	sr = uart_getreg(bas, AML_UART_STATUS_REG);
X	while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) {
X		if (uart_rx_full(sc)) {
X			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
X			break;
X		}
X		xc = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff;
X		if (sr & AML_UART_STATUS_FRAME_ERR)
X			xc |= UART_STAT_FRAMERR;
X		if (sr & AML_UART_STATUS_PARITY_ERR)
X			xc |= UART_STAT_PARERR;
X		uart_rx_put(sc, xc);
X		sr = uart_getreg(bas, AML_UART_STATUS_REG);
X	}
X	/* Discard everything left in the RX FIFO. */
X	while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) {
X		(void)uart_getreg(bas, AML_UART_RFIFO_REG);
X		sr = uart_getreg(bas, AML_UART_STATUS_REG);
X	}
X	/* Reset error bits */
X	if ((sr & (AML_UART_STATUS_FRAME_ERR | AML_UART_STATUS_PARITY_ERR)) != 0) {
X		uart_setreg(bas, AML_UART_CONTROL_REG,
X			    (uart_getreg(bas, AML_UART_CONTROL_REG)
X			     | AML_UART_CONTROL_CLR_ERR));
X		uart_barrier(bas);
X		uart_setreg(bas, AML_UART_CONTROL_REG,
X			    (uart_getreg(bas, AML_UART_CONTROL_REG)
X			     & ~AML_UART_CONTROL_CLR_ERR));
X		uart_barrier(bas);
X	}
X
X	uart_unlock(sc->sc_hwmtx);
X
X 	return (0);
}
X
X
static int
aml8726_uart_bus_transmit(struct uart_softc *sc)
{
X	struct uart_bas *bas;
X	int i;
X	uint32_t cr;
X
X	bas = &sc->sc_bas;
X	uart_lock(sc->sc_hwmtx);
X
X	/*
X	 * Wait for sufficient space since aml8726_uart_putc
X	 * may have been called after SER_INT_TXIDLE occurred.
X	 */
X	while ((uart_getreg(bas, AML_UART_STATUS_REG)
X		& AML_UART_STATUS_TX_FIFO_EMPTY) == 0)
X		cpu_spinwait();
X
X	for (i = 0; i < sc->sc_txdatasz; i++) {
X		uart_setreg(bas, AML_UART_WFIFO_REG, sc->sc_txbuf[i]);
X		uart_barrier(bas);
X	}
X
X	sc->sc_txbusy = 1;
X
X	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X	cr |= AML_UART_CONTROL_TX_INT_EN;
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	uart_unlock(sc->sc_hwmtx);
X
X	return (0);
}
X
X
static void
aml8726_uart_bus_grab(struct uart_softc *sc)
{
X	struct uart_bas *bas;
X	uint32_t cr;
X
X	/*
X	 * Disable the receive interrupt to avoid a race between
X	 * aml8726_uart_getc and aml8726_uart_bus_receive which
X	 * can trigger:
X	 *
X	 *   panic: bad stray interrupt
X	 *
X	 * due to the RX FIFO receiving a character causing an
X	 * interrupt which gets serviced after aml8726_uart_getc
X	 * has been called (meaning the RX FIFO is now empty).
X	 */
X
X	bas = &sc->sc_bas;
X	uart_lock(sc->sc_hwmtx);
X
X	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X	cr &= ~AML_UART_CONTROL_RX_INT_EN;
X	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X	uart_barrier(bas);
X
X	uart_unlock(sc->sc_hwmtx);
}
X
X
static void
aml8726_uart_bus_ungrab(struct uart_softc *sc)
{
X	struct uart_bas *bas;
X	uint32_t cr;
X	uint32_t mr;
X
X	/*
X	 * The RX FIFO level being set indicates that the device
X	 * is currently attached meaning the receive interrupt
X	 * should be enabled.
X	 */
X
X	bas = &sc->sc_bas;
X	uart_lock(sc->sc_hwmtx);
X
X	mr = uart_getreg(bas, AML_UART_MISC_REG);
X	mr &= AML_UART_MISC_RECV_IRQ_CNT_MASK;
X
X	if (mr != 0) {
X		cr = uart_getreg(bas, AML_UART_CONTROL_REG);
X		cr |= AML_UART_CONTROL_RX_INT_EN;
X		uart_setreg(bas, AML_UART_CONTROL_REG, cr);
X		uart_barrier(bas);
X	}
X
X	uart_unlock(sc->sc_hwmtx);
}
X
X
static kobj_method_t aml8726_uart_methods[] = {
X	KOBJMETHOD(uart_probe,		aml8726_uart_bus_probe),
X	KOBJMETHOD(uart_attach,		aml8726_uart_bus_attach),
X	KOBJMETHOD(uart_detach,		aml8726_uart_bus_detach),
X	KOBJMETHOD(uart_flush,		aml8726_uart_bus_flush),
X	KOBJMETHOD(uart_getsig,		aml8726_uart_bus_getsig),
X	KOBJMETHOD(uart_setsig,		aml8726_uart_bus_setsig),
X	KOBJMETHOD(uart_ioctl,		aml8726_uart_bus_ioctl),
X	KOBJMETHOD(uart_ipend,		aml8726_uart_bus_ipend),
X	KOBJMETHOD(uart_param,		aml8726_uart_bus_param),
X	KOBJMETHOD(uart_receive,	aml8726_uart_bus_receive),
X	KOBJMETHOD(uart_transmit,	aml8726_uart_bus_transmit),
X	KOBJMETHOD(uart_grab,		aml8726_uart_bus_grab),
X	KOBJMETHOD(uart_ungrab,		aml8726_uart_bus_ungrab),
X	{ 0, 0 }
};
X
struct uart_class uart_aml8726_class = {
X	"uart",
X	aml8726_uart_methods,
X	sizeof(struct uart_softc),
X	.uc_ops = &aml8726_uart_ops,
X	.uc_range = 24,
X	.uc_rclk = 0
};
SHAR_EOF
  (set 20 14 02 19 00 25 31 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c'
   eval "${shar_touch}") && \
  chmod 0644 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c'
if test $? -ne 0
then ${echo} "restore of sys/arm/amlogic/aml8726/uart_dev_aml8726.c failed"
fi
  if ${md5check}
  then (
       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c': 'MD5 check failed'
       ) << \SHAR_EOF
6604236035c33da69d47dd973b0531e3  sys/arm/amlogic/aml8726/uart_dev_aml8726.c
SHAR_EOF

else
test `LC_ALL=C wc -c < 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c'` -ne 16704 && \
  ${echo} "restoration warning:  size of 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c' is not 16704"
  fi
fi
if rm -fr ${lock_dir}
then ${echo} "x - removed lock directory ${lock_dir}."
else ${echo} "x - failed to remove lock directory ${lock_dir}."
     exit 1
fi
exit 0
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502012333.t11NXPOe028696>