# Copyright (c) 2007, Technologic Systems.
# All rights reserved.

# Note: Be sure you have 64-bit arithmetic compiled into your shell, or some
# of these functions will fail (e.g. for ADDRESS > 0x7FFFFFFF)

# bit_set BIT_WIDTH ADDRESS BIT_NUMBER
bit_set() {
  local MASK VAL
  MASK=$((1<<$3))
  VAL=`peekpoke $1 $2`
  VAL=$((MASK|VAL))
  peekpoke $1 $2 $VAL
}
                                                                                                                    
# bit_clr BIT_WIDTH ADDRESS BIT_NUMBER
bit_clr() {
  local MASK VAL
  MASK=$((1<<$3))
  VAL=`peekpoke $1 $2`
  VAL=$((~MASK&VAL))
  peekpoke $1 $2 $VAL
}
                                                                                                                    
# bit_get BIT_WIDTH ADDRESS BIT_NUMBER
bit_get() {
  local MASK VAL
  MASK=$((1<<$3))
  VAL=`peekpoke $1 $2`
  VAL=$((VAL>>$3))
  VAL=$((VAL&1))
  echo $VAL
}

# cpu gpio_dir_get BANK(1..4) DIO_NUM(0..15)
gpio_dir_get() {
  local ADRS
  if test $1 -eq 1; then
    let ADRS=0x73F84004
  elif test $1 -eq 2; then
    let ADRS=0x73F88004
  elif test $1 -eq 3; then
    let ADRS=0x73F8c004
  else
    let ADRS=0x73F90004
  fi
  bit_get 32 $ADRS $2
}

# cpu gpio_dir_set BANK(1..4) DIO_NUM(0..15) DIR(0=input,1=output)
gpio_dir_set() {
  local ADRS
  if test $1 -eq 1; then
    let ADRS=0x73F84004
  elif test $1 -eq 2; then
    let ADRS=0x73F88004
  elif test $1 -eq 3; then
    let ADRS=0x73F8c004
  else
    let ADRS=0x73F90004
  fi
  if test $3 -eq 0; then
    bit_clr 32 $ADRS $2
  else
    bit_set 32 $ADRS $2
  fi
}

# cpu gpio_data_get BANK(1..4) DIO_NUM(0..15)
gpio_data_get() {
  local ADRS
  if test $1 -eq 1; then
    let ADRS=0x73F84008
  elif test $1 -eq 2; then
    let ADRS=0x73F88008
  elif test $1 -eq 3; then
    let ADRS=0x73F8c008
  else
    let ADRS=0x73F90008
  fi
  bit_get 32 $ADRS $2
}

# cpu gpio_data_set BANK(1..4) DIO_NUM(0..15) 0|1
gpio_data_set() {
  local ADRS
  if test $1 -eq 1; then
    let ADRS=0x73F84000
  elif test $1 -eq 2; then
    let ADRS=0x73F88000
  elif test $1 -eq 3; then
    let ADRS=0x73F8c000
  else
    let ADRS=0x73F90000
  fi
  if test $3 -eq 0; then
    bit_clr 32 $ADRS $2
  else
    bit_set 32 $ADRS $2
  fi
}

# fpga dio_dir_get BANK(1..4) DIO_NUM(0..15)
dio_dir_get() {
  local ADRS
  if test $1 -eq 1; then
    let ADRS=0xb0010024
  elif test $1 -eq 2; then
    let ADRS=0xb001002c
  elif test $1 -eq 3; then
    let ADRS=0xb0010034
  else
    let ADRS=0xb001003c
  fi
  bit_get 16 $ADRS $2
}

# fpga dio_dir_set BANK(1..4) DIO_NUM(0..15) DIR(0=input,1=output)
dio_dir_set() {
  local ADRS
  if test $1 -eq 1; then
    let ADRS=0xb0010024
  elif test $1 -eq 2; then
    let ADRS=0xb001002c
  elif test $1 -eq 3; then
    let ADRS=0xb0010034
  else
    let ADRS=0xb001003c
  fi
  if test $3 -eq 0; then
    bit_clr 16 $ADRS $2
  else
    bit_set 16 $ADRS $2
  fi
}

# fpga dio_data_get BANK(1..4) DIO_NUM(0..15)
dio_data_get() {
  local ADRS
  if test $1 -eq 1; then
    let ADRS=0xb0010020
  elif test $1 -eq 2; then
    let ADRS=0xb0010028
  elif test $1 -eq 3; then
    let ADRS=0xb0010030
  else
    let ADRS=0xb0010038
  fi
  bit_get 16 $ADRS $2
}

# fpga dio_data_set BANK(1..4) DIO_NUM(0..15) 0|1
dio_data_set() {
  local ADRS
  if test $1 -eq 1; then
    let ADRS=0xb0010022
  elif test $1 -eq 2; then
    let ADRS=0xb001002a
  elif test $1 -eq 3; then
    let ADRS=0xb0010032
  else
    let ADRS=0xb001003a
  fi
  if test $3 -eq 0; then
    bit_clr 16 $ADRS $2
  else
    bit_set 16 $ADRS $2
  fi
}

# usb_power_on
usb_on() {
  gpio_dir_set 1 9 1
  gpio_data_set 1 9 1
}

# usb_power_off
usb_off() {
  gpio_dir_set 1 9 1
  gpio_data_set 1 9 0
}

# usb_init
usb_init() {
  bit_set 32 0x80930004 28 > /dev/null
  bit_clr 32 0x80020004 6 > /dev/null
  bit_set 32 0x80020004 7 > /dev/null
}

# usb_numports
usb_numports() {
  local NUM

  let NUM=`peekpoke 32 0x80020048`
  let NUM=NUM\&255
  echo $NUM
}

# usb_port_devexists PORTNUM(zero indexed)
usb_port_devexists() {
  local ADDR

  let ADDR=0x80020054
  let ADDR=$ADDR+4*$1
  bit_get 32 $ADDR 0
}

usbload() {
  modprobe scsi_mod 
  modprobe sd_mod
  modprobe usbcore
  modprobe ehci_hcd
  modprobe usb_storage
  modprobe vfat
}

bbclk_on() {
  bit_set 16 0xb0010002 11 > /dev/null
}

bbclk_off() {
  bit_clr 16 0xb0010002 11 > /dev/null
}

led0() {
  if test "$1" = "0"; then
    bit_clr 16 0xb0010010 15 > /dev/null
  else
    bit_set 16 0xb0010010 15 > /dev/null
  fi
}

led1() {
  if test "$1" = "0"; then
    bit_clr 16 0xb0010010 14 > /dev/null
  else
    bit_set 16 0xb0010010 14 > /dev/null
  fi
}

lcd_on() {
  gpio_dir_set 4 9 1
  gpio_data_set 4 9 1
}

lcd_off() {
  gpio_dir_set 4 9 1
  gpio_data_set 4 9 0
}

backlite_on() {
  bit_set 32 0x73FB4000 0 > /dev/null
}

backlite_off() {
  bit_clr 32 0x73FB4000 0 > /dev/null
}

backlite_high() {
  backlite_on
  #pwm_period_ns = 78770
  peekpoke 32 0x73FB4010 0x276 > /dev/null
  peekpoke 32 0x73FB400c 0x276 > /dev/null
}

backlite_medium() {
  backlite_on > /dev/null
  #pwm_period_ns = 78770
  peekpoke 32 0x73FB4010 0x276 > /dev/null
  peekpoke 32 0x73FB400c 0x220 > /dev/null
}

backlite_low() {
  backlite_on
  #pwm_period_ns = 78770
  peekpoke 32 0x73FB4010 0x276 > /dev/null
  peekpoke 32 0x73FB400c 0x180 > /dev/null
}

fix_display() {
  peekpoke 32 0x73fa8730 0x0
  peekpoke 32 0x73fa8738 0x7
  peekpoke 32 0x73fa86cc 0x7
  peekpoke 32 0x73fa86d0 0x7
  peekpoke 32 0x73fa86d4 0x7
  peekpoke 32 0x73fa86d8 0x7
  peekpoke 32 0x73fa86dc 0x7
  peekpoke 32 0x73fa86e0 0x7
  peekpoke 32 0x73fa86e4 0x7
  peekpoke 32 0x73fa86e8 0x7
  peekpoke 32 0x73fa86ec 0x7
  peekpoke 32 0x73fa8610 0x7
  peekpoke 32 0x73fa8614 0x7
  peekpoke 32 0x73fa8618 0x7
  peekpoke 32 0x73fa861c 0x7
  peekpoke 32 0x73fa8700 0x7
  peekpoke 32 0x73fa8704 0x7
  peekpoke 32 0x73fa8708 0x7
  peekpoke 32 0x73fa870c 0x7
  peekpoke 32 0x73fa8710 0x7
  peekpoke 32 0x73fa8714 0x7
  peekpoke 32 0x73fa8718 0x7
  peekpoke 32 0x73fa871c 0x7
  peekpoke 32 0x73fa8720 0x7
  peekpoke 32 0x73fa8724 0x7
  peekpoke 32 0x73fa8728 0x7
}

touchscreen_on() {
  bit_set 16 0xB0010010 6 > /dev/nul
}

touchscreen_off() {
  bit_clr 16 0xB0010010 6 > /dev/nul
}

tpc_up() {
  #fix_display
  lcd_on
  backlite_high
  usb_on
}

can0_on() {
  bit_set 16 0xB0010010 0 > /dev/nul
}
can0_off() {
  bit_clr 16 0xB0010010 0 > /dev/nul
}

can1_on() {
  bit_set 16 0xB0010010 1 > /dev/nul
}
can1_off() {
  bit_clr 16 0xB0010010 1 > /dev/nul
}

xuart0_on() {
  bit_set 16 0xB0010010 2 > /dev/nul
}
xuart0_off() {
  bit_clr 16 0xB0010010 2 > /dev/nul
}

xuart3_on() {
  bit_set 16 0xB0010010 3 > /dev/nul
}
xuart3_off() {
  bit_clr 16 0xB0010010 3 > /dev/nul
}

xuart4_on() {
  bit_set 16 0xB0010010 4 > /dev/nul
}
xuart4_off() {
  bit_clr 16 0xB0010010 4 > /dev/nul
}

xuart5_on() {
  bit_set 16 0xB0010010 5 > /dev/nul
}
xuart5_off() {
  bit_clr 16 0xB0010010 5 > /dev/nul
}

spi_on() {
  bit_set 16 0xB0010010 7 > /dev/nul
}
spi_off() {
  bit_clr 16 0xB0010010 7 > /dev/nul
}

motor_on() {
  bit_set 16 0xB0010010 8 > /dev/nul
}
motor_off() {
  bit_clr 16 0xB0010010 8 > /dev/nul
}

snd_on() {
  bit_set 16 0xB0010010 9 > /dev/nul
}
snd_off() {
  bit_clr 16 0xB0010010 9 > /dev/nul
}

irq5_on() {
  bit_set 16 0xB0010010 11 > /dev/nul
}
irq5_off() {
  bit_clr 16 0xB0010010 11 > /dev/nul
}

irq6_on() {
  bit_set 16 0xB0010010 12 > /dev/nul
}
irq6_off() {
  bit_clr 16 0xB0010010 12 > /dev/nul
}

irq7_on() {
  bit_set 16 0xB0010010 13 > /dev/nul
}
irq7_off() {
  bit_clr 16 0xB0010010 13 > /dev/nul
}

spk_on() {
  (
  peekpoke 32 0x73fa8248 0x3
  gpio_dir_set 1 24 1
  gpio_data_set 1 24 1
  ) > /dev/nul
}

spk_off() {                  
  (                               
  peekpoke 32 0x73fa8248 0x3
  gpio_dir_set 1 24 1
  gpio_data_set 1 24 0
  ) > /dev/nul                    
}     

is_ts4800 () {
  local VAL
  let VAL=`peekpoke 16 0xb0010000`
  let VAL=$VAL\&0xffff
  if test $VAL -eq 18432; then
    echo "1"
  else
    echo "0"
  fi
}

mxtime() {
  local x secs tenths
  let x=`peekpoke 16 0xb001000a`
  secs=$(((x>>4)&0xff))
  tenths=$((x&0xf))
  printf "%d.%02d\n" $secs $tenths
  # Return the value read from mem
  return $x
}

save2sd () {
  echo "Saving ramdisk to SD Card, please do not remove power..."
  dd if=/dev/zero of=/zerofiller > /dev/null 2>&1
  rm -f /zerofiller
  mount -o remount,ro rootfs /
  insmod /mx_sdhci.ko >/dev/null 2>&1
  mdev -s
  dd if=/dev/ram0 of=/dev/mmcblk0p3 >/dev/null 2>&1
  mount -o remount,rw rootfs /
  echo "done"
}

save2xnand () {
  echo "Saving ramdisk to XNAND, please do not remove power..."
  dd if=/dev/zero of=/zerofiller > /dev/null 2>&1
  rm -f /zerofiller
  mount -o remount,ro rootfs /
  #dd if=/dev/ram0 of=/dev/nbd2 bs=512 count=4k >/dev/null 2>&1  
  nandctl -W 16 -k part2 -z 131072 -X -i /dev/ram0 >/dev/null 2>&1
  mount -o remount,rw rootfs /
  echo "done"
}

save () {
  eval `ts4800ctl --info|grep bootdev` 
  if [ "$bootdev" == "0x1" -a -e /dev/mmcblk0p3 ]; then
    save2sd
  elif [ "$bootdev" == "0x0" -a -e /dev/nbd2 ]; then
    save2xnand
  else
    echo "No boot device found"
  fi
}

sd2xnand () {
  echo "Copying Kernel and ramdisk from SD to XNAND..." 
  insmod /mx_sdhci.ko >/dev/null 2>&1
  mdev -s
  #dd if=/dev/mmcblk0p2 of=/dev/nbd1 >/dev/null 2>&1
  #dd if=/dev/mmcblk0p3 of=/dev/nbd2 >/dev/null 2>&1
  nandctl -W 28 -z 131072 -k part1 -X -i /dev/mmcblk0p2 > /dev/null 2>&1
  nandctl -W 16 -z 131072 -k part2 -X -i /dev/mmcblk0p3 > /dev/null 2>&1
  echo "done"
}

xnand2sd () {
  echo "Copying Kernel and ramdisk from XNAND to SD..."
  insmod /mx_sdhci.ko >/dev/null 2>&1
  mdev -s
  dd of=/dev/mmcblk0p2 if=/dev/nbd1 >/dev/null 2>&1
  dd of=/dev/mmcblk0p3 if=/dev/nbd2 >/dev/null 2>&1
  echo "done"
}

createxnandboot () {
  echo "Preparing XNAND flash drive..."
  nandctl --erase 0x100000 >/dev/null 2>&1
  nandctl --xnandinit 0x80000 >/dev/null 2>&1
  #dd if=/xnandmbr.dd of=/dev/nbd0 bs=512 count=1 >/dev/null 2>&1
  nandctl -W 1 -z 512 -X -i /xnandmbr.dd > /dev/null 2>&1
  sync
  sd2xnand
}

createxnandroot() {
  createxnandboot
  echo "Creating root filesystem..."
  (
  umount /onboardflash
  mkfs.ext3 /dev/nbd3 256480
  mount /dev/nbd3 /onboardflash
  if [ -e /mnt/root/home/eclipse/mini-debian.tar.gz ]; then
    tar zxf /mnt/root/home/eclipse/mini-debian.tar.gz -C /onboardflash
  fi
  umount /onboardflash
  ) >/dev/null 2>&1
  echo "done"
}

get_2nd_mac() {
  eval `ts4800ctl -g`
  mac1=${mac:0:9}
  mac=${mac:9:2}${mac:12:2}${mac:15:2}
  let mac=0x$mac+1
  mac=`printf "%x\n" $mac`
  s=$mac1${mac:0:2}":"${mac:2:2}":"${mac:4:2}
  echo "mac2=$s"
}

tshelp() {
  echo "Technologic Systems Linux miniroot commands:"
  echo "============================================"
  echo
  echo "'save' - save current miniroot initrd configuration to boot device"
  echo "'save2sd' - save current miniroot initrd configuration to SD card"
  echo "'save2xnand' - save current miniroot initrd configuration to xnand"
  echo "'sd2xnand' - copy kernel and initrd from sd to xnand"
  echo "'xnand2sd' - copy kernel and initrd from xnand to sd"
  echo "'createxnandroot' - create new xnand boot device from SD card"
  echo "'exit' - start full Linux boot or exits telnet session"
  echo "'help' - lists busybox shell built-in Linux commands"
  echo
  echo "Other functions included. Please read /ts.subr source code." 
  echo
  echo "To change the default Linux root filesystem, link a different sample"
  echo "linuxrc bootup script by typing (e.g.) the following command:"
  echo "  ln -sf /linuxrc-sdroot /linuxrc; save"
  echo "Several sample linuxrc scripts are available:"
  echo "  '/linuxrc-sdroot' - boots to SD flash filesystem on partition #4"
  echo "  '/linuxrc-mtdroot' - boots to YAFFS NAND flash"
  echo "  '/linuxrc-fastboot' - unconditionally drops to fastboot shell on bootup"
  echo "  '/linuxrc-nfsroot' - boots to network NFS root"
  echo "Auto-booting of NAND flash, SD card, or NFS will be aborted to"
  echo "the fastboot shell prompt if the presence of a file named '/fastboot'"
  echo "is present on the filesystem.  You may customize bootup behavior"
  echo "further by modifying these simple linuxrc shell script samples."
  echo
  echo "Contact support@embeddedARM.com for further questions."
}

sdmount() {
  (
  insmod /mx_sdhci.ko
  mdev -s
  if [ -e /dev/mmcblk0p4 ]; then
    mount /dev/mmcblk0p4 /mnt/root -o ro
    #mount -o remount,rw /dev/mmcblk0p4 /mnt/root
  fi
  ) > /dev/null 2>&1
}

help() {
  /bin/busybox
}

